Contract 0x58228d352B6B2b8642395e6175b06D90ceA93B5a 1

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xa15ab3793e911275b9072aaac5ff544e02c2c1edcf956a7e2e4f6e8305ad95c90x6080604031000882021-11-17 7:56:2819 days 13 hrs ago0x904b5993fc92979eeedc19ccc58bed6b7216667c IN  Contract Creation0 ETH0.168235518804 ETH
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TunableOracleRegister

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion
File 1 of 20 : TunableOracle.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/SafeCastUpgradeable.sol";

import "@openzeppelin/contracts/proxy/IBeacon.sol";
import "@openzeppelin/contracts/proxy/BeaconProxy.sol";

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

/**
 * @dev TunableOracleRegister is managed by MCDEX DAO, who can add some ExternalOracles.
 *      TunableOracle selects one of the registered ExternalOracles and set FineTunedPrice
 *      to improve the precision.
 */
contract TunableOracleRegister is
    Initializable,
    ContextUpgradeable,
    AccessControlUpgradeable,
    IBeacon
{
    struct ExternalOracle {
        bool isAdded;
        bool isTerminated;
        uint64 deviation; // decimals = 18. index price will be truncated to mark price * (1 ± deviation).
        uint64 timeout; // seconds. the effective timespan of FineTunedPrice.
    }

    mapping(address => ExternalOracle) internal _externalOracles;
    bool public isAllTerminated;
    address private _tunableOracleImplementation;
    mapping(address => bool) public tunableOracles;

    event SetExternalOracle(address indexed externalOracle, uint64 deviation, uint64 timeout);
    event Terminated(address indexed externalOracle);
    event AllTerminated();
    event Upgraded(address indexed implementation);
    event TunableOracleCreated(
        address indexed liquidityPool,
        address indexed externalOracle,
        address newOracle
    );

    /**
     * @dev TERMINATER_ROLE can shutdown the oracle service and never online again.
     */
    bytes32 public constant TERMINATER_ROLE = keccak256("TERMINATER_ROLE");

    function initialize() external virtual initializer {
        __TunableOracleRegister_init();
    }

    function __TunableOracleRegister_init() internal initializer {
        __Context_init_unchained();
        __AccessControl_init_unchained();
        __TunableOracleRegister_init_unchained();
    }

    function __TunableOracleRegister_init_unchained() internal initializer {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _setupRole(TERMINATER_ROLE, _msgSender());
        _setTunableOracleImplementation(address(new TunableOracle()));
    }

    /**
     * @dev Read an ExternalOracle config.
     */
    function getExternalOracle(address externalOracle)
        external
        view
        returns (ExternalOracle memory)
    {
        return _externalOracles[externalOracle];
    }

    /**
     * @dev The ExternalOracle was shutdown and never online again.
     */
    function isTerminated(address externalOracle) external view returns (bool) {
        ExternalOracle storage m = _externalOracles[externalOracle];
        return isAllTerminated || m.isTerminated;
    }

    /**
     * @dev Beacon implementation of a TunableOracle.
     *
     *      CAUTION: if TunableOracleRegister is proxied by a TransparentUpgradeableProxy,
     *               the ProxyAdmin will get the TunableOracleRegister implementation and
     *               other address will get TunableOracle implementation.
     */
    function implementation() public view virtual override returns (address) {
        return _tunableOracleImplementation;
    }

    /**
     * @dev Anyone can create an TunableOracle.
     */
    function newTunableOracle(address liquidityPool, address externalOracle)
        external
        returns (address)
    {
        BeaconProxy newOracle = new BeaconProxy(
            address(this), // beacon
            abi.encodeWithSignature(
                "initialize(address,address,address)",
                address(this), // register
                liquidityPool,
                externalOracle
            )
        );
        tunableOracles[address(newOracle)] = true;
        emit TunableOracleCreated(liquidityPool, externalOracle, address(newOracle));
        return address(newOracle);
    }

    /**
     * @dev Admin can add or overwrite an ExternalOracle.
     */
    function setExternalOracle(
        address externalOracle,
        uint64 deviation, // decimals = 18
        uint64 timeout
    ) external {
        require(!isAllTerminated, "all terminated");
        require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "role");
        ExternalOracle storage config = _externalOracles[externalOracle];
        config.isAdded = true;
        config.deviation = deviation;
        config.timeout = timeout;
        emit SetExternalOracle(externalOracle, deviation, timeout);
    }

    /**
     * @dev Admin can upgrade all TunableOracles.
     */
    function upgradeTunableOracle(address newImplementation) public virtual {
        require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "role");
        _setTunableOracleImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Terminater can stop an ExternalOracle.
     */
    function setTerminated(address externalOracle) external {
        require(!isAllTerminated, "all terminated");
        require(hasRole(TERMINATER_ROLE, _msgSender()), "role");
        ExternalOracle storage m = _externalOracles[externalOracle];
        m.isTerminated = true;
        emit Terminated(externalOracle);
    }

    /**
     * @dev Terminater can stop all ExternalOracles.
     */
    function setAllTerminated() external {
        require(!isAllTerminated, "all terminated");
        require(hasRole(TERMINATER_ROLE, _msgSender()), "role");
        isAllTerminated = true;
        emit AllTerminated();
    }

    function _setTunableOracleImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "not a contract");
        _tunableOracleImplementation = newImplementation;
    }
}

/**
 * @dev TunableOracle uses an ExternalOracle as MarkPrice and backup IndexPrice (AMM reference price).
 *      IndexPrice can be set by FineTuner unless timeout or given up (released) by FineTuner.
 *
 *      CAUTION: TunableOracle only uses externalOracle.markPrice.
 *
 *               +--------+--------+-----------+--------+---------+--------+
 * FineTunePrice | Price1 |        | (timeout) | Price4 | Release |        |
 *               +--------+--------+-----------+--------+---------+--------+
 * ExternalPrice | Price2 | Price3 |           |        |         | Price5 |
 *               +--------+--------+-----------+--------+---------+--------+
 * IndexPrice    | Price1 | Price1 | Price3    | Price4 | Price3  | Price5 |
 *               +--------+--------+-----------+--------+---------+--------+
 */
contract TunableOracle is Initializable, ContextUpgradeable, IOracle {
    using SignedSafeMathUpgradeable for int256;
    using SafeMathExt for int256;
    using SafeMathExt for uint256;
    using SafeCastUpgradeable for int256;
    using SafeCastUpgradeable for uint256;

    TunableOracleRegister public register;
    ILiquidityPoolGetter public liquidityPool;
    IOracle public externalOracle;

    // in order to save gas
    struct Price {
        int192 price;
        uint64 timestamp;
    }
    Price public externalPrice;
    Price public fineTunedPrice;
    bool public isReleased;
    address public fineTuner;

    event SetFineTuner(address fineTuner);
    event SetPrice(int256 price, uint256 timestamp);
    event Released();

    modifier onlyOperator() {
        require(_msgSender() == _getOperator(), "only Operator");
        _;
    }

    modifier onlyFineTuner() {
        require(_msgSender() == fineTuner, "only FineTuner");
        _;
    }

    function blockTimestamp() internal view virtual returns (uint256) {
        return block.timestamp;
    }

    function initialize(
        address tunableOracleRegister_,
        address liquidityPool_,
        address externalOracle_
    ) external virtual initializer {
        __TunableOracle_init(tunableOracleRegister_, liquidityPool_, externalOracle_);
    }

    function __TunableOracle_init(
        address tunableOracleRegister_,
        address liquidityPool_,
        address externalOracle_
    ) internal initializer {
        __Context_init_unchained();
        __TunableOracle_init_unchained(tunableOracleRegister_, liquidityPool_, externalOracle_);
    }

    function __TunableOracle_init_unchained(
        address tunableOracleRegister_,
        address liquidityPool_,
        address externalOracle_
    ) internal initializer {
        require(AddressUpgradeable.isContract(tunableOracleRegister_), "not a contract");
        require(AddressUpgradeable.isContract(liquidityPool_), "not a contract");
        register = TunableOracleRegister(tunableOracleRegister_);
        liquidityPool = ILiquidityPoolGetter(liquidityPool_);
        externalOracle = IOracle(externalOracle_);

        // must registered
        TunableOracleRegister.ExternalOracle memory config = register.getExternalOracle(
            address(externalOracle)
        );
        require(config.isAdded, "not registered");

        // must have operator
        require(_getOperator() != address(0), "no operator");

        // must not terminated
        require(!register.isTerminated(address(externalOracle)), "terminated");
        require(!externalOracle.isTerminated(), "external terminated");

        // save the initial mark price to make sure everything is working
        _forceUpdateExternalOracle();
    }

    /**
     * @dev Get collateral symbol. Also known as quote.
     */
    function collateral() external view override returns (string memory) {
        return externalOracle.collateral();
    }

    /**
     * @dev Get underlying asset symbol. Also known as base.
     */
    function underlyingAsset() external view override returns (string memory) {
        return externalOracle.underlyingAsset();
    }

    /**
     * @dev Mark price. Used to evaluate the account margin balance and liquidation.
     *
     *      Mark price is always ExternalOracle price.
     *      It does not need to be a TWAP. This name is only for backward compatibility.
     */
    function priceTWAPLong() public override returns (int256, uint256) {
        if (!isTerminated()) {
            _forceUpdateExternalOracle();
        } else {
            // leave the last price unchanged
        }
        return (externalPrice.price, externalPrice.timestamp);
    }

    /**
     * @dev Index price. It is AMM reference price.
     *
     *      It does not need to be a TWAP. This name is only for backward compatibility.
     */
    function priceTWAPShort() external override returns (int256, uint256) {
        // update external
        bool isTerminated_ = isTerminated();
        if (!isTerminated_) {
            _forceUpdateExternalOracle();
        } else {
            // leave the last price unchanged
        }
        int256 markPrice = int256(externalPrice.price);

        // pause the timestamp if terminated
        uint256 currentTime;
        if (!isTerminated_) {
            currentTime = blockTimestamp();
        } else {
            currentTime = uint256(externalPrice.timestamp).max(uint256(fineTunedPrice.timestamp));
        }

        // use ExternalOracle
        TunableOracleRegister.ExternalOracle memory config = register.getExternalOracle(
            address(externalOracle)
        );
        uint256 timeToDie = uint256(fineTunedPrice.timestamp) + uint256(config.timeout);
        if (currentTime >= timeToDie || isReleased) {
            return (
                markPrice,
                // time can not turn back
                uint256(externalPrice.timestamp).max(currentTime)
            );
        }

        // use FineTuner
        int256 width = int256(config.deviation).wmul(markPrice);
        int256 price = int256(fineTunedPrice.price);
        price = price.min(markPrice.add(width));
        price = price.max(markPrice.sub(width));
        return (price, fineTunedPrice.timestamp);
    }

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

    /**
     * @dev The oracle service was shutdown and never online again.
     */
    function isTerminated() public override returns (bool) {
        return register.isTerminated(address(externalOracle)) || externalOracle.isTerminated();
    }

    /**
     * @dev Operator can grant a FineTuner.
     */
    function setFineTuner(address newFineTuner) external onlyOperator {
        require(fineTuner != newFineTuner, "already set");
        fineTuner = newFineTuner;
        emit SetFineTuner(newFineTuner);
    }

    /**
     * @dev FineTuner can set price.
     *
     *      Implies timestamp = block.timestamp.
     */
    function setPrice(int256 newPrice) external onlyFineTuner {
        require(newPrice > 0, "price <= 0");
        require(!isTerminated(), "terminated");
        uint256 currentTime = blockTimestamp();
        fineTunedPrice = Price(_toInt192(newPrice), currentTime.toUint64());
        isReleased = false;
        emit SetPrice(newPrice, currentTime);
    }

    /**
     * @dev FineTuner can give up the FineTunedPrice.
     */
    function release() external onlyFineTuner {
        require(!isTerminated(), "terminated");
        isReleased = true;
        emit Released();
    }

    function _getOperator() internal view returns (address) {
        address[7] memory poolAddresses;
        uint256[6] memory uintNums;
        (, , poolAddresses, , uintNums) = liquidityPool.getLiquidityPoolInfo();
        return
            blockTimestamp() <= uintNums[3] /* operatorExpiration */
                ? poolAddresses[1] /* operator */
                : address(0);
    }

    function _forceUpdateExternalOracle() internal {
        (int256 p, uint256 t) = externalOracle.priceTWAPLong();
        require(p > 0, "external price <= 0");
        require(t > 0, "external time = 0");
        require(externalPrice.timestamp <= t, "external time reversed");
        // truncate timestamp to block.timestamp, so that when FineTuner sets price,
        // FineTuned price timestamp will >= markPrice.timestamp.
        t = t.min(blockTimestamp());
        externalPrice = Price(_toInt192(p), t.toUint64());
    }

    function _toInt192(int256 value) internal pure returns (int192) {
        require(value >= -2**191 && value < 2**191, "can not fit in int192");
        return int192(value);
    }
}

/**
 * @dev A simple tool to call setPrice of multiple TunableOracles.
 */
contract MultiTunableOracleSetter is
    Initializable,
    ContextUpgradeable,
    AccessControlUpgradeable
{
    mapping(uint32 => address) public tunableOracles;

    event SetTunableOracle(uint32 indexed id, address tunableOracle);
    
    /**
     * @dev FINE_TUNER_ROLE can set price.
     */
    bytes32 public constant FINE_TUNER_ROLE = keccak256("FINE_TUNER_ROLE");

    function initialize() external virtual initializer {
        __MultiTunableOracleSetter_init();
    }

    function __MultiTunableOracleSetter_init() internal initializer {
        __Context_init_unchained();
        __AccessControl_init_unchained();
        __MultiTunableOracleSetter_init_unchained();
    }

    function __MultiTunableOracleSetter_init_unchained() internal initializer {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _setupRole(FINE_TUNER_ROLE, _msgSender());
    }

    /**
     * @dev Admin can refer an id to a TunableOracle.
     */
    function setOracle(
        uint32 id,
        address tunableOracle
    ) external {
        require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "role");
        tunableOracles[id] = tunableOracle;
        emit SetTunableOracle(id, tunableOracle);
    }

    /**
     * @dev FineTuner can set prices.
     *
     * @param price1 is a packed structure.
     *         255     224 223         192 191           0
     *        +-----------+---------------+---------------+
     *        | id 32bits | unused 32bits | price 192bits |
     *        +-----------+---------------+---------------+
     */
    function setPrice1(bytes32 price1) external {
        require(hasRole(FINE_TUNER_ROLE, _msgSender()), "role");
        _setPrice(price1);
    }

    function setPrice2(bytes32 price1, bytes32 price2) external {
        require(hasRole(FINE_TUNER_ROLE, _msgSender()), "role");
        _setPrice(price1);
        _setPrice(price2);
    }

    function setPrices(bytes32[] memory prices) external {
        require(hasRole(FINE_TUNER_ROLE, _msgSender()), "role");
        for (uint256 i = 0; i < prices.length; i++) {
            _setPrice(prices[i]);
        }
    }

    function _setPrice(bytes32 price1) internal {
        uint32 id = uint32(uint256(price1) >> 224);
        int192 price = int192(uint256(price1));
        TunableOracle oracle = TunableOracle(tunableOracles[id]);
        require(oracle != TunableOracle(0), "unregistered");
        oracle.setPrice(price);
    }
}

File 2 of 20 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract 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 protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already 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) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 3 of 20 : AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/EnumerableSetUpgradeable.sol";
import "../utils/AddressUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable {
    function __AccessControl_init() internal initializer {
        __Context_init_unchained();
        __AccessControl_init_unchained();
    }

    function __AccessControl_init_unchained() internal initializer {
    }
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
    using AddressUpgradeable for address;

    struct RoleData {
        EnumerableSetUpgradeable.AddressSet members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view returns (bool) {
        return _roles[role].members.contains(account);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view returns (uint256) {
        return _roles[role].members.length();
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
        return _roles[role].members.at(index);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (_roles[role].members.add(account)) {
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (_roles[role].members.remove(account)) {
            emit RoleRevoked(role, account, _msgSender());
        }
    }
    uint256[49] private __gap;
}

File 4 of 20 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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 on 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");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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);
            }
        }
    }
}

File 5 of 20 : SafeCastUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such 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.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCastUpgradeable {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 6 of 20 : IBeacon.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 7 of 20 : BeaconProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Proxy.sol";
import "../utils/Address.sol";
import "./IBeacon.sol";

/**
 * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
 *
 * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
 * conflict with the storage layout of the implementation behind the proxy.
 *
 * _Available since v3.4._
 */
contract BeaconProxy is Proxy {
    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 private constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Initializes the proxy with `beacon`.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
     * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
     * constructor.
     *
     * Requirements:
     *
     * - `beacon` must be a contract with the interface {IBeacon}.
     */
    constructor(address beacon, bytes memory data) public payable {
        assert(_BEACON_SLOT == bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1));
        _setBeacon(beacon, data);
    }

    /**
     * @dev Returns the current beacon address.
     */
    function _beacon() internal view virtual returns (address beacon) {
        bytes32 slot = _BEACON_SLOT;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            beacon := sload(slot)
        }
    }

    /**
     * @dev Returns the current implementation address of the associated beacon.
     */
    function _implementation() internal view virtual override returns (address) {
        return IBeacon(_beacon()).implementation();
    }

    /**
     * @dev Changes the proxy to use a new beacon.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
     *
     * Requirements:
     *
     * - `beacon` must be a contract.
     * - The implementation returned by `beacon` must be a contract.
     */
    function _setBeacon(address beacon, bytes memory data) internal virtual {
        require(
            Address.isContract(beacon),
            "BeaconProxy: beacon is not a contract"
        );
        require(
            Address.isContract(IBeacon(beacon).implementation()),
            "BeaconProxy: beacon implementation is not a contract"
        );
        bytes32 slot = _BEACON_SLOT;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, beacon)
        }

        if (data.length > 0) {
            Address.functionDelegateCall(_implementation(), data, "BeaconProxy: function call failed");
        }
    }
}

File 8 of 20 : 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. Also known as quote.
     */
    function collateral() external view returns (string memory);

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

    /**
     * @dev Mark price. Used to evaluate the account margin balance and liquidation.
     *
     *      It does not need to be a TWAP. This name is only for backward compatibility.
     */
    function priceTWAPLong() external returns (int256 newPrice, uint256 newTimestamp);

    /**
     * @dev Index price. It is AMM reference price.
     *
     *      It does not need to be a TWAP. This name is only for backward compatibility.
     */
    function priceTWAPShort() external returns (int256 newPrice, uint256 newTimestamp);
}

File 9 of 20 : ILiquidityPoolGetter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "../Type.sol";

interface ILiquidityPoolGetter {
    /**
     * @notice Get the info of the liquidity pool
     * @return isRunning True if the liquidity pool is running
     * @return isFastCreationEnabled True if the operator of the liquidity pool is allowed to create new perpetual
     *                               when the liquidity pool is running
     * @return addresses The related addresses of the liquidity pool
     * @return intNums Int type properties, see below for details.
     * @return uintNums Uint type properties, see below for details.
     */
    function getLiquidityPoolInfo()
        external
        view
        returns (
            bool isRunning,
            bool isFastCreationEnabled,
            // [0] creator,
            // [1] operator,
            // [2] transferringOperator,
            // [3] governor,
            // [4] shareToken,
            // [5] collateralToken,
            // [6] vault,
            address[7] memory addresses,
            // [0] vaultFeeRate,
            // [1] poolCash,
            // [2] insuranceFundCap,
            // [3] insuranceFund,
            // [4] donatedInsuranceFund,
            int256[5] memory intNums,
            // [0] collateralDecimals,
            // [1] perpetualCount,
            // [2] fundingTime,
            // [3] operatorExpiration,
            // [4] liquidityCap,
            // [5] shareTransferDelay,
            uint256[6] memory uintNums
        );

    /**
     * @notice Get the info of the perpetual. Need to update the funding state and the oracle price
     *         of each perpetual before and update the funding rate of each perpetual after
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return state The state of the perpetual
     * @return oracle The oracle's address of the perpetual
     * @return nums The related numbers of the perpetual
     */
    function getPerpetualInfo(uint256 perpetualIndex)
        external
        view
        returns (
            PerpetualState state,
            address oracle,
            // [0] totalCollateral
            // [1] markPrice, (return settlementPrice if it is in EMERGENCY state)
            // [2] indexPrice,
            // [3] fundingRate,
            // [4] unitAccumulativeFunding,
            // [5] initialMarginRate,
            // [6] maintenanceMarginRate,
            // [7] operatorFeeRate,
            // [8] lpFeeRate,
            // [9] referralRebateRate,
            // [10] liquidationPenaltyRate,
            // [11] keeperGasReward,
            // [12] insuranceFundRate,
            // [13-15] halfSpread value, min, max,
            // [16-18] openSlippageFactor value, min, max,
            // [19-21] closeSlippageFactor value, min, max,
            // [22-24] fundingRateLimit value, min, max,
            // [25-27] ammMaxLeverage value, min, max,
            // [28-30] maxClosePriceDiscount value, min, max,
            // [31] openInterest,
            // [32] maxOpenInterestRate,
            // [33-35] fundingRateFactor value, min, max,
            // [36-38] defaultTargetLeverage value, min, max,
            // [39-41] baseFundingRate value, min, max,
            int256[42] memory nums
        );

    /**
     * @notice Get the account info of the trader. Need to update the funding state and the oracle price
     *         of each perpetual before and update the funding rate of each perpetual after
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param trader The address of the trader
     * @return cash The cash(collateral) of the account
     * @return position The position of the account
     * @return availableMargin The available margin of the account
     * @return margin The margin of the account
     * @return settleableMargin The settleable margin of the account
     * @return isInitialMarginSafe True if the account is initial margin safe
     * @return isMaintenanceMarginSafe True if the account is maintenance margin safe
     * @return isMarginSafe True if the total value of margin account is beyond 0
     * @return targetLeverage   The target leverage for openning position.
     */
    function getMarginAccount(uint256 perpetualIndex, address trader)
        external
        view
        returns (
            int256 cash,
            int256 position,
            int256 availableMargin,
            int256 margin,
            int256 settleableMargin,
            bool isInitialMarginSafe,
            bool isMaintenanceMarginSafe,
            bool isMarginSafe, // bankrupt
            int256 targetLeverage
        );

    /**
     * @notice Get the number of active accounts in the perpetual.
     *         Active means the trader's account is not empty in the perpetual.
     *         Empty means cash and position are zero
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return activeAccountCount The number of active accounts in the perpetual
     */
    function getActiveAccountCount(uint256 perpetualIndex) external view returns (uint256);

    /**
     * @notice Get the active accounts in the perpetual whose index between begin and end.
     *         Active means the trader's account is not empty in the perpetual.
     *         Empty means cash and position are zero
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @param begin The begin index
     * @param end The end index
     * @return result The active accounts in the perpetual whose index between begin and end
     */
    function listActiveAccounts(
        uint256 perpetualIndex,
        uint256 begin,
        uint256 end
    ) external view returns (address[] memory result);

    /**
     * @notice Get the progress of clearing active accounts.
     *         Return the number of total active accounts and the number of active accounts not cleared
     * @param perpetualIndex The index of the perpetual in the liquidity pool
     * @return left The left active accounts
     * @return total The total active accounts
     */
    function getClearProgress(uint256 perpetualIndex)
        external
        view
        returns (uint256 left, uint256 total);

    /**
     * @notice Get the pool margin of the liquidity pool.
     *         Pool margin is how much collateral of the pool considering the AMM's positions of perpetuals
     * @return poolMargin The pool margin of the liquidity pool
     */
    function getPoolMargin() external view returns (int256 poolMargin, bool isSafe);

    /**
     * @notice  Query the price, fees and cost when trade agaist amm.
     *          The trading price is determined by the AMM based on the index price of the perpetual.
     *          This method should returns the same result as a 'read-only' trade.
     *          WARN: the result of this function is base on current storage of liquidityPool, not the latest.
     *          To get the latest status, call `syncState` first.
     *
     *          Flags is a 32 bit uint value which indicates: (from highest bit)
     *            - close only      only close position during trading;
     *            - market order    do not check limit price during trading;
     *            - stop loss       only available in brokerTrade mode;
     *            - take profit     only available in brokerTrade mode;
     *          For stop loss and take profit, see `validateTriggerPrice` in OrderModule.sol for details.
     *
     * @param   perpetualIndex  The index of the perpetual in liquidity pool.
     * @param   trader          The address of trader.
     * @param   amount          The amount of position to trader, positive for buying and negative for selling. The amount always use decimals 18.
     * @param   referrer        The address of referrer who will get rebate from the deal.
     * @param   flags           The flags of the trade.
     * @return  tradePrice      The average fill price.
     * @return  totalFee        The total fee collected from the trader after the trade.
     * @return  cost            Deposit or withdraw to let effective leverage == targetLeverage if flags contain USE_TARGET_LEVERAGE. > 0 if deposit, < 0 if withdraw.
     */
    function queryTrade(
        uint256 perpetualIndex,
        address trader,
        int256 amount,
        address referrer,
        uint32 flags
    )
        external
        returns (
            int256 tradePrice,
            int256 totalFee,
            int256 cost
        );

    /**
     * @notice  Query cash to add / share to mint when adding liquidity to the liquidity pool.
     *          Only one of cashToAdd or shareToMint may be non-zero.
     *
     * @param   cashToAdd         The amount of cash to add, always use decimals 18.
     * @param   shareToMint       The amount of share token to mint, always use decimals 18.
     * @return  cashToAddResult   The amount of cash to add, always use decimals 18. Equal to cashToAdd if cashToAdd is non-zero.
     * @return  shareToMintResult The amount of cash to add, always use decimals 18. Equal to shareToMint if shareToMint is non-zero.
     */
    function queryAddLiquidity(int256 cashToAdd, int256 shareToMint)
        external
        view
        returns (int256 cashToAddResult, int256 shareToMintResult);

    /**
     * @notice  Query cash to return / share to redeem when removing liquidity from the liquidity pool.
     *          Only one of shareToRemove or cashToReturn may be non-zero.
     *          Can only called when the pool is running.
     *
     * @param   shareToRemove       The amount of share token to redeem, always use decimals 18.
     * @param   cashToReturn        The amount of cash to return, always use decimals 18.
     * @return  shareToRemoveResult The amount of share token to redeem, always use decimals 18. Equal to shareToRemove if shareToRemove is non-zero.
     * @return  cashToReturnResult  The amount of cash to return, always use decimals 18. Equal to cashToReturn if cashToReturn is non-zero.
     */
    function queryRemoveLiquidity(int256 shareToRemove, int256 cashToReturn)
        external
        view
        returns (int256 shareToRemoveResult, int256 cashToReturnResult);
}

File 10 of 20 : 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 11 of 20 : 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));
    }
}

File 12 of 20 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

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

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

File 13 of 20 : Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback () external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive () external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {
    }
}

File 14 of 20 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @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 on 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");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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);
            }
        }
    }
}

File 15 of 20 : Type.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;

import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";

/**
 * @notice  Perpetual state:
 *          - INVALID:      Uninitialized or not non-existent perpetual;
 *          - INITIALIZING: Only when LiquidityPoolStorage.isRunning == false. Traders cannot perform operations;
 *          - NORMAL:       Full functional state. Traders is able to perform all operations;
 *          - EMERGENCY:    Perpetual is unsafe and only clear is available;
 *          - CLEARED:      All margin account is cleared. Trade could withdraw remaining margin balance.
 */
enum PerpetualState {
    INVALID,
    INITIALIZING,
    NORMAL,
    EMERGENCY,
    CLEARED
}
enum OrderType {
    LIMIT,
    MARKET,
    STOP
}

/**
 * @notice  Data structure to store risk parameter value.
 */
struct Option {
    int256 value;
    int256 minValue;
    int256 maxValue;
}

/**
 * @notice  Data structure to store oracle price data.
 */
struct OraclePriceData {
    int256 price;
    uint256 time;
}

/**
 * @notice  Data structure to store user margin information. See MarginAccountModule.sol for details.
 */
struct MarginAccount {
    int256 cash;
    int256 position;
    int256 targetLeverage;
}

/**
 * @notice  Data structure of an order object.
 */
struct Order {
    address trader;
    address broker;
    address relayer;
    address referrer;
    address liquidityPool;
    int256 minTradeAmount;
    int256 amount;
    int256 limitPrice;
    int256 triggerPrice;
    uint256 chainID;
    uint64 expiredAt;
    uint32 perpetualIndex;
    uint32 brokerFeeLimit;
    uint32 flags;
    uint32 salt;
}

/**
 * @notice  Core data structure, a core .
 */
struct LiquidityPoolStorage {
    bool isRunning;
    bool isFastCreationEnabled;
    // addresses
    address creator;
    address operator;
    address transferringOperator;
    address governor;
    address shareToken;
    address accessController;
    bool reserved3; // isWrapped
    uint256 scaler;
    uint256 collateralDecimals;
    address collateralToken;
    // pool attributes
    int256 poolCash;
    uint256 fundingTime;
    uint256 reserved5;
    uint256 operatorExpiration;
    mapping(address => int256) reserved1;
    bytes32[] reserved2;
    // perpetuals
    uint256 perpetualCount;
    mapping(uint256 => PerpetualStorage) perpetuals;
    // insurance fund
    int256 insuranceFundCap;
    int256 insuranceFund;
    int256 donatedInsuranceFund;
    address reserved4;
    uint256 liquidityCap;
    uint256 shareTransferDelay;
    // reserved slot for future upgrade
    bytes32[14] reserved;
}

/**
 * @notice  Core data structure, storing perpetual information.
 */
struct PerpetualStorage {
    uint256 id;
    PerpetualState state;
    address oracle;
    int256 totalCollateral;
    int256 openInterest;
    // prices
    OraclePriceData indexPriceData;
    OraclePriceData markPriceData;
    OraclePriceData settlementPriceData;
    // funding state
    int256 fundingRate;
    int256 unitAccumulativeFunding;
    // base parameters
    int256 initialMarginRate;
    int256 maintenanceMarginRate;
    int256 operatorFeeRate;
    int256 lpFeeRate;
    int256 referralRebateRate;
    int256 liquidationPenaltyRate;
    int256 keeperGasReward;
    int256 insuranceFundRate;
    int256 reserved1;
    int256 maxOpenInterestRate;
    // risk parameters
    Option halfSpread;
    Option openSlippageFactor;
    Option closeSlippageFactor;
    Option fundingRateLimit;
    Option fundingRateFactor;
    Option ammMaxLeverage;
    Option maxClosePriceDiscount;
    // users
    uint256 totalAccount;
    int256 totalMarginWithoutPosition;
    int256 totalMarginWithPosition;
    int256 redemptionRateWithoutPosition;
    int256 redemptionRateWithPosition;
    EnumerableSetUpgradeable.AddressSet activeAccounts;
    // insurance fund
    int256 reserved2;
    int256 reserved3;
    // accounts
    mapping(address => MarginAccount) marginAccounts;
    Option defaultTargetLeverage;
    // keeper
    address reserved4;
    EnumerableSetUpgradeable.AddressSet ammKeepers;
    EnumerableSetUpgradeable.AddressSet reserved5;
    Option baseFundingRate;
    // reserved slot for future upgrade
    bytes32[9] reserved;
}

File 16 of 20 : 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 17 of 20 : 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 18 of 20 : 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 19 of 20 : 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 20 of 20 : 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));
    }
}

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

Contract ABI

[{"anonymous":false,"inputs":[],"name":"AllTerminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"externalOracle","type":"address"},{"indexed":false,"internalType":"uint64","name":"deviation","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"timeout","type":"uint64"}],"name":"SetExternalOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"externalOracle","type":"address"}],"name":"Terminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidityPool","type":"address"},{"indexed":true,"internalType":"address","name":"externalOracle","type":"address"},{"indexed":false,"internalType":"address","name":"newOracle","type":"address"}],"name":"TunableOracleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERMINATER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"externalOracle","type":"address"}],"name":"getExternalOracle","outputs":[{"components":[{"internalType":"bool","name":"isAdded","type":"bool"},{"internalType":"bool","name":"isTerminated","type":"bool"},{"internalType":"uint64","name":"deviation","type":"uint64"},{"internalType":"uint64","name":"timeout","type":"uint64"}],"internalType":"struct TunableOracleRegister.ExternalOracle","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAllTerminated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"externalOracle","type":"address"}],"name":"isTerminated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"address","name":"externalOracle","type":"address"}],"name":"newTunableOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setAllTerminated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"externalOracle","type":"address"},{"internalType":"uint64","name":"deviation","type":"uint64"},{"internalType":"uint64","name":"timeout","type":"uint64"}],"name":"setExternalOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"externalOracle","type":"address"}],"name":"setTerminated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tunableOracles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTunableOracle","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50613b33806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001905760003560e01c806391d1485411620000e1578063c37ad4f2116200008d578063d2ec06da116200006f578063d2ec06da1462000306578063d547741f146200031d578063e4bd63d014620003345762000190565b8063c37ad4f214620002d8578063ca15c87314620002ef5762000190565b8063a217fddf11620000c3578063a217fddf14620002ad578063c0ef593a14620002b7578063c0f49d1614620002c15762000190565b806391d14854146200027f5780639a650fd814620002965762000190565b806356062ee811620001415780635fd7987411620001235780635fd7987414620002455780638129fc1c146200025e5780639010d07c14620002685762000190565b806356062ee814620002155780635c60da1b146200022c5762000190565b8063248a9ca31162000177578063248a9ca314620001d05780632f2ff15d14620001e757806336568abe14620001fe5762000190565b806303d7d65a14620001955780630d015fff14620001ae575b600080fd5b620001ac620001a636600462001116565b6200035a565b005b620001b8620003d4565b604051620001c79190620012bc565b60405180910390f35b620001b8620001e1366004620011b3565b620003f8565b620001ac620001f8366004620011cc565b62000410565b620001ac6200020f366004620011cc565b6200047e565b620001ac6200022636600462001116565b620004e5565b62000236620005ab565b604051620001c7919062001213565b6200024f620005bf565b604051620001c79190620012b1565b620001ac620005c8565b6200023662000279366004620011f1565b6200067c565b6200024f62000290366004620011cc565b6200069f565b6200024f620002a736600462001116565b620006b9565b620001b8620006f0565b620001ac620006f5565b6200024f620002d236600462001116565b620007a1565b620001ac620002e93660046200116a565b620007b6565b620001b862000300366004620011b3565b620008ce565b620002366200031736600462001133565b620008e7565b620001ac6200032e366004620011cc565b62000a01565b6200034b6200034536600462001116565b62000a5f565b604051620001c791906200136a565b6200036a60006200029062000ad9565b620003925760405162461bcd60e51b81526004016200038990620012fc565b60405180910390fd5b6200039d8162000add565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7f4a0dd322941a79e91b8bc2de0d3eb943ea81e07d00f71bb32ad8b6fc1b60386681565b6000818152603360205260409020600201545b919050565b60008281526033602052604090206002015462000431906200029062000ad9565b6200046e5760405162461bcd60e51b815260040180806020018281038252602f81526020018062003a42602f913960400191505060405180910390fd5b6200047a828262000b46565b5050565b6200048862000ad9565b6001600160a01b0316816001600160a01b031614620004d95760405162461bcd60e51b815260040180806020018281038252602f81526020018062003acf602f913960400191505060405180910390fd5b6200047a828262000bb4565b60665460ff16156200050b5760405162461bcd60e51b8152600401620003899062001333565b6200053a7f4a0dd322941a79e91b8bc2de0d3eb943ea81e07d00f71bb32ad8b6fc1b6038666200029062000ad9565b620005595760405162461bcd60e51b81526004016200038990620012fc565b6001600160a01b038116600081815260656020526040808220805461ff00191661010017815590519092917f98cd97fc1a1cc958cbd729b1bb531d4f3ea4925470bf23ea9af386640cbd07be91a25050565b60665461010090046001600160a01b031690565b60665460ff1681565b600054610100900460ff1680620005e45750620005e462000c22565b80620005f3575060005460ff16155b620006305760405162461bcd60e51b815260040180806020018281038252602e81526020018062003aa1602e913960400191505060405180910390fd5b600054610100900460ff161580156200065c576000805460ff1961ff0019909116610100171660011790555b6200066662000c35565b801562000679576000805461ff00191690555b50565b600082815260336020526040812062000696908362000ce7565b90505b92915050565b600082815260336020526040812062000696908362000cf5565b6001600160a01b038116600090815260656020526040812060665460ff1680620006e957508054610100900460ff165b9392505050565b600081565b60665460ff16156200071b5760405162461bcd60e51b8152600401620003899062001333565b6200074a7f4a0dd322941a79e91b8bc2de0d3eb943ea81e07d00f71bb32ad8b6fc1b6038666200029062000ad9565b620007695760405162461bcd60e51b81526004016200038990620012fc565b6066805460ff191660011790556040517f1c9e3aa973990202a369c55466e97e7452b2aa2921f319e9a76e2b279b65490c90600090a1565b60676020526000908152604090205460ff1681565b60665460ff1615620007dc5760405162461bcd60e51b8152600401620003899062001333565b620007ec60006200029062000ad9565b6200080b5760405162461bcd60e51b81526004016200038990620012fc565b6001600160a01b03831660008181526065602052604090819020805467ffffffffffffffff8581166a0100000000000000000000027fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff918816620100000269ffffffffffffffff00001960ff1990941660011793909316929092171617815590519091907fe09787eb5714aca0943fc37dccfb7340a80177b8a2a1819db7d2c3262010113690620008c09086908690620013a9565b60405180910390a250505050565b6000818152603360205260408120620006999062000d0c565b60008030308585604051602401620009029392919062001227565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc0c53b8b00000000000000000000000000000000000000000000000000000000179052516200096690620010a2565b620009739291906200124a565b604051809103906000f08015801562000990573d6000803e3d6000fd5b506001600160a01b0380821660009081526067602052604090819020805460ff191660011790555191925084811691908616907f0a5c393ff07b91251e4d0dc2850f2c7275ebdfb20afd3b0eebda944b9804ae2790620009f290859062001213565b60405180910390a39392505050565b60008281526033602052604090206002015462000a22906200029062000ad9565b620004d95760405162461bcd60e51b815260040180806020018281038252603081526020018062003a716030913960400191505060405180910390fd5b62000a69620010b0565b506001600160a01b03166000908152606560209081526040918290208251608081018452905460ff8082161515835261010082041615159282019290925267ffffffffffffffff6201000083048116938201939093526a0100000000000000000000909104909116606082015290565b3390565b62000ae88162000d19565b62000b075760405162461bcd60e51b81526004016200038990620012c5565b606680546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b600082815260336020526040902062000b60908262000d1f565b156200047a5762000b7062000ad9565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260336020526040902062000bce908262000d36565b156200047a5762000bde62000ad9565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600062000c2f3062000d19565b15905090565b600054610100900460ff168062000c51575062000c5162000c22565b8062000c60575060005460ff16155b62000c9d5760405162461bcd60e51b815260040180806020018281038252602e81526020018062003aa1602e913960400191505060405180910390fd5b600054610100900460ff1615801562000cc9576000805460ff1961ff0019909116610100171660011790555b62000cd362000d4d565b62000cdd62000d4d565b6200066662000df5565b600062000696838362000f04565b600062000696836001600160a01b03841662000f6b565b6000620006998262000f83565b3b151590565b600062000696836001600160a01b03841662000f87565b600062000696836001600160a01b03841662000fd6565b600054610100900460ff168062000d69575062000d6962000c22565b8062000d78575060005460ff16155b62000db55760405162461bcd60e51b815260040180806020018281038252602e81526020018062003aa1602e913960400191505060405180910390fd5b600054610100900460ff1615801562000666576000805460ff1961ff001990911661010017166001179055801562000679576000805461ff001916905550565b600054610100900460ff168062000e11575062000e1162000c22565b8062000e20575060005460ff16155b62000e5d5760405162461bcd60e51b815260040180806020018281038252602e81526020018062003aa1602e913960400191505060405180910390fd5b600054610100900460ff1615801562000e89576000805460ff1961ff0019909116610100171660011790555b62000e9f600062000e9962000ad9565b6200046e565b62000ece7f4a0dd322941a79e91b8bc2de0d3eb943ea81e07d00f71bb32ad8b6fc1b60386662000e9962000ad9565b6200066660405162000ee090620010d7565b604051809103906000f08015801562000efd573d6000803e3d6000fd5b5062000add565b8154600090821062000f485760405162461bcd60e51b815260040180806020018281038252602281526020018062003a206022913960400191505060405180910390fd5b82600001828154811062000f5857fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b600062000f95838362000f6b565b62000fcd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000699565b50600062000699565b600081815260018301602052604081205480156200109757835460001980830191908101906000908790839081106200100b57fe5b90600052602060002001549050808760000184815481106200102957fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806200105a57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505062000699565b600091505062000699565b61086080620013c583390190565b60408051608081018252600080825260208201819052918101829052606081019190915290565b611dfb8062001c2583390190565b80356001600160a01b03811681146200040b57600080fd5b803567ffffffffffffffff811681146200040b57600080fd5b60006020828403121562001128578081fd5b6200069682620010e5565b6000806040838503121562001146578081fd5b6200115183620010e5565b91506200116160208401620010e5565b90509250929050565b6000806000606084860312156200117f578081fd5b6200118a84620010e5565b92506200119a60208501620010fd565b9150620011aa60408501620010fd565b90509250925092565b600060208284031215620011c5578081fd5b5035919050565b60008060408385031215620011df578182fd5b823591506200116160208401620010e5565b6000806040838503121562001204578182fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006001600160a01b038416825260206040818401528351806040850152825b8181101562001288578581018301518582016060015282016200126a565b818111156200129a5783606083870101525b50601f01601f191692909201606001949350505050565b901515815260200190565b90815260200190565b6020808252600e908201527f6e6f74206120636f6e7472616374000000000000000000000000000000000000604082015260600190565b60208082526004908201527f726f6c6500000000000000000000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f616c6c207465726d696e61746564000000000000000000000000000000000000604082015260600190565b81511515815260208083015115159082015260408083015167ffffffffffffffff90811691830191909152606092830151169181019190915260800190565b67ffffffffffffffff9283168152911660208201526040019056fe60806040526040516108603803806108608339818101604052604081101561002657600080fd5b81516020830180516040519294929383019291908464010000000082111561004d57600080fd5b90830190602082018581111561006257600080fd5b825164010000000081118282018810171561007c57600080fd5b82525081516020918201929091019080838360005b838110156100a9578181015183820152602001610091565b50505050905090810190601f1680156100d65780820380516001836020036101000a031916815260200191505b50604052506100e3915050565b6100ed82826100f4565b505061047f565b6101078261024960201b6100311760201c565b6101425760405162461bcd60e51b81526004018080602001828103825260258152602001806107e16025913960400191505060405180910390fd5b6101ba826001600160a01b0316635c60da1b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561017e57600080fd5b505afa158015610192573d6000803e3d6000fd5b505050506040513d60208110156101a857600080fd5b5051610249602090811b61003117901c565b6101f55760405162461bcd60e51b815260040180806020018281038252603481526020018061082c6034913960400191505060405180910390fd5b6000805160206107a08339815191528281558151156102445761024261021961024f565b836040518060600160405280602181526020016107c0602191396102c260201b6100371760201c565b505b505050565b3b151590565b60006102596103c8565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60208110156102bb57600080fd5b5051905090565b60606102cd84610249565b6103085760405162461bcd60e51b81526004018080602001828103825260268152602001806108066026913960400191505060405180910390fd5b60006060856001600160a01b0316856040518082805190602001908083835b602083106103465780518252601f199092019160209182019101610327565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146103a6576040519150601f19603f3d011682016040523d82523d6000602084013e6103ab565b606091505b5090925090506103bc8282866103db565b925050505b9392505050565b6000805160206107a08339815191525490565b606083156103ea5750816103c1565b8251156103fa5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561044457818101518382015260200161042c565b50505050905090810190601f1680156104715780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6103128061048e6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f61002f565b61002f61002a610149565b6101c9565b565b3b151590565b606061004284610031565b61007d5760405162461bcd60e51b81526004018080602001828103825260268152602001806102b76026913960400191505060405180910390fd5b600060608573ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b602083106100c85780518252601f1990920191602091820191016100a9565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610128576040519150601f19603f3d011682016040523d82523d6000602084013e61012d565b606091505b509150915061013d8282866101ed565b925050505b9392505050565b6000610153610291565b73ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561019857600080fd5b505afa1580156101ac573d6000803e3d6000fd5b505050506040513d60208110156101c257600080fd5b5051905090565b3660008037600080366000845af43d6000803e8080156101e8573d6000f35b3d6000fd5b606083156101fc575081610142565b82511561020c5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561025657818101518382015260200161023e565b50505050905090810190601f1680156102835780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50549056fe416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6e7472616374a2646970667358221220d94471f5aabfe1bb1164ce982a8b144c1527f912d479a8fe8af7110e0547ffd764736f6c63430007040033a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50426561636f6e50726f78793a2066756e6374696f6e2063616c6c206661696c6564426561636f6e50726f78793a20626561636f6e206973206e6f74206120636f6e7472616374416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6e7472616374426561636f6e50726f78793a20626561636f6e20696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374608060405234801561001057600080fd5b50611ddb806100206000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c8063b7e86c1f116100b2578063d1cc997611610081578063f0b793bd11610066578063f0b793bd146101e9578063f7a30806146101fc578063fa2a89971461020f5761011b565b8063d1cc9976146101d9578063d8dfeb45146101e15761011b565b8063b7e86c1f146101a1578063c0c53b8b146101b6578063c3c68298146101c9578063ccbdbee2146101d15761011b565b80634e56c57a116100ee5780634e56c57a14610172578063665a11ca1461017a5780637158da7c1461018257806386d1a69f146101975761011b565b80630e222f9b146101205780631aa3a0081461013f57806333a412a51461015457806346d8cf3f1461016a575b600080fd5b610128610217565b604051610136929190611974565b60405180910390f35b610147610251565b6040516101369190611938565b61015c610260565b604051610136929190611957565b61014761027d565b61015c61028c565b6101476102a9565b61018a6102b8565b6040516101369190611982565b61019f610357565b005b6101a96103fc565b604051610136919061194c565b61019f6101c43660046116e2565b610493565b610147610543565b610128610557565b6101a9610726565b61018a610804565b61019f6101f73660046116c6565b610862565b61019f61020a3660046117fd565b610946565b6101a9610ab7565b600080610222610726565b61022e5761022e610ac0565b5050603654601781810b900b90600160c01b900467ffffffffffffffff165b9091565b6033546001600160a01b031681565b603754601781900b90600160c01b900467ffffffffffffffff1682565b6035546001600160a01b031681565b603654601781900b90600160c01b900467ffffffffffffffff1682565b6034546001600160a01b031681565b603554604080517f7158da7c00000000000000000000000000000000000000000000000000000000815290516060926001600160a01b031691637158da7c916004808301926000929190829003018186803b15801561031657600080fd5b505afa15801561032a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103529190810190611838565b905090565b60385461010090046001600160a01b0316610370610c7f565b6001600160a01b03161461039f5760405162461bcd60e51b815260040161039690611bdb565b60405180910390fd5b6103a7610726565b156103c45760405162461bcd60e51b815260040161039690611ba4565b6038805460ff191660011790556040517f20d29efe076941f73e5574acb023c424d63cd6d3d12eb5ac3108a5eaf177daed90600090a1565b603554604080517fb7e86c1f00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163b7e86c1f91600480830192602092919082900301818787803b15801561045b57600080fd5b505af115801561046f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610352919061172c565b600054610100900460ff16806104ac57506104ac610c83565b806104ba575060005460ff16155b6104f55760405162461bcd60e51b815260040180806020018281038252602e815260200180611d07602e913960400191505060405180910390fd5b600054610100900460ff16158015610520576000805460ff1961ff0019909116610100171660011790555b61052b848484610c94565b801561053d576000805461ff00191690555b50505050565b60385461010090046001600160a01b031681565b6000806000610564610726565b90508061057357610573610ac0565b603654601790810b900b6000826105935761058c610d34565b90506105be565b6037546036546105bb9167ffffffffffffffff600160c01b9283900481169290910416610d38565b90505b6105c6611566565b603354603554604051630e4bd63d60e41b81526001600160a01b039283169263e4bd63d0926105fa92911690600401611938565b60806040518083038186803b15801561061257600080fd5b505afa158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a91906118c2565b606081015160375491925067ffffffffffffffff908116600160c01b9092041601808310158061067c575060385460ff165b156106af5760365484906106a190600160c01b900467ffffffffffffffff1685610d38565b96509650505050505061024d565b60408201516000906106cb9067ffffffffffffffff1686610d53565b603754909150601790810b900b6106ec6106e58784610d88565b8290610ded565b90506107026106fb8784610dfc565b8290610e61565b603754909a600160c01b90910467ffffffffffffffff169950975050505050505050565b60335460355460405163134ca1fb60e31b81526000926001600160a01b0390811692639a650fd89261075e9290911690600401611938565b60206040518083038186803b15801561077657600080fd5b505afa15801561078a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ae919061172c565b806103525750603560009054906101000a90046001600160a01b03166001600160a01b031663d1cc99766040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561045b57600080fd5b603554604080517fd8dfeb4500000000000000000000000000000000000000000000000000000000815290516060926001600160a01b03169163d8dfeb45916004808301926000929190829003018186803b15801561031657600080fd5b61086a610e71565b6001600160a01b031661087b610c7f565b6001600160a01b0316146108a15760405162461bcd60e51b815260040161039690611a5a565b6038546001600160a01b038281166101009092041614156108d45760405162461bcd60e51b815260040161039690611c49565b603880547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101006001600160a01b038416021790556040517fd2153930bfb50c02e848f1c25f9e1679c08ead0f57c36d10a25431b5575c223e9061093b908390611938565b60405180910390a150565b60385461010090046001600160a01b031661095f610c7f565b6001600160a01b0316146109855760405162461bcd60e51b815260040161039690611bdb565b600081136109a55760405162461bcd60e51b815260040161039690611a23565b6109ad610726565b156109ca5760405162461bcd60e51b815260040161039690611ba4565b60006109d4610d34565b905060405180604001604052806109ea84610f45565b60170b81526020016109fb83610fb2565b67ffffffffffffffff9081169091528151603780546020909401517fffffffffffffffff00000000000000000000000000000000000000000000000090941677ffffffffffffffffffffffffffffffffffffffffffffffff60179390930b831617909116600160c01b93909216929092021790556038805460ff191690556040517fda577f919948e50d25df312cc4eaf16144bb88caf80212d25812180f632f1a7190610aab9084908490611974565b60405180910390a15050565b60385460ff1681565b603554604080517f0e222f9b000000000000000000000000000000000000000000000000000000008152815160009384936001600160a01b0390911692630e222f9b926004808301939282900301818787803b158015610b1f57600080fd5b505af1158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b579190611815565b9150915060008213610b7b5760405162461bcd60e51b815260040161039690611c12565b60008111610b9b5760405162461bcd60e51b815260040161039690611aff565b603654600160c01b900467ffffffffffffffff16811015610bce5760405162461bcd60e51b815260040161039690611ac8565b610be0610bd9610d34565b8290610ffb565b90506040518060400160405280610bf684610f45565b60170b8152602001610c0783610fb2565b67ffffffffffffffff9081169091528151603680546020909401517fffffffffffffffff00000000000000000000000000000000000000000000000090941677ffffffffffffffffffffffffffffffffffffffffffffffff60179390930b831617909116600160c01b93909216929092021790555050565b3390565b6000610c8e3061100a565b15905090565b600054610100900460ff1680610cad5750610cad610c83565b80610cbb575060005460ff16155b610cf65760405162461bcd60e51b815260040180806020018281038252602e815260200180611d07602e913960400191505060405180910390fd5b600054610100900460ff16158015610d21576000805460ff1961ff0019909116610100171660011790555b610d29611010565b61052b8484846110b2565b4290565b600081831015610d485781610d4a565b825b90505b92915050565b6000670de0b6b3a7640000610d79610d6b8585611422565b670de0b6b3a76400006114e7565b81610d8057fe5b059392505050565b6000828201818312801590610d9d5750838112155b80610db25750600083128015610db257508381125b610d4a5760405162461bcd60e51b8152600401808060200182810382526021815260200180611ce66021913960400191505060405180910390fd5b6000818312610d485781610d4a565b6000818303818312801590610e115750838113155b80610e265750600083128015610e2657508381135b610d4a5760405162461bcd60e51b8152600401808060200182810382526024815260200180611d826024913960400191505060405180910390fd5b600081831215610d485781610d4a565b6000610e7b61158d565b610e836115ab565b603460009054906101000a90046001600160a01b03166001600160a01b0316630cdc105a6040518163ffffffff1660e01b81526004016102806040518083038186803b158015610ed257600080fd5b505afa158015610ee6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0a9190611746565b91955090935083925060039150610f1e9050565b6020020151610f2b610d34565b1115610f38576000610f3e565b60208201515b9250505090565b60007fffffffffffffffff8000000000000000000000000000000000000000000000008212158015610f8e57507780000000000000000000000000000000000000000000000082125b610faa5760405162461bcd60e51b815260040161039690611b6d565b50805b919050565b6000680100000000000000008210610faa5760405162461bcd60e51b8152600401808060200182810382526026815260200180611d356026913960400191505060405180910390fd5b6000818310610d485781610d4a565b3b151590565b600054610100900460ff16806110295750611029610c83565b80611037575060005460ff16155b6110725760405162461bcd60e51b815260040180806020018281038252602e815260200180611d07602e913960400191505060405180910390fd5b600054610100900460ff1615801561109d576000805460ff1961ff0019909116610100171660011790555b80156110af576000805461ff00191690555b50565b600054610100900460ff16806110cb57506110cb610c83565b806110d9575060005460ff16155b6111145760405162461bcd60e51b815260040180806020018281038252602e815260200180611d07602e913960400191505060405180910390fd5b600054610100900460ff1615801561113f576000805460ff1961ff0019909116610100171660011790555b6111488461100a565b6111645760405162461bcd60e51b8152600401610396906119ec565b61116d8361100a565b6111895760405162461bcd60e51b8152600401610396906119ec565b603380546001600160a01b038087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556034805486841690831617905560358054928516929091169190911790556111e6611566565b603354603554604051630e4bd63d60e41b81526001600160a01b039283169263e4bd63d09261121a92911690600401611938565b60806040518083038186803b15801561123257600080fd5b505afa158015611246573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126a91906118c2565b805190915061128b5760405162461bcd60e51b815260040161039690611a91565b6000611295610e71565b6001600160a01b031614156112bc5760405162461bcd60e51b8152600401610396906119b5565b60335460355460405163134ca1fb60e31b81526001600160a01b0392831692639a650fd8926112f092911690600401611938565b60206040518083038186803b15801561130857600080fd5b505afa15801561131c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611340919061172c565b1561135d5760405162461bcd60e51b815260040161039690611ba4565b603560009054906101000a90046001600160a01b03166001600160a01b031663d1cc99766040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156113ad57600080fd5b505af11580156113c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e5919061172c565b156114025760405162461bcd60e51b815260040161039690611b36565b61140a610ac0565b50801561053d576000805461ff001916905550505050565b60008261143157506000610d4d565b8260001914801561146157507f800000000000000000000000000000000000000000000000000000000000000082145b1561149d5760405162461bcd60e51b8152600401808060200182810382526027815260200180611d5b6027913960400191505060405180910390fd5b828202828482816114aa57fe5b0514610d4a5760405162461bcd60e51b8152600401808060200182810382526027815260200180611d5b6027913960400191505060405180910390fd5b600080821361153d576040805162461bcd60e51b815260206004820152601f60248201527f726f756e6448616c665570206f6e6c7920737570706f7274732079203e203000604482015290519081900360640190fd5b60008312611559576115528360028405610d88565b9050610d4d565b610d4a8360028405610dfc565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518060e001604052806007906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b600082601f8301126115d9578081fd5b60405160a0810181811067ffffffffffffffff821117156115f657fe5b6040529050808260a0810185101561160d57600080fd5b60005b600581101561162f578151835260209283019290910190600101611610565b50505092915050565b600082601f830112611648578081fd5b60405160c0810181811067ffffffffffffffff8211171561166557fe5b6040529050808260c0810185101561167c57600080fd5b60005b600681101561162f57815183526020928301929091019060010161167f565b80518015158114610fad57600080fd5b805167ffffffffffffffff81168114610fad57600080fd5b6000602082840312156116d7578081fd5b8135610d4a81611cd0565b6000806000606084860312156116f6578182fd5b833561170181611cd0565b9250602084013561171181611cd0565b9150604084013561172181611cd0565b809150509250925092565b60006020828403121561173d578081fd5b610d4a8261169e565b6000806000806000610280868803121561175e578081fd5b6117678661169e565b9450602061177681880161169e565b945087605f880112611786578182fd5b61179060e0611c80565b80604089016101208a018b8111156117a6578586fd5b855b60078110156117ce5782516117bc81611cd0565b855293850193918501916001016117a8565b508297506117dc8c826115c9565b965050505050506117f1876101c08801611638565b90509295509295909350565b60006020828403121561180e578081fd5b5035919050565b60008060408385031215611827578182fd5b505080516020909101519092909150565b600060208284031215611849578081fd5b815167ffffffffffffffff80821115611860578283fd5b818401915084601f830112611873578283fd5b81518181111561187f57fe5b611892601f8201601f1916602001611c80565b91508082528560208285010111156118a8578384fd5b6118b9816020840160208601611ca4565b50949350505050565b6000608082840312156118d3578081fd5b6040516080810181811067ffffffffffffffff821117156118f057fe5b6040526118fc8361169e565b815261190a6020840161169e565b602082015261191b604084016116ae565b604082015261192c606084016116ae565b60608201529392505050565b6001600160a01b0391909116815260200190565b901515815260200190565b60179290920b825267ffffffffffffffff16602082015260400190565b918252602082015260400190565b60006020825282518060208401526119a1816040850160208701611ca4565b601f01601f19169190910160400192915050565b6020808252600b908201527f6e6f206f70657261746f72000000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6e6f74206120636f6e7472616374000000000000000000000000000000000000604082015260600190565b6020808252600a908201527f7072696365203c3d203000000000000000000000000000000000000000000000604082015260600190565b6020808252600d908201527f6f6e6c79204f70657261746f7200000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6e6f742072656769737465726564000000000000000000000000000000000000604082015260600190565b60208082526016908201527f65787465726e616c2074696d6520726576657273656400000000000000000000604082015260600190565b60208082526011908201527f65787465726e616c2074696d65203d2030000000000000000000000000000000604082015260600190565b60208082526013908201527f65787465726e616c207465726d696e6174656400000000000000000000000000604082015260600190565b60208082526015908201527f63616e206e6f742066697420696e20696e743139320000000000000000000000604082015260600190565b6020808252600a908201527f7465726d696e6174656400000000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6f6e6c792046696e6554756e6572000000000000000000000000000000000000604082015260600190565b60208082526013908201527f65787465726e616c207072696365203c3d203000000000000000000000000000604082015260600190565b6020808252600b908201527f616c726561647920736574000000000000000000000000000000000000000000604082015260600190565b60405181810167ffffffffffffffff81118282101715611c9c57fe5b604052919050565b60005b83811015611cbf578181015183820152602001611ca7565b8381111561053d5750506000910152565b6001600160a01b03811681146110af57600080fdfe5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f77496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a656453616665436173743a2076616c756520646f65736e27742066697420696e20363420626974735369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f77a26469706673582212208f49098a7a89c7774ce8d1260a012682bb9bde8562d0c9bd5af742b2186b89b564736f6c63430007040033456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e74416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b65496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a2646970667358221220a93e8f9c22fc734e0d94e82a65801d8212f88150d88e80d77272c1f9f7e5511364736f6c63430007040033

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.