Contract 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec50

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x2b1355583cacd8e65e2f2b8c22408f20735fd3d37d7592d7af2da86049bcd2490x6080604087368312021-05-11 2:46:24137 days 23 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.04135019
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x5a54b423f9a45abfce4c5887e1ce84ca62989eb5d3c8a1f8ff4135348051cb51123873562021-09-15 12:22:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x5a54b423f9a45abfce4c5887e1ce84ca62989eb5d3c8a1f8ff4135348051cb51123873562021-09-15 12:22:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x5a54b423f9a45abfce4c5887e1ce84ca62989eb5d3c8a1f8ff4135348051cb51123873562021-09-15 12:22:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x625e5023ff9116ae5bc7345883efe44b87128dd425d7c0f5f23b1e6b54c14314123873492021-09-15 12:21:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x625e5023ff9116ae5bc7345883efe44b87128dd425d7c0f5f23b1e6b54c14314123873492021-09-15 12:21:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x625e5023ff9116ae5bc7345883efe44b87128dd425d7c0f5f23b1e6b54c14314123873492021-09-15 12:21:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x191d40b329b740f1d48a4f240f97bec567eb925ebc2b3cafd57ce2e180c7c8ef123873292021-09-15 12:20:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x191d40b329b740f1d48a4f240f97bec567eb925ebc2b3cafd57ce2e180c7c8ef123873292021-09-15 12:20:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x191d40b329b740f1d48a4f240f97bec567eb925ebc2b3cafd57ce2e180c7c8ef123873292021-09-15 12:20:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x6112466e6e95ddff7c7ff01f624e20a5932fad2fe8534a2d2ba090ba563192c8123872632021-09-15 12:17:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x6112466e6e95ddff7c7ff01f624e20a5932fad2fe8534a2d2ba090ba563192c8123872632021-09-15 12:17:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x6112466e6e95ddff7c7ff01f624e20a5932fad2fe8534a2d2ba090ba563192c8123872632021-09-15 12:17:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xd9d092213f7121c351146ba2ffc4e5b36000c33e51a5e9fb9c33d905b0e187cb123872292021-09-15 12:15:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xd9d092213f7121c351146ba2ffc4e5b36000c33e51a5e9fb9c33d905b0e187cb123872292021-09-15 12:15:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xd9d092213f7121c351146ba2ffc4e5b36000c33e51a5e9fb9c33d905b0e187cb123872292021-09-15 12:15:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x885af7b861aed679fb97d62edc3526ea9ca49a7b6f8b047653dbe259953d14c3123872232021-09-15 12:15:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x885af7b861aed679fb97d62edc3526ea9ca49a7b6f8b047653dbe259953d14c3123872232021-09-15 12:15:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x885af7b861aed679fb97d62edc3526ea9ca49a7b6f8b047653dbe259953d14c3123872232021-09-15 12:15:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xe1a6657d036e10dce32a5d1e793ac58229765aaa589d329888bea82362d00a43123871692021-09-15 12:12:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xe1a6657d036e10dce32a5d1e793ac58229765aaa589d329888bea82362d00a43123871692021-09-15 12:12:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xe1a6657d036e10dce32a5d1e793ac58229765aaa589d329888bea82362d00a43123871692021-09-15 12:12:4610 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x70a7e781a69519fa28a9fafdcba9fd2e46fa735a9b7569d5955617639b62e163123871562021-09-15 12:12:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x70a7e781a69519fa28a9fafdcba9fd2e46fa735a9b7569d5955617639b62e163123871562021-09-15 12:12:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0x70a7e781a69519fa28a9fafdcba9fd2e46fa735a9b7569d5955617639b62e163123871562021-09-15 12:12:0710 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
0xe56ab4dadbdad552e6a8a5e66de7f704e5d17032328e51d38c33618fa556ca44123870832021-09-15 12:08:2810 days 14 hrs ago 0x2b090de2128d34b3fd502e2ef4c414e64d879b90 0x398e0f41e3d6eddc5122f2572ab83d2c9062ec500 BNB
[ Download CSV Export 
Loading

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

Contract Name:
SakePerpVault

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/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/utils/AddressUpgradeable.sol



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

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

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

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

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

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

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

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

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

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

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

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

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

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

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






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

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

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

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

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

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

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

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

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




/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    function __ReentrancyGuard_init() internal initializer {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal initializer {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
    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/ISakePerpVaultTypes.sol

pragma experimental ABIEncoderV2;

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

// File: contracts/types/IExchangeTypes.sol




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/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/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/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: @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/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/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/SakePerpVault.sol
















contract SakePerpVault is ISakePerpVault, OwnableUpgradeable {
    using Decimal for Decimal.decimal;
    using SignedDecimal for SignedDecimal.signedDecimal;
    using MixedDecimal for SignedDecimal.signedDecimal;
    using SafeERC20Upgradeable for IERC20Upgradeable;
    using SafeMathUpgradeable for uint256;

    //
    // EVENTS
    //
    event LiquidityAdd(
        address indexed exchange,
        address indexed account,
        uint256 risk,
        uint256 lpfund,
        uint256 tokenamount
    );
    event LiquidityRemove(
        address indexed exchange,
        address indexed account,
        uint256 risk,
        uint256 lpfund,
        uint256 tokenamount
    );
    //changeType shows the liquidity changed by what
    event LiquidityModify(address indexed exchange, uint256 lpfundHigh, uint256 lpfundLow);
    event BadDebtResolved(
        address indexed exchange,
        uint256 badDebt,
        uint256 insuranceFundResolveBadDebt,
        uint256 mmHighResolveBadDebt,
        uint256 mmLowResolveBadDebt
    );

    struct PoolInfo {
        SignedDecimal.signedDecimal totalLiquidity; // total liquidity of high/low risk pool
        Decimal.decimal totalFund; // fund of MM, not include the fee and pnl
        mapping(address => Decimal.decimal) fund;
        mapping(address => uint256) nextWithdrawTime;
        uint256 maxLoss;
    }

    struct ExchangeInfo {
        mapping(uint256 => PoolInfo) poolInfo; // pool info of high/low risk pool
        Decimal.decimal cachedLiquidity;
        uint256 highRiskLiquidityWeight;
        uint256 lowRiskLiquidityWeight;
    }

    uint256 private constant UINT100 = 100;
    ISystemSettings public systemSettings;
    address public sakePerp;
    uint256 public lpLockTime;

    // exchange info
    mapping(address => ExchangeInfo) public exchangeInfo;

    //**********************************************************//
    //    Can not change the order of above state variables     //
    //**********************************************************//

    //◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//

    //◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
    uint256[50] private __gap;

    //
    // MODIFIERS
    //
    modifier onlySakePerp() {
        require(_msgSender() == sakePerp, "only sakePerp");
        _;
    }

    //
    // PUBLIC
    //
    function initialize(
        address _sakePerp,
        address _systemSettings,
        uint256 _lockTime
    ) public initializer {
        sakePerp = _sakePerp;
        systemSettings = ISystemSettings(_systemSettings);
        lpLockTime = _lockTime;
        __Ownable_init();
    }

    /**
     * @notice set SakePerp dependency
     * @dev only owner can call
     * @param _sakePerp address
     */
    function setSakePerp(address _sakePerp) external onlyOwner {
        require(_sakePerp != address(0), "empty address");
        sakePerp = _sakePerp;
    }

    /**
     * @notice set systemSettings dependency
     * @dev only owner can call
     * @param _systemSettings address
     */
    function setSystemSettings(address _systemSettings) external onlyOwner {
        require(_systemSettings != address(0), "empty address");
        systemSettings = ISystemSettings(_systemSettings);
    }

    /**
     * @notice set high risk liquidity provider token weight
     * @dev only owner can call
     * @param _exchange address
     * @param _highWeight high risk pool lp token weight
     * @param _lowWeight low risk pool lp token weight
     */
    function setRiskLiquidityWeight(
        address _exchange,
        uint256 _highWeight,
        uint256 _lowWeight
    ) public override {
        require(_msgSender() == owner() || _msgSender() == _exchange, "invalid caller");
        require(_highWeight.add(_lowWeight) > 0, "invalid weight");
        exchangeInfo[_exchange].highRiskLiquidityWeight = _highWeight;
        exchangeInfo[_exchange].lowRiskLiquidityWeight = _lowWeight;
    }

    /**
     * @notice set pool max loss
     * @dev only owner can call
     * @param _exchange exchange address
     * @param _risk pool type
     * @param _max max loss
     */
    function setMaxLoss(
        address _exchange,
        Risk _risk,
        uint256 _max
    ) public override {
        require(_msgSender() == owner() || _msgSender() == _exchange, "invalid caller");
        require(_max > 0 && _max <= UINT100, "invalid max loss value");
        PoolInfo storage poolInfo = exchangeInfo[_exchange].poolInfo[uint256(_risk)];
        SignedDecimal.signedDecimal memory lpUnrealizedPNL = getLpUnrealizedPNL(_exchange, _risk);
        Decimal.decimal memory lockedLiquidity = poolInfo.totalFund.mulScalar(UINT100 - _max).divScalar(UINT100);
        require(!poolInfo.totalLiquidity.subD(lockedLiquidity).addD(lpUnrealizedPNL).isNegative(), "fund not enough");
        poolInfo.maxLoss = _max;
    }

    /**
     * @notice set lp liquidity lock time
     * @dev only owner can call
     * @param _lockTime new lock time
     */
    function setLpLockTime(uint256 _lockTime) external onlyOwner {
        lpLockTime = _lockTime;
    }

    /**
     * @notice withdraw token to trader/liquidator
     * @dev only SakePerp can call
     * @param _exchange exchange address
     * @param _receiver receiver, could be trader or liquidator
     * @param _amount token amount
     */
    function withdraw(
        IExchange _exchange,
        address _receiver,
        Decimal.decimal memory _amount
    ) public override onlySakePerp {
        _withdraw(_exchange, _receiver, _amount);
    }

    function _withdraw(
        IExchange _exchange,
        address _receiver,
        Decimal.decimal memory _amount
    ) internal {
        IERC20Upgradeable _token = _exchange.quoteAsset();
        Decimal.decimal memory totalTokenBalance = Decimal.decimal(_token.balanceOf(address(this)));
        if (totalTokenBalance.toUint() < _amount.toUint()) {
            Decimal.decimal memory balanceShortage = _amount.subD(totalTokenBalance);
            IInsuranceFund insuranceFund = systemSettings.getInsuranceFund(_exchange);
            Decimal.decimal memory totalInsurceFund = Decimal.decimal(_token.balanceOf(address(insuranceFund)));
            require(totalInsurceFund.toUint() >= balanceShortage.toUint(), "Fund not enough");
            insuranceFund.withdraw(balanceShortage);
        }

        _token.safeTransfer(_receiver, _amount.toUint());
    }

    function _realizeMMBadDebt(address _exchange, Decimal.decimal memory _badDebt)
        internal
        returns (Decimal.decimal memory, Decimal.decimal memory)
    {
        Decimal.decimal memory mmHighResolveBadDebt = Decimal.zero();
        Decimal.decimal memory mmLowResolveBadDebt = Decimal.zero();

        (SignedDecimal.signedDecimal memory highAvailable, SignedDecimal.signedDecimal memory lowAvailable) =
            getAllMMAvailableLiquidityWithPNL(_exchange);
        require(highAvailable.addD(lowAvailable).subD(_badDebt).toInt() >= 0, "MM Bankrupt");

        (Decimal.decimal memory highFactor, Decimal.decimal memory lowFactor) = _getMMFactor(_exchange);
        mmHighResolveBadDebt = _badDebt.mulD(highFactor).divD(highFactor.addD(lowFactor));
        mmLowResolveBadDebt = _badDebt.subD(mmHighResolveBadDebt);

        SignedDecimal.signedDecimal memory highRemainLiquidity = highAvailable.subD(mmHighResolveBadDebt);
        SignedDecimal.signedDecimal memory lowRemainLiquidity = lowAvailable.subD(mmLowResolveBadDebt);
        if (highRemainLiquidity.isNegative()) {
            mmHighResolveBadDebt = highAvailable.abs();
            mmLowResolveBadDebt = _badDebt.subD(mmHighResolveBadDebt);
        } else if (lowRemainLiquidity.isNegative()) {
            mmLowResolveBadDebt = lowAvailable.abs();
            mmHighResolveBadDebt = _badDebt.subD(mmLowResolveBadDebt);
        }

        PoolInfo storage highPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)];
        PoolInfo storage lowPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)];
        highPool.totalLiquidity = highPool.totalLiquidity.subD(mmHighResolveBadDebt);
        lowPool.totalLiquidity = lowPool.totalLiquidity.subD(mmLowResolveBadDebt);

        return (mmHighResolveBadDebt, mmLowResolveBadDebt);
    }

    /**
     * @notice realize bad debt. insurance fund will pay first, lp fund will pay the rest
     * @dev only SakePerp can call
     * @param _exchange IExchange address
     * @param _badDebt amount of the bad debt
     */
    function realizeBadDebt(IExchange _exchange, Decimal.decimal memory _badDebt) external override onlySakePerp {
        // in order to realize all the bad debt vault need extra tokens from insuranceFund
        IInsuranceFund insuranceFund = systemSettings.getInsuranceFund(_exchange);
        Decimal.decimal memory totalInsuranceFund =
            Decimal.decimal(_exchange.quoteAsset().balanceOf(address(insuranceFund)));
        Decimal.decimal memory mmResolveBadDebt = Decimal.zero();
        Decimal.decimal memory insuranceFundResolveBadDebt = Decimal.zero();
        Decimal.decimal memory mmHighResolveBadDebt = Decimal.zero();
        Decimal.decimal memory mmLowResolveBadDebt = Decimal.zero();

        if (totalInsuranceFund.toUint() >= _badDebt.toUint()) {
            insuranceFund.withdraw(_badDebt);
            insuranceFundResolveBadDebt = _badDebt;
            mmResolveBadDebt = Decimal.zero();
        } else {
            insuranceFund.withdraw(totalInsuranceFund);
            insuranceFundResolveBadDebt = totalInsuranceFund;
            mmResolveBadDebt = _badDebt.subD(totalInsuranceFund);
        }

        if (mmResolveBadDebt.toUint() > 0) {
            (mmHighResolveBadDebt, mmLowResolveBadDebt) = _realizeMMBadDebt(address(_exchange), mmResolveBadDebt);
        }

        emit BadDebtResolved(
            address(_exchange),
            _badDebt.toUint(),
            insuranceFundResolveBadDebt.toUint(),
            mmHighResolveBadDebt.toUint(),
            mmLowResolveBadDebt.toUint()
        );
    }

    /**
     * @notice add cached liquidity to mm's total liquidity
     */
    function modifyLiquidity() external override {
        address _exchange = _msgSender();
        require(systemSettings.isExistedExchange(IExchange(_exchange)), "exchange not found");
        (Decimal.decimal memory highFactor, Decimal.decimal memory lowFactor) = _getMMFactor(_exchange);
        ExchangeInfo storage _exchangeInfo = exchangeInfo[_exchange];
        PoolInfo storage highPool = _exchangeInfo.poolInfo[uint256(Risk.HIGH)];
        PoolInfo storage lowPool = _exchangeInfo.poolInfo[uint256(Risk.LOW)];
        Decimal.decimal memory cachedLiquidity = _exchangeInfo.cachedLiquidity;
        Decimal.decimal memory cachedForHigh = cachedLiquidity.mulD(highFactor).divD(highFactor.addD(lowFactor));
        Decimal.decimal memory cachedForLow = cachedLiquidity.subD(cachedForHigh);
        highPool.totalLiquidity = highPool.totalLiquidity.addD(cachedForHigh);
        lowPool.totalLiquidity = lowPool.totalLiquidity.addD(cachedForLow);
        _exchangeInfo.cachedLiquidity = Decimal.zero();
        emit LiquidityModify(_exchange, cachedForHigh.toUint(), cachedForLow.toUint());
    }

    /**
     * @notice addCachedLiquidity (trader fee, overnight fee, trading spread)
     * @param _exchange exchange address
     * @param _DeltaLpLiquidity liquidity amount to be added
     */
    function addCachedLiquidity(address _exchange, Decimal.decimal memory _DeltaLpLiquidity)
        public
        override
        onlySakePerp
    {
        ExchangeInfo storage _exchangeInfo = exchangeInfo[_exchange];
        _exchangeInfo.cachedLiquidity = _exchangeInfo.cachedLiquidity.addD(_DeltaLpLiquidity);
    }

    /**
     * @notice addLiquidity to Exchange
     * @param _exchange IExchange address
     * @param _risk pool type
     * @param _quoteAssetAmount quote asset amount in 18 digits. Can Not be 0
     */
    function addLiquidity(
        IExchange _exchange,
        Risk _risk,
        Decimal.decimal memory _quoteAssetAmount
    ) external {
        requireExchange(_exchange, true);
        requireNonZeroInput(_quoteAssetAmount);

        address sender = _msgSender();
        PoolInfo storage poolInfo = exchangeInfo[address(_exchange)].poolInfo[uint256(_risk)];
        SignedDecimal.signedDecimal memory lpUnrealizedPNL = getLpUnrealizedPNL(address(_exchange), _risk);

        Decimal.decimal memory totalLpTokenAmount =
            Decimal.decimal(IExchangeState(_exchange.getExchangeState()).getLPToken(_risk).totalSupply());
        if (totalLpTokenAmount.toUint() > 0) {
            _requireMMNotBankrupt(address(_exchange), _risk);
        }

        SignedDecimal.signedDecimal memory returnLpAmount = SignedDecimal.zero();
        if (totalLpTokenAmount.toUint() == 0) {
            returnLpAmount = MixedDecimal.fromDecimal(_quoteAssetAmount);
        } else {
            returnLpAmount = MixedDecimal.fromDecimal(_quoteAssetAmount).mulD(totalLpTokenAmount).divD(
                poolInfo.totalLiquidity.addD(lpUnrealizedPNL)
            );
        }

        if (poolInfo.fund[sender].toUint() == 0) {
            poolInfo.nextWithdrawTime[sender] = block.timestamp.add(lpLockTime);
        }

        poolInfo.totalLiquidity = poolInfo.totalLiquidity.addD(_quoteAssetAmount);
        poolInfo.totalFund = poolInfo.totalFund.addD(_quoteAssetAmount);
        poolInfo.fund[sender] = poolInfo.fund[sender].addD(_quoteAssetAmount);

        _exchange.quoteAsset().safeTransferFrom(sender, address(this), _quoteAssetAmount.toUint());
        _exchange.mint(_risk, sender, returnLpAmount.toUint());

        emit LiquidityAdd(
            address(_exchange),
            sender,
            uint256(_risk),
            _quoteAssetAmount.toUint(),
            returnLpAmount.toUint()
        );
    }

    /**
     * @notice remove Liquidity from Exchange
     * @param _exchange IExchange address
     * @param _risk pool type
     * @param _lpTokenAmount lp token asset amount in 18 digits. Can Not be 0
     */
    function removeLiquidity(
        IExchange _exchange,
        Risk _risk,
        Decimal.decimal memory _lpTokenAmount
    ) external {
        PoolInfo storage poolInfo = exchangeInfo[address(_exchange)].poolInfo[uint256(_risk)];

        address sender = _msgSender();
        require(block.timestamp >= poolInfo.nextWithdrawTime[sender], "liquidity locked");
        requireExchange(_exchange, true);
        requireNonZeroInput(_lpTokenAmount);
        _requireMMNotBankrupt(address(_exchange), _risk);

        MMLPToken lpToken = IExchangeState(_exchange.getExchangeState()).getLPToken(_risk);
        SignedDecimal.signedDecimal memory lpUnrealizedPNL = getLpUnrealizedPNL(address(_exchange), _risk);
        Decimal.decimal memory totalLpTokenAmount = Decimal.decimal(lpToken.totalSupply());
        Decimal.decimal memory traderLpTokenAmount = Decimal.decimal(lpToken.balanceOf(sender));
        Decimal.decimal memory removeFund = poolInfo.fund[sender].mulD(_lpTokenAmount).divD(traderLpTokenAmount);
        SignedDecimal.signedDecimal memory returnAmount =
            poolInfo.totalLiquidity.addD(lpUnrealizedPNL).mulD(_lpTokenAmount).divD(totalLpTokenAmount).mulD(
                Decimal.one().subD(systemSettings.lpWithdrawFeeRatio())
            );

        poolInfo.totalLiquidity = poolInfo.totalLiquidity.subD(returnAmount);
        poolInfo.totalFund = poolInfo.totalFund.subD(removeFund);
        poolInfo.fund[sender] = poolInfo.fund[sender].subD(removeFund);

        poolInfo.nextWithdrawTime[sender] = block.timestamp.add(lpLockTime);
        _withdraw(_exchange, sender, returnAmount.abs());
        _exchange.burn(_risk, sender, _lpTokenAmount.toUint());

        emit LiquidityRemove(
            address(_exchange),
            sender,
            uint256(_risk),
            returnAmount.toUint(),
            _lpTokenAmount.toUint()
        );
    }

    /**
     * @notice remove Liquidity from Exchange when shutdown
     * @param _exchange IExchange address
     * @param _risk pool type
     */
    function removeLiquidityWhenShutdown(IExchange _exchange, Risk _risk) external {
        address sender = _msgSender();
        requireExchange(_exchange, false);

        PoolInfo storage poolInfo = exchangeInfo[address(_exchange)].poolInfo[uint256(_risk)];
        SignedDecimal.signedDecimal memory lpUnrealizedPNL = getLpUnrealizedPNL(address(_exchange), _risk);
        SignedDecimal.signedDecimal memory remainAmount = poolInfo.totalLiquidity.addD(lpUnrealizedPNL);
        if (remainAmount.toInt() > 0) {
            MMLPToken lpToken = IExchangeState(_exchange.getExchangeState()).getLPToken(_risk);
            Decimal.decimal memory _lpTokenAmount = Decimal.decimal(lpToken.balanceOf(sender));
            Decimal.decimal memory totalLpTokenAmount = Decimal.decimal(lpToken.totalSupply());
            Decimal.decimal memory removeFund = poolInfo.fund[sender];
            SignedDecimal.signedDecimal memory returnAmount =
                remainAmount.mulD(_lpTokenAmount).divD(totalLpTokenAmount);

            poolInfo.totalLiquidity = poolInfo.totalLiquidity.subD(returnAmount);
            poolInfo.totalFund = poolInfo.totalFund.subD(removeFund);
            poolInfo.fund[sender] = Decimal.zero();

            _exchange.burn(_risk, sender, _lpTokenAmount.toUint());
            _withdraw(_exchange, sender, returnAmount.abs());

            emit LiquidityRemove(
                address(_exchange),
                sender,
                uint256(_risk),
                returnAmount.toUint(),
                _lpTokenAmount.toUint()
            );
        }
    }

    //
    // VIEW FUNCTIONS
    //
    function getTotalLpUnrealizedPNL(IExchange _exchange)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        (Decimal.decimal memory _quoteAssetReserve, Decimal.decimal memory _baseAssetReserve) = _exchange.getReserve();
        return _exchange.getMMUnrealizedPNL(_baseAssetReserve, _quoteAssetReserve);
    }

    function getAllLpUnrealizedPNL(address _exchange)
        public
        view
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory)
    {
        SignedDecimal.signedDecimal memory totalLpUnrealizedPNL = getTotalLpUnrealizedPNL(IExchange(_exchange));
        (Decimal.decimal memory highFactor, Decimal.decimal memory lowFactor) = _getMMFactor(_exchange);
        if (totalLpUnrealizedPNL.toInt() == 0) {
            return (SignedDecimal.zero(), SignedDecimal.zero());
        }

        SignedDecimal.signedDecimal memory highUnrealizedPNL =
            totalLpUnrealizedPNL.mulD(highFactor).divD(highFactor.addD(lowFactor));
        SignedDecimal.signedDecimal memory lowUnrealizedPNL = totalLpUnrealizedPNL.subD(highUnrealizedPNL);

        {
            (SignedDecimal.signedDecimal memory highAvailable, SignedDecimal.signedDecimal memory lowAvailable) =
                getAllMMAvailableLiquidity(_exchange);
            SignedDecimal.signedDecimal memory highTotalLiquidity = highAvailable.addD(highUnrealizedPNL);
            SignedDecimal.signedDecimal memory lowTotalLiquidity = lowAvailable.addD(lowUnrealizedPNL);
            if (highTotalLiquidity.isNegative()) {
                highUnrealizedPNL = highAvailable.mulScalar(-1);
                lowUnrealizedPNL = totalLpUnrealizedPNL.subD(highUnrealizedPNL);
            } else if (lowTotalLiquidity.isNegative()) {
                lowUnrealizedPNL = lowAvailable.mulScalar(-1);
                highUnrealizedPNL = totalLpUnrealizedPNL.subD(lowUnrealizedPNL);
            }
        }

        return (highUnrealizedPNL, lowUnrealizedPNL);
    }

    function getLpUnrealizedPNL(address _exchange, Risk _risk)
        public
        view
        returns (SignedDecimal.signedDecimal memory)
    {
        (SignedDecimal.signedDecimal memory high, SignedDecimal.signedDecimal memory low) =
            getAllLpUnrealizedPNL(_exchange);
        return _risk == Risk.HIGH ? high : low;
    }

    function getLpLiquidityAndUnrealizedPNL(address _exchange, Risk _risk)
        public
        view
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory)
    {
        (SignedDecimal.signedDecimal memory highLiquidity, SignedDecimal.signedDecimal memory lowLiquidity) =
            getAllMMLiquidity(_exchange);
        (SignedDecimal.signedDecimal memory highUnrealizedPNL, SignedDecimal.signedDecimal memory lowUnrealizedPNL) =
            getAllLpUnrealizedPNL(_exchange);

        if (Risk.HIGH == _risk) {
            return (highLiquidity, highUnrealizedPNL);
        } else {
            return (lowLiquidity, lowUnrealizedPNL);
        }
    }

    function getLpTokenPrice(IExchange _exchange, Risk _risk)
        public
        view
        returns (int256 tokenPrice, int256 tokenPriceWithFee)
    {
        (SignedDecimal.signedDecimal memory lpLiquidity, SignedDecimal.signedDecimal memory lpUnrealizedPNL) =
            getLpLiquidityAndUnrealizedPNL(address(_exchange), _risk);

        Decimal.decimal memory totalLpTokenAmount =
            Decimal.decimal(IExchangeState(_exchange.getExchangeState()).getLPToken(_risk).totalSupply());
        if (totalLpTokenAmount.toUint() == 0) {
            tokenPriceWithFee = int256(Decimal.one().toUint());
            tokenPrice = int256(Decimal.one().toUint());
        } else {
            SignedDecimal.signedDecimal memory lpLiquidityWithFee =
                lpLiquidity.addD(getMMCachedLiquidity(address(_exchange), _risk));
            tokenPriceWithFee = lpUnrealizedPNL.addD(lpLiquidityWithFee).divD(totalLpTokenAmount).toInt();
            tokenPrice = lpUnrealizedPNL.addD(lpLiquidity).divD(totalLpTokenAmount).toInt();
        }
    }

    function getMMLiquidity(address _exchange, Risk _risk)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        return exchangeInfo[_exchange].poolInfo[uint256(_risk)].totalLiquidity;
    }

    function getAllMMLiquidity(address _exchange)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory)
    {
        PoolInfo memory highPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)];
        PoolInfo memory lowPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)];
        return (highPool.totalLiquidity, lowPool.totalLiquidity);
    }

    function getAllMMAvailableLiquidity(address _exchange)
        public
        view
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory)
    {
        PoolInfo memory highPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)];
        PoolInfo memory lowPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)];
        Decimal.decimal memory highLockedLiquidity =
            highPool.totalFund.mulScalar(UINT100 - highPool.maxLoss).divScalar(UINT100);
        Decimal.decimal memory lowLockedLiquidity =
            lowPool.totalFund.mulScalar(UINT100 - lowPool.maxLoss).divScalar(UINT100);
        SignedDecimal.signedDecimal memory highAvailable = highPool.totalLiquidity.subD(highLockedLiquidity);
        SignedDecimal.signedDecimal memory lowAvailable = lowPool.totalLiquidity.subD(lowLockedLiquidity);
        return (highAvailable, lowAvailable);
    }

    function getAllMMAvailableLiquidityWithPNL(address _exchange)
        public
        view
        returns (SignedDecimal.signedDecimal memory, SignedDecimal.signedDecimal memory)
    {
        (SignedDecimal.signedDecimal memory highAvailable, SignedDecimal.signedDecimal memory lowAvailable) =
            getAllMMAvailableLiquidity(_exchange);
        (SignedDecimal.signedDecimal memory highUnrealizedPNL, SignedDecimal.signedDecimal memory lowUnrealizedPNL) =
            getAllLpUnrealizedPNL(_exchange);
        return (highAvailable.addD(highUnrealizedPNL), lowAvailable.addD(lowUnrealizedPNL));
    }

    function getTotalMMLiquidity(address _exchange) public view override returns (SignedDecimal.signedDecimal memory) {
        PoolInfo memory highPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)];
        PoolInfo memory lowPool = exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)];
        return highPool.totalLiquidity.addD(lowPool.totalLiquidity);
    }

    function getTotalMMAvailableLiquidity(address _exchange)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        (SignedDecimal.signedDecimal memory high, SignedDecimal.signedDecimal memory low) =
            getAllMMAvailableLiquidity(_exchange);
        return high.addD(low);
    }

    function getMMCachedLiquidity(address _exchange, Risk _risk) public view override returns (Decimal.decimal memory) {
        Decimal.decimal memory cachedLiquidity = exchangeInfo[_exchange].cachedLiquidity;
        (Decimal.decimal memory highFactor, Decimal.decimal memory lowFactor) = _getMMFactor(_exchange);
        Decimal.decimal memory cachedForHigh = cachedLiquidity.mulD(highFactor).divD(highFactor.addD(lowFactor));
        Decimal.decimal memory cachedForLow = cachedLiquidity.subD(cachedForHigh);
        return Risk.HIGH == _risk ? cachedForHigh : cachedForLow;
    }

    function getTotalMMCachedLiquidity(address _exchange) public view override returns (Decimal.decimal memory) {
        return exchangeInfo[_exchange].cachedLiquidity;
    }

    function _getMMFactor(address _exchange) internal view returns (Decimal.decimal memory, Decimal.decimal memory) {
        ExchangeInfo memory _exchangeInfo = exchangeInfo[_exchange];
        return (
            Decimal.decimal(_exchangeInfo.highRiskLiquidityWeight),
            Decimal.decimal(_exchangeInfo.lowRiskLiquidityWeight)
        );
    }

    function getMaxLoss(address _exchange) public view returns (uint256, uint256) {
        return (
            exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)].maxLoss,
            exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)].maxLoss
        );
    }

    function getPoolWeight(address _exchange) public view returns (uint256, uint256) {
        return (exchangeInfo[_exchange].highRiskLiquidityWeight, exchangeInfo[_exchange].highRiskLiquidityWeight);
    }

    function getLockedLiquidity(
        address _exchange,
        Risk _risk,
        address _mm
    ) public view returns (Decimal.decimal memory) {
        PoolInfo storage poolInfo = exchangeInfo[_exchange].poolInfo[uint256(_risk)];
        return poolInfo.fund[_mm].mulScalar(UINT100 - poolInfo.maxLoss).divScalar(UINT100);
    }

    function getTotalFund(address _exchange, Risk _risk) public view returns (Decimal.decimal memory) {
        return exchangeInfo[_exchange].poolInfo[uint256(_risk)].totalFund;
    }

    function getFund(
        address _exchange,
        Risk _risk,
        address _mm
    ) public view returns (Decimal.decimal memory) {
        return exchangeInfo[_exchange].poolInfo[uint256(_risk)].fund[_mm];
    }

    function getNextWidhdrawTime(
        address _exchange,
        Risk _risk,
        address _mm
    ) public view returns (uint256) {
        return exchangeInfo[_exchange].poolInfo[uint256(_risk)].nextWithdrawTime[_mm];
    }

    //
    // REQUIRE FUNCTIONS
    //
    function requireMMNotBankrupt(address _exchange) public override {
        SignedDecimal.signedDecimal memory totalLpUnrealizedPNL = getTotalLpUnrealizedPNL(IExchange(_exchange));
        (SignedDecimal.signedDecimal memory highLiquidity, SignedDecimal.signedDecimal memory lowLiquidity) =
            getAllMMLiquidity(_exchange);
        require(totalLpUnrealizedPNL.addD(highLiquidity).addD(lowLiquidity).toInt() > 0, "MM Bankrupt");
    }

    function _requireMMNotBankrupt(address _exchange, Risk _risk) internal view {
        (SignedDecimal.signedDecimal memory lpLiquidity, SignedDecimal.signedDecimal memory lpUnrealizedPNL) =
            getLpLiquidityAndUnrealizedPNL(_exchange, _risk);
        require(lpUnrealizedPNL.addD(lpLiquidity).toInt() >= 0, "MM Bankrupt");
    }

    function requireNonZeroInput(Decimal.decimal memory _decimal) private pure {
        require(_decimal.toUint() != 0, "input is 0");
    }

    function requireExchange(IExchange _exchange, bool _open) private view {
        require(systemSettings.isExistedExchange(_exchange), "exchange not found");
        require(_open == _exchange.open(), _open ? "exchange was closed" : "exchange is open");
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"badDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"insuranceFundResolveBadDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mmHighResolveBadDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mmLowResolveBadDebt","type":"uint256"}],"name":"BadDebtResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"risk","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpfund","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenamount","type":"uint256"}],"name":"LiquidityAdd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"lpfundHigh","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpfundLow","type":"uint256"}],"name":"LiquidityModify","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"risk","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpfund","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenamount","type":"uint256"}],"name":"LiquidityRemove","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":[{"internalType":"address","name":"_exchange","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_DeltaLpLiquidity","type":"tuple"}],"name":"addCachedLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"exchangeInfo","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"cachedLiquidity","type":"tuple"},{"internalType":"uint256","name":"highRiskLiquidityWeight","type":"uint256"},{"internalType":"uint256","name":"lowRiskLiquidityWeight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getAllLpUnrealizedPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getAllMMAvailableLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getAllMMAvailableLiquidityWithPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getAllMMLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"address","name":"_mm","type":"address"}],"name":"getFund","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":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"address","name":"_mm","type":"address"}],"name":"getLockedLiquidity","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":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getLpLiquidityAndUnrealizedPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getLpTokenPrice","outputs":[{"internalType":"int256","name":"tokenPrice","type":"int256"},{"internalType":"int256","name":"tokenPriceWithFee","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getLpUnrealizedPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getMMCachedLiquidity","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":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getMMLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getMaxLoss","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"address","name":"_mm","type":"address"}],"name":"getNextWidhdrawTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getPoolWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"getTotalFund","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"getTotalLpUnrealizedPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getTotalMMAvailableLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getTotalMMCachedLiquidity","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"}],"name":"getTotalMMLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sakePerp","type":"address"},{"internalType":"address","name":"_systemSettings","type":"address"},{"internalType":"uint256","name":"_lockTime","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpLockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"modifyLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_badDebt","type":"tuple"}],"name":"realizeBadDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_lpTokenAmount","type":"tuple"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"}],"name":"removeLiquidityWhenShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"requireMMNotBankrupt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sakePerp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockTime","type":"uint256"}],"name":"setLpLockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"enum ISakePerpVaultTypes.Risk","name":"_risk","type":"uint8"},{"internalType":"uint256","name":"_max","type":"uint256"}],"name":"setMaxLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"uint256","name":"_highWeight","type":"uint256"},{"internalType":"uint256","name":"_lowWeight","type":"uint256"}],"name":"setRiskLiquidityWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sakePerp","type":"address"}],"name":"setSakePerp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_systemSettings","type":"address"}],"name":"setSystemSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"systemSettings","outputs":[{"internalType":"contract ISystemSettings","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_amount","type":"tuple"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506149cf806100206000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c80638df3fab31161013b578063c7c332d3116100b8578063eb8460d21161007c578063eb8460d214610501578063ebb5b42c14610514578063eec6298f14610527578063f2a5dca31461053a578063f2fde38b1461054d57610248565b8063c7c332d3146104a2578063d9f9ac64146104b5578063e16448b8146104c8578063e4d8074e146104db578063e885c04d146104ee57610248565b8063b411db68116100ff578063b411db6814610443578063bd27ca3c14610456578063bebb00a314610469578063c53ab8a21461047c578063c5e2a11a1461048f57610248565b80638df3fab3146104055780638e4833281461040d578063a79dca5614610415578063a7b1284614610428578063ae9a04341461043057610248565b8063559b37d2116101c9578063633ceadb1161018d578063633ceadb146103bc57806370c53938146103cf578063715018a6146103e257806386be9e8b146103ea5780638da5cb5b146103fd57610248565b8063559b37d21461034c5780635757ed5b1461035f5780635dbbfc47146103725780635f06cd2c1461038557806360b42f12146103a757610248565b806338ef35701161021057806338ef3570146102e05780633dd97387146102f35780634d068a43146103065780634fa4e5361461031957806350b7c6581461033957610248565b8063033e97f41461024d578063140eb8e7146102775780631794bb3c1461028c578063180c91f11461029f5780633400d7c9146102bf575b600080fd5b61026061025b36600461406e565b610560565b60405161026e92919061433f565b60405180910390f35b61028a6102853660046141f1565b61077b565b005b61028a61029a36600461402e565b610c3b565b6102b26102ad366004613ff6565b610d07565b60405161026e9190614889565b6102d26102cd366004613ff6565b610d41565b60405161026e929190614893565b61028a6102ee3660046141aa565b610dae565b61028a610301366004613ff6565b610df8565b6102b261031436600461406e565b610e75565b61032c6103273660046140a3565b610ec1565b60405161026e91906148ba565b61028a61034736600461412a565b610f25565b61028a61035a366004614156565b6112f6565b61026061036d366004613ff6565b6113a8565b610260610380366004613ff6565b6113c8565b610398610393366004613ff6565b611401565b60405161026e939291906148a3565b6103af611433565b60405161026e91906142b1565b6102b26103ca366004613ff6565b611442565b6102b26103dd3660046140a3565b611479565b61028a611507565b61028a6103f83660046140ec565b611586565b6103af6116e3565b61028a6116f2565b6103af6118e0565b6102b261042336600461406e565b6118ef565b61032c611941565b6102d261043e366004613ff6565b611947565b6102d261045136600461406e565b611a92565b6102b261046436600461406e565b611b0f565b6102b2610477366004613ff6565b611bc3565b6102b261048a3660046140a3565b611cce565b6102d261049d366004613ff6565b611d38565b61028a6104b03660046141f1565b611ea4565b6102b26104c336600461406e565b612413565b6102b26104d6366004613ff6565b612468565b61028a6104e9366004613ff6565b612541565b61028a6104fc36600461406e565b6125be565b61028a61050f366004614265565b6129d7565b61028a61052236600461412a565b612a11565b6102d2610535366004613ff6565b612a8b565b61028a610548366004613ff6565b612b6c565b61028a61055b366004613ff6565b612bcd565b60008061056b613f36565b610573613f36565b61057d8686611a92565b91509150610589613f36565b6040518060200160405280886001600160a01b03166360d982016040518163ffffffff1660e01b815260040160206040518083038186803b1580156105cd57600080fd5b505afa1580156105e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106059190614012565b6001600160a01b03166351f59d0c896040518263ffffffff1660e01b81526004016106309190614302565b60206040518083038186803b15801561064857600080fd5b505afa15801561065c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106809190614012565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106b857600080fd5b505afa1580156106cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f0919061427d565b905290506106fd81612c84565b6107255761071161070c612c88565b612c84565b935061071e61070c612c88565b9450610771565b61072d613f36565b61074161073a8989611b0f565b8590612cac565b905061075a61070c836107548685612d1b565b90612d41565b945061076d61070c836107548688612d1b565b9550505b5050509250929050565b610786836001612dac565b61078f81612f3d565b6000610799612f65565b6001600160a01b038516600090815260686020526040812091925090818560018111156107c257fe5b815260200190815260200160002090506107da613f36565b6107e48686610e75565b90506107ee613f36565b6040518060200160405280886001600160a01b03166360d982016040518163ffffffff1660e01b815260040160206040518083038186803b15801561083257600080fd5b505afa158015610846573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086a9190614012565b6001600160a01b03166351f59d0c896040518263ffffffff1660e01b81526004016108959190614302565b60206040518083038186803b1580156108ad57600080fd5b505afa1580156108c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e59190614012565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561091d57600080fd5b505afa158015610931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610955919061427d565b90529050600061096482612c84565b1115610974576109748787612f69565b61097c613f36565b610984612fb5565b905061098f82612c84565b6109a35761099c86612fd0565b90506109dc565b6040805160208101909152845481526109d9906109c09085612d1b565b6109d3846109cd8a612fd0565b90613034565b9061309f565b90505b6001600160a01b0385166000908152600285016020908152604091829020825191820190925290548152610a0f90612c84565b610a3d57606754610a219042906130bc565b6001600160a01b03861660009081526003860160205260409020555b604080516020810190915284548152610a569087612cac565b518455604080516020810190915260018501548152610a7590876130e1565b5160018501556001600160a01b0385166000908152600285016020908152604091829020825191820190925290548152610aaf90876130e1565b6001600160a01b0386166000908152600286016020526040902090519055610b5d8530610adb89612c84565b8b6001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1457600080fd5b505afa158015610b28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4c9190614012565b6001600160a01b03169291906130fe565b876001600160a01b031663eebab8ef8887610b7785613156565b6040518463ffffffff1660e01b8152600401610b9593929190614315565b600060405180830381600087803b158015610baf57600080fd5b505af1158015610bc3573d6000803e3d6000fd5b50505050846001600160a01b0316886001600160a01b03167fe67d500110d375cdd8e134bf404908658cd4c8c7813d9822169f5d2a9a3c5077896001811115610c0857fe5b610c118a612c84565b610c1a86613156565b604051610c29939291906148c3565b60405180910390a35050505050505050565b600054610100900460ff1680610c545750610c54613168565b80610c62575060005460ff16155b610c875760405162461bcd60e51b8152600401610c7e9061454d565b60405180910390fd5b600054610100900460ff16158015610cb2576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b038087166001600160a01b03199283161790925560658054928616929091169190911790556067829055610cef61316e565b8015610d01576000805461ff00191690555b50505050565b610d0f613f36565b610d17613f36565b610d1f613f36565b610d2884611d38565b9092509050610d378282612d1b565b925050505b919050565b610d49613f36565b610d51613f36565b610d59613f36565b610d61613f36565b610d6a85611d38565b91509150610d76613f36565b610d7e613f36565b610d8787611947565b9092509050610d968483612d1b565b610da08483612d1b565b95509550505050505b915091565b6066546001600160a01b0316610dc2612f65565b6001600160a01b031614610de85760405162461bcd60e51b8152600401610c7e90614776565b610df3838383613200565b505050565b610e00612f65565b6033546001600160a01b03908116911614610e2d5760405162461bcd60e51b8152600401610c7e90614641565b6001600160a01b038116610e535760405162461bcd60e51b8152600401610c7e906144bb565b606680546001600160a01b0319166001600160a01b0392909216919091179055565b610e7d613f36565b610e85613f36565b610e8d613f36565b610e9685611947565b90925090506000846001811115610ea957fe5b14610eb45780610eb6565b815b925050505b92915050565b6001600160a01b038316600090815260686020526040812081846001811115610ee657fe5b81526020019081526020016000206003016000836001600160a01b03166001600160a01b031681526020019081526020016000205490505b9392505050565b6066546001600160a01b0316610f39612f65565b6001600160a01b031614610f5f5760405162461bcd60e51b8152600401610c7e90614776565b606554604051633f694ac560e11b81526000916001600160a01b031690637ed2958a90610f909086906004016142b1565b60206040518083038186803b158015610fa857600080fd5b505afa158015610fbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe09190614012565b9050610fea613f36565b6040518060200160405280856001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561102e57600080fd5b505afa158015611042573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110669190614012565b6001600160a01b03166370a08231856040518263ffffffff1660e01b815260040161109191906142b1565b60206040518083038186803b1580156110a957600080fd5b505afa1580156110bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e1919061427d565b905290506110ed613f36565b6110f5612fb5565b90506110ff613f36565b611107612fb5565b9050611111613f36565b611119612fb5565b9050611123613f36565b61112b612fb5565b905061113687612c84565b61113f86612c84565b106111d557604051631f73d2e760e11b81526001600160a01b03871690633ee7a5ce90611170908a90600401614889565b602060405180830381600087803b15801561118a57600080fd5b505af115801561119e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c2919061421f565b508692506111ce612fb5565b9350611264565b604051631f73d2e760e11b81526001600160a01b03871690633ee7a5ce90611201908890600401614889565b602060405180830381600087803b15801561121b57600080fd5b505af115801561122f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611253919061421f565b50849250611261878461351f565b93505b600061126f85612c84565b11156112855761127f888561353c565b90925090505b876001600160a01b03167f61ccdbfcc4d71fe0e0db8f266c52487a8203332dc6fde7623f262f5a052b7ccd6112b989612c84565b6112c286612c84565b6112cb86612c84565b6112d486612c84565b6040516112e494939291906148d9565b60405180910390a25050505050505050565b6112fe6116e3565b6001600160a01b031661130f612f65565b6001600160a01b0316148061133c5750826001600160a01b0316611331612f65565b6001600160a01b0316145b6113585760405162461bcd60e51b8152600401610c7e906143f2565b600061136483836130bc565b116113815760405162461bcd60e51b8152600401610c7e906146e7565b6001600160a01b039092166000908152606860205260409020600281019190915560030155565b6001600160a01b0316600090815260686020526040902060020154908190565b6001600160a01b031660009081526068602090815260408083208380528083528184206004908101546001865291909352922001549091565b606860209081526000918252604091829020825191820190925260018201548152600282015460039092015490919083565b6065546001600160a01b031681565b61144a613f36565b506001600160a01b03166000908152606860209081526040918290208251918201909252600190910154815290565b611481613f36565b6001600160a01b0384166000908152606860205260408120818560018111156114a657fe5b81526020808201929092526040908101600090812060048101546001600160a01b0388168352600282018552918390208351948501909352915483529092506114fe916064916114f8919083036136f4565b90613710565b95945050505050565b61150f612f65565b6033546001600160a01b0390811691161461153c5760405162461bcd60e51b8152600401610c7e90614641565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b61158e6116e3565b6001600160a01b031661159f612f65565b6001600160a01b031614806115cc5750826001600160a01b03166115c1612f65565b6001600160a01b0316145b6115e85760405162461bcd60e51b8152600401610c7e906143f2565b6000811180156115f9575060648111155b6116155760405162461bcd60e51b8152600401610c7e9061470f565b6001600160a01b03831660009081526068602052604081208184600181111561163a57fe5b81526020019081526020016000209050611652613f36565b61165c8585610e75565b9050611666613f36565b60408051602081019091526001840154815261168b906064906114f8908783036136f4565b6040805160208101909152845481529091506116bc906116b79084906116b1908561372c565b90612d1b565b613791565b156116d95760405162461bcd60e51b8152600401610c7e90614451565b5050600401555050565b6033546001600160a01b031690565b60006116fc612f65565b6065546040516357de0c5b60e01b81529192506001600160a01b0316906357de0c5b9061172d9084906004016142b1565b60206040518083038186803b15801561174557600080fd5b505afa158015611759573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177d919061418a565b6117995760405162461bcd60e51b8152600401610c7e90614380565b6117a1613f36565b6117a9613f36565b6117b2836137af565b6001600160a01b03851660009081526068602090815260408083208380529182905280832060018452922093955091935090916117ed613f36565b50604080516020810190915260018401548152611808613f36565b61182561181588886130e1565b61181f848a61382d565b9061384a565b905061182f613f36565b611839838361351f565b6040805160208101909152865481529091506118559083612cac565b5185556040805160208101909152845481526118719082612cac565b51845561187c612fb5565b5160018701556001600160a01b0389167f53b51cf5a1ebe438d76007c88a77b178f23d7ac34918998a2140fac3e15ca5b46118b684612c84565b6118bf84612c84565b6040516118cd92919061433f565b60405180910390a2505050505050505050565b6066546001600160a01b031681565b6118f7613f36565b6001600160a01b03831660009081526068602052604081209083600181111561191c57fe5b8152602080820192909252604090810160002081519283019091525481529392505050565b60675481565b61194f613f36565b611957613f36565b61195f613f36565b61196884611bc3565b9050611972613f36565b61197a613f36565b611983866137af565b9150915061199083612c84565b6119b05761199c612fb5565b6119a4612fb5565b94509450505050610da9565b6119b8613f36565b6119cf6119c584846130e1565b6107548686613034565b90506119d9613f36565b6119e38583613867565b90506119ed613f36565b6119f5613f36565b6119fe8a611d38565b91509150611a0a613f36565b611a148386612d1b565b9050611a1e613f36565b611a288386612d1b565b9050611a3382613791565b15611a5757611a4484600019613884565b9550611a508987613867565b9450611a80565b611a6081613791565b15611a8057611a7183600019613884565b9450611a7d8986613867565b95505b50939850919650505050505050915091565b611a9a613f36565b611aa2613f36565b611aaa613f36565b611ab2613f36565b611abb86612a8b565b91509150611ac7613f36565b611acf613f36565b611ad888611947565b91509150866001811115611ae857fe5b611afa5750919350909150611b089050565b919450909250611b08915050565b9250929050565b611b17613f36565b611b1f613f36565b506001600160a01b03831660009081526068602090815260409182902082519182019092526001909101548152611b54613f36565b611b5c613f36565b611b65866137af565b91509150611b71613f36565b611b88611b7e84846130e1565b61181f868661382d565b9050611b92613f36565b611b9c858361351f565b9050866001811115611baa57fe5b15611bb55780611bb7565b815b98975050505050505050565b611bcb613f36565b611bd3613f36565b611bdb613f36565b836001600160a01b03166359bf5d396040518163ffffffff1660e01b8152600401604080518083038186803b158015611c1357600080fd5b505afa158015611c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4b919061423a565b6040516320855f0560e01b815291935091506001600160a01b038516906320855f0590611c7e9084908690600401614893565b60206040518083038186803b158015611c9657600080fd5b505afa158015611caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d379190613fd1565b611cd6613f36565b6001600160a01b038416600090815260686020526040812090846001811115611cfb57fe5b8152602080820192909252604090810160009081206001600160a01b03861682526002018352819020815192830190915254815290509392505050565b611d40613f36565b611d48613f36565b611d50613f49565b506001600160a01b0383166000908152606860209081526040808320838052825291829020825160808101845281546060820190815281528351808401855260018301548152928101929092526004015491810191909152611db0613f49565b6001600160a01b0385166000908152606860205260408120906001815260208082019290925260409081016000208151608081018352815460608201908152815282518085018452600183015481529381019390935260040154908201529050611e18613f36565b611e3b60646114f8856040015160640386602001516136f490919063ffffffff16565b9050611e45613f36565b611e6860646114f8856040015160640386602001516136f490919063ffffffff16565b9050611e72613f36565b8451611e7e908461372c565b9050611e88613f36565b8451611e94908461372c565b9197509095505050505050915091565b6001600160a01b038316600090815260686020526040812081846001811115611ec957fe5b815260200190815260200160002090506000611ee3612f65565b6001600160a01b0381166000908152600384016020526040902054909150421015611f205760405162461bcd60e51b8152600401610c7e90614676565b611f2b856001612dac565b611f3483612f3d565b611f3e8585612f69565b6000856001600160a01b03166360d982016040518163ffffffff1660e01b815260040160206040518083038186803b158015611f7957600080fd5b505afa158015611f8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb19190614012565b6001600160a01b03166351f59d0c866040518263ffffffff1660e01b8152600401611fdc9190614302565b60206040518083038186803b158015611ff457600080fd5b505afa158015612008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202c9190614012565b9050612036613f36565b6120408787610e75565b905061204a613f36565b6040518060200160405280846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561208e57600080fd5b505afa1580156120a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c6919061427d565b905290506120d2613f36565b6040805160208101918290526370a0823160e01b909152806001600160a01b0386166370a0823161210689602485016142b1565b60206040518083038186803b15801561211e57600080fd5b505afa158015612132573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612156919061427d565b90529050612162613f36565b6001600160a01b038616600090815260028801602090815260409182902082519182019092529054815261219c90839061181f908b61382d565b90506121a6613f36565b612263612240606560009054906101000a90046001600160a01b03166001600160a01b031663294585296040518163ffffffff1660e01b815260040160206040518083038186803b1580156121fa57600080fd5b505afa15801561220e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612232919061421f565b61223a612c88565b9061351f565b60408051602081019091528a5481526109cd908790610754908e9084908c612d1b565b60408051602081019091528954815290915061227f9082613867565b51885560408051602081019091526001890154815261229e908361351f565b5160018901556001600160a01b03871660009081526002890160209081526040918290208251918201909252905481526122d8908361351f565b6001600160a01b038816600090815260028a0160205260409020905190556067546123049042906130bc565b6001600160a01b038816600090815260038a0160205260409020556123328b8861232d846138a0565b613200565b8a6001600160a01b0316638eb86e8b8b8961234c8d612c84565b6040518463ffffffff1660e01b815260040161236a93929190614315565b600060405180830381600087803b15801561238457600080fd5b505af1158015612398573d6000803e3d6000fd5b50505050866001600160a01b03168b6001600160a01b03167f0a1c25ae924704549adf45406b392212e731505f6eb60f707265434cbc5f22658c60018111156123dd57fe5b6123e685613156565b6123ef8e612c84565b6040516123fe939291906148c3565b60405180910390a35050505050505050505050565b61241b613f36565b6001600160a01b03831660009081526068602052604081209083600181111561244057fe5b8152602080820192909252604090810160002081519283019091526001015481529392505050565b612470613f36565b612478613f49565b506001600160a01b03821660009081526068602090815260408083208380528252918290208251608081018452815460608201908152815283518084018552600183015481529281019290925260040154918101919091526124d8613f49565b506001600160a01b03831660009081526068602090815260408083206001808552908352928190208151608081018352815460608201908152815282518085018452948201548552928301939093526004909201549181019190915280518251610d3791612d1b565b612549612f65565b6033546001600160a01b039081169116146125765760405162461bcd60e51b8152600401610c7e90614641565b6001600160a01b03811661259c5760405162461bcd60e51b8152600401610c7e906144bb565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b60006125c8612f65565b90506125d5836000612dac565b6001600160a01b0383166000908152606860205260408120818460018111156125fa57fe5b81526020019081526020016000209050612612613f36565b61261c8585610e75565b9050612626613f36565b60408051602081019091528354815261263f9083612d1b565b9050600061264c82612c84565b13156129cf576000866001600160a01b03166360d982016040518163ffffffff1660e01b815260040160206040518083038186803b15801561268d57600080fd5b505afa1580156126a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c59190614012565b6001600160a01b03166351f59d0c876040518263ffffffff1660e01b81526004016126f09190614302565b60206040518083038186803b15801561270857600080fd5b505afa15801561271c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127409190614012565b905061274a613f36565b6040805160208101918290526370a0823160e01b909152806001600160a01b0384166370a0823161277e8a602485016142b1565b60206040518083038186803b15801561279657600080fd5b505afa1580156127aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ce919061427d565b905290506127da613f36565b6040518060200160405280846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561281e57600080fd5b505afa158015612832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612856919061427d565b90529050612862613f36565b506001600160a01b0387166000908152600287016020908152604091829020825191820190925290548152612895613f36565b6128a3836107548887613034565b6040805160208101909152895481529091506128bf9082613867565b5188556040805160208101909152600189015481526128de908361351f565b5160018901556128ec612fb5565b6001600160a01b03808b16600090815260028b016020526040902091519091558b16638eb86e8b8b8b61291e88612c84565b6040518463ffffffff1660e01b815260040161293c93929190614315565b600060405180830381600087803b15801561295657600080fd5b505af115801561296a573d6000803e3d6000fd5b5050505061297c8b8a61232d846138a0565b886001600160a01b03168b6001600160a01b03167f0a1c25ae924704549adf45406b392212e731505f6eb60f707265434cbc5f22658c60018111156129bd57fe5b6129c685613156565b6123ef89612c84565b505050505050565b6129df612f65565b6033546001600160a01b03908116911614612a0c5760405162461bcd60e51b8152600401610c7e90614641565b606755565b6066546001600160a01b0316612a25612f65565b6001600160a01b031614612a4b5760405162461bcd60e51b8152600401610c7e90614776565b6001600160a01b038216600090815260686020908152604091829020825191820190925260018201548152612a8090836130e1565b516001909101555050565b612a93613f36565b612a9b613f36565b612aa3613f49565b506001600160a01b0383166000908152606860209081526040808320838052825291829020825160808101845281546060820190815281528351808401855260018301548152928101929092526004015491810191909152612b03613f49565b506001600160a01b0393909316600090815260686020908152604080832060018085529083529281902081516080810183528154606082019081528152825180850184529482015485529283019390935260049092015491810191909152925192519293915050565b612b74613f36565b612b7d82611bc3565b9050612b87613f36565b612b8f613f36565b612b9884612a8b565b90925090506000612bb061070c836116b18787612d1b565b13610d015760405162461bcd60e51b8152600401610c7e90614528565b612bd5612f65565b6033546001600160a01b03908116911614612c025760405162461bcd60e51b8152600401610c7e90614641565b6001600160a01b038116612c285760405162461bcd60e51b8152600401610c7e906143ac565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5190565b612c90613f36565b6040518060200160405280612ca560126138ce565b9052905090565b612cb4613f36565b8180600001516001600160ff1b0310156040518060600160405280603381526020016149676033913990612cfb5760405162461bcd60e51b8152600401610c7e919061434d565b50612d04613f36565b83518551612d11916138d7565b8152949350505050565b612d23613f36565b612d2b613f36565b82518451612d38916138d7565b81529392505050565b612d49613f36565b8180600001516001600160ff1b0310156040518060600160405280603381526020016149676033913990612d905760405162461bcd60e51b8152600401610c7e919061434d565b50612d99613f36565b610eb6612da585612fd0565b869061309f565b6065546040516357de0c5b60e01b81526001600160a01b03909116906357de0c5b90612ddc9085906004016142b1565b60206040518083038186803b158015612df457600080fd5b505afa158015612e08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2c919061418a565b612e485760405162461bcd60e51b8152600401610c7e90614380565b816001600160a01b031663fcfff16f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612e8157600080fd5b505afa158015612e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb9919061418a565b15158115151481612ef2576040518060400160405280601081526020016f32bc31b430b733b29034b99037b832b760811b815250612f1f565b60405180604001604052806013815260200172195e18da185b99d9481dd85cc818db1bdcd959606a1b8152505b90610df35760405162461bcd60e51b8152600401610c7e919061434d565b612f4681612c84565b612f625760405162461bcd60e51b8152600401610c7e9061461d565b50565b3390565b612f71613f36565b612f79613f36565b612f838484611a92565b90925090506000612f9761070c8385612d1b565b1215610d015760405162461bcd60e51b8152600401610c7e90614528565b612fbd613f36565b5060408051602081019091526000815290565b612fd8613f36565b8180600001516001600160ff1b031015604051806060016040528060338152602001614967603391399061301f5760405162461bcd60e51b8152600401610c7e919061434d565b50506040805160208101909152915182525090565b61303c613f36565b8180600001516001600160ff1b03101560405180606001604052806033815260200161496760339139906130835760405162461bcd60e51b8152600401610c7e919061434d565b5061308c613f36565b610eb661309885612fd0565b869061391d565b6130a7613f36565b6130af613f36565b82518451612d389161393a565b600082820183811015610f1e5760405162461bcd60e51b8152600401610c7e9061441a565b6130e9613f36565b6130f1613f36565b82518451612d38916130bc565b610d01846323b872dd60e01b85858560405160240161311f939291906142c5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613948565b6000613161826138a0565b5192915050565b303b1590565b600054610100900460ff16806131875750613187613168565b80613195575060005460ff16155b6131b15760405162461bcd60e51b8152600401610c7e9061454d565b600054610100900460ff161580156131dc576000805460ff1961ff0019909116610100171660011790555b6131e46139d7565b6131ec613a58565b8015612f62576000805461ff001916905550565b6000836001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561323b57600080fd5b505afa15801561324f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132739190614012565b905061327d613f36565b6040805160208101918290526370a0823160e01b909152806001600160a01b0384166370a082316132b130602485016142b1565b60206040518083038186803b1580156132c957600080fd5b505afa1580156132dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613301919061427d565b9052905061330e83612c84565b61331782612c84565b10156134fa57613325613f36565b61332f848361351f565b606554604051633f694ac560e11b81529192506000916001600160a01b0390911690637ed2958a90613365908a906004016142b1565b60206040518083038186803b15801561337d57600080fd5b505afa158015613391573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b59190614012565b90506133bf613f36565b6040805160208101918290526370a0823160e01b909152806001600160a01b0387166370a082316133f386602485016142b1565b60206040518083038186803b15801561340b57600080fd5b505afa15801561341f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613443919061427d565b9052905061345083612c84565b61345982612c84565b10156134775760405162461bcd60e51b8152600401610c7e9061482b565b604051631f73d2e760e11b81526001600160a01b03831690633ee7a5ce906134a3908690600401614889565b602060405180830381600087803b1580156134bd57600080fd5b505af11580156134d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f5919061421f565b505050505b6135188461350785612c84565b6001600160a01b0385169190613b32565b5050505050565b613527613f36565b61352f613f36565b82518451612d3891613b51565b613544613f36565b61354c613f36565b613554613f36565b61355c612fb5565b9050613566613f36565b61356e612fb5565b9050613578613f36565b613580613f36565b61358988610d41565b909250905060006135a761070c896135a18686612d1b565b9061372c565b12156135c55760405162461bcd60e51b8152600401610c7e90614528565b6135cd613f36565b6135d5613f36565b6135de8a6137af565b90925090506135fa6135f083836130e1565b61181f8b8561382d565b9550613606898761351f565b9450613610613f36565b61361a858861372c565b9050613624613f36565b61362e858861372c565b905061363982613791565b1561365a57613647866138a0565b97506136538b8961351f565b9650613680565b61366381613791565b1561368057613671856138a0565b965061367d8b8861351f565b97505b6001600160a01b038c16600090815260686020908152604080832083805282528083206001845292819020815192830190915282548252906136c2908b61372c565b5182556040805160208101909152815481526136de908a61372c565b51905550969b959a509498505050505050505050565b6136fc613f36565b613704613f36565b8351612d389084613b93565b613718613f36565b613720613f36565b8351612d389084613bcd565b613734613f36565b8180600001516001600160ff1b031015604051806060016040528060338152602001614967603391399061377b5760405162461bcd60e51b8152600401610c7e919061434d565b50613784613f36565b83518551612d1191613c0f565b600080826000015112156137a757506001610d3c565b506000919050565b6137b7613f36565b6137bf613f36565b6137c7613f76565b5050506001600160a01b031660009081526068602090815260409182902082516080810184526001820154606082019081528152600282015481840190815260039092015490840190815283518084018552915182528351928301909352915181529091565b613835613f36565b61383d613f36565b82518451612d3891613c55565b613852613f36565b61385a613f36565b82518451612d3891613c63565b61386f613f36565b613877613f36565b82518451612d3891613c0f565b61388c613f36565b613894613f36565b8351612d389084613c71565b6138a8613f36565b6138b0613f36565b8251600013156138c65782516000038152610ebb565b915182525090565b60ff16600a0a90565b60008282018183128015906138ec5750838112155b80613901575060008312801561390157508381125b610f1e5760405162461bcd60e51b8152600401610c7e9061447a565b613925613f36565b61392d613f36565b82518451612d3891613cdc565b6000610f1e83836012613cea565b606061399d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d119092919063ffffffff16565b805190915015610df357808060200190518101906139bb919061418a565b610df35760405162461bcd60e51b8152600401610c7e906147e1565b600054610100900460ff16806139f057506139f0613168565b806139fe575060005460ff16155b613a1a5760405162461bcd60e51b8152600401610c7e9061454d565b600054610100900460ff161580156131ec576000805460ff1961ff0019909116610100171660011790558015612f62576000805461ff001916905550565b600054610100900460ff1680613a715750613a71613168565b80613a7f575060005460ff16155b613a9b5760405162461bcd60e51b8152600401610c7e9061454d565b600054610100900460ff16158015613ac6576000805460ff1961ff0019909116610100171660011790555b6000613ad0612f65565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015612f62576000805461ff001916905550565b610df38363a9059cbb60e01b848460405160240161311f9291906142e9565b6000610f1e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613d20565b600082613ba257506000610ebb565b82820282848281613baf57fe5b0414610f1e5760405162461bcd60e51b8152600401610c7e906145dc565b6000610f1e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613d4c565b6000818303818312801590613c245750838113155b80613c395750600083128015613c3957508381135b610f1e5760405162461bcd60e51b8152600401610c7e9061479d565b6000610f1e83836012613d83565b6000610f1e83836012613da1565b600082613c8057506000610ebb565b82600019148015613c945750600160ff1b82145b15613cb15760405162461bcd60e51b8152600401610c7e906146a0565b82820282848281613cbe57fe5b0514610f1e5760405162461bcd60e51b8152600401610c7e906146a0565b6000610f1e83836012613dba565b6000613d0983613d03613cfc856138ce565b8790613c71565b90613dd2565b949350505050565b6060613d098484600085613e36565b60008184841115613d445760405162461bcd60e51b8152600401610c7e919061434d565b505050900390565b60008183613d6d5760405162461bcd60e51b8152600401610c7e919061434d565b506000838581613d7957fe5b0495945050505050565b6000613d09613d91836138ce565b613d9b8686613b93565b90613bcd565b6000613d0983613d9b613db3856138ce565b8790613b93565b6000613d09613dc8836138ce565b613d038686613c71565b600081613df15760405162461bcd60e51b8152600401610c7e90614854565b81600019148015613e055750600160ff1b83145b15613e225760405162461bcd60e51b8152600401610c7e9061459b565b6000828481613e2d57fe5b05949350505050565b606082471015613e585760405162461bcd60e51b8152600401610c7e906144e2565b613e6185613ef7565b613e7d5760405162461bcd60e51b8152600401610c7e9061473f565b60006060866001600160a01b03168587604051613e9a9190614295565b60006040518083038185875af1925050503d8060008114613ed7576040519150601f19603f3d011682016040523d82523d6000602084013e613edc565b606091505b5091509150613eec828286613efd565b979650505050505050565b3b151590565b60608315613f0c575081610f1e565b825115613f1c5782518084602001fd5b8160405162461bcd60e51b8152600401610c7e919061434d565b6040518060200160405280600081525090565b6040518060600160405280613f5c613f36565b8152602001613f69613f36565b8152602001600081525090565b6040518060600160405280613f89613f36565b815260200160008152602001600081525090565b803560028110610ebb57600080fd5b600060208284031215613fbd578081fd5b613fc760206148f4565b9135825250919050565b600060208284031215613fe2578081fd5b613fec60206148f4565b9151825250919050565b600060208284031215614007578081fd5b8135610f1e81614951565b600060208284031215614023578081fd5b8151610f1e81614951565b600080600060608486031215614042578182fd5b833561404d81614951565b9250602084013561405d81614951565b929592945050506040919091013590565b60008060408385031215614080578182fd5b823561408b81614951565b915061409a8460208501613f9d565b90509250929050565b6000806000606084860312156140b7578283fd5b83356140c281614951565b92506140d18560208601613f9d565b915060408401356140e181614951565b809150509250925092565b600080600060608486031215614100578283fd5b833561410b81614951565b925061411a8560208601613f9d565b9150604084013590509250925092565b6000806040838503121561413c578182fd5b823561414781614951565b915061409a8460208501613fac565b60008060006060848603121561416a578283fd5b833561417581614951565b95602085013595506040909401359392505050565b60006020828403121561419b578081fd5b81518015158114610f1e578182fd5b6000806000606084860312156141be578081fd5b83356141c981614951565b925060208401356141d981614951565b91506141e88560408601613fac565b90509250925092565b600080600060608486031215614205578081fd5b833561421081614951565b92506141d98560208601613f9d565b600060208284031215614230578081fd5b610f1e8383613fd1565b6000806040838503121561424c578182fd5b6142568484613fd1565b915061409a8460208501613fd1565b600060208284031215614276578081fd5b5035919050565b60006020828403121561428e578081fd5b5051919050565b600082516142a781846020870161491b565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6020810161430f83614947565b91905290565b6060810161432285614947565b9381526001600160a01b0392909216602083015260409091015290565b918252602082015260400190565b600060208252825180602084015261436c81604085016020870161491b565b601f01601f19169190910160400192915050565b602080825260129082015271195e18da185b99d9481b9bdd08199bdd5b9960721b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252600e908201526d34b73b30b634b21031b0b63632b960911b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600f908201526e0cceadcc840dcdee840cadcdeeaced608b1b604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600d908201526c656d707479206164647265737360981b604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600b908201526a13534810985b9adc9d5c1d60aa1b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600a90820152690696e70757420697320360b41b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526010908201526f1b1a5c5d5a591a5d1e481b1bd8dad95960821b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252600e908201526d1a5b9d985b1a59081dd95a59da1d60921b604082015260600190565b602080825260169082015275696e76616c6964206d6178206c6f73732076616c756560501b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600d908201526c06f6e6c792073616b655065727609c1b604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600f908201526e08ceadcc840dcdee840cadcdeeaced608b1b604082015260600190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b9051815260200190565b9151825251602082015260400190565b925183526020830191909152604082015260600190565b90815260200190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60405181810167ffffffffffffffff8111828210171561491357600080fd5b604052919050565b60005b8381101561493657818101518382015260200161491e565b83811115610d015750506000910152565b60028110612f6257fe5b6001600160a01b0381168114612f6257600080fdfe4d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a2646970667358221220d3898b02a2646e8dd0f3368b28679817a441d5017cf1b284079b1be09139240964736f6c634300060c0033

Deployed ByteCode Sourcemap

66175:29409:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87624:1067;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;78580:1952;;;;;;:::i;:::-;;:::i;:::-;;68762:295;;;;;;:::i;:::-;;:::i;91337:349::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;90333:618::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;71852:212::-;;;;;;:::i;:::-;;:::i;69189:158::-;;;;;;:::i;:::-;;:::i;86563:345::-;;;;;;:::i;:::-;;:::i;94087:233::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;75054:1573::-;;;;;;:::i;:::-;;:::i;69964:451::-;;;;;;:::i;:::-;;:::i;93105:205::-;;;;;;:::i;:::-;;:::i;92833:264::-;;;;;;:::i;:::-;;:::i;68015:52::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;67885:37::-;;;:::i;:::-;;;;;;;:::i;92288:173::-;;;;;;:::i;:::-;;:::i;93318:339::-;;;;;;:::i;:::-;;:::i;24859:148::-;;;:::i;70610:742::-;;;;;;:::i;:::-;;:::i;24217:79::-;;;:::i;76714:1112::-;;;:::i;67929:23::-;;;:::i;88699:251::-;;;;;;:::i;:::-;;:::i;67959:25::-;;;:::i;84881:1674::-;;;;;;:::i;:::-;;:::i;86916:700::-;;;;;;:::i;:::-;;:::i;91694:586::-;;;;;;:::i;:::-;;:::i;84498:375::-;;;;;;:::i;:::-;;:::i;93855:224::-;;;;;;:::i;:::-;;:::i;89408:917::-;;;;;;:::i;:::-;;:::i;80758:1921::-;;;;;;:::i;:::-;;:::i;93665:182::-;;;;;;:::i;:::-;;:::i;90959:370::-;;;;;;:::i;:::-;;:::i;69491:205::-;;;;;;:::i;:::-;;:::i;82840:1611::-;;;;;;:::i;:::-;;:::i;71493:102::-;;;;;;:::i;:::-;;:::i;78035:325::-;;;;;;:::i;:::-;;:::i;88958:442::-;;;;;;:::i;:::-;;:::i;94370:447::-;;;;;;:::i;:::-;;:::i;25162:244::-;;;;;;:::i;:::-;;:::i;87624:1067::-;87730:17;87749:24;87792:46;;:::i;:::-;87840:50;;:::i;:::-;87907:57;87946:9;87958:5;87907:30;:57::i;:::-;87791:173;;;;87977:41;;:::i;:::-;88034:93;;;;;;;;88065:9;-1:-1:-1;;;;;88065:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;88050:55:0;;88106:5;88050:62;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;88050:74:0;;:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88034:93;;87977:150;-1:-1:-1;88142:27:0;87977:150;88142:25;:27::i;:::-;88138:546;;88218:22;:13;:11;:13::i;:::-;:20;:22::i;:::-;88191:50;;88276:22;:13;:11;:13::i;:22::-;88256:43;;88138:546;;;88332:53;;:::i;:::-;88405:65;88422:47;88451:9;88463:5;88422:20;:47::i;:::-;88405:11;;:16;:65::i;:::-;88332:138;-1:-1:-1;88505:73:0;:65;88551:18;88505:40;:15;88332:138;88505:20;:40::i;:::-;:45;;:65::i;:73::-;88485:93;-1:-1:-1;88606:66:0;:58;88645:18;88606:33;:15;88627:11;88606:20;:33::i;:66::-;88593:79;;88138:546;;87624:1067;;;;;;;;:::o;78580:1952::-;78731:32;78747:9;78758:4;78731:15;:32::i;:::-;78774:38;78794:17;78774:19;:38::i;:::-;78825:14;78842:12;:10;:12::i;:::-;-1:-1:-1;;;;;78893:32:0;;78865:25;78893:32;;;:12;:32;;;;;78825:29;;-1:-1:-1;78865:25:0;;78943:5;78935:14;;;;;;;;78893:57;;;;;;;;;;;78865:85;;78961:50;;:::i;:::-;79014:45;79041:9;79053:5;79014:18;:45::i;:::-;78961:98;;79072:41;;:::i;:::-;79129:93;;;;;;;;79160:9;-1:-1:-1;;;;;79160:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79145:55:0;;79201:5;79145:62;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79145:74:0;;:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79129:93;;79072:150;-1:-1:-1;79267:1:0;79237:27;79072:150;79237:25;:27::i;:::-;:31;79233:112;;;79285:48;79315:9;79327:5;79285:21;:48::i;:::-;79357:49;;:::i;:::-;79409:20;:18;:20::i;:::-;79357:72;;79444:27;:18;:25;:27::i;:::-;79440:327;;79510:43;79535:17;79510:24;:43::i;:::-;79493:60;;79440:327;;;79695:28;;;;;;;;;;;;;79603:152;;79695:45;;79724:15;79695:28;:45::i;:::-;79603:68;79652:18;79603:43;79628:17;79603:24;:43::i;:::-;:48;;:68::i;:::-;:73;;:152::i;:::-;79586:169;;79440:327;-1:-1:-1;;;;;79783:21:0;;;;;;:13;;;:21;;;;;;;;;:28;;;;;;;;;;;;:30;;:28;:30::i;:::-;79779:135;;79891:10;;79871:31;;:15;;:19;:31::i;:::-;-1:-1:-1;;;;;79835:33:0;;;;;;:25;;;:33;;;;;:67;79779:135;79952:28;;;;;;;;;;;;;:47;;79981:17;79952:28;:47::i;:::-;79926:73;;;80031:23;;;;;;;;;:18;;;:23;;;:42;;80055:17;80031:23;:42::i;:::-;80010:63;:18;;;:63;-1:-1:-1;;;;;80108:21:0;;80010:63;80108:21;;;:13;;;:21;;;;;;;;;:26;;;;;;;;;;;;:45;;80135:17;80108:26;:45::i;:::-;-1:-1:-1;;;;;80084:21:0;;;;;;:13;;;:21;;;;;:69;;;;80166:90;80098:6;80222:4;80229:26;:17;:24;:26::i;:::-;80166:9;-1:-1:-1;;;;;80166:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;80166:39:0;;:90;;:39;:90::i;:::-;80267:9;-1:-1:-1;;;;;80267:14:0;;80282:5;80289:6;80297:23;:14;:21;:23::i;:::-;80267:54;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80399:6;-1:-1:-1;;;;;80339:185:0;80374:9;-1:-1:-1;;;;;80339:185:0;;80428:5;80420:14;;;;;;;;80449:26;:17;:24;:26::i;:::-;80490:23;:14;:21;:23::i;:::-;80339:185;;;;;;;;:::i;:::-;;;;;;;;78580:1952;;;;;;;;:::o;68762:295::-;20633:13;;;;;;;;:33;;;20650:16;:14;:16::i;:::-;20633:50;;;-1:-1:-1;20671:12:0;;;;20670:13;20633:50;20625:109;;;;-1:-1:-1;;;20625:109:0;;;;;;;:::i;:::-;;;;;;;;;20747:19;20770:13;;;;;;20769:14;20794:101;;;;20829:13;:20;;-1:-1:-1;;;;20829:20:0;;;;;20864:19;20845:4;20864:19;;;20794:101;68909:8:::1;:20:::0;;-1:-1:-1;;;;;68909:20:0;;::::1;-1:-1:-1::0;;;;;;68909:20:0;;::::1;;::::0;;;68940:14:::1;:49:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;69000:10:::1;:22:::0;;;69033:16:::1;:14;:16::i;:::-;20925:14:::0;20921:68;;;20972:5;20956:21;;-1:-1:-1;;20956:21:0;;;20921:68;68762:295;;;;:::o;91337:349::-;91460:34;;:::i;:::-;91513:39;;:::i;:::-;91554:38;;:::i;:::-;91609:37;91636:9;91609:26;:37::i;:::-;91512:134;;-1:-1:-1;91512:134:0;-1:-1:-1;91664:14:0;91512:134;;91664:9;:14::i;:::-;91657:21;;;;91337:349;;;;:::o;90333:618::-;90443:34;;:::i;:::-;90479;;:::i;:::-;90532:48;;:::i;:::-;90582:47;;:::i;:::-;90646:37;90673:9;90646:26;:37::i;:::-;90531:152;;;;90695:52;;:::i;:::-;90749:51;;:::i;:::-;90817:32;90839:9;90817:21;:32::i;:::-;90694:155;;-1:-1:-1;90694:155:0;-1:-1:-1;90868:37:0;:13;90694:155;90868:18;:37::i;:::-;90907:35;:12;90925:16;90907:17;:35::i;:::-;90860:83;;;;;;;;90333:618;;;;:::o;71852:212::-;68677:8;;-1:-1:-1;;;;;68677:8:0;68661:12;:10;:12::i;:::-;-1:-1:-1;;;;;68661:24:0;;68653:50;;;;-1:-1:-1;;;68653:50:0;;;;;;;:::i;:::-;72016:40:::1;72026:9;72037;72048:7;72016:9;:40::i;:::-;71852:212:::0;;;:::o;69189:158::-;24439:12;:10;:12::i;:::-;24429:6;;-1:-1:-1;;;;;24429:6:0;;;:22;;;24421:67;;;;-1:-1:-1;;;24421:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;69267:23:0;::::1;69259:49;;;;-1:-1:-1::0;;;69259:49:0::1;;;;;;;:::i;:::-;69319:8;:20:::0;;-1:-1:-1;;;;;;69319:20:0::1;-1:-1:-1::0;;;;;69319:20:0;;;::::1;::::0;;;::::1;::::0;;69189:158::o;86563:345::-;86670:34;;:::i;:::-;86723:39;;:::i;:::-;86764:38;;:::i;:::-;86819:32;86841:9;86819:21;:32::i;:::-;86722:129;;-1:-1:-1;86722:129:0;-1:-1:-1;86878:9:0;86869:5;:18;;;;;;;;;:31;;86897:3;86869:31;;;86890:4;86869:31;86862:38;;;;86563:345;;;;;:::o;94087:233::-;-1:-1:-1;;;;;94242:23:0;;94215:7;94242:23;;;:12;:23;;;;;94215:7;94283:5;94275:14;;;;;;;;94242:48;;;;;;;;;;;:65;;:70;94308:3;-1:-1:-1;;;;;94242:70:0;-1:-1:-1;;;;;94242:70:0;;;;;;;;;;;;;94235:77;;94087:233;;;;;;:::o;75054:1573::-;68677:8;;-1:-1:-1;;;;;68677:8:0;68661:12;:10;:12::i;:::-;-1:-1:-1;;;;;68661:24:0;;68653:50;;;;-1:-1:-1;;;68653:50:0;;;;;;;:::i;:::-;75297:14:::1;::::0;:42:::1;::::0;-1:-1:-1;;;75297:42:0;;75266:28:::1;::::0;-1:-1:-1;;;;;75297:14:0::1;::::0;:31:::1;::::0;:42:::1;::::0;75329:9;;75297:42:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75266:73;;75350:41;;:::i;:::-;75407:73;;;;;;;;75423:9;-1:-1:-1::0;;;;;75423:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;75423:32:0::1;;75464:13;75423:56;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75407:73:::0;;75350:130;-1:-1:-1;75491:39:0::1;;:::i;:::-;75533:14;:12;:14::i;:::-;75491:56;;75558:50;;:::i;:::-;75611:14;:12;:14::i;:::-;75558:67;;75636:43;;:::i;:::-;75682:14;:12;:14::i;:::-;75636:60;;75707:42;;:::i;:::-;75752:14;:12;:14::i;:::-;75707:59;;75814:17;:8;:15;:17::i;:::-;75783:27;:18;:25;:27::i;:::-;:48;75779:419;;75848:32;::::0;-1:-1:-1;;;75848:32:0;;-1:-1:-1;;;;;75848:22:0;::::1;::::0;::::1;::::0;:32:::1;::::0;75871:8;;75848:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;75925:8;75895:38;;75967:14;:12;:14::i;:::-;75948:33;;75779:419;;;76014:42;::::0;-1:-1:-1;;;76014:42:0;;-1:-1:-1;;;;;76014:22:0;::::1;::::0;::::1;::::0;:42:::1;::::0;76037:18;;76014:42:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;76101:18:0;;-1:-1:-1;76153:33:0::1;:8:::0;76101:18;76153:13:::1;:33::i;:::-;76134:52;;75779:419;76242:1;76214:25;:16;:23;:25::i;:::-;:29;76210:163;;;76306:55;76332:9;76344:16;76306:17;:55::i;:::-;76260:101:::0;;-1:-1:-1;76260:101:0;-1:-1:-1;76210:163:0::1;76428:9;-1:-1:-1::0;;;;;76390:229:0::1;;76453:17;:8;:15;:17::i;:::-;76485:36;:27;:34;:36::i;:::-;76536:29;:20;:27;:29::i;:::-;76580:28;:19;:26;:28::i;:::-;76390:229;;;;;;;;;:::i;:::-;;;;;;;;68714:1;;;;;;75054:1573:::0;;:::o;69964:451::-;70141:7;:5;:7::i;:::-;-1:-1:-1;;;;;70125:23:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;70125:23:0;;:52;;;;70168:9;-1:-1:-1;;;;;70152:25:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;70152:25:0;;70125:52;70117:79;;;;-1:-1:-1;;;70117:79:0;;;;;;;:::i;:::-;70245:1;70215:27;:11;70231:10;70215:15;:27::i;:::-;:31;70207:58;;;;-1:-1:-1;;;70207:58:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;70276:23:0;;;;;;;:12;:23;;;;;:47;;;:61;;;;70348:46;;:59;69964:451::o;93105:205::-;-1:-1:-1;;;;;93205:23:0;93168:7;93205:23;;;:12;:23;;;;;:47;;;;;;93105:205::o;92833:264::-;-1:-1:-1;;;;;92944:23:0;92893:7;92944:23;;;:12;:23;;;;;;;;:52;;;;;;;;;:60;;;;;93060:8;93019:51;;;;;;;;:59;;92944:60;;92833:264::o;68015:52::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;67885:37::-;;;-1:-1:-1;;;;;67885:37:0;;:::o;92288:173::-;92372:22;;:::i;:::-;-1:-1:-1;;;;;;92414:23:0;;;;;:12;:23;;;;;;;;;92407:46;;;;;;;;92414:39;;;;92407:46;;;;92288:173::o;93318:339::-;93445:22;;:::i;:::-;-1:-1:-1;;;;;93508:23:0;;93480:25;93508:23;;;:12;:23;;;;;93480:25;93549:5;93541:14;;;;;;;;93508:48;;;;;;;;;;;;;;-1:-1:-1;93508:48:0;;;93613:16;;;;-1:-1:-1;;;;;93574:18:0;;;;:13;;;:18;;;;;;:28;;;;;;;;;;;;93508:48;;-1:-1:-1;93574:75:0;;67875:3;;93574:56;;:28;93603:26;;93574:28;:56::i;:::-;:66;;:75::i;:::-;93567:82;93318:339;-1:-1:-1;;;;;93318:339:0:o;24859:148::-;24439:12;:10;:12::i;:::-;24429:6;;-1:-1:-1;;;;;24429:6:0;;;:22;;;24421:67;;;;-1:-1:-1;;;24421:67:0;;;;;;;:::i;:::-;24950:6:::1;::::0;24929:40:::1;::::0;24966:1:::1;::::0;-1:-1:-1;;;;;24950:6:0::1;::::0;24929:40:::1;::::0;24966:1;;24929:40:::1;24980:6;:19:::0;;-1:-1:-1;;;;;;24980:19:0::1;::::0;;24859:148::o;70610:742::-;70760:7;:5;:7::i;:::-;-1:-1:-1;;;;;70744:23:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;70744:23:0;;:52;;;;70787:9;-1:-1:-1;;;;;70771:25:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;70771:25:0;;70744:52;70736:79;;;;-1:-1:-1;;;70736:79:0;;;;;;;:::i;:::-;70841:1;70834:4;:8;:27;;;;;67875:3;70846:4;:15;;70834:27;70826:62;;;;-1:-1:-1;;;70826:62:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;70927:23:0;;70899:25;70927:23;;;:12;:23;;;;;70899:25;70968:5;70960:14;;;;;;;;70927:48;;;;;;;;;;;70899:76;;70986:50;;:::i;:::-;71039:36;71058:9;71069:5;71039:18;:36::i;:::-;70986:89;;71086:38;;:::i;:::-;71127:28;;;;;;;;;:18;;;:28;;;:63;;67875:3;;71127:44;;71156:14;;;71127:28;:44::i;:63::-;71210:28;;;;;;;;;;;;;71086:104;;-1:-1:-1;71210:80:0;;:67;;71261:15;;71210:45;;71086:104;71210:28;:45::i;:::-;:50;;:67::i;:::-;:78;:80::i;:::-;71209:81;71201:109;;;;-1:-1:-1;;;71201:109:0;;;;;;;:::i;:::-;-1:-1:-1;;71321:16:0;;:23;-1:-1:-1;;70610:742:0:o;24217:79::-;24282:6;;-1:-1:-1;;;;;24282:6:0;24217:79;:::o;76714:1112::-;76770:17;76790:12;:10;:12::i;:::-;76821:14;;:54;;-1:-1:-1;;;76821:54:0;;76770:32;;-1:-1:-1;;;;;;76821:14:0;;:32;;:54;;76770:32;;76821:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76813:85;;;;-1:-1:-1;;;76813:85:0;;;;;;;:::i;:::-;76910:33;;:::i;:::-;76945:32;;:::i;:::-;76981:23;76994:9;76981:12;:23::i;:::-;-1:-1:-1;;;;;77052:23:0;;77015:34;77052:23;;;:12;:23;;;;;;;;77114:42;;;;;;;;;;77225:8;77194:41;;;;76909:95;;-1:-1:-1;76909:95:0;;-1:-1:-1;77052:23:0;;77246:38;;:::i;:::-;-1:-1:-1;77246:70:0;;;;;;;;;77287:29;;;77246:70;;;77327:36;;:::i;:::-;77366:65;77404:26;:10;77420:9;77404:15;:26::i;:::-;77366:32;:15;77387:10;77366:20;:32::i;:::-;:37;;:65::i;:::-;77327:104;;77442:35;;:::i;:::-;77480;:15;77501:13;77480:20;:35::i;:::-;77552:28;;;;;;;;;;;;;77442:73;;-1:-1:-1;77552:43:0;;77581:13;77552:28;:43::i;:::-;77526:69;;;77631:27;;;;;;;;;;;;;:41;;77659:12;77631:27;:41::i;:::-;77606:66;;;77715:14;:12;:14::i;:::-;77683:46;:29;;;:46;-1:-1:-1;;;;;77745:73:0;;;77772:22;:13;:20;:22::i;:::-;77796:21;:12;:19;:21::i;:::-;77745:73;;;;;;;:::i;:::-;;;;;;;;76714:1112;;;;;;;;;:::o;67929:23::-;;;-1:-1:-1;;;;;67929:23:0;;:::o;88699:251::-;88820:34;;:::i;:::-;-1:-1:-1;;;;;88879:23:0;;;;;;:12;:23;;;;;;88920:5;88912:14;;;;;;;;88879:48;;;;;;;;;;;;;;-1:-1:-1;88879:48:0;88872:70;;;;;;;;;;;;88699:251;-1:-1:-1;;;88699:251:0:o;67959:25::-;;;;:::o;84881:1674::-;84979:34;;:::i;:::-;85015;;:::i;:::-;85067:55;;:::i;:::-;85125:45;85159:9;85125:23;:45::i;:::-;85067:103;;85182:33;;:::i;:::-;85217:32;;:::i;:::-;85253:23;85266:9;85253:12;:23::i;:::-;85181:95;;;;85291:28;:20;:26;:28::i;:::-;85287:117;;85349:20;:18;:20::i;:::-;85371;:18;:20::i;:::-;85341:51;;;;;;;;;85287:117;85416:52;;:::i;:::-;85484:70;85527:26;:10;85543:9;85527:15;:26::i;:::-;85484:37;:20;85510:10;85484:25;:37::i;:70::-;85416:138;;85565:51;;:::i;:::-;85619:44;:20;85645:17;85619:25;:44::i;:::-;85565:98;;85692:48;;:::i;:::-;85742:47;;:::i;:::-;85810:37;85837:9;85810:26;:37::i;:::-;85691:156;;;;85862:53;;:::i;:::-;85918:37;:13;85937:17;85918:18;:37::i;:::-;85862:93;;85970:52;;:::i;:::-;86025:35;:12;86043:16;86025:17;:35::i;:::-;85970:90;;86079:31;:18;:29;:31::i;:::-;86075:405;;;86151:27;:13;-1:-1:-1;;86151:23:0;:27::i;:::-;86131:47;-1:-1:-1;86216:44:0;:20;86131:47;86216:25;:44::i;:::-;86197:63;;86075:405;;;86286:30;:17;:28;:30::i;:::-;86282:198;;;86356:26;:12;-1:-1:-1;;86356:22:0;:26::i;:::-;86337:45;-1:-1:-1;86421:43:0;:20;86337:45;86421:25;:43::i;:::-;86401:63;;86282:198;-1:-1:-1;86511:17:0;;-1:-1:-1;86530:16:0;;-1:-1:-1;;;;;;;84881:1674:0;;;:::o;86916:700::-;87035:34;;:::i;:::-;87071;;:::i;:::-;87124:48;;:::i;:::-;87174:47;;:::i;:::-;87238:28;87256:9;87238:17;:28::i;:::-;87123:143;;;;87278:52;;:::i;:::-;87332:51;;:::i;:::-;87400:32;87422:9;87400:21;:32::i;:::-;87277:155;;;;87462:5;87449:18;;;;;;;;87445:164;;-1:-1:-1;87492:13:0;;-1:-1:-1;87507:17:0;;-1:-1:-1;87484:41:0;;-1:-1:-1;87484:41:0;87445:164;87566:12;;-1:-1:-1;87580:16:0;;-1:-1:-1;87558:39:0;;-1:-1:-1;;87558:39:0;86916:700;;;;;;:::o;91694:586::-;91785:22;;:::i;:::-;91820:38;;:::i;:::-;-1:-1:-1;;;;;;91861:23:0;;;;;;:12;:23;;;;;;;;;91820:80;;;;;;;;91861:39;;;;91820:80;;;91912:33;;:::i;:::-;91947:32;;:::i;:::-;91983:23;91996:9;91983:12;:23::i;:::-;91911:95;;;;92017:36;;:::i;:::-;92056:65;92094:26;:10;92110:9;92094:15;:26::i;:::-;92056:32;:15;92077:10;92056:20;:32::i;:65::-;92017:104;;92132:35;;:::i;:::-;92170;:15;92191:13;92170:20;:35::i;:::-;92132:73;;92236:5;92223:18;;;;;;;;;:49;;92260:12;92223:49;;;92244:13;92223:49;92216:56;91694:586;-1:-1:-1;;;;;;;;91694:586:0:o;84498:375::-;84618:34;;:::i;:::-;84671:41;;:::i;:::-;84714:40;;:::i;:::-;84758:9;-1:-1:-1;;;;;84758:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84798:67;;-1:-1:-1;;;84798:67:0;;84670:110;;-1:-1:-1;84670:110:0;-1:-1:-1;;;;;;84798:28:0;;;;;:67;;84670:110;;;;84798:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;93855:224::-;93971:22;;:::i;:::-;-1:-1:-1;;;;;94013:23:0;;;;;;:12;:23;;;;;;94054:5;94046:14;;;;;;;;94013:48;;;;;;;;;;;;;;-1:-1:-1;94013:48:0;;;-1:-1:-1;;;;;94013:58:0;;;;:53;;:58;;;;;94006:65;;;;;;;;;;;;-1:-1:-1;93855:224:0;;;;;:::o;89408:917::-;89511:34;;:::i;:::-;89547;;:::i;:::-;89599:24;;:::i;:::-;-1:-1:-1;;;;;;89626:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;89599:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89599:79:0;;;;;;;;;;;;;;89689:23;;:::i;:::-;-1:-1:-1;;;;;89715:23:0;;;;;;:12;:23;;;;;;89756:8;89715:51;;;;;;;;;;;;;;-1:-1:-1;89715:51:0;89689:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89777:42:0;;:::i;:::-;89835:75;67875:3;89835:56;89874:8;:16;;;67875:3;89864:26;89835:8;:18;;;:28;;:56;;;;:::i;:75::-;89777:133;;89921:41;;:::i;:::-;89978:73;67875:3;89978:54;90016:7;:15;;;67875:3;90006:25;89978:7;:17;;;:27;;:54;;;;:::i;:73::-;89921:130;;90062:48;;:::i;:::-;90113:23;;:49;;90142:19;90113:28;:49::i;:::-;90062:100;;90173:47;;:::i;:::-;90223:22;;:47;;90251:18;90223:27;:47::i;:::-;90289:13;;-1:-1:-1;90173:97:0;;-1:-1:-1;;;;;;89408:917:0;;;:::o;80758:1921::-;-1:-1:-1;;;;;80937:32:0;;80909:25;80937:32;;;:12;:32;;;;;80909:25;80987:5;80979:14;;;;;;;;80937:57;;;;;;;;;;;80909:85;;81007:14;81024:12;:10;:12::i;:::-;-1:-1:-1;;;;;81074:33:0;;;;;;:25;;;:33;;;;;;81007:29;;-1:-1:-1;81055:15:0;:52;;81047:81;;;;-1:-1:-1;;;81047:81:0;;;;;;;:::i;:::-;81139:32;81155:9;81166:4;81139:15;:32::i;:::-;81182:35;81202:14;81182:19;:35::i;:::-;81228:48;81258:9;81270:5;81228:21;:48::i;:::-;81289:17;81324:9;-1:-1:-1;;;;;81324:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81309:55:0;;81365:5;81309:62;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81289:82;;81382:50;;:::i;:::-;81435:45;81462:9;81474:5;81435:18;:45::i;:::-;81382:98;;81491:41;;:::i;:::-;81535:38;;;;;;;;81551:7;-1:-1:-1;;;;;81551:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81535:38;;81491:82;-1:-1:-1;81584:42:0;;:::i;:::-;81629;;;;;;;;;;-1:-1:-1;;;81645:25:0;;;81629:42;-1:-1:-1;;;;;81645:17:0;;;:25;81663:6;81645:25;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81629:42;;81584:87;-1:-1:-1;81682:33:0;;:::i;:::-;-1:-1:-1;;;;;81718:21:0;;;;;;:13;;;:21;;;;;;;;;:26;;;;;;;;;;;;:68;;81766:19;;81718:42;;81745:14;81718:26;:42::i;:68::-;81682:104;;81797:47;;:::i;:::-;81860:185;81975:55;81994:14;;;;;;;;;-1:-1:-1;;;;;81994:14:0;-1:-1:-1;;;;;81994:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81975:13;:11;:13::i;:::-;:18;;:55::i;:::-;81860:28;;;;;;;;;;;;;:91;;81932:18;;81860:66;;81911:14;;81860:91;;81889:15;81860:28;:45::i;:185::-;82084:28;;;;;;;;;;;;;81797:248;;-1:-1:-1;82084:42:0;;81797:248;82084:28;:42::i;:::-;82058:68;;;82158:23;;;;;;;;;:18;;;:23;;;:35;;82182:10;82158:23;:35::i;:::-;82137:56;:18;;;:56;-1:-1:-1;;;;;82228:21:0;;82137:56;82228:21;;;:13;;;:21;;;;;;;;;:26;;;;;;;;;;;;:38;;82255:10;82228:26;:38::i;:::-;-1:-1:-1;;;;;82204:21:0;;;;;;:13;;;:21;;;;;:62;;;;82335:10;;82315:31;;:15;;:19;:31::i;:::-;-1:-1:-1;;;;;82279:33:0;;;;;;:25;;;:33;;;;;:67;82357:48;82367:9;82305:6;82386:18;:12;:16;:18::i;:::-;82357:9;:48::i;:::-;82416:9;-1:-1:-1;;;;;82416:14:0;;82431:5;82438:6;82446:23;:14;:21;:23::i;:::-;82416:54;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82551:6;-1:-1:-1;;;;;82488:183:0;82526:9;-1:-1:-1;;;;;82488:183:0;;82580:5;82572:14;;;;;;;;82601:21;:12;:19;:21::i;:::-;82637:23;:14;:21;:23::i;:::-;82488:183;;;;;;;;:::i;:::-;;;;;;;;80758:1921;;;;;;;;;;;:::o;93665:182::-;93739:22;;:::i;:::-;-1:-1:-1;;;;;93781:23:0;;;;;;:12;:23;;;;;;93822:5;93814:14;;;;;;;;93781:48;;;;;;;;;;;;;;-1:-1:-1;93781:48:0;93774:65;;;;;;;;93781:58;;93774:65;;;;93665:182;-1:-1:-1;;;93665:182:0:o;90959:370::-;91037:34;;:::i;:::-;91084:24;;:::i;:::-;-1:-1:-1;;;;;;91111:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;91084:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91084:79:0;;;;;;;;;;;;;;91174:23;;:::i;:::-;-1:-1:-1;;;;;;91200:23:0;;;;;;:12;:23;;;;;;;;91241:8;91200:51;;;;;;;;;;91174:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91174:77:0;;;;;;;;;;;;;;;;91298:22;;91269:23;;:52;;:28;:52::i;69491:205::-;24439:12;:10;:12::i;:::-;24429:6;;-1:-1:-1;;;;;24429:6:0;;;:22;;;24421:67;;;;-1:-1:-1;;;24421:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;69581:29:0;::::1;69573:55;;;;-1:-1:-1::0;;;69573:55:0::1;;;;;;;:::i;:::-;69639:14;:49:::0;;-1:-1:-1;;;;;;69639:49:0::1;-1:-1:-1::0;;;;;69639:49:0;;;::::1;::::0;;;::::1;::::0;;69491:205::o;82840:1611::-;82930:14;82947:12;:10;:12::i;:::-;82930:29;;82970:33;82986:9;82997:5;82970:15;:33::i;:::-;-1:-1:-1;;;;;83044:32:0;;83016:25;83044:32;;;:12;:32;;;;;83016:25;83094:5;83086:14;;;;;;;;83044:57;;;;;;;;;;;83016:85;;83112:50;;:::i;:::-;83165:45;83192:9;83204:5;83165:18;:45::i;:::-;83112:98;;83221:47;;:::i;:::-;83271:28;;;;;;;;;;;;;:45;;83300:15;83271:28;:45::i;:::-;83221:95;;83354:1;83331:20;:12;:18;:20::i;:::-;:24;83327:1117;;;83372:17;83407:9;-1:-1:-1;;;;;83407:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;83392:55:0;;83448:5;83392:62;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83372:82;;83469:37;;:::i;:::-;83509:42;;;;;;;;;;-1:-1:-1;;;83525:25:0;;;83509:42;-1:-1:-1;;;;;83525:17:0;;;:25;83543:6;83525:25;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83509:42;;83469:82;-1:-1:-1;83566:41:0;;:::i;:::-;83610:38;;;;;;;;83626:7;-1:-1:-1;;;;;83626:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83610:38;;83566:82;-1:-1:-1;83663:33:0;;:::i;:::-;-1:-1:-1;;;;;;83699:21:0;;;;;;:13;;;:21;;;;;;;;;83663:57;;;;;;;;;;;;83735:47;;:::i;:::-;83802:58;83841:18;83802:33;:12;83820:14;83802:17;:33::i;:58::-;83903:28;;;;;;;;;;;;;83735:125;;-1:-1:-1;83903:42:0;;83735:125;83903:28;:42::i;:::-;83877:68;;;83981:23;;;;;;;;;:18;;;:23;;;:35;;84005:10;83981:23;:35::i;:::-;83960:56;:18;;;:56;84055:14;:12;:14::i;:::-;-1:-1:-1;;;;;84031:21:0;;;;;;;:13;;;:21;;;;;:38;;;;;84086:14;;;84101:5;84045:6;84116:23;:14;:21;:23::i;:::-;84086:54;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84155:48;84165:9;84176:6;84184:18;:12;:16;:18::i;84155:48::-;84296:6;-1:-1:-1;;;;;84225:207:0;84267:9;-1:-1:-1;;;;;84225:207:0;;84329:5;84321:14;;;;;;;;84354:21;:12;:19;:21::i;:::-;84394:23;:14;:21;:23::i;83327:1117::-;82840:1611;;;;;;:::o;71493:102::-;24439:12;:10;:12::i;:::-;24429:6;;-1:-1:-1;;;;;24429:6:0;;;:22;;;24421:67;;;;-1:-1:-1;;;24421:67:0;;;;;;;:::i;:::-;71565:10:::1;:22:::0;71493:102::o;78035:325::-;68677:8;;-1:-1:-1;;;;;68677:8:0;68661:12;:10;:12::i;:::-;-1:-1:-1;;;;;68661:24:0;;68653:50;;;;-1:-1:-1;;;68653:50:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;78233:23:0;::::1;78196:34;78233:23:::0;;;:12:::1;:23;::::0;;;;;;;;78299:34;;;;::::1;::::0;;;:29:::1;::::0;::::1;:34:::0;;;:53:::1;::::0;78334:17;78299:34:::1;:53::i;:::-;78267:85:::0;:29:::1;::::0;;::::1;:85:::0;-1:-1:-1;;78035:325:0:o;88958:442::-;89070:34;;:::i;:::-;89106;;:::i;:::-;89158:24;;:::i;:::-;-1:-1:-1;;;;;;89185:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;89158:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89158:79:0;;;;;;;;;;;;;;89248:23;;:::i;:::-;-1:-1:-1;;;;;;89274:23:0;;;;;;;;:12;:23;;;;;;;;89315:8;89274:51;;;;;;;;;;89248:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89248:77:0;;;;;;;;;;;;;;;;89344:23;;89369:22;;89344:23;;88958:442;-1:-1:-1;;88958:442:0:o;94370:447::-;94446:55;;:::i;:::-;94504:45;94538:9;94504:23;:45::i;:::-;94446:103;;94561:48;;:::i;:::-;94611:47;;:::i;:::-;94675:28;94693:9;94675:17;:28::i;:::-;94560:143;;-1:-1:-1;94560:143:0;-1:-1:-1;94792:1:0;94722:67;:59;94560:143;94722:40;:20;94560:143;94722:25;:40::i;:67::-;:71;94714:95;;;;-1:-1:-1;;;94714:95:0;;;;;;;:::i;25162:244::-;24439:12;:10;:12::i;:::-;24429:6;;-1:-1:-1;;;;;24429:6:0;;;:22;;;24421:67;;;;-1:-1:-1;;;24421:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;25251:22:0;::::1;25243:73;;;;-1:-1:-1::0;;;25243:73:0::1;;;;;;;:::i;:::-;25353:6;::::0;25332:38:::1;::::0;-1:-1:-1;;;;;25332:38:0;;::::1;::::0;25353:6:::1;::::0;25332:38:::1;::::0;25353:6:::1;::::0;25332:38:::1;25381:6;:17:::0;;-1:-1:-1;;;;;;25381:17:0::1;-1:-1:-1::0;;;;;25381:17:0;;;::::1;::::0;;;::::1;::::0;;25162:244::o;30552:95::-;30636:3;;30552:95::o;30435:109::-;30473:14;;:::i;:::-;30507:29;;;;;;;;30515:20;30532:2;30515:16;:20::i;:::-;30507:29;;30500:36;-1:-1:-1;30435:109:0;:::o;63809:304::-;63961:34;;:::i;:::-;63940:1;63292;:3;;;-1:-1:-1;;;;;63277:18:0;;63297:21;;;;;;;;;;;;;;;;;63269:50;;;;;-1:-1:-1;;;63269:50:0;;;;;;;;:::i;:::-;;64013:36:::1;;:::i;:::-;64081:3:::0;;64066;;:20:::1;::::0;:7:::1;:20::i;:::-;64060:26:::0;;;63809:304;-1:-1:-1;;;;63809:304:0:o;37823:196::-;37908:20;;:::i;:::-;37941:22;;:::i;:::-;37988:3;;37980;;:12;;:7;:12::i;:::-;37974:18;;;37823:196;-1:-1:-1;;;37823:196:0:o;65393:304::-;65545:34;;:::i;:::-;65524:1;63292;:3;;;-1:-1:-1;;;;;63277:18:0;;63297:21;;;;;;;;;;;;;;;;;63269:50;;;;;-1:-1:-1;;;63269:50:0;;;;;;;;:::i;:::-;;65597:36:::1;;:::i;:::-;65648:22;65655:14;65667:1;65655:11;:14::i;:::-;65648:1:::0;;:6:::1;:22::i;95320:261::-:0;95410:14;;:43;;-1:-1:-1;;;95410:43:0;;-1:-1:-1;;;;;95410:14:0;;;;:32;;:43;;95443:9;;95410:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95402:74;;;;-1:-1:-1;;;95402:74:0;;;;;;;:::i;:::-;95504:9;-1:-1:-1;;;;;95504:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95495:25;;:5;:25;;;95522:5;:50;;;;;;;;;;;;;;;-1:-1:-1;;;95522:50:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;95522:50:0;;;;95487:86;;;;;-1:-1:-1;;;95487:86:0;;;;;;;;:::i;95173:139::-;95267:17;:8;:15;:17::i;:::-;95259:45;;;;-1:-1:-1;;;95259:45:0;;;;;;;:::i;:::-;95173:139;:::o;22523:106::-;22611:10;22523:106;:::o;94825:340::-;94913:46;;:::i;:::-;94961:50;;:::i;:::-;95028:48;95059:9;95070:5;95028:30;:48::i;:::-;94912:164;;-1:-1:-1;94912:164:0;-1:-1:-1;95140:1:0;95095:41;:33;94912:164;;95095:20;:33::i;:41::-;:46;;95087:70;;;;-1:-1:-1;;;95087:70:0;;;;;;;:::i;37124:103::-;37163:20;;:::i;:::-;-1:-1:-1;37203:16:0;;;;;;;;;-1:-1:-1;37203:16:0;;37124:103;:::o;63347:228::-;63468:34;;:::i;:::-;63447:1;63292;:3;;;-1:-1:-1;;;;;63277:18:0;;63297:21;;;;;;;;;;;;;;;;;63269:50;;;;;-1:-1:-1;;;63269:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;63527:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;63562:3;;63527:40;;-1:-1:-1;63527:40:0;63347:228::o;64606:304::-;64758:34;;:::i;:::-;64737:1;63292;:3;;;-1:-1:-1;;;;;63277:18:0;;63297:21;;;;;;;;;;;;;;;;;63269:50;;;;;-1:-1:-1;;;63269:50:0;;;;;;;;:::i;:::-;;64810:36:::1;;:::i;:::-;64861:22;64868:14;64880:1;64868:11;:14::i;:::-;64861:1:::0;;:6:::1;:22::i;38786:197::-:0;38871:20;;:::i;:::-;38904:22;;:::i;:::-;38952:3;;38943;;:13;;:8;:13::i;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46:0;;;;;;;:::i;31083:172::-;31156:14;;:::i;:::-;31183:16;;:::i;:::-;31224:3;;31216;;:12;;:7;:12::i;16179:216::-;16291:96;16311:5;16341:27;;;16370:4;16376:2;16380:5;16318:68;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;16318:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;16318:68:0;-1:-1:-1;;;;;;16318:68:0;;;;;;;;;;16291:19;:96::i;63583:121::-;63660:7;63687;:1;:5;:7::i;:::-;:9;;63583:121;-1:-1:-1;;63583:121:0:o;21089:604::-;21531:4;21642:17;21678:7;21089:604;:::o;23803:129::-;20633:13;;;;;;;;:33;;;20650:16;:14;:16::i;:::-;20633:50;;;-1:-1:-1;20671:12:0;;;;20670:13;20633:50;20625:109;;;;-1:-1:-1;;;20625:109:0;;;;;;;:::i;:::-;20747:19;20770:13;;;;;;20769:14;20794:101;;;;20829:13;:20;;-1:-1:-1;;;;20829:20:0;;;;;20864:19;20845:4;20864:19;;;20794:101;23861:26:::1;:24;:26::i;:::-;23898;:24;:26::i;:::-;20925:14:::0;20921:68;;;20972:5;20956:21;;-1:-1:-1;;20956:21:0;;;23803:129;:::o;72072:877::-;72217:24;72244:9;-1:-1:-1;;;;;72244:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72217:49;;72277:40;;:::i;:::-;72320:48;;;;;;;;;;-1:-1:-1;;;72336:31:0;;;72320:48;-1:-1:-1;;;;;72336:16:0;;;:31;72361:4;72336:31;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72320:48;;72277:91;-1:-1:-1;72412:16:0;:7;:14;:16::i;:::-;72383:26;:17;:24;:26::i;:::-;:45;72379:502;;;72445:38;;:::i;:::-;72486:31;:7;72499:17;72486:12;:31::i;:::-;72563:14;;:42;;-1:-1:-1;;;72563:42:0;;72445:72;;-1:-1:-1;72532:28:0;;-1:-1:-1;;;;;72563:14:0;;;;:31;;:42;;72595:9;;72563:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72532:73;;72620:39;;:::i;:::-;72662:57;;;;;;;;;;-1:-1:-1;;;72678:40:0;;;72662:57;-1:-1:-1;;;;;72678:16:0;;;:40;72703:13;72678:40;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72662:57;;72620:99;-1:-1:-1;72771:24:0;:15;:22;:24::i;:::-;72742:25;:16;:23;:25::i;:::-;:53;;72734:81;;;;-1:-1:-1;;;72734:81:0;;;;;;;:::i;:::-;72830:39;;-1:-1:-1;;;72830:39:0;;-1:-1:-1;;;;;72830:22:0;;;;;:39;;72853:15;;72830:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;72379:502;;;;72893:48;72913:9;72924:16;:7;:14;:16::i;:::-;-1:-1:-1;;;;;72893:19:0;;;:48;:19;:48::i;:::-;72072:877;;;;;:::o;31299:172::-;31372:14;;:::i;:::-;31399:16;;:::i;:::-;31440:3;;31432;;:12;;:7;:12::i;72957:1854::-;73072:22;;:::i;:::-;73096;;:::i;:::-;73136:43;;:::i;:::-;73182:14;:12;:14::i;:::-;73136:60;;73207:42;;:::i;:::-;73252:14;:12;:14::i;:::-;73207:59;;73280:48;;:::i;:::-;73330:47;;:::i;:::-;73394:44;73428:9;73394:33;:44::i;:::-;73279:159;;-1:-1:-1;73279:159:0;-1:-1:-1;73516:1:0;73457:55;:47;73495:8;73457:32;73279:159;;73457:18;:32::i;:::-;:37;;:47::i;:55::-;:60;;73449:84;;;;-1:-1:-1;;;73449:84:0;;;;;;;:::i;:::-;73547:33;;:::i;:::-;73582:32;;:::i;:::-;73618:23;73631:9;73618:12;:23::i;:::-;73546:95;;-1:-1:-1;73546:95:0;-1:-1:-1;73675:58:0;73706:26;73546:95;;73706:15;:26::i;:::-;73675:25;:8;73689:10;73675:13;:25::i;:58::-;73652:81;-1:-1:-1;73766:35:0;:8;73652:81;73766:13;:35::i;:::-;73744:57;;73814:54;;:::i;:::-;73871:40;:13;73890:20;73871:18;:40::i;:::-;73814:97;;73922:53;;:::i;:::-;73978:38;:12;73996:19;73978:17;:38::i;:::-;73922:94;;74031:32;:19;:30;:32::i;:::-;74027:361;;;74103:19;:13;:17;:19::i;:::-;74080:42;-1:-1:-1;74159:35:0;:8;74080:42;74159:13;:35::i;:::-;74137:57;;74027:361;;;74216:31;:18;:29;:31::i;:::-;74212:176;;;74286:18;:12;:16;:18::i;:::-;74264:40;-1:-1:-1;74342:34:0;:8;74264:40;74342:13;:34::i;:::-;74319:57;;74212:176;-1:-1:-1;;;;;74428:23:0;;74400:25;74428:23;;;:12;:23;;;;;;;;:52;;;;;;;;74559:8;74518:51;;;;;;74606:28;;;;;;;;;;;;74518:51;74606:50;;74635:20;74606:28;:50::i;:::-;74580:76;;;74692:27;;;;;;;;;;;;;:48;;74720:19;74692:27;:48::i;:::-;74667:73;;;-1:-1:-1;74761:20:0;;74783:19;;-1:-1:-1;72957:1854:0;;-1:-1:-1;;;;;;;;;72957:1854:0:o;31742:168::-;31813:14;;:::i;:::-;31840:16;;:::i;:::-;31873:3;;:10;;31881:1;31873:7;:10::i;32177:168::-;32248:14;;:::i;:::-;32275:16;;:::i;:::-;32308:3;;:10;;32316:1;32308:7;:10::i;64222:304::-;64374:34;;:::i;:::-;64353:1;63292;:3;;;-1:-1:-1;;;;;63277:18:0;;63297:21;;;;;;;;;;;;;;;;;63269:50;;;;;-1:-1:-1;;;63269:50:0;;;;;;;;:::i;:::-;;64426:36:::1;;:::i;:::-;64494:3:::0;;64479;;:20:::1;::::0;:7:::1;:20::i;37342:165::-:0;37409:4;37436:1;37430;:3;;;:7;37426:51;;;-1:-1:-1;37461:4:0;37454:11;;37426:51;-1:-1:-1;37494:5:0;37342:165;;;:::o;92469:356::-;92533:22;;:::i;:::-;92557;;:::i;:::-;92592:33;;:::i;:::-;-1:-1:-1;;;;;;;;92628:23:0;;;;;:12;:23;;;;;;;;;92592:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92684:54;;;;;;;92700:37;;92684:54;;92753:53;;;;;;;;92769:36;;92753:53;;92684:54;;92469:356::o;31515:173::-;31588:14;;:::i;:::-;31615:16;;:::i;:::-;31657:3;;31648;;:13;;:8;:13::i;31952:173::-;32025:14;;:::i;:::-;32052:16;;:::i;:::-;32094:3;;32085;;:13;;:8;:13::i;38063:196::-;38148:20;;:::i;:::-;38181:22;;:::i;:::-;38228:3;;38220;;:12;;:7;:12::i;38559:185::-;38635:20;;:::i;:::-;38668:22;;:::i;:::-;38707:3;;:10;;38715:1;38707:7;:10::i;37515:269::-;37575:22;;:::i;:::-;37610:24;;:::i;:::-;37649:3;;37655:1;-1:-1:-1;37645:113:0;;;37691:3;;;37687:7;37673:22;;37645:113;;;37742:3;;37728:18;;-1:-1:-1;37728:18:0;37515:269::o;28680:109::-;28764:17;;28760:2;:21;;28680:109::o;34919:215::-;34975:6;35005:5;;;35030:6;;;;;;:16;;;35045:1;35040;:6;;35030:16;35029:38;;;;35056:1;35052;:5;:14;;;;;35065:1;35061;:5;35052:14;35021:84;;;;-1:-1:-1;;;35021:84:0;;;;;;;:::i;38303:197::-;38388:20;;:::i;:::-;38421:22;;:::i;:::-;38469:3;;38460;;:13;;:8;:13::i;36510:105::-;36567:6;36593:14;36598:1;36601;36604:2;36593:4;:14::i;18343:772::-;18778:23;18804:69;18832:4;18804:69;;;;;;;;;;;;;;;;;18812:5;-1:-1:-1;;;;;18804:27:0;;;:69;;;;;:::i;:::-;18888:17;;18778:95;;-1:-1:-1;18888:21:0;18884:224;;19030:10;19019:30;;;;;;;;;;;;:::i;:::-;19011:85;;;;-1:-1:-1;;;19011:85:0;;;;;;;:::i;22452:65::-;20633:13;;;;;;;;:33;;;20650:16;:14;:16::i;:::-;20633:50;;;-1:-1:-1;20671:12:0;;;;20670:13;20633:50;20625:109;;;;-1:-1:-1;;;20625:109:0;;;;;;;:::i;:::-;20747:19;20770:13;;;;;;20769:14;20794:101;;;;20829:13;:20;;-1:-1:-1;;;;20829:20:0;;;;;20864:19;20845:4;20864:19;;;20925:14;20921:68;;;20972:5;20956:21;;-1:-1:-1;;20956:21:0;;;22452:65;:::o;23940:196::-;20633:13;;;;;;;;:33;;;20650:16;:14;:16::i;:::-;20633:50;;;-1:-1:-1;20671:12:0;;;;20670:13;20633:50;20625:109;;;;-1:-1:-1;;;20625:109:0;;;;;;;:::i;:::-;20747:19;20770:13;;;;;;20769:14;20794:101;;;;20829:13;:20;;-1:-1:-1;;;;20829:20:0;;;;;20864:19;20845:4;20864:19;;;20794:101;24008:17:::1;24028:12;:10;:12::i;:::-;24051:6;:18:::0;;-1:-1:-1;;;;;;24051:18:0::1;-1:-1:-1::0;;;;;24051:18:0;::::1;::::0;;::::1;::::0;;;24085:43:::1;::::0;24051:18;;-1:-1:-1;24051:18:0;-1:-1:-1;;24085:43:0::1;::::0;-1:-1:-1;;24085:43:0::1;20907:1;20925:14:::0;20921:68;;;20972:5;20956:21;;-1:-1:-1;;20956:21:0;;;23940:196;:::o;15983:188::-;16077:86;16097:5;16127:23;;;16152:2;16156:5;16104:58;;;;;;;;;:::i;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;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;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;34456:218::-;34512:6;34542:5;;;34567:6;;;;;;:16;;;34582:1;34577;:6;;34567:16;34566:38;;;;34593:1;34589;:5;:14;;;;;34602:1;34598;:5;34589:14;34558:87;;;;-1:-1:-1;;;34558:87:0;;;;;;;:::i;29270:108::-;29329:7;29356:14;29361:1;29364;29367:2;29356:4;:14::i;29745:108::-;29804:7;29831:14;29836:1;29839;29842:2;29831:4;:14::i;32892:568::-;32948:6;33192;33188:47;;-1:-1:-1;33222:1:0;33215:8;;33188:47;33257:1;-1:-1:-1;;33257:7:0;:27;;;;;-1:-1:-1;;;33268:1:0;:16;33257:27;33255:30;33247:82;;;;-1:-1:-1;;;33247:82:0;;;;;;;:::i;:::-;33353:5;;;33357:1;33353;:5;:1;33377:5;;;;;:10;33369:62;;;;-1:-1:-1;;;33369:62:0;;;;;;;:::i;36041:105::-;36098:6;36124:14;36129:1;36132;36135:2;36124:4;:14::i;36717:169::-;36824:6;36850:28;36876:1;36850:21;36856:14;36861:8;36856:4;:14::i;:::-;36850:1;;:5;:21::i;:::-;:25;;:28::i;:::-;36843:35;36717:169;-1:-1:-1;;;;36717:169:0:o;11959:195::-;12062:12;12094:52;12116:6;12124:4;12130:1;12133:12;12094:21;:52::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;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;29479:172::-;29588:7;29615:28;29628:14;29633:8;29628:4;:14::i;:::-;29615:8;:1;29621;29615:5;:8::i;:::-;:12;;:28::i;29955:172::-;30064:7;30091:28;30117:1;30091:21;30097:14;30102:8;30097:4;:14::i;:::-;30091:1;;:5;:21::i;36247:169::-;36354:6;36380:28;36393:14;36398:8;36393:4;:14::i;:::-;36380:8;:1;36386;36380:5;:8::i;33934:271::-;33990:6;34017;34009:51;;;;-1:-1:-1;;;34009:51:0;;;;;;;:::i;:::-;34081:1;-1:-1:-1;;34081:7:0;:27;;;;;-1:-1:-1;;;34092:1:0;:16;34081:27;34079:30;34071:76;;;;-1:-1:-1;;;34071:76:0;;;;;;;:::i;:::-;34160:8;34175:1;34171;:5;;;;;;;33934:271;-1:-1:-1;;;;33934:271:0:o;13011:530::-;13138:12;13196:5;13171:21;:30;;13163:81;;;;-1:-1:-1;;;13163:81:0;;;;;;;:::i;:::-;13263:18;13274:6;13263:10;:18::i;:::-;13255:60;;;;-1:-1:-1;;;13255:60:0;;;;;;;:::i;:::-;13389:12;13403:23;13430:6;-1:-1:-1;;;;;13430:11:0;13450:5;13458:4;13430:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13388:75;;;;13481:52;13499:7;13508:10;13520:12;13481:17;:52::i;:::-;13474:59;13011:530;-1:-1:-1;;;;;;;13011:530:0:o;9041:422::-;9408:20;9447:8;;;9041:422::o;14547:742::-;14662:12;14691:7;14687:595;;;-1:-1:-1;14722:10:0;14715:17;;14687:595;14836:17;;:21;14832:439;;15099:10;15093:17;15160:15;15147:10;15143:2;15139:19;15132:44;15047:148;15242:12;15235:20;;-1:-1:-1;;;15235:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;1146:148::-;1222:20;;43833:1;43823:12;;43813:2;;43849:1;;43839:12;1469:320;;1583:4;1571:9;1566:3;1562:19;1558:30;1555:2;;;-1:-1;;1591:12;1555:2;1619:20;1583:4;1619:20;:::i;:::-;2636;;1693:75;;-1:-1;1610:29;1549:240;-1:-1;1549:240::o;1825:342::-;;1950:4;1938:9;1933:3;1929:19;1925:30;1922:2;;;-1:-1;;1958:12;1922:2;1986:20;1950:4;1986:20;:::i;:::-;2784:13;;2060:86;;-1:-1;1977:29;1916:251;-1:-1;1916:251::o;2847:241::-;;2951:2;2939:9;2930:7;2926:23;2922:32;2919:2;;;-1:-1;;2957:12;2919:2;85:6;72:20;97:33;124:5;97:33;:::i;3095:263::-;;3210:2;3198:9;3189:7;3185:23;3181:32;3178:2;;;-1:-1;;3216:12;3178:2;226:6;220:13;238:33;265:5;238:33;:::i;3365:491::-;;;;3503:2;3491:9;3482:7;3478:23;3474:32;3471:2;;;-1:-1;;3509:12;3471:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3561:63;-1:-1;3661:2;3700:22;;72:20;97:33;72:20;97:33;:::i;:::-;3465:391;;3669:63;;-1:-1;;;3769:2;3808:22;;;;2636:20;;3465:391::o;3863:384::-;;;3993:2;3981:9;3972:7;3968:23;3964:32;3961:2;;;-1:-1;;3999:12;3961:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4051:63;-1:-1;4169:62;4223:7;4151:2;4199:22;;4169:62;:::i;:::-;4159:72;;3955:292;;;;;:::o;4254:509::-;;;;4401:2;4389:9;4380:7;4376:23;4372:32;4369:2;;;-1:-1;;4407:12;4369:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4459:63;-1:-1;4577:62;4631:7;4559:2;4607:22;;4577:62;:::i;:::-;4567:72;;4676:2;4719:9;4715:22;72:20;97:33;124:5;97:33;:::i;:::-;4684:63;;;;4363:400;;;;;:::o;4770:509::-;;;;4917:2;4905:9;4896:7;4892:23;4888:32;4885:2;;;-1:-1;;4923:12;4885:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4975:63;-1:-1;5093:62;5147:7;5075:2;5123:22;;5093:62;:::i;:::-;5083:72;;5192:2;5235:9;5231:22;2636:20;5200:63;;4879:400;;;;;:::o;5286:416::-;;;5432:2;5420:9;5411:7;5407:23;5403:32;5400:2;;;-1:-1;;5438:12;5400:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5490:63;-1:-1;5608:78;5678:7;5590:2;5654:22;;5608:78;:::i;5709:491::-;;;;5847:2;5835:9;5826:7;5822:23;5818:32;5815:2;;;-1:-1;;5853:12;5815:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5905:63;6005:2;6044:22;;2636:20;;-1:-1;6113:2;6152:22;;;2636:20;;5809:391;-1:-1;;;5809:391::o;6207:257::-;;6319:2;6307:9;6298:7;6294:23;6290:32;6287:2;;;-1:-1;;6325:12;6287:2;364:6;358:13;43054:5;40699:13;40692:21;43032:5;43029:32;43019:2;;-1:-1;;43065:12;7075:577;;;;7256:2;7244:9;7235:7;7231:23;7227:32;7224:2;;;-1:-1;;7262:12;7224:2;707:6;694:20;719:51;764:5;719:51;:::i;:::-;7314:81;-1:-1;7432:2;7471:22;;72:20;97:33;72:20;97:33;:::i;:::-;7440:63;-1:-1;7558:78;7628:7;7540:2;7604:22;;7558:78;:::i;:::-;7548:88;;7218:434;;;;;:::o;8086:595::-;;;;8276:2;8264:9;8255:7;8251:23;8247:32;8244:2;;;-1:-1;;8282:12;8244:2;707:6;694:20;719:51;764:5;719:51;:::i;:::-;8334:81;-1:-1;8470:62;8524:7;8452:2;8500:22;;8470:62;:::i;9769:313::-;;9909:2;9897:9;9888:7;9884:23;9880:32;9877:2;;;-1:-1;;9915:12;9877:2;9977:89;10058:7;10034:22;9977:89;:::i;10089:499::-;;;10271:2;10259:9;10250:7;10246:23;10242:32;10239:2;;;-1:-1;;10277:12;10239:2;10339:89;10420:7;10396:22;10339:89;:::i;:::-;10329:99;;10483:89;10564:7;10465:2;10544:9;10540:22;10483:89;:::i;10927:241::-;;11031:2;11019:9;11010:7;11006:23;11002:32;10999:2;;;-1:-1;;11037:12;10999:2;-1:-1;2636:20;;10993:175;-1:-1;10993:175::o;11175:263::-;;11290:2;11278:9;11269:7;11265:23;11261:32;11258:2;;;-1:-1;;11296:12;11258:2;-1:-1;2784:13;;11252:186;-1:-1;11252:186::o;22397:271::-;;11725:5;40040:12;11836:52;11881:6;11876:3;11869:4;11862:5;11858:16;11836:52;:::i;:::-;11900:16;;;;;22531:137;-1:-1;;22531:137::o;22675:222::-;-1:-1;;;;;41472:54;;;;11516:37;;22802:2;22787:18;;22773:124::o;22904:444::-;-1:-1;;;;;41472:54;;;11516:37;;41472:54;;;;23251:2;23236:18;;11516:37;23334:2;23319:18;;12484:36;;;;23087:2;23072:18;;23058:290::o;23355:333::-;-1:-1;;;;;41472:54;;;;11516:37;;23674:2;23659:18;;12484:36;23510:2;23495:18;;23481:207::o;24237:236::-;24371:2;24356:18;;41278:42;41314:5;41278:42;:::i;:::-;12356:57;;;24342:131;:::o;24480:458::-;24670:2;24655:18;;41278:42;41314:5;41278:42;:::i;:::-;12356:57;;;-1:-1;;;;;41472:54;;;;24841:2;24826:18;;11516:37;24924:2;24909:18;;;12484:36;24641:297;:::o;24945:325::-;12484:36;;;25256:2;25241:18;;12484:36;25096:2;25081:18;;25067:203::o;25277:310::-;;25424:2;25445:17;25438:47;12794:5;40040:12;40479:6;25424:2;25413:9;25409:18;40467:19;12888:52;12933:6;40507:14;25413:9;40507:14;25424:2;12914:5;12910:16;12888:52;:::i;:::-;42721:7;42705:14;-1:-1;;42701:28;12952:39;;;;40507:14;12952:39;;25395:192;-1:-1;;25395:192::o;25594:416::-;25794:2;25808:47;;;13228:2;25779:18;;;40467:19;-1:-1;;;40507:14;;;13244:41;13304:12;;;25765:245::o;26017:416::-;26217:2;26231:47;;;13555:2;26202:18;;;40467:19;13591:34;40507:14;;;13571:55;-1:-1;;;13646:12;;;13639:30;13688:12;;;26188:245::o;26440:416::-;26640:2;26654:47;;;13939:2;26625:18;;;40467:19;-1:-1;;;40507:14;;;13955:37;14011:12;;;26611:245::o;26863:416::-;27063:2;27077:47;;;14262:2;27048:18;;;40467:19;14298:29;40507:14;;;14278:50;14347:12;;;27034:245::o;27286:416::-;27486:2;27500:47;;;14598:2;27471:18;;;40467:19;-1:-1;;;40507:14;;;14614:38;14671:12;;;27457:245::o;27709:416::-;27909:2;27923:47;;;14922:2;27894:18;;;40467:19;14958:34;40507:14;;;14938:55;-1:-1;;;15013:12;;;15006:25;15050:12;;;27880:245::o;28132:416::-;28332:2;28346:47;;;15301:2;28317:18;;;40467:19;-1:-1;;;40507:14;;;15317:36;15372:12;;;28303:245::o;28555:416::-;28755:2;28769:47;;;15623:2;28740:18;;;40467:19;15659:34;40507:14;;;15639:55;-1:-1;;;15714:12;;;15707:30;15756:12;;;28726:245::o;28978:416::-;29178:2;29192:47;;;16007:2;29163:18;;;40467:19;-1:-1;;;40507:14;;;16023:34;16076:12;;;29149:245::o;29401:416::-;29601:2;29615:47;;;16327:2;29586:18;;;40467:19;16363:34;40507:14;;;16343:55;-1:-1;;;16418:12;;;16411:38;16468:12;;;29572:245::o;29824:416::-;30024:2;30038:47;;;16719:2;30009:18;;;40467:19;16755:34;40507:14;;;16735:55;-1:-1;;;16810:12;;;16803:25;16847:12;;;29995:245::o;30247:416::-;30447:2;30461:47;;;17098:2;30432:18;;;40467:19;17134:34;40507:14;;;17114:55;-1:-1;;;17189:12;;;17182:25;17226:12;;;30418:245::o;30670:416::-;30870:2;30884:47;;;17477:2;30855:18;;;40467:19;-1:-1;;;40507:14;;;17493:33;17545:12;;;30841:245::o;31093:416::-;31293:2;31307:47;;;31278:18;;;40467:19;17832:34;40507:14;;;17812:55;17886:12;;;31264:245::o;31516:416::-;31716:2;31730:47;;;18137:2;31701:18;;;40467:19;-1:-1;;;40507:14;;;18153:39;18211:12;;;31687:245::o;31939:416::-;32139:2;32153:47;;;18462:2;32124:18;;;40467:19;18498:34;40507:14;;;18478:55;-1:-1;;;18553:12;;;18546:31;18596:12;;;32110:245::o;32362:416::-;32562:2;32576:47;;;18847:2;32547:18;;;40467:19;-1:-1;;;40507:14;;;18863:37;18919:12;;;32533:245::o;32785:416::-;32985:2;32999:47;;;19170:2;32970:18;;;40467:19;-1:-1;;;40507:14;;;19186:45;19250:12;;;32956:245::o;33208:416::-;33408:2;33422:47;;;19501:2;33393:18;;;40467:19;19537:31;40507:14;;;19517:52;19588:12;;;33379:245::o;33631:416::-;33831:2;33845:47;;;19839:2;33816:18;;;40467:19;-1:-1;;;40507:14;;;19855:36;19910:12;;;33802:245::o;34054:416::-;34254:2;34268:47;;;20161:2;34239:18;;;40467:19;20197:34;40507:14;;;20177:55;-1:-1;;;20252:12;;;20245:28;20292:12;;;34225:245::o;34477:416::-;34677:2;34691:47;;;20543:2;34662:18;;;40467:19;20579:34;40507:14;;;20559:55;-1:-1;;;20634:12;;;20627:34;20680:12;;;34648:245::o;34900:416::-;35100:2;35114:47;;;20931:2;35085:18;;;40467:19;-1:-1;;;40507:14;;;20947:38;21004:12;;;35071:245::o;35323:416::-;35523:2;35537:47;;;35508:18;;;40467:19;21291:34;40507:14;;;21271:55;21345:12;;;35494:245::o;35746:322::-;21632:23;;12484:36;;35923:2;35908:18;;35894:174::o;36075:533::-;21632:23;;12484:36;;21632:23;36594:2;36579:18;;12484:36;36330:2;36315:18;;36301:307::o;36615:544::-;21632:23;;12484:36;;37062:2;37047:18;;12484:36;;;;37145:2;37130:18;;12484:36;36848:2;36833:18;;36819:340::o;38107:222::-;12484:36;;;38234:2;38219:18;;38205:124::o;38676:444::-;12484:36;;;39023:2;39008:18;;12484:36;;;;39106:2;39091:18;;12484:36;38859:2;38844:18;;38830:290::o;39127:556::-;12484:36;;;39503:2;39488:18;;12484:36;;;;39586:2;39571:18;;12484:36;39669:2;39654:18;;12484:36;39338:3;39323:19;;39309:374::o;39690:256::-;39752:2;39746:9;39778:17;;;39853:18;39838:34;;39874:22;;;39835:62;39832:2;;;39910:1;;39900:12;39832:2;39752;39919:22;39730:216;;-1:-1;39730:216::o;42361:268::-;42426:1;42433:101;42447:6;42444:1;42441:13;42433:101;;;42514:11;;;42508:18;42495:11;;;42488:39;42469:2;42462:10;42433:101;;;42549:6;42546:1;42543:13;42540:2;;;-1:-1;;42426:1;42596:16;;42589:27;42410:219::o;42742:100::-;42820:1;42813:5;42810:12;42800:2;;42826:9;42849:117;-1:-1;;;;;41472:54;;42908:35;;42898:2;;42957:1;;42947:12

Swarm Source

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