Contract 0x890c67d593f1ac30fa93606543cd93d1704cb1e6

Contract Overview

Balance:
0 BTT
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xae2e9dc2bdc8bdf43d92236b4d24a6b64bbaff3cf72b9865ba95dbf33b04445b0x6080604081134732022-06-09 8:44:01176 days 8 hrs ago0x9957887a260c7db1d4cb1fa67c0ce43d9b1d72c5 IN  Create: ForTubeOracle0 BTT546.0237
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x618375546e66ce7923dcc7d1481c9d26dcdc82b86359013916f8fee3838089f0152590092022-12-02 14:13:203 hrs 7 mins ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xa5844dc3336ed830f1316ad051efdc51789e363b6d3b718b5fff4332bc507616152545012022-12-02 11:38:205 hrs 42 mins ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x29162d1cd96eb9cdd37d2155b02b2ec9c6a21456e1eae59577798f659e1be940152387902022-12-02 2:38:1814 hrs 42 mins ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x114740962a8a198d3d8c68932f1fc5fbb5b0c6abfac3ff2cb051b447dae22572152248282022-12-01 18:38:1822 hrs 42 mins ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x50761d262b43cf726de03ec3b786604c7066e2fe96216867771fbdf002e91e1d152210462022-12-01 16:28:181 day 52 mins ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x12eb74f778a1c3dd155605e55bcc79349604d3d038a3df9df14596fba72a8066152193002022-12-01 15:28:181 day 1 hr ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x505c43d7f82fbeb9533ddf5b750ef691b9ab021807d7c528c23eefd48dc22fd3152133372022-12-01 12:03:201 day 5 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xa066a32923ad933c783ec2815a0143cf743020b58540875e03b460df4c6fa917152131912022-12-01 11:58:201 day 5 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x8cf03c96f204af2b00847e0fcee81e4f1066831156e6b5842506ff61c6b3c771152014092022-12-01 5:13:201 day 12 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x57d8d7f8f99d4cfa95fb9055e5f63a8a1bb328cb866b9045ec233295c9861bf4151919552022-11-30 23:48:201 day 17 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x971ff86b5161d6264dc8f1aebe0710f0e890f75a1e60492db4097c8958aa2528151886092022-11-30 21:53:201 day 19 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xb53fa6579c3322c05278f6210c22f47663d7f92c28b0cfb3ba06c398e4ec25e1151842462022-11-30 19:23:181 day 21 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xc57c1f64e73c764c4c1c6ef86d0c6687be4af050659c82b4fe5d481ea728afd2151838092022-11-30 19:08:201 day 22 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xa7f23f27eadb0325c41bee253de27981094bc8dfcac3ba4ae48300f1f5103f38151810462022-11-30 17:33:181 day 23 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x8f80274f2a17ff9e068bc0b092d4ccf75835d098a2a64d1b932ede927cfe2e7d151771182022-11-30 15:18:182 days 2 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x2f88136fe533f9f016c9e3f9abbb7c6e5e3d11196cb633d8c62c174de525970e151763902022-11-30 14:53:182 days 2 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x112908a614737b6f4a7d5664d2e5299cc69681be450f7b54a4eb4b34f01a4068151747902022-11-30 13:58:182 days 3 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x8bb3afe5e49eb2f491c1a46c7fc2c39203dce1391c12c9106aea3c0b742f784c151742092022-11-30 13:38:202 days 3 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xc6aeab1baa10de2fe0e7ab549de05ff663b4317998a58806d4e64644dc06c87e151715902022-11-30 12:08:182 days 5 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x0f0abbe26558f47eff0aa9e156a2ea1eb7c7c4efe70bbc5dfb9fe2f921073a38151521002022-11-30 0:58:182 days 16 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xbcd4668f3260042f093085efa60551386ed8082b08d3f78df7b3a3540f10ff2e151518092022-11-30 0:48:202 days 16 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x76f31952b002f6f3a276b4cdd00ee7a3742887260f3f00d54e9412634086cd08151326092022-11-29 13:48:203 days 3 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xddb2e69acf96c5d83fc919d2f1a4d855fccb7fc670cec0ea11d90f19e1e921c9151294092022-11-29 11:58:203 days 5 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0x57edc5807b816a0e6481a5da2a19181378f741aeb386bf108e06c8213c7a2c0e151292642022-11-29 11:53:183 days 5 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
0xb21e900e75f0382dd692139b3cdd4e7bb7ba44f43c074bff327c8b2f7e2efc25151238822022-11-29 8:48:183 days 8 hrs ago 0xf162e9650f38ee5491497eb4e4b2d7787431725a 0x890c67d593f1ac30fa93606543cd93d1704cb1e60 BTT
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ForTubeOracle

Compiler Version
v0.6.4+commit.1dca32f3

Optimization Enabled:
Yes with 200 runs

Other Settings:
petersburg EvmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at testnet.bttcscan.com on 2022-07-20
*/

pragma experimental ABIEncoderV2;
pragma solidity 0.6.4;


// SPDX-License-Identifier: MIT
library EthAddressLib {
    /**
     * @dev returns the address used within the protocol to identify ETH
     * @return the address assigned to ETH
     */
    function ethAddress() internal pure returns (address) {
        return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    }
}

// SPDX-License-Identifier: MIT
interface IOracleProxy {
    function get(address token) external view returns (uint256, bool);
}

// SPDX-License-Identifier: MIT
interface IPriceOracles {
    function get(address token) external view returns (uint256, bool);
}

// SPDX-License-Identifier: MIT
/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    function decimals() external view returns (uint8);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

// SPDX-License-Identifier: MIT
/**
 * @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 addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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-contracts/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) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. 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 mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a <= b ? a : b;
    }

    function abs(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a < b) {
            return b - a;
        }
        return a - b;
    }
}

// SPDX-License-Identifier: MIT
/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                "Address: low-level call with value failed"
            );
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            "Address: insufficient balance for call"
        );
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 weiValue,
        string memory errorMessage
    ) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{value: weiValue}(
            data
        );
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transfer.selector, to, value)
        );
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
        );
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, value)
        );
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(
            value
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(
            value,
            "SafeERC20: decreased allowance below zero"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(
            data,
            "SafeERC20: low-level call failed"
        );
        if (returndata.length > 0) {
            // Return data is optional
            // solhint-disable-next-line max-line-length
            require(
                abi.decode(returndata, (bool)),
                "SafeERC20: ERC20 operation did not succeed"
            );
        }
    }
}

library SignedSafeMath {
  int256 constant private _INT256_MIN = -2**255;

  /**
   * @dev Multiplies two signed integers, reverts on overflow.
   */
  function mul(int256 a, int256 b) internal pure returns (int256) {
    // 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-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

    int256 c = a * b;
    require(c / a == b, "SignedSafeMath: multiplication overflow");

    return c;
  }

  /**
   * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
   */
  function div(int256 a, int256 b) internal pure returns (int256) {
    require(b != 0, "SignedSafeMath: division by zero");
    require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

    int256 c = a / b;

    return c;
  }

  /**
   * @dev Subtracts two signed integers, reverts on overflow.
   */
  function sub(int256 a, int256 b) internal pure returns (int256) {
    int256 c = a - b;
    require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

    return c;
  }

  /**
   * @dev Adds two signed integers, reverts on overflow.
   */
  function add(int256 a, int256 b) internal pure returns (int256) {
    int256 c = a + b;
    require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

    return c;
  }

  /**
   * @notice Computes average of two signed integers, ensuring that the computation
   * doesn't overflow.
   * @dev If the result is not an integer, it is rounded towards zero. For example,
   * avg(-3, -4) = -3
   */
  function avg(int256 _a, int256 _b)
    internal
    pure
    returns (int256)
  {
    if ((_a < 0 && _b > 0) || (_a > 0 && _b < 0)) {
      return add(_a, _b) / 2;
    }
    int256 remainder = (_a % 2 + _b % 2) / 2;
    return add(add(_a / 2, _b / 2), remainder);
  }
}

library Median {
  using SignedSafeMath for int256;

  int256 constant INT_MAX = 2**255-1;

  /**
   * @notice Returns the sorted middle, or the average of the two middle indexed items if the
   * array has an even number of elements.
   * @dev The list passed as an argument isn't modified.
   * @dev This algorithm has expected runtime O(n), but for adversarially chosen inputs
   * the runtime is O(n^2).
   * @param list The list of elements to compare
   */
  function calculate(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    return calculateInplace(copy(list));
  }

  /**
   * @notice See documentation for function calculate.
   * @dev The list passed as an argument may be permuted.
   */
  function calculateInplace(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    require(0 < list.length, "list must not be empty");
    uint256 len = list.length;
    uint256 middleIndex = len / 2;
    if (len % 2 == 0) {
      int256 median1;
      int256 median2;
      (median1, median2) = quickselectTwo(list, 0, len - 1, middleIndex - 1, middleIndex);
      return SignedSafeMath.avg(median1, median2);
    } else {
      return quickselect(list, 0, len - 1, middleIndex);
    }
  }

  /**
   * @notice Maximum length of list that shortSelectTwo can handle
   */
  uint256 constant SHORTSELECTTWO_MAX_LENGTH = 7;

  /**
   * @notice Select the k1-th and k2-th element from list of length at most 7
   * @dev Uses an optimal sorting network
   */
  function shortSelectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    private
    pure
    returns (int256 k1th, int256 k2th)
  {
    // Uses an optimal sorting network (https://en.wikipedia.org/wiki/Sorting_network)
    // for lists of length 7. Network layout is taken from
    // http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=7&algorithm=hibbard&output=svg

    uint256 len = hi + 1 - lo;
    int256 x0 = list[lo + 0];
    int256 x1 = 1 < len ? list[lo + 1] : INT_MAX;
    int256 x2 = 2 < len ? list[lo + 2] : INT_MAX;
    int256 x3 = 3 < len ? list[lo + 3] : INT_MAX;
    int256 x4 = 4 < len ? list[lo + 4] : INT_MAX;
    int256 x5 = 5 < len ? list[lo + 5] : INT_MAX;
    int256 x6 = 6 < len ? list[lo + 6] : INT_MAX;

    if (x0 > x1) {(x0, x1) = (x1, x0);}
    if (x2 > x3) {(x2, x3) = (x3, x2);}
    if (x4 > x5) {(x4, x5) = (x5, x4);}
    if (x0 > x2) {(x0, x2) = (x2, x0);}
    if (x1 > x3) {(x1, x3) = (x3, x1);}
    if (x4 > x6) {(x4, x6) = (x6, x4);}
    if (x1 > x2) {(x1, x2) = (x2, x1);}
    if (x5 > x6) {(x5, x6) = (x6, x5);}
    if (x0 > x4) {(x0, x4) = (x4, x0);}
    if (x1 > x5) {(x1, x5) = (x5, x1);}
    if (x2 > x6) {(x2, x6) = (x6, x2);}
    if (x1 > x4) {(x1, x4) = (x4, x1);}
    if (x3 > x6) {(x3, x6) = (x6, x3);}
    if (x2 > x4) {(x2, x4) = (x4, x2);}
    if (x3 > x5) {(x3, x5) = (x5, x3);}
    if (x3 > x4) {(x3, x4) = (x4, x3);}

    uint256 index1 = k1 - lo;
    if (index1 == 0) {k1th = x0;}
    else if (index1 == 1) {k1th = x1;}
    else if (index1 == 2) {k1th = x2;}
    else if (index1 == 3) {k1th = x3;}
    else if (index1 == 4) {k1th = x4;}
    else if (index1 == 5) {k1th = x5;}
    else if (index1 == 6) {k1th = x6;}
    else {revert("k1 out of bounds");}

    uint256 index2 = k2 - lo;
    if (k1 == k2) {return (k1th, k1th);}
    else if (index2 == 0) {return (k1th, x0);}
    else if (index2 == 1) {return (k1th, x1);}
    else if (index2 == 2) {return (k1th, x2);}
    else if (index2 == 3) {return (k1th, x3);}
    else if (index2 == 4) {return (k1th, x4);}
    else if (index2 == 5) {return (k1th, x5);}
    else if (index2 == 6) {return (k1th, x6);}
    else {revert("k2 out of bounds");}
  }

  /**
   * @notice Selects the k-th ranked element from list, looking only at indices between lo and hi
   * (inclusive). Modifies list in-place.
   */
  function quickselect(int256[] memory list, uint256 lo, uint256 hi, uint256 k)
    private
    pure
    returns (int256 kth)
  {
    require(lo <= k);
    require(k <= hi);
    while (lo < hi) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        int256 ignore;
        (kth, ignore) = shortSelectTwo(list, lo, hi, k, k);
        return kth;
      }
      uint256 pivotIndex = partition(list, lo, hi);
      if (k <= pivotIndex) {
        // since pivotIndex < (original hi passed to partition),
        // termination is guaranteed in this case
        hi = pivotIndex;
      } else {
        // since (original lo passed to partition) <= pivotIndex,
        // termination is guaranteed in this case
        lo = pivotIndex + 1;
      }
    }
    return list[lo];
  }

  /**
   * @notice Selects the k1-th and k2-th ranked elements from list, looking only at indices between
   * lo and hi (inclusive). Modifies list in-place.
   */
  function quickselectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    internal // for testing
    pure
    returns (int256 k1th, int256 k2th)
  {
    require(k1 < k2);
    require(lo <= k1 && k1 <= hi);
    require(lo <= k2 && k2 <= hi);

    while (true) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        return shortSelectTwo(list, lo, hi, k1, k2);
      }
      uint256 pivotIdx = partition(list, lo, hi);
      if (k2 <= pivotIdx) {
        hi = pivotIdx;
      } else if (pivotIdx < k1) {
        lo = pivotIdx + 1;
      } else {
        assert(k1 <= pivotIdx && pivotIdx < k2);
        k1th = quickselect(list, lo, pivotIdx, k1);
        k2th = quickselect(list, pivotIdx + 1, hi, k2);
        return (k1th, k2th);
      }
    }
  }

  /**
   * @notice Partitions list in-place using Hoare's partitioning scheme.
   * Only elements of list between indices lo and hi (inclusive) will be modified.
   * Returns an index i, such that:
   * - lo <= i < hi
   * - forall j in [lo, i]. list[j] <= list[i]
   * - forall j in [i, hi]. list[i] <= list[j]
   */
  function partition(int256[] memory list, uint256 lo, uint256 hi)
    private
    pure
    returns (uint256)
  {
    // We don't care about overflow of the addition, because it would require a list
    // larger than any feasible computer's memory.
    int256 pivot = list[(lo + hi) / 2];
    lo -= 1; // this can underflow. that's intentional.
    hi += 1;
    while (true) {
      do {
        lo += 1;
      } while (list[lo] < pivot);
      do {
        hi -= 1;
      } while (list[hi] > pivot);
      if (lo < hi) {
        (list[lo], list[hi]) = (list[hi], list[lo]);
      } else {
        // Let orig_lo and orig_hi be the original values of lo and hi passed to partition.
        // Then, hi < orig_hi, because hi decreases *strictly* monotonically
        // in each loop iteration and
        // - either list[orig_hi] > pivot, in which case the first loop iteration
        //   will achieve hi < orig_hi;
        // - or list[orig_hi] <= pivot, in which case at least two loop iterations are
        //   needed:
        //   - lo will have to stop at least once in the interval
        //     [orig_lo, (orig_lo + orig_hi)/2]
        //   - (orig_lo + orig_hi)/2 < orig_hi
        return hi;
      }
    }
  }

  /**
   * @notice Makes an in-memory copy of the array passed in
   * @param list Reference to the array to be copied
   */
  function copy(int256[] memory list)
    private
    pure
    returns(int256[] memory)
  {
    int256[] memory list2 = new int256[](list.length);
    for (uint256 i = 0; i < list.length; i++) {
      list2[i] = list[i];
    }
    return list2;
  }
}

/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {

  /**
   * @dev Indicates that the contract has been initialized.
   */
  bool private initialized;

  /**
   * @dev Indicates that the contract is in the process of being initialized.
   */
  bool private initializing;

  /**
   * @dev Modifier to use in the initializer function of a contract.
   */
  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool isTopLevelCall = !initializing;
    if (isTopLevelCall) {
      initializing = true;
      initialized = true;
    }

    _;

    if (isTopLevelCall) {
      initializing = false;
    }
  }

  /// @dev Returns true if and only if the function is running in the constructor
  function isConstructor() private view returns (bool) {
    // extcodesize checks the size of the code stored in an address, and
    // address returns the current address. Since the code is still not
    // deployed when running a constructor, any checks on its code size will
    // yield zero, making it an effective way to detect if a contract is
    // under construction or not.
    address self = address(this);
    uint256 cs;
    assembly { cs := extcodesize(self) }
    return cs == 0;
  }

  // Reserved storage space to allow for layout changes in the future.
  uint256[50] private ______gap;
}

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint256(_at(set._inner, index)));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

/**
 *Submitted for verification at Etherscan.io on 2020-06-04
*/
contract ForTubeOracle is Initializable, IPriceOracles {
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.UintSet;

    event Enable(address feeder);
    event Disable(address feeder);

    event Enables(address[] feeder);
    event Disables(address[] feeder);

    event EnableToken(address token);
    event DisableToken(address token);

    event EnableTokens(address[] ts);
    event DisableTokens(address[] ts);

    event Set(address who, address token, uint val, uint exp);
    event BatchSet(address[] tokens, uint[] vals, uint exp);

    address public multiSig;
    address public admin;

    //所有喂价地址列表,每个节点一个喂价地址,下架节点时,需要删除下架节点的数据。
    EnumerableSet.AddressSet private _tokens;// 支持的币种列表

    // to save gas
    struct Price {
        uint192 price;
        uint64 expiration;
    }
    mapping (address => Price) public finalPrices;//最终结果

    //使用新的address作为Key
    EnumerableSet.AddressSet private _feeders;// 支持的喂价者列表
    mapping (address => mapping (address => Price)) public _prices;

    function initialize(address _multiSig, address[] memory _initFeeders)
        public
        initializer
    {
        multiSig = _multiSig;
        admin = msg.sender;

        require(_initFeeders.length >= 1, "invalid length");
        for (uint256 i = 0; i < _initFeeders.length; i++) {
            _feeders.add(_initFeeders[i]);
        }
    }

    // constructor(address _multiSig, address[] memory _initFeeders) public
    // {
    //     multiSig = _multiSig;
    //     admin = msg.sender;

    //     require(_initFeeders.length >= 1, "invalid length");
    //     for (uint256 i = 0; i < _initFeeders.length; i++) {
    //         _feeders.add(_initFeeders[i]);
    //     }
    // }

    // 每个节点都能访问该喂价合约,但只能喂价属于本节点的数据
    modifier auth {
        require(_feeders.contains(msg.sender), "unauthorized feeder");
        _;
    }

    modifier onlyMultiSig {
        require(msg.sender == multiSig, "require multiSig");
        _;
    }

    function setMultiSig(address _multiSig) external onlyMultiSig {
        multiSig = _multiSig;
    }

    modifier onlyAdmin {
        require(msg.sender == admin, "require admin");
        _;
    }

    function setAdmin(address _admin) external onlyMultiSig {
        admin = _admin;
    }

    function enable(address feeder) public onlyMultiSig {
        require(!_feeders.contains(feeder), "duplicated feeder");
        _feeders.add(feeder);
        emit Enable(feeder);
    }

    function disable(address feeder) public onlyMultiSig {
        require(_feeders.contains(feeder), "not exist");
        _feeders.remove(feeder);

        for (uint i = 0; i < _tokens.length(); i++) {
            delete _prices[feeder][_tokens.at(i)];
        }
        emit Disable(feeder);
    }

    function enables(address[] calldata feeders) external onlyMultiSig {
        for (uint256 i = 0; i < feeders.length; i++) {
            enable(feeders[i]);
        }
        emit Enables(feeders);
    }

    function disables(address[] calldata feeders) external onlyMultiSig {
        for (uint256 i = 0; i < feeders.length; i++) {
            disable(feeders[i]);
        }
        emit Disables(feeders);
    }

    function enableToken(address token) public onlyAdmin {
        require(_tokens.add(token), "Duplicate token");
        emit EnableToken(token);
    }

    function disableToken(address token) public onlyAdmin {
        require(_tokens.remove(token), "nonexist token");
        //TODO: delete feeder's history price data
        emit DisableToken(token);
    }

    function enableTokens(address[] calldata tokens) external onlyAdmin {
        for (uint256 i = 0; i < tokens.length; i++) {
            enableToken(tokens[i]);
        }
        emit EnableTokens(tokens);
    }

    function disableTokens(address[] calldata tokens) external onlyAdmin {
        for (uint256 i = 0; i < tokens.length; i++) {
            disableToken(tokens[i]);
        }
        emit DisableTokens(tokens);
    }

    function tokens() public view returns (address[] memory) {
        address[] memory values = new address[](_tokens.length());
        for (uint256 i = 0; i < _tokens.length(); ++i) {
            values[i] = _tokens.at(i);
        }
        return values;
    }

    // 设置价格为 @val, 保持有效时间为 @exp second.
    function set(address token, uint val, uint exp) public auth {
        require(_feeders.contains(msg.sender), "unauth feeder");

        _prices[msg.sender][token].price = uint192(val);
        _prices[msg.sender][token].expiration = uint64(now + exp);

        int256[] memory priceList = new int256[](_feeders.length());
        uint256 j = 0;
        for (uint256 i = 0; i < _feeders.length(); i++) {
            address who = _feeders.at(i);
            if (_prices[who][token].price != 0 && now < _prices[who][token].expiration) {
                priceList[j++] = int256(_prices[who][token].price);
            }
        }

        int256[] memory priceFilter = new int256[](j);
        for (uint256 i = 0; i < j; i++) {
            priceFilter[i] = priceList[i];
        }

        finalPrices[token].price = uint192(Median.calculateInplace(priceFilter));
        finalPrices[token].expiration = uint64(now + exp);

        emit Set(msg.sender, token, val, exp);
    }

    //批量设置,减少gas使用
    function batchSet(address[] calldata tokens, uint[] calldata vals, uint exp) external auth {
        uint nToken = tokens.length;
        require(nToken == vals.length, "invalid array length");

        for (uint i = 0; i < nToken; ++i) {
            set(tokens[i], vals[i], exp);
        }

        emit BatchSet(tokens, vals, exp);
    }

    function getExpiration(address token) external view returns (uint) {
        return finalPrices[token].expiration;
    }

    function getPrice(address token) external view returns (uint) {
        return finalPrices[token].price;
    }

    function get(address token) external override view returns (uint, bool) {
        return (finalPrices[token].price, valid(token));
    }

    function valid(address token) public view returns (bool) {
        return now < finalPrices[token].expiration;
    }

    function getLastPriceByFeeder(address feeder, address token) public view returns (uint price, uint expiration) {
        return (_prices[feeder][token].price, _prices[feeder][token].expiration);
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"vals","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"exp","type":"uint256"}],"name":"BatchSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeder","type":"address"}],"name":"Disable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"DisableToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"ts","type":"address[]"}],"name":"DisableTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"feeder","type":"address[]"}],"name":"Disables","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeder","type":"address"}],"name":"Enable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"EnableToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"ts","type":"address[]"}],"name":"EnableTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"feeder","type":"address[]"}],"name":"Enables","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"val","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exp","type":"uint256"}],"name":"Set","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"_prices","outputs":[{"internalType":"uint192","name":"price","type":"uint192"},{"internalType":"uint64","name":"expiration","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"vals","type":"uint256[]"},{"internalType":"uint256","name":"exp","type":"uint256"}],"name":"batchSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeder","type":"address"}],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"disableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"disableTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"feeders","type":"address[]"}],"name":"disables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeder","type":"address"}],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"enableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"enableTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"feeders","type":"address[]"}],"name":"enables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"finalPrices","outputs":[{"internalType":"uint192","name":"price","type":"uint192"},{"internalType":"uint64","name":"expiration","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"get","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getExpiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"feeder","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getLastPriceByFeeder","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_multiSig","type":"address"},{"internalType":"address[]","name":"_initFeeders","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"multiSig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"val","type":"uint256"},{"internalType":"uint256","name":"exp","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_multiSig","type":"address"}],"name":"setMultiSig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"valid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50611ff2806100206000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c80638308d7e9116100c3578063ac8a260c1161007c578063ac8a260c146102cd578063c2bc2efc146102ed578063c690908a1461030e578063cfb4d57514610321578063e6c09edf14610334578063f851a440146103475761014d565b80638308d7e91461024b578063872e505b1461025e5780638acf9c9c146102715780638c2de1a514610292578063946d9204146102a55780639d63848a146102b85761014d565b80634ec70a48116101155780634ec70a48146101d957806353b9ed17146101ec5780635bfa1b68146101ff578063704b6c021461021257806371ca543b146102255780637f2aaf58146102385761014d565b8063032fc4671461015257806323e27a641461017c578063284d30ef1461019157806336e0004a146101a457806341976e09146101b9575b600080fd5b61016561016036600461192f565b61034f565b604051610173929190611f2e565b60405180910390f35b61018f61018a366004611914565b610387565b005b61018f61019f366004611914565b610421565b6101ac61046d565b6040516101739190611b40565b6101cc6101c7366004611914565b61047c565b6040516101739190611f50565b6101cc6101e7366004611914565b6104a4565b61018f6101fa366004611a49565b6104cf565b61018f61020d366004611914565b61056e565b61018f610220366004611914565b610607565b61018f610233366004611a49565b610653565b61018f610246366004611a49565b6106e6565b61018f610259366004611a16565b610779565b61016561026c366004611914565b610a60565b61028461027f36600461192f565b610a8d565b604051610173929190611f69565b61018f6102a0366004611a49565b610ad6565b61018f6102b3366004611963565b610b69565b6102c0610c76565b6040516101739190611be7565b6102e06102db366004611914565b610d06565b6040516101739190611c34565b6103006102fb366004611914565b610d33565b604051610173929190611f59565b61018f61031c366004611914565b610d74565b61018f61032f366004611a88565b610dfa565b61018f610342366004611914565b610ecf565b6101ac610fca565b603a6020908152600092835260408084209091529082529020546001600160c01b03811690600160c01b90046001600160401b031682565b6034546001600160a01b031633146103ba5760405162461bcd60e51b81526004016103b190611e8b565b60405180910390fd5b6103cb60358263ffffffff610fd916565b6103e75760405162461bcd60e51b81526004016103b190611d15565b7f3907c2f289c906800bbef774e6e4a476623eae8c1abc6cd0a78ef88aba9a6225816040516104169190611b40565b60405180910390a150565b6033546001600160a01b0316331461044b5760405162461bcd60e51b81526004016103b190611dbb565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b031681565b6001600160a01b0381166000908152603760205260409020546001600160c01b03165b919050565b6001600160a01b0316600090815260376020526040902054600160c01b90046001600160401b031690565b6034546001600160a01b031633146104f95760405162461bcd60e51b81526004016103b190611e8b565b60005b818110156105305761052883838381811061051357fe5b905060200201602081019061018a9190611914565b6001016104fc565b507f9c249de45402367091df502d43397a3a3743b76325528e7e600008e8b087eb008282604051610562929190611b7d565b60405180910390a15050565b6033546001600160a01b031633146105985760405162461bcd60e51b81526004016103b190611dbb565b6105a960388263ffffffff610ff716565b156105c65760405162461bcd60e51b81526004016103b190611d90565b6105d760388263ffffffff61100c16565b507fd4b303e8702428e1e0fe4a0c45cfd6f44c57f247681f0b21c46f339fa12ff1b3816040516104169190611b40565b6033546001600160a01b031633146106315760405162461bcd60e51b81526004016103b190611dbb565b603480546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b0316331461067d5760405162461bcd60e51b81526004016103b190611dbb565b60005b818110156106b4576106ac83838381811061069757fe5b90506020020160208101906103429190611914565b600101610680565b507f7956a3e15146e52d66b0611988fb8986c2720c014c959ea73785c4967b4fe2f78282604051610562929190611b7d565b6033546001600160a01b031633146107105760405162461bcd60e51b81526004016103b190611dbb565b60005b818110156107475761073f83838381811061072a57fe5b905060200201602081019061020d9190611914565b600101610713565b507f5de4e9bd993420104b24a7a67654883d63633818a80e63c4eda5385e610e0d948282604051610562929190611b7d565b61078a60383363ffffffff610ff716565b6107a65760405162461bcd60e51b81526004016103b190611ed9565b6107b760383363ffffffff610ff716565b6107d35760405162461bcd60e51b81526004016103b190611eb2565b336000908152603a602090815260408083206001600160a01b0387168452909152902080546001600160c01b0319166001600160c01b038481169190911716600160c01b4284016001600160401b03160217905560606108336038611021565b60405190808252806020026020018201604052801561085c578160200160208202803683370190505b5090506000805b61086d6038611021565b81101561095957600061088760388363ffffffff61102c16565b6001600160a01b038082166000908152603a60209081526040808320938c16835292905220549091506001600160c01b0316158015906108fb57506001600160a01b038181166000908152603a60209081526040808320938b1683529290522054600160c01b90046001600160401b031642105b15610950576001600160a01b038082166000908152603a60209081526040808320938b1683529290522054845160018501946001600160c01b03909216918691811061094357fe5b6020026020010181815250505b50600101610863565b50606081604051908082528060200260200182016040528015610986578160200160208202803683370190505b50905060005b828110156109c7578381815181106109a057fe5b60200260200101518282815181106109b457fe5b602090810291909101015260010161098c565b506109d181611038565b6001600160a01b0387166000908152603760205260409081902080546001600160c01b0319166001600160c01b0393841617909216600160c01b4288016001600160401b03160217909155517ffbb24065f2824e76e641debb0ecb0c301156418389e069d9dccd02c41005f08490610a50903390899089908990611b54565b60405180910390a1505050505050565b6037602052600090815260409020546001600160c01b03811690600160c01b90046001600160401b031682565b6001600160a01b038281166000908152603a60209081526040808320938516835292905220546001600160c01b03811690600160c01b90046001600160401b03165b9250929050565b6034546001600160a01b03163314610b005760405162461bcd60e51b81526004016103b190611e8b565b60005b81811015610b3757610b2f838383818110610b1a57fe5b905060200201602081019061031c9190611914565b600101610b03565b507f045343e77afb3d128b8b702cd80e26b88628649a99d2cddac4a196c4dbf082a48282604051610562929190611b7d565b600054610100900460ff1680610b825750610b826110b3565b80610b90575060005460ff16155b610bac5760405162461bcd60e51b81526004016103b190611de5565b600054610100900460ff16158015610bd7576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0385166001600160a01b0319918216179091556034805490911633179055815160011115610c225760405162461bcd60e51b81526004016103b190611f06565b60005b8251811015610c5e57610c55838281518110610c3d57fe5b6020026020010151603861100c90919063ffffffff16565b50600101610c25565b508015610c71576000805461ff00191690555b505050565b606080610c836035611021565b604051908082528060200260200182016040528015610cac578160200160208202803683370190505b50905060005b610cbc6035611021565b811015610d0057610cd460358263ffffffff61102c16565b828281518110610ce057fe5b6001600160a01b0390921660209283029190910190910152600101610cb2565b50905090565b6001600160a01b0316600090815260376020526040902054600160c01b90046001600160401b0316421090565b6001600160a01b03811660009081526037602052604081205481906001600160c01b0316610d6084610d06565b6001600160c01b0390911692509050915091565b6034546001600160a01b03163314610d9e5760405162461bcd60e51b81526004016103b190611e8b565b610daf60358263ffffffff61100c16565b610dcb5760405162461bcd60e51b81526004016103b190611c81565b7f1f4b6598cc34e310cc34bcfcb372afb5ba5af654fad97b26cc10ae8289f1c62f816040516104169190611b40565b610e0b60383363ffffffff610ff716565b610e275760405162461bcd60e51b81526004016103b190611ed9565b83828114610e475760405162461bcd60e51b81526004016103b190611e5d565b60005b81811015610e9757610e8f878783818110610e6157fe5b9050602002016020810190610e769190611914565b868684818110610e8257fe5b9050602002013585610779565b600101610e4a565b507f3d42dcf7dc9d942d0432de62f545e4f39cd82301f72f0a070a17b6ff2d05a68b8686868686604051610a50959493929190611b91565b6033546001600160a01b03163314610ef95760405162461bcd60e51b81526004016103b190611dbb565b610f0a60388263ffffffff610ff716565b610f265760405162461bcd60e51b81526004016103b190611d6d565b610f3760388263ffffffff610fd916565b5060005b610f456035611021565b811015610f9a576001600160a01b0382166000908152603a6020526040812090610f7660358463ffffffff61102c16565b6001600160a01b031681526020810191909152604001600090812055600101610f3b565b507f1d6f80aff2255e9cb1aee4abaf819aec89a6ae3fce7eb53b852640eb8052609c816040516104169190611b40565b6034546001600160a01b031681565b6000610fee836001600160a01b0384166110b9565b90505b92915050565b6000610fee836001600160a01b03841661117f565b6000610fee836001600160a01b038416611197565b6000610ff1826111e1565b6000610fee83836111e5565b6000815160001061105b5760405162461bcd60e51b81526004016103b190611d3d565b8151600281046001821661109a5760008061108086600060018703600187038761122a565b909250905061108f8282611308565b94505050505061049f565b6110aa846000600185038461137e565b9250505061049f565b303b1590565b6000818152600183016020526040812054801561117557835460001980830191908101906000908790839081106110ec57fe5b906000526020600020015490508087600001848154811061110957fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061113957fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610ff1565b6000915050610ff1565b60009081526001919091016020526040902054151590565b60006111a3838361117f565b6111d957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610ff1565b506000610ff1565b5490565b815460009082106112085760405162461bcd60e51b81526004016103b190611c3f565b82600001828154811061121757fe5b9060005260206000200154905092915050565b60008082841061123957600080fd5b8386111580156112495750848411155b61125257600080fd5b8286111580156112625750848311155b61126b57600080fd5b6007868603101561128c57611283878787878761140f565b915091506112fe565b6000611299888888611792565b90508084116112aa578095506112f8565b848110156112bd578060010196506112f8565b8085111580156112cc57508381105b6112d257fe5b6112de8888838861137e565b92506112ef8882600101888761137e565b91506112fe9050565b5061126b565b9550959350505050565b600080831280156113195750600082135b8061132f575060008313801561132f5750600082125b1561134f5760026113408484611876565b8161134757fe5b059050610ff1565b60006002808507818507010590506113766113706002860560028605611876565b82611876565b949350505050565b60008184111561138d57600080fd5b8282111561139a57600080fd5b828410156113f157600784840310156113c65760006113bc868686868761140f565b5091506113769050565b60006113d3868686611792565b90508083116113e4578093506113eb565b8060010194505b5061139a565b8484815181106113fd57fe5b60200260200101519050949350505050565b60008060008686600101039050600088886000018151811061142d57fe5b6020026020010151905060008260011061144e576001600160ff1b03611466565b89896001018151811061145d57fe5b60200260200101515b905060008360021061147f576001600160ff1b03611497565b8a8a6002018151811061148e57fe5b60200260200101515b90506000846003106114b0576001600160ff1b036114c8565b8b8b600301815181106114bf57fe5b60200260200101515b90506000856004106114e1576001600160ff1b036114f9565b8c8c600401815181106114f057fe5b60200260200101515b9050600086600510611512576001600160ff1b0361152a565b8d8d6005018151811061152157fe5b60200260200101515b9050600087600610611543576001600160ff1b0361155b565b8e8e6006018151811061155257fe5b60200260200101515b905085871315611569579495945b83851315611575579293925b81831315611581579091905b8487131561158d579395935b83861315611599579294925b808313156115a357915b848613156115af579394935b808213156115b957905b828713156115c5579195915b818613156115d1579094905b808513156115db57935b828613156115e7579194915b808413156115f157925b828513156115fd579193915b81841315611609579092905b82841315611615579192915b8d8c038061162557879a506116a3565b806001141561163657869a506116a3565b806002141561164757859a506116a3565b806003141561165857849a506116a3565b806004141561166957839a506116a3565b806005141561167a57829a506116a3565b806006141561168b57819a506116a3565b60405162461bcd60e51b81526004016103b190611caa565b8e8c038d8d14156116c157508a99506112fe98505050505050505050565b806116d857509698506112fe975050505050505050565b80600114156116f357509598506112fe975050505050505050565b806002141561170e57509498506112fe975050505050505050565b806003141561172957509398506112fe975050505050505050565b806004141561174457509298506112fe975050505050505050565b806005141561175f57509198506112fe975050505050505050565b806006141561177a57509098506112fe975050505050505050565b60405162461bcd60e51b81526004016103b190611e33565b60008084600285850104815181106117a657fe5b602002602001015190506001840393506001830192505b600184019350808585815181106117d057fe5b6020026020010151126117bd575b600183039250808584815181106117f157fe5b6020026020010151136117de57828410156118615784838151811061181257fe5b602002602001015185858151811061182657fe5b602002602001015186868151811061183a57fe5b6020026020010187868151811061184d57fe5b60209081029190910101919091525261186a565b8291505061186f565b6117bd565b9392505050565b600082820181831280159061188b5750838112155b806118a057506000831280156118a057508381125b610fee5760405162461bcd60e51b81526004016103b190611cd4565b80356001600160a01b0381168114610ff157600080fd5b60008083601f8401126118e4578182fd5b5081356001600160401b038111156118fa578182fd5b6020830191508360208083028501011115610acf57600080fd5b600060208284031215611925578081fd5b610fee83836118bc565b60008060408385031215611941578081fd5b61194b84846118bc565b915061195a84602085016118bc565b90509250929050565b60008060408385031215611975578182fd5b61197f84846118bc565b91506020808401356001600160401b0381111561199a578283fd5b80850186601f8201126119ab578384fd5b803591506119c06119bb83611f9d565b611f77565b82815283810190828501858502840186018a10156119dc578687fd5b8693505b84841015611a06576119f28a826118bc565b8352600193909301929185019185016119e0565b5080955050505050509250929050565b600080600060608486031215611a2a578081fd5b611a3485856118bc565b95602085013595506040909401359392505050565b60008060208385031215611a5b578182fd5b82356001600160401b03811115611a70578283fd5b611a7c858286016118d3565b90969095509350505050565b600080600080600060608688031215611a9f578081fd5b85356001600160401b0380821115611ab5578283fd5b611ac189838a016118d3565b90975095506020880135915080821115611ad9578283fd5b50611ae6888289016118d3565b96999598509660400135949350505050565b60008284526020808501945082825b85811015611b35578183016001600160a01b03611b2482856118bc565b168852968301969150600101611b07565b509495945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b600060208252611376602083018486611af8565b600060608252611ba5606083018789611af8565b82810360208401528481526001600160fb1b03851115611bc3578182fd5b60208502808760208401370160200190815260409190910191909152949350505050565b6020808252825182820181905260009190848201906040850190845b81811015611c285783516001600160a01b031683529284019291840191600101611c03565b50909695505050505050565b901515815260200190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252600f908201526e223ab83634b1b0ba32903a37b5b2b760891b604082015260600190565b60208082526010908201526f6b31206f7574206f6620626f756e647360801b604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600e908201526d3737b732bc34b9ba103a37b5b2b760911b604082015260600190565b6020808252601690820152756c697374206d757374206e6f7420626520656d70747960501b604082015260600190565b6020808252600990820152681b9bdd08195e1a5cdd60ba1b604082015260600190565b602080825260119082015270323ab83634b1b0ba32b2103332b2b232b960791b604082015260600190565b60208082526010908201526f72657175697265206d756c746953696760801b604082015260600190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526010908201526f6b32206f7574206f6620626f756e647360801b604082015260600190565b6020808252601490820152730d2dcecc2d8d2c840c2e4e4c2f240d8cadccee8d60631b604082015260600190565b6020808252600d908201526c3932b8bab4b9329030b236b4b760991b604082015260600190565b6020808252600d908201526c3ab730baba34103332b2b232b960991b604082015260600190565b6020808252601390820152723ab730baba3437b934bd32b2103332b2b232b960691b604082015260600190565b6020808252600e908201526d0d2dcecc2d8d2c840d8cadccee8d60931b604082015260600190565b6001600160c01b039290921682526001600160401b0316602082015260400190565b90815260200190565b9182521515602082015260400190565b918252602082015260400190565b6040518181016001600160401b0381118282101715611f9557600080fd5b604052919050565b60006001600160401b03821115611fb2578081fd5b506020908102019056fea2646970667358221220b56b861efe9115508cd849b66b4cab2f10ee8114e61c89c9991eec04a3621cb064736f6c63430006040033

Deployed ByteCode Sourcemap

40038:6797:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;40038:6797:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;41183:62:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;43705:208;;;;;;;;;:::i;:::-;;42295:101;;;;;;;;;:::i;40651:23::-;;;:::i;:::-;;;;;;;;46238:112;;;;;;;;;:::i;:::-;;;;;;;;46108:122;;;;;;;;;:::i;44144:218::-;;;;;;;;;:::i;42604:188::-;;;;;;;;;:::i;42507:89::-;;;;;;;;;:::i;43327:210::-;;;;;;;;;:::i;43112:207::-;;;;;;;;;:::i;44709:997::-;;;;;;;;;:::i;41004:45::-;;;;;;;;;:::i;46630:202::-;;;;;;;;;:::i;:::-;;;;;;;;;43921:215;;;;;;;;;:::i;41254:360::-;;;;;;;;;:::i;44370:266::-;;;:::i;:::-;;;;;;;;46504:118;;;;;;;;;:::i;:::-;;;;;;;;46358:138;;;;;;;;;:::i;:::-;;;;;;;;;43545:152;;;;;;;;;:::i;45752:348::-;;;;;;;;;:::i;42800:304::-;;;;;;;;;:::i;40681:20::-;;;:::i;41183:62::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;41183:62:0;;;-1:-1:-1;;;41183:62:0;;-1:-1:-1;;;;;41183:62:0;;:::o;43705:208::-;42456:5;;-1:-1:-1;;;;;42456:5:0;42442:10;:19;42434:45;;;;-1:-1:-1;;;42434:45:0;;;;;;;;;;;;;;;;;43778:21:::1;:7;43793:5:::0;43778:21:::1;:14;:21;:::i;:::-;43770:48;;;;-1:-1:-1::0;;;43770:48:0::1;;;;;;;;;43886:19;43899:5;43886:19;;;;;;;;;;;;;;;43705:208:::0;:::o;42295:101::-;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;42368:8:::1;:20:::0;;-1:-1:-1;;;;;;42368:20:0::1;-1:-1:-1::0;;;;;42368:20:0;;;::::1;::::0;;;::::1;::::0;;42295:101::o;40651:23::-;;;-1:-1:-1;;;;;40651:23:0;;:::o;46238:112::-;-1:-1:-1;;;;;46318:18:0;;46294:4;46318:18;;;:11;:18;;;;;:24;-1:-1:-1;;;;;46318:24:0;46238:112;;;;:::o;46108:122::-;-1:-1:-1;;;;;46193:18:0;46169:4;46193:18;;;:11;:18;;;;;:29;-1:-1:-1;;;46193:29:0;;-1:-1:-1;;;;;46193:29:0;;46108:122::o;44144:218::-;42456:5;;-1:-1:-1;;;;;42456:5:0;42442:10;:19;42434:45;;;;-1:-1:-1;;;42434:45:0;;;;;;;;;44229:9:::1;44224:94;44244:17:::0;;::::1;44224:94;;;44283:23;44296:6;;44303:1;44296:9;;;;;;;;;;;;;;;;;;;;;44283:23;44263:3;;44224:94;;;;44333:21;44347:6;;44333:21;;;;;;;;;;;;;;;;44144:218:::0;;:::o;42604:188::-;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;42676:25:::1;:8;42694:6:::0;42676:25:::1;:17;:25;:::i;:::-;42675:26;42667:56;;;;-1:-1:-1::0;;;42667:56:0::1;;;;;;;;;42734:20;:8;42747:6:::0;42734:20:::1;:12;:20;:::i;:::-;;42770:14;42777:6;42770:14;;;;;;;42507:89:::0;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;42574:5:::1;:14:::0;;-1:-1:-1;;;;;;42574:14:0::1;-1:-1:-1::0;;;;;42574:14:0;;;::::1;::::0;;;::::1;::::0;;42507:89::o;43327:210::-;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;43411:9:::1;43406:91;43426:18:::0;;::::1;43406:91;;;43466:19;43474:7;;43482:1;43474:10;;;;;;;;;;;;;;;;;;;;;43466:19;43446:3;;43406:91;;;;43512:17;43521:7;;43512:17;;;;;;;;43112:207:::0;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;43195:9:::1;43190:90;43210:18:::0;;::::1;43190:90;;;43250:18;43257:7;;43265:1;43257:10;;;;;;;;;;;;;;;;;;;;;43250:18;43230:3;;43190:90;;;;43295:16;43303:7;;43295:16;;;;;;;;44709:997:::0;42102:29;:8;42120:10;42102:29;:17;:29;:::i;:::-;42094:61;;;;-1:-1:-1;;;42094:61:0;;;;;;;;;44788:29:::1;:8;44806:10;44788:29;:17;:29;:::i;:::-;44780:55;;;;-1:-1:-1::0;;;44780:55:0::1;;;;;;;;;44856:10;44848:19;::::0;;;:7:::1;:19;::::0;;;;;;;-1:-1:-1;;;;;44848:26:0;::::1;::::0;;;;;;;:47;;-1:-1:-1;;;;;;44848:47:0::1;-1:-1:-1::0;;;;;44848:47:0;;::::1;::::0;;;::::1;44906:57;-1:-1:-1::0;;;44953:3:0::1;:9:::0;::::1;-1:-1:-1::0;;;;;44906:57:0::1;;;::::0;;44976:25:::1;45017:17;:8;:15;:17::i;:::-;45004:31;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;45004:31:0::1;-1:-1:-1::0;44976:59:0;-1:-1:-1;45046:9:0::1;::::0;45070:278:::1;45094:17;:8;:15;:17::i;:::-;45090:1;:21;45070:278;;;45133:11;45147:14;:8;45159:1:::0;45147:14:::1;:11;:14;:::i;:::-;-1:-1:-1::0;;;;;45180:12:0;;::::1;;::::0;;;:7:::1;:12;::::0;;;;;;;:19;;::::1;::::0;;;;;;:25;45133:28;;-1:-1:-1;;;;;;45180:25:0::1;:30:::0;;::::1;::::0;:70:::1;;-1:-1:-1::0;;;;;;45220:12:0;;::::1;;::::0;;;:7:::1;:12;::::0;;;;;;;:19;;::::1;::::0;;;;;;:30;-1:-1:-1;;;45220:30:0;::::1;-1:-1:-1::0;;;;;45220:30:0::1;45214:3;:36;45180:70;45176:161;;;-1:-1:-1::0;;;;;45295:12:0;;::::1;;::::0;;;:7:::1;:12;::::0;;;;;;;:19;;::::1;::::0;;;;;;:25;45271:14;;45295:25;45281:3;::::1;::::0;-1:-1:-1;;;;;45295:25:0;;::::1;::::0;45271:9;;:14;::::1;;;;;;;;;;:50;;;::::0;::::1;45176:161;-1:-1:-1::0;45113:3:0::1;;45070:278;;;;45360:27;45403:1;45390:15;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;::::0;-1:-1;45390:15:0::1;-1:-1:-1::0;45360:45:0;-1:-1:-1;45421:9:0::1;45416:88;45440:1;45436;:5;45416:88;;;45480:9;45490:1;45480:12;;;;;;;;;;;;;;45463:11;45475:1;45463:14;;;;;;;;;::::0;;::::1;::::0;;;;;:29;45443:3:::1;;45416:88;;;;45551:36;45575:11;45551:23;:36::i;:::-;-1:-1:-1::0;;;;;45516:18:0;::::1;;::::0;;;:11:::1;:18;::::0;;;;;;:72;;-1:-1:-1;;;;;;45516:72:0::1;-1:-1:-1::0;;;;;45516:72:0;;::::1;;45599:49:::0;;::::1;-1:-1:-1::0;;;45638:3:0::1;:9:::0;::::1;-1:-1:-1::0;;;;;45599:49:0::1;;;::::0;;;45666:32;::::1;::::0;::::1;::::0;45670:10:::1;::::0;45516:18;;45689:3;;45638:9;;45666:32:::1;;;;;;;;;;42166:1;;;44709:997:::0;;;:::o;41004:45::-;;;;;;;;;;;;-1:-1:-1;;;;;41004:45:0;;;-1:-1:-1;;;41004:45:0;;-1:-1:-1;;;;;41004:45:0;;:::o;46630:202::-;-1:-1:-1;;;;;46760:15:0;;;46712:10;46760:15;;;:7;:15;;;;;;;;:22;;;;;;;;;:28;-1:-1:-1;;;;;46760:28:0;;;-1:-1:-1;;;46790:33:0;;-1:-1:-1;;;;;46790:33:0;46630:202;;;;;;:::o;43921:215::-;42456:5;;-1:-1:-1;;;;;42456:5:0;42442:10;:19;42434:45;;;;-1:-1:-1;;;42434:45:0;;;;;;;;;44005:9:::1;44000:93;44020:17:::0;;::::1;44000:93;;;44059:22;44071:6;;44078:1;44071:9;;;;;;;;;;;;;;;;;;;;;44059:22;44039:3;;44000:93;;;;44108:20;44121:6;;44108:20;;;;;;;;41254:360:::0;30975:12;;;;;;;;:31;;;30991:15;:13;:15::i;:::-;30975:47;;;-1:-1:-1;31011:11:0;;;;31010:12;30975:47;30967:106;;;;-1:-1:-1;;;30967:106:0;;;;;;;;;31082:19;31105:12;;;;;;31104:13;31124:83;;;;31153:12;:19;;-1:-1:-1;;;;31153:19:0;;;;;31181:18;31168:4;31181:18;;;31124:83;41377:8:::1;:20:::0;;-1:-1:-1;;;;;41377:20:0;::::1;-1:-1:-1::0;;;;;;41377:20:0;;::::1;;::::0;;;41408:5:::1;:18:::0;;;;::::1;41416:10;41408:18;::::0;;41447:19;;41377:20;-1:-1:-1;41447:24:0::1;41439:51;;;;-1:-1:-1::0;;;41439:51:0::1;;;;;;;;;41506:9;41501:106;41525:12;:19;41521:1;:23;41501:106;;;41566:29;41579:12;41592:1;41579:15;;;;;;;;;;;;;;41566:8;:12;;:29;;;;:::i;:::-;-1:-1:-1::0;41546:3:0::1;;41501:106;;;;31229:14:::0;31225:57;;;31269:5;31254:20;;-1:-1:-1;;31254:20:0;;;31225:57;41254:360;;;:::o;44370:266::-;44409:16;44438:23;44478:16;:7;:14;:16::i;:::-;44464:31;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;44464:31:0;-1:-1:-1;44438:57:0;-1:-1:-1;44511:9:0;44506:99;44530:16;:7;:14;:16::i;:::-;44526:1;:20;44506:99;;;44580:13;:7;44591:1;44580:13;:10;:13;:::i;:::-;44568:6;44575:1;44568:9;;;;;;;;-1:-1:-1;;;;;44568:25:0;;;:9;;;;;;;;;;;:25;44548:3;;44506:99;;;-1:-1:-1;44622:6:0;-1:-1:-1;44370:266:0;:::o;46504:118::-;-1:-1:-1;;;;;46585:18:0;46555:4;46585:18;;;:11;:18;;;;;:29;-1:-1:-1;;;46585:29:0;;-1:-1:-1;;;;;46585:29:0;46579:3;:35;;46504:118::o;46358:138::-;-1:-1:-1;;;;;46449:18:0;;46418:4;46449:18;;;:11;:18;;;;;:24;46418:4;;-1:-1:-1;;;;;46449:24:0;46475:12;46461:5;46475;:12::i;:::-;-1:-1:-1;;;;;46441:47:0;;;;-1:-1:-1;46441:47:0;-1:-1:-1;46358:138:0;;;:::o;43545:152::-;42456:5;;-1:-1:-1;;;;;42456:5:0;42442:10;:19;42434:45;;;;-1:-1:-1;;;42434:45:0;;;;;;;;;43617:18:::1;:7;43629:5:::0;43617:18:::1;:11;:18;:::i;:::-;43609:46;;;;-1:-1:-1::0;;;43609:46:0::1;;;;;;;;;43671:18;43683:5;43671:18;;;;;;;45752:348:::0;42102:29;:8;42120:10;42102:29;:17;:29;:::i;:::-;42094:61;;;;-1:-1:-1;;;42094:61:0;;;;;;;;;45868:6;45900:21;;::::1;45892:54;;;;-1:-1:-1::0;;;45892:54:0::1;;;;;;;;;45964:6;45959:89;45980:6;45976:1;:10;45959:89;;;46008:28;46012:6;;46019:1;46012:9;;;;;;;;;;;;;;;;;;;;;;46023:4;;46028:1;46023:7;;;;;;;;;;;;;46032:3;46008;:28::i;:::-;45988:3;;45959:89;;;;46065:27;46074:6;;46082:4;;46088:3;46065:27;;;;;;;;;;;42800:304:::0;42238:8;;-1:-1:-1;;;;;42238:8:0;42224:10;:22;42216:51;;;;-1:-1:-1;;;42216:51:0;;;;;;;;;42872:25:::1;:8;42890:6:::0;42872:25:::1;:17;:25;:::i;:::-;42864:47;;;;-1:-1:-1::0;;;42864:47:0::1;;;;;;;;;42922:23;:8;42938:6:::0;42922:23:::1;:15;:23;:::i;:::-;-1:-1:-1::0;42963:6:0::1;42958:108;42979:16;:7;:14;:16::i;:::-;42975:1;:20;42958:108;;;-1:-1:-1::0;;;;;43024:15:0;::::1;;::::0;;;:7:::1;:15;::::0;;;;;43040:13:::1;:7;43051:1:::0;43040:13:::1;:10;:13;:::i;:::-;-1:-1:-1::0;;;;;43024:30:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;43024:30:0;;;43017:37;;42997:3:::1;42958:108;;;;43081:15;43089:6;43081:15;;;;;;;40681:20:::0;;;-1:-1:-1;;;;;40681:20:0;;:::o;37266:149::-;37339:4;37363:44;37371:3;-1:-1:-1;;;;;37391:14:0;;37363:7;:44::i;:::-;37356:51;;37266:149;;;;;:::o;37501:158::-;37581:4;37605:46;37615:3;-1:-1:-1;;;;;37635:14:0;;37605:9;:46::i;36947:143::-;37017:4;37041:41;37046:3;-1:-1:-1;;;;;37066:14:0;;37041:4;:41::i;37745:117::-;37808:7;37835:19;37843:3;37835:7;:19::i;38206:149::-;38280:7;38323:22;38327:3;38339:5;38323:3;:22::i;22950:522::-;23036:6;23066:4;:11;23062:1;:15;23054:50;;;;-1:-1:-1;;;23054:50:0;;;;;;;;;23125:11;;23171:1;23165:7;;23183;;;23179:288;;23206:14;23229;23273:62;23288:4;23294:1;23303;23297:3;:7;23320:1;23306:11;:15;23323:11;23273:14;:62::i;:::-;23252:83;;-1:-1:-1;23252:83:0;-1:-1:-1;23351:36:0;23252:83;;23351:18;:36::i;:::-;23344:43;;;;;;;;23179:288;23417:42;23429:4;23435:1;23444;23438:3;:7;23447:11;23417;:42::i;:::-;23410:49;;;;;;31376:508;31793:4;31839:17;31871:7;31376:508;:::o;34191:1544::-;34257:4;34396:19;;;:12;;;:19;;;;;;34432:15;;34428:1300;;34867:18;;-1:-1:-1;;34818:14:0;;;;34867:22;;;;34794:21;;34867:3;;:22;;35154;;;;;;;;;;;;;;35134:42;;35300:9;35271:3;:11;;35283:13;35271:26;;;;;;;;;;;;;;;;;;;:38;;;;35377:23;;;35419:1;35377:12;;;:23;;;;;;35403:17;;;35377:43;;35529:17;;35377:3;;35529:17;;;;;;;;;;;;;;;;;;;;;;35624:3;:12;;:19;35637:5;35624:19;;;;;;;;;;;35617:26;;;35667:4;35660:11;;;;;;;;34428:1300;35711:5;35704:12;;;;;35821:129;35894:4;35918:19;;;:12;;;;;:19;;;;;;:24;;;35821:129::o;33601:414::-;33664:4;33686:21;33696:3;33701:5;33686:9;:21::i;:::-;33681:327;;-1:-1:-1;27:10;;39:1;23:18;;;45:23;;33724:11:0;:23;;;;;;;;;;;;;33907:18;;33885:19;;;:12;;;:19;;;;;;:40;;;;33940:11;;33681:327;-1:-1:-1;33991:5:0;33984:12;;36036:109;36119:18;;36036:109::o;36489:204::-;36584:18;;36556:7;;36584:26;-1:-1:-1;36576:73:0;;;;-1:-1:-1;;;36576:73:0;;;;;;;;;36667:3;:11;;36679:5;36667:18;;;;;;;;;;;;;;;;36660:25;;36489:204;;;;:::o;27141:831::-;27318:11;27331;27367:2;27362;:7;27354:16;;12:1:-1;9;2:12;27354:16:0;27391:2;27385;:8;;:20;;;;;27403:2;27397;:8;;27385:20;27377:29;;12:1:-1;9;2:12;27377:29:0;27427:2;27421;:8;;:20;;;;;27439:2;27433;:8;;27421:20;27413:29;;12:1:-1;9;2:12;27413:29:0;23605:1;27482:2;27477;:7;:35;27473:105;;;27532:36;27547:4;27553:2;27557;27561;27565;27532:14;:36::i;:::-;27525:43;;;;;;27473:105;27586:16;27605:23;27615:4;27621:2;27625;27605:9;:23::i;:::-;27586:42;;27647:8;27641:2;:14;27637:323;;27673:8;27668:13;;27637:323;;;27712:2;27701:8;:13;27697:263;;;27732:8;27743:1;27732:12;27727:17;;27697:263;;;27784:8;27778:2;:14;;:31;;;;;27807:2;27796:8;:13;27778:31;27771:39;;;;27828:35;27840:4;27846:2;27850:8;27860:2;27828:11;:35::i;:::-;27821:42;;27881:39;27893:4;27899:8;27910:1;27899:12;27913:2;27917;27881:11;:39::i;:::-;27874:46;-1:-1:-1;27931:19:0;;-1:-1:-1;27931:19:0;27697:263;27451:516;;;;27141:831;;;;;;;;:::o;21915:277::-;21988:6;22016:1;22011:2;:6;:16;;;;;22026:1;22021:2;:6;22011:16;22010:40;;;;22038:1;22033:2;:6;:16;;;;;22048:1;22043:2;:6;22033:16;22006:85;;;22082:1;22068:11;22072:2;22076;22068:3;:11::i;:::-;:15;;;;;;22061:22;;;;22006:85;22097:16;22136:1;22117:6;;;22126;;;22117:15;22116:21;;-1:-1:-1;22151:35:0;22155:19;22164:1;22159:2;:6;22172:1;22167:2;:6;22155:3;:19::i;:::-;22176:9;22151:3;:35::i;:::-;22144:42;21915:277;-1:-1:-1;;;;21915:277:0:o;26169:798::-;26284:10;26320:1;26314:2;:7;;26306:16;;12:1:-1;9;2:12;26306:16:0;26342:2;26337:1;:7;;26329:16;;12:1:-1;9;2:12;26329:16:0;26364:2;26359;:7;26352:588;;;23605:1;26386:2;26381;:7;:35;26377:157;;;26429:13;26469:34;26484:4;26490:2;26494;26498:1;26501;26469:14;:34::i;:::-;-1:-1:-1;26453:50:0;-1:-1:-1;26514:10:0;;-1:-1:-1;26514:10:0;26377:157;26542:18;26563:23;26573:4;26579:2;26583;26563:9;:23::i;:::-;26542:44;;26604:10;26599:1;:15;26595:338;;26749:10;26744:15;;26595:338;;;26909:10;26922:1;26909:14;26904:19;;26595:338;26352:588;;;;26953:4;26958:2;26953:8;;;;;;;;;;;;;;26946:15;;26169:798;;;;;;:::o;23749:2258::-;23910:11;23923;24182;24205:2;24196;24201:1;24196:6;:11;24182:25;;24214:9;24226:4;24231:2;24236:1;24231:6;24226:12;;;;;;;;;;;;;;24214:24;;24245:9;24261:3;24257:1;:7;:32;;-1:-1:-1;;;;;24257:32:0;;;24267:4;24272:2;24277:1;24272:6;24267:12;;;;;;;;;;;;;;24257:32;24245:44;;24296:9;24312:3;24308:1;:7;:32;;-1:-1:-1;;;;;24308:32:0;;;24318:4;24323:2;24328:1;24323:6;24318:12;;;;;;;;;;;;;;24308:32;24296:44;;24347:9;24363:3;24359:1;:7;:32;;-1:-1:-1;;;;;24359:32:0;;;24369:4;24374:2;24379:1;24374:6;24369:12;;;;;;;;;;;;;;24359:32;24347:44;;24398:9;24414:3;24410:1;:7;:32;;-1:-1:-1;;;;;24410:32:0;;;24420:4;24425:2;24430:1;24425:6;24420:12;;;;;;;;;;;;;;24410:32;24398:44;;24449:9;24465:3;24461:1;:7;:32;;-1:-1:-1;;;;;24461:32:0;;;24471:4;24476:2;24481:1;24476:6;24471:12;;;;;;;;;;;;;;24461:32;24449:44;;24500:9;24516:3;24512:1;:7;:32;;-1:-1:-1;;;;;24512:32:0;;;24522:4;24527:2;24532:1;24527:6;24522:12;;;;;;;;;;;;;;24512:32;24500:44;;24562:2;24557;:7;24553:35;;;24579:2;;24583;24553:35;24603:2;24598;:7;24594:35;;;24620:2;;24624;24594:35;24644:2;24639;:7;24635:35;;;24661:2;;24665;24635:35;24685:2;24680;:7;24676:35;;;24702:2;;24706;24676:35;24726:2;24721;:7;24717:35;;;24743:2;;24747;24717:35;24767:2;24762;:7;24758:35;;;24784:2;24758:35;24808:2;24803;:7;24799:35;;;24825:2;;24829;24799:35;24849:2;24844;:7;24840:35;;;24866:2;24840:35;24890:2;24885;:7;24881:35;;;24907:2;;24911;24881:35;24931:2;24926;:7;24922:35;;;24948:2;;24952;24922:35;24972:2;24967;:7;24963:35;;;24989:2;24963:35;25013:2;25008;:7;25004:35;;;25030:2;;25034;25004:35;25054:2;25049;:7;25045:35;;;25071:2;25045:35;25095:2;25090;:7;25086:35;;;25112:2;;25116;25086:35;25136:2;25131;:7;25127:35;;;25153:2;;25157;25127:35;25177:2;25172;:7;25168:35;;;25194:2;;25198;25168:35;25228:7;;;25246:11;25242:309;;25267:2;25260:9;;25242:309;;;25286:6;25296:1;25286:11;25282:269;;;25307:2;25300:9;;25282:269;;;25326:6;25336:1;25326:11;25322:229;;;25347:2;25340:9;;25322:229;;;25366:6;25376:1;25366:11;25362:189;;;25387:2;25380:9;;25362:189;;;25406:6;25416:1;25406:11;25402:149;;;25427:2;25420:9;;25402:149;;;25446:6;25456:1;25446:11;25442:109;;;25467:2;25460:9;;25442:109;;;25486:6;25496:1;25486:11;25482:69;;;25507:2;25500:9;;25482:69;;;25523:26;;-1:-1:-1;;;25523:26:0;;;;;;;;25482:69;25576:7;;;25594:8;;;25590:412;;;-1:-1:-1;25613:4:0;;-1:-1:-1;25605:19:0;;-1:-1:-1;;;;;;;;;25605:19:0;25590:412;25641:11;25637:365;;-1:-1:-1;25669:2:0;;-1:-1:-1;25655:17:0;;-1:-1:-1;;;;;;;;25655:17:0;25637:365;25689:6;25699:1;25689:11;25685:317;;;-1:-1:-1;25717:2:0;;-1:-1:-1;25703:17:0;;-1:-1:-1;;;;;;;;25703:17:0;25685:317;25737:6;25747:1;25737:11;25733:269;;;-1:-1:-1;25765:2:0;;-1:-1:-1;25751:17:0;;-1:-1:-1;;;;;;;;25751:17:0;25733:269;25785:6;25795:1;25785:11;25781:221;;;-1:-1:-1;25813:2:0;;-1:-1:-1;25799:17:0;;-1:-1:-1;;;;;;;;25799:17:0;25781:221;25833:6;25843:1;25833:11;25829:173;;;-1:-1:-1;25861:2:0;;-1:-1:-1;25847:17:0;;-1:-1:-1;;;;;;;;25847:17:0;25829:173;25881:6;25891:1;25881:11;25877:125;;;-1:-1:-1;25909:2:0;;-1:-1:-1;25895:17:0;;-1:-1:-1;;;;;;;;25895:17:0;25877:125;25929:6;25939:1;25929:11;25925:77;;;-1:-1:-1;25957:2:0;;-1:-1:-1;25943:17:0;;-1:-1:-1;;;;;;;;25943:17:0;25925:77;25974:26;;-1:-1:-1;;;25974:26:0;;;;;;;;28304:1256;28406:7;;28578:4;28595:1;28584:7;;;28583:13;28578:19;;;;;;;;;;;;;;28563:34;;28610:1;28604:7;;;;28667:1;28661:7;;;;28675:880;28717:1;28711:7;;;;28747:5;28736:4;28741:2;28736:8;;;;;;;;;;;;;;:16;28697:57;;28762;28782:1;28776:7;;;;28812:5;28801:4;28806:2;28801:8;;;;;;;;;;;;;;:16;28762:57;;28836:2;28831;:7;28827:721;;;28875:4;28880:2;28875:8;;;;;;;;;;;;;;28885:4;28890:2;28885:8;;;;;;;;;;;;;;28852:4;28857:2;28852:8;;;;;;;;;;;;;28862:4;28867:2;28862:8;;;;;;;;;;;;;;;;;28851:43;;;;;28827:721;;;29536:2;29529:9;;;;;28827:721;28675:880;;28304:1256;;;;;;:::o;21477:201::-;21533:6;21559:5;;;21580:6;;;;;;:16;;;21595:1;21590;:6;;21580:16;21579:38;;;;21606:1;21602;:5;:14;;;;;21615:1;21611;:5;21602:14;21571:84;;;;-1:-1:-1;;;21571:84:0;;;;;;;;5:130:-1;72:20;;-1:-1;;;;;25461:54;;26437:35;;26427:2;;26486:1;;26476:12;160:352;;;290:3;283:4;275:6;271:17;267:27;257:2;;-1:-1;;298:12;257:2;-1:-1;328:20;;-1:-1;;;;;357:30;;354:2;;;-1:-1;;390:12;354:2;434:4;426:6;422:17;410:29;;485:3;434:4;;469:6;465:17;426:6;451:32;;448:41;445:2;;;502:1;;492:12;1768:241;;1872:2;1860:9;1851:7;1847:23;1843:32;1840:2;;;-1:-1;;1878:12;1840:2;1940:53;1985:7;1961:22;1940:53;;2016:366;;;2137:2;2125:9;2116:7;2112:23;2108:32;2105:2;;;-1:-1;;2143:12;2105:2;2205:53;2250:7;2226:22;2205:53;;;2195:63;;2313:53;2358:7;2295:2;2338:9;2334:22;2313:53;;;2303:63;;2099:283;;;;;;2389:502;;;2535:2;2523:9;2514:7;2510:23;2506:32;2503:2;;;-1:-1;;2541:12;2503:2;2603:53;2648:7;2624:22;2603:53;;;2593:63;;2721:2;;2710:9;2706:18;2693:32;-1:-1;;;;;2737:6;2734:30;2731:2;;;-1:-1;;2767:12;2731:2;2858:6;2847:9;2843:22;655:3;648:4;640:6;636:17;632:27;622:2;;-1:-1;;663:12;622:2;710:6;697:20;683:34;;732:80;747:64;804:6;747:64;;;732:80;;;840:21;;;897:14;;;;872:17;;;986;;;977:27;;;;974:36;-1:-1;971:2;;;-1:-1;;1013:12;971:2;-1:-1;1039:10;;1033:206;1058:6;1055:1;1052:13;1033:206;;;1138:37;1171:3;1159:10;1138:37;;;1126:50;;1080:1;1073:9;;;;;1190:14;;;;1218;;1033:206;;;1037:14;2787:88;;;;;;;;2497:394;;;;;;2898:491;;;;3036:2;3024:9;3015:7;3011:23;3007:32;3004:2;;;-1:-1;;3042:12;3004:2;3104:53;3149:7;3125:22;3104:53;;;3094:63;3194:2;3233:22;;1698:20;;-1:-1;3302:2;3341:22;;;1698:20;;2998:391;-1:-1;;;2998:391;3396:397;;;3535:2;3523:9;3514:7;3510:23;3506:32;3503:2;;;-1:-1;;3541:12;3503:2;3599:17;3586:31;-1:-1;;;;;3629:6;3626:30;3623:2;;;-1:-1;;3659:12;3623:2;3697:80;3769:7;3760:6;3749:9;3745:22;3697:80;;;3687:90;;;;-1:-1;3497:296;-1:-1;;;;3497:296;3800:803;;;;;;4008:2;3996:9;3987:7;3983:23;3979:32;3976:2;;;-1:-1;;4014:12;3976:2;4072:17;4059:31;-1:-1;;;;;4110:18;4102:6;4099:30;4096:2;;;-1:-1;;4132:12;4096:2;4170:80;4242:7;4233:6;4222:9;4218:22;4170:80;;;4160:90;;-1:-1;4160:90;-1:-1;4315:2;4300:18;;4287:32;;-1:-1;4328:30;;;4325:2;;;-1:-1;;4361:12;4325:2;;4399:80;4471:7;4462:6;4451:9;4447:22;4399:80;;;3970:633;;;;-1:-1;4389:90;4516:2;4555:22;1698:20;;3970:633;-1:-1;;;;3970:633;5202:665;;24666:6;24661:3;24654:19;24703:4;;24698:3;24694:14;5349:93;;5527:21;-1:-1;5554:291;5579:6;5576:1;5573:13;5554:291;;;25182:12;;;-1:-1;;;;;25156:39;25182:12;5675:6;25156:39;;;25461:54;5002:37;;4764:14;;;;5766:72;-1:-1;5601:1;5594:9;5554:291;;;-1:-1;5851:10;;5336:531;-1:-1;;;;;5336:531;12949:213;-1:-1;;;;;25461:54;;;;5002:37;;13067:2;13052:18;;13038:124;13169:563;-1:-1;;;;;25461:54;;;4871:58;;25461:54;;;;13552:2;13537:18;;5002:37;13635:2;13620:18;;12783:37;13718:2;13703:18;;12783:37;;;;13379:3;13364:19;;13350:382;13739:381;;13917:2;13938:17;13931:47;13992:118;13917:2;13906:9;13902:18;14096:6;14088;13992:118;;14127:771;;14421:2;14442:17;14435:47;14496:118;14421:2;14410:9;14406:18;14600:6;14592;14496:118;;;14652:20;;;14647:2;14632:18;;14625:48;24654:19;;;-1:-1;;;;;6883:78;;6880:2;;;-1:-1;;6964:12;6880:2;14647;6999:6;6995:17;26306:6;26301:3;14647:2;24698:3;24694:14;26283:30;26344:16;14647:2;26344:16;26337:27;;;14884:2;14869:18;;;;12783:37;;;;26344:16;14392:506;-1:-1;;;;14392:506;14905:361;15073:2;15087:47;;;24262:12;;15058:18;;;24654:19;;;14905:361;;15073:2;24116:14;;;;24694;;;;14905:361;6314:260;6339:6;6336:1;6333:13;6314:260;;;6400:13;;-1:-1;;;;;25461:54;5002:37;;24394:14;;;;4764;;;;25472:42;6354:9;6314:260;;;-1:-1;15140:116;;15044:222;-1:-1;;;;;;15044:222;15273:201;25373:13;;25366:21;7175:34;;15385:2;15370:18;;15356:118;15481:407;15672:2;15686:47;;;7446:2;15657:18;;;24654:19;7482:34;24694:14;;;7462:55;-1:-1;;;7537:12;;;7530:26;7575:12;;;15643:245;15895:407;16086:2;16100:47;;;7826:2;16071:18;;;24654:19;-1:-1;;;24694:14;;;7842:38;7899:12;;;16057:245;16309:407;16500:2;16514:47;;;8150:2;16485:18;;;24654:19;-1:-1;;;24694:14;;;8166:39;8224:12;;;16471:245;16723:407;16914:2;16928:47;;;8475:2;16899:18;;;24654:19;8511:34;24694:14;;;8491:55;-1:-1;;;8566:12;;;8559:25;8603:12;;;16885:245;17137:407;17328:2;17342:47;;;8854:2;17313:18;;;24654:19;-1:-1;;;24694:14;;;8870:37;8926:12;;;17299:245;17551:407;17742:2;17756:47;;;9177:2;17727:18;;;24654:19;-1:-1;;;24694:14;;;9193:45;9257:12;;;17713:245;17965:407;18156:2;18170:47;;;9508:1;18141:18;;;24654:19;-1:-1;;;24694:14;;;9523:32;9574:12;;;18127:245;18379:407;18570:2;18584:47;;;9825:2;18555:18;;;24654:19;-1:-1;;;24694:14;;;9841:40;9900:12;;;18541:245;18793:407;18984:2;18998:47;;;10151:2;18969:18;;;24654:19;-1:-1;;;24694:14;;;10167:39;10225:12;;;18955:245;19207:407;19398:2;19412:47;;;10476:2;19383:18;;;24654:19;10512:34;24694:14;;;10492:55;-1:-1;;;10567:12;;;10560:38;10617:12;;;19369:245;19621:407;19812:2;19826:47;;;10868:2;19797:18;;;24654:19;-1:-1;;;24694:14;;;10884:39;10942:12;;;19783:245;20035:407;20226:2;20240:47;;;11193:2;20211:18;;;24654:19;-1:-1;;;24694:14;;;11209:43;11271:12;;;20197:245;20449:407;20640:2;20654:47;;;11522:2;20625:18;;;24654:19;-1:-1;;;24694:14;;;11538:36;11593:12;;;20611:245;20863:407;21054:2;21068:47;;;11844:2;21039:18;;;24654:19;-1:-1;;;24694:14;;;11860:36;11915:12;;;21025:245;21277:407;21468:2;21482:47;;;12166:2;21453:18;;;24654:19;-1:-1;;;24694:14;;;12182:42;12243:12;;;21439:245;21691:407;21882:2;21896:47;;;12494:2;21867:18;;;24654:19;-1:-1;;;24694:14;;;12510:37;12566:12;;;21853:245;22105:320;-1:-1;;;;;25589:62;;;;12663:37;;-1:-1;;;;;25803:30;22411:2;22396:18;;12901:36;22249:2;22234:18;;22220:205;22432:213;12783:37;;;22550:2;22535:18;;22521:124;22652:312;12783:37;;;25373:13;25366:21;22950:2;22935:18;;7175:34;22792:2;22777:18;;22763:201;22971:324;12783:37;;;23281:2;23266:18;;12783:37;23117:2;23102:18;;23088:207;23302:256;23364:2;23358:9;23390:17;;;-1:-1;;;;;23450:34;;23486:22;;;23447:62;23444:2;;;23522:1;;23512:12;23444:2;23364;23531:22;23342:216;;-1:-1;23342:216;23565:304;;-1:-1;;;;;23716:6;23713:30;23710:2;;;-1:-1;;23746:12;23710:2;-1:-1;23791:4;23779:17;;;23844:15;;23647:222

Swarm Source

ipfs://b56b861efe9115508cd849b66b4cab2f10ee8114e61c89c9991eec04a3621cb0
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading