Contract Address Details

0xeD074DA2A76FD2Ca90C1508930b4FB4420e413B0

Contract Name
WitnetPriceRouter
Creator
0x8d86bc–44ea8b at 0x92a376–d52b81
Balance
0 TCRO
Tokens
Fetching tokens...
Transactions
116 Transactions
Transfers
0 Transfers
Gas Used
1,286,005,577
Last Balance Update
21065314
Contract name:
WitnetPriceRouter




Optimization enabled
true
Compiler version
v0.8.11+commit.d7f03943




Optimization runs
200
EVM Version
default




Verified at
2022-03-21T15:02:20.714118Z

Contract source code

// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0 <0.9.0;
pragma experimental ABIEncoderV2;

// File: ado-contracts\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\interfaces\IERC165.sol
/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: contracts\interfaces\IWitnetPriceRouter.sol
/// @title The Witnet Price Router basic interface.
/// @dev Guides implementation of price feeds aggregation contracts.
/// @author The Witnet Foundation.
abstract contract IWitnetPriceRouter
    is
        IERC2362 
{
    /// Emitted everytime a currency pair is attached to a new price feed contract
    /// @dev See https://github.com/adoracles/ADOIPs/blob/main/adoip-0010.md 
    /// @dev to learn how these ids are created.
    event CurrencyPairSet(bytes32 indexed erc2362ID, IERC165 pricefeed);

    /// Helper pure function: returns hash of the provided ERC2362-compliant currency pair caption (aka ID).
    function currencyPairId(string memory) external pure virtual returns (bytes32);

    /// Returns the ERC-165-compliant price feed contract currently serving 
    /// updates on the given currency pair.
    function getPriceFeed(bytes32 _erc2362id) external view virtual returns (IERC165);

    /// Returns human-readable ERC2362-based caption of the currency pair being
    /// served by the given price feed contract address. 
    /// @dev Should fail if the given price feed contract address is not currently
    /// @dev registered in the router.
    function getPriceFeedCaption(IERC165) external view virtual returns (string memory);

    /// Returns human-readable caption of the ERC2362-based currency pair identifier, if known.
    function lookupERC2362ID(bytes32 _erc2362id) external view virtual returns (string memory);

    /// Register a price feed contract that will serve updates for the given currency pair.
    /// @dev Setting zero address to a currency pair implies that it will not be served any longer.
    /// @dev Otherwise, should fail if the price feed contract does not support the `IWitnetPriceFeed` interface,
    /// @dev or if given price feed is already serving another currency pair (within this WitnetPriceRouter instance).
    function setPriceFeed(
            IERC165 _pricefeed,
            uint256 _decimals,
            string calldata _base,
            string calldata _quote
        )
        external virtual;

    /// Returns list of known currency pairs IDs.
    function supportedCurrencyPairs() external view virtual returns (bytes32[] memory);

    /// Returns `true` if given pair is currently being served by a compliant price feed contract.
    function supportsCurrencyPair(bytes32 _erc2362id) external view virtual returns (bool);

    /// Returns `true` if given price feed contract is currently serving updates to any known currency pair. 
    function supportsPriceFeed(IERC165 _priceFeed) external view virtual returns (bool);
}
// File: node_modules\@openzeppelin\contracts\utils\Context.sol
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)


/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
// File: @openzeppelin\contracts\access\Ownable.sol
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)



/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
// File: contracts\interfaces\IWitnetPriceFeed.sol
/// @title The Witnet Price Feed basic interface.
/// @dev Guides implementation of active price feed polling contracts.
/// @author The Witnet Foundation.

interface IWitnetPriceFeed {

    /// Signals that a new price update request is being posted to the Witnet Request Board
    event PriceFeeding(address indexed from, uint256 queryId, uint256 extraFee);

    /// Estimates minimum fee amount in native currency to be paid when 
    /// requesting a new price update.
    /// @dev Actual fee depends on the gas price of the `requestUpdate()` transaction.
    /// @param _gasPrice Gas price expected to be paid when calling `requestUpdate()`
    function estimateUpdateFee(uint256 _gasPrice) external view returns (uint256);

    /// Returns result of the last valid price update request successfully solved by the Witnet oracle.
    function lastPrice() external view returns (int256);

    /// Returns the EVM-timestamp when last valid price was reported back from the Witnet oracle.
    function lastTimestamp() external view returns (uint256);    

    /// Returns tuple containing last valid price and timestamp, as well as status code of latest update
    /// request that got posted to the Witnet Request Board.
    /// @return _lastPrice Last valid price reported back from the Witnet oracle.
    /// @return _lastTimestamp EVM-timestamp of the last valid price.
    /// @return _lastDrTxHash Hash of the Witnet Data Request that solved the last valid price.
    /// @return _latestUpdateStatus Status code of the latest update request.
    function lastValue() external view returns (
        int _lastPrice,
        uint _lastTimestamp,
        bytes32 _lastDrTxHash,
        uint _latestUpdateStatus
    );

    /// Returns identifier of the latest update request posted to the Witnet Request Board.
    function latestQueryId() external view returns (uint256);

    /// Returns hash of the Witnet Data Request that solved the latest update request.
    /// @dev Returning 0 while the latest update request remains unsolved.
    function latestUpdateDrTxHash() external view returns (bytes32);

    /// Returns error message of latest update request posted to the Witnet Request Board.
    /// @dev Returning empty string if the latest update request remains unsolved, or
    /// @dev if it was succesfully solved with no errors.
    function latestUpdateErrorMessage() external view returns (string memory);

    /// Returns status code of latest update request posted to the Witnet Request Board:
    /// @dev Status codes:
    /// @dev   - 200: update request was succesfully solved with no errors
    /// @dev   - 400: update request was solved with errors
    /// @dev   - 404: update request was not solved yet 
    function latestUpdateStatus() external view returns (uint256);

    /// Returns `true` if latest update request posted to the Witnet Request Board 
    /// has not been solved yet by the Witnet oracle.
    function pendingUpdate() external view returns (bool);

    /// Posts a new price update request to the Witnet Request Board. Requires payment of a fee
    /// that depends on the value of `tx.gasprice`. See `estimateUpdateFee(uint256)`.
    /// @dev If previous update request was not solved yet, calling this method again allows
    /// @dev upgrading the update fee if called with a higher `tx.gasprice` value.
    function requestUpdate() external payable;

    /// Tells whether this contract implements the interface defined by `interfaceId`. 
    /// @dev See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
    /// @dev to learn more about how these ids are created.
    function supportsInterface(bytes4) external view returns (bool);
}
// File: @openzeppelin\contracts\utils\Strings.sol
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)


/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}
// File: contracts\apps\WitnetPriceRouter.sol
contract WitnetPriceRouter
    is
        IWitnetPriceRouter,
        Ownable
{
    using Strings for uint256;
    
    struct Pair {
        IERC165 pricefeed;
        uint256 decimals;
        string  base;
        string  quote;
    }    

    mapping (bytes4 => Pair) internal __pairs;
    mapping (address => bytes32) internal __pricefeedId_;

    bytes32[] internal __supportedCurrencyPairs;

    // ========================================================================
    // --- Implementation of 'IERC2362' ---------------------------------------

    /// Returns last valid price value and timestamp, as well as status of
    /// the latest update request that got posted to the Witnet Request Board. 
    /// @dev Fails if the given currency pair is not currently supported.
    /// @param _erc2362id Price pair identifier as specified in https://github.com/adoracles/ADOIPs/blob/main/adoip-0010.md
    /// @return _lastPrice Last valid price reported back from the Witnet oracle.
    /// @return _lastTimestamp EVM-timestamp of the last valid price.
    /// @return _latestUpdateStatus Status code of latest update request that got posted to the Witnet Request Board:
    ///          - 200: latest update request was succesfully solved with no errors
    ///          - 400: latest update request was solved with errors
    ///          - 404: latest update request is still pending to be solved    
	function valueFor(bytes32 _erc2362id)
        external view
        virtual override
        returns (
            int256 _lastPrice,
            uint256 _lastTimestamp,
            uint256 _latestUpdateStatus
        )
    {
        IWitnetPriceFeed _pricefeed = IWitnetPriceFeed(address(getPriceFeed(_erc2362id)));
        require(address(_pricefeed) != address(0), "WitnetPriceRouter: unsupported currency pair");
        (_lastPrice, _lastTimestamp,, _latestUpdateStatus) = _pricefeed.lastValue();
    }


    // ========================================================================
    // --- Implementation of 'IWitnetPriceRouter' ---------------------------    

    /// Helper pure function: returns hash of the provided ERC2362-compliant currency pair caption (aka ID).
    function currencyPairId(string memory _caption)
        public pure
        virtual override
        returns (bytes32)
    {
        return keccak256(bytes(_caption));
    }

    /// Returns the ERC-165-compliant price feed contract currently serving 
    /// updates on the given currency pair.
    function getPriceFeed(bytes32 _erc2362id)
        public view
        virtual override
        returns (IERC165)
    {
        return __pairs[bytes4(_erc2362id)].pricefeed;
    }

    /// Returns human-readable ERC2362-based caption of the currency pair being
    /// served by the given price feed contract address. 
    /// @dev Fails if the given price feed contract address is not currently
    /// @dev registered in the router.
    function getPriceFeedCaption(IERC165 _pricefeed) 
        public view
        virtual override
        returns (string memory)
    {
        require(supportsPriceFeed(_pricefeed), "WitnetPriceRouter: unknown");
        return lookupERC2362ID(__pricefeedId_[address(_pricefeed)]);
    }

    /// Returns human-readable caption of the ERC2362-based currency pair identifier, if known.
    function lookupERC2362ID(bytes32 _erc2362id)
        public view
        virtual override
        returns (string memory _caption)
    {
        Pair storage _pair = __pairs[bytes4(_erc2362id)];
        if (
            bytes(_pair.base).length > 0 
                && bytes(_pair.quote).length > 0
        ) {
            _caption = string(abi.encodePacked(
                "Price-",
                _pair.base,
                "/",
                _pair.quote,
                "-",
                _pair.decimals.toString()
            ));
        }
    }

    /// Register a price feed contract that will serve updates for the given currency pair.
    /// @dev Setting zero address to a currency pair implies that it will not be served any longer.
    /// @dev Otherwise, fails if the price feed contract does not support the `IWitnetPriceFeed` interface,
    /// @dev or if given price feed is already serving another currency pair (within this WitnetPriceRouter instance).
    function setPriceFeed(
            IERC165 _pricefeed,
            uint256 _decimals,
            string calldata _base,
            string calldata _quote
        )
        public 
        virtual override
        onlyOwner
    {
        if (address(_pricefeed) != address(0)) {
            require(
                _pricefeed.supportsInterface(type(IWitnetPriceFeed).interfaceId),
                "WitnetPriceRouter: feed contract is not compliant with IWitnetPriceFeed"
            );
            require(
                __pricefeedId_[address(_pricefeed)] == bytes32(0),
                "WitnetPriceRouter: already serving a currency pair"
            );
        }
        bytes memory _caption = abi.encodePacked(
            "Price-",
            bytes(_base),
            "/",
            bytes(_quote),
            "-",
            _decimals.toString()
        );
        bytes32 _erc2362id = keccak256(_caption);
        
        Pair storage _record = __pairs[bytes4(_erc2362id)];
        address _currentPriceFeed = address(_record.pricefeed);
        if (bytes(_record.base).length == 0) {
            _record.base = _base;
            _record.quote = _quote;
            _record.decimals = _decimals;
            __supportedCurrencyPairs.push(_erc2362id);
        }
        else if (_currentPriceFeed != address(0)) {
            __pricefeedId_[_currentPriceFeed] = bytes32(0);
        }
        if (address(_pricefeed) != _currentPriceFeed) {
            __pricefeedId_[address(_pricefeed)] = _erc2362id;
        }
        _record.pricefeed = _pricefeed;
        emit CurrencyPairSet(_erc2362id, _pricefeed);
    }

    /// Returns list of known currency pairs IDs.
    function supportedCurrencyPairs()
        external view
        virtual override
        returns (bytes32[] memory)
    {
        return __supportedCurrencyPairs;
    }

    /// Returns `true` if given pair is currently being served by a compliant price feed contract.
    function supportsCurrencyPair(bytes32 _erc2362id)
        public view
        virtual override
        returns (bool)
    {
        return address(__pairs[bytes4(_erc2362id)].pricefeed) != address(0);
    }

    /// Returns `true` if given price feed contract is currently serving updates to any known currency pair. 
    function supportsPriceFeed(IERC165 _pricefeed)
        public view
        virtual override
        returns (bool)
    {
        return __pairs[bytes4(__pricefeedId_[address(_pricefeed)])].pricefeed == _pricefeed;
    }
}
        

Contract ABI

[{"type":"event","name":"CurrencyPairSet","inputs":[{"type":"bytes32","name":"erc2362ID","internalType":"bytes32","indexed":true},{"type":"address","name":"pricefeed","internalType":"contract IERC165","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"currencyPairId","inputs":[{"type":"string","name":"_caption","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC165"}],"name":"getPriceFeed","inputs":[{"type":"bytes32","name":"_erc2362id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getPriceFeedCaption","inputs":[{"type":"address","name":"_pricefeed","internalType":"contract IERC165"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"_caption","internalType":"string"}],"name":"lookupERC2362ID","inputs":[{"type":"bytes32","name":"_erc2362id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPriceFeed","inputs":[{"type":"address","name":"_pricefeed","internalType":"contract IERC165"},{"type":"uint256","name":"_decimals","internalType":"uint256"},{"type":"string","name":"_base","internalType":"string"},{"type":"string","name":"_quote","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"supportedCurrencyPairs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsCurrencyPair","inputs":[{"type":"bytes32","name":"_erc2362id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsPriceFeed","inputs":[{"type":"address","name":"_pricefeed","internalType":"contract IERC165"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"_lastPrice","internalType":"int256"},{"type":"uint256","name":"_lastTimestamp","internalType":"uint256"},{"type":"uint256","name":"_latestUpdateStatus","internalType":"uint256"}],"name":"valueFor","inputs":[{"type":"bytes32","name":"_erc2362id","internalType":"bytes32"}]}]
            

Contract Creation Code

0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6110728061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806399d32a041161007157806399d32a0414610157578063a027ad1514610177578063bbfa81181461019a578063ca64c540146101ad578063f2fde38b146101e2578063f78eea83146101f557600080fd5b80633fd29ebd146100b9578063715018a6146100d757806377021267146100e1578063835262f5146100f45780638c0adf621461011b5780638da5cb5b14610146575b600080fd5b6100c1610223565b6040516100ce9190610ae0565b60405180910390f35b6100df61027b565b005b6100df6100ef366004610b82565b6102ba565b61010d610102366004610c24565b805160209091012090565b6040519081526020016100ce565b61012e610129366004610cd5565b6105fd565b6040516001600160a01b0390911681526020016100ce565b6000546001600160a01b031661012e565b61016a610165366004610cd5565b610622565b6040516100ce9190610d1e565b61018a610185366004610d51565b6106b2565b60405190151581526020016100ce565b61016a6101a8366004610d51565b6106ea565b61018a6101bb366004610cd5565b6001600160e01b0319166000908152600160205260409020546001600160a01b0316151590565b6100df6101f0366004610d51565b610769565b610208610203366004610cd5565b610804565b604080519384526020840192909252908201526060016100ce565b6060600380548060200260200160405190810160405280929190818152602001828054801561027157602002820191906000526020600020905b81548152602001906001019080831161025d575b5050505050905090565b6000546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a590610d75565b60405180910390fd5b6102b860006108f1565b565b6000546001600160a01b031633146102e45760405162461bcd60e51b81526004016102a590610d75565b6001600160a01b03861615610465576040516301ffc9a760e01b8152632089297160e11b60048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610daa565b6103e45760405162461bcd60e51b815260206004820152604760248201527f5769746e65745072696365526f757465723a206665656420636f6e747261637460448201527f206973206e6f7420636f6d706c69616e74207769746820495769746e657450726064820152661a58d95199595960ca1b608482015260a4016102a5565b6001600160a01b038616600090815260026020526040902054156104655760405162461bcd60e51b815260206004820152603260248201527f5769746e65745072696365526f757465723a20616c7265616479207365727669604482015271373390309031bab93932b731bc903830b4b960711b60648201526084016102a5565b6000848484846104748a610941565b604051602001610488959493929190610dcc565b60408051601f1981840301815291815281516020808401919091206001600160e01b03198116600090815260019092529190208054600282018054949550929391926001600160a01b03909116916104df90610e2b565b15159050610543576104f5600283018989610a47565b50610504600383018787610a47565b5060018083018a90556003805491820181556000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0183905561056c565b6001600160a01b0381161561056c576001600160a01b0381166000908152600260205260408120555b806001600160a01b03168a6001600160a01b0316146105a1576001600160a01b038a1660009081526002602052604090208390555b81546001600160a01b0319166001600160a01b038b16908117835560405190815283907f2a1586394a17f79a4cc822c7b077653442e5a6fd7c78be98349291aa67a50c219060200160405180910390a250505050505050505050565b6001600160e01b0319166000908152600160205260409020546001600160a01b031690565b6001600160e01b031981166000908152600160205260408120600281018054606093919061064f90610e2b565b905011801561066e5750600081600301805461066a90610e2b565b9050115b156106ac5780600201816003016106888360010154610941565b60405160200161069a93929190610efa565b60405160208183030381529060405291505b50919050565b6001600160a01b039081166000818152600260209081526040808320546001600160e01b031916835260019091529020549091161490565b60606106f5826106b2565b6107415760405162461bcd60e51b815260206004820152601a60248201527f5769746e65745072696365526f757465723a20756e6b6e6f776e00000000000060448201526064016102a5565b6001600160a01b03821660009081526002602052604090205461076390610622565b92915050565b6000546001600160a01b031633146107935760405162461bcd60e51b81526004016102a590610d75565b6001600160a01b0381166107f85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102a5565b610801816108f1565b50565b600080600080610813856105fd565b90506001600160a01b0381166108805760405162461bcd60e51b815260206004820152602c60248201527f5769746e65745072696365526f757465723a20756e737570706f72746564206360448201526b3ab93932b731bc903830b4b960a11b60648201526084016102a5565b806001600160a01b031663431838346040518163ffffffff1660e01b8152600401608060405180830381865afa1580156108be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e29190610f52565b92989197509195509350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816109655750506040805180820190915260018152600360fc1b602082015290565b8160005b811561098f578061097981610f9e565b91506109889050600a83610fcf565b9150610969565b60008167ffffffffffffffff8111156109aa576109aa610c0e565b6040519080825280601f01601f1916602001820160405280156109d4576020820181803683370190505b5090505b8415610a3f576109e9600183610fe3565b91506109f6600a86610ffa565b610a0190603061100e565b60f81b818381518110610a1657610a16611026565b60200101906001600160f81b031916908160001a905350610a38600a86610fcf565b94506109d8565b949350505050565b828054610a5390610e2b565b90600052602060002090601f016020900481019282610a755760008555610abb565b82601f10610a8e5782800160ff19823516178555610abb565b82800160010185558215610abb579182015b82811115610abb578235825591602001919060010190610aa0565b50610ac7929150610acb565b5090565b5b80821115610ac75760008155600101610acc565b6020808252825182820181905260009190848201906040850190845b81811015610b1857835183529284019291840191600101610afc565b50909695505050505050565b6001600160a01b038116811461080157600080fd5b60008083601f840112610b4b57600080fd5b50813567ffffffffffffffff811115610b6357600080fd5b602083019150836020828501011115610b7b57600080fd5b9250929050565b60008060008060008060808789031215610b9b57600080fd5b8635610ba681610b24565b955060208701359450604087013567ffffffffffffffff80821115610bca57600080fd5b610bd68a838b01610b39565b90965094506060890135915080821115610bef57600080fd5b50610bfc89828a01610b39565b979a9699509497509295939492505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610c3657600080fd5b813567ffffffffffffffff80821115610c4e57600080fd5b818401915084601f830112610c6257600080fd5b813581811115610c7457610c74610c0e565b604051601f8201601f19908116603f01168101908382118183101715610c9c57610c9c610c0e565b81604052828152876020848701011115610cb557600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610ce757600080fd5b5035919050565b60005b83811015610d09578181015183820152602001610cf1565b83811115610d18576000848401525b50505050565b6020815260008251806020840152610d3d816040850160208701610cee565b601f01601f19169190910160400192915050565b600060208284031215610d6357600080fd5b8135610d6e81610b24565b9392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215610dbc57600080fd5b81518015158114610d6e57600080fd5b6550726963652d60d01b81528486600683013760008582016006810160008152602f60f81b81525084866007830137602d60f81b6007918601918201528351610e1c816008840160208801610cee565b01600801979650505050505050565b600181811c90821680610e3f57607f821691505b602082108114156106ac57634e487b7160e01b600052602260045260246000fd5b8054600090600181811c9080831680610e7a57607f831692505b6020808410821415610e9c57634e487b7160e01b600052602260045260246000fd5b818015610eb05760018114610ec157610eee565b60ff19861689528489019650610eee565b60008881526020902060005b86811015610ee65781548b820152908501908301610ecd565b505084890196505b50505050505092915050565b6550726963652d60d01b81526000610f156006830186610e60565b602f60f81b8152610f296001820186610e60565b9050602d60f81b81528351610f45816001840160208801610cee565b0160010195945050505050565b60008060008060808587031215610f6857600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610fb257610fb2610f88565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610fde57610fde610fb9565b500490565b600082821015610ff557610ff5610f88565b500390565b60008261100957611009610fb9565b500690565b6000821982111561102157611021610f88565b500190565b634e487b7160e01b600052603260045260246000fdfea26469706673582212202a23dbd73d817d4184ff4e8eb625863fe1105d0de5340cedccfd4ef8794805d264736f6c634300080b0033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806399d32a041161007157806399d32a0414610157578063a027ad1514610177578063bbfa81181461019a578063ca64c540146101ad578063f2fde38b146101e2578063f78eea83146101f557600080fd5b80633fd29ebd146100b9578063715018a6146100d757806377021267146100e1578063835262f5146100f45780638c0adf621461011b5780638da5cb5b14610146575b600080fd5b6100c1610223565b6040516100ce9190610ae0565b60405180910390f35b6100df61027b565b005b6100df6100ef366004610b82565b6102ba565b61010d610102366004610c24565b805160209091012090565b6040519081526020016100ce565b61012e610129366004610cd5565b6105fd565b6040516001600160a01b0390911681526020016100ce565b6000546001600160a01b031661012e565b61016a610165366004610cd5565b610622565b6040516100ce9190610d1e565b61018a610185366004610d51565b6106b2565b60405190151581526020016100ce565b61016a6101a8366004610d51565b6106ea565b61018a6101bb366004610cd5565b6001600160e01b0319166000908152600160205260409020546001600160a01b0316151590565b6100df6101f0366004610d51565b610769565b610208610203366004610cd5565b610804565b604080519384526020840192909252908201526060016100ce565b6060600380548060200260200160405190810160405280929190818152602001828054801561027157602002820191906000526020600020905b81548152602001906001019080831161025d575b5050505050905090565b6000546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a590610d75565b60405180910390fd5b6102b860006108f1565b565b6000546001600160a01b031633146102e45760405162461bcd60e51b81526004016102a590610d75565b6001600160a01b03861615610465576040516301ffc9a760e01b8152632089297160e11b60048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610daa565b6103e45760405162461bcd60e51b815260206004820152604760248201527f5769746e65745072696365526f757465723a206665656420636f6e747261637460448201527f206973206e6f7420636f6d706c69616e74207769746820495769746e657450726064820152661a58d95199595960ca1b608482015260a4016102a5565b6001600160a01b038616600090815260026020526040902054156104655760405162461bcd60e51b815260206004820152603260248201527f5769746e65745072696365526f757465723a20616c7265616479207365727669604482015271373390309031bab93932b731bc903830b4b960711b60648201526084016102a5565b6000848484846104748a610941565b604051602001610488959493929190610dcc565b60408051601f1981840301815291815281516020808401919091206001600160e01b03198116600090815260019092529190208054600282018054949550929391926001600160a01b03909116916104df90610e2b565b15159050610543576104f5600283018989610a47565b50610504600383018787610a47565b5060018083018a90556003805491820181556000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0183905561056c565b6001600160a01b0381161561056c576001600160a01b0381166000908152600260205260408120555b806001600160a01b03168a6001600160a01b0316146105a1576001600160a01b038a1660009081526002602052604090208390555b81546001600160a01b0319166001600160a01b038b16908117835560405190815283907f2a1586394a17f79a4cc822c7b077653442e5a6fd7c78be98349291aa67a50c219060200160405180910390a250505050505050505050565b6001600160e01b0319166000908152600160205260409020546001600160a01b031690565b6001600160e01b031981166000908152600160205260408120600281018054606093919061064f90610e2b565b905011801561066e5750600081600301805461066a90610e2b565b9050115b156106ac5780600201816003016106888360010154610941565b60405160200161069a93929190610efa565b60405160208183030381529060405291505b50919050565b6001600160a01b039081166000818152600260209081526040808320546001600160e01b031916835260019091529020549091161490565b60606106f5826106b2565b6107415760405162461bcd60e51b815260206004820152601a60248201527f5769746e65745072696365526f757465723a20756e6b6e6f776e00000000000060448201526064016102a5565b6001600160a01b03821660009081526002602052604090205461076390610622565b92915050565b6000546001600160a01b031633146107935760405162461bcd60e51b81526004016102a590610d75565b6001600160a01b0381166107f85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102a5565b610801816108f1565b50565b600080600080610813856105fd565b90506001600160a01b0381166108805760405162461bcd60e51b815260206004820152602c60248201527f5769746e65745072696365526f757465723a20756e737570706f72746564206360448201526b3ab93932b731bc903830b4b960a11b60648201526084016102a5565b806001600160a01b031663431838346040518163ffffffff1660e01b8152600401608060405180830381865afa1580156108be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e29190610f52565b92989197509195509350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816109655750506040805180820190915260018152600360fc1b602082015290565b8160005b811561098f578061097981610f9e565b91506109889050600a83610fcf565b9150610969565b60008167ffffffffffffffff8111156109aa576109aa610c0e565b6040519080825280601f01601f1916602001820160405280156109d4576020820181803683370190505b5090505b8415610a3f576109e9600183610fe3565b91506109f6600a86610ffa565b610a0190603061100e565b60f81b818381518110610a1657610a16611026565b60200101906001600160f81b031916908160001a905350610a38600a86610fcf565b94506109d8565b949350505050565b828054610a5390610e2b565b90600052602060002090601f016020900481019282610a755760008555610abb565b82601f10610a8e5782800160ff19823516178555610abb565b82800160010185558215610abb579182015b82811115610abb578235825591602001919060010190610aa0565b50610ac7929150610acb565b5090565b5b80821115610ac75760008155600101610acc565b6020808252825182820181905260009190848201906040850190845b81811015610b1857835183529284019291840191600101610afc565b50909695505050505050565b6001600160a01b038116811461080157600080fd5b60008083601f840112610b4b57600080fd5b50813567ffffffffffffffff811115610b6357600080fd5b602083019150836020828501011115610b7b57600080fd5b9250929050565b60008060008060008060808789031215610b9b57600080fd5b8635610ba681610b24565b955060208701359450604087013567ffffffffffffffff80821115610bca57600080fd5b610bd68a838b01610b39565b90965094506060890135915080821115610bef57600080fd5b50610bfc89828a01610b39565b979a9699509497509295939492505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610c3657600080fd5b813567ffffffffffffffff80821115610c4e57600080fd5b818401915084601f830112610c6257600080fd5b813581811115610c7457610c74610c0e565b604051601f8201601f19908116603f01168101908382118183101715610c9c57610c9c610c0e565b81604052828152876020848701011115610cb557600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610ce757600080fd5b5035919050565b60005b83811015610d09578181015183820152602001610cf1565b83811115610d18576000848401525b50505050565b6020815260008251806020840152610d3d816040850160208701610cee565b601f01601f19169190910160400192915050565b600060208284031215610d6357600080fd5b8135610d6e81610b24565b9392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060208284031215610dbc57600080fd5b81518015158114610d6e57600080fd5b6550726963652d60d01b81528486600683013760008582016006810160008152602f60f81b81525084866007830137602d60f81b6007918601918201528351610e1c816008840160208801610cee565b01600801979650505050505050565b600181811c90821680610e3f57607f821691505b602082108114156106ac57634e487b7160e01b600052602260045260246000fd5b8054600090600181811c9080831680610e7a57607f831692505b6020808410821415610e9c57634e487b7160e01b600052602260045260246000fd5b818015610eb05760018114610ec157610eee565b60ff19861689528489019650610eee565b60008881526020902060005b86811015610ee65781548b820152908501908301610ecd565b505084890196505b50505050505092915050565b6550726963652d60d01b81526000610f156006830186610e60565b602f60f81b8152610f296001820186610e60565b9050602d60f81b81528351610f45816001840160208801610cee565b0160010195945050505050565b60008060008060808587031215610f6857600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610fb257610fb2610f88565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610fde57610fde610fb9565b500490565b600082821015610ff557610ff5610f88565b500390565b60008261100957611009610fb9565b500690565b6000821982111561102157611021610f88565b500190565b634e487b7160e01b600052603260045260246000fdfea26469706673582212202a23dbd73d817d4184ff4e8eb625863fe1105d0de5340cedccfd4ef8794805d264736f6c634300080b0033