Contract 0xb6c8b4e646afc84fd59b7384781d8dc060016f72

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xf1a7a4fd029244c08c6cb16dcbe07468d553e9657776433ed2f8a08b6c2e1c510x6080604087368422021-05-11 2:46:57138 days 4 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.03142846
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x5a54b423f9a45abfce4c5887e1ce84ca62989eb5d3c8a1f8ff4135348051cb51123873562021-09-15 12:22:0710 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x625e5023ff9116ae5bc7345883efe44b87128dd425d7c0f5f23b1e6b54c14314123873492021-09-15 12:21:4610 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x191d40b329b740f1d48a4f240f97bec567eb925ebc2b3cafd57ce2e180c7c8ef123873292021-09-15 12:20:4610 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x6112466e6e95ddff7c7ff01f624e20a5932fad2fe8534a2d2ba090ba563192c8123872632021-09-15 12:17:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xd9d092213f7121c351146ba2ffc4e5b36000c33e51a5e9fb9c33d905b0e187cb123872292021-09-15 12:15:4610 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x885af7b861aed679fb97d62edc3526ea9ca49a7b6f8b047653dbe259953d14c3123872232021-09-15 12:15:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xe1a6657d036e10dce32a5d1e793ac58229765aaa589d329888bea82362d00a43123871692021-09-15 12:12:4610 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x70a7e781a69519fa28a9fafdcba9fd2e46fa735a9b7569d5955617639b62e163123871562021-09-15 12:12:0710 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xe56ab4dadbdad552e6a8a5e66de7f704e5d17032328e51d38c33618fa556ca44123870832021-09-15 12:08:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x3e35a860f6885abb4aa51b3aa070750928d003991653e3fd5f6db41608822c43123870632021-09-15 12:07:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xcee49178f21d6509020e55f7ddab3d131a7235d24eb868299439ab16a984124d123870432021-09-15 12:06:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xd672575061bacea0b8c24cd0723943b1003ee308b00071f302fc7aea5acec457123870362021-09-15 12:06:0710 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xb530f883d09de39b255632d8b5886ba45c2270c5869aab9ae57a1a3396821696123869892021-09-15 12:03:4610 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xc8936efb4c5b324b007dca89699cc3b00b040e9cbf3fef509705a306d22c6211123869632021-09-15 12:02:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xc854986696e5323510929d844a45e283f4dea95767ffba5ec9a6775550c9be1b123869232021-09-15 12:00:2810 days 18 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xea2e58ab6b688628faef7723119ae9c0e5fee41b975db837ba59ef488816d9e6123869162021-09-15 12:00:0710 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x61685772f5b5c89c11c2c65e2278b1bb7f321bec4fc51284412d18b0e8b260bb123869102021-09-15 11:59:4910 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xbd1c8ae56c56ed79fff2f3187327847f670e4f164e7985aa67f4695ac26df89e123869032021-09-15 11:59:2810 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xca98a79a4590cd5c0f5a8cca85f7bb29735d105c0b6d8e7c52302762dc8b07a4123868962021-09-15 11:59:0710 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xe082e3084059adf23dace51d5bb404718be8b23126473aac1ca3a47c7cc76ae4123868892021-09-15 11:58:4610 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x1b2d835d857379bbf74817b3bf9565d5542803a53b2f591c1a64a5c493ef5402123868492021-09-15 11:56:4610 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x500bcad16eec413baf39907f5240d400db766ea14b93aa97b8ddd856e3301a9d123868432021-09-15 11:56:2810 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x6398618bb56849a78952cf91e9543148bc4fa2cd4d90081c80cbacf1ccd0a061123868362021-09-15 11:56:0710 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0x682902b3f9d534fdf7656dea46673c347e57bb9e3107cd9626c0399a0532aca8123868302021-09-15 11:55:4910 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
0xad48587e672f1012c26b3b5b9dc1b7d4631919059fc281bc5f9de6f9025fac30123868232021-09-15 11:55:2810 days 19 hrs ago 0xdcdd9efc1e6d20369a00a350c490282dec6d53b1 0xb6c8b4e646afc84fd59b7384781d8dc060016f720 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xd17AD82Ef186A1657213c80aEC6D8b63862E28c7

Contract Name:
ExchangeState

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at BscScan.com on 2021-05-10
*/

// 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: @openzeppelin/contracts-upgradeable/proxy/Initializable.sol


// solhint-disable-next-line compiler-version


/**
 * @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: @openzeppelin/contracts-upgradeable/GSN/ContextUpgradeable.sol




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

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

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

// File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol




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



/// @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




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



/**
 * @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



/// @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





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 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


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

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



/**
 * @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







/**
 * @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/interface/IExchange.sol







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 getExchangeState() external view returns (address);

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

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

// File: contracts/interface/IInsuranceFund.sol




interface IInsuranceFund {
    function withdraw(Decimal.decimal calldata _amount) external returns (Decimal.decimal memory badDebt);

    function setExchange(IExchange _exchange) external;

    function setBeneficiary(address _beneficiary) external;
}

// File: contracts/interface/ISystemSettings.sol





interface ISystemSettings {
    function insuranceFundFeeRatio() external view returns (Decimal.decimal memory);

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

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

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

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

    function overnightFeePeriod() external view returns (uint256);

    function isExistedExchange(IExchange _exchange) external view returns (bool);

    function getAllExchanges() external view returns (IExchange[] memory);

    function getInsuranceFund(IExchange _exchange) external view returns (IInsuranceFund);

    function setNextOvernightFeeTime(IExchange _exchange) external;

    function nextOvernightFeeTime(address _exchange) external view returns (uint256);

    function checkTransfer(address _from, address _to) external view returns (bool);
}

// File: contracts/MMLPToken.sol





contract MMLPToken is ERC20Upgradeable, OwnableUpgradeable {
    ISystemSettings public systemSettings;

    constructor(
        string memory _name,
        string memory _symbol,
        address _systemSettings
    ) public {
        systemSettings = ISystemSettings(_systemSettings);
        __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);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        amount;
        require(systemSettings.checkTransfer(from, to), "illegal transfer");
    }
}

// File: contracts/interface/IExchangeState.sol







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/ISakePerpVault.sol






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 setRiskLiquidityWeight(address _exchange, uint256 _highWeight, uint256 _lowWeight) external;

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

// File: contracts/utils/MixedDecimal.sol





/// @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












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,
        address systemSettings
    ) 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", systemSettings);
        LowRiskLPToken = new MMLPToken("MM Low Risk LP Token", "MLT", systemSettings);
    }

    /**
     * @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"},{"internalType":"address","name":"systemSettings","type":"address"}],"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"}]

608060405234801561001057600080fd5b50613808806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001f05760003560e01c806383acb48a1162000111578063cfe7110311620000a5578063e79f7005116200007b578063e79f700514620003b7578063eeb016f214620003c1578063eebab8ef14620003cb578063f2fde38b14620003e257620001f0565b8063cfe711031462000399578063d2f7265a14620003a3578063e57d563614620003ad57620001f0565b80638eb86e8b11620000e75780638eb86e8b146200033d5780639bf5d1d41462000354578063b4448711146200036b578063c9dde756146200038257620001f0565b806383acb48a1462000312578063848ff684146200031c5780638da5cb5b146200033357620001f0565b8063524f15a1116200018957806362267955116200015f5780636226795514620002d05780636c12744614620002e75780636febdd5014620002fe578063715018a6146200030857620001f0565b8063524f15a114620002985780635254541014620002af5780636050cf1e14620002b957620001f0565b8063203b378811620001cb578063203b3788146200024957806337292b60146200026057806350799c81146200026a57806351f59d0c146200028157620001f0565b80630dd68c7014620001f557806311377394146200020e57806313f2ca711462000230575b600080fd5b6200020c6200020636600462001b79565b620003f9565b005b62000218620004ba565b604051620002279190620020e8565b60405180910390f35b6200023a620004d8565b60405162000227919062001bb2565b6200020c6200025a36600462001b5b565b620004e7565b62000218620005b8565b620002186200027b36600462001a74565b620005d6565b6200023a6200029236600462001ad5565b6200074f565b6200020c620002a936600462001b5b565b62000789565b62000218620007c9565b6200020c620002ca36600462001b5b565b620007e7565b62000218620002e136600462001b43565b62000827565b6200020c620002f836600462001b5b565b62000890565b620002186200093f565b6200020c6200095d565b62000218620009e1565b6200020c6200032d36600462001a01565b620009ff565b6200023a62000c0f565b6200020c6200034e36600462001af4565b62000c1e565b620002186200036536600462001a74565b62000d45565b6200020c6200037c36600462001b5b565b62000e28565b6200020c6200039336600462001b5b565b62000ed7565b6200021862000f86565b6200023a62000fa4565b6200021862000fb3565b6200023a62000fd1565b6200021862000fe0565b6200020c620003dc36600462001af4565b62000ffe565b6200020c620003f3366004620019e3565b620010cc565b620004036200118b565b6033546001600160a01b039081169116146200043c5760405162461bcd60e51b8152600401620004339062001e0b565b60405180910390fd5b81516067819055815160685560408051602081019091529081527f7338f3784ceb8f9456bac0c4a69f1c6354dc325fa6455e3e3f6a8a9bf9249a7c9062000483906200118f565b604080516020810190915260685481526200049e906200118f565b604051620004ae929190620020fb565b60405180910390a15050565b620004c46200196b565b506040805160208101909152606754815290565b606e546001600160a01b031681565b620004f16200118b565b6033546001600160a01b03908116911614620005215760405162461bcd60e51b8152600401620004339062001e0b565b6000620005396200053162001193565b8390620011b0565b60000b136200055c5760405162461bcd60e51b8152600401620004339062001f49565b8051606b81905560408051602081019091529081527f6f825f18b787836f7cf974799b160538ab237aa0d14af3611fa69683a40c6d22906200059e906200118f565b604051620005ad9190620020f2565b60405180910390a150565b620005c26200196b565b506040805160208101909152606f54815290565b620005e06200196b565b620005eb846200118f565b6200060257620005fa62001193565b905062000747565b6000808660018111156200061257fe5b1490506200061f6200196b565b620006356200062f8686620011e5565b62001211565b9050620006416200196b565b6200064b6200196b565b620006556200196b565b8415620006705762000668888a6200127b565b91506200067f565b6200067c888a6200129e565b91505b6200068a826200118f565b620006a95760405162461bcd60e51b8152600401620004339062001fb7565b620006b58483620012c1565b9250620006cd620006c7848962001341565b620013ba565b9050620006f0620006ea83620006e387620013ba565b90620013ee565b6200118f565b15620007405784156200072157604080516020810190915260018152620007199082906200129e565b905062000740565b6040805160208101909152600181526200073d9082906200127b565b90505b9450505050505b949350505050565b60008160018111156200075e57fe5b620007765750606d546001600160a01b031662000784565b50606e546001600160a01b03165b919050565b620007936200118b565b6033546001600160a01b03908116911614620007c35760405162461bcd60e51b8152600401620004339062001e0b565b51606655565b620007d36200196b565b506040805160208101909152606854815290565b620007f16200118b565b6033546001600160a01b03908116911614620008215760405162461bcd60e51b8152600401620004339062001e0b565b51606f55565b620008316200196b565b62000846620006ea3684900384018462001b5b565b6200085d576200085562001193565b905062000784565b604080516020810190915260665481526200088a90620008833685900385018562001b5b565b90620011e5565b92915050565b6200089a6200118b565b6033546001600160a01b03908116911614620008ca5760405162461bcd60e51b8152600401620004339062001e0b565b6000620008da6200053162001193565b60000b13620008fd5760405162461bcd60e51b8152600401620004339062002052565b8051606a81905560408051602081019091529081527fe75e3e311afafb466335ae8af3bf1d55443d8937fb5ada14583f4fca729c0fa8906200059e906200118f565b620009496200196b565b506040805160208101909152606654815290565b620009676200118b565b6033546001600160a01b03908116911614620009975760405162461bcd60e51b8152600401620004339062001e0b565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b620009eb6200196b565b506040805160208101909152606a54815290565b600054610100900460ff168062000a1b575062000a1b62001433565b8062000a2a575060005460ff16155b62000a495760405162461bcd60e51b8152600401620004339062001d3b565b600054610100900460ff1615801562000a75576000805460ff1961ff0019909116610100171660011790555b861580159062000a8457508515155b801562000a9057508415155b801562000a9c57508315155b62000abb5760405162461bcd60e51b8152600401620004339062001fe7565b62000ac562001439565b606580546001600160a01b0319166001600160a01b038b161790556040805160208082018352908a905260668a905581518082018352899052606989905581518082018352889052606a88905581518082018352879052606b87905581518082018352869052606c86905581519081018252849052606f84905551829062000b4d906200197e565b62000b59919062001e40565b604051809103906000f08015801562000b76573d6000803e3d6000fd5b50606d80546001600160a01b0319166001600160a01b0392909216919091179055604051829062000ba7906200197e565b62000bb3919062001ce1565b604051809103906000f08015801562000bd0573d6000803e3d6000fd5b50606e80546001600160a01b0319166001600160a01b0392909216919091179055801562000c04576000805461ff00191690555b505050505050505050565b6033546001600160a01b031690565b62000c286200118b565b6065546001600160a01b0390811691161462000c585760405162461bcd60e51b8152600401620004339062001ed2565b600083600181111562000c6757fe5b141562000cdc57606d54604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac9062000ca2908590859060040162001bc6565b600060405180830381600087803b15801562000cbd57600080fd5b505af115801562000cd2573d6000803e3d6000fd5b5050505062000d40565b600183600181111562000ceb57fe5b141562000d2657606e54604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac9062000ca2908590859060040162001bc6565b60405162461bcd60e51b81526004016200043390620020bc565b505050565b62000d4f6200196b565b62000d5a846200118f565b62000d6957620005fa62001193565b60008086600181111562000d7957fe5b14905062000d866200196b565b62000d966200062f8686620011e5565b905062000da26200196b565b62000dac6200196b565b62000db66200196b565b841562000dd15762000dc9878a6200127b565b915062000de0565b62000ddd878a6200129e565b91505b62000deb826200118f565b62000e0a5760405162461bcd60e51b8152600401620004339062001c35565b62000e168483620012c1565b9250620006cd620006c7848a62001341565b62000e326200118b565b6033546001600160a01b0390811691161462000e625760405162461bcd60e51b8152600401620004339062001e0b565b600062000e726200053162001193565b60000b1362000e955760405162461bcd60e51b8152600401620004339062001f80565b8051606c81905560408051602081019091529081527f0565ffb26c5ec0ddf0975584b3c48758d8486aea008bd280bf2c98f2464f441f906200059e906200118f565b62000ee16200118b565b6033546001600160a01b0390811691161462000f115760405162461bcd60e51b8152600401620004339062001e0b565b600062000f216200053162001193565b60000b1362000f445760405162461bcd60e51b8152600401620004339062001e9b565b8051606981905560408051602081019091529081527fd67453718fc57aad470d91be51568530ed02cc941c846cd9e281dc56b300e95e906200059e906200118f565b62000f906200196b565b506040805160208101909152606b54815290565b6065546001600160a01b031681565b62000fbd6200196b565b506040805160208101909152606954815290565b606d546001600160a01b031681565b62000fea6200196b565b506040805160208101909152606c54815290565b620010086200118b565b6065546001600160a01b03908116911614620010385760405162461bcd60e51b8152600401620004339062001ed2565b60008360018111156200104757fe5b14156200108257606d546040516340c10f1960e01b81526001600160a01b03909116906340c10f199062000ca2908590859060040162001bc6565b60018360018111156200109157fe5b141562000d2657606e546040516340c10f1960e01b81526001600160a01b03909116906340c10f199062000ca2908590859060040162001bc6565b620010d66200118b565b6033546001600160a01b03908116911614620011065760405162461bcd60e51b8152600401620004339062001e0b565b6001600160a01b0381166200112f5760405162461bcd60e51b8152600401620004339062001c64565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b5190565b6200119d6200196b565b5060408051602081019091526000815290565b805182516000911015620011c7575060016200088a565b815183511015620011dc57506000196200088a565b50600092915050565b620011ef6200196b565b620011f96200196b565b825184516200120891620014d9565b81529392505050565b6200121b6200196b565b8180600001516001600160ff1b031015604051806060016040528060338152602001620037a06033913990620012665760405162461bcd60e51b815260040162000433919062001bdf565b50506040805160208101909152915182525090565b620012856200196b565b6200128f6200196b565b825184516200120891620014f0565b620012a86200196b565b620012b26200196b565b82518451620012089162001518565b620012cb6200196b565b8180600001516001600160ff1b031015604051806060016040528060338152602001620037a06033913990620013165760405162461bcd60e51b815260040162000433919062001bdf565b50620013216200196b565b62001338620013308562001211565b86906200155c565b95945050505050565b6200134b6200196b565b8180600001516001600160ff1b031015604051806060016040528060338152602001620037a06033913990620013965760405162461bcd60e51b815260040162000433919062001bdf565b50620013a16200196b565b83518551620013b0916200157f565b8152949350505050565b620013c46200196b565b620013ce6200196b565b825160001315620013e657825160000381526200088a565b915182525090565b620013f86200196b565b6040518060200160405280836000015162001421620014186012620015cb565b875190620015d4565b816200142957fe5b0690529392505050565b303b1590565b600054610100900460ff16806200145557506200145562001433565b8062001464575060005460ff16155b620014835760405162461bcd60e51b8152600401620004339062001d3b565b600054610100900460ff16158015620014af576000805460ff1961ff0019909116610100171660011790555b620014b962001614565b620014c36200169e565b8015620014d6576000805461ff00191690555b50565b6000620014e98383601262001783565b9392505050565b600082820183811015620014e95760405162461bcd60e51b8152600401620004339062001caa565b6000620014e983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250620017a7565b620015666200196b565b620015706200196b565b825184516200120891620017d6565b6000818303818312801590620015955750838113155b80620015ac5750600083128015620015ac57508381135b620014e95760405162461bcd60e51b815260040162000433906200200e565b60ff16600a0a90565b600082620015e5575060006200088a565b82820282848281620015f357fe5b0414620014e95760405162461bcd60e51b8152600401620004339062001dca565b600054610100900460ff16806200163057506200163062001433565b806200163f575060005460ff16155b6200165e5760405162461bcd60e51b8152600401620004339062001d3b565b600054610100900460ff16158015620014c3576000805460ff1961ff0019909116610100171660011790558015620014d6576000805461ff001916905550565b600054610100900460ff1680620016ba5750620016ba62001433565b80620016c9575060005460ff16155b620016e85760405162461bcd60e51b8152600401620004339062001d3b565b600054610100900460ff1615801562001714576000805460ff1961ff0019909116610100171660011790555b6000620017206200118b565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015620014d6576000805461ff001916905550565b6000620007476200179483620015cb565b620017a08686620015d4565b90620017e6565b60008184841115620017ce5760405162461bcd60e51b815260040162000433919062001bdf565b505050900390565b6000620014e9838360126200182a565b6000620014e983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200184f565b60006200074783620018486200184085620015cb565b87906200188a565b90620018ff565b60008183620018735760405162461bcd60e51b815260040162000433919062001bdf565b5060008385816200188057fe5b0495945050505050565b6000826200189b575060006200088a565b82600019148015620018b05750600160ff1b82145b15620018d05760405162461bcd60e51b8152600401620004339062001f02565b82820282848281620018de57fe5b0514620014e95760405162461bcd60e51b8152600401620004339062001f02565b600081620019215760405162461bcd60e51b8152600401620004339062002087565b81600019148015620019365750600160ff1b83145b15620019565760405162461bcd60e51b8152600401620004339062001d89565b60008284816200196257fe5b05949350505050565b6040518060200160405280600081525090565b611688806200211883390190565b80356001600160a01b03811681146200088a57600080fd5b600060208284031215620019b6578081fd5b6040516020810181811067ffffffffffffffff82111715620019d6578283fd5b6040529135825250919050565b600060208284031215620019f5578081fd5b620014e983836200198c565b600080600080600080600080610100898b03121562001a1e578384fd5b62001a2a8a8a6200198c565b97506020890135965060408901359550606089013594506080890135935060a0890135925060c0890135915062001a658a60e08b016200198c565b90509295985092959890939650565b6000806000806080858703121562001a8a578384fd5b843562001a978162002109565b935062001aa88660208701620019a4565b925062001ab98660408701620019a4565b915062001aca8660608701620019a4565b905092959194509250565b60006020828403121562001ae7578081fd5b8135620014e98162002109565b60008060006060848603121562001b09578283fd5b833562001b168162002109565b925060208401356001600160a01b038116811462001b32578283fd5b929592945050506040919091013590565b60006020828403121562001b55578081fd5b50919050565b60006020828403121562001b6d578081fd5b620014e98383620019a4565b6000806040838503121562001b8c578182fd5b62001b988484620019a4565b915062001ba98460208501620019a4565b90509250929050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6000602080835283518082850152825b8181101562001c0d5785810183015185820160400152820162001bef565b8181111562001c1f5783604083870101525b50601f01601f1916929092016040019392505050565b602080825260159082015274062617365206173736574206166746572206973203605c1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60608082526014908201527326a6902637bb902934b9b5902628102a37b5b2b760611b608082015260a0602082018190526003908201526213531560ea1b60c08201526001600160a01b0391909116604082015260e00190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60608082526015908201527426a6902434b3b4102934b9b5902628102a37b5b2b760591b608082015260a0602082018190526003908201526213521560ea1b60c08201526001600160a01b0391909116604082015260e00190565b60208082526019908201527f696e76616c696420696e6974206d617267696e20726174696f00000000000000604082015260600190565b60208082526016908201527563616c6c6572206973206e6f742065786368616e676560501b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252601d908201527f696e76616c6964206c69717569646174696f6e2066656520726174696f000000604082015260600190565b6020808252601b908201527f696e76616c6964206d6178206c69717569646174696f6e206665650000000000604082015260600190565b602080825260169082015275071756f746520617373657420616674657220697320360541b604082015260600190565b6020808252600d908201526c1a5b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252818101527f696e76616c6964206d61696e74656e616e6365206d617267696e20726174696f604082015260600190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601290820152711a5b9d985b1a59081c9a5cdac81b195d995b60721b604082015260600190565b9051815260200190565b90815260200190565b918252602082015260400190565b60028110620014d657600080fdfe60806040523480156200001157600080fd5b50604051620016883803806200168883398101604081905262000034916200053d565b609780546001600160a01b0319166001600160a01b0383161790556200005b83836200006e565b620000656200011b565b50505062000614565b600054610100900460ff16806200008a57506200008a620001bb565b8062000099575060005460ff16155b620000c15760405162461bcd60e51b8152600401620000b890620005c6565b60405180910390fd5b600054610100900460ff16158015620000ed576000805460ff1961ff0019909116610100171660011790555b620000f7620001c1565b6200010383836200024b565b801562000116576000805461ff00191690555b505050565b600054610100900460ff168062000137575062000137620001bb565b8062000146575060005460ff16155b620001655760405162461bcd60e51b8152600401620000b890620005c6565b600054610100900460ff1615801562000191576000805460ff1961ff0019909116610100171660011790555b6200019b620001c1565b620001a562000311565b8015620001b8576000805461ff00191690555b50565b303b1590565b600054610100900460ff1680620001dd5750620001dd620001bb565b80620001ec575060005460ff16155b6200020b5760405162461bcd60e51b8152600401620000b890620005c6565b600054610100900460ff16158015620001a5576000805460ff1961ff0019909116610100171660011790558015620001b8576000805461ff001916905550565b600054610100900460ff168062000267575062000267620001bb565b8062000276575060005460ff16155b620002955760405162461bcd60e51b8152600401620000b890620005c6565b600054610100900460ff16158015620002c1576000805460ff1961ff0019909116610100171660011790555b8251620002d6906036906020860190620003fa565b508151620002ec906037906020850190620003fa565b506038805460ff19166012179055801562000116576000805461ff0019169055505050565b600054610100900460ff16806200032d57506200032d620001bb565b806200033c575060005460ff16155b6200035b5760405162461bcd60e51b8152600401620000b890620005c6565b600054610100900460ff1615801562000387576000805460ff1961ff0019909116610100171660011790555b600062000393620003f6565b606580546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015620001b8576000805461ff001916905550565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200043d57805160ff19168380011785556200046d565b828001600101855582156200046d579182015b828111156200046d57825182559160200191906001019062000450565b506200047b9291506200047f565b5090565b5b808211156200047b576000815560010162000480565b600082601f830112620004a7578081fd5b81516001600160401b0380821115620004be578283fd5b6040516020601f8401601f1916820181018381118382101715620004e0578586fd5b80604052508194508382528681858801011115620004fd57600080fd5b600092505b8383101562000521578583018101518284018201529182019162000502565b83831115620005335760008185840101525b5050505092915050565b60008060006060848603121562000552578283fd5b83516001600160401b038082111562000569578485fd5b620005778783880162000496565b945060208601519150808211156200058d578384fd5b506200059c8682870162000496565b604086015190935090506001600160a01b0381168114620005bb578182fd5b809150509250925092565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61106480620006246000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a25780639dc29fac116100715780639dc29fac146101f3578063a457c2d714610206578063a9059cbb14610219578063dd62ed3e1461022c578063f2fde38b1461023f5761010b565b806370a08231146101c8578063715018a6146101db5780638da5cb5b146101e357806395d89b41146101eb5761010b565b8063313ce567116100de578063313ce56714610176578063395093511461018b57806340c10f191461019e57806360b42f12146101b35761010b565b806306fdde0314610110578063095ea7b31461012e57806318160ddd1461014e57806323b872dd14610163575b600080fd5b610118610252565b6040516101259190610cb5565b60405180910390f35b61014161013c366004610c32565b6102e8565b6040516101259190610caa565b610156610306565b6040516101259190610f6a565b610141610171366004610bf2565b61030c565b61017e610393565b6040516101259190610f73565b610141610199366004610c32565b61039c565b6101b16101ac366004610c32565b6103ea565b005b6101bb610436565b6040516101259190610c7c565b6101566101d6366004610ba3565b610445565b6101b1610460565b6101bb6104df565b6101186104ee565b6101b1610201366004610c32565b61054f565b610141610214366004610c32565b61058e565b610141610227366004610c32565b6105f6565b61015661023a366004610bbe565b61060a565b6101b161024d366004610ba3565b610635565b60368054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156102de5780601f106102b3576101008083540402835291602001916102de565b820191906000526020600020905b8154815290600101906020018083116102c157829003601f168201915b5050505050905090565b60006102fc6102f56106ec565b84846106f0565b5060015b92915050565b60355490565b60006103198484846107a4565b610389846103256106ec565b61038485604051806060016040528060288152602001610fe2602891396001600160a01b038a166000908152603460205260408120906103636106ec565b6001600160a01b0316815260208101919091526040016000205491906108b9565b6106f0565b5060019392505050565b60385460ff1690565b60006102fc6103a96106ec565b8461038485603460006103ba6106ec565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906108e5565b6103f26106ec565b6065546001600160a01b039081169116146104285760405162461bcd60e51b815260040161041f90610e34565b60405180910390fd5b6104328282610911565b5050565b6097546001600160a01b031681565b6001600160a01b031660009081526033602052604090205490565b6104686106ec565b6065546001600160a01b039081169116146104955760405162461bcd60e51b815260040161041f90610e34565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b6065546001600160a01b031690565b60378054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156102de5780601f106102b3576101008083540402835291602001916102de565b6105576106ec565b6065546001600160a01b039081169116146105845760405162461bcd60e51b815260040161041f90610e34565b61043282826109d1565b60006102fc61059b6106ec565b846103848560405180606001604052806025815260200161100a60259139603460006105c56106ec565b6001600160a01b03908116825260208083019390935260409182016000908120918d168152925290205491906108b9565b60006102fc6106036106ec565b84846107a4565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61063d6106ec565b6065546001600160a01b0390811691161461066a5760405162461bcd60e51b815260040161041f90610e34565b6001600160a01b0381166106905760405162461bcd60e51b815260040161041f90610d75565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b0383166107165760405162461bcd60e51b815260040161041f90610eef565b6001600160a01b03821661073c5760405162461bcd60e51b815260040161041f90610dbb565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610797908590610f6a565b60405180910390a3505050565b6001600160a01b0383166107ca5760405162461bcd60e51b815260040161041f90610eaa565b6001600160a01b0382166107f05760405162461bcd60e51b815260040161041f90610d08565b6107fb838383610aa7565b61083881604051806060016040528060268152602001610fbc602691396001600160a01b03861660009081526033602052604090205491906108b9565b6001600160a01b03808516600090815260336020526040808220939093559084168152205461086790826108e5565b6001600160a01b0380841660008181526033602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610797908590610f6a565b600081848411156108dd5760405162461bcd60e51b815260040161041f9190610cb5565b505050900390565b60008282018381101561090a5760405162461bcd60e51b815260040161041f90610dfd565b9392505050565b6001600160a01b0382166109375760405162461bcd60e51b815260040161041f90610f33565b61094360008383610aa7565b60355461095090826108e5565b6035556001600160a01b03821660009081526033602052604090205461097690826108e5565b6001600160a01b0383166000818152603360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109c5908590610f6a565b60405180910390a35050565b6001600160a01b0382166109f75760405162461bcd60e51b815260040161041f90610e69565b610a0382600083610aa7565b610a4081604051806060016040528060228152602001610f9a602291396001600160a01b03851660009081526033602052604090205491906108b9565b6001600160a01b038316600090815260336020526040902055603554610a669082610b4a565b6035556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109c5908590610f6a565b60975460405163d2ad07fb60e01b81526001600160a01b039091169063d2ad07fb90610ad99086908690600401610c90565b60206040518083038186803b158015610af157600080fd5b505afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190610c5c565b610b455760405162461bcd60e51b815260040161041f90610d4b565b505050565b600061090a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506108b9565b80356001600160a01b038116811461030057600080fd5b600060208284031215610bb4578081fd5b61090a8383610b8c565b60008060408385031215610bd0578081fd5b610bda8484610b8c565b9150610be98460208501610b8c565b90509250929050565b600080600060608486031215610c06578081fd5b8335610c1181610f81565b92506020840135610c2181610f81565b929592945050506040919091013590565b60008060408385031215610c44578182fd5b610c4e8484610b8c565b946020939093013593505050565b600060208284031215610c6d578081fd5b8151801515811461090a578182fd5b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b6000602080835283518082850152825b81811015610ce157858101830151858201604001528201610cc5565b81811115610cf25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526010908201526f34b63632b3b0b6103a3930b739b332b960811b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b90815260200190565b60ff91909116815260200190565b6001600160a01b0381168114610f9657600080fd5b5056fe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212207b5ca8d29e999a1d99c5dd086165a06186b1cc06959c66c4cfdd3dc69f3372cc64736f6c634300060c00334d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a264697066735822122076fb0a27ec79e80f62f7f0a3f97701c41b50ab3bbb513fa7138997ae9845b51f64736f6c634300060c0033

Deployed ByteCode Sourcemap

52399:12927:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61398:362;;;;;;:::i;:::-;;:::i;:::-;;63941:136;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53444:31;;;:::i;:::-;;;;;;;:::i;62669:284::-;;;;;;:::i;:::-;;:::i;64920:135::-;;;:::i;57769:1599::-;;;;;;:::i;:::-;;:::i;65063:260::-;;;;;;:::i;:::-;;:::i;63482:122::-;;;;;;:::i;:::-;;:::i;64085:144::-;;;:::i;63775:158::-;;;;;;:::i;:::-;;:::i;56579:315::-;;;;;;:::i;:::-;;:::i;62254:299::-;;;;;;:::i;:::-;;:::i;64795:117::-;;;:::i;11195:148::-;;;:::i;64370:139::-;;;:::i;54164:1152::-;;;;;;:::i;:::-;;:::i;10553:79::-;;;:::i;55968:443::-;;;;;;:::i;:::-;;:::i;59376:1586::-;;;;;;:::i;:::-;;:::i;63063:268::-;;;;;;:::i;:::-;;:::i;61868:264::-;;;;;;:::i;:::-;;:::i;64517:133::-;;;:::i;53021:23::-;;;:::i;64237:125::-;;;:::i;53405:32::-;;;:::i;64658:129::-;;;:::i;55424:443::-;;;;;;:::i;:::-;;:::i;11498:244::-;;;;;;:::i;:::-;;:::i;61398:362::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;;;;;;;;;61557:42;;:20:::1;:42:::0;;;61610:50;;:24:::1;:50:::0;61687:27:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;61676:76:::1;::::0;61687:29:::1;::::0;:27:::1;:29::i;:::-;61718:31;::::0;;::::1;::::0;::::1;::::0;;;:24:::1;:31:::0;;;:33:::1;::::0;:31:::1;:33::i;:::-;61676:76;;;;;;;:::i;:::-;;;;;;;;61398:362:::0;;:::o;63941:136::-;64007:22;;:::i;:::-;-1:-1:-1;64042:27:0;;;;;;;;;64049:20;64042:27;;;63941:136;:::o;53444:31::-;;;-1:-1:-1;;;;;53444:31:0;;:::o;62669:284::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;62797:1:::1;62768:26;62779:14;:12;:14::i;:::-;62768:6:::0;;:10:::1;:26::i;:::-;:30;;;62760:72;;;;-1:-1:-1::0;;;62760:72:0::1;;;;;;;:::i;:::-;62843:29:::0;;:20:::1;:29:::0;;;62915:27:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;62888:57:::1;::::0;62915:29:::1;::::0;:27:::1;:29::i;:::-;62888:57;;;;;;:::i;:::-;;;;;;;;62669:284:::0;:::o;64920:135::-;64984:22;;:::i;:::-;-1:-1:-1;65019:28:0;;;;;;;;;65026:21;65019:28;;;64920:135;:::o;57769:1599::-;58035:22;;:::i;:::-;58074:26;:17;:24;:26::i;:::-;58070:85;;58129:14;:12;:14::i;:::-;58122:21;;;;58070:85;58167:15;;58185:4;:37;;;;;;;;;58167:55;;58233:44;;:::i;:::-;58293:74;58318:48;:21;58345:20;58318:26;:48::i;:::-;58293:24;:74::i;:::-;58233:134;;58378:49;;:::i;:::-;58438:38;;:::i;:::-;58487;;:::i;:::-;58540:10;58536:202;;;58585:45;:21;58612:17;58585:26;:45::i;:::-;58567:63;;58536:202;;;58681:45;:21;58708:17;58681:26;:45::i;:::-;58663:63;;58536:202;58756:24;:15;:22;:24::i;:::-;58748:64;;;;-1:-1:-1;;;58748:64:0;;;;;;;:::i;:::-;58842:31;:9;58857:15;58842:14;:31::i;:::-;58825:48;-1:-1:-1;58902:47:0;:41;58825:48;58922:20;58902:19;:41::i;:::-;:45;:47::i;:::-;58884:65;;59039:46;:37;59060:15;59039;:9;:13;:15::i;:::-;:20;;:37::i;:::-;:44;:46::i;:::-;:51;59035:291;;59111:10;59107:208;;;59181:18;;;;;;;;;59197:1;59181:18;;59160:40;;:15;;:20;:40::i;:::-;59142:58;;59107:208;;;59280:18;;;;;;;;;59296:1;59280:18;;59259:40;;:15;;:20;:40::i;:::-;59241:58;;59107:208;59345:15;-1:-1:-1;;;;;57769:1599:0;;;;;;;:::o;65063:260::-;65147:9;65206:5;65173:38;;;;;;;;65169:147;;-1:-1:-1;65235:15:0;;-1:-1:-1;;;;;65235:15:0;65228:22;;65169:147;-1:-1:-1;65290:14:0;;-1:-1:-1;;;;;65290:14:0;65169:147;65063:260;;;:::o;63482:122::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;63570:26;:12:::1;:26:::0;63482:122::o;64085:144::-;64155:22;;:::i;:::-;-1:-1:-1;64190:31:0;;;;;;;;;64197:24;64190:31;;;64085:144;:::o;63775:158::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;63881:44;:21:::1;:44:::0;63775:158::o;56579:315::-;56708:22;;:::i;:::-;56752:26;:24;;;;;;;:17;:24;:::i;:26::-;56748:85;;56807:14;:12;:14::i;:::-;56800:21;;;;56748:85;56850:36;;;;;;;;;56873:12;56850:36;;;;;:22;;;;;;;:17;:22;:::i;:::-;;;:36::i;:::-;56843:43;56579:315;-1:-1:-1;;56579:315:0:o;62254:299::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;62385:1:::1;62356:26;62367:14;:12;:14::i;62356:26::-;:30;;;62348:75;;;;-1:-1:-1::0;;;62348:75:0::1;;;;;;;:::i;:::-;62434:32:::0;;:23:::1;:32:::0;;;62512:30:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;62482:63:::1;::::0;62512:32:::1;::::0;:30:::1;:32::i;64795:117::-:0;64850:22;;:::i;:::-;-1:-1:-1;64885:19:0;;;;;;;;;64892:12;64885:19;;;64795:117;:::o;11195:148::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;11286:6:::1;::::0;11265:40:::1;::::0;11302:1:::1;::::0;-1:-1:-1;;;;;11286:6:0::1;::::0;11265:40:::1;::::0;11302:1;;11265:40:::1;11316:6;:19:::0;;-1:-1:-1;;;;;;11316:19:0::1;::::0;;11195:148::o;64370:139::-;64436:22;;:::i;:::-;-1:-1:-1;64471:30:0;;;;;;;;;64478:23;64471:30;;;64370:139;:::o;54164:1152::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;54522:20;;;::::1;::::0;:51:::1;;-1:-1:-1::0;54546:27:0;;::::1;54522:51;:79;;;;-1:-1:-1::0;54577:24:0;;::::1;54522:79;:105;;;;-1:-1:-1::0;54605:22:0;;::::1;54522:105;54500:168;;;;-1:-1:-1::0;;;54500:168:0::1;;;;;;;:::i;:::-;54679:16;:14;:16::i;:::-;54708:8;:20:::0;;-1:-1:-1;;;;;;54708:20:0::1;-1:-1:-1::0;;;;;54708:20:0;::::1;;::::0;;54754:28:::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;54739:12:::1;:43:::0;;;54812:32;;;;::::1;::::0;;;;;54793:16:::1;:51:::0;;;54881:39;;;;::::1;::::0;;;;;54855:23:::1;:65:::0;;;54954:36;;;;::::1;::::0;;;;;54931:20:::1;:59:::0;;;55022:34;;;;::::1;::::0;;;;;55001:18:::1;:55:::0;;;55091:37;;;;::::1;::::0;;;;;55067:21:::1;:61:::0;;;55159;55205:14;;55159:61:::1;::::0;::::1;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;55141:15:0::1;:79:::0;;-1:-1:-1;;;;;;55141:79:0::1;-1:-1:-1::0;;;;;55141:79:0;;;::::1;::::0;;;::::1;::::0;;55248:60:::1;::::0;55293:14;;55248:60:::1;::::0;::::1;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;55231:14:0::1;:77:::0;;-1:-1:-1;;;;;;55231:77:0::1;-1:-1:-1::0;;;;;55231:77:0;;;::::1;::::0;;;::::1;::::0;;7257:68;;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;7257:68;54164:1152;;;;;;;;;:::o;10553:79::-;10618:6;;-1:-1:-1;;;;;10618:6:0;10553:79;:::o;55968:443::-;54097:12;:10;:12::i;:::-;54085:8;;-1:-1:-1;;;;;54085:8:0;;;:24;;;54077:59;;;;-1:-1:-1;;;54077:59:0;;;;;;;:::i;:::-;56136:29:::1;56127:5;:38;;;;;;;;;56123:281;;;56182:15;::::0;:37:::1;::::0;-1:-1:-1;;;56182:37:0;;-1:-1:-1;;;;;56182:15:0;;::::1;::::0;:20:::1;::::0;:37:::1;::::0;56203:7;;56212:6;;56182:37:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;56123:281;;;56250:28;56241:5;:37;;;;;;;;;56237:167;;;56295:14;::::0;:36:::1;::::0;-1:-1:-1;;;56295:36:0;;-1:-1:-1;;;;;56295:14:0;;::::1;::::0;:19:::1;::::0;:36:::1;::::0;56315:7;;56324:6;;56295:36:::1;;;:::i;56237:167::-;56364:28;;-1:-1:-1::0;;;56364:28:0::1;;;;;;;:::i;56237:167::-;55968:443:::0;;;:::o;59376:1586::-;59642:22;;:::i;:::-;59681:25;:16;:23;:25::i;:::-;59677:84;;59735:14;:12;:14::i;59677:84::-;59773:15;;59791:4;:37;;;;;;;;;59773:55;;59839:44;;:::i;:::-;59899:74;59924:48;:21;59951:20;59924:26;:48::i;59899:74::-;59839:134;;59984:50;;:::i;:::-;60045:37;;:::i;:::-;60093;;:::i;:::-;60147:10;60143:196;;;60191:43;:20;60217:16;60191:25;:43::i;:::-;60174:60;;60143:196;;;60284:43;:20;60310:16;60284:25;:43::i;:::-;60267:60;;60143:196;60357:23;:14;:21;:23::i;:::-;60349:62;;;;-1:-1:-1;;;60349:62:0;;;;;;;:::i;:::-;60442:30;:9;60457:14;60442;:30::i;:::-;60424:48;-1:-1:-1;60500:49:0;:43;60424:48;60521:21;60500:20;:43::i;63063:268::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;63185:1:::1;63158:24;63167:14;:12;:14::i;63158:24::-;:28;;;63150:68;;;;-1:-1:-1::0;;;63150:68:0::1;;;;;;;:::i;:::-;63229:25:::0;;:18:::1;:25:::0;;;63295::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;63270:53:::1;::::0;63295:27:::1;::::0;:25:::1;:27::i;61868:264::-:0;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;61992:1:::1;61963:26;61974:14;:12;:14::i;61963:26::-;:30;;;61955:68;;;;-1:-1:-1::0;;;61955:68:0::1;;;;;;;:::i;:::-;62034:25:::0;;:16:::1;:25:::0;;;62098:23:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;62075:49:::1;::::0;62098:25:::1;::::0;:23:::1;:25::i;64517:133::-:0;64580:22;;:::i;:::-;-1:-1:-1;64615:27:0;;;;;;;;;64622:20;64615:27;;;64517:133;:::o;53021:23::-;;;-1:-1:-1;;;;;53021:23:0;;:::o;64237:125::-;64296:22;;:::i;:::-;-1:-1:-1;64331:23:0;;;;;;;;;64338:16;64331:23;;;64237:125;:::o;53405:32::-;;;-1:-1:-1;;;;;53405:32:0;;:::o;64658:129::-;64719:22;;:::i;:::-;-1:-1:-1;64754:25:0;;;;;;;;;64761:18;64754:25;;;64658:129;:::o;55424:443::-;54097:12;:10;:12::i;:::-;54085:8;;-1:-1:-1;;;;;54085:8:0;;;:24;;;54077:59;;;;-1:-1:-1;;;54077:59:0;;;;;;;:::i;:::-;55592:29:::1;55583:5;:38;;;;;;;;;55579:281;;;55638:15;::::0;:37:::1;::::0;-1:-1:-1;;;55638:37:0;;-1:-1:-1;;;;;55638:15:0;;::::1;::::0;:20:::1;::::0;:37:::1;::::0;55659:7;;55668:6;;55638:37:::1;;;:::i;55579:281::-;55706:28;55697:5;:37;;;;;;;;;55693:167;;;55751:14;::::0;:36:::1;::::0;-1:-1:-1;;;55751:36:0;;-1:-1:-1;;;;;55751:14:0;;::::1;::::0;:19:::1;::::0;:36:::1;::::0;55771:7;;55780:6;;55751:36:::1;;;:::i;11498:244::-:0;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;11587:22:0;::::1;11579:73;;;;-1:-1:-1::0;;;11579:73:0::1;;;;;;;:::i;:::-;11689:6;::::0;11668:38:::1;::::0;-1:-1:-1;;;;;11668:38:0;;::::1;::::0;11689:6:::1;::::0;11668:38:::1;::::0;11689:6:::1;::::0;11668:38:::1;11717:6;:17:::0;;-1:-1:-1;;;;;;11717:17:0::1;-1:-1:-1::0;;;;;11717:17:0;;;::::1;::::0;;;::::1;::::0;;11498:244::o;8859:106::-;8947:10;8859:106;:::o;13974:95::-;14058:3;;13974:95::o;13758:91::-;13797:14;;:::i;:::-;-1:-1:-1;13831:10:0;;;;;;;;;-1:-1:-1;13831:10:0;;13758:91;:::o;14244:222::-;14343:3;;14337;;14316:4;;-1:-1:-1;14333:107:0;;;-1:-1:-1;14370:1:0;14363:8;;14333:107;14399:3;;14393;;:9;14389:51;;;-1:-1:-1;;;14419:9:0;;14389:51;-1:-1:-1;14457:1:0;14244:222;;;;:::o;14937:173::-;15010:14;;:::i;:::-;15037:16;;:::i;:::-;15079:3;;15070;;:13;;:8;:13::i;:::-;15064:19;;;14937:173;-1:-1:-1;;;14937:173:0:o;49579:228::-;49700:34;;:::i;:::-;49679:1;49524;:3;;;-1:-1:-1;;;;;49509:18:0;;49529:21;;;;;;;;;;;;;;;;;49501:50;;;;;-1:-1:-1;;;49501:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;49759:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;49794:3;;49759:40;;-1:-1:-1;49759:40:0;49579:228::o;14505:172::-;14578:14;;:::i;:::-;14605:16;;:::i;:::-;14646:3;;14638;;:12;;:7;:12::i;14721:172::-;14794:14;;:::i;:::-;14821:16;;:::i;:::-;14862:3;;14854;;:12;;:7;:12::i;51625:304::-;51777:34;;:::i;:::-;51756:1;49524;:3;;;-1:-1:-1;;;;;49509:18:0;;49529:21;;;;;;;;;;;;;;;;;49501:50;;;;;-1:-1:-1;;;49501:50:0;;;;;;;;:::i;:::-;;51829:36:::1;;:::i;:::-;51880:22;51887:14;51899:1;51887:11;:14::i;:::-;51880:1:::0;;:6:::1;:22::i;:::-;51876:26:::0;51625:304;-1:-1:-1;;;;;51625:304:0:o;50454:::-;50606:34;;:::i;:::-;50585:1;49524;:3;;;-1:-1:-1;;;;;49509:18:0;;49529:21;;;;;;;;;;;;;;;;;49501:50;;;;;-1:-1:-1;;;49501:50:0;;;;;;;;:::i;:::-;;50658:36:::1;;:::i;:::-;50726:3:::0;;50711;;:20:::1;::::0;:7:::1;:20::i;:::-;50705:26:::0;;;50454:304;-1:-1:-1;;;;50454:304:0:o;20937:269::-;20997:22;;:::i;:::-;21032:24;;:::i;:::-;21071:3;;21077:1;-1:-1:-1;21067:113:0;;;21113:3;;;21109:7;21095:22;;21067:113;;;21164:3;;21150:18;;-1:-1:-1;21150:18:0;20937:269::o;14077:159::-;14150:14;;:::i;:::-;14184:44;;;;;;;;14224:1;:3;;;14192:29;14200:20;14217:2;14200:16;:20::i;:::-;14192:3;;;:7;:29::i;:::-;:35;;;;;;14184:44;;14177:51;14077:159;-1:-1:-1;;;14077:159:0:o;7425:604::-;7867:4;7978:17;8014:7;7425:604;:::o;10139:129::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;10197:26:::1;:24;:26::i;:::-;10234;:24;:26::i;:::-;7261:14:::0;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;7257:68;10139:129;:::o;12692:108::-;12751:7;12778:14;12783:1;12786;12789:2;12778:4;:14::i;:::-;12771:21;12692:108;-1:-1:-1;;;12692: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;22208:197::-;22293:20;;:::i;:::-;22326:22;;:::i;:::-;22374:3;;22365;;:13;;:8;:13::i;17878:218::-;17934:6;17964:5;;;17989:6;;;;;;:16;;;18004:1;17999;:6;;17989:16;17988:38;;;;18015:1;18011;:5;:14;;;;;18024:1;18020;:5;18011:14;17980:87;;;;-1:-1:-1;;;17980:87:0;;;;;;;:::i;12102:109::-;12186:17;;12182:2;:21;;12102: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;8788:65::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7261:14;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;8788:65;:::o;10276:196::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;10344:17:::1;10364:12;:10;:12::i;:::-;10387:6;:18:::0;;-1:-1:-1;;;;;;10387:18:0::1;-1:-1:-1::0;;;;;10387:18:0;::::1;::::0;;::::1;::::0;;;10421:43:::1;::::0;10387:18;;-1:-1:-1;10387:18:0;-1:-1:-1;;10421:43:0::1;::::0;-1:-1:-1;;10421:43:0::1;7243:1;7261:14:::0;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;10276:196;:::o;12901:172::-;13010:7;13037:28;13050:14;13055:8;13050:4;:14::i;:::-;13037:8;:1;13043;13037: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;19932:105::-;19989:6;20015:14;20020:1;20023;20026:2;20015:4;:14::i;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;20139:169::-;20246:6;20272:28;20298:1;20272:21;20278:14;20283:8;20278:4;:14::i;:::-;20272: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;16314:568::-;16370:6;16614;16610:47;;-1:-1:-1;16644:1:0;16637:8;;16610:47;16679:1;-1:-1:-1;;16679:7:0;:27;;;;;-1:-1:-1;;;16690:1:0;:16;16679:27;16677:30;16669:82;;;;-1:-1:-1;;;16669:82:0;;;;;;;:::i;:::-;16775:5;;;16779:1;16775;:5;:1;16799:5;;;;;:10;16791:62;;;;-1:-1:-1;;;16791:62:0;;;;;;;:::i;17356:271::-;17412:6;17439;17431:51;;;;-1:-1:-1;;;17431:51:0;;;;;;;:::i;:::-;17503:1;-1:-1:-1;;17503:7:0;:27;;;;;-1:-1:-1;;;17514:1:0;:16;17503:27;17501:30;17493:76;;;;-1:-1:-1;;;17493:76:0;;;;;;;:::i;:::-;17582:8;17597:1;17593;:5;;;;;;;17356:271;-1:-1:-1;;;;17356:271:0:o;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::o;5:130::-;72:20;;-1:-1;;;;;26047:54;;26930:35;;26920:2;;26979:1;;26969:12;674:319;;787:4;775:9;770:3;766:19;762:30;759:2;;;-1:-1;;795:12;759:2;25385;25379:9;787:4;25415:6;25411:17;25522:6;25510:10;25507:22;25486:18;25474:10;25471:34;25468:62;25465:2;;;-1:-1;;25533:12;25465:2;25385;25552: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;1309:53;1354:7;1330:22;1309:53;:::i;1385:1121::-;;;;;;;;;1608:3;1596:9;1587:7;1583:23;1579:33;1576:2;;;-1:-1;;1615:12;1576:2;1677:53;1722:7;1698:22;1677:53;:::i;:::-;1667:63;;1767:2;1810:9;1806:22;1067:20;1775:63;;1875:2;1918:9;1914:22;1067:20;1883:63;;1983:2;2026:9;2022:22;1067:20;1991:63;;2091:3;2135:9;2131:22;1067:20;2100:63;;2200:3;2244:9;2240:22;1067:20;2209:63;;2309:3;2353:9;2349:22;1067:20;2318:63;;2437:53;2482:7;2418:3;2462:9;2458:22;2437:53;:::i;:::-;2427:63;;1570:936;;;;;;;;;;;:::o;2513:777::-;;;;;2748:3;2736:9;2727:7;2723:23;2719:33;2716:2;;;-1:-1;;2755:12;2716:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;2807:71;-1:-1;2933:77;3002:7;2915:2;2978:22;;2933:77;:::i;:::-;2923:87;;3065:77;3134:7;3047:2;3114:9;3110:22;3065:77;:::i;:::-;3055:87;;3197:77;3266:7;3179:2;3246:9;3242:22;3197:77;:::i;:::-;3187:87;;2710:580;;;;;;;:::o;3297:259::-;;3410:2;3398:9;3389:7;3385:23;3381:32;3378:2;;;-1:-1;;3416:12;3378:2;230:6;217:20;242:41;277:5;242:41;:::i;3563:509::-;;;;3710:2;3698:9;3689:7;3685:23;3681:32;3678:2;;;-1:-1;;3716:12;3678:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;3768:72;-1:-1;3877:2;3916:22;;72:20;-1:-1;;;;;26047:54;;26930:35;;26920:2;;-1:-1;;26969:12;26920:2;3672:400;;3885:63;;-1:-1;;;3985:2;4024:22;;;;1067:20;;3672:400::o;4079:293::-;;4209:2;4197:9;4188:7;4184:23;4180:32;4177:2;;;-1:-1;;4215:12;4177:2;-1:-1;4267:89;4171:201;-1:-1;4171:201::o;4379:289::-;;4507:2;4495:9;4486:7;4482:23;4478:32;4475:2;;;-1:-1;;4513:12;4475:2;4575:77;4644:7;4620:22;4575:77;:::i;4675:462::-;;;4844:2;4832:9;4823:7;4819:23;4815:32;4812:2;;;-1:-1;;4850:12;4812:2;4912:77;4981:7;4957:22;4912:77;:::i;:::-;4902:87;;5044:77;5113:7;5026:2;5093:9;5089:22;5044:77;:::i;:::-;5034:87;;4806:331;;;;;:::o;13986:222::-;-1:-1;;;;;26047:54;;;;5215:37;;14113:2;14098:18;;14084:124::o;14215:333::-;-1:-1;;;;;26047:54;;;;5215:37;;14534:2;14519:18;;13817:37;14370:2;14355:18;;14341:207::o;14820:310::-;;14967:2;;14988:17;14981:47;5578:5;25674:12;25831:6;14967:2;14956:9;14952:18;25819:19;-1:-1;26562:101;26576:6;26573:1;26570:13;26562:101;;;26643:11;;;;;26637:18;26624:11;;;25859:14;26624:11;26617:39;26591:10;;26562:101;;;26678:6;26675:1;26672:13;26669:2;;;-1:-1;25859:14;26734:6;14956:9;26725:16;;26718:27;26669:2;-1:-1;26850:7;26834:14;-1:-1;;26830:28;5736:39;;;;25859:14;5736:39;;14938:192;-1:-1;;;14938:192::o;15137:416::-;15337:2;15351:47;;;6012:2;15322:18;;;25819:19;-1:-1;;;25859:14;;;6028:44;6091:12;;;15308:245::o;15560:416::-;15760:2;15774:47;;;6342:2;15745:18;;;25819:19;6378:34;25859:14;;;6358:55;-1:-1;;;6433:12;;;6426:30;6475:12;;;15731:245::o;15983:416::-;16183:2;16197:47;;;6726:2;16168:18;;;25819:19;6762:29;25859:14;;;6742:50;6811:12;;;16154:245::o;16406:832::-;16735:2;16749:47;;;7062:2;16720:18;;;25819:19;-1:-1;;;25859:14;;;7078:43;7140:12;25868:4;16959:18;;16952:48;;;7391:1;7140:12;;;25819:19;-1:-1;;;25859:14;;;7406:26;-1:-1;;;;;26047:54;;;;-1:-1;17209:18;;5215:37;7451:12;;;16706:532::o;17245:416::-;17445:2;17459:47;;;7702:2;17430:18;;;25819:19;7738:34;25859:14;;;7718:55;-1:-1;;;7793:12;;;7786:38;7843:12;;;17416:245::o;17668:416::-;17868:2;17882:47;;;8094:2;17853:18;;;25819:19;8130:34;25859:14;;;8110:55;-1:-1;;;8185:12;;;8178:25;8222:12;;;17839:245::o;18091:416::-;18291:2;18305:47;;;8473:2;18276:18;;;25819:19;8509:34;25859:14;;;8489:55;-1:-1;;;8564:12;;;8557:25;8601:12;;;18262:245::o;18514:416::-;18714:2;18728:47;;;18699:18;;;25819:19;8888:34;25859:14;;;8868:55;8942:12;;;18685:245::o;18937:832::-;19266:2;19280:47;;;9193:2;19251:18;;;25819:19;-1:-1;;;25859:14;;;9209:44;9272:12;25868:4;19490:18;;19483:48;;;12282:1;9272:12;;;25819:19;-1:-1;;;25859:14;;;12297:26;-1:-1;;;;;26047:54;;;;-1:-1;19740:18;;5215:37;12342:12;;;19237:532::o;19776:416::-;19976:2;19990:47;;;9523:2;19961:18;;;25819:19;9559:27;25859:14;;;9539:48;9606:12;;;19947:245::o;20199:416::-;20399:2;20413:47;;;9857:2;20384:18;;;25819:19;-1:-1;;;25859:14;;;9873:45;9937:12;;;20370:245::o;20622:416::-;20822:2;20836:47;;;10188:2;20807:18;;;25819:19;10224:34;25859:14;;;10204:55;-1:-1;;;10279:12;;;10272:31;10322:12;;;20793:245::o;21045:416::-;21245:2;21259:47;;;10573:2;21230:18;;;25819:19;10609:31;25859:14;;;10589:52;10660:12;;;21216:245::o;21468:416::-;21668:2;21682:47;;;10911:2;21653:18;;;25819:19;10947:29;25859:14;;;10927:50;10996:12;;;21639:245::o;21891:416::-;22091:2;22105:47;;;11247:2;22076:18;;;25819:19;-1:-1;;;25859:14;;;11263:45;11327:12;;;22062:245::o;22314:416::-;22514:2;22528:47;;;11578:2;22499:18;;;25819:19;-1:-1;;;25859:14;;;11594:36;11649:12;;;22485:245::o;22737:416::-;22937:2;22951:47;;;11900:2;22922:18;;;25819:19;11936:34;25859:14;;;11916:55;-1:-1;;;11991:12;;;11984:28;12031:12;;;22908:245::o;23160:416::-;23360:2;23374:47;;;23345:18;;;25819:19;12629:34;25859:14;;;12609:55;12683:12;;;23331:245::o;23583:416::-;23783:2;23797:47;;;23768:18;;;25819:19;12970:34;25859:14;;;12950:55;13024:12;;;23754:245::o;24006:416::-;24206:2;24220:47;;;13275:2;24191:18;;;25819:19;-1:-1;;;25859:14;;;13291:41;13351:12;;;24177:245::o;24429:318::-;13636:23;;13817:37;;24604:2;24589:18;;24575:172::o;24754:222::-;13817:37;;;24881:2;24866:18;;24852:124::o;24983:333::-;13817:37;;;25302:2;25287:18;;13817:37;25138:2;25123:18;;25109:207::o;26995:102::-;27072:1;27065:5;27062:12;27052:2;;27088:1;;27078:12

Swarm Source

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