Contract 0xC3E272F76b3740C2AcF8e5272CbEF06D70e14FF3

 
Txn Hash
Block
From
To
Value [Txn Fee]
0x98b8414715b3faf5367bc01bf2c5f9edc1d7bb368d35585a95a4a165e424a0017891432021-09-14 6:47:213 days 12 hrs ago0x0f3bf5c241b6625c0fa781ed137fde6786b2e66f IN  0xc3e272f76b3740c2acf8e5272cbef06d70e14ff30 ETH0.001080850888 ETH
0x04647cb0ed45f251e970c6b8d9c57aef620ae4fdc9598c03082136d232b35f7f2199062021-08-17 13:23:5431 days 5 hrs ago0x904b5993fc92979eeedc19ccc58bed6b7216667c IN  Contract Creation0 ETH0.026076887673 ETH
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OracleRouterCreator

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : OracleRouterCreator.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "./OracleRouter.sol";

// A factory to deploy OracleRouter. Each path should be deployed only once.
contract OracleRouterCreator {
    mapping(bytes32 => address) public routers;

    event NewOracleRouter(
        address router,
        string collateral,
        string underlyingAsset,
        OracleRouter.Route[] path
    );

    /**
     * @notice Geth hash key of given path.
     * @param path [(oracle, isInverse)]. The OracleRouterCreator never verifies whether the path is reasonable.
     *             collateral() and underlyingAsset() only shows correct value if the collateral token is in
     *             the 1st item and the underlying asset is always in the last item.
     * @return @return The encoded bytes of data
     */
    function getPathHash(OracleRouter.Route[] memory path) public pure returns (bytes32) {
        return keccak256(abi.encode(path));
    }

    /**
     * @notice Create an OracleRouter. Revert if the router is already deployed.
     * @param path [(oracle, isInverse)]. The OracleRouterCreator never verifies whether the path is reasonable.
     *             collateral() and underlyingAsset() only shows correct value if the collateral token is in
     *             the 1st item and the underlying asset is always in the last item.
     * @return instance The address of the created OracleRouter
     */
    function createOracleRouter(OracleRouter.Route[] memory path)
        public
        returns (address instance)
    {
        require(path.length > 0, "empty path");
        bytes32 key = getPathHash(path);
        require(routers[key] == address(0), "already deployed");
        OracleRouter router = new OracleRouter(path);
        instance = address(router);
        routers[key] = instance;
        emit NewOracleRouter(instance, router.collateral(), router.underlyingAsset(), path);
    }
}

File 2 of 10 : OracleRouter.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "../../libraries/SafeMathExt.sol";
import "../../interface/IOracle.sol";

// An oracle router calculates the asset price with a given path.
// A path is [(oracle, isInverse)]. The OracleRouter never verifies whether the path is reasonable.
// collateral() and underlyingAsset() only shows correct value if the collateral token is in the 1st item
// and the underlying asset is always in the last item.
//
// Example 1: underlying = eth, collateral = usd, oracle1 = eth/usd = 1000
// [(oracle1, false)], return oracle1 = 1000
//
// Example 2: underlying = usd, collateral = eth, oracle1 = eth/usd
// [(oracle1, true)], return (1 / oracle1) = 0.001
//
// Example 3: underlying = btc, collateral = eth, oracle1 = btc/usd = 10000, oracle2 = eth/usd = 1000
// [(oracle2, true), (oracle1, false)], return (1 / oracle2) * oracle1 = 10
//
// Example 4: underlying = eth, collateral = btc, oracle1 = btc/usd = 10000, oracle2 = usd/eth = 0.001
// [(oracle1, true), (oracle2, true)], return (1 / oracle1) * (1 / oracle2) = 0.1
//
// Example 5: underlying = xxx, collateral = eth, oracle1 = btc/usd = 10000, oracle2 = eth/usd = 1000, oracle3 = xxx/btc = 2
// [(oracle2, true), (oracle1, false), (oracle3, false)], return (1 / oracle2) * oracle1 * oracle3 = 20
//
contract OracleRouter {
    using SafeMathExt for int256;
    using SafeMathExt for uint256;

    struct Route {
        address oracle;
        bool isInverse;
    }

    struct RouteDump {
        address oracle;
        bool isInverse;
        string underlyingAsset;
        string collateral;
    }

    string public constant source = "OracleRouter";
    Route[] internal _path;

    constructor(Route[] memory path_) {
        require(path_.length > 0, "empty path");
        for (uint256 i = 0; i < path_.length; i++) {
            require(path_[i].oracle != address(0), "empty oracle");
            _path.push(Route({ oracle: path_[i].oracle, isInverse: path_[i].isInverse }));
        }
    }

    /**
     * @dev Get collateral symbol.
     *
     *      The OracleRouter never verifies whether the path is reasonable.
     *      collateral() and underlyingAsset() only shows correct value if the collateral token is in
     *      the 1st item and the underlying asset is always in the last item.
     * @return symbol string
     */
    function collateral() public view returns (string memory) {
        if (_path[0].isInverse) {
            return IOracle(_path[0].oracle).underlyingAsset();
        } else {
            return IOracle(_path[0].oracle).collateral();
        }
    }

    /**
     * @dev Get underlying asset symbol.
     *
     *      The OracleRouter never verifies whether the path is reasonable.
     *      collateral() and underlyingAsset() only shows correct value if the collateral token is in
     *      the 1st item and the underlying asset is always in the last item.
     * @return symbol string
     */
    function underlyingAsset() public view returns (string memory) {
        uint256 i = _path.length - 1;
        if (_path[i].isInverse) {
            return IOracle(_path[i].oracle).collateral();
        } else {
            return IOracle(_path[i].oracle).underlyingAsset();
        }
    }

    /**
     * @dev Mark price.
     */
    function priceTWAPLong() external returns (int256 newPrice, uint256 newTimestamp) {
        newPrice = Constant.SIGNED_ONE;
        for (uint256 i = 0; i < _path.length; i++) {
            (int256 p, uint256 t) = IOracle(_path[i].oracle).priceTWAPLong();
            if (_path[i].isInverse && p != 0) {
                p = Constant.SIGNED_ONE.wdiv(p);
            }
            newPrice = newPrice.wmul(p);
            newTimestamp = newTimestamp.max(t);
        }
    }

    /**
     * @dev Index price.
     */
    function priceTWAPShort() external returns (int256 newPrice, uint256 newTimestamp) {
        newPrice = Constant.SIGNED_ONE;
        for (uint256 i = 0; i < _path.length; i++) {
            (int256 p, uint256 t) = IOracle(_path[i].oracle).priceTWAPShort();
            if (_path[i].isInverse && p != 0) {
                p = Constant.SIGNED_ONE.wdiv(p);
            }
            newPrice = newPrice.wmul(p);
            newTimestamp = newTimestamp.max(t);
        }
    }

    /**
     * @dev The market is closed if the market is not in its regular trading period.
     */
    function isMarketClosed() external returns (bool) {
        for (uint256 i = 0; i < _path.length; i++) {
            if (IOracle(_path[i].oracle).isMarketClosed()) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev The oracle service was shutdown and never online again.
     */
    function isTerminated() external returns (bool) {
        for (uint256 i = 0; i < _path.length; i++) {
            if (IOracle(_path[i].oracle).isTerminated()) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Dump the addresses
     */
    function getPath() external view returns (Route[] memory) {
        return _path;
    }

    /**
     * @dev Dump the path with info
     */
    function dumpPath() external view returns (RouteDump[] memory) {
        RouteDump[] memory ret = new RouteDump[](_path.length);
        for (uint256 i = 0; i < _path.length; i++) {
            ret[i].oracle = _path[i].oracle;
            ret[i].isInverse = _path[i].isInverse;
            ret[i].underlyingAsset = IOracle(_path[i].oracle).underlyingAsset();
            ret[i].collateral = IOracle(_path[i].oracle).collateral();
        }
        return ret;
    }
}

File 3 of 10 : SafeMathExt.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;

import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol";

import "./Constant.sol";
import "./Utils.sol";

enum Round {
    CEIL,
    FLOOR
}

library SafeMathExt {
    using SafeMathUpgradeable for uint256;
    using SignedSafeMathUpgradeable for int256;

    /*
     * @dev Always half up for uint256
     */
    function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x.mul(y).add(Constant.UNSIGNED_ONE / 2) / Constant.UNSIGNED_ONE;
    }

    /*
     * @dev Always half up for uint256
     */
    function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x.mul(Constant.UNSIGNED_ONE).add(y / 2).div(y);
    }

    /*
     * @dev Always half up for uint256
     */
    function wfrac(
        uint256 x,
        uint256 y,
        uint256 z
    ) internal pure returns (uint256 r) {
        r = x.mul(y).add(z / 2).div(z);
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wmul(int256 x, int256 y) internal pure returns (int256 z) {
        z = roundHalfUp(x.mul(y), Constant.SIGNED_ONE) / Constant.SIGNED_ONE;
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wdiv(int256 x, int256 y) internal pure returns (int256 z) {
        if (y < 0) {
            y = neg(y);
            x = neg(x);
        }
        z = roundHalfUp(x.mul(Constant.SIGNED_ONE), y).div(y);
    }

    /*
     * @dev Always half up if no rounding parameter
     */
    function wfrac(
        int256 x,
        int256 y,
        int256 z
    ) internal pure returns (int256 r) {
        int256 t = x.mul(y);
        if (z < 0) {
            z = neg(z);
            t = neg(t);
        }
        r = roundHalfUp(t, z).div(z);
    }

    function wmul(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 z) {
        z = div(x.mul(y), Constant.SIGNED_ONE, round);
    }

    function wdiv(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 z) {
        z = div(x.mul(Constant.SIGNED_ONE), y, round);
    }

    function wfrac(
        int256 x,
        int256 y,
        int256 z,
        Round round
    ) internal pure returns (int256 r) {
        int256 t = x.mul(y);
        r = div(t, z, round);
    }

    function abs(int256 x) internal pure returns (int256) {
        return x >= 0 ? x : neg(x);
    }

    function neg(int256 a) internal pure returns (int256) {
        return SignedSafeMathUpgradeable.sub(int256(0), a);
    }

    /*
     * @dev ROUND_HALF_UP rule helper.
     *      You have to call roundHalfUp(x, y) / y to finish the rounding operation.
     *      0.5 ≈ 1, 0.4 ≈ 0, -0.5 ≈ -1, -0.4 ≈ 0
     */
    function roundHalfUp(int256 x, int256 y) internal pure returns (int256) {
        require(y > 0, "roundHalfUp only supports y > 0");
        if (x >= 0) {
            return x.add(y / 2);
        }
        return x.sub(y / 2);
    }

    /*
     * @dev Division, rounding ceil or rounding floor
     */
    function div(
        int256 x,
        int256 y,
        Round round
    ) internal pure returns (int256 divResult) {
        require(y != 0, "division by zero");
        divResult = x.div(y);
        if (x % y == 0) {
            return divResult;
        }
        bool isSameSign = Utils.hasTheSameSign(x, y);
        if (round == Round.CEIL && isSameSign) {
            divResult = divResult.add(1);
        }
        if (round == Round.FLOOR && !isSameSign) {
            divResult = divResult.sub(1);
        }
    }

    function max(int256 a, int256 b) internal pure returns (int256) {
        return a >= b ? a : b;
    }

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

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

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

File 4 of 10 : IOracle.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.4;

interface IOracle {
    /**
     * @dev The market is closed if the market is not in its regular trading period.
     */
    function isMarketClosed() external returns (bool);

    /**
     * @dev The oracle service was shutdown and never online again.
     */
    function isTerminated() external returns (bool);

    /**
     * @dev Get collateral symbol.
     */
    function collateral() external view returns (string memory);

    /**
     * @dev Get underlying asset symbol.
     */
    function underlyingAsset() external view returns (string memory);

    /**
     * @dev Mark price.
     */
    function priceTWAPLong() external returns (int256 newPrice, uint256 newTimestamp);

    /**
     * @dev Index price.
     */
    function priceTWAPShort() external returns (int256 newPrice, uint256 newTimestamp);
}

File 5 of 10 : SafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @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 SafeMathUpgradeable {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

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

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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;
    }
}

File 6 of 10 : SignedSafeMathUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMathUpgradeable {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot 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 Returns the integer division of two signed 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(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 Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot 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 Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot 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;
    }
}

File 7 of 10 : Constant.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;

library Constant {
    address internal constant INVALID_ADDRESS = address(0);

    int256 internal constant SIGNED_ONE = 10**18;
    uint256 internal constant UNSIGNED_ONE = 10**18;

    uint256 internal constant PRIVILEGE_DEPOSIT = 0x1;
    uint256 internal constant PRIVILEGE_WITHDRAW = 0x2;
    uint256 internal constant PRIVILEGE_TRADE = 0x4;
    uint256 internal constant PRIVILEGE_LIQUIDATE = 0x8;
    uint256 internal constant PRIVILEGE_GUARD =
        PRIVILEGE_DEPOSIT | PRIVILEGE_WITHDRAW | PRIVILEGE_TRADE | PRIVILEGE_LIQUIDATE;
    // max number of uint256
    uint256 internal constant SET_ALL_PERPETUALS_TO_EMERGENCY_STATE =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
}

File 8 of 10 : Utils.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;

import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";

import "./SafeMathExt.sol";

library Utils {
    using SafeMathExt for int256;
    using SafeMathExt for uint256;
    using SafeMathUpgradeable for uint256;
    using SignedSafeMathUpgradeable for int256;
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.Bytes32Set;

    /*
     * @dev Check if two numbers have the same sign. Zero has the same sign with any number
     */
    function hasTheSameSign(int256 x, int256 y) internal pure returns (bool) {
        if (x == 0 || y == 0) {
            return true;
        }
        return (x ^ y) >> 255 == 0;
    }

    /**
     * @dev     Check if the trader has opened position in the trade.
     *          Example: 2, 1 => true; 2, -1 => false; -2, -3 => true
     * @param   amount  The position of the trader after the trade
     * @param   delta   The update position amount of the trader after the trade
     * @return  True if the trader has opened position in the trade
     */
    function hasOpenedPosition(int256 amount, int256 delta) internal pure returns (bool) {
        if (amount == 0) {
            return false;
        }
        return Utils.hasTheSameSign(amount, delta);
    }

    /*
     * @dev Split the delta to two numbers.
     *      Use for splitting the trading amount to the amount to close position and the amount to open position.
     *      Examples: 2, 1 => 0, 1; 2, -1 => -1, 0; 2, -3 => -2, -1
     */
    function splitAmount(int256 amount, int256 delta) internal pure returns (int256, int256) {
        if (Utils.hasTheSameSign(amount, delta)) {
            return (0, delta);
        } else if (amount.abs() >= delta.abs()) {
            return (delta, 0);
        } else {
            return (amount.neg(), amount.add(delta));
        }
    }

    /*
     * @dev Check if amount will be away from zero or cross zero if added the delta.
     *      Use for checking if trading amount will make trader open position.
     *      Example: 2, 1 => true; 2, -1 => false; 2, -3 => true
     */
    function isOpen(int256 amount, int256 delta) internal pure returns (bool) {
        return Utils.hasTheSameSign(amount, delta) || amount.abs() < delta.abs();
    }

    /*
     * @dev Get the id of the current chain
     */
    function chainID() internal pure returns (uint256 id) {
        assembly {
            id := chainid()
        }
    }

    // function toArray(
    //     EnumerableSet.AddressSet storage set,
    //     uint256 begin,
    //     uint256 end
    // ) internal view returns (address[] memory result) {
    //     require(end > begin, "begin should be lower than end");
    //     uint256 length = set.length();
    //     if (begin >= length) {
    //         return result;
    //     }
    //     uint256 safeEnd = end.min(length);
    //     result = new address[](safeEnd.sub(begin));
    //     for (uint256 i = begin; i < safeEnd; i++) {
    //         result[i.sub(begin)] = set.at(i);
    //     }
    //     return result;
    // }

    function toArray(
        EnumerableSetUpgradeable.AddressSet storage set,
        uint256 begin,
        uint256 end
    ) internal view returns (address[] memory result) {
        require(end > begin, "begin should be lower than end");
        uint256 length = set.length();
        if (begin >= length) {
            return result;
        }
        uint256 safeEnd = end.min(length);
        result = new address[](safeEnd.sub(begin));
        for (uint256 i = begin; i < safeEnd; i++) {
            result[i.sub(begin)] = set.at(i);
        }
        return result;
    }

    function toArray(
        EnumerableSetUpgradeable.Bytes32Set storage set,
        uint256 begin,
        uint256 end
    ) internal view returns (bytes32[] memory result) {
        require(end > begin, "begin should be lower than end");
        uint256 length = set.length();
        if (begin >= length) {
            return result;
        }
        uint256 safeEnd = end.min(length);
        result = new bytes32[](safeEnd.sub(begin));
        for (uint256 i = begin; i < safeEnd; i++) {
            result[i.sub(begin)] = set.at(i);
        }
        return result;
    }
}

File 9 of 10 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @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.3.0, sets of type `bytes32` (`Bytes32Set`), `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];
    }

    // Bytes32Set

    struct Bytes32Set {
        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(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, 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(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

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

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set 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(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, 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(uint160(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(uint160(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(uint160(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(uint160(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));
    }
}

File 10 of 10 : EnumerableSetUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @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.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSetUpgradeable {
    // 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];
    }

    // Bytes32Set

    struct Bytes32Set {
        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(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, 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(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

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

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set 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(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, 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(uint160(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(uint160(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(uint160(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(uint160(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));
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"router","type":"address"},{"indexed":false,"internalType":"string","name":"collateral","type":"string"},{"indexed":false,"internalType":"string","name":"underlyingAsset","type":"string"},{"components":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"bool","name":"isInverse","type":"bool"}],"indexed":false,"internalType":"struct OracleRouter.Route[]","name":"path","type":"tuple[]"}],"name":"NewOracleRouter","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"bool","name":"isInverse","type":"bool"}],"internalType":"struct OracleRouter.Route[]","name":"path","type":"tuple[]"}],"name":"createOracleRouter","outputs":[{"internalType":"address","name":"instance","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"bool","name":"isInverse","type":"bool"}],"internalType":"struct OracleRouter.Route[]","name":"path","type":"tuple[]"}],"name":"getPathHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"routers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50611b66806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000465760003560e01c80635801d66f146200004b5780637889515b146200007a578063aa1fce6914620000a0575b600080fd5b620000626200005c366004620003c7565b620000b7565b60405162000071919062000635565b60405180910390f35b620000916200008b366004620003c7565b620000e9565b604051620000719190620005ac565b62000091620000b136600462000480565b6200032d565b600081604051602001620000cc919062000619565b604051602081830303815290604052805190602001209050919050565b600080825111620001175760405162461bcd60e51b81526004016200010e9062000675565b60405180910390fd5b60006200012483620000b7565b6000818152602081905260409020549091506001600160a01b0316156200015f5760405162461bcd60e51b81526004016200010e906200063e565b600083604051620001709062000348565b6200017c919062000619565b604051809103906000f08015801562000199573d6000803e3d6000fd5b5060008381526020819052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03851690811790915581517fd8dfeb4500000000000000000000000000000000000000000000000000000000815291519396508694507faa12a8903c780c1b4d3d993af516ecb732ab70b8363e9095d81da857d4358dc1938593919263d8dfeb45926004808301939192829003018186803b1580156200025357600080fd5b505afa15801562000268573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000292919081019062000499565b836001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160006040518083038186803b158015620002cc57600080fd5b505afa158015620002e1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200030b919081019062000499565b876040516200031e9493929190620005c0565b60405180910390a15050919050565b6000602081905290815260409020546001600160a01b031681565b61142c806200070583390190565b60006040828403121562000368578081fd5b6040516040810181811067ffffffffffffffff821117156200038657fe5b60405290508082356001600160a01b0381168114620003a457600080fd5b815260208301358015158114620003ba57600080fd5b6020919091015292915050565b60006020808385031215620003da578182fd5b823567ffffffffffffffff80821115620003f2578384fd5b818501915085601f83011262000406578384fd5b8135818111156200041357fe5b620004228485830201620006ac565b81815284810192508385016040808402860187018a101562000442578788fd5b8795505b8386101562000472576200045b8a8362000356565b855260019590950194938601939081019062000446565b509098975050505050505050565b60006020828403121562000492578081fd5b5035919050565b600060208284031215620004ab578081fd5b815167ffffffffffffffff80821115620004c3578283fd5b818401915084601f830112620004d7578283fd5b815181811115620004e457fe5b620004f9601f8201601f1916602001620006ac565b915080825285602082850101111562000510578384fd5b62000523816020840160208601620006d1565b50949350505050565b6000815180845260208085019450808401835b838110156200057357815180516001600160a01b03168852830151151583880152604090960195908201906001016200053f565b509495945050505050565b6000815180845262000598816020860160208601620006d1565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b60006001600160a01b038616825260806020830152620005e460808301866200057e565b8281036040840152620005f881866200057e565b905082810360608401526200060e81856200052c565b979650505050505050565b6000602082526200062e60208301846200052c565b9392505050565b90815260200190565b60208082526010908201527f616c7265616479206465706c6f79656400000000000000000000000000000000604082015260600190565b6020808252600a908201527f656d707479207061746800000000000000000000000000000000000000000000604082015260600190565b60405181810167ffffffffffffffff81118282101715620006c957fe5b604052919050565b60005b83811015620006ee578181015183820152602001620006d4565b83811115620006fe576000848401525b5050505056fe60806040523480156200001157600080fd5b506040516200142c3803806200142c8339810160408190526200003491620001df565b6000815111620000615760405162461bcd60e51b81526004016200005890620002bd565b60405180910390fd5b60005b8151811015620001655760006001600160a01b03168282815181106200008657fe5b6020026020010151600001516001600160a01b03161415620000bc5760405162461bcd60e51b8152600401620000589062000297565b60006040518060400160405280848481518110620000d657fe5b6020026020010151600001516001600160a01b03168152602001848481518110620000fd57fe5b602090810291909101810151810151151590915282546001818101855560009485529382902083519101805493909201511515600160a01b0260ff60a01b196001600160a01b039092166001600160a01b031990941693909317169190911790550162000064565b505062000305565b6000604082840312156200017f578081fd5b604080519081016001600160401b03811182821017156200019c57fe5b604052825190915081906001600160a01b0381168114620001bc57600080fd5b815260208301518015158114620001d257600080fd5b6020919091015292915050565b60006020808385031215620001f2578182fd5b82516001600160401b038082111562000209578384fd5b818501915085601f8301126200021d578384fd5b8151818111156200022a57fe5b620002398485830201620002e1565b81815284810192508385016040808402860187018a101562000259578788fd5b8795505b838610156200028957620002728a836200016d565b85526001959095019493860193908101906200025d565b509098975050505050505050565b6020808252600c908201526b656d707479206f7261636c6560a01b604082015260600190565b6020808252600a90820152690cadae0e8f240e0c2e8d60b31b604082015260600190565b6040518181016001600160401b0381118282101715620002fd57fe5b604052919050565b61111780620003156000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80639410b9e211610076578063ccbdbee21161005b578063ccbdbee214610123578063d1cc99761461012b578063d8dfeb4514610133576100a3565b80639410b9e2146100f9578063b7e86c1f1461010e576100a3565b80630e222f9b146100a8578063555b37be146100c757806367e828bf146100dc5780637158da7c146100f1575b600080fd5b6100b061013b565b6040516100be929190611003565b60405180910390f35b6100cf610273565b6040516100be9190610f9e565b6100e46102ec565b6040516100be9190611011565b6100e4610325565b610101610443565b6040516100be9190610efa565b6101166106a2565b6040516100be9190610ff8565b6100b061076f565b6101166108a2565b6100e4610967565b670de0b6b3a76400006000805b60005481101561026e576000806000838154811061016257fe5b6000918252602082200154604080517f0e222f9b00000000000000000000000000000000000000000000000000000000815281516001600160a01b0390931693630e222f9b93600480840194939192918390030190829087803b1580156101c857600080fd5b505af11580156101dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102009190610e14565b915091506000838154811061021157fe5b600091825260209091200154600160a01b900460ff16801561023257508115155b1561024c57610249670de0b6b3a764000083610a7c565b91505b6102568583610ac9565b94506102628482610afe565b93505050600101610148565b509091565b60606000805480602002602001604051908101604052809291908181526020016000905b828210156102e257600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900460ff16151581830152825260019092019101610297565b5050505090505b90565b6040518060400160405280600c81526020017f4f7261636c65526f75746572000000000000000000000000000000000000000081525081565b600080546060916000198201918290811061033c57fe5b600091825260209091200154600160a01b900460ff16156103ef576000818154811061036457fe5b60009182526020822001546040805163d8dfeb4560e01b815290516001600160a01b039092169263d8dfeb4592600480840193829003018186803b1580156103ab57600080fd5b505afa1580156103bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103e79190810190610e37565b9150506102e9565b600081815481106103fc57fe5b600091825260208220015460408051631c56369f60e21b815290516001600160a01b0390921692637158da7c92600480840193829003018186803b1580156103ab57600080fd5b600054606090819067ffffffffffffffff8111801561046157600080fd5b5060405190808252806020026020018201604052801561049b57816020015b610488610dce565b8152602001906001900390816104805790505b50905060005b60005481101561069c57600081815481106104b857fe5b60009182526020909120015482516001600160a01b03909116908390839081106104de57fe5b60209081029190910101516001600160a01b039091169052600080548290811061050457fe5b9060005260206000200160000160149054906101000a900460ff1682828151811061052b57fe5b602090810291909101810151911515910152600080548290811061054b57fe5b600091825260208220015460408051631c56369f60e21b815290516001600160a01b0390921692637158da7c92600480840193829003018186803b15801561059257600080fd5b505afa1580156105a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105ce9190810190610e37565b8282815181106105da57fe5b602002602001015160400181905250600081815481106105f657fe5b60009182526020822001546040805163d8dfeb4560e01b815290516001600160a01b039092169263d8dfeb4592600480840193829003018186803b15801561063d57600080fd5b505afa158015610651573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106799190810190610e37565b82828151811061068557fe5b6020908102919091010151606001526001016104a1565b50905090565b6000805b60005481101561076757600081815481106106bd57fe5b9060005260206000200160000160009054906101000a90046001600160a01b03166001600160a01b031663b7e86c1f6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561071857600080fd5b505af115801561072c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107509190610df4565b1561075f5760019150506102e9565b6001016106a6565b506000905090565b670de0b6b3a76400006000805b60005481101561026e576000806000838154811061079657fe5b6000918252602082200154604080517fccbdbee200000000000000000000000000000000000000000000000000000000815281516001600160a01b039093169363ccbdbee293600480840194939192918390030190829087803b1580156107fc57600080fd5b505af1158015610810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108349190610e14565b915091506000838154811061084557fe5b600091825260209091200154600160a01b900460ff16801561086657508115155b156108805761087d670de0b6b3a764000083610a7c565b91505b61088a8583610ac9565b94506108968482610afe565b9350505060010161077c565b6000805b60005481101561076757600081815481106108bd57fe5b9060005260206000200160000160009054906101000a90046001600160a01b03166001600160a01b031663d1cc99766040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561091857600080fd5b505af115801561092c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109509190610df4565b1561095f5760019150506102e9565b6001016108a6565b60606000808154811061097657fe5b600091825260209091200154600160a01b900460ff1615610a28576000808154811061099e57fe5b600091825260208220015460408051631c56369f60e21b815290516001600160a01b0390921692637158da7c92600480840193829003018186803b1580156109e557600080fd5b505afa1580156109f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a219190810190610e37565b90506102e9565b60008081548110610a3557fe5b60009182526020822001546040805163d8dfeb4560e01b815290516001600160a01b039092169263d8dfeb4592600480840193829003018186803b1580156109e557600080fd5b600080821215610a9d57610a8f82610b17565b9150610a9a83610b17565b92505b610ac282610abc610ab686670de0b6b3a7640000610b24565b85610bcd565b90610c4c565b9392505050565b6000670de0b6b3a7640000610aef610ae18585610b24565b670de0b6b3a7640000610bcd565b81610af657fe5b059392505050565b600081831015610b0e5781610ac2565b50815b92915050565b6000610b11600083610d04565b600082610b3357506000610b11565b82600019148015610b475750600160ff1b82145b15610b835760405162461bcd60e51b81526004018080602001828103825260278152602001806110976027913960400191505060405180910390fd5b82820282848281610b9057fe5b0514610ac25760405162461bcd60e51b81526004018080602001828103825260278152602001806110976027913960400191505060405180910390fd5b6000808213610c23576040805162461bcd60e51b815260206004820152601f60248201527f726f756e6448616c665570206f6e6c7920737570706f7274732079203e203000604482015290519081900360640190fd5b60008312610c3f57610c388360028405610d69565b9050610b11565b610ac28360028405610d04565b600081610ca0576040805162461bcd60e51b815260206004820181905260248201527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604482015290519081900360640190fd5b81600019148015610cb45750600160ff1b83145b15610cf05760405162461bcd60e51b81526004018080602001828103825260218152602001806110766021913960400191505060405180910390fd5b6000828481610cfb57fe5b05949350505050565b6000818303818312801590610d195750838113155b80610d2e5750600083128015610d2e57508381135b610ac25760405162461bcd60e51b81526004018080602001828103825260248152602001806110be6024913960400191505060405180910390fd5b6000828201818312801590610d7e5750838112155b80610d935750600083128015610d9357508381125b610ac25760405162461bcd60e51b81526004018080602001828103825260218152602001806110556021913960400191505060405180910390fd5b604080516080810182526000808252602082015260609181018290528181019190915290565b600060208284031215610e05578081fd5b81518015158114610ac2578182fd5b60008060408385031215610e26578081fd5b505080516020909101519092909150565b600060208284031215610e48578081fd5b815167ffffffffffffffff80821115610e5f578283fd5b818401915084601f830112610e72578283fd5b815181811115610e7e57fe5b604051601f8201601f191681016020018381118282101715610e9c57fe5b604052818152838201602001871015610eb3578485fd5b610ec4826020830160208701611024565b9695505050505050565b60008151808452610ee6816020860160208601611024565b601f01601f19169290920160200192915050565b60208082528251828201819052600091906040908185019080840286018301878501865b83811015610f9057603f19898403018552815160806001600160a01b03825116855288820151151589860152878201518189870152610f5f82870182610ece565b91505060608083015192508582038187015250610f7c8183610ece565b968901969450505090860190600101610f1e565b509098975050505050505050565b602080825282518282018190526000919060409081850190868401855b82811015610feb57815180516001600160a01b031685528601511515868501529284019290850190600101610fbb565b5091979650505050505050565b901515815260200190565b918252602082015260400190565b600060208252610ac26020830184610ece565b60005b8381101561103f578181015183820152602001611027565b8381111561104e576000848401525b5050505056fe5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f775369676e6564536166654d6174683a206469766973696f6e206f766572666c6f775369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f77a2646970667358221220a4c2a47d962be5d1086ee09a986ddb5e8caf1659b21283a450f1ea231291460964736f6c63430007040033a2646970667358221220e94c2323e8b7b06673c8441c3ac5fcf2b8d4471a29d8860bf475560339309e8764736f6c63430007040033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.