Contract Address Details

0xD7f7933992c25A504e9Ddf7e76a3c1D6c432b25D

Contract Name
WitnetPriceRouter
Creator
0x102cb4–8586da at 0xc13b00–504f76
Balance
0 Doge
Tokens
Fetching tokens...
Transactions
5 Transactions
Transfers
0 Transfers
Gas Used
348,162
Last Balance Update
26739940
Contract name:
WitnetPriceRouter




Optimization enabled
true
Compiler version
v0.8.13+commit.abaa5c0e




Optimization runs
200
EVM Version
default




Verified at
2022-11-07T13:29:41.760941Z

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: @openzeppelin\contracts\utils\introspection\IERC165.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/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\IERC165.sol

// 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.1 (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 (last updated v4.7.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 Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        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 (last updated v4.7.0) (utils/Strings.sol)


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

    /**
     * @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);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}
// 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

0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6110278061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806399d32a041161007157806399d32a0414610157578063a027ad1514610177578063bbfa81181461019a578063ca64c540146101ad578063f2fde38b146101e2578063f78eea83146101f557600080fd5b80633fd29ebd146100b9578063715018a6146100d757806377021267146100e1578063835262f5146100f45780638c0adf621461011b5780638da5cb5b14610146575b600080fd5b6100c1610223565b6040516100ce9190610ad4565b60405180910390f35b6100df61027b565b005b6100df6100ef366004610b76565b61028f565b61010d610102366004610c18565b805160209091012090565b6040519081526020016100ce565b61012e610129366004610cc9565b6105b6565b6040516001600160a01b0390911681526020016100ce565b6000546001600160a01b031661012e565b61016a610165366004610cc9565b6105db565b6040516100ce9190610d12565b61018a610185366004610d45565b61066b565b60405190151581526020016100ce565b61016a6101a8366004610d45565b6106a3565b61018a6101bb366004610cc9565b6001600160e01b0319166000908152600160205260409020546001600160a01b0316151590565b6100df6101f0366004610d45565b610722565b610208610203366004610cc9565b61079b565b604080519384526020840192909252908201526060016100ce565b6060600380548060200260200160405190810160405280929190818152602001828054801561027157602002820191906000526020600020905b81548152602001906001019080831161025d575b5050505050905090565b610283610888565b61028d60006108e2565b565b610297610888565b6001600160a01b0386161561041d576040516301ffc9a760e01b8152632089297160e11b60048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa1580156102f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103159190610d69565b61039c5760405162461bcd60e51b815260206004820152604760248201527f5769746e65745072696365526f757465723a206665656420636f6e747261637460448201527f206973206e6f7420636f6d706c69616e74207769746820495769746e657450726064820152661a58d95199595960ca1b608482015260a4015b60405180910390fd5b6001600160a01b0386166000908152600260205260409020541561041d5760405162461bcd60e51b815260206004820152603260248201527f5769746e65745072696365526f757465723a20616c7265616479207365727669604482015271373390309031bab93932b731bc903830b4b960711b6064820152608401610393565b60008484848461042c8a610932565b604051602001610440959493929190610d8b565b60408051601f1981840301815291815281516020808401919091206001600160e01b03198116600090815260019092529190208054600282018054949550929391926001600160a01b039091169161049790610de4565b90506000036104fc576104ae600283018989610a3b565b506104bd600383018787610a3b565b5060018083018a90556003805491820181556000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01839055610525565b6001600160a01b03811615610525576001600160a01b0381166000908152600260205260408120555b806001600160a01b03168a6001600160a01b03161461055a576001600160a01b038a1660009081526002602052604090208390555b81546001600160a01b0319166001600160a01b038b16908117835560405190815283907f2a1586394a17f79a4cc822c7b077653442e5a6fd7c78be98349291aa67a50c219060200160405180910390a250505050505050505050565b6001600160e01b0319166000908152600160205260409020546001600160a01b031690565b6001600160e01b031981166000908152600160205260408120600281018054606093919061060890610de4565b90501180156106275750600081600301805461062390610de4565b9050115b156106655780600201816003016106418360010154610932565b60405160200161065393929190610eb1565b60405160208183030381529060405291505b50919050565b6001600160a01b039081166000818152600260209081526040808320546001600160e01b031916835260019091529020549091161490565b60606106ae8261066b565b6106fa5760405162461bcd60e51b815260206004820152601a60248201527f5769746e65745072696365526f757465723a20756e6b6e6f776e0000000000006044820152606401610393565b6001600160a01b03821660009081526002602052604090205461071c906105db565b92915050565b61072a610888565b6001600160a01b03811661078f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610393565b610798816108e2565b50565b6000806000806107aa856105b6565b90506001600160a01b0381166108175760405162461bcd60e51b815260206004820152602c60248201527f5769746e65745072696365526f757465723a20756e737570706f72746564206360448201526b3ab93932b731bc903830b4b960a11b6064820152608401610393565b806001600160a01b031663431838346040518163ffffffff1660e01b8152600401608060405180830381865afa158015610855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108799190610f09565b92989197509195509350505050565b6000546001600160a01b0316331461028d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610393565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816000036109595750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610983578061096d81610f55565b915061097c9050600a83610f84565b915061095d565b60008167ffffffffffffffff81111561099e5761099e610c02565b6040519080825280601f01601f1916602001820160405280156109c8576020820181803683370190505b5090505b8415610a33576109dd600183610f98565b91506109ea600a86610faf565b6109f5906030610fc3565b60f81b818381518110610a0a57610a0a610fdb565b60200101906001600160f81b031916908160001a905350610a2c600a86610f84565b94506109cc565b949350505050565b828054610a4790610de4565b90600052602060002090601f016020900481019282610a695760008555610aaf565b82601f10610a825782800160ff19823516178555610aaf565b82800160010185558215610aaf579182015b82811115610aaf578235825591602001919060010190610a94565b50610abb929150610abf565b5090565b5b80821115610abb5760008155600101610ac0565b6020808252825182820181905260009190848201906040850190845b81811015610b0c57835183529284019291840191600101610af0565b50909695505050505050565b6001600160a01b038116811461079857600080fd5b60008083601f840112610b3f57600080fd5b50813567ffffffffffffffff811115610b5757600080fd5b602083019150836020828501011115610b6f57600080fd5b9250929050565b60008060008060008060808789031215610b8f57600080fd5b8635610b9a81610b18565b955060208701359450604087013567ffffffffffffffff80821115610bbe57600080fd5b610bca8a838b01610b2d565b90965094506060890135915080821115610be357600080fd5b50610bf089828a01610b2d565b979a9699509497509295939492505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610c2a57600080fd5b813567ffffffffffffffff80821115610c4257600080fd5b818401915084601f830112610c5657600080fd5b813581811115610c6857610c68610c02565b604051601f8201601f19908116603f01168101908382118183101715610c9057610c90610c02565b81604052828152876020848701011115610ca957600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610cdb57600080fd5b5035919050565b60005b83811015610cfd578181015183820152602001610ce5565b83811115610d0c576000848401525b50505050565b6020815260008251806020840152610d31816040850160208701610ce2565b601f01601f19169190910160400192915050565b600060208284031215610d5757600080fd5b8135610d6281610b18565b9392505050565b600060208284031215610d7b57600080fd5b81518015158114610d6257600080fd5b6550726963652d60d01b8152848660068301376000858201602f60f81b600682015284866007830137602d60f81b6007918601918201528351610dd5816008840160208801610ce2565b01600801979650505050505050565b600181811c90821680610df857607f821691505b60208210810361066557634e487b7160e01b600052602260045260246000fd5b8054600090600181811c9080831680610e3257607f831692505b60208084108203610e5357634e487b7160e01b600052602260045260246000fd5b818015610e675760018114610e7857610ea5565b60ff19861689528489019650610ea5565b60008881526020902060005b86811015610e9d5781548b820152908501908301610e84565b505084890196505b50505050505092915050565b6550726963652d60d01b81526000610ecc6006830186610e18565b602f60f81b8152610ee06001820186610e18565b9050602d60f81b81528351610efc816001840160208801610ce2565b0160010195945050505050565b60008060008060808587031215610f1f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052601160045260246000fd5b600060018201610f6757610f67610f3f565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610f9357610f93610f6e565b500490565b600082821015610faa57610faa610f3f565b500390565b600082610fbe57610fbe610f6e565b500690565b60008219821115610fd657610fd6610f3f565b500190565b634e487b7160e01b600052603260045260246000fdfea264697066735822122074439116591690445fccbbee3924f071786fbcaaa052f7bd7f2dc482ab39908664736f6c634300080d0033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806399d32a041161007157806399d32a0414610157578063a027ad1514610177578063bbfa81181461019a578063ca64c540146101ad578063f2fde38b146101e2578063f78eea83146101f557600080fd5b80633fd29ebd146100b9578063715018a6146100d757806377021267146100e1578063835262f5146100f45780638c0adf621461011b5780638da5cb5b14610146575b600080fd5b6100c1610223565b6040516100ce9190610ad4565b60405180910390f35b6100df61027b565b005b6100df6100ef366004610b76565b61028f565b61010d610102366004610c18565b805160209091012090565b6040519081526020016100ce565b61012e610129366004610cc9565b6105b6565b6040516001600160a01b0390911681526020016100ce565b6000546001600160a01b031661012e565b61016a610165366004610cc9565b6105db565b6040516100ce9190610d12565b61018a610185366004610d45565b61066b565b60405190151581526020016100ce565b61016a6101a8366004610d45565b6106a3565b61018a6101bb366004610cc9565b6001600160e01b0319166000908152600160205260409020546001600160a01b0316151590565b6100df6101f0366004610d45565b610722565b610208610203366004610cc9565b61079b565b604080519384526020840192909252908201526060016100ce565b6060600380548060200260200160405190810160405280929190818152602001828054801561027157602002820191906000526020600020905b81548152602001906001019080831161025d575b5050505050905090565b610283610888565b61028d60006108e2565b565b610297610888565b6001600160a01b0386161561041d576040516301ffc9a760e01b8152632089297160e11b60048201526001600160a01b038716906301ffc9a790602401602060405180830381865afa1580156102f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103159190610d69565b61039c5760405162461bcd60e51b815260206004820152604760248201527f5769746e65745072696365526f757465723a206665656420636f6e747261637460448201527f206973206e6f7420636f6d706c69616e74207769746820495769746e657450726064820152661a58d95199595960ca1b608482015260a4015b60405180910390fd5b6001600160a01b0386166000908152600260205260409020541561041d5760405162461bcd60e51b815260206004820152603260248201527f5769746e65745072696365526f757465723a20616c7265616479207365727669604482015271373390309031bab93932b731bc903830b4b960711b6064820152608401610393565b60008484848461042c8a610932565b604051602001610440959493929190610d8b565b60408051601f1981840301815291815281516020808401919091206001600160e01b03198116600090815260019092529190208054600282018054949550929391926001600160a01b039091169161049790610de4565b90506000036104fc576104ae600283018989610a3b565b506104bd600383018787610a3b565b5060018083018a90556003805491820181556000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01839055610525565b6001600160a01b03811615610525576001600160a01b0381166000908152600260205260408120555b806001600160a01b03168a6001600160a01b03161461055a576001600160a01b038a1660009081526002602052604090208390555b81546001600160a01b0319166001600160a01b038b16908117835560405190815283907f2a1586394a17f79a4cc822c7b077653442e5a6fd7c78be98349291aa67a50c219060200160405180910390a250505050505050505050565b6001600160e01b0319166000908152600160205260409020546001600160a01b031690565b6001600160e01b031981166000908152600160205260408120600281018054606093919061060890610de4565b90501180156106275750600081600301805461062390610de4565b9050115b156106655780600201816003016106418360010154610932565b60405160200161065393929190610eb1565b60405160208183030381529060405291505b50919050565b6001600160a01b039081166000818152600260209081526040808320546001600160e01b031916835260019091529020549091161490565b60606106ae8261066b565b6106fa5760405162461bcd60e51b815260206004820152601a60248201527f5769746e65745072696365526f757465723a20756e6b6e6f776e0000000000006044820152606401610393565b6001600160a01b03821660009081526002602052604090205461071c906105db565b92915050565b61072a610888565b6001600160a01b03811661078f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610393565b610798816108e2565b50565b6000806000806107aa856105b6565b90506001600160a01b0381166108175760405162461bcd60e51b815260206004820152602c60248201527f5769746e65745072696365526f757465723a20756e737570706f72746564206360448201526b3ab93932b731bc903830b4b960a11b6064820152608401610393565b806001600160a01b031663431838346040518163ffffffff1660e01b8152600401608060405180830381865afa158015610855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108799190610f09565b92989197509195509350505050565b6000546001600160a01b0316331461028d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610393565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816000036109595750506040805180820190915260018152600360fc1b602082015290565b8160005b8115610983578061096d81610f55565b915061097c9050600a83610f84565b915061095d565b60008167ffffffffffffffff81111561099e5761099e610c02565b6040519080825280601f01601f1916602001820160405280156109c8576020820181803683370190505b5090505b8415610a33576109dd600183610f98565b91506109ea600a86610faf565b6109f5906030610fc3565b60f81b818381518110610a0a57610a0a610fdb565b60200101906001600160f81b031916908160001a905350610a2c600a86610f84565b94506109cc565b949350505050565b828054610a4790610de4565b90600052602060002090601f016020900481019282610a695760008555610aaf565b82601f10610a825782800160ff19823516178555610aaf565b82800160010185558215610aaf579182015b82811115610aaf578235825591602001919060010190610a94565b50610abb929150610abf565b5090565b5b80821115610abb5760008155600101610ac0565b6020808252825182820181905260009190848201906040850190845b81811015610b0c57835183529284019291840191600101610af0565b50909695505050505050565b6001600160a01b038116811461079857600080fd5b60008083601f840112610b3f57600080fd5b50813567ffffffffffffffff811115610b5757600080fd5b602083019150836020828501011115610b6f57600080fd5b9250929050565b60008060008060008060808789031215610b8f57600080fd5b8635610b9a81610b18565b955060208701359450604087013567ffffffffffffffff80821115610bbe57600080fd5b610bca8a838b01610b2d565b90965094506060890135915080821115610be357600080fd5b50610bf089828a01610b2d565b979a9699509497509295939492505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610c2a57600080fd5b813567ffffffffffffffff80821115610c4257600080fd5b818401915084601f830112610c5657600080fd5b813581811115610c6857610c68610c02565b604051601f8201601f19908116603f01168101908382118183101715610c9057610c90610c02565b81604052828152876020848701011115610ca957600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610cdb57600080fd5b5035919050565b60005b83811015610cfd578181015183820152602001610ce5565b83811115610d0c576000848401525b50505050565b6020815260008251806020840152610d31816040850160208701610ce2565b601f01601f19169190910160400192915050565b600060208284031215610d5757600080fd5b8135610d6281610b18565b9392505050565b600060208284031215610d7b57600080fd5b81518015158114610d6257600080fd5b6550726963652d60d01b8152848660068301376000858201602f60f81b600682015284866007830137602d60f81b6007918601918201528351610dd5816008840160208801610ce2565b01600801979650505050505050565b600181811c90821680610df857607f821691505b60208210810361066557634e487b7160e01b600052602260045260246000fd5b8054600090600181811c9080831680610e3257607f831692505b60208084108203610e5357634e487b7160e01b600052602260045260246000fd5b818015610e675760018114610e7857610ea5565b60ff19861689528489019650610ea5565b60008881526020902060005b86811015610e9d5781548b820152908501908301610e84565b505084890196505b50505050505092915050565b6550726963652d60d01b81526000610ecc6006830186610e18565b602f60f81b8152610ee06001820186610e18565b9050602d60f81b81528351610efc816001840160208801610ce2565b0160010195945050505050565b60008060008060808587031215610f1f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b600052601160045260246000fd5b600060018201610f6757610f67610f3f565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610f9357610f93610f6e565b500490565b600082821015610faa57610faa610f3f565b500390565b600082610fbe57610fbe610f6e565b500690565b60008219821115610fd657610fd6610f3f565b500190565b634e487b7160e01b600052603260045260246000fdfea264697066735822122074439116591690445fccbbee3924f071786fbcaaa052f7bd7f2dc482ab39908664736f6c634300080d0033