Contract 0x61a00cef1802e297b10bbe66a5719a420ec43cae

Contract Overview

Balance:
0 BNB
Txn Hash
Block
From
To
Value [Txn Fee]
0x2c426629d4c35f8ed47a5e29c8d3d1578b1fedf2ddd494f7cb71f833508a994083973342021-04-29 7:43:1344 days 2 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.03051178
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:0215 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:0215 days 2 hrs ago 0xcf2a666f3fb43269159308497319e7c8db76b14e 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:5915 days 2 hrs ago 0x26bf9e3697d3dfc2bdd69b7467a1747bd91733fc 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
0xf20c981e6b31b8960e12b35fcb457972df124edc4e565af149e9e6a1aab38c8f92315782021-05-28 7:59:0515 days 2 hrs ago 0x53a0fc7ffb551c940f3002ab3dab253fd9ba6bb7 0x61a00cef1802e297b10bbe66a5719a420ec43cae0 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ExchangeState

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at BscScan.com on 2021-04-29
*/

// File: @openzeppelin\contracts-upgradeable\math\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, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

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

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

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: node_modules\@openzeppelin\contracts-upgradeable\proxy\Initializable.sol


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


/**
 * @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) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        // solhint-disable-next-line no-inline-assembly
        assembly { cs := extcodesize(self) }
        return cs == 0;
    }
}

// File: node_modules\@openzeppelin\contracts-upgradeable\GSN\ContextUpgradeable.sol


pragma solidity >=0.6.0 <0.8.0;


/*
 * @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: @openzeppelin\contracts-upgradeable\access\OwnableUpgradeable.sol


pragma solidity >=0.6.0 <0.8.0;


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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

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

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

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

// File: contracts\utils\DecimalMath.sol

pragma solidity ^0.6.12;


/// @dev Implements simple fixed point math add, sub, mul and div operations.
/// @author Alberto Cuesta Cañada
library DecimalMath {
    using SafeMathUpgradeable for uint256;

    /// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
    function unit(uint8 decimals) internal pure returns (uint256) {
        return 10**uint256(decimals);
    }

    /// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
    function addd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.add(y);
    }

    /// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
    function subd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.sub(y);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
    function muld(uint256 x, uint256 y) internal pure returns (uint256) {
        return muld(x, y, 18);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
    function muld(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(y).div(unit(decimals));
    }

    /// @dev Divides x between y, assuming they are both fixed point with 18 digits.
    function divd(uint256 x, uint256 y) internal pure returns (uint256) {
        return divd(x, y, 18);
    }

    /// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
    function divd(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(unit(decimals)).div(y);
    }
}

// File: contracts\utils\Decimal.sol

pragma solidity ^0.6.12;



library Decimal {
    using DecimalMath for uint256;
    using SafeMathUpgradeable for uint256;

    struct decimal {
        uint256 d;
    }

    function zero() internal pure returns (decimal memory) {
        return decimal(0);
    }

    function one() internal pure returns (decimal memory) {
        return decimal(DecimalMath.unit(18));
    }

    function toUint(decimal memory x) internal pure returns (uint256) {
        return x.d;
    }

    function modD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        return decimal(x.d.mul(DecimalMath.unit(18)) % y.d);
    }

    function cmp(decimal memory x, decimal memory y) internal pure returns (int8) {
        if (x.d > y.d) {
            return 1;
        } else if (x.d < y.d) {
            return -1;
        }
        return 0;
    }

    /// @dev add two decimals
    function addD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.add(y.d);
        return t;
    }

    /// @dev subtract two decimals
    function subD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.sub(y.d);
        return t;
    }

    /// @dev multiple two decimals
    function mulD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.muld(y.d);
        return t;
    }

    /// @dev multiple a decimal by a uint256
    function mulScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.mul(y);
        return t;
    }

    /// @dev divide two decimals
    function divD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.divd(y.d);
        return t;
    }

    /// @dev divide a decimal by a uint256
    function divScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.div(y);
        return t;
    }
}

// File: @openzeppelin\contracts-upgradeable\math\SignedSafeMathUpgradeable.sol


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: contracts\utils\SignedDecimalMath.sol

pragma solidity ^0.6.12;


/// @dev Implements simple signed fixed point math add, sub, mul and div operations.
library SignedDecimalMath {
    using SignedSafeMathUpgradeable for int256;

    /// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
    function unit(uint8 decimals) internal pure returns (int256) {
        return int256(10**uint256(decimals));
    }

    /// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
    function addd(int256 x, int256 y) internal pure returns (int256) {
        return x.add(y);
    }

    /// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
    function subd(int256 x, int256 y) internal pure returns (int256) {
        return x.sub(y);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
    function muld(int256 x, int256 y) internal pure returns (int256) {
        return muld(x, y, 18);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
    function muld(
        int256 x,
        int256 y,
        uint8 decimals
    ) internal pure returns (int256) {
        return x.mul(y).div(unit(decimals));
    }

    /// @dev Divides x between y, assuming they are both fixed point with 18 digits.
    function divd(int256 x, int256 y) internal pure returns (int256) {
        return divd(x, y, 18);
    }

    /// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
    function divd(
        int256 x,
        int256 y,
        uint8 decimals
    ) internal pure returns (int256) {
        return x.mul(unit(decimals)).div(y);
    }
}

// File: contracts\utils\SignedDecimal.sol

pragma solidity ^0.6.12;




library SignedDecimal {
    using SignedDecimalMath for int256;
    using SignedSafeMathUpgradeable for int256;

    struct signedDecimal {
        int256 d;
    }

    function zero() internal pure returns (signedDecimal memory) {
        return signedDecimal(0);
    }

    function toInt(signedDecimal memory x) internal pure returns (int256) {
        return x.d;
    }

    function isNegative(signedDecimal memory x) internal pure returns (bool) {
        if (x.d < 0) {
            return true;
        }
        return false;
    }

    function abs(signedDecimal memory x) internal pure returns (Decimal.decimal memory) {
        Decimal.decimal memory t;
        if (x.d < 0) {
            t.d = uint256(0 - x.d);
        } else {
            t.d = uint256(x.d);
        }
        return t;
    }

    /// @dev add two decimals
    function addD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.add(y.d);
        return t;
    }

    /// @dev subtract two decimals
    function subD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.sub(y.d);
        return t;
    }

    /// @dev multiple two decimals
    function mulD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.muld(y.d);
        return t;
    }

    /// @dev multiple a signedDecimal by a int256
    function mulScalar(signedDecimal memory x, int256 y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.mul(y);
        return t;
    }

    /// @dev divide two decimals
    function divD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.divd(y.d);
        return t;
    }

    /// @dev divide a signedDecimal by a int256
    function divScalar(signedDecimal memory x, int256 y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.div(y);
        return t;
    }
}

// File: contracts\types\IExchangeTypes.sol

pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;



interface IExchangeTypes {
    /**
     * @notice asset direction, used in getInputPrice, getOutputPrice, swapInput and swapOutput
     * @param ADD_TO_AMM add asset to Amm
     * @param REMOVE_FROM_AMM remove asset from Amm
     */
    enum Dir {ADD_TO_AMM, REMOVE_FROM_AMM}

    struct LiquidityChangedSnapshot {
        SignedDecimal.signedDecimal cumulativeNotional;
        // the base/quote reserve of amm right before liquidity changed
        Decimal.decimal quoteAssetReserve;
        Decimal.decimal baseAssetReserve;
        // total position size owned by amm after last snapshot taken
        // `totalPositionSize` = currentBaseAssetReserve - lastLiquidityChangedHistoryItem.baseAssetReserve + prevTotalPositionSize
        SignedDecimal.signedDecimal totalPositionSize;
    }
}

// File: contracts\types\ISakePerpVaultTypes.sol

pragma solidity ^0.6.12;

interface ISakePerpVaultTypes {
    /**
     * @notice pool types
     * @param HIGH high risk pool
     * @param LOW low risk pool
     */
    enum Risk {HIGH, LOW}
}

// File: node_modules\@openzeppelin\contracts-upgradeable\token\ERC20\IERC20Upgradeable.sol


pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

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

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



// File: @openzeppelin\contracts-upgradeable\token\ERC20\ERC20Upgradeable.sol


pragma solidity >=0.6.0 <0.8.0;





/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {
    using SafeMathUpgradeable for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
        __Context_init_unchained();
        __ERC20_init_unchained(name_, symbol_);
    }

    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
    uint256[44] private __gap;
}

// File: contracts\MMLPToken.sol

pragma solidity ^0.6.12;



contract MMLPToken is ERC20Upgradeable, OwnableUpgradeable {
    constructor(string memory _name, string memory _symbol) public {
        __ERC20_init(_name, _symbol);
        __Ownable_init();
    }

    function mint(address _account, uint256 _amount) external onlyOwner {
        _mint(_account, _amount);
    }

    function burn(address _account, uint256 _amount) external onlyOwner {
        _burn(_account, _amount);
    }
}

// File: contracts\interface\IExchangeState.sol

pragma solidity ^0.6.12;


interface IExchangeState {
    function getMaxHoldingBaseAsset() external view returns (Decimal.decimal memory);

    function getOpenInterestNotionalCap() external view returns (Decimal.decimal memory);

    function initMarginRatio() external view returns (Decimal.decimal memory);

    function maintenanceMarginRatio() external view returns (Decimal.decimal memory);

    function liquidationFeeRatio() external view returns (Decimal.decimal memory);

    function maxLiquidationFee() external view returns (Decimal.decimal memory);

    function spreadRatio() external view returns (Decimal.decimal memory);

    function maxOracleSpreadRatio() external view returns (Decimal.decimal memory);

    function getInputPriceWithReserves(
        IExchangeTypes.Dir _dir,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) external pure returns (Decimal.decimal memory);

    function getOutputPriceWithReserves(
        IExchangeTypes.Dir _dir,
        Decimal.decimal memory _baseAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) external pure returns (Decimal.decimal memory);

    function calcFee(Decimal.decimal calldata _quoteAssetAmount) external view returns (Decimal.decimal memory);

    function mint(
        ISakePerpVaultTypes.Risk _level,
        address account,
        uint256 amount
    ) external;

    function burn(
        ISakePerpVaultTypes.Risk _level,
        address account,
        uint256 amount
    ) external;

    function getLPToken(ISakePerpVaultTypes.Risk _level) external view returns (MMLPToken);
}

// File: contracts\interface\IExchange.sol

pragma solidity ^0.6.12;

interface IExchange is IExchangeTypes {
    function swapInput(
        Dir _dir,
        Decimal.decimal calldata _quoteAssetAmount,
        Decimal.decimal calldata _baseAssetAmountLimit
    ) external returns (Decimal.decimal memory);

    function swapOutput(
        Dir _dir,
        Decimal.decimal calldata _baseAssetAmount,
        Decimal.decimal calldata _quoteAssetAmountLimit,
        bool _skipFluctuationCheck
    ) external returns (Decimal.decimal memory);

    function migrateLiquidity(Decimal.decimal calldata _liquidityMultiplier, Decimal.decimal calldata _priceLimitRatio)
        external;

    function shutdown() external;

    function settleFunding() external returns (SignedDecimal.signedDecimal memory);

    function calcFee(Decimal.decimal calldata _quoteAssetAmount) external view returns (Decimal.decimal memory);

    function calcBaseAssetAfterLiquidityMigration(
        SignedDecimal.signedDecimal memory _baseAssetAmount,
        Decimal.decimal memory _fromQuoteReserve,
        Decimal.decimal memory _fromBaseReserve
    ) external view returns (SignedDecimal.signedDecimal memory);

    function getInputTwap(Dir _dir, Decimal.decimal calldata _quoteAssetAmount)
        external
        view
        returns (Decimal.decimal memory);

    function getOutputTwap(Dir _dir, Decimal.decimal calldata _baseAssetAmount)
        external
        view
        returns (Decimal.decimal memory);

    function getInputPrice(Dir _dir, Decimal.decimal calldata _quoteAssetAmount)
        external
        view
        returns (Decimal.decimal memory);

    function getOutputPrice(Dir _dir, Decimal.decimal calldata _baseAssetAmount)
        external
        view
        returns (Decimal.decimal memory);

    function getInputPriceWithReserves(
        Dir _dir,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) external view returns (Decimal.decimal memory);

    function getOutputPriceWithReserves(
        Dir _dir,
        Decimal.decimal memory _baseAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) external view returns (Decimal.decimal memory);

    function getSpotPrice() external view returns (Decimal.decimal memory);

    function getLiquidityHistoryLength() external view returns (uint256);

    // overridden by state variable
    function quoteAsset() external view returns (IERC20Upgradeable);

    function open() external view returns (bool);

    // can not be overridden by state variable due to type `Deciaml.decimal`
    function getSettlementPrice() external view returns (Decimal.decimal memory);

    function getCumulativeNotional() external view returns (SignedDecimal.signedDecimal memory);

    function getMaxHoldingBaseAsset() external view returns (Decimal.decimal memory);

    function getOpenInterestNotionalCap() external view returns (Decimal.decimal memory);

    function getLiquidityChangedSnapshots(uint256 i) external view returns (LiquidityChangedSnapshot memory);

    function mint(
        ISakePerpVaultTypes.Risk _level,
        address account,
        uint256 amount
    ) external;

    function burn(
        ISakePerpVaultTypes.Risk _level,
        address account,
        uint256 amount
    ) external;

    function getMMUnrealizedPNL(Decimal.decimal memory _baseAssetReserve, Decimal.decimal memory _quoteAssetReserve)
        external
        view
        returns (SignedDecimal.signedDecimal memory);

    function moveAMMPriceToOracle(uint256 _oraclePrice, bytes32 _priceFeedKey) external;

    function setPriceFeed(address _priceFeed) external;

    function getReserve() external view returns (Decimal.decimal memory, Decimal.decimal memory);

    function initMarginRatio() external view returns (Decimal.decimal memory);

    function maintenanceMarginRatio() external view returns (Decimal.decimal memory);

    function liquidationFeeRatio() external view returns (Decimal.decimal memory);

    function maxLiquidationFee() external view returns (Decimal.decimal memory);

    function spreadRatio() external view returns (Decimal.decimal memory);

    function priceFeedKey() external view returns (bytes32);

    function tradeLimitRatio() external view returns (uint256);

    function priceAdjustRatio() external view returns (uint256);

    function fluctuationLimitRatio() external view returns (uint256);

    function fundingPeriod() external view returns (uint256);

    function adjustTotalPosition(
        SignedDecimal.signedDecimal memory adjustedPosition,
        SignedDecimal.signedDecimal memory oldAdjustedPosition
    ) external;

    function getTotalPositionSize() external view returns (SignedDecimal.signedDecimal memory);

    function exchangeState() external view returns (IExchangeState);

    function getUnderlyingPrice() external view returns (Decimal.decimal memory);

    function isOverSpreadLimit() external view returns (bool);
}

// File: contracts\interface\ISakePerpVault.sol

pragma solidity ^0.6.12;

interface ISakePerpVault is ISakePerpVaultTypes {
    function withdraw(
        IExchange _exchange,
        address _receiver,
        Decimal.decimal memory _amount
    ) external;

    function realizeBadDebt(IExchange _exchange, Decimal.decimal memory _badDebt) external;

    function modifyLiquidity() external;

    function getMMLiquidity(address _exchange, Risk _risk) external view returns (SignedDecimal.signedDecimal memory);

    function getAllMMLiquidity(address _exchange)
        external
        view
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory);

    function getTotalMMLiquidity(address _exchange) external view returns (SignedDecimal.signedDecimal memory);

    function getTotalMMAvailableLiquidity(address _exchange) external view returns (SignedDecimal.signedDecimal memory);

    function getTotalLpUnrealizedPNL(IExchange _exchange) external view returns (SignedDecimal.signedDecimal memory);

    function addCachedLiquidity(address _exchange, Decimal.decimal memory _DeltalpLiquidity) external;

    function requireMMNotBankrupt(address _exchange) external;

    function getMMCachedLiquidity(address _exchange, Risk _risk) external view returns (Decimal.decimal memory);

    function getTotalMMCachedLiquidity(address _exchange) external view returns (Decimal.decimal memory);

    function setHighRiskLiquidityWeight(address _exchange, uint256 _weight) external;

    function setMaxLoss(
        address _exchange,
        Risk _risk,
        uint256 _max
    ) external;
}

// File: contracts\utils\MixedDecimal.sol
pragma solidity ^0.6.12;

/// @dev To handle a signedDecimal add/sub/mul/div a decimal and provide convert decimal to signedDecimal helper
library MixedDecimal {
    using SignedDecimal for SignedDecimal.signedDecimal;
    using SignedSafeMathUpgradeable for int256;

    uint256 private constant _INT256_MAX = 2**255 - 1;
    string private constant ERROR_NON_CONVERTIBLE = "MixedDecimal: uint value is bigger than _INT256_MAX";

    modifier convertible(Decimal.decimal memory x) {
        require(_INT256_MAX >= x.d, ERROR_NON_CONVERTIBLE);
        _;
    }

    function fromDecimal(Decimal.decimal memory x)
        internal
        pure
        convertible(x)
        returns (SignedDecimal.signedDecimal memory)
    {
        return SignedDecimal.signedDecimal(int256(x.d));
    }

    function toUint(SignedDecimal.signedDecimal memory x) internal pure returns (uint256) {
        return x.abs().d;
    }

    /// @dev add SignedDecimal.signedDecimal and Decimal.decimal, using SignedSafeMath directly
    function addD(SignedDecimal.signedDecimal memory x, Decimal.decimal memory y)
        internal
        pure
        convertible(y)
        returns (SignedDecimal.signedDecimal memory)
    {
        SignedDecimal.signedDecimal memory t;
        t.d = x.d.add(int256(y.d));
        return t;
    }

    /// @dev subtract SignedDecimal.signedDecimal by Decimal.decimal, using SignedSafeMath directly
    function subD(SignedDecimal.signedDecimal memory x, Decimal.decimal memory y)
        internal
        pure
        convertible(y)
        returns (SignedDecimal.signedDecimal memory)
    {
        SignedDecimal.signedDecimal memory t;
        t.d = x.d.sub(int256(y.d));
        return t;
    }

    /// @dev multiple a SignedDecimal.signedDecimal by Decimal.decimal
    function mulD(SignedDecimal.signedDecimal memory x, Decimal.decimal memory y)
        internal
        pure
        convertible(y)
        returns (SignedDecimal.signedDecimal memory)
    {
        SignedDecimal.signedDecimal memory t;
        t = x.mulD(fromDecimal(y));
        return t;
    }

    /// @dev multiple a SignedDecimal.signedDecimal by a uint256
    function mulScalar(SignedDecimal.signedDecimal memory x, uint256 y)
        internal
        pure
        returns (SignedDecimal.signedDecimal memory)
    {
        require(_INT256_MAX >= y, ERROR_NON_CONVERTIBLE);
        SignedDecimal.signedDecimal memory t;
        t = x.mulScalar(int256(y));
        return t;
    }

    /// @dev divide a SignedDecimal.signedDecimal by a Decimal.decimal
    function divD(SignedDecimal.signedDecimal memory x, Decimal.decimal memory y)
        internal
        pure
        convertible(y)
        returns (SignedDecimal.signedDecimal memory)
    {
        SignedDecimal.signedDecimal memory t;
        t = x.divD(fromDecimal(y));
        return t;
    }

    /// @dev divide a SignedDecimal.signedDecimal by a uint256
    function divScalar(SignedDecimal.signedDecimal memory x, uint256 y)
        internal
        pure
        returns (SignedDecimal.signedDecimal memory)
    {
        require(_INT256_MAX >= y, ERROR_NON_CONVERTIBLE);
        SignedDecimal.signedDecimal memory t;
        t = x.divScalar(int256(y));
        return t;
    }
}

// File: contracts\ExchangeState.sol

pragma solidity ^0.6.12;

contract ExchangeState is IExchangeState, OwnableUpgradeable {
    using SafeMathUpgradeable for uint256;
    using Decimal for Decimal.decimal;
    using SignedDecimal for SignedDecimal.signedDecimal;
    using MixedDecimal for SignedDecimal.signedDecimal;

    event CapChanged(uint256 maxHoldingBaseAsset, uint256 openInterestNotionalCap);
    event InitMarginRatioChanged(uint256 initMarginRatio);
    event MaintenanceMarginRatioChanged(uint256 maintenanceMarginRatio);
    event LiquidationFeeRatioChanged(uint256 liquidationFeeRatio);
    event MaxLiquidationFeeChanged(uint256 maxliquidationFee);

    address public exchange;

    Decimal.decimal private _spreadRatio;
    Decimal.decimal private _maxHoldingBaseAsset;
    Decimal.decimal private _openInterestNotionalCap;
    Decimal.decimal private _initMarginRatio;
    Decimal.decimal private _maintenanceMarginRatio;
    Decimal.decimal private _liquidationFeeRatio;
    Decimal.decimal private _maxLiquidationFee;

    MMLPToken public HighRiskLPToken;
    MMLPToken public LowRiskLPToken;


    //**********************************************************//
    //    The above state variables can not change the order    //
    //**********************************************************//

    //◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//
    Decimal.decimal private _maxOracleSpreadRatio;
    //◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
    uint256[49] private __gap;

    modifier onlyExchange() {
        require(exchange == _msgSender(), "caller is not exchange");
        _;
    }

    function initialize(
        address _exchange,
        uint256 spreadRatio,
        uint256 initMarginRatio,
        uint256 maintenanceMarginRatio,
        uint256 liquidationFeeRatio,
        uint256 maxLiquidationFee,
        uint256 maxOracleSpreadRatio
    ) public initializer {
        require(
            initMarginRatio != 0 && maintenanceMarginRatio != 0 && liquidationFeeRatio != 0 && maxLiquidationFee != 0,
            "invalid input"
        );
        __Ownable_init();

        exchange = _exchange;
        _spreadRatio = Decimal.decimal(spreadRatio);
        _initMarginRatio = Decimal.decimal(initMarginRatio);
        _maintenanceMarginRatio = Decimal.decimal(maintenanceMarginRatio);
        _liquidationFeeRatio = Decimal.decimal(liquidationFeeRatio);
        _maxLiquidationFee = Decimal.decimal(maxLiquidationFee);
        _maxOracleSpreadRatio = Decimal.decimal(maxOracleSpreadRatio);


        HighRiskLPToken = new MMLPToken("MM High Risk LP Token", "MHT");
        LowRiskLPToken = new MMLPToken("MM Low Risk LP Token", "MLT");
    }

    /**
     * @notice mint MLP for MM
     * @dev only SakePerp can call this function
     */
    function mint(
        ISakePerpVaultTypes.Risk _risk,
        address account,
        uint256 amount
    ) external override onlyExchange {
        if (_risk == ISakePerpVaultTypes.Risk.HIGH) {
            HighRiskLPToken.mint(account, amount);
        } else if (_risk == ISakePerpVaultTypes.Risk.LOW) {
            LowRiskLPToken.mint(account, amount);
        } else {
            revert("invalid risk level");
        }
    }

    /**
     * @notice burn MLP
     * @dev only SakePerp can call this function
     */
    function burn(
        ISakePerpVaultTypes.Risk _risk,
        address account,
        uint256 amount
    ) external override onlyExchange {
        if (_risk == ISakePerpVaultTypes.Risk.HIGH) {
            HighRiskLPToken.burn(account, amount);
        } else if (_risk == ISakePerpVaultTypes.Risk.LOW) {
            LowRiskLPToken.burn(account, amount);
        } else {
            revert("invalid risk level");
        }
    }

    /**
     * @notice calculate spread fee by input quoteAssetAmount
     * @param _quoteAssetAmount quoteAssetAmount
     * @return total tx fee
     */
    function calcFee(Decimal.decimal calldata _quoteAssetAmount)
        external
        view
        override
        returns (Decimal.decimal memory)
    {
        if (_quoteAssetAmount.toUint() == 0) {
            return Decimal.zero();
        }
        return _quoteAssetAmount.mulD(_spreadRatio);
    }

    /*       plus/minus 1 while the amount is not dividable
     *
     *        getInputPrice                         getOutputPrice
     *
     *     ADD      (amount - 1)              (amount + 1)   REMOVE
     *      ◥◤            ▲                         |             ◢◣
     *      ◥◤  ------->  |                         ▼  <--------  ◢◣
     *    -------      -------                   -------        -------
     *    |  Q  |      |  B  |                   |  Q  |        |  B  |
     *    -------      -------                   -------        -------
     *      ◥◤  ------->  ▲                         |  <--------  ◢◣
     *      ◥◤            |                         ▼             ◢◣
     *   REMOVE  (amount + 1)              (amount + 1)      ADD
     **/

    function getInputPriceWithReserves(
        IExchangeTypes.Dir _dir,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) public pure override returns (Decimal.decimal memory) {
        if (_quoteAssetAmount.toUint() == 0) {
            return Decimal.zero();
        }

        bool isAddToAmm = _dir == IExchangeTypes.Dir.ADD_TO_AMM;
        SignedDecimal.signedDecimal memory invariant =
            MixedDecimal.fromDecimal(_quoteAssetPoolAmount.mulD(_baseAssetPoolAmount));
        SignedDecimal.signedDecimal memory baseAssetAfter;
        Decimal.decimal memory quoteAssetAfter;
        Decimal.decimal memory baseAssetBought;
        if (isAddToAmm) {
            quoteAssetAfter = _quoteAssetPoolAmount.addD(_quoteAssetAmount);
        } else {
            quoteAssetAfter = _quoteAssetPoolAmount.subD(_quoteAssetAmount);
        }
        require(quoteAssetAfter.toUint() != 0, "quote asset after is 0");

        baseAssetAfter = invariant.divD(quoteAssetAfter);
        baseAssetBought = baseAssetAfter.subD(_baseAssetPoolAmount).abs();

        // if the amount is not dividable, return 1 wei less for trader
        if (invariant.abs().modD(quoteAssetAfter).toUint() != 0) {
            if (isAddToAmm) {
                baseAssetBought = baseAssetBought.subD(Decimal.decimal(1));
            } else {
                baseAssetBought = baseAssetBought.addD(Decimal.decimal(1));
            }
        }

        return baseAssetBought;
    }

    function getOutputPriceWithReserves(
        IExchangeTypes.Dir _dir,
        Decimal.decimal memory _baseAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) public pure override returns (Decimal.decimal memory) {
        if (_baseAssetAmount.toUint() == 0) {
            return Decimal.zero();
        }

        bool isAddToAmm = _dir == IExchangeTypes.Dir.ADD_TO_AMM;
        SignedDecimal.signedDecimal memory invariant =
            MixedDecimal.fromDecimal(_quoteAssetPoolAmount.mulD(_baseAssetPoolAmount));
        SignedDecimal.signedDecimal memory quoteAssetAfter;
        Decimal.decimal memory baseAssetAfter;
        Decimal.decimal memory quoteAssetSold;

        if (isAddToAmm) {
            baseAssetAfter = _baseAssetPoolAmount.addD(_baseAssetAmount);
        } else {
            baseAssetAfter = _baseAssetPoolAmount.subD(_baseAssetAmount);
        }
        require(baseAssetAfter.toUint() != 0, "base asset after is 0");

        quoteAssetAfter = invariant.divD(baseAssetAfter);
        quoteAssetSold = quoteAssetAfter.subD(_quoteAssetPoolAmount).abs();

        // if the amount is not dividable, return 1 wei less for trader
        if (invariant.abs().modD(baseAssetAfter).toUint() != 0) {
            if (isAddToAmm) {
                quoteAssetSold = quoteAssetSold.subD(Decimal.decimal(1));
            } else {
                quoteAssetSold = quoteAssetSold.addD(Decimal.decimal(1));
            }
        }

        return quoteAssetSold;
    }

    /**
     * @notice set new cap during guarded period, which is max position size that traders can hold
     * @dev only owner can call. assume this will be removes soon once the guarded period has ended. must be set before opening exchange
     * @param maxHoldingBaseAsset max position size that traders can hold in 18 digits
     * @param openInterestNotionalCap open interest cap, denominated in quoteToken
     */
    function setCap(Decimal.decimal memory maxHoldingBaseAsset, Decimal.decimal memory openInterestNotionalCap)
        public
        onlyOwner
    {
        _maxHoldingBaseAsset = maxHoldingBaseAsset;
        _openInterestNotionalCap = openInterestNotionalCap;
        emit CapChanged(_maxHoldingBaseAsset.toUint(), _openInterestNotionalCap.toUint());
    }

    /**
     * @notice set init margin ratio
     * @param _ratio new init margin ratio
     */
    function setInitMarginRatio(Decimal.decimal memory _ratio) public onlyOwner {
        require(_ratio.cmp(Decimal.zero()) > 0, "invalid init margin ratio");
        _initMarginRatio = _ratio;
        emit InitMarginRatioChanged(_initMarginRatio.toUint());
    }

    /**
     * @notice set maintenance margin ratio
     * @param _ratio new maintenance margin ratio
     */
    function setMaintenanceMarginRatio(Decimal.decimal memory _ratio) public onlyOwner {
        require(_ratio.cmp(Decimal.zero()) > 0, "invalid maintenance margin ratio");
        _maintenanceMarginRatio = _ratio;
        emit MaintenanceMarginRatioChanged(_maintenanceMarginRatio.toUint());
    }

    /**
     * @notice set liquidation fee ratio
     * @param _ratio new liquidation fee ratio
     */
    function setLiquidationFeeRatio(Decimal.decimal memory _ratio) public onlyOwner {
        require(_ratio.cmp(Decimal.zero()) > 0, "invalid liquidation fee ratio");
        _liquidationFeeRatio = _ratio;
        emit LiquidationFeeRatioChanged(_liquidationFeeRatio.toUint());
    }

    /**
     * @notice set max liquidation Fee
     * @param _fee new max liquidation Fee
     */
    function setMaxLiquidationFee(Decimal.decimal memory _fee) public onlyOwner {
        require(_fee.cmp(Decimal.zero()) > 0, "invalid max liquidation fee");
        _maxLiquidationFee = _fee;
        emit MaxLiquidationFeeChanged(_maxLiquidationFee.toUint());
    }

    /**
     * @notice set new spread ratio
     * @dev only owner can call
     * @param spreadRatio new toll ratio in 18 digits
     */
    function setSpreadRatio(Decimal.decimal memory spreadRatio) public onlyOwner {
        _spreadRatio = spreadRatio;
    }

    /**
     * @notice set new max oracle spread ratio
     * @dev only owner can call
     * @param maxOracleSpreadRatio new toll ratio in 18 digits
     */
    function setMaxOracleSpreadRatio(Decimal.decimal memory maxOracleSpreadRatio) public onlyOwner {
        _maxOracleSpreadRatio = maxOracleSpreadRatio;
    } 

    function getMaxHoldingBaseAsset() external view override returns (Decimal.decimal memory) {
        return _maxHoldingBaseAsset;
    }

    function getOpenInterestNotionalCap() external view override returns (Decimal.decimal memory) {
        return _openInterestNotionalCap;
    }

    function initMarginRatio() external view override returns (Decimal.decimal memory) {
        return _initMarginRatio;
    }

    function maintenanceMarginRatio() external view override returns (Decimal.decimal memory) {
        return _maintenanceMarginRatio;
    }

    function liquidationFeeRatio() external view override returns (Decimal.decimal memory) {
        return _liquidationFeeRatio;
    }

    function maxLiquidationFee() external view override returns (Decimal.decimal memory) {
        return _maxLiquidationFee;
    }

    function spreadRatio() external view override returns (Decimal.decimal memory) {
        return _spreadRatio;
    }

    function maxOracleSpreadRatio() external view override returns (Decimal.decimal memory) {
        return _maxOracleSpreadRatio;
    }

    function getLPToken(ISakePerpVaultTypes.Risk _risk) external view override returns (MMLPToken) {
        if (ISakePerpVaultTypes.Risk.HIGH == _risk) {
            return HighRiskLPToken;
        } else {
            return LowRiskLPToken;
        }
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxHoldingBaseAsset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"openInterestNotionalCap","type":"uint256"}],"name":"CapChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initMarginRatio","type":"uint256"}],"name":"InitMarginRatioChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidationFeeRatio","type":"uint256"}],"name":"LiquidationFeeRatioChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maintenanceMarginRatio","type":"uint256"}],"name":"MaintenanceMarginRatioChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxliquidationFee","type":"uint256"}],"name":"MaxLiquidationFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"HighRiskLPToken","outputs":[{"internalType":"contract MMLPToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LowRiskLPToken","outputs":[{"internalType":"contract MMLPToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"}],"name":"calcFee","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchange","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchangeTypes.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetPoolAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetPoolAmount","type":"tuple"}],"name":"getInputPriceWithReserves","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getLPToken","outputs":[{"internalType":"contract MMLPToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxHoldingBaseAsset","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpenInterestNotionalCap","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchangeTypes.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetPoolAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetPoolAmount","type":"tuple"}],"name":"getOutputPriceWithReserves","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"initMarginRatio","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"uint256","name":"spreadRatio","type":"uint256"},{"internalType":"uint256","name":"initMarginRatio","type":"uint256"},{"internalType":"uint256","name":"maintenanceMarginRatio","type":"uint256"},{"internalType":"uint256","name":"liquidationFeeRatio","type":"uint256"},{"internalType":"uint256","name":"maxLiquidationFee","type":"uint256"},{"internalType":"uint256","name":"maxOracleSpreadRatio","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationFeeRatio","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maintenanceMarginRatio","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLiquidationFee","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxOracleSpreadRatio","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"maxHoldingBaseAsset","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"openInterestNotionalCap","type":"tuple"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_ratio","type":"tuple"}],"name":"setInitMarginRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_ratio","type":"tuple"}],"name":"setLiquidationFeeRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_ratio","type":"tuple"}],"name":"setMaintenanceMarginRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_fee","type":"tuple"}],"name":"setMaxLiquidationFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"maxOracleSpreadRatio","type":"tuple"}],"name":"setMaxOracleSpreadRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"spreadRatio","type":"tuple"}],"name":"setSpreadRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spreadRatio","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50613660806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001f05760003560e01c80638142951a1162000111578063cfe7110311620000a5578063e79f7005116200007b578063e79f700514620003b7578063eeb016f214620003c1578063eebab8ef14620003cb578063f2fde38b14620003e257620001f0565b8063cfe711031462000399578063d2f7265a14620003a3578063e57d563614620003ad57620001f0565b80638eb86e8b11620000e75780638eb86e8b146200033d5780639bf5d1d41462000354578063b4448711146200036b578063c9dde756146200038257620001f0565b80638142951a146200031257806383acb48a14620003295780638da5cb5b146200033357620001f0565b8063524f15a1116200018957806362267955116200015f5780636226795514620002d05780636c12744614620002e75780636febdd5014620002fe578063715018a6146200030857620001f0565b8063524f15a114620002985780635254541014620002af5780636050cf1e14620002b957620001f0565b8063203b378811620001cb578063203b3788146200024957806337292b60146200026057806350799c81146200026a57806351f59d0c146200028157620001f0565b80630dd68c7014620001f557806311377394146200020e57806313f2ca711462000230575b600080fd5b6200020c6200020636600462001b3f565b620003f9565b005b62000218620004ba565b6040516200022791906200208c565b60405180910390f35b6200023a620004d8565b60405162000227919062001b78565b6200020c6200025a36600462001b21565b620004e7565b62000218620005b8565b620002186200027b36600462001a44565b620005d6565b6200023a6200029236600462001aa5565b6200074f565b6200020c620002a936600462001b21565b62000789565b62000218620007c9565b6200020c620002ca36600462001b21565b620007e7565b62000218620002e136600462001b09565b62000827565b6200020c620002f836600462001b21565b62000890565b620002186200093f565b6200020c6200095d565b6200020c62000323366004620019ed565b620009e1565b6200021862000bea565b6200023a62000c08565b6200020c6200034e36600462001ac4565b62000c17565b620002186200036536600462001a44565b62000d3e565b6200020c6200037c36600462001b21565b62000e21565b6200020c6200039336600462001b21565b62000ed0565b6200021862000f7f565b6200023a62000f9d565b6200021862000fac565b6200023a62000fca565b6200021862000fd9565b6200020c620003dc36600462001ac4565b62000ff7565b6200020c620003f3366004620019c4565b620010c5565b6200040362001184565b6033546001600160a01b039081169116146200043c5760405162461bcd60e51b8152600401620004339062001dc0565b60405180910390fd5b81516067819055815160685560408051602081019091529081527f7338f3784ceb8f9456bac0c4a69f1c6354dc325fa6455e3e3f6a8a9bf9249a7c90620004839062001188565b604080516020810190915260685481526200049e9062001188565b604051620004ae9291906200209f565b60405180910390a15050565b620004c462001964565b506040805160208101909152606754815290565b606e546001600160a01b031681565b620004f162001184565b6033546001600160a01b03908116911614620005215760405162461bcd60e51b8152600401620004339062001dc0565b600062000539620005316200118c565b8390620011a9565b60000b136200055c5760405162461bcd60e51b8152600401620004339062001eed565b8051606b81905560408051602081019091529081527f6f825f18b787836f7cf974799b160538ab237aa0d14af3611fa69683a40c6d22906200059e9062001188565b604051620005ad919062002096565b60405180910390a150565b620005c262001964565b506040805160208101909152606f54815290565b620005e062001964565b620005eb8462001188565b6200060257620005fa6200118c565b905062000747565b6000808660018111156200061257fe5b1490506200061f62001964565b620006356200062f8686620011de565b6200120a565b90506200064162001964565b6200064b62001964565b6200065562001964565b8415620006705762000668888a62001274565b91506200067f565b6200067c888a62001297565b91505b6200068a8262001188565b620006a95760405162461bcd60e51b8152600401620004339062001f5b565b620006b58483620012ba565b9250620006cd620006c784896200133a565b620013b3565b9050620006f0620006ea83620006e387620013b3565b90620013e7565b62001188565b156200074057841562000721576040805160208101909152600181526200071990829062001297565b905062000740565b6040805160208101909152600181526200073d90829062001274565b90505b9450505050505b949350505050565b60008160018111156200075e57fe5b620007765750606d546001600160a01b031662000784565b50606e546001600160a01b03165b919050565b6200079362001184565b6033546001600160a01b03908116911614620007c35760405162461bcd60e51b8152600401620004339062001dc0565b51606655565b620007d362001964565b506040805160208101909152606854815290565b620007f162001184565b6033546001600160a01b03908116911614620008215760405162461bcd60e51b8152600401620004339062001dc0565b51606f55565b6200083162001964565b62000846620006ea3684900384018462001b21565b6200085d57620008556200118c565b905062000784565b604080516020810190915260665481526200088a90620008833685900385018562001b21565b90620011de565b92915050565b6200089a62001184565b6033546001600160a01b03908116911614620008ca5760405162461bcd60e51b8152600401620004339062001dc0565b6000620008da620005316200118c565b60000b13620008fd5760405162461bcd60e51b8152600401620004339062001ff6565b8051606a81905560408051602081019091529081527fe75e3e311afafb466335ae8af3bf1d55443d8937fb5ada14583f4fca729c0fa8906200059e9062001188565b6200094962001964565b506040805160208101909152606654815290565b6200096762001184565b6033546001600160a01b03908116911614620009975760405162461bcd60e51b8152600401620004339062001dc0565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b600054610100900460ff1680620009fd5750620009fd6200142c565b8062000a0c575060005460ff16155b62000a2b5760405162461bcd60e51b8152600401620004339062001cf0565b600054610100900460ff1615801562000a57576000805460ff1961ff0019909116610100171660011790555b851580159062000a6657508415155b801562000a7257508315155b801562000a7e57508215155b62000a9d5760405162461bcd60e51b8152600401620004339062001f8b565b62000aa762001432565b606580546001600160a01b0319166001600160a01b038a16179055604080516020808201835290899052606689905581518082018352889052606988905581518082018352879052606a87905581518082018352869052606b86905581518082018352859052606c85905581519081018252839052606f8390555162000b2d9062001977565b62000b389062001df5565b604051809103906000f08015801562000b55573d6000803e3d6000fd5b50606d80546001600160a01b0319166001600160a01b039290921691909117905560405162000b849062001977565b62000b8f9062001ca7565b604051809103906000f08015801562000bac573d6000803e3d6000fd5b50606e80546001600160a01b0319166001600160a01b0392909216919091179055801562000be0576000805461ff00191690555b5050505050505050565b62000bf462001964565b506040805160208101909152606a54815290565b6033546001600160a01b031690565b62000c2162001184565b6065546001600160a01b0390811691161462000c515760405162461bcd60e51b8152600401620004339062001e76565b600083600181111562000c6057fe5b141562000cd557606d54604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac9062000c9b908590859060040162001b8c565b600060405180830381600087803b15801562000cb657600080fd5b505af115801562000ccb573d6000803e3d6000fd5b5050505062000d39565b600183600181111562000ce457fe5b141562000d1f57606e54604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac9062000c9b908590859060040162001b8c565b60405162461bcd60e51b8152600401620004339062002060565b505050565b62000d4862001964565b62000d538462001188565b62000d6257620005fa6200118c565b60008086600181111562000d7257fe5b14905062000d7f62001964565b62000d8f6200062f8686620011de565b905062000d9b62001964565b62000da562001964565b62000daf62001964565b841562000dca5762000dc2878a62001274565b915062000dd9565b62000dd6878a62001297565b91505b62000de48262001188565b62000e035760405162461bcd60e51b8152600401620004339062001bfb565b62000e0f8483620012ba565b9250620006cd620006c7848a6200133a565b62000e2b62001184565b6033546001600160a01b0390811691161462000e5b5760405162461bcd60e51b8152600401620004339062001dc0565b600062000e6b620005316200118c565b60000b1362000e8e5760405162461bcd60e51b8152600401620004339062001f24565b8051606c81905560408051602081019091529081527f0565ffb26c5ec0ddf0975584b3c48758d8486aea008bd280bf2c98f2464f441f906200059e9062001188565b62000eda62001184565b6033546001600160a01b0390811691161462000f0a5760405162461bcd60e51b8152600401620004339062001dc0565b600062000f1a620005316200118c565b60000b1362000f3d5760405162461bcd60e51b8152600401620004339062001e3f565b8051606981905560408051602081019091529081527fd67453718fc57aad470d91be51568530ed02cc941c846cd9e281dc56b300e95e906200059e9062001188565b62000f8962001964565b506040805160208101909152606b54815290565b6065546001600160a01b031681565b62000fb662001964565b506040805160208101909152606954815290565b606d546001600160a01b031681565b62000fe362001964565b506040805160208101909152606c54815290565b6200100162001184565b6065546001600160a01b03908116911614620010315760405162461bcd60e51b8152600401620004339062001e76565b60008360018111156200104057fe5b14156200107b57606d546040516340c10f1960e01b81526001600160a01b03909116906340c10f199062000c9b908590859060040162001b8c565b60018360018111156200108a57fe5b141562000d1f57606e546040516340c10f1960e01b81526001600160a01b03909116906340c10f199062000c9b908590859060040162001b8c565b620010cf62001184565b6033546001600160a01b03908116911614620010ff5760405162461bcd60e51b8152600401620004339062001dc0565b6001600160a01b038116620011285760405162461bcd60e51b8152600401620004339062001c2a565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b5190565b6200119662001964565b5060408051602081019091526000815290565b805182516000911015620011c0575060016200088a565b815183511015620011d557506000196200088a565b50600092915050565b620011e862001964565b620011f262001964565b825184516200120191620014d2565b81529392505050565b6200121462001964565b8180600001516001600160ff1b031015604051806060016040528060338152602001620035f860339139906200125f5760405162461bcd60e51b815260040162000433919062001ba5565b50506040805160208101909152915182525090565b6200127e62001964565b6200128862001964565b825184516200120191620014e9565b620012a162001964565b620012ab62001964565b82518451620012019162001511565b620012c462001964565b8180600001516001600160ff1b031015604051806060016040528060338152602001620035f860339139906200130f5760405162461bcd60e51b815260040162000433919062001ba5565b506200131a62001964565b6200133162001329856200120a565b869062001555565b95945050505050565b6200134462001964565b8180600001516001600160ff1b031015604051806060016040528060338152602001620035f860339139906200138f5760405162461bcd60e51b815260040162000433919062001ba5565b506200139a62001964565b83518551620013a99162001578565b8152949350505050565b620013bd62001964565b620013c762001964565b825160001315620013df57825160000381526200088a565b915182525090565b620013f162001964565b604051806020016040528083600001516200141a620014116012620015c4565b875190620015cd565b816200142257fe5b0690529392505050565b303b1590565b600054610100900460ff16806200144e57506200144e6200142c565b806200145d575060005460ff16155b6200147c5760405162461bcd60e51b8152600401620004339062001cf0565b600054610100900460ff16158015620014a8576000805460ff1961ff0019909116610100171660011790555b620014b26200160d565b620014bc62001697565b8015620014cf576000805461ff00191690555b50565b6000620014e2838360126200177c565b9392505050565b600082820183811015620014e25760405162461bcd60e51b8152600401620004339062001c70565b6000620014e283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250620017a0565b6200155f62001964565b6200156962001964565b825184516200120191620017cf565b60008183038183128015906200158e5750838113155b80620015a55750600083128015620015a557508381135b620014e25760405162461bcd60e51b8152600401620004339062001fb2565b60ff16600a0a90565b600082620015de575060006200088a565b82820282848281620015ec57fe5b0414620014e25760405162461bcd60e51b8152600401620004339062001d7f565b600054610100900460ff1680620016295750620016296200142c565b8062001638575060005460ff16155b620016575760405162461bcd60e51b8152600401620004339062001cf0565b600054610100900460ff16158015620014bc576000805460ff1961ff0019909116610100171660011790558015620014cf576000805461ff001916905550565b600054610100900460ff1680620016b35750620016b36200142c565b80620016c2575060005460ff16155b620016e15760405162461bcd60e51b8152600401620004339062001cf0565b600054610100900460ff161580156200170d576000805460ff1961ff0019909116610100171660011790555b60006200171962001184565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015620014cf576000805461ff001916905550565b6000620007476200178d83620015c4565b620017998686620015cd565b90620017df565b60008184841115620017c75760405162461bcd60e51b815260040162000433919062001ba5565b505050900390565b6000620014e28383601262001823565b6000620014e283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525062001848565b60006200074783620018416200183985620015c4565b879062001883565b90620018f8565b600081836200186c5760405162461bcd60e51b815260040162000433919062001ba5565b5060008385816200187957fe5b0495945050505050565b60008262001894575060006200088a565b82600019148015620018a95750600160ff1b82145b15620018c95760405162461bcd60e51b8152600401620004339062001ea6565b82820282848281620018d757fe5b0514620014e25760405162461bcd60e51b8152600401620004339062001ea6565b6000816200191a5760405162461bcd60e51b815260040162000433906200202b565b816000191480156200192f5750600160ff1b83145b156200194f5760405162461bcd60e51b8152600401620004339062001d3e565b60008284816200195b57fe5b05949350505050565b6040518060200160405280600081525090565b61152680620020d283390190565b60006020828403121562001997578081fd5b6040516020810181811067ffffffffffffffff82111715620019b7578283fd5b6040529135825250919050565b600060208284031215620019d6578081fd5b81356001600160a01b0381168114620014e2578182fd5b600080600080600080600060e0888a03121562001a08578283fd5b873562001a1581620020ad565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b6000806000806080858703121562001a5a578384fd5b843562001a6781620020c3565b935062001a78866020870162001985565b925062001a89866040870162001985565b915062001a9a866060870162001985565b905092959194509250565b60006020828403121562001ab7578081fd5b8135620014e281620020c3565b60008060006060848603121562001ad9578283fd5b833562001ae681620020c3565b9250602084013562001af881620020ad565b929592945050506040919091013590565b60006020828403121562001b1b578081fd5b50919050565b60006020828403121562001b33578081fd5b620014e2838362001985565b6000806040838503121562001b52578182fd5b62001b5e848462001985565b915062001b6f846020850162001985565b90509250929050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6000602080835283518082850152825b8181101562001bd35785810183015185820160400152820162001bb5565b8181111562001be55783604083870101525b50601f01601f1916929092016040019392505050565b602080825260159082015274062617365206173736574206166746572206973203605c1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60408082526014908201527326a6902637bb902934b9b5902628102a37b5b2b760611b60608201526080602082018190526003908201526213531560ea1b60a082015260c00190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60408082526015908201527426a6902434b3b4102934b9b5902628102a37b5b2b760591b60608201526080602082018190526003908201526213521560ea1b60a082015260c00190565b60208082526019908201527f696e76616c696420696e6974206d617267696e20726174696f00000000000000604082015260600190565b60208082526016908201527563616c6c6572206973206e6f742065786368616e676560501b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252601d908201527f696e76616c6964206c69717569646174696f6e2066656520726174696f000000604082015260600190565b6020808252601b908201527f696e76616c6964206d6178206c69717569646174696f6e206665650000000000604082015260600190565b602080825260169082015275071756f746520617373657420616674657220697320360541b604082015260600190565b6020808252600d908201526c1a5b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252818101527f696e76616c6964206d61696e74656e616e6365206d617267696e20726174696f604082015260600190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601290820152711a5b9d985b1a59081c9a5cdac81b195d995b60721b604082015260600190565b9051815260200190565b90815260200190565b918252602082015260400190565b6001600160a01b0381168114620014cf57600080fd5b60028110620014cf57600080fdfe60806040523480156200001157600080fd5b506040516200152638038062001526833981016040819052620000349162000521565b62000040828262000052565b6200004a620000ff565b5050620005d6565b600054610100900460ff16806200006e57506200006e6200019f565b806200007d575060005460ff16155b620000a55760405162461bcd60e51b81526004016200009c9062000588565b60405180910390fd5b600054610100900460ff16158015620000d1576000805460ff1961ff0019909116610100171660011790555b620000db620001a5565b620000e783836200022f565b8015620000fa576000805461ff00191690555b505050565b600054610100900460ff16806200011b57506200011b6200019f565b806200012a575060005460ff16155b620001495760405162461bcd60e51b81526004016200009c9062000588565b600054610100900460ff1615801562000175576000805460ff1961ff0019909116610100171660011790555b6200017f620001a5565b62000189620002f5565b80156200019c576000805461ff00191690555b50565b303b1590565b600054610100900460ff1680620001c15750620001c16200019f565b80620001d0575060005460ff16155b620001ef5760405162461bcd60e51b81526004016200009c9062000588565b600054610100900460ff1615801562000189576000805460ff1961ff00199091166101001716600117905580156200019c576000805461ff001916905550565b600054610100900460ff16806200024b57506200024b6200019f565b806200025a575060005460ff16155b620002795760405162461bcd60e51b81526004016200009c9062000588565b600054610100900460ff16158015620002a5576000805460ff1961ff0019909116610100171660011790555b8251620002ba906036906020860190620003de565b508151620002d0906037906020850190620003de565b506038805460ff191660121790558015620000fa576000805461ff0019169055505050565b600054610100900460ff1680620003115750620003116200019f565b8062000320575060005460ff16155b6200033f5760405162461bcd60e51b81526004016200009c9062000588565b600054610100900460ff161580156200036b576000805460ff1961ff0019909116610100171660011790555b600062000377620003da565b606580546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156200019c576000805461ff001916905550565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200042157805160ff191683800117855562000451565b8280016001018555821562000451579182015b828111156200045157825182559160200191906001019062000434565b506200045f92915062000463565b5090565b5b808211156200045f576000815560010162000464565b600082601f8301126200048b578081fd5b81516001600160401b0380821115620004a2578283fd5b6040516020601f8401601f1916820181018381118382101715620004c4578586fd5b80604052508194508382528681858801011115620004e157600080fd5b600092505b83831015620005055785830181015182840182015291820191620004e6565b83831115620005175760008185840101525b5050505092915050565b6000806040838503121562000534578182fd5b82516001600160401b03808211156200054b578384fd5b62000559868387016200047a565b935060208501519150808211156200056f578283fd5b506200057e858286016200047a565b9150509250929050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b610f4080620005e66000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063715018a611610097578063a457c2d711610066578063a457c2d7146101f3578063a9059cbb14610206578063dd62ed3e14610219578063f2fde38b1461022c57610100565b8063715018a6146101bb5780638da5cb5b146101c357806395d89b41146101d85780639dc29fac146101e057610100565b8063313ce567116100d3578063313ce5671461016b578063395093511461018057806340c10f191461019357806370a08231146101a857610100565b806306fdde0314610105578063095ea7b31461012357806318160ddd1461014357806323b872dd14610158575b600080fd5b61010d61023f565b60405161011a9190610bbb565b60405180910390f35b610136610131366004610b72565b6102d5565b60405161011a9190610bb0565b61014b6102f3565b60405161011a9190610e46565b610136610166366004610b32565b6102f9565b610173610380565b60405161011a9190610e4f565b61013661018e366004610b72565b610389565b6101a66101a1366004610b72565b6103d7565b005b61014b6101b6366004610ae3565b610423565b6101a661043e565b6101cb6104bd565b60405161011a9190610b9c565b61010d6104cc565b6101a66101ee366004610b72565b61052d565b610136610201366004610b72565b61056c565b610136610214366004610b72565b6105d4565b61014b610227366004610afe565b6105e8565b6101a661023a366004610ae3565b610613565b60368054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156102cb5780601f106102a0576101008083540402835291602001916102cb565b820191906000526020600020905b8154815290600101906020018083116102ae57829003601f168201915b5050505050905090565b60006102e96102e26106ca565b84846106ce565b5060015b92915050565b60355490565b6000610306848484610782565b610376846103126106ca565b61037185604051806060016040528060288152602001610ebe602891396001600160a01b038a166000908152603460205260408120906103506106ca565b6001600160a01b031681526020810191909152604001600020549190610897565b6106ce565b5060019392505050565b60385460ff1690565b60006102e96103966106ca565b8461037185603460006103a76106ca565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906108c3565b6103df6106ca565b6065546001600160a01b039081169116146104155760405162461bcd60e51b815260040161040c90610d10565b60405180910390fd5b61041f82826108ef565b5050565b6001600160a01b031660009081526033602052604090205490565b6104466106ca565b6065546001600160a01b039081169116146104735760405162461bcd60e51b815260040161040c90610d10565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b6065546001600160a01b031690565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156102cb5780601f106102a0576101008083540402835291602001916102cb565b6105356106ca565b6065546001600160a01b039081169116146105625760405162461bcd60e51b815260040161040c90610d10565b61041f82826109af565b60006102e96105796106ca565b8461037185604051806060016040528060258152602001610ee660259139603460006105a36106ca565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610897565b60006102e96105e16106ca565b8484610782565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61061b6106ca565b6065546001600160a01b039081169116146106485760405162461bcd60e51b815260040161040c90610d10565b6001600160a01b03811661066e5760405162461bcd60e51b815260040161040c90610c51565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b0383166106f45760405162461bcd60e51b815260040161040c90610dcb565b6001600160a01b03821661071a5760405162461bcd60e51b815260040161040c90610c97565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610775908590610e46565b60405180910390a3505050565b6001600160a01b0383166107a85760405162461bcd60e51b815260040161040c90610d86565b6001600160a01b0382166107ce5760405162461bcd60e51b815260040161040c90610c0e565b6107d9838383610a85565b61081681604051806060016040528060268152602001610e98602691396001600160a01b0386166000908152603360205260409020549190610897565b6001600160a01b03808516600090815260336020526040808220939093559084168152205461084590826108c3565b6001600160a01b0380841660008181526033602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610775908590610e46565b600081848411156108bb5760405162461bcd60e51b815260040161040c9190610bbb565b505050900390565b6000828201838110156108e85760405162461bcd60e51b815260040161040c90610cd9565b9392505050565b6001600160a01b0382166109155760405162461bcd60e51b815260040161040c90610e0f565b61092160008383610a85565b60355461092e90826108c3565b6035556001600160a01b03821660009081526033602052604090205461095490826108c3565b6001600160a01b0383166000818152603360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109a3908590610e46565b60405180910390a35050565b6001600160a01b0382166109d55760405162461bcd60e51b815260040161040c90610d45565b6109e182600083610a85565b610a1e81604051806060016040528060228152602001610e76602291396001600160a01b0385166000908152603360205260409020549190610897565b6001600160a01b038316600090815260336020526040902055603554610a449082610a8a565b6035556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109a3908590610e46565b505050565b60006108e883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610897565b80356001600160a01b03811681146102ed57600080fd5b600060208284031215610af4578081fd5b6108e88383610acc565b60008060408385031215610b10578081fd5b610b1a8484610acc565b9150610b298460208501610acc565b90509250929050565b600080600060608486031215610b46578081fd5b8335610b5181610e5d565b92506020840135610b6181610e5d565b929592945050506040919091013590565b60008060408385031215610b84578182fd5b610b8e8484610acc565b946020939093013593505050565b6001600160a01b0391909116815260200190565b901515815260200190565b6000602080835283518082850152825b81811015610be757858101830151858201604001528201610bcb565b81811115610bf85783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b90815260200190565b60ff91909116815260200190565b6001600160a01b0381168114610e7257600080fd5b5056fe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220015cadf52baa30ad301981da075cb409fe3859867ed174f85c185f8521abee4c64736f6c634300060c00334d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a26469706673582212206cf60277769f865b0f40b8ccd3c3cc9e89ea2f233b657c51f8fdec42e7d09d3364736f6c634300060c0033

Deployed ByteCode Sourcemap

51057:12867:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59995:362;;;;;;:::i;:::-;;:::i;:::-;;62539:136;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;52102:31;;;:::i;:::-;;;;;;;:::i;61266:284::-;;;;;;:::i;:::-;;:::i;63518:135::-;;;:::i;56366:1599::-;;;;;;:::i;:::-;;:::i;63661:260::-;;;;;;:::i;:::-;;:::i;62079:122::-;;;;;;:::i;:::-;;:::i;62683:144::-;;;:::i;62372:158::-;;;;;;:::i;:::-;;:::i;55176:315::-;;;;;;:::i;:::-;;:::i;60851:299::-;;;;;;:::i;:::-;;:::i;63393:117::-;;;:::i;11321:148::-;;;:::i;52824:1089::-;;;;;;:::i;:::-;;:::i;62968:139::-;;;:::i;10679:79::-;;;:::i;54565:443::-;;;;;;:::i;:::-;;:::i;57973:1586::-;;;;;;:::i;:::-;;:::i;61660:268::-;;;;;;:::i;:::-;;:::i;60465:264::-;;;;;;:::i;:::-;;:::i;63115:133::-;;;:::i;51679:23::-;;;:::i;62835:125::-;;;:::i;52063:32::-;;;:::i;63256:129::-;;;:::i;54021:443::-;;;;;;:::i;:::-;;:::i;11624:244::-;;;;;;:::i;:::-;;:::i;59995:362::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;;;;;;;;;60154:42;;:20:::1;:42:::0;;;60207:50;;:24:::1;:50:::0;60284:27:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;60273:76:::1;::::0;60284:29:::1;::::0;:27:::1;:29::i;:::-;60315:31;::::0;;::::1;::::0;::::1;::::0;;;:24:::1;:31:::0;;;:33:::1;::::0;:31:::1;:33::i;:::-;60273:76;;;;;;;:::i;:::-;;;;;;;;59995:362:::0;;:::o;62539:136::-;62605:22;;:::i;:::-;-1:-1:-1;62640:27:0;;;;;;;;;62647:20;62640:27;;;62539:136;:::o;52102:31::-;;;-1:-1:-1;;;;;52102:31:0;;:::o;61266:284::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;61394:1:::1;61365:26;61376:14;:12;:14::i;:::-;61365:6:::0;;:10:::1;:26::i;:::-;:30;;;61357:72;;;;-1:-1:-1::0;;;61357:72:0::1;;;;;;;:::i;:::-;61440:29:::0;;:20:::1;:29:::0;;;61512:27:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;61485:57:::1;::::0;61512:29:::1;::::0;:27:::1;:29::i;:::-;61485:57;;;;;;:::i;:::-;;;;;;;;61266:284:::0;:::o;63518:135::-;63582:22;;:::i;:::-;-1:-1:-1;63617:28:0;;;;;;;;;63624:21;63617:28;;;63518:135;:::o;56366:1599::-;56632:22;;:::i;:::-;56671:26;:17;:24;:26::i;:::-;56667:85;;56726:14;:12;:14::i;:::-;56719:21;;;;56667:85;56764:15;;56782:4;:37;;;;;;;;;56764:55;;56830:44;;:::i;:::-;56890:74;56915:48;:21;56942:20;56915:26;:48::i;:::-;56890:24;:74::i;:::-;56830:134;;56975:49;;:::i;:::-;57035:38;;:::i;:::-;57084;;:::i;:::-;57137:10;57133:202;;;57182:45;:21;57209:17;57182:26;:45::i;:::-;57164:63;;57133:202;;;57278:45;:21;57305:17;57278:26;:45::i;:::-;57260:63;;57133:202;57353:24;:15;:22;:24::i;:::-;57345:64;;;;-1:-1:-1;;;57345:64:0;;;;;;;:::i;:::-;57439:31;:9;57454:15;57439:14;:31::i;:::-;57422:48;-1:-1:-1;57499:47:0;:41;57422:48;57519:20;57499:19;:41::i;:::-;:45;:47::i;:::-;57481:65;;57636:46;:37;57657:15;57636;:9;:13;:15::i;:::-;:20;;:37::i;:::-;:44;:46::i;:::-;:51;57632:291;;57708:10;57704:208;;;57778:18;;;;;;;;;57794:1;57778:18;;57757:40;;:15;;:20;:40::i;:::-;57739:58;;57704:208;;;57877:18;;;;;;;;;57893:1;57877:18;;57856:40;;:15;;:20;:40::i;:::-;57838:58;;57704:208;57942:15;-1:-1:-1;;;;;56366:1599:0;;;;;;;:::o;63661:260::-;63745:9;63804:5;63771:38;;;;;;;;63767:147;;-1:-1:-1;63833:15:0;;-1:-1:-1;;;;;63833:15:0;63826:22;;63767:147;-1:-1:-1;63888:14:0;;-1:-1:-1;;;;;63888:14:0;63767:147;63661:260;;;:::o;62079:122::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;62167:26;:12:::1;:26:::0;62079:122::o;62683:144::-;62753:22;;:::i;:::-;-1:-1:-1;62788:31:0;;;;;;;;;62795:24;62788:31;;;62683:144;:::o;62372:158::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;62478:44;:21:::1;:44:::0;62372:158::o;55176:315::-;55305:22;;:::i;:::-;55349:26;:24;;;;;;;:17;:24;:::i;:26::-;55345:85;;55404:14;:12;:14::i;:::-;55397:21;;;;55345:85;55447:36;;;;;;;;;55470:12;55447:36;;;;;:22;;;;;;;:17;:22;:::i;:::-;;;:36::i;:::-;55440:43;55176:315;-1:-1:-1;;55176:315:0:o;60851:299::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;60982:1:::1;60953:26;60964:14;:12;:14::i;60953:26::-;:30;;;60945:75;;;;-1:-1:-1::0;;;60945:75:0::1;;;;;;;:::i;:::-;61031:32:::0;;:23:::1;:32:::0;;;61109:30:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;61079:63:::1;::::0;61109:32:::1;::::0;:30:::1;:32::i;63393:117::-:0;63448:22;;:::i;:::-;-1:-1:-1;63483:19:0;;;;;;;;;63490:12;63483:19;;;63393:117;:::o;11321:148::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;11412:6:::1;::::0;11391:40:::1;::::0;11428:1:::1;::::0;-1:-1:-1;;;;;11412:6:0::1;::::0;11391:40:::1;::::0;11428:1;;11391:40:::1;11442:6;:19:::0;;-1:-1:-1;;;;;;11442:19:0::1;::::0;;11321:148::o;52824:1089::-;7016:13;;;;;;;;:33;;;7033:16;:14;:16::i;:::-;7016:50;;;-1:-1:-1;7054:12:0;;;;7053:13;7016:50;7008:109;;;;-1:-1:-1;;;7008:109:0;;;;;;;:::i;:::-;7130:19;7153:13;;;;;;7152:14;7177:101;;;;7212:13;:20;;-1:-1:-1;;;;7212:20:0;;;;;7247:19;7228:4;7247:19;;;7177:101;53149:20;;;::::1;::::0;:51:::1;;-1:-1:-1::0;53173:27:0;;::::1;53149:51;:79;;;;-1:-1:-1::0;53204:24:0;;::::1;53149:79;:105;;;;-1:-1:-1::0;53232:22:0;;::::1;53149:105;53127:168;;;;-1:-1:-1::0;;;53127:168:0::1;;;;;;;:::i;:::-;53306:16;:14;:16::i;:::-;53335:8;:20:::0;;-1:-1:-1;;;;;;53335:20:0::1;-1:-1:-1::0;;;;;53335:20:0;::::1;;::::0;;53381:28:::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;53366:12:::1;:43:::0;;;53439:32;;;;::::1;::::0;;;;;53420:16:::1;:51:::0;;;53508:39;;;;::::1;::::0;;;;;53482:23:::1;:65:::0;;;53581:36;;;;::::1;::::0;;;;;53558:20:::1;:59:::0;;;53649:34;;;;::::1;::::0;;;;;53628:18:::1;:55:::0;;;53718:37;;;;::::1;::::0;;;;;53694:21:::1;:61:::0;;;53788:45;::::1;::::0;::::1;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;53770:15:0::1;:63:::0;;-1:-1:-1;;;;;;53770:63:0::1;-1:-1:-1::0;;;;;53770:63:0;;;::::1;::::0;;;::::1;::::0;;53861:44:::1;::::0;::::1;::::0;::::1;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;53844:14:0::1;:61:::0;;-1:-1:-1;;;;;;53844:61:0::1;-1:-1:-1::0;;;;;53844:61:0;;;::::1;::::0;;;::::1;::::0;;7304:68;;;;7355:5;7339:21;;-1:-1:-1;;7339:21:0;;;7304:68;52824:1089;;;;;;;;:::o;62968:139::-;63034:22;;:::i;:::-;-1:-1:-1;63069:30:0;;;;;;;;;63076:23;63069:30;;;62968:139;:::o;10679:79::-;10744:6;;-1:-1:-1;;;;;10744:6:0;10679:79;:::o;54565:443::-;52757:12;:10;:12::i;:::-;52745:8;;-1:-1:-1;;;;;52745:8:0;;;:24;;;52737:59;;;;-1:-1:-1;;;52737:59:0;;;;;;;:::i;:::-;54733:29:::1;54724:5;:38;;;;;;;;;54720:281;;;54779:15;::::0;:37:::1;::::0;-1:-1:-1;;;54779:37:0;;-1:-1:-1;;;;;54779:15:0;;::::1;::::0;:20:::1;::::0;:37:::1;::::0;54800:7;;54809:6;;54779:37:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;54720:281;;;54847:28;54838:5;:37;;;;;;;;;54834:167;;;54892:14;::::0;:36:::1;::::0;-1:-1:-1;;;54892:36:0;;-1:-1:-1;;;;;54892:14:0;;::::1;::::0;:19:::1;::::0;:36:::1;::::0;54912:7;;54921:6;;54892:36:::1;;;:::i;54834:167::-;54961:28;;-1:-1:-1::0;;;54961:28:0::1;;;;;;;:::i;54834:167::-;54565:443:::0;;;:::o;57973:1586::-;58239:22;;:::i;:::-;58278:25;:16;:23;:25::i;:::-;58274:84;;58332:14;:12;:14::i;58274:84::-;58370:15;;58388:4;:37;;;;;;;;;58370:55;;58436:44;;:::i;:::-;58496:74;58521:48;:21;58548:20;58521:26;:48::i;58496:74::-;58436:134;;58581:50;;:::i;:::-;58642:37;;:::i;:::-;58690;;:::i;:::-;58744:10;58740:196;;;58788:43;:20;58814:16;58788:25;:43::i;:::-;58771:60;;58740:196;;;58881:43;:20;58907:16;58881:25;:43::i;:::-;58864:60;;58740:196;58954:23;:14;:21;:23::i;:::-;58946:62;;;;-1:-1:-1;;;58946:62:0;;;;;;;:::i;:::-;59039:30;:9;59054:14;59039;:30::i;:::-;59021:48;-1:-1:-1;59097:49:0;:43;59021:48;59118:21;59097:20;:43::i;61660:268::-;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;61782:1:::1;61755:24;61764:14;:12;:14::i;61755:24::-;:28;;;61747:68;;;;-1:-1:-1::0;;;61747:68:0::1;;;;;;;:::i;:::-;61826:25:::0;;:18:::1;:25:::0;;;61892::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;61867:53:::1;::::0;61892:27:::1;::::0;:25:::1;:27::i;60465:264::-:0;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;60589:1:::1;60560:26;60571:14;:12;:14::i;60560:26::-;:30;;;60552:68;;;;-1:-1:-1::0;;;60552:68:0::1;;;;;;;:::i;:::-;60631:25:::0;;:16:::1;:25:::0;;;60695:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;60672:49:::1;::::0;60695:25:::1;::::0;:23:::1;:25::i;63115:133::-:0;63178:22;;:::i;:::-;-1:-1:-1;63213:27:0;;;;;;;;;63220:20;63213:27;;;63115:133;:::o;51679:23::-;;;-1:-1:-1;;;;;51679:23:0;;:::o;62835:125::-;62894:22;;:::i;:::-;-1:-1:-1;62929:23:0;;;;;;;;;62936:16;62929:23;;;62835:125;:::o;52063:32::-;;;-1:-1:-1;;;;;52063:32:0;;:::o;63256:129::-;63317:22;;:::i;:::-;-1:-1:-1;63352:25:0;;;;;;;;;63359:18;63352:25;;;63256:129;:::o;54021:443::-;52757:12;:10;:12::i;:::-;52745:8;;-1:-1:-1;;;;;52745:8:0;;;:24;;;52737:59;;;;-1:-1:-1;;;52737:59:0;;;;;;;:::i;:::-;54189:29:::1;54180:5;:38;;;;;;;;;54176:281;;;54235:15;::::0;:37:::1;::::0;-1:-1:-1;;;54235:37:0;;-1:-1:-1;;;;;54235:15:0;;::::1;::::0;:20:::1;::::0;:37:::1;::::0;54256:7;;54265:6;;54235:37:::1;;;:::i;54176:281::-;54303:28;54294:5;:37;;;;;;;;;54290:167;;;54348:14;::::0;:36:::1;::::0;-1:-1:-1;;;54348:36:0;;-1:-1:-1;;;;;54348:14:0;;::::1;::::0;:19:::1;::::0;:36:::1;::::0;54368:7;;54377:6;;54348:36:::1;;;:::i;11624:244::-:0;10901:12;:10;:12::i;:::-;10891:6;;-1:-1:-1;;;;;10891:6:0;;;:22;;;10883:67;;;;-1:-1:-1;;;10883:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;11713:22:0;::::1;11705:73;;;;-1:-1:-1::0;;;11705:73:0::1;;;;;;;:::i;:::-;11815:6;::::0;11794:38:::1;::::0;-1:-1:-1;;;;;11794:38:0;;::::1;::::0;11815:6:::1;::::0;11794:38:::1;::::0;11815:6:::1;::::0;11794:38:::1;11843:6;:17:::0;;-1:-1:-1;;;;;;11843:17:0::1;-1:-1:-1::0;;;;;11843:17:0;;;::::1;::::0;;;::::1;::::0;;11624:244::o;8952:106::-;9040:10;8952:106;:::o;14152:95::-;14236:3;;14152:95::o;13936:91::-;13975:14;;:::i;:::-;-1:-1:-1;14009:10:0;;;;;;;;;-1:-1:-1;14009:10:0;;13936:91;:::o;14422:222::-;14521:3;;14515;;14494:4;;-1:-1:-1;14511:107:0;;;-1:-1:-1;14548:1:0;14541:8;;14511:107;14577:3;;14571;;:9;14567:51;;;-1:-1:-1;;;14597:9:0;;14567:51;-1:-1:-1;14635:1:0;14422:222;;;;:::o;15115:173::-;15188:14;;:::i;:::-;15215:16;;:::i;:::-;15257:3;;15248;;:13;;:8;:13::i;:::-;15242:19;;;15115:173;-1:-1:-1;;;15115:173:0:o;48231:228::-;48352:34;;:::i;:::-;48331:1;48176;:3;;;-1:-1:-1;;;;;48161:18:0;;48181:21;;;;;;;;;;;;;;;;;48153:50;;;;;-1:-1:-1;;;48153:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;48411:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;48446:3;;48411:40;;-1:-1:-1;48411:40:0;48231:228::o;14683:172::-;14756:14;;:::i;:::-;14783:16;;:::i;:::-;14824:3;;14816;;:12;;:7;:12::i;14899:172::-;14972:14;;:::i;:::-;14999:16;;:::i;:::-;15040:3;;15032;;:12;;:7;:12::i;50277:304::-;50429:34;;:::i;:::-;50408:1;48176;:3;;;-1:-1:-1;;;;;48161:18:0;;48181:21;;;;;;;;;;;;;;;;;48153:50;;;;;-1:-1:-1;;;48153:50:0;;;;;;;;:::i;:::-;;50481:36:::1;;:::i;:::-;50532:22;50539:14;50551:1;50539:11;:14::i;:::-;50532:1:::0;;:6:::1;:22::i;:::-;50528:26:::0;50277:304;-1:-1:-1;;;;;50277:304:0:o;49106:::-;49258:34;;:::i;:::-;49237:1;48176;:3;;;-1:-1:-1;;;;;48161:18:0;;48181:21;;;;;;;;;;;;;;;;;48153:50;;;;;-1:-1:-1;;;48153:50:0;;;;;;;;:::i;:::-;;49310:36:::1;;:::i;:::-;49378:3:::0;;49363;;:20:::1;::::0;:7:::1;:20::i;:::-;49357:26:::0;;;49106:304;-1:-1:-1;;;;49106:304:0:o;21200:269::-;21260:22;;:::i;:::-;21295:24;;:::i;:::-;21334:3;;21340:1;-1:-1:-1;21330:113:0;;;21376:3;;;21372:7;21358:22;;21330:113;;;21427:3;;21413:18;;-1:-1:-1;21413:18:0;21200:269::o;14255:159::-;14328:14;;:::i;:::-;14362:44;;;;;;;;14402:1;:3;;;14370:29;14378:20;14395:2;14378:16;:20::i;:::-;14370:3;;;:7;:29::i;:::-;:35;;;;;;14362:44;;14355:51;14255:159;-1:-1:-1;;;14255:159:0:o;7472:604::-;7914:4;8025:17;8061:7;7472:604;:::o;10265:129::-;7016:13;;;;;;;;:33;;;7033:16;:14;:16::i;:::-;7016:50;;;-1:-1:-1;7054:12:0;;;;7053:13;7016:50;7008:109;;;;-1:-1:-1;;;7008:109:0;;;;;;;:::i;:::-;7130:19;7153:13;;;;;;7152:14;7177:101;;;;7212:13;:20;;-1:-1:-1;;;;7212:20:0;;;;;7247:19;7228:4;7247:19;;;7177:101;10323:26:::1;:24;:26::i;:::-;10360;:24;:26::i;:::-;7308:14:::0;7304:68;;;7355:5;7339:21;;-1:-1:-1;;7339:21:0;;;7304:68;10265:129;:::o;12844:108::-;12903:7;12930:14;12935:1;12938;12941:2;12930:4;:14::i;:::-;12923:21;12844:108;-1:-1:-1;;;12844:108:0:o;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46:0;;;;;;;:::i;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;22471:197::-;22556:20;;:::i;:::-;22589:22;;:::i;:::-;22637:3;;22628;;:13;;:8;:13::i;18089:218::-;18145:6;18175:5;;;18200:6;;;;;;:16;;;18215:1;18210;:6;;18200:16;18199:38;;;;18226:1;18222;:5;:14;;;;;18235:1;18231;:5;18222:14;18191:87;;;;-1:-1:-1;;;18191:87:0;;;;;;;:::i;12254:109::-;12338:17;;12334:2;:21;;12254:109::o;2352:471::-;2410:7;2655:6;2651:47;;-1:-1:-1;2685:1:0;2678:8;;2651:47;2722:5;;;2726:1;2722;:5;:1;2746:5;;;;;:10;2738:56;;;;-1:-1:-1;;;2738:56:0;;;;;;;:::i;8881:65::-;7016:13;;;;;;;;:33;;;7033:16;:14;:16::i;:::-;7016:50;;;-1:-1:-1;7054:12:0;;;;7053:13;7016:50;7008:109;;;;-1:-1:-1;;;7008:109:0;;;;;;;:::i;:::-;7130:19;7153:13;;;;;;7152:14;7177:101;;;;7212:13;:20;;-1:-1:-1;;;;7212:20:0;;;;;7247:19;7228:4;7247:19;;;7308:14;7304:68;;;7355:5;7339:21;;-1:-1:-1;;7339:21:0;;;8881:65;:::o;10402:196::-;7016:13;;;;;;;;:33;;;7033:16;:14;:16::i;:::-;7016:50;;;-1:-1:-1;7054:12:0;;;;7053:13;7016:50;7008:109;;;;-1:-1:-1;;;7008:109:0;;;;;;;:::i;:::-;7130:19;7153:13;;;;;;7152:14;7177:101;;;;7212:13;:20;;-1:-1:-1;;;;7212:20:0;;;;;7247:19;7228:4;7247:19;;;7177:101;10470:17:::1;10490:12;:10;:12::i;:::-;10513:6;:18:::0;;-1:-1:-1;;;;;;10513:18:0::1;-1:-1:-1::0;;;;;10513:18:0;::::1;::::0;;::::1;::::0;;;10547:43:::1;::::0;10513:18;;-1:-1:-1;10513:18:0;-1:-1:-1;;10547:43:0::1;::::0;-1:-1:-1;;10547:43:0::1;7290:1;7308:14:::0;7304:68;;;7355:5;7339:21;;-1:-1:-1;;7339:21:0;;;10402:196;:::o;13053:172::-;13162:7;13189:28;13202:14;13207:8;13202:4;:14::i;:::-;13189:8;:1;13195;13189:5;:8::i;:::-;:12;;:28::i;1901:192::-;1987:7;2023:12;2015:6;;;;2007:29;;;;-1:-1:-1;;;2007:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;2059:5:0;;;1901:192::o;20169:105::-;20226:6;20252:14;20257:1;20260;20263:2;20252:4;:14::i;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;20376:169::-;20483:6;20509:28;20535:1;20509:21;20515:14;20520:8;20515:4;:14::i;:::-;20509:1;;:5;:21::i;:::-;:25;;:28::i;3927:278::-;4013:7;4048:12;4041:5;4033:28;;;;-1:-1:-1;;;4033:28:0;;;;;;;;:::i;:::-;;4072:9;4088:1;4084;:5;;;;;;;3927:278;-1:-1:-1;;;;;3927:278:0:o;16525:568::-;16581:6;16825;16821:47;;-1:-1:-1;16855:1:0;16848:8;;16821:47;16890:1;-1:-1:-1;;16890:7:0;:27;;;;;-1:-1:-1;;;16901:1:0;:16;16890:27;16888:30;16880:82;;;;-1:-1:-1;;;16880:82:0;;;;;;;:::i;:::-;16986:5;;;16990:1;16986;:5;:1;17010:5;;;;;:10;17002:62;;;;-1:-1:-1;;;17002:62:0;;;;;;;:::i;17567:271::-;17623:6;17650;17642:51;;;;-1:-1:-1;;;17642:51:0;;;;;;;:::i;:::-;17714:1;-1:-1:-1;;17714:7:0;:27;;;;;-1:-1:-1;;;17725:1:0;:16;17714:27;17712:30;17704:76;;;;-1:-1:-1;;;17704:76:0;;;;;;;:::i;:::-;17793:8;17808:1;17804;:5;;;;;;;17567:271;-1:-1:-1;;;;17567:271:0:o;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::o;674:319::-;;787:4;775:9;770:3;766:19;762:30;759:2;;;-1:-1;;795:12;759:2;25037;25031:9;787:4;25067:6;25063:17;25174:6;25162:10;25159:22;25138:18;25126:10;25123:34;25120:62;25117:2;;;-1:-1;;25185:12;25117:2;25037;25204:22;1067:20;;897:75;;-1:-1;814:29;753:240;-1:-1;753:240::o;1137:241::-;;1241:2;1229:9;1220:7;1216:23;1212:32;1209:2;;;-1:-1;;1247:12;1209:2;72:20;;-1:-1;;;;;25699:54;;26582:35;;26572:2;;-1:-1;;26621:12;1385:995;;;;;;;;1591:3;1579:9;1570:7;1566:23;1562:33;1559:2;;;-1:-1;;1598:12;1559:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;1650:63;1750:2;1789:22;;1067:20;;-1:-1;1858:2;1897:22;;1067:20;;1966:2;2005:22;;1067:20;;-1:-1;2074:3;2114:22;;1067:20;;-1:-1;2183:3;2223:22;;1067:20;;-1:-1;2292:3;2332:22;1067:20;;-1:-1;1553:827;-1:-1;;;1553:827::o;2387:777::-;;;;;2622:3;2610:9;2601:7;2597:23;2593:33;2590:2;;;-1:-1;;2629:12;2590:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;2681:71;-1:-1;2807:77;2876:7;2789:2;2852:22;;2807:77;:::i;:::-;2797:87;;2939:77;3008:7;2921:2;2988:9;2984:22;2939:77;:::i;:::-;2929:87;;3071:77;3140:7;3053:2;3120:9;3116:22;3071:77;:::i;:::-;3061:87;;2584:580;;;;;;;:::o;3171:259::-;;3284:2;3272:9;3263:7;3259:23;3255:32;3252:2;;;-1:-1;;3290:12;3252:2;230:6;217:20;242:41;277:5;242:41;:::i;3437:509::-;;;;3584:2;3572:9;3563:7;3559:23;3555:32;3552:2;;;-1:-1;;3590:12;3552:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;3642:72;-1:-1;3751:2;3790:22;;72:20;97:33;72:20;97:33;:::i;:::-;3546:400;;3759:63;;-1:-1;;;3859:2;3898:22;;;;1067:20;;3546:400::o;3953:293::-;;4083:2;4071:9;4062:7;4058:23;4054:32;4051:2;;;-1:-1;;4089:12;4051:2;-1:-1;4141:89;4045:201;-1:-1;4045:201::o;4253:289::-;;4381:2;4369:9;4360:7;4356:23;4352:32;4349:2;;;-1:-1;;4387:12;4349:2;4449:77;4518:7;4494:22;4449:77;:::i;4549:462::-;;;4718:2;4706:9;4697:7;4693:23;4689:32;4686:2;;;-1:-1;;4724:12;4686:2;4786:77;4855:7;4831:22;4786:77;:::i;:::-;4776:87;;4918:77;4987:7;4900:2;4967:9;4963:22;4918:77;:::i;:::-;4908:87;;4680:331;;;;;:::o;13860:222::-;-1:-1;;;;;25699:54;;;;5089:37;;13987:2;13972:18;;13958:124::o;14089:333::-;-1:-1;;;;;25699:54;;;;5089:37;;14408:2;14393:18;;13691:37;14244:2;14229:18;;14215:207::o;14694:310::-;;14841:2;;14862:17;14855:47;5452:5;25326:12;25483:6;14841:2;14830:9;14826:18;25471:19;-1:-1;26214:101;26228:6;26225:1;26222:13;26214:101;;;26295:11;;;;;26289:18;26276:11;;;25511:14;26276:11;26269:39;26243:10;;26214:101;;;26330:6;26327:1;26324:13;26321:2;;;-1:-1;25511:14;26386:6;14830:9;26377:16;;26370:27;26321:2;-1:-1;26502:7;26486:14;-1:-1;;26482:28;5610:39;;;;25511:14;5610:39;;14812:192;-1:-1;;;14812:192::o;15011:416::-;15211:2;15225:47;;;5886:2;15196:18;;;25471:19;-1:-1;;;25511:14;;;5902:44;5965:12;;;15182:245::o;15434:416::-;15634:2;15648:47;;;6216:2;15619:18;;;25471:19;6252:34;25511:14;;;6232:55;-1:-1;;;6307:12;;;6300:30;6349:12;;;15605:245::o;15857:416::-;16057:2;16071:47;;;6600:2;16042:18;;;25471:19;6636:29;25511:14;;;6616:50;6685:12;;;16028:245::o;16280:721::-;16581:2;16595:47;;;6936:2;16566:18;;;25471:19;-1:-1;;;25511:14;;;6952:43;7014:12;25520:4;16805:18;;16798:48;;;7265:1;7014:12;;;25471:19;-1:-1;;;25511:14;;;7280:26;7325:12;;;16552:449::o;17008:416::-;17208:2;17222:47;;;7576:2;17193:18;;;25471:19;7612:34;25511:14;;;7592:55;-1:-1;;;7667:12;;;7660:38;7717:12;;;17179:245::o;17431:416::-;17631:2;17645:47;;;7968:2;17616:18;;;25471:19;8004:34;25511:14;;;7984:55;-1:-1;;;8059:12;;;8052:25;8096:12;;;17602:245::o;17854:416::-;18054:2;18068:47;;;8347:2;18039:18;;;25471:19;8383:34;25511:14;;;8363:55;-1:-1;;;8438:12;;;8431:25;8475:12;;;18025:245::o;18277:416::-;18477:2;18491:47;;;18462:18;;;25471:19;8762:34;25511:14;;;8742:55;8816:12;;;18448:245::o;18700:721::-;19001:2;19015:47;;;9067:2;18986:18;;;25471:19;-1:-1;;;25511:14;;;9083:44;9146:12;25520:4;19225:18;;19218:48;;;12156:1;9146:12;;;25471:19;-1:-1;;;25511:14;;;12171:26;12216:12;;;18972:449::o;19428:416::-;19628:2;19642:47;;;9397:2;19613:18;;;25471:19;9433:27;25511:14;;;9413:48;9480:12;;;19599:245::o;19851:416::-;20051:2;20065:47;;;9731:2;20036:18;;;25471:19;-1:-1;;;25511:14;;;9747:45;9811:12;;;20022:245::o;20274:416::-;20474:2;20488:47;;;10062:2;20459:18;;;25471:19;10098:34;25511:14;;;10078:55;-1:-1;;;10153:12;;;10146:31;10196:12;;;20445:245::o;20697:416::-;20897:2;20911:47;;;10447:2;20882:18;;;25471:19;10483:31;25511:14;;;10463:52;10534:12;;;20868:245::o;21120:416::-;21320:2;21334:47;;;10785:2;21305:18;;;25471:19;10821:29;25511:14;;;10801:50;10870:12;;;21291:245::o;21543:416::-;21743:2;21757:47;;;11121:2;21728:18;;;25471:19;-1:-1;;;25511:14;;;11137:45;11201:12;;;21714:245::o;21966:416::-;22166:2;22180:47;;;11452:2;22151:18;;;25471:19;-1:-1;;;25511:14;;;11468:36;11523:12;;;22137:245::o;22389:416::-;22589:2;22603:47;;;11774:2;22574:18;;;25471:19;11810:34;25511:14;;;11790:55;-1:-1;;;11865:12;;;11858:28;11905:12;;;22560:245::o;22812:416::-;23012:2;23026:47;;;22997:18;;;25471:19;12503:34;25511:14;;;12483:55;12557:12;;;22983:245::o;23235:416::-;23435:2;23449:47;;;23420:18;;;25471:19;12844:34;25511:14;;;12824:55;12898:12;;;23406:245::o;23658:416::-;23858:2;23872:47;;;13149:2;23843:18;;;25471:19;-1:-1;;;25511:14;;;13165:41;13225:12;;;23829:245::o;24081:318::-;13510:23;;13691:37;;24256:2;24241:18;;24227:172::o;24406:222::-;13691:37;;;24533:2;24518:18;;24504:124::o;24635:333::-;13691:37;;;24954:2;24939:18;;13691:37;24790:2;24775:18;;24761:207::o;26523:117::-;-1:-1;;;;;25699:54;;26582:35;;26572:2;;26631:1;;26621:12;26647:102;26724:1;26717:5;26714:12;26704:2;;26740:1;;26730:12

Swarm Source

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