Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xa10dd65f2231aea80f7d3bc53789d520620a4291.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- AccessControlledOffchainAggregator
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 20000
- Verified at
- 2022-09-26T01:58:57.421174Z
Contract source code
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; interface AccessControllerInterface { function hasAccess(address user, bytes calldata data) external view returns (bool); } // File contracts/interfaces/AggregatorInterface.sol interface AggregatorInterface { function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); } // File contracts/interfaces/AggregatorV3Interface.sol interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/interfaces/AggregatorV2V3Interface.sol interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} // File contracts/interfaces/TypeAndVersionInterface.sol abstract contract TypeAndVersionInterface { function typeAndVersion() external pure virtual returns (string memory); } // File contracts/interfaces/OwnableInterface.sol interface OwnableInterface { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; } // File contracts/ConfirmedOwnerWithProposal.sol /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwnerWithProposal is OwnableInterface { address private s_owner; address private s_pendingOwner; event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { require(newOwner != address(0), "Cannot set owner to zero"); s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /** * @notice Allows an owner to begin transferring ownership to a new address, * pending. */ function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /** * @notice Allows an ownership transfer to be completed by the recipient. */ function acceptOwnership() external override { require(msg.sender == s_pendingOwner, "Must be proposed owner"); address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /** * @notice Get the current owner */ function owner() public view override returns (address) { return s_owner; } /** * @notice validate, transfer ownership, and emit relevant events */ function _transferOwnership(address to) private { require(to != msg.sender, "Cannot transfer to self"); s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /** * @notice validate access */ function _validateOwnership() internal view { require(msg.sender == s_owner, "Only callable by owner"); } /** * @notice Reverts if called by anyone other than the contract owner. */ modifier onlyOwner() { _validateOwnership(); _; } } // File contracts/ConfirmedOwner.sol /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwner is ConfirmedOwnerWithProposal { constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} } // File contracts/OwnerIsCreator.sol /** * @title The OwnerIsCreator contract * @notice A contract with helpers for basic contract ownership. */ contract OwnerIsCreator is ConfirmedOwner { constructor() ConfirmedOwner(msg.sender) {} } // File contracts/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } } // File contracts/interfaces/IMojitoOracle.sol interface IMojitoOracle { function getMojitoTwap(bytes32 pairId) external view returns (uint256); function currencyPairId(string memory) external view returns (bytes32); function lookupERC2362ID(bytes32 _erc2362id) external view returns (string memory _caption); } // File contracts/interfaces/IERC2362.sol /** * @dev EIP2362 Interface for pull oracles * https://github.com/adoracles/EIPs/blob/erc-2362/EIPS/eip-2362.md */ interface IERC2362 { /** * @dev Exposed function pertaining to EIP standards * @param _id bytes32 ID of the query * @return int,uint,uint returns the value, timestamp, and status code of query */ function valueFor(bytes32 _id) external view returns ( int256, uint256, uint256 ); } // File contracts/AnchoredView.sol contract AnchoredView is OwnerIsCreator { using SafeMath for uint256; bool public validateAnswerEnabled; /// @notice how many digits of precision to retain, in 1e-decimals token units uint256 public immutable answerBaseUnit; struct MojitoConfig { bool available; bytes32 pairA; uint256 pairABaseUnit; } MojitoConfig internal mojitoConfig; /// @notice emitted when mojito config are set event MojitoConfigSet(bool available, bytes32 pairA, uint256 pairABaseUnit); struct WitnetConfig { bool available; bytes32 pairA; bytes32 pairB; uint256 pairABaseUnit; uint256 pairBBaseUnit; } WitnetConfig internal witnetConfig; /// @notice emitted when witnet config are set event WitnetConfigSet(bool available, bytes32 pairA, bytes32 pairB, uint256 pairABaseUnit, uint256 pairBBaseUnit); // The price oracle IMojitoOracle public mojitoOracle; IERC2362 public witnetOracle; /** * @notice emitted when a new mojito oracle contract is set * @param old the address prior to the current setting * @param current the address of the new mojito oracle contract */ event MojitoOracleSet(IMojitoOracle old, IMojitoOracle current); /** * @notice emitted when a new witnet oracle contract is set * @param old the address prior to the current setting * @param current the address of the new witnet oracle contract */ event WitnetOracleSet(IERC2362 old, IERC2362 current); event ValidateAnswerEnabled(); event ValidateAnswerDisabled(); /* * @param _mojitoOracle address of the mojito oracle contract * @param _witnetOracle address of the witnet oracle contract * @param _decimals answers are stored in fixed-point format, with this many digits of precision * @param _validateAnswerEnabled whether to enable the switch for validate answer */ constructor( address _mojitoOracle, address _witnetOracle, uint8 _decimals, bool _validateAnswerEnabled ) { _setMojitoOracle(IMojitoOracle(_mojitoOracle)); _setWitnetOracle(IERC2362(_witnetOracle)); // pow(10, _decimals) answerBaseUnit = 10**_decimals; validateAnswerEnabled = _validateAnswerEnabled; } /** * @notice sets the mojito twap oracle * @param _oracle the address of the mojito oracle contract */ function setMojitoOracle(IMojitoOracle _oracle) external onlyOwner { _setMojitoOracle(_oracle); } function _setMojitoOracle(IMojitoOracle _oracle) internal { IMojitoOracle oldOracle = mojitoOracle; if (_oracle != oldOracle) { mojitoOracle = _oracle; emit MojitoOracleSet(oldOracle, _oracle); } } /** * @notice sets the witnet oracle * @param _oracle the address of the witnet oracle contract */ function setWitnetOracle(IERC2362 _oracle) external onlyOwner { _setWitnetOracle(_oracle); } function _setWitnetOracle(IERC2362 _oracle) internal { IERC2362 oldOracle = witnetOracle; if (_oracle != oldOracle) { witnetOracle = _oracle; emit WitnetOracleSet(oldOracle, _oracle); } } function _getMojitoPriceInternal() internal view returns (uint256) { if (mojitoConfig.available) { uint256 twapPrice = mojitoOracle.getMojitoTwap(mojitoConfig.pairA); return twapPrice.mul(answerBaseUnit).div(mojitoConfig.pairABaseUnit); } return 0; } function _getWitnetPriceInternal() internal view returns (uint256) { if (witnetConfig.available) { int256 pairAPrice; (pairAPrice, , ) = witnetOracle.valueFor(witnetConfig.pairA); if (witnetConfig.pairB == "") { return uint256(pairAPrice).mul(answerBaseUnit).div(witnetConfig.pairABaseUnit); } else { int256 pairBPrice; (pairBPrice, , ) = witnetOracle.valueFor(witnetConfig.pairB); return uint256(pairAPrice).mul(uint256(pairBPrice)).mul(answerBaseUnit).div(witnetConfig.pairABaseUnit).div( witnetConfig.pairBBaseUnit ); } } return 0; } /** * @notice sets mojito parameters * @param _available is the price available * @param _pairA pairA erc2362 asset id * @param _pairABaseUnit pairA decimals * @dev must be called by owner */ function setMojitoConfig( bool _available, bytes32 _pairA, uint256 _pairABaseUnit ) external onlyOwner { mojitoConfig.available = _available; mojitoConfig.pairA = _pairA; mojitoConfig.pairABaseUnit = _pairABaseUnit; emit MojitoConfigSet(_available, _pairA, _pairABaseUnit); } /* * @notice gets the mojito config * @return The config object */ function getMojitoConfig() external view returns ( bool available, bytes32 pairA, uint256 pairABaseUnit ) { return (mojitoConfig.available, mojitoConfig.pairA, mojitoConfig.pairABaseUnit); } /** * @notice sets winet parameters * @param _available is the price available * @param _pairA pairA erc2362 asset id * @param _pairB pairB erc2362 asset id, optimal exchange rate when used * @param _pairABaseUnit pairA decimals * @param _pairBBaseUnit pairB decimals * @dev must be called by owner */ function setWitnetConfig( bool _available, bytes32 _pairA, bytes32 _pairB, uint256 _pairABaseUnit, uint256 _pairBBaseUnit ) external onlyOwner { witnetConfig.available = _available; witnetConfig.pairA = _pairA; witnetConfig.pairB = _pairB; witnetConfig.pairABaseUnit = _pairABaseUnit; witnetConfig.pairBBaseUnit = _pairBBaseUnit; emit WitnetConfigSet(_available, _pairA, _pairB, _pairABaseUnit, _pairBBaseUnit); } /* * @notice gets the witnet config * @return The config object */ function getWitnetConfig() external view returns ( bool available, bytes32 pairA, bytes32 pairB, uint256 pairABaseUnit, uint256 pairBBaseUnit ) { return ( witnetConfig.available, witnetConfig.pairA, witnetConfig.pairB, witnetConfig.pairABaseUnit, witnetConfig.pairBBaseUnit ); } /** * @notice Get the mojito oracle twap for a underlying * @return Price denominated in USD, with 8 decimals */ function getMojitoPrice() external view returns (uint256) { return _getMojitoPriceInternal(); } /** * @notice Get the witnet oracle price for a underlying * @return Price denominated in USD, with 8 decimals */ function getWitnetPrice() external view returns (uint256) { return _getWitnetPriceInternal(); } /** * @notice makes the answer validate enforced */ function enableAnswerValidate() external onlyOwner { if (!validateAnswerEnabled) { validateAnswerEnabled = true; emit ValidateAnswerEnabled(); } } /** * @notice makes the answer validate unenforced */ function disableAnswerValidate() external onlyOwner { if (validateAnswerEnabled) { validateAnswerEnabled = false; emit ValidateAnswerDisabled(); } } } // File contracts/OffchainAggregator.sol /** * @notice Onchain verification of reports from the offchain reporting protocol * @dev For details on its operation, see the offchain reporting protocol design * @dev doc, which refers to this contract as simply the "contract". */ contract OffchainAggregator is OwnerIsCreator, AggregatorV2V3Interface, TypeAndVersionInterface, AnchoredView { using SafeMath for uint256; // Storing these fields used on the hot path in a HotVars variable reduces the // retrieval of all of them to a single SLOAD. If any further fields are // added, make sure that storage of the struct still takes at most 32 bytes. struct HotVars { // Oracle Aggregators expose a roundId to consumers. The offchain reporting // protocol does not use this id anywhere. We increment it whenever a new // transmission is made to provide callers with contiguous ids for successive // reports. uint32 latestAggregatorRoundId; } HotVars internal s_hotVars; // Transmission records the median answer from the transmit transaction at time timestamp struct Transmission { int192 answer; // 192 bits ought to be enough for anyone uint32 observationsTimestamp; // when were observations made offchain uint32 transmissionTimestamp; // when was report received onchain } mapping(uint32 => Transmission) /* aggregator round ID */ internal s_transmissions; // incremented each time a new config is posted. This count is incorporated // into the config digest to prevent replay attacks. uint32 internal s_configCount; // makes it easier for offchain systems to extract config from logs uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs address internal s_latestTransmitter; // lowest answers for calculating the old price or the anchor price uint8 public lowerBoundAnchorRatio; //0.8e2 // highest answers for calculating the old price or the anchor price uint8 public upperBoundAnchorRatio; //1.2e2 uint8 internal constant minLowerBoundAnchorRatio = 0.8e2; uint8 internal constant maxUpperBoundAnchorRatio = 1.2e2; struct Transmitter { bool active; // Index of oracle in s_signersList/s_transmittersList uint8 index; } mapping(address => Transmitter) /* transmitter address */ internal s_transmitters; struct Signer { bool active; // Index of oracle in s_signersList/s_transmittersList uint8 index; } mapping(address => Signer) /* signer address */ internal s_signers; // s_signersList contains the signing address of each oracle address[] internal s_signersList; // s_transmittersList contains the transmission address of each oracle, // i.e. the address the oracle actually sends transactions to the contract from address[] internal s_transmittersList; /* * @param _lowerBoundAnchorRatio lowest answers for calculating the old price or the anchor price * @param _upperBoundAnchorRatio highest answers for calculating the old price or the anchor price * @param _decimals answers are stored in fixed-point format, with this many digits of precision * @param _description short human-readable description of observable this contract's answers pertain to * @param _mojitoOracle address of the mojito oracle contract * @param _witnetOracle address of the witnet oracle contract * @param _validateAnswerEnabled whether to enable the switch for validate answer */ constructor( uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio, uint8 _decimals, string memory _description, address _mojitoOracle, address _witnetOracle, bool _validateAnswerEnabled ) AnchoredView(_mojitoOracle, _witnetOracle, _decimals, _validateAnswerEnabled) { lowerBoundAnchorRatio = _lowerBoundAnchorRatio; upperBoundAnchorRatio = _upperBoundAnchorRatio; decimals = _decimals; s_description = _description; } /* * Versioning */ function typeAndVersion() external pure virtual override returns (string memory) { return "OffchainAggregator 1.0.0"; } /* * AnchorRatio logic */ event AnchorRatioUpdated(uint8 lowerBoundAnchorRatio, uint8 upperBoundAnchorRatio); function setAnchorRatio(uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio) external onlyOwner { require( minLowerBoundAnchorRatio <= _lowerBoundAnchorRatio, "lowerBoundAnchorRatio must greater or equal to minLowerBoundAnchorRatio" ); require( maxUpperBoundAnchorRatio >= _upperBoundAnchorRatio, "upperBoundAnchorRatio must Less than or equal to maxUpperBoundAnchorRatio" ); require( _upperBoundAnchorRatio > _lowerBoundAnchorRatio, "upperBoundAnchorRatio must Less than lowerBoundAnchorRatio" ); lowerBoundAnchorRatio = _lowerBoundAnchorRatio; upperBoundAnchorRatio = _upperBoundAnchorRatio; emit AnchorRatioUpdated(lowerBoundAnchorRatio, upperBoundAnchorRatio); } /* * Config logic */ /** * @notice triggers a new run of the offchain reporting protocol * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis * @param configCount ordinal number of this config setting among all config settings over the life of this contract * @param signers ith element is address ith oracle uses to sign a report * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method */ event ConfigSet(uint32 previousConfigBlockNumber, uint64 configCount, address[] signers, address[] transmitters); /** * @notice sets offchain reporting protocol configuration incl. participating oracles * @param _transmitters addresses oracles use to transmit the reports */ function setConfig(address[] calldata _signers, address[] calldata _transmitters) external onlyOwner { require(_signers.length == _transmitters.length, "oracle length mismatch"); // remove any old signer/transmitter addresses uint256 oldLength = s_signersList.length; for (uint256 i = 0; i < oldLength; i++) { address signer = s_signersList[i]; address transmitter = s_transmittersList[i]; delete s_signers[signer]; delete s_transmitters[transmitter]; } delete s_signersList; delete s_transmittersList; // add new signer/transmitter addresses for (uint256 i = 0; i < _signers.length; i++) { require(!s_signers[_signers[i]].active, "repeated signer address"); s_signers[_signers[i]] = Signer({active: true, index: uint8(i)}); require(!s_transmitters[_transmitters[i]].active, "repeated transmitter address"); s_transmitters[_transmitters[i]] = Transmitter({active: true, index: uint8(i)}); } s_signersList = _signers; s_transmittersList = _transmitters; uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; s_latestConfigBlockNumber = uint32(block.number); s_configCount += 1; emit ConfigSet(previousConfigBlockNumber, s_configCount, _signers, _transmitters); } /** * @notice information about current offchain reporting protocol configuration * @return configCount ordinal number of current config, out of all configs applied to this contract so far * @return blockNumber block at which this config was set */ function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber) { return (s_configCount, s_latestConfigBlockNumber); } /** * @return list of addresses permitted to transmit reports to this contract * @dev The list will match the order used to specify the transmitter during setConfig */ function getTransmitters() external view returns (address[] memory) { return s_transmittersList; } /* * Transmission logic */ /** * @notice indicates that a new report was transmitted * @param aggregatorRoundId the round to which this report was assigned * @param answer median of the observations attached this report * @param transmitter address from which the report was transmitted * @param observationsTimestamp when were observations made offchain */ event NewTransmission( uint32 indexed aggregatorRoundId, int192 answer, address transmitter, uint32 observationsTimestamp ); /* * @notice details about the most transmission details * @return nextTransmitter who will be next to transmit the report * @return afterNextTransmitter who will transmit the report next afterwards * @return nextIndex the index of the next transmitter * @return length the length of the s_transmittersList * @return roundId aggregator round of latest report * @return answer median value from latest report * @return startedAt when the latest report was transmitted * @return updatedAt when the latest report was transmitted */ function latestTransmissionDetails() external view returns ( address nextTransmitter, address afterNextTransmitter, uint8 nextIndex, uint256 transmittersLength, uint80 roundId, int192 answer, uint256 startedAt, uint256 updatedAt ) { require(msg.sender == tx.origin, "Only callable by EOA"); nextIndex = 0; uint8 afterNextIndex = 0; // Calculating the index of the next transmitter uint256 s_length = s_transmittersList.length; if (s_length > 0) { // the index of the current transmitter Transmitter memory s_transmitter; s_transmitter = s_transmitters[s_latestTransmitter]; if (s_transmitter.active) { nextIndex = s_transmitter.index; nextIndex++; if (s_length == nextIndex) { nextIndex = 0; } } afterNextIndex = nextIndex; afterNextIndex++; if (s_length == afterNextIndex) { afterNextIndex = 0; } nextTransmitter = s_transmittersList[nextIndex]; afterNextTransmitter = s_transmittersList[afterNextIndex]; } roundId = s_hotVars.latestAggregatorRoundId; Transmission memory transmission = s_transmissions[uint32(roundId)]; return ( nextTransmitter, afterNextTransmitter, nextIndex, s_length, roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp ); } // The constant-length components of the msg.data sent to transmit. // See the "If we wanted to call sam" example on for example reasoning // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = 4 + // function selector 32 + // word containing start location of abiencoded _report value 32 + // _rs value 32 + // _ss value 32 + // _vs value 32 + // word containing length of _report 0; // placeholder function expectedMsgDataLength() private pure returns (uint256 length) { // calldata will never be big enough to make this overflow return uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + 64 + // one byte pure entry in _report 0; // placeholder } /** * @notice transmit is called to post a new report to the contract * @param _report serialized report, which the signatures are signing. See parsing code below for format. * @param _rs the R components of the signature on report. * @param _ss the S components of the signature on report. * @param _vs the V component of the signature on report. */ function transmit( // NOTE: If these parameters are changed, expectedMsgDataLength and/or // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly bytes calldata _report, // ECDSA signature bytes32 _rs, bytes32 _ss, uint8 _vs ) external { require(s_transmitters[msg.sender].active, "unauthorized transmitter"); require(msg.data.length == expectedMsgDataLength(), "transmit message length mismatch"); uint192 median; uint32 observationsTimestamp; (median, observationsTimestamp) = abi.decode(_report, (uint192, uint32)); uint32 s_latestTimestamp = s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp; require(observationsTimestamp > s_latestTimestamp, "invalid observations timestamp"); // Verify signatures attached to report { bytes32 h = keccak256(_report); Signer memory signer; address signerAddress = ecrecover(h, _vs + 27, _rs, _ss); signer = s_signers[signerAddress]; require(signer.active, "signature error"); } if (validateAnswerEnabled) { if (_validateAnswer(uint256(median))) { _transmit(int192(median), observationsTimestamp); } } else { uint256 previousAnswer = uint192(s_transmissions[s_hotVars.latestAggregatorRoundId].answer); if (previousAnswer > 0) { require(isWithinAnchor(median, previousAnswer), "median is out of min-max range"); } _transmit(int192(median), observationsTimestamp); } } function transmitWithForce(uint192 median) external onlyOwner { _transmit(int192(median), uint32(block.timestamp)); } function _transmit(int192 median, uint32 observationsTimestamp) internal { HotVars memory hotVars = s_hotVars; // cache read from storage hotVars.latestAggregatorRoundId++; s_transmissions[hotVars.latestAggregatorRoundId] = Transmission({ answer: median, observationsTimestamp: observationsTimestamp, transmissionTimestamp: uint32(block.timestamp) }); s_latestTransmitter = msg.sender; emit NewTransmission(hotVars.latestAggregatorRoundId, median, msg.sender, observationsTimestamp); // Emit these for backwards compatability with offchain consumers // that only support legacy events emit NewRound( hotVars.latestAggregatorRoundId, address(0x0), // use zero address since we don't have anybody "starting" the round here observationsTimestamp ); emit AnswerUpdated(median, hotVars.latestAggregatorRoundId, block.timestamp); // persist updates to hotVars s_hotVars = hotVars; } /// @notice The event emitted when new prices are posted but the stored price is not updated due to the anchor event AnswerGuarded( uint32 indexed aggregatorRoundId, uint256 reporterPrice, uint256 anchorMojitoPrice, uint256 anchorWitnetPrice, uint256 updatedAt ); /** * @notice This is called by the reporter whenever a new price is posted on-chain * @param reporterPrice the price from the reporter * @return valid bool */ function _validateAnswer(uint256 reporterPrice) internal returns (bool) { uint256 anchorMojitoPrice = _getMojitoPriceInternal(); if (isWithinAnchor(reporterPrice, anchorMojitoPrice)) { return true; } else { uint256 anchorWitnetPrice = _getWitnetPriceInternal(); if (isWithinAnchor(reporterPrice, anchorWitnetPrice)) { return true; } else { emit AnswerGuarded( s_hotVars.latestAggregatorRoundId + 1, reporterPrice, anchorMojitoPrice, anchorWitnetPrice, block.timestamp ); return false; } } } /** * @notice This is called by the reporter whenever a new price is posted on-chain * @param reporterPrice the price from the reporter * @param anchorPrice the price from the other contract * @return valid bool */ function isWithinAnchor(uint256 reporterPrice, uint256 anchorPrice) internal view returns (bool) { if (reporterPrice > 0 && anchorPrice > 0) { uint256 minAnswer = anchorPrice.mul(lowerBoundAnchorRatio).div(1e2); uint256 maxAnswer = anchorPrice.mul(upperBoundAnchorRatio).div(1e2); return minAnswer <= reporterPrice && reporterPrice <= maxAnswer; } return false; } /* * v2 Aggregator interface */ /** * @notice median from the most recent report */ function latestAnswer() public view virtual override returns (int256) { return s_transmissions[s_hotVars.latestAggregatorRoundId].answer; } /** * @notice timestamp of block in which last report was transmitted */ function latestTimestamp() public view virtual override returns (uint256) { return s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp; } /** * @notice Aggregator round (NOT OCR round) in which last report was transmitted */ function latestRound() public view virtual override returns (uint256) { return s_hotVars.latestAggregatorRoundId; } /** * @notice median of report from given aggregator round (NOT OCR round) * @param _roundId the aggregator round of the target report */ function getAnswer(uint256 _roundId) public view virtual override returns (int256) { if (_roundId > 0xFFFFFFFF) { return 0; } return s_transmissions[uint32(_roundId)].answer; } /** * @notice timestamp of block in which report from given aggregator round was transmitted * @param _roundId aggregator round (NOT OCR round) of target report */ function getTimestamp(uint256 _roundId) public view virtual override returns (uint256) { if (_roundId > 0xFFFFFFFF) { return 0; } return s_transmissions[uint32(_roundId)].transmissionTimestamp; } /* * v3 Aggregator interface */ string private constant V3_NO_DATA_ERROR = "No data present"; /** * @return answers are stored in fixed-point format, with this many digits of precision */ uint8 public immutable override decimals; /** * @notice aggregator contract version */ uint256 public constant override version = 1; string internal s_description; /** * @notice human-readable description of observable this contract is reporting on */ function description() public view virtual override returns (string memory) { return s_description; } /** * @notice details for the given aggregator round * @param _roundId target aggregator round (NOT OCR round). Must fit in uint32 * @return roundId _roundId * @return answer median of report from given _roundId * @return startedAt timestamp of block in which report from given _roundId was transmitted * @return updatedAt timestamp of block in which report from given _roundId was transmitted * @return answeredInRound _roundId */ function getRoundData(uint80 _roundId) public view virtual override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { require(_roundId <= 0xFFFFFFFF, V3_NO_DATA_ERROR); Transmission memory transmission = s_transmissions[uint32(_roundId)]; return ( _roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp, _roundId ); } /** * @notice aggregator details for the most recently transmitted report * @return roundId aggregator round of latest report (NOT OCR round) * @return answer median of latest report * @return startedAt timestamp of block containing latest report * @return updatedAt timestamp of block containing latest report * @return answeredInRound aggregator round of latest report */ function latestRoundData() public view virtual override returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { roundId = s_hotVars.latestAggregatorRoundId; // Skipped for compatability with existing FluxAggregator in which latestRoundData never reverts. // require(roundId != 0, V3_NO_DATA_ERROR); Transmission memory transmission = s_transmissions[uint32(roundId)]; return ( roundId, transmission.answer, transmission.observationsTimestamp, transmission.transmissionTimestamp, roundId ); } } // File contracts/SimpleWriteAccessController.sol /** * @title SimpleWriteAccessController * @notice Gives access to accounts explicitly added to an access list by the * controller's owner. * @dev does not make any special permissions for externally, see * SimpleReadAccessController for that. */ contract SimpleWriteAccessController is AccessControllerInterface, OwnerIsCreator { bool public checkEnabled; mapping(address => bool) internal accessList; event AddedAccess(address user); event RemovedAccess(address user); event CheckAccessEnabled(); event CheckAccessDisabled(); constructor() { checkEnabled = true; } /** * @notice Returns the access of an address * @param _user The address to query */ function hasAccess(address _user, bytes memory) public view virtual override returns (bool) { return accessList[_user] || !checkEnabled; } /** * @notice Adds an address to the access list * @param _user The address to add */ function addAccess(address _user) external onlyOwner { if (!accessList[_user]) { accessList[_user] = true; emit AddedAccess(_user); } } /** * @notice Removes an address from the access list * @param _user The address to remove */ function removeAccess(address _user) external onlyOwner { if (accessList[_user]) { accessList[_user] = false; emit RemovedAccess(_user); } } /** * @notice makes the access check enforced */ function enableAccessCheck() external onlyOwner { if (!checkEnabled) { checkEnabled = true; emit CheckAccessEnabled(); } } /** * @notice makes the access check unenforced */ function disableAccessCheck() external onlyOwner { if (checkEnabled) { checkEnabled = false; emit CheckAccessDisabled(); } } /** * @dev reverts if the caller does not have access */ modifier checkAccess() { require(hasAccess(msg.sender, msg.data), "No access"); _; } } // File contracts/SimpleReadAccessController.sol /** * @title SimpleReadAccessController * @notice Gives access to: * - any externally owned account (note that offchain actors can always read * any contract storage regardless of onchain access control measures, so this * does not weaken the access control while improving usability) * - accounts explicitly added to an access list * @dev SimpleReadAccessController is not suitable for access controlling writes * since it grants any externally owned account access! See * SimpleWriteAccessController for that. */ contract SimpleReadAccessController is SimpleWriteAccessController { /** * @notice Returns the access of an address * @param _user The address to query */ function hasAccess(address _user, bytes memory _calldata) public view virtual override returns (bool) { return super.hasAccess(_user, _calldata) || _user == tx.origin; } } // File contracts/AccessControlledOffchainAggregator.sol /** * @notice Wrapper of OffchainAggregator which checks read access on Aggregator-interface methods */ contract AccessControlledOffchainAggregator is OffchainAggregator, SimpleReadAccessController { constructor( uint8 _lowerBoundAnchorRatio, uint8 _upperBoundAnchorRatio, uint8 _decimals, string memory _description, address _mojitoOracle, address _witnetOracle, bool _validateAnswerEnabled ) OffchainAggregator( _lowerBoundAnchorRatio, _upperBoundAnchorRatio, _decimals, _description, _mojitoOracle, _witnetOracle, _validateAnswerEnabled ) {} /* * Versioning */ function typeAndVersion() external pure virtual override returns (string memory) { return "AccessControlledOffchainAggregator 1.0.0"; } /* * v2 Aggregator interface */ /// @inheritdoc OffchainAggregator function latestAnswer() public view override checkAccess returns (int256) { return super.latestAnswer(); } /// @inheritdoc OffchainAggregator function latestTimestamp() public view override checkAccess returns (uint256) { return super.latestTimestamp(); } /// @inheritdoc OffchainAggregator function latestRound() public view override checkAccess returns (uint256) { return super.latestRound(); } /// @inheritdoc OffchainAggregator function getAnswer(uint256 _roundId) public view override checkAccess returns (int256) { return super.getAnswer(_roundId); } /// @inheritdoc OffchainAggregator function getTimestamp(uint256 _roundId) public view override checkAccess returns (uint256) { return super.getTimestamp(_roundId); } /* * v3 Aggregator interface */ /// @inheritdoc OffchainAggregator function description() public view override checkAccess returns (string memory) { return super.description(); } /// @inheritdoc OffchainAggregator function getRoundData(uint80 _roundId) public view override checkAccess returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { return super.getRoundData(_roundId); } /// @inheritdoc OffchainAggregator function latestRoundData() public view override checkAccess returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ) { return super.latestRoundData(); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint8","name":"_lowerBoundAnchorRatio","internalType":"uint8"},{"type":"uint8","name":"_upperBoundAnchorRatio","internalType":"uint8"},{"type":"uint8","name":"_decimals","internalType":"uint8"},{"type":"string","name":"_description","internalType":"string"},{"type":"address","name":"_mojitoOracle","internalType":"address"},{"type":"address","name":"_witnetOracle","internalType":"address"},{"type":"bool","name":"_validateAnswerEnabled","internalType":"bool"}]},{"type":"event","name":"AddedAccess","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"AnchorRatioUpdated","inputs":[{"type":"uint8","name":"lowerBoundAnchorRatio","internalType":"uint8","indexed":false},{"type":"uint8","name":"upperBoundAnchorRatio","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"AnswerGuarded","inputs":[{"type":"uint32","name":"aggregatorRoundId","internalType":"uint32","indexed":true},{"type":"uint256","name":"reporterPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"anchorMojitoPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"anchorWitnetPrice","internalType":"uint256","indexed":false},{"type":"uint256","name":"updatedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AnswerUpdated","inputs":[{"type":"int256","name":"current","internalType":"int256","indexed":true},{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"uint256","name":"updatedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CheckAccessDisabled","inputs":[],"anonymous":false},{"type":"event","name":"CheckAccessEnabled","inputs":[],"anonymous":false},{"type":"event","name":"ConfigSet","inputs":[{"type":"uint32","name":"previousConfigBlockNumber","internalType":"uint32","indexed":false},{"type":"uint64","name":"configCount","internalType":"uint64","indexed":false},{"type":"address[]","name":"signers","internalType":"address[]","indexed":false},{"type":"address[]","name":"transmitters","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"MojitoConfigSet","inputs":[{"type":"bool","name":"available","internalType":"bool","indexed":false},{"type":"bytes32","name":"pairA","internalType":"bytes32","indexed":false},{"type":"uint256","name":"pairABaseUnit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MojitoOracleSet","inputs":[{"type":"address","name":"old","internalType":"contract IMojitoOracle","indexed":false},{"type":"address","name":"current","internalType":"contract IMojitoOracle","indexed":false}],"anonymous":false},{"type":"event","name":"NewRound","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"address","name":"startedBy","internalType":"address","indexed":true},{"type":"uint256","name":"startedAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewTransmission","inputs":[{"type":"uint32","name":"aggregatorRoundId","internalType":"uint32","indexed":true},{"type":"int192","name":"answer","internalType":"int192","indexed":false},{"type":"address","name":"transmitter","internalType":"address","indexed":false},{"type":"uint32","name":"observationsTimestamp","internalType":"uint32","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferRequested","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RemovedAccess","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ValidateAnswerDisabled","inputs":[],"anonymous":false},{"type":"event","name":"ValidateAnswerEnabled","inputs":[],"anonymous":false},{"type":"event","name":"WitnetConfigSet","inputs":[{"type":"bool","name":"available","internalType":"bool","indexed":false},{"type":"bytes32","name":"pairA","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"pairB","internalType":"bytes32","indexed":false},{"type":"uint256","name":"pairABaseUnit","internalType":"uint256","indexed":false},{"type":"uint256","name":"pairBBaseUnit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"WitnetOracleSet","inputs":[{"type":"address","name":"old","internalType":"contract IERC2362","indexed":false},{"type":"address","name":"current","internalType":"contract IERC2362","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addAccess","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"answerBaseUnit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"checkEnabled","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"description","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableAccessCheck","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableAnswerValidate","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableAccessCheck","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableAnswerValidate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"getAnswer","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"available","internalType":"bool"},{"type":"bytes32","name":"pairA","internalType":"bytes32"},{"type":"uint256","name":"pairABaseUnit","internalType":"uint256"}],"name":"getMojitoConfig","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getMojitoPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint80","name":"roundId","internalType":"uint80"},{"type":"int256","name":"answer","internalType":"int256"},{"type":"uint256","name":"startedAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"},{"type":"uint80","name":"answeredInRound","internalType":"uint80"}],"name":"getRoundData","inputs":[{"type":"uint80","name":"_roundId","internalType":"uint80"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTimestamp","inputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getTransmitters","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"available","internalType":"bool"},{"type":"bytes32","name":"pairA","internalType":"bytes32"},{"type":"bytes32","name":"pairB","internalType":"bytes32"},{"type":"uint256","name":"pairABaseUnit","internalType":"uint256"},{"type":"uint256","name":"pairBBaseUnit","internalType":"uint256"}],"name":"getWitnetConfig","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getWitnetPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasAccess","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"bytes","name":"_calldata","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"latestAnswer","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"configCount","internalType":"uint32"},{"type":"uint32","name":"blockNumber","internalType":"uint32"}],"name":"latestConfigDetails","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestRound","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint80","name":"roundId","internalType":"uint80"},{"type":"int256","name":"answer","internalType":"int256"},{"type":"uint256","name":"startedAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"},{"type":"uint80","name":"answeredInRound","internalType":"uint80"}],"name":"latestRoundData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"nextTransmitter","internalType":"address"},{"type":"address","name":"afterNextTransmitter","internalType":"address"},{"type":"uint8","name":"nextIndex","internalType":"uint8"},{"type":"uint256","name":"transmittersLength","internalType":"uint256"},{"type":"uint80","name":"roundId","internalType":"uint80"},{"type":"int192","name":"answer","internalType":"int192"},{"type":"uint256","name":"startedAt","internalType":"uint256"},{"type":"uint256","name":"updatedAt","internalType":"uint256"}],"name":"latestTransmissionDetails","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"lowerBoundAnchorRatio","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IMojitoOracle"}],"name":"mojitoOracle","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeAccess","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAnchorRatio","inputs":[{"type":"uint8","name":"_lowerBoundAnchorRatio","internalType":"uint8"},{"type":"uint8","name":"_upperBoundAnchorRatio","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setConfig","inputs":[{"type":"address[]","name":"_signers","internalType":"address[]"},{"type":"address[]","name":"_transmitters","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMojitoConfig","inputs":[{"type":"bool","name":"_available","internalType":"bool"},{"type":"bytes32","name":"_pairA","internalType":"bytes32"},{"type":"uint256","name":"_pairABaseUnit","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMojitoOracle","inputs":[{"type":"address","name":"_oracle","internalType":"contract IMojitoOracle"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setWitnetConfig","inputs":[{"type":"bool","name":"_available","internalType":"bool"},{"type":"bytes32","name":"_pairA","internalType":"bytes32"},{"type":"bytes32","name":"_pairB","internalType":"bytes32"},{"type":"uint256","name":"_pairABaseUnit","internalType":"uint256"},{"type":"uint256","name":"_pairBBaseUnit","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setWitnetOracle","inputs":[{"type":"address","name":"_oracle","internalType":"contract IERC2362"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transmit","inputs":[{"type":"bytes","name":"_report","internalType":"bytes"},{"type":"bytes32","name":"_rs","internalType":"bytes32"},{"type":"bytes32","name":"_ss","internalType":"bytes32"},{"type":"uint8","name":"_vs","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transmitWithForce","inputs":[{"type":"uint192","name":"median","internalType":"uint192"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"typeAndVersion","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"upperBoundAnchorRatio","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"validateAnswerEnabled","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"version","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC2362"}],"name":"witnetOracle","inputs":[]}]
Contract Creation Code
0x60c06040523480156200001157600080fd5b506040516200398938038062003989833981810160405260e08110156200003757600080fd5b8151602083015160408085015160608601805192519496939591949391820192846401000000008211156200006b57600080fd5b9083019060208201858111156200008157600080fd5b82516401000000008111828201881017156200009c57600080fd5b82525081516020918201929091019080838360005b83811015620000cb578181015183820152602001620000b1565b50505050905090810190601f168015620000f95780820380516001836020036101000a031916815260200191505b5060409081526020820151908201516060909201519093509091508686868686868682828683338060008162000176576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620001a957620001a98162000282565b505050620001bd846200033260201b60201c565b620001c883620003ab565b60ff918216600a0a6080526001805460ff60a01b1916600160a01b92151592909202919091179055600e805460ff60e01b1916600160e01b8c8416021760ff60e81b1916600160e81b928b1692909202919091179055505060f885901b7fff000000000000000000000000000000000000000000000000000000000000001660a05283516200025f90601390602087019062000423565b50506014805460ff1916600117905550620004cf9b505050505050505050505050565b6001600160a01b038116331415620002e1576040805162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600a546001600160a01b039081169082168114620003a757600a80546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f9d835f4731b75b6c2365317484d718ea9ba2102b89b5547092f7fe1c6fea5c299281900390910190a15b5050565b600b546001600160a01b039081169082168114620003a757600b80546001600160a01b0319166001600160a01b03848116918217909255604080519284168352602083019190915280517f5308b9ec263489f989284cee03c20f22af06d25e5758670c809795165997ea839281900390910190a15050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200045b5760008555620004a6565b82601f106200047657805160ff1916838001178555620004a6565b82800160010185558215620004a6579182015b82811115620004a657825182559160200191906001019062000489565b50620004b4929150620004b8565b5090565b5b80821115620004b45760008155600101620004b9565b60805160a05160f81c6134846200050560003980610bcc5250806116a952806125ba52806126a1528061301252506134846000f3fe608060405234801561001057600080fd5b50600436106102e95760003560e01c80638038e4a111610191578063b2310a40116100e3578063dc7f012411610097578063f27f55c011610071578063f27f55c0146109d9578063f2fde38b14610a10578063feaf968c14610a43576102e9565b8063dc7f012414610937578063dd76c8e11461093f578063e5fe457714610967576102e9565b8063b633620c116100c8578063b633620c1461090a578063c769952114610927578063d2266a4d1461092f576102e9565b8063b2310a40146108b6578063b5ab58dc146108ed576102e9565b806392b8435711610145578063a118f2491161011f578063a118f24914610848578063a5db36ed1461087b578063af8477c6146108ae576102e9565b806392b84357146107a557806397953585146107ad5780639a6fc8f5146107d5576102e9565b80638205bf6a116101765780638205bf6a146107625780638823da6c1461076a5780638da5cb5b1461079d576102e9565b80638038e4a11461072957806381ff704814610731576102e9565b806350d25bcd1161024a578063666cab8d116101fe5780637284e416116101d85780637284e416146106e6578063789a0e61146106ee57806379ba509714610721576102e9565b8063666cab8d146105c3578063668a0f021461061b5780636b14daf814610623576102e9565b806354fd4d501161022f57806354fd4d50146104f1578063632042b4146104f95780636659d920146105bb576102e9565b806350d25bcd146104cd57806352c48571146104d5576102e9565b806324105209116102a1578063313ce56711610286578063313ce5671461043e578063420d2d631461044657806343c417a21461044e576102e9565b806324105209146103ef57806326300a3b1461040d576102e9565b806311b36ce5116102d257806311b36ce514610323578063181f5a771461033d578063194d4d9a146103ba576102e9565b80630490fd1d146102ee5780630a7569831461031b575b600080fd5b6103196004803603606081101561030457600080fd5b50803515159060208101359060400135610a4b565b005b610319610ad1565b61032b610b38565b60408051918252519081900360200190f35b610345610b48565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561037f578181015183820152602001610367565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103c2610b68565b60408051951515865260208601949094528484019290925260608401526080830152519081900360a00190f35b6103f7610b84565b6040805160ff9092168252519081900360200190f35b610415610bae565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103f7610bca565b610319610bee565b6103196004803603608081101561046457600080fd5b81019060208101813564010000000081111561047f57600080fd5b82018360208201111561049157600080fd5b803590602001918460018302840111640100000000831117156104b357600080fd5b91935091508035906020810135906040013560ff16610c6c565b61032b61106c565b6104dd611108565b604080519115158252519081900360200190f35b61032b611129565b6103196004803603604081101561050f57600080fd5b81019060208101813564010000000081111561052a57600080fd5b82018360208201111561053c57600080fd5b8035906020019184602083028401116401000000008311171561055e57600080fd5b91939092909160208101903564010000000081111561057c57600080fd5b82018360208201111561058e57600080fd5b803590602001918460208302840111640100000000831117156105b057600080fd5b50909250905061112e565b61032b6116a7565b6105cb6116cb565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106075781810151838201526020016105ef565b505050509050019250505060405180910390f35b61032b61173a565b6104dd6004803603604081101561063957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561067157600080fd5b82018360208201111561068357600080fd5b803590602001918460018302840111640100000000831117156106a557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506117d6945050505050565b61034561180b565b6103196004803603602081101561070457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118a7565b6103196118bb565b6103196119a3565b610739611a0b565b604051808363ffffffff1681526020018263ffffffff1681526020019250505060405180910390f35b61032b611a24565b6103196004803603602081101561078057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ac0565b610415611b79565b6103f7611b95565b610319600480360360408110156107c357600080fd5b5060ff81358116916020013516611bbe565b6107fe600480360360208110156107eb57600080fd5b503569ffffffffffffffffffff16611d72565b604051808669ffffffffffffffffffff1681526020018581526020018481526020018381526020018269ffffffffffffffffffff1681526020019550505050505060405180910390f35b6103196004803603602081101561085e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e27565b6103196004803603602081101561089157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ee2565b610319611ef3565b610319600480360360a08110156108cc57600080fd5b50803515159060208101359060408101359060608101359060800135611f87565b61032b6004803603602081101561090357600080fd5b5035612027565b61032b6004803603602081101561092057600080fd5b50356120cc565b61032b612169565b610415612173565b6104dd61218f565b610947612198565b604080519315158452602084019290925282820152519081900360600190f35b61096f6121ac565b6040805173ffffffffffffffffffffffffffffffffffffffff998a16815297909816602088015260ff90951686880152606086019390935269ffffffffffffffffffff909116608085015260170b60a084015260c083015260e08201529051908190036101000190f35b610319600480360360208110156109ef57600080fd5b503577ffffffffffffffffffffffffffffffffffffffffffffffff166123b2565b61031960048036036020811015610a2657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166123c4565b6107fe6123d5565b610a53612488565b600280548415157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091168117909155600383905560048290556040805191825260208201849052818101839052517f2978888affaf766022740d128cfc5375b42a4cdf47a49fd773497210645f8fbf9181900360600190a1505050565b610ad9612488565b60145460ff1615610b3657601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f3be8a977a014527b50ae38adda80b56911c267328965c98ddc385d248f53963890600090a15b565b6000610b426124f4565b90505b90565b606060405180606001604052806028815260200161333c60289139905090565b60055460065460075460085460095460ff909416939091929394565b600e547d010000000000000000000000000000000000000000000000000000000000900460ff1681565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b610bf6612488565b60015474010000000000000000000000000000000000000000900460ff1615610b3657600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f625848e8e55631f99209e68ae0f6cbe04c01ee090e7addf3b54e93756c58aa9c90600090a1565b336000908152600f602052604090205460ff16610cd0576040805162461bcd60e51b815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015290519081900360640190fd5b610cd86126df565b3614610d2b576040805162461bcd60e51b815260206004820181905260248201527f7472616e736d6974206d657373616765206c656e677468206d69736d61746368604482015290519081900360640190fd5b60008086866040811015610d3e57600080fd5b50600c5463ffffffff9081166000908152600d602090815260409091205477ffffffffffffffffffffffffffffffffffffffffffffffff8435169550920135811692507c010000000000000000000000000000000000000000000000000000000090910416808211610df7576040805162461bcd60e51b815260206004820152601e60248201527f696e76616c6964206f62736572766174696f6e732074696d657374616d700000604482015290519081900360640190fd5b600088886040518083838082843760405192018290039091209450610e20935061326992505050565b600060018388601b018b8b60405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015610e7f573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526010602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290945092509050610f48576040805162461bcd60e51b815260206004820152600f60248201527f7369676e6174757265206572726f720000000000000000000000000000000000604482015290519081900360640190fd5b505060015474010000000000000000000000000000000000000000900460ff16159050610fa657610f928377ffffffffffffffffffffffffffffffffffffffffffffffff166126e4565b15610fa157610fa18383612793565b611062565b600c5463ffffffff166000908152600d602052604090205460170b77ffffffffffffffffffffffffffffffffffffffffffffffff168015611056576110058477ffffffffffffffffffffffffffffffffffffffffffffffff1682612a01565b611056576040805162461bcd60e51b815260206004820152601e60248201527f6d656469616e206973206f7574206f66206d696e2d6d61782072616e67650000604482015290519081900360640190fd5b6110608484612793565b505b5050505050505050565b60006110af336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611100576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612ab5565b60015474010000000000000000000000000000000000000000900460ff1681565b600181565b611136612488565b82811461118a576040805162461bcd60e51b815260206004820152601660248201527f6f7261636c65206c656e677468206d69736d6174636800000000000000000000604482015290519081900360640190fd5b60115460005b81811015611253576000601182815481106111a757fe5b60009182526020822001546012805473ffffffffffffffffffffffffffffffffffffffff909216935090849081106111db57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff948516835260108252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000908116909155959091168352600f9091529020805490921690915550600101611190565b5061126060116000613280565b61126c60126000613280565b60005b84811015611528576010600087878481811061128757fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff161561130c576040805162461bcd60e51b815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015290519081900360640190fd5b604080518082019091526001815260ff821660208201526010600088888581811061133357fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508181019290925260400160009081208351815494909301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909416921515929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff90941693909302929092179055600f908585848181106113dc57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1615611461576040805162461bcd60e51b815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015290519081900360640190fd5b604080518082019091526001815260ff82166020820152600f600086868581811061148857fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff16835250818101929092526040016000208251815493909201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316911515919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560010161126f565b506115356011868661329e565b506115426012848461329e565b50600e80544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff84161780831660010183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000090911617938490556040805191909304821680825293909116602080830182905260809383018481529383018990527fe8d070a65cc69d4aaeb20e8cdc65fdd7a656a77ee34614d6758ffd9eac3d1cd09385938b928b928b928b92909190606083019060a08401908890880280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039a509098505050505050505050a1505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060601280548060200260200160405190810160405280929190818152602001828054801561173057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611705575b5050505050905090565b600061177d336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b6117ce576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612ad7565b60006117e28383612ae3565b80611802575073ffffffffffffffffffffffffffffffffffffffff831632145b90505b92915050565b606061184e336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b61189f576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612b20565b6118af612488565b6118b881612bcb565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611927576040805162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015290519081900360640190fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6119ab612488565b60145460ff16610b3657601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517faebf329500988c6488a0074e5a0a9ff304561fc5c6fc877aeb1d59c8282c348090600090a1565b600e5463ffffffff808216916401000000009004169091565b6000611a67336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611ab8576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612c75565b611ac8612488565b73ffffffffffffffffffffffffffffffffffffffff811660009081526015602052604090205460ff16156118b85773ffffffffffffffffffffffffffffffffffffffff811660008181526015602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815192835290517f3d68a6fce901d20453d1a7aa06bf3950302a735948037deb182a8db66df2a0d19281900390910190a150565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b600e547c0100000000000000000000000000000000000000000000000000000000900460ff1681565b611bc6612488565b60ff821660501115611c095760405162461bcd60e51b81526004018080602001828103825260478152602001806133646047913960600191505060405180910390fd5b60ff811660781015611c4c5760405162461bcd60e51b81526004018080602001828103825260498152602001806134066049913960600191505060405180910390fd5b8160ff168160ff1611611c905760405162461bcd60e51b815260040180806020018281038252603a8152602001806133cc603a913960400191505060405180910390fd5b600e805460ff8381167d0100000000000000000000000000000000000000000000000000000000009081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8388167c01000000000000000000000000000000000000000000000000000000009081027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff909616959095171617938490556040805193850483168452930416602082015281517ff899e0ea4845aabbeda4bd108029c91ecfd7e0afa5a1eefbdbf436d15a6ffb3c929181900390910190a15050565b6000806000806000611dbb336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611e0c576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1586612cb3565b939a9299509097509550909350915050565b611e2f612488565b73ffffffffffffffffffffffffffffffffffffffff811660009081526015602052604090205460ff166118b85773ffffffffffffffffffffffffffffffffffffffff811660008181526015602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815192835290517f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49281900390910190a150565b611eea612488565b6118b881612e22565b611efb612488565b60015474010000000000000000000000000000000000000000900460ff16610b3657600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f0b3307cc46a1592167f2a25f93a31437772754c8517ffb3c78ab9d254183300590600090a1565b611f8f612488565b600580548615157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091168117909155600685905560078490556008839055600982905560408051918252602082018690528181018590526060820184905260808201839052517fb5e4346584d07c27736121a2e37073a71bed9243ef9c7fed5e18520cda3a85919181900360a00190a15050505050565b600061206a336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b6120bb576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6120c482612ecb565b90505b919050565b600061210f336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b612160576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6120c482612f01565b6000610b42612f53565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b60145460ff1681565b60025460035460045460ff90921691909192565b600080808080808080333214612209576040805162461bcd60e51b815260206004820152601460248201527f4f6e6c792063616c6c61626c6520627920454f41000000000000000000000000604482015290519081900360640190fd5b601254600096508690801561231b57612220613269565b50600e5468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff166000908152600f602090815260409182902082518084019093525460ff80821615801585526101009092041691830191909152612297576020810151600101985060ff891682141561229757600098505b60018901925060ff83168214156122ad57600092505b60128960ff16815481106122bd57fe5b6000918252602090912001546012805473ffffffffffffffffffffffffffffffffffffffff9092169c509060ff85169081106122f557fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169950505b600c5463ffffffff9081166000818152600d602090815260409182902082516060810184529054601781810b810b900b8083527801000000000000000000000000000000000000000000000000820487169383018490527c010000000000000000000000000000000000000000000000000000000090910490951692018290529c9d9b9c9a9b939a91995091975095509350915050565b6123ba612488565b6118b88142612793565b6123cc612488565b6118b881613036565b600080600080600061241e336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b61246f576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b612477613117565b945094509450945094509091929394565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b36576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60055460009060ff16156126d957600b54600654604080517ff78eea8300000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff169163f78eea83916024808301926060929190829003018186803b15801561257757600080fd5b505afa15801561258b573d6000803e3d6000fd5b505050506040513d60608110156125a157600080fd5b50516007549091506125ec576008546125e4906125de837f00000000000000000000000000000000000000000000000000000000000000006131a6565b906131ff565b915050610b45565b600b54600754604080517ff78eea8300000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff169163f78eea83916024808301926060929190829003018186803b15801561266157600080fd5b505afa158015612675573d6000803e3d6000fd5b505050506040513d606081101561268b57600080fd5b50516009546008549192506126d0916125de90817f00000000000000000000000000000000000000000000000000000000000000006126ca88886131a6565b906131a6565b92505050610b45565b50600090565b60e490565b6000806126ef612f53565b90506126fb8382612a01565b1561270a5760019150506120c7565b60006127146124f4565b90506127208482612a01565b15612730576001925050506120c7565b600c546040805186815260208101859052808201849052426060820152905163ffffffff928316600101909216917f65565676f315d68005ab81e249a31da541380309599c72a46103cbf9381cf6e29181900360800190a26000925050506120c7565b6040805160208082018352600c5463ffffffff90811660010181168352835160608082018652601788810b808452888516848701818152428716868b01908152895188166000908152600d8a528b9020965187549251915189167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff928a167801000000000000000000000000000000000000000000000000027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff9290970b77ffffffffffffffffffffffffffffffffffffffffffffffff167fffffffffffffffff0000000000000000000000000000000000000000000000009094169390931716949094179390931692909217909355600e805468010000000000000000339081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff909216919091179091558651885194855295840152828701529451939492909116927f38567aa999bdbf56a2a0e536f6d3420a6befcc0d5a443f686e3bded71d09157e929181900390910190a280516040805163ffffffff8581168252915160009392909216917f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac602719181900360200190a3806000015163ffffffff168360170b7f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f426040518082815260200191505060405180910390a351600c80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9092169190911790555050565b60008083118015612a125750600082115b15612aac57600e54600090612a52906064906125de9086907c0100000000000000000000000000000000000000000000000000000000900460ff166131a6565b600e54909150600090612a91906064906125de9087907d010000000000000000000000000000000000000000000000000000000000900460ff166131a6565b9050848211158015612aa35750808511155b92505050611805565b50600092915050565b600c5463ffffffff166000908152600d6020526040902054601790810b900b90565b600c5463ffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff821660009081526015602052604081205460ff168061180257505060145460ff161592915050565b60138054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156117305780601f10612b9f57610100808354040283529160200191611730565b820191906000526020600020905b815481529060010190602001808311612bad57509395945050505050565b600a5473ffffffffffffffffffffffffffffffffffffffff9081169082168114612c7157600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255604080519284168352602083019190915280517f9d835f4731b75b6c2365317484d718ea9ba2102b89b5547092f7fe1c6fea5c299281900390910190a15b5050565b600c5463ffffffff9081166000908152600d60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b600080600080600063ffffffff8669ffffffffffffffffffff1611156040518060400160405280600f81526020017f4e6f20646174612070726573656e74000000000000000000000000000000000081525090612d8e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d53578181015183820152602001612d3b565b50505050905090810190601f168015612d805780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505063ffffffff8381166000908152600d602090815260409182902082516060810184529054601781810b810b810b8084527801000000000000000000000000000000000000000000000000830487169484018590527c01000000000000000000000000000000000000000000000000000000009092049095169190930181905295969190920b949193509091508490565b600b5473ffffffffffffffffffffffffffffffffffffffff9081169082168114612c7157600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255604080519284168352602083019190915280517f5308b9ec263489f989284cee03c20f22af06d25e5758670c809795165997ea839281900390910190a15050565b600063ffffffff821115612ee1575060006120c7565b5063ffffffff166000908152600d6020526040902054601790810b900b90565b600063ffffffff821115612f17575060006120c7565b5063ffffffff9081166000908152600d60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b60025460009060ff16156126d957600a54600354604080517f0ca55a8e00000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff1691630ca55a8e916024808301926020929190829003018186803b158015612fd657600080fd5b505afa158015612fea573d6000803e3d6000fd5b505050506040513d602081101561300057600080fd5b50516004549091506125e4906125de837f00000000000000000000000000000000000000000000000000000000000000006131a6565b73ffffffffffffffffffffffffffffffffffffffff81163314156130a1576040805162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600c5463ffffffff9081166000818152600d602090815260409182902082516060810184529054601781810b810b810b8084527801000000000000000000000000000000000000000000000000830488169484018590527c01000000000000000000000000000000000000000000000000000000009092049096169190930181905292949190930b9291908490565b6000826131b557506000611805565b828202828482816131c257fe5b04146118025760405162461bcd60e51b81526004018080602001828103825260218152602001806133ab6021913960400191505060405180910390fd5b6000808211613255576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161326057fe5b04949350505050565b604080518082019091526000808252602082015290565b50805460008255906000526020600020908101906118b89190613326565b828054828255906000526020600020908101928215613316579160200282015b828111156133165781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906132be565b50613322929150613326565b5090565b5b80821115613322576000815560010161332756fe416363657373436f6e74726f6c6c65644f6666636861696e41676772656761746f7220312e302e306c6f776572426f756e64416e63686f72526174696f206d7573742067726561746572206f7220657175616c20746f206d696e4c6f776572426f756e64416e63686f72526174696f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777570706572426f756e64416e63686f72526174696f206d757374204c657373207468616e206c6f776572426f756e64416e63686f72526174696f7570706572426f756e64416e63686f72526174696f206d757374204c657373207468616e206f7220657175616c20746f206d61785570706572426f756e64416e63686f72526174696fa264697066735822122089c04ce7e80dc14713cd06e7c1d1c712af74c99da7dfd6ad6771310f18c7139364736f6c63430007060033000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000009515646b5833526dff12fae9b03754c7f0e0a8f000000000000000000000000d39d4d972c7e166856c4eb29e54d3548b4597f530000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a55534443202f2055534400000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106102e95760003560e01c80638038e4a111610191578063b2310a40116100e3578063dc7f012411610097578063f27f55c011610071578063f27f55c0146109d9578063f2fde38b14610a10578063feaf968c14610a43576102e9565b8063dc7f012414610937578063dd76c8e11461093f578063e5fe457714610967576102e9565b8063b633620c116100c8578063b633620c1461090a578063c769952114610927578063d2266a4d1461092f576102e9565b8063b2310a40146108b6578063b5ab58dc146108ed576102e9565b806392b8435711610145578063a118f2491161011f578063a118f24914610848578063a5db36ed1461087b578063af8477c6146108ae576102e9565b806392b84357146107a557806397953585146107ad5780639a6fc8f5146107d5576102e9565b80638205bf6a116101765780638205bf6a146107625780638823da6c1461076a5780638da5cb5b1461079d576102e9565b80638038e4a11461072957806381ff704814610731576102e9565b806350d25bcd1161024a578063666cab8d116101fe5780637284e416116101d85780637284e416146106e6578063789a0e61146106ee57806379ba509714610721576102e9565b8063666cab8d146105c3578063668a0f021461061b5780636b14daf814610623576102e9565b806354fd4d501161022f57806354fd4d50146104f1578063632042b4146104f95780636659d920146105bb576102e9565b806350d25bcd146104cd57806352c48571146104d5576102e9565b806324105209116102a1578063313ce56711610286578063313ce5671461043e578063420d2d631461044657806343c417a21461044e576102e9565b806324105209146103ef57806326300a3b1461040d576102e9565b806311b36ce5116102d257806311b36ce514610323578063181f5a771461033d578063194d4d9a146103ba576102e9565b80630490fd1d146102ee5780630a7569831461031b575b600080fd5b6103196004803603606081101561030457600080fd5b50803515159060208101359060400135610a4b565b005b610319610ad1565b61032b610b38565b60408051918252519081900360200190f35b610345610b48565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561037f578181015183820152602001610367565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103c2610b68565b60408051951515865260208601949094528484019290925260608401526080830152519081900360a00190f35b6103f7610b84565b6040805160ff9092168252519081900360200190f35b610415610bae565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103f7610bca565b610319610bee565b6103196004803603608081101561046457600080fd5b81019060208101813564010000000081111561047f57600080fd5b82018360208201111561049157600080fd5b803590602001918460018302840111640100000000831117156104b357600080fd5b91935091508035906020810135906040013560ff16610c6c565b61032b61106c565b6104dd611108565b604080519115158252519081900360200190f35b61032b611129565b6103196004803603604081101561050f57600080fd5b81019060208101813564010000000081111561052a57600080fd5b82018360208201111561053c57600080fd5b8035906020019184602083028401116401000000008311171561055e57600080fd5b91939092909160208101903564010000000081111561057c57600080fd5b82018360208201111561058e57600080fd5b803590602001918460208302840111640100000000831117156105b057600080fd5b50909250905061112e565b61032b6116a7565b6105cb6116cb565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106075781810151838201526020016105ef565b505050509050019250505060405180910390f35b61032b61173a565b6104dd6004803603604081101561063957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561067157600080fd5b82018360208201111561068357600080fd5b803590602001918460018302840111640100000000831117156106a557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506117d6945050505050565b61034561180b565b6103196004803603602081101561070457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118a7565b6103196118bb565b6103196119a3565b610739611a0b565b604051808363ffffffff1681526020018263ffffffff1681526020019250505060405180910390f35b61032b611a24565b6103196004803603602081101561078057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ac0565b610415611b79565b6103f7611b95565b610319600480360360408110156107c357600080fd5b5060ff81358116916020013516611bbe565b6107fe600480360360208110156107eb57600080fd5b503569ffffffffffffffffffff16611d72565b604051808669ffffffffffffffffffff1681526020018581526020018481526020018381526020018269ffffffffffffffffffff1681526020019550505050505060405180910390f35b6103196004803603602081101561085e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611e27565b6103196004803603602081101561089157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ee2565b610319611ef3565b610319600480360360a08110156108cc57600080fd5b50803515159060208101359060408101359060608101359060800135611f87565b61032b6004803603602081101561090357600080fd5b5035612027565b61032b6004803603602081101561092057600080fd5b50356120cc565b61032b612169565b610415612173565b6104dd61218f565b610947612198565b604080519315158452602084019290925282820152519081900360600190f35b61096f6121ac565b6040805173ffffffffffffffffffffffffffffffffffffffff998a16815297909816602088015260ff90951686880152606086019390935269ffffffffffffffffffff909116608085015260170b60a084015260c083015260e08201529051908190036101000190f35b610319600480360360208110156109ef57600080fd5b503577ffffffffffffffffffffffffffffffffffffffffffffffff166123b2565b61031960048036036020811015610a2657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166123c4565b6107fe6123d5565b610a53612488565b600280548415157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091168117909155600383905560048290556040805191825260208201849052818101839052517f2978888affaf766022740d128cfc5375b42a4cdf47a49fd773497210645f8fbf9181900360600190a1505050565b610ad9612488565b60145460ff1615610b3657601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f3be8a977a014527b50ae38adda80b56911c267328965c98ddc385d248f53963890600090a15b565b6000610b426124f4565b90505b90565b606060405180606001604052806028815260200161333c60289139905090565b60055460065460075460085460095460ff909416939091929394565b600e547d010000000000000000000000000000000000000000000000000000000000900460ff1681565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000881565b610bf6612488565b60015474010000000000000000000000000000000000000000900460ff1615610b3657600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f625848e8e55631f99209e68ae0f6cbe04c01ee090e7addf3b54e93756c58aa9c90600090a1565b336000908152600f602052604090205460ff16610cd0576040805162461bcd60e51b815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015290519081900360640190fd5b610cd86126df565b3614610d2b576040805162461bcd60e51b815260206004820181905260248201527f7472616e736d6974206d657373616765206c656e677468206d69736d61746368604482015290519081900360640190fd5b60008086866040811015610d3e57600080fd5b50600c5463ffffffff9081166000908152600d602090815260409091205477ffffffffffffffffffffffffffffffffffffffffffffffff8435169550920135811692507c010000000000000000000000000000000000000000000000000000000090910416808211610df7576040805162461bcd60e51b815260206004820152601e60248201527f696e76616c6964206f62736572766174696f6e732074696d657374616d700000604482015290519081900360640190fd5b600088886040518083838082843760405192018290039091209450610e20935061326992505050565b600060018388601b018b8b60405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015610e7f573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526010602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290945092509050610f48576040805162461bcd60e51b815260206004820152600f60248201527f7369676e6174757265206572726f720000000000000000000000000000000000604482015290519081900360640190fd5b505060015474010000000000000000000000000000000000000000900460ff16159050610fa657610f928377ffffffffffffffffffffffffffffffffffffffffffffffff166126e4565b15610fa157610fa18383612793565b611062565b600c5463ffffffff166000908152600d602052604090205460170b77ffffffffffffffffffffffffffffffffffffffffffffffff168015611056576110058477ffffffffffffffffffffffffffffffffffffffffffffffff1682612a01565b611056576040805162461bcd60e51b815260206004820152601e60248201527f6d656469616e206973206f7574206f66206d696e2d6d61782072616e67650000604482015290519081900360640190fd5b6110608484612793565b505b5050505050505050565b60006110af336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611100576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612ab5565b60015474010000000000000000000000000000000000000000900460ff1681565b600181565b611136612488565b82811461118a576040805162461bcd60e51b815260206004820152601660248201527f6f7261636c65206c656e677468206d69736d6174636800000000000000000000604482015290519081900360640190fd5b60115460005b81811015611253576000601182815481106111a757fe5b60009182526020822001546012805473ffffffffffffffffffffffffffffffffffffffff909216935090849081106111db57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff948516835260108252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000908116909155959091168352600f9091529020805490921690915550600101611190565b5061126060116000613280565b61126c60126000613280565b60005b84811015611528576010600087878481811061128757fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff161561130c576040805162461bcd60e51b815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015290519081900360640190fd5b604080518082019091526001815260ff821660208201526010600088888581811061133357fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508181019290925260400160009081208351815494909301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909416921515929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff90941693909302929092179055600f908585848181106113dc57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1615611461576040805162461bcd60e51b815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015290519081900360640190fd5b604080518082019091526001815260ff82166020820152600f600086868581811061148857fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff16835250818101929092526040016000208251815493909201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316911515919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560010161126f565b506115356011868661329e565b506115426012848461329e565b50600e80544363ffffffff9081166401000000009081027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff84161780831660010183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000090911617938490556040805191909304821680825293909116602080830182905260809383018481529383018990527fe8d070a65cc69d4aaeb20e8cdc65fdd7a656a77ee34614d6758ffd9eac3d1cd09385938b928b928b928b92909190606083019060a08401908890880280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039a509098505050505050505050a1505050505050565b7f0000000000000000000000000000000000000000000000000000000005f5e10081565b6060601280548060200260200160405190810160405280929190818152602001828054801561173057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611705575b5050505050905090565b600061177d336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b6117ce576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612ad7565b60006117e28383612ae3565b80611802575073ffffffffffffffffffffffffffffffffffffffff831632145b90505b92915050565b606061184e336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b61189f576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612b20565b6118af612488565b6118b881612bcb565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611927576040805162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015290519081900360640190fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6119ab612488565b60145460ff16610b3657601480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517faebf329500988c6488a0074e5a0a9ff304561fc5c6fc877aeb1d59c8282c348090600090a1565b600e5463ffffffff808216916401000000009004169091565b6000611a67336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611ab8576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610b42612c75565b611ac8612488565b73ffffffffffffffffffffffffffffffffffffffff811660009081526015602052604090205460ff16156118b85773ffffffffffffffffffffffffffffffffffffffff811660008181526015602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815192835290517f3d68a6fce901d20453d1a7aa06bf3950302a735948037deb182a8db66df2a0d19281900390910190a150565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b600e547c0100000000000000000000000000000000000000000000000000000000900460ff1681565b611bc6612488565b60ff821660501115611c095760405162461bcd60e51b81526004018080602001828103825260478152602001806133646047913960600191505060405180910390fd5b60ff811660781015611c4c5760405162461bcd60e51b81526004018080602001828103825260498152602001806134066049913960600191505060405180910390fd5b8160ff168160ff1611611c905760405162461bcd60e51b815260040180806020018281038252603a8152602001806133cc603a913960400191505060405180910390fd5b600e805460ff8381167d0100000000000000000000000000000000000000000000000000000000009081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8388167c01000000000000000000000000000000000000000000000000000000009081027fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff909616959095171617938490556040805193850483168452930416602082015281517ff899e0ea4845aabbeda4bd108029c91ecfd7e0afa5a1eefbdbf436d15a6ffb3c929181900390910190a15050565b6000806000806000611dbb336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b611e0c576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e1586612cb3565b939a9299509097509550909350915050565b611e2f612488565b73ffffffffffffffffffffffffffffffffffffffff811660009081526015602052604090205460ff166118b85773ffffffffffffffffffffffffffffffffffffffff811660008181526015602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815192835290517f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49281900390910190a150565b611eea612488565b6118b881612e22565b611efb612488565b60015474010000000000000000000000000000000000000000900460ff16610b3657600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f0b3307cc46a1592167f2a25f93a31437772754c8517ffb3c78ab9d254183300590600090a1565b611f8f612488565b600580548615157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091168117909155600685905560078490556008839055600982905560408051918252602082018690528181018590526060820184905260808201839052517fb5e4346584d07c27736121a2e37073a71bed9243ef9c7fed5e18520cda3a85919181900360a00190a15050505050565b600061206a336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b6120bb576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6120c482612ecb565b90505b919050565b600061210f336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b612160576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6120c482612f01565b6000610b42612f53565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b60145460ff1681565b60025460035460045460ff90921691909192565b600080808080808080333214612209576040805162461bcd60e51b815260206004820152601460248201527f4f6e6c792063616c6c61626c6520627920454f41000000000000000000000000604482015290519081900360640190fd5b601254600096508690801561231b57612220613269565b50600e5468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff166000908152600f602090815260409182902082518084019093525460ff80821615801585526101009092041691830191909152612297576020810151600101985060ff891682141561229757600098505b60018901925060ff83168214156122ad57600092505b60128960ff16815481106122bd57fe5b6000918252602090912001546012805473ffffffffffffffffffffffffffffffffffffffff9092169c509060ff85169081106122f557fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169950505b600c5463ffffffff9081166000818152600d602090815260409182902082516060810184529054601781810b810b900b8083527801000000000000000000000000000000000000000000000000820487169383018490527c010000000000000000000000000000000000000000000000000000000090910490951692018290529c9d9b9c9a9b939a91995091975095509350915050565b6123ba612488565b6118b88142612793565b6123cc612488565b6118b881613036565b600080600080600061241e336000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d692505050565b61246f576040805162461bcd60e51b815260206004820152600960248201527f4e6f206163636573730000000000000000000000000000000000000000000000604482015290519081900360640190fd5b612477613117565b945094509450945094509091929394565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b36576040805162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015290519081900360640190fd5b60055460009060ff16156126d957600b54600654604080517ff78eea8300000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff169163f78eea83916024808301926060929190829003018186803b15801561257757600080fd5b505afa15801561258b573d6000803e3d6000fd5b505050506040513d60608110156125a157600080fd5b50516007549091506125ec576008546125e4906125de837f0000000000000000000000000000000000000000000000000000000005f5e1006131a6565b906131ff565b915050610b45565b600b54600754604080517ff78eea8300000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff169163f78eea83916024808301926060929190829003018186803b15801561266157600080fd5b505afa158015612675573d6000803e3d6000fd5b505050506040513d606081101561268b57600080fd5b50516009546008549192506126d0916125de90817f0000000000000000000000000000000000000000000000000000000005f5e1006126ca88886131a6565b906131a6565b92505050610b45565b50600090565b60e490565b6000806126ef612f53565b90506126fb8382612a01565b1561270a5760019150506120c7565b60006127146124f4565b90506127208482612a01565b15612730576001925050506120c7565b600c546040805186815260208101859052808201849052426060820152905163ffffffff928316600101909216917f65565676f315d68005ab81e249a31da541380309599c72a46103cbf9381cf6e29181900360800190a26000925050506120c7565b6040805160208082018352600c5463ffffffff90811660010181168352835160608082018652601788810b808452888516848701818152428716868b01908152895188166000908152600d8a528b9020965187549251915189167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff928a167801000000000000000000000000000000000000000000000000027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff9290970b77ffffffffffffffffffffffffffffffffffffffffffffffff167fffffffffffffffff0000000000000000000000000000000000000000000000009094169390931716949094179390931692909217909355600e805468010000000000000000339081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff909216919091179091558651885194855295840152828701529451939492909116927f38567aa999bdbf56a2a0e536f6d3420a6befcc0d5a443f686e3bded71d09157e929181900390910190a280516040805163ffffffff8581168252915160009392909216917f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac602719181900360200190a3806000015163ffffffff168360170b7f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f426040518082815260200191505060405180910390a351600c80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9092169190911790555050565b60008083118015612a125750600082115b15612aac57600e54600090612a52906064906125de9086907c0100000000000000000000000000000000000000000000000000000000900460ff166131a6565b600e54909150600090612a91906064906125de9087907d010000000000000000000000000000000000000000000000000000000000900460ff166131a6565b9050848211158015612aa35750808511155b92505050611805565b50600092915050565b600c5463ffffffff166000908152600d6020526040902054601790810b900b90565b600c5463ffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff821660009081526015602052604081205460ff168061180257505060145460ff161592915050565b60138054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156117305780601f10612b9f57610100808354040283529160200191611730565b820191906000526020600020905b815481529060010190602001808311612bad57509395945050505050565b600a5473ffffffffffffffffffffffffffffffffffffffff9081169082168114612c7157600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255604080519284168352602083019190915280517f9d835f4731b75b6c2365317484d718ea9ba2102b89b5547092f7fe1c6fea5c299281900390910190a15b5050565b600c5463ffffffff9081166000908152600d60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b600080600080600063ffffffff8669ffffffffffffffffffff1611156040518060400160405280600f81526020017f4e6f20646174612070726573656e74000000000000000000000000000000000081525090612d8e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d53578181015183820152602001612d3b565b50505050905090810190601f168015612d805780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505063ffffffff8381166000908152600d602090815260409182902082516060810184529054601781810b810b810b8084527801000000000000000000000000000000000000000000000000830487169484018590527c01000000000000000000000000000000000000000000000000000000009092049095169190930181905295969190920b949193509091508490565b600b5473ffffffffffffffffffffffffffffffffffffffff9081169082168114612c7157600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255604080519284168352602083019190915280517f5308b9ec263489f989284cee03c20f22af06d25e5758670c809795165997ea839281900390910190a15050565b600063ffffffff821115612ee1575060006120c7565b5063ffffffff166000908152600d6020526040902054601790810b900b90565b600063ffffffff821115612f17575060006120c7565b5063ffffffff9081166000908152600d60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b60025460009060ff16156126d957600a54600354604080517f0ca55a8e00000000000000000000000000000000000000000000000000000000815260048101929092525160009273ffffffffffffffffffffffffffffffffffffffff1691630ca55a8e916024808301926020929190829003018186803b158015612fd657600080fd5b505afa158015612fea573d6000803e3d6000fd5b505050506040513d602081101561300057600080fd5b50516004549091506125e4906125de837f0000000000000000000000000000000000000000000000000000000005f5e1006131a6565b73ffffffffffffffffffffffffffffffffffffffff81163314156130a1576040805162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600c5463ffffffff9081166000818152600d602090815260409182902082516060810184529054601781810b810b810b8084527801000000000000000000000000000000000000000000000000830488169484018590527c01000000000000000000000000000000000000000000000000000000009092049096169190930181905292949190930b9291908490565b6000826131b557506000611805565b828202828482816131c257fe5b04146118025760405162461bcd60e51b81526004018080602001828103825260218152602001806133ab6021913960400191505060405180910390fd5b6000808211613255576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161326057fe5b04949350505050565b604080518082019091526000808252602082015290565b50805460008255906000526020600020908101906118b89190613326565b828054828255906000526020600020908101928215613316579160200282015b828111156133165781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906132be565b50613322929150613326565b5090565b5b80821115613322576000815560010161332756fe416363657373436f6e74726f6c6c65644f6666636861696e41676772656761746f7220312e302e306c6f776572426f756e64416e63686f72526174696f206d7573742067726561746572206f7220657175616c20746f206d696e4c6f776572426f756e64416e63686f72526174696f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777570706572426f756e64416e63686f72526174696f206d757374204c657373207468616e206c6f776572426f756e64416e63686f72526174696f7570706572426f756e64416e63686f72526174696f206d757374204c657373207468616e206f7220657175616c20746f206d61785570706572426f756e64416e63686f72526174696fa264697066735822122089c04ce7e80dc14713cd06e7c1d1c712af74c99da7dfd6ad6771310f18c7139364736f6c63430007060033