Contract 0xb001af779dd686ec93e6276e53562693a793f1f9

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xdec451441de10378cac3db8cc1a23d05cbd3bbcb2ed5212149a43c76f01d5ecd0x6080604084461552021-05-01 0:24:19142 days 19 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.04275022
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x0cb56f9298a9a366d7b5341fab7eae265adeaf29dac66fd45a3c3c2510d393eb92317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x894efae7102784ca378bb24fbe2581744df0f9baf8a1995bff8adb5464827b1192317772021-05-28 8:09:02115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:59115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:59115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xca18c999db51acfc8b32a7abac2ae58becb27936cd3162cabff875cc9944a02792317762021-05-28 8:08:59115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xf20c981e6b31b8960e12b35fcb457972df124edc4e565af149e9e6a1aab38c8f92315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xf20c981e6b31b8960e12b35fcb457972df124edc4e565af149e9e6a1aab38c8f92315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xf20c981e6b31b8960e12b35fcb457972df124edc4e565af149e9e6a1aab38c8f92315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x2f3244798831a8e9353420721f8ea34ed3b92ca39977ae623b432b2b26e16aa892315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x2f3244798831a8e9353420721f8ea34ed3b92ca39977ae623b432b2b26e16aa892315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x2f3244798831a8e9353420721f8ea34ed3b92ca39977ae623b432b2b26e16aa892315782021-05-28 7:59:05115 days 11 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xcfda2716d7fe7042f304cd036b944d006fe8a4ede216748f5c9fe07cb6deb8b792315162021-05-28 7:55:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xcfda2716d7fe7042f304cd036b944d006fe8a4ede216748f5c9fe07cb6deb8b792315162021-05-28 7:55:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xcfda2716d7fe7042f304cd036b944d006fe8a4ede216748f5c9fe07cb6deb8b792315162021-05-28 7:55:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x0e590e31b97481e6090fa739a79f15f60166145241a46e4f8e39c7f2de97abea92314172021-05-28 7:51:02115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x0e590e31b97481e6090fa739a79f15f60166145241a46e4f8e39c7f2de97abea92314172021-05-28 7:51:02115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x0e590e31b97481e6090fa739a79f15f60166145241a46e4f8e39c7f2de97abea92314172021-05-28 7:51:02115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x5d342f3b054cd75f048e70790d4ce1b9fd2f53bdcc91163b84872bc2f8ab9c5592314162021-05-28 7:50:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x5d342f3b054cd75f048e70790d4ce1b9fd2f53bdcc91163b84872bc2f8ab9c5592314162021-05-28 7:50:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0x5d342f3b054cd75f048e70790d4ce1b9fd2f53bdcc91163b84872bc2f8ab9c5592314162021-05-28 7:50:59115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
0xbf636ff78acc17c77458db84bb85117b28b2512acabb2d358972f4b1c9d679c292313802021-05-28 7:49:11115 days 12 hrs ago 0xc8e4b4849e8867bdb97c62c54a53011244807e32 0xb001af779dd686ec93e6276e53562693a793f1f90 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

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

// 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: @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 {
    constructor(string memory _name, string memory _symbol) public {
        __ERC20_init(_name, _symbol);
        __Ownable_init();
    }

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

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

// File: contracts/interface/IExchangeState.sol







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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: contracts/interface/IExchange.sol








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

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

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

    function shutdown() external;

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

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

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

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

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

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

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

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

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

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

    function getLiquidityHistoryLength() external view returns (uint256);

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

    function open() external view returns (bool);

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

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

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

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

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

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

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

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

    function moveAMMPriceToOracle(uint256 _oraclePrice, bytes32 _priceFeedKey) external;

    function setPriceFeed(address _priceFeed) external;

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

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

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

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

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

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

    function priceFeedKey() external view returns (bytes32);

    function tradeLimitRatio() external view returns (uint256);

    function priceAdjustRatio() external view returns (uint256);

    function fluctuationLimitRatio() external view returns (uint256);

    function fundingPeriod() external view returns (uint256);

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

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

    function exchangeState() external view returns (IExchangeState);

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

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

// File: contracts/interface/ISakePerpVault.sol






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

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

    function modifyLiquidity() external;

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

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

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

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

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

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

    function requireMMNotBankrupt(address _exchange) external;

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

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

    function setHighRiskLiquidityWeight(address _exchange, uint256 _weight) external;

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

// File: contracts/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);
}

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

    //
    // 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;
        uint256 maxLoss;
    }

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

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

    // exchange info
    mapping(address => ExchangeInfo) public exchangeInfo;
    // minimum lp price for every exchange
    mapping(address => mapping(uint256 => Decimal.decimal)) public minLpTokenPrice;

    //**********************************************************//
    //    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) public initializer {
        sakePerp = _sakePerp;
        systemSettings = ISystemSettings(_systemSettings);
        __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 _weight lp token weight
     */
    function setHighRiskLiquidityWeight(address _exchange, uint256 _weight) public override {
        require(_msgSender() == owner() || _msgSender() == _exchange, "invalid caller");
        exchangeInfo[_exchange].highRiskLiquidityWeight = _weight;
    }

    /**
     * @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");
        exchangeInfo[_exchange].poolInfo[uint256(_risk)].maxLoss = _max;
    }

    /**
     * @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();
        updateMinLpTokenPrice(_exchange);
        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);

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

        Decimal.decimal memory totalLpTokenAmount =
            Decimal.decimal(_exchange.exchangeState().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)
            );
        }

        poolInfo.totalLiquidity = poolInfo.totalLiquidity.addD(_quoteAssetAmount);
        _exchange.quoteAsset().safeTransferFrom(_msgSender(), address(this), _quoteAssetAmount.toUint());
        _exchange.mint(_risk, _msgSender(), returnLpAmount.toUint());

        emit LiquidityAdd(
            address(_exchange),
            _msgSender(),
            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 {
        requireExchange(_exchange, true);
        requireNonZeroInput(_lpTokenAmount);
        _requireMMNotBankrupt(address(_exchange), _risk);

        PoolInfo storage poolInfo = exchangeInfo[address(_exchange)].poolInfo[uint256(_risk)];
        SignedDecimal.signedDecimal memory lpUnrealizedPNL = getLpUnrealizedPNL(address(_exchange), _risk);
        Decimal.decimal memory totalLpTokenAmount =
            Decimal.decimal(_exchange.exchangeState().getLPToken(_risk).totalSupply());
        SignedDecimal.signedDecimal memory returnAmount =
            poolInfo.totalLiquidity.addD(lpUnrealizedPNL).mulD(_lpTokenAmount).divD(totalLpTokenAmount).mulD(
                Decimal.one().subD(systemSettings.lpWithdrawFeeRatio())
            );

        poolInfo.totalLiquidity = poolInfo.totalLiquidity.subD(returnAmount);
        _withdraw(_exchange, _msgSender(), returnAmount.abs());
        _exchange.burn(_risk, _msgSender(), _lpTokenAmount.toUint());

        emit LiquidityRemove(
            address(_exchange),
            _msgSender(),
            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 {
        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) {
            Decimal.decimal memory _lpTokenAmount =
                Decimal.decimal(_exchange.exchangeState().getLPToken(_risk).balanceOf(_msgSender()));
            Decimal.decimal memory totalLpTokenAmount =
                Decimal.decimal(_exchange.exchangeState().getLPToken(_risk).totalSupply());
            SignedDecimal.signedDecimal memory returnAmount =
                remainAmount.mulD(_lpTokenAmount).divD(totalLpTokenAmount);

            poolInfo.totalLiquidity = poolInfo.totalLiquidity.subD(returnAmount);
            _exchange.burn(_risk, _msgSender(), _lpTokenAmount.toUint());
            _withdraw(_exchange, _msgSender(), returnAmount.abs());

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

    function updateMinLpTokenPrice(address _exchange) internal {
        (SignedDecimal.signedDecimal memory highLiquidity, SignedDecimal.signedDecimal memory lowLiquidity) =
            getAllMMLiquidity(_exchange);
        (SignedDecimal.signedDecimal memory highUnrealizedPNL, SignedDecimal.signedDecimal memory lowUnrealizedPNL) =
            getAllLpUnrealizedPNL(_exchange);

        // check if need to update high pool minimum price
        {
            Decimal.decimal memory totalHighLpTokenAmount =
                Decimal.decimal(IExchange(_exchange).exchangeState().getLPToken(Risk.HIGH).totalSupply());
            if (totalHighLpTokenAmount.toUint() > 0) {
                Decimal.decimal memory _highPrice =
                    highLiquidity.addD(highUnrealizedPNL).divD(totalHighLpTokenAmount).abs();
                uint256 _maxLoss = exchangeInfo[_exchange].poolInfo[uint256(Risk.HIGH)].maxLoss;
                Decimal.decimal memory _highMinPrice = _highPrice.mulScalar(UINT100 - _maxLoss).divScalar(UINT100);
                Decimal.decimal memory lastHighMinPrice = getMinLpTokenPrice(_exchange, Risk.HIGH);
                if (_highMinPrice.cmp(lastHighMinPrice) > 0) {
                    minLpTokenPrice[_exchange][uint256(Risk.HIGH)] = _highMinPrice;
                }
            }
        }

        // check if need to update low pool minimum price
        {
            Decimal.decimal memory totalLowLpTokenAmount =
                Decimal.decimal(IExchange(_exchange).exchangeState().getLPToken(Risk.LOW).totalSupply());
            if (totalLowLpTokenAmount.toUint() > 0) {
                Decimal.decimal memory _lowPrice =
                    lowLiquidity.addD(lowUnrealizedPNL).divD(totalLowLpTokenAmount).abs();
                uint256 _maxLoss = exchangeInfo[_exchange].poolInfo[uint256(Risk.LOW)].maxLoss;
                Decimal.decimal memory _lowMinPrice = _lowPrice.mulScalar(UINT100 - _maxLoss).divScalar(UINT100);
                Decimal.decimal memory lastLowMinPrice = getMinLpTokenPrice(_exchange, Risk.LOW);
                if (_lowMinPrice.cmp(lastLowMinPrice) > 0) {
                    minLpTokenPrice[_exchange][uint256(Risk.LOW)] = _lowMinPrice;
                }
            }
        }
    }

    //
    // 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)
    {
        (Decimal.decimal memory highFactor, Decimal.decimal memory lowFactor) = _getMMFactor(_exchange);
        SignedDecimal.signedDecimal memory totalLpUnrealizedPNL = getTotalLpUnrealizedPNL(IExchange(_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(_exchange.exchangeState().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 totalHighLpTokenAmount =
            Decimal.decimal(IExchange(_exchange).exchangeState().getLPToken(Risk.HIGH).totalSupply());
        Decimal.decimal memory totalLowLpTokenAmount =
            Decimal.decimal(IExchange(_exchange).exchangeState().getLPToken(Risk.LOW).totalSupply());
        Decimal.decimal memory highLockedLiquidity =
            getMinLpTokenPrice(_exchange, Risk.HIGH).mulD(totalHighLpTokenAmount);
        Decimal.decimal memory lowLockedLiquidity = getMinLpTokenPrice(_exchange, Risk.LOW).mulD(totalLowLpTokenAmount);
        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);
        if (highFactor.addD(lowFactor).toUint() == 0) {
            return Decimal.zero();
        }
        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(UINT100));
    }

    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, UINT100);
    }

    function getMinLpTokenPrice(address _exchange, Risk _risk) public view returns (Decimal.decimal memory) {
        Decimal.decimal memory minPrice = minLpTokenPrice[_exchange][uint256(_risk)];
        if (minPrice.toUint() == 0) {
            uint256 _maxLoss = exchangeInfo[_exchange].poolInfo[uint256(_risk)].maxLoss;
            return Decimal.one().mulScalar(UINT100 - _maxLoss).divScalar(UINT100);
        }
        return minPrice;
    }

    //
    // 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"}],"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"}],"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"}],"name":"getMinLpTokenPrice","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":"getPoolWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"minLpTokenPrice","outputs":[{"internalType":"uint256","name":"d","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":"address","name":"_exchange","type":"address"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"setHighRiskLiquidityWeight","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":"_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"}]

608060405234801561001057600080fd5b50614c58806100206000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80638df3fab311610125578063c7c332d3116100ad578063e885c04d1161007c578063e885c04d14610493578063ebb5b42c146104a6578063eec6298f146104b9578063f2a5dca3146104cc578063f2fde38b146104df5761021c565b8063c7c332d314610447578063d25ca42a1461045a578063e16448b81461046d578063e4d8074e146104805761021c565b8063b411db68116100f4578063b411db68146103db578063bd27ca3c146103ee578063bebb00a314610401578063c098075714610414578063c5e2a11a146104345761021c565b80638df3fab3146103a55780638e483328146103ad578063a79dca56146103b5578063ae9a0434146103c85761021c565b806350b7c658116101a857806360b42f121161017757806360b42f121461035a578063633ceadb1461036f578063715018a61461038257806386be9e8b1461038a5780638da5cb5b1461039d5761021c565b806350b7c658146103005780635757ed5b146103135780635dbbfc47146103265780635f06cd2c146103395761021c565b806338ef3570116101ef57806338ef3570146102a15780633dd97387146102b4578063485cc955146102c75780634b89a6a0146102da5780634d068a43146102ed5761021c565b8063033e97f414610221578063140eb8e71461024b578063180c91f1146102605780633400d7c914610280575b600080fd5b61023461022f3660046143c8565b6104f2565b60405161024292919061464b565b60405180910390f35b61025e610259366004614515565b61070d565b005b61027361026e366004614374565b610afe565b6040516102429190614b1a565b61029361028e366004614374565b610b38565b604051610242929190614b24565b61025e6102af3660046144ce565b610ba5565b61025e6102c2366004614374565b610bf8565b61025e6102d5366004614390565b610c75565b61025e6102e8366004614467565b610d31565b6102736102fb3660046143c8565b610db2565b61025e61030e36600461443b565b610dfe565b610234610321366004614374565b6111cf565b610234610334366004614374565b6111f0565b61034c610347366004614374565b611229565b604051610242929190614b34565b610362611253565b60405161024291906145bd565b61027361037d366004614374565b611262565b61025e611299565b61025e6103983660046143fd565b611318565b6103626113e6565b61025e6113f5565b6103626115ec565b6102736103c33660046143c8565b6115fb565b6102936103d6366004614374565b61164d565b6102936103e93660046143c8565b611798565b6102736103fc3660046143c8565b611815565b61027361040f366004614374565b6118ed565b610427610422366004614467565b6119f8565b6040516102429190614b43565b610293610442366004614374565b611a15565b61025e610455366004614515565b611e49565b6102736104683660046143c8565b6121ec565b61027361047b366004614374565b6122b7565b61025e61048e366004614374565b612390565b61025e6104a13660046143c8565b61240d565b61025e6104b436600461443b565b6128bb565b6102936104c7366004614374565b612935565b61025e6104da366004614374565b612a16565b61025e6104ed366004614374565b612a83565b6000806104fd6142c8565b6105056142c8565b61050f8686611798565b9150915061051b6142c8565b6040518060200160405280886001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b15801561055f57600080fd5b505afa158015610573573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059791906144b2565b6001600160a01b03166351f59d0c896040518263ffffffff1660e01b81526004016105c2919061460e565b60206040518083038186803b1580156105da57600080fd5b505afa1580156105ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061291906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064a57600080fd5b505afa15801561065e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106829190614589565b9052905061068f81612b3a565b6106b7576106a361069e612b3e565b612b3a565b93506106b061069e612b3e565b9450610703565b6106bf6142c8565b6106d36106cc8989611815565b8590612b62565b90506106ec61069e836106e68685612bd1565b90612bf7565b94506106ff61069e836106e68688612bd1565b9550505b5050509250929050565b610718836001612c62565b61072181612df3565b6001600160a01b03831660009081526067602052604081208184600181111561074657fe5b8152602001908152602001600020905061075e6142c8565b6107688585610db2565b90506107726142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b1580156107b657600080fd5b505afa1580156107ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ee91906144b2565b6001600160a01b03166351f59d0c886040518263ffffffff1660e01b8152600401610819919061460e565b60206040518083038186803b15801561083157600080fd5b505afa158015610845573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086991906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108a157600080fd5b505afa1580156108b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d99190614589565b9052905060006108e882612b3a565b11156108f8576108f88686612e1b565b6109006142c8565b610908612e67565b905061091382612b3a565b6109275761092085612e82565b9050610960565b60408051602081019091528454815261095d906109449085612bd1565b6109578461095189612e82565b90612ee6565b90612f51565b90505b6040805160208101909152845481526109799086612b62565b518455610a13610987612f6e565b3061099188612b3a565b8a6001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b1580156109ca57600080fd5b505afa1580156109de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0291906144b2565b6001600160a01b0316929190612f72565b866001600160a01b031663eebab8ef87610a2b612f6e565b610a3485612fca565b6040518463ffffffff1660e01b8152600401610a5293929190614621565b600060405180830381600087803b158015610a6c57600080fd5b505af1158015610a80573d6000803e3d6000fd5b50505050610a8c612f6e565b6001600160a01b0316876001600160a01b03167fe67d500110d375cdd8e134bf404908658cd4c8c7813d9822169f5d2a9a3c5077886001811115610acc57fe5b610ad589612b3a565b610ade86612fca565b604051610aed93929190614b4c565b60405180910390a350505050505050565b610b066142c8565b610b0e6142c8565b610b166142c8565b610b1f84611a15565b9092509050610b2e8282612bd1565b925050505b919050565b610b406142c8565b610b486142c8565b610b506142c8565b610b586142c8565b610b6185611a15565b91509150610b6d6142c8565b610b756142c8565b610b7e8761164d565b9092509050610b8d8483612bd1565b610b978483612bd1565b95509550505050505b915091565b6066546001600160a01b0316610bb9612f6e565b6001600160a01b031614610be85760405162461bcd60e51b8152600401610bdf90614a07565b60405180910390fd5b610bf3838383612fdc565b505050565b610c00612f6e565b6033546001600160a01b03908116911614610c2d5760405162461bcd60e51b8152600401610bdf90614924565b6001600160a01b038116610c535760405162461bcd60e51b8152600401610bdf9061479e565b606680546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1680610c8e5750610c8e6132f4565b80610c9c575060005460ff16155b610cb85760405162461bcd60e51b8152600401610bdf90614830565b600054610100900460ff16158015610ce3576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b038086166001600160a01b0319928316179092556065805492851692909116919091179055610d1b6132fa565b8015610bf3576000805461ff0019169055505050565b610d396113e6565b6001600160a01b0316610d4a612f6e565b6001600160a01b03161480610d775750816001600160a01b0316610d6c612f6e565b6001600160a01b0316145b610d935760405162461bcd60e51b8152600401610bdf906146fe565b6001600160a01b03909116600090815260676020526040902060020155565b610dba6142c8565b610dc26142c8565b610dca6142c8565b610dd38561164d565b90925090506000846001811115610de657fe5b14610df15780610df3565b815b925050505b92915050565b6066546001600160a01b0316610e12612f6e565b6001600160a01b031614610e385760405162461bcd60e51b8152600401610bdf90614a07565b606554604051633f694ac560e11b81526000916001600160a01b031690637ed2958a90610e699086906004016145bd565b60206040518083038186803b158015610e8157600080fd5b505afa158015610e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb991906144b2565b9050610ec36142c8565b6040518060200160405280856001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b158015610f0757600080fd5b505afa158015610f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3f91906144b2565b6001600160a01b03166370a08231856040518263ffffffff1660e01b8152600401610f6a91906145bd565b60206040518083038186803b158015610f8257600080fd5b505afa158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba9190614589565b90529050610fc66142c8565b610fce612e67565b9050610fd86142c8565b610fe0612e67565b9050610fea6142c8565b610ff2612e67565b9050610ffc6142c8565b611004612e67565b905061100f87612b3a565b61101886612b3a565b106110ae57604051631f73d2e760e11b81526001600160a01b03871690633ee7a5ce90611049908a90600401614b1a565b602060405180830381600087803b15801561106357600080fd5b505af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b9190614543565b508692506110a7612e67565b935061113d565b604051631f73d2e760e11b81526001600160a01b03871690633ee7a5ce906110da908890600401614b1a565b602060405180830381600087803b1580156110f457600080fd5b505af1158015611108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112c9190614543565b5084925061113a878461338c565b93505b600061114885612b3a565b111561115e5761115888856133a9565b90925090505b876001600160a01b03167f61ccdbfcc4d71fe0e0db8f266c52487a8203332dc6fde7623f262f5a052b7ccd61119289612b3a565b61119b86612b3a565b6111a486612b3a565b6111ad86612b3a565b6040516111bd9493929190614b62565b60405180910390a25050505050505050565b6001600160a01b031660009081526067602052604090206002015490606490565b6001600160a01b031660009081526067602090815260408083208380528083528184206003908101546001865291909352922001549091565b60676020908152600091825260409182902082519182019092526001820154815260029091015482565b6065546001600160a01b031681565b61126a6142c8565b506001600160a01b03166000908152606760209081526040918290208251918201909252600190910154815290565b6112a1612f6e565b6033546001600160a01b039081169116146112ce5760405162461bcd60e51b8152600401610bdf90614924565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6113206113e6565b6001600160a01b0316611331612f6e565b6001600160a01b0316148061135e5750826001600160a01b0316611353612f6e565b6001600160a01b0316145b61137a5760405162461bcd60e51b8152600401610bdf906146fe565b60008111801561138b575060648111155b6113a75760405162461bcd60e51b8152600401610bdf906149a0565b6001600160a01b038316600090815260676020526040812082918460018111156113cd57fe5b8152602081019190915260400160002060030155505050565b6033546001600160a01b031690565b60006113ff612f6e565b6065546040516357de0c5b60e01b81529192506001600160a01b0316906357de0c5b906114309084906004016145bd565b60206040518083038186803b15801561144857600080fd5b505afa15801561145c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114809190614492565b61149c5760405162461bcd60e51b8152600401610bdf9061468c565b6114a46142c8565b6114ac6142c8565b6114b583613561565b6001600160a01b03851660009081526067602090815260408083208380529182905280832060018452922093955091935090916114f06142c8565b5060408051602081019091526001840154815261150b6142c8565b61152861151888886135d3565b611522848a6135f0565b9061360d565b90506115326142c8565b61153c838361338c565b6040805160208101909152865481529091506115589083612b62565b5185556040805160208101909152845481526115749082612b62565b51845561157f612e67565b51600187015561158e8961362a565b886001600160a01b03167f53b51cf5a1ebe438d76007c88a77b178f23d7ac34918998a2140fac3e15ca5b46115c284612b3a565b6115cb84612b3a565b6040516115d992919061464b565b60405180910390a2505050505050505050565b6066546001600160a01b031681565b6116036142c8565b6001600160a01b03831660009081526067602052604081209083600181111561162857fe5b8152602080820192909252604090810160002081519283019091525481529392505050565b6116556142c8565b61165d6142c8565b6116656142c8565b61166d6142c8565b61167685613561565b915091506116826142c8565b61168b866118ed565b905061169681612b3a565b6116b6576116a2612e67565b6116aa612e67565b94509450505050610ba0565b6116be6142c8565b6116d56116cb85856135d3565b6106e68487612ee6565b90506116df6142c8565b6116e98383613ae8565b90506116f36142c8565b6116fb6142c8565b6117048a611a15565b915091506117106142c8565b61171a8386612bd1565b90506117246142c8565b61172e8386612bd1565b905061173982613b05565b1561175d5761174a84600019613b23565b95506117568787613ae8565b9450611786565b61176681613b05565b156117865761177783600019613b23565b94506117838786613ae8565b95505b50939850919650505050505050915091565b6117a06142c8565b6117a86142c8565b6117b06142c8565b6117b86142c8565b6117c186612935565b915091506117cd6142c8565b6117d56142c8565b6117de8861164d565b915091508660018111156117ee57fe5b611800575091935090915061180e9050565b91945090925061180e915050565b9250929050565b61181d6142c8565b6118256142c8565b506001600160a01b0383166000908152606760209081526040918290208251918201909252600190910154815261185a6142c8565b6118626142c8565b61186b86613561565b909250905061187d61069e83836135d3565b61189357611889612e67565b9350505050610df8565b61189b6142c8565b6118b26118a884846135d3565b61152286866135f0565b90506118bc6142c8565b6118c6858361338c565b90508660018111156118d457fe5b156118df57806118e1565b815b98975050505050505050565b6118f56142c8565b6118fd6142c8565b6119056142c8565b836001600160a01b03166359bf5d396040518163ffffffff1660e01b8152600401604080518083038186803b15801561193d57600080fd5b505afa158015611951573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611975919061455e565b6040516320855f0560e01b815291935091506001600160a01b038516906320855f05906119a89084908690600401614b24565b60206040518083038186803b1580156119c057600080fd5b505afa1580156119d4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2e919061434f565b606860209081526000928352604080842090915290825290205481565b611a1d6142c8565b611a256142c8565b611a2d6142db565b506001600160a01b0383166000908152606760209081526040808320838052825291829020825160808101845281546060820190815281528351808401855260018301548152928101929092526003015491810191909152611a8d6142db565b6001600160a01b0385166000908152606760205260408120906001815260208082019290925260409081016000208151608081018352815460608201908152815282518085018452600183015481529381019390935260030154908201529050611af56142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b158015611b3957600080fd5b505afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7191906144b2565b6001600160a01b03166351f59d0c60006040518263ffffffff1660e01b8152600401611b9d919061460e565b60206040518083038186803b158015611bb557600080fd5b505afa158015611bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bed91906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c2557600080fd5b505afa158015611c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5d9190614589565b90529050611c696142c8565b6040518060200160405280886001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b158015611cad57600080fd5b505afa158015611cc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce591906144b2565b6001600160a01b03166351f59d0c60016040518263ffffffff1660e01b8152600401611d11919061460e565b60206040518083038186803b158015611d2957600080fd5b505afa158015611d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6191906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9957600080fd5b505afa158015611dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd19190614589565b90529050611ddd6142c8565b611df283611dec8a60006121ec565b906135f0565b9050611dfc6142c8565b611e0b83611dec8b60016121ec565b9050611e156142c8565b8651611e219084613b3f565b9050611e2b6142c8565b8651611e379084613b3f565b91995090975050505050505050915091565b611e54836001612c62565b611e5d81612df3565b611e678383612e1b565b6001600160a01b038316600090815260676020526040812081846001811115611e8c57fe5b81526020019081526020016000209050611ea46142c8565b611eae8585610db2565b9050611eb86142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b158015611efc57600080fd5b505afa158015611f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3491906144b2565b6001600160a01b03166351f59d0c886040518263ffffffff1660e01b8152600401611f5f919061460e565b60206040518083038186803b158015611f7757600080fd5b505afa158015611f8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611faf91906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611fe757600080fd5b505afa158015611ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201f9190614589565b9052905061202b6142c8565b6120e86120c5606560009054906101000a90046001600160a01b03166001600160a01b031663294585296040518163ffffffff1660e01b815260040160206040518083038186803b15801561207f57600080fd5b505afa158015612093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b79190614543565b6120bf612b3e565b9061338c565b6040805160208101909152865481526109519085906106e6908a9084908a612bd1565b6040805160208101909152855481529091506121049082613ae8565b51845561212187612113612f6e565b61211c84613ba4565b612fdc565b866001600160a01b0316638eb86e8b87612139612f6e565b61214289612b3a565b6040518463ffffffff1660e01b815260040161216093929190614621565b600060405180830381600087803b15801561217a57600080fd5b505af115801561218e573d6000803e3d6000fd5b5050505061219a612f6e565b6001600160a01b0316876001600160a01b03167f0a1c25ae924704549adf45406b392212e731505f6eb60f707265434cbc5f22658860018111156121da57fe5b6121e385612fca565b610ade8a612b3a565b6121f46142c8565b6121fc6142c8565b6001600160a01b03841660009081526068602052604081209084600181111561222157fe5b815260208082019290925260409081016000208151928301909152548152905061224a81612b3a565b6122b0576001600160a01b03841660009081526067602052604081208185600181111561227357fe5b81526020019081526020016000206003015490506122a760646122a18360640361229b612b3e565b90613bd2565b90613bee565b92505050610df8565b9392505050565b6122bf6142c8565b6122c76142db565b506001600160a01b03821660009081526067602090815260408083208380528252918290208251608081018452815460608201908152815283518084018552600183015481529281019290925260030154918101919091526123276142db565b506001600160a01b03831660009081526067602090815260408083206001808552908352928190208151608081018352815460608201908152815282518085018452948201548552928301939093526003909201549181019190915280518251610b2e91612bd1565b612398612f6e565b6033546001600160a01b039081169116146123c55760405162461bcd60e51b8152600401610bdf90614924565b6001600160a01b0381166123eb5760405162461bcd60e51b8152600401610bdf9061479e565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b612418826000612c62565b6001600160a01b03821660009081526067602052604081208183600181111561243d57fe5b815260200190815260200160002090506124556142c8565b61245f8484610db2565b90506124696142c8565b6040805160208101909152835481526124829083612bd1565b9050600061248f82612b3a565b13156128b45761249d6142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b1580156124e157600080fd5b505afa1580156124f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251991906144b2565b6001600160a01b03166351f59d0c886040518263ffffffff1660e01b8152600401612544919061460e565b60206040518083038186803b15801561255c57600080fd5b505afa158015612570573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259491906144b2565b6001600160a01b03166370a082316125aa612f6e565b6040518263ffffffff1660e01b81526004016125c691906145bd565b60206040518083038186803b1580156125de57600080fd5b505afa1580156125f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126169190614589565b905290506126226142c8565b6040518060200160405280886001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b15801561266657600080fd5b505afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e91906144b2565b6001600160a01b03166351f59d0c896040518263ffffffff1660e01b81526004016126c9919061460e565b60206040518083038186803b1580156126e157600080fd5b505afa1580156126f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271991906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561275157600080fd5b505afa158015612765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127899190614589565b905290506127956142c8565b6127a3826106e68686612ee6565b6040805160208101909152875481529091506127bf9082613ae8565b5186556001600160a01b038816638eb86e8b886127da612f6e565b6127e387612b3a565b6040518463ffffffff1660e01b815260040161280193929190614621565b600060405180830381600087803b15801561281b57600080fd5b505af115801561282f573d6000803e3d6000fd5b5050505061283f88612113612f6e565b612847612f6e565b6001600160a01b0316886001600160a01b03167f0a1c25ae924704549adf45406b392212e731505f6eb60f707265434cbc5f226589600181111561288757fe5b61289085612fca565b61289988612b3a565b6040516128a893929190614b4c565b60405180910390a35050505b5050505050565b6066546001600160a01b03166128cf612f6e565b6001600160a01b0316146128f55760405162461bcd60e51b8152600401610bdf90614a07565b6001600160a01b03821660009081526067602090815260409182902082519182019092526001820154815261292a90836135d3565b516001909101555050565b61293d6142c8565b6129456142c8565b61294d6142db565b506001600160a01b03831660009081526067602090815260408083208380528252918290208251608081018452815460608201908152815283518084018552600183015481529281019290925260030154918101919091526129ad6142db565b506001600160a01b0393909316600090815260676020908152604080832060018085529083529281902081516080810183528154606082019081528152825180850184529482015485529283019390935260039092015491810191909152925192519293915050565b612a1e6142c8565b612a27826118ed565b9050612a316142c8565b612a396142c8565b612a4284612935565b90925090506000612a6061069e83612a5a8787612bd1565b90612bd1565b13612a7d5760405162461bcd60e51b8152600401610bdf9061480b565b50505050565b612a8b612f6e565b6033546001600160a01b03908116911614612ab85760405162461bcd60e51b8152600401610bdf90614924565b6001600160a01b038116612ade5760405162461bcd60e51b8152600401610bdf906146b8565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5190565b612b466142c8565b6040518060200160405280612b5b6012613c0a565b9052905090565b612b6a6142c8565b8180600001516001600160ff1b031015604051806060016040528060338152602001614bf06033913990612bb15760405162461bcd60e51b8152600401610bdf9190614659565b50612bba6142c8565b83518551612bc791613c13565b8152949350505050565b612bd96142c8565b612be16142c8565b82518451612bee91613c13565b81529392505050565b612bff6142c8565b8180600001516001600160ff1b031015604051806060016040528060338152602001614bf06033913990612c465760405162461bcd60e51b8152600401610bdf9190614659565b50612c4f6142c8565b610df3612c5b85612e82565b8690612f51565b6065546040516357de0c5b60e01b81526001600160a01b03909116906357de0c5b90612c929085906004016145bd565b60206040518083038186803b158015612caa57600080fd5b505afa158015612cbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce29190614492565b612cfe5760405162461bcd60e51b8152600401610bdf9061468c565b816001600160a01b031663fcfff16f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3757600080fd5b505afa158015612d4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6f9190614492565b15158115151481612da8576040518060400160405280601081526020016f32bc31b430b733b29034b99037b832b760811b815250612dd5565b60405180604001604052806013815260200172195e18da185b99d9481dd85cc818db1bdcd959606a1b8152505b90610bf35760405162461bcd60e51b8152600401610bdf9190614659565b612dfc81612b3a565b612e185760405162461bcd60e51b8152600401610bdf90614900565b50565b612e236142c8565b612e2b6142c8565b612e358484611798565b90925090506000612e4961069e8385612bd1565b1215612a7d5760405162461bcd60e51b8152600401610bdf9061480b565b612e6f6142c8565b5060408051602081019091526000815290565b612e8a6142c8565b8180600001516001600160ff1b031015604051806060016040528060338152602001614bf06033913990612ed15760405162461bcd60e51b8152600401610bdf9190614659565b50506040805160208101909152915182525090565b612eee6142c8565b8180600001516001600160ff1b031015604051806060016040528060338152602001614bf06033913990612f355760405162461bcd60e51b8152600401610bdf9190614659565b50612f3e6142c8565b610df3612f4a85612e82565b8690613c59565b612f596142c8565b612f616142c8565b82518451612bee91613c76565b3390565b612a7d846323b872dd60e01b858585604051602401612f93939291906145d1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613c84565b6000612fd582613ba4565b5192915050565b6000836001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561301757600080fd5b505afa15801561302b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304f91906144b2565b90506130596142c8565b6040805160208101918290526370a0823160e01b909152806001600160a01b0384166370a0823161308d30602485016145bd565b60206040518083038186803b1580156130a557600080fd5b505afa1580156130b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130dd9190614589565b905290506130ea83612b3a565b6130f382612b3a565b10156132d6576131016142c8565b61310b848361338c565b606554604051633f694ac560e11b81529192506000916001600160a01b0390911690637ed2958a90613141908a906004016145bd565b60206040518083038186803b15801561315957600080fd5b505afa15801561316d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319191906144b2565b905061319b6142c8565b6040805160208101918290526370a0823160e01b909152806001600160a01b0387166370a082316131cf86602485016145bd565b60206040518083038186803b1580156131e757600080fd5b505afa1580156131fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321f9190614589565b9052905061322c83612b3a565b61323582612b3a565b10156132535760405162461bcd60e51b8152600401610bdf90614abc565b604051631f73d2e760e11b81526001600160a01b03831690633ee7a5ce9061327f908690600401614b1a565b602060405180830381600087803b15801561329957600080fd5b505af11580156132ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d19190614543565b505050505b6128b4846132e385612b3a565b6001600160a01b0385169190613d13565b303b1590565b600054610100900460ff168061331357506133136132f4565b80613321575060005460ff16155b61333d5760405162461bcd60e51b8152600401610bdf90614830565b600054610100900460ff16158015613368576000805460ff1961ff0019909116610100171660011790555b613370613d32565b613378613db3565b8015612e18576000805461ff001916905550565b6133946142c8565b61339c6142c8565b82518451612bee91613e8d565b6133b16142c8565b6133b96142c8565b6133c16142c8565b6133c9612e67565b90506133d36142c8565b6133db612e67565b90506133e56142c8565b6133ed6142c8565b6133f688610b38565b9092509050600061341461069e8961340e8686612bd1565b90613b3f565b12156134325760405162461bcd60e51b8152600401610bdf9061480b565b61343a6142c8565b6134426142c8565b61344b8a613561565b909250905061346761345d83836135d3565b6115228b856135f0565b9550613473898761338c565b945061347d6142c8565b6134878588613b3f565b90506134916142c8565b61349b8588613b3f565b90506134a682613b05565b156134c7576134b486613ba4565b97506134c08b8961338c565b96506134ed565b6134d081613b05565b156134ed576134de85613ba4565b96506134ea8b8861338c565b97505b6001600160a01b038c166000908152606760209081526040808320838052825280832060018452928190208151928301909152825482529061352f908b613b3f565b51825560408051602081019091528154815261354b908a613b3f565b51905550969b959a509498505050505050505050565b6135696142c8565b6135716142c8565b613579614308565b5050506001600160a01b031660009081526067602090815260409182902082516060810184526001820154818501908152815260029091015490820190815282518083018452905181528251918201909252606481529091565b6135db6142c8565b6135e36142c8565b82518451612bee91613ecf565b6135f86142c8565b6136006142c8565b82518451612bee91613ef4565b6136156142c8565b61361d6142c8565b82518451612bee91613f02565b6136326142c8565b61363a6142c8565b61364383612935565b9150915061364f6142c8565b6136576142c8565b6136608561164d565b9150915061366c6142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b1580156136b057600080fd5b505afa1580156136c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e891906144b2565b6001600160a01b03166351f59d0c60006040518263ffffffff1660e01b8152600401613714919061460e565b60206040518083038186803b15801561372c57600080fd5b505afa158015613740573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376491906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561379c57600080fd5b505afa1580156137b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d49190614589565b9052905060006137e382612b3a565b11156138a3576137f16142c8565b613807613802836106e68988612bd1565b613ba4565b6001600160a01b03881660009081526067602090815260408083208380529091529020600301549091506138396142c8565b61384a60646122a185858303613bd2565b90506138546142c8565b61385f8a60006121ec565b9050600061386d8383613f10565b60000b131561389e576001600160a01b038a1660009081526068602090815260408083208380529091529020825190555b505050505b506138ac6142c8565b6040518060200160405280876001600160a01b0316630dd271206040518163ffffffff1660e01b815260040160206040518083038186803b1580156138f057600080fd5b505afa158015613904573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392891906144b2565b6001600160a01b03166351f59d0c60016040518263ffffffff1660e01b8152600401613954919061460e565b60206040518083038186803b15801561396c57600080fd5b505afa158015613980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a491906144b2565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156139dc57600080fd5b505afa1580156139f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a149190614589565b905290506000613a2382612b3a565b1115613ae057613a316142c8565b613a42613802836106e68887612bd1565b6001600160a01b038816600090815260676020908152604080832060018452909152902060030154909150613a756142c8565b613a8660646122a185858303613bd2565b9050613a906142c8565b613a9b8a60016121ec565b90506000613aa98383613f10565b60000b1315613adb576001600160a01b038a166000908152606860209081526040808320600184529091529020825190555b505050505b505050505050565b613af06142c8565b613af86142c8565b82518451612bee91613f41565b60008082600001511215613b1b57506001610b33565b506000919050565b613b2b6142c8565b613b336142c8565b8351612bee9084613f87565b613b476142c8565b8180600001516001600160ff1b031015604051806060016040528060338152602001614bf06033913990613b8e5760405162461bcd60e51b8152600401610bdf9190614659565b50613b976142c8565b83518551612bc791613f41565b613bac6142c8565b613bb46142c8565b825160001315613bca5782516000038152610df8565b915182525090565b613bda6142c8565b613be26142c8565b8351612bee9084613ff2565b613bf66142c8565b613bfe6142c8565b8351612bee908461402c565b60ff16600a0a90565b6000828201818312801590613c285750838112155b80613c3d5750600083128015613c3d57508381125b6122b05760405162461bcd60e51b8152600401610bdf9061475d565b613c616142c8565b613c696142c8565b82518451612bee9161406e565b60006122b08383601261407c565b6060613cd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166140a39092919063ffffffff16565b805190915015610bf35780806020019051810190613cf79190614492565b610bf35760405162461bcd60e51b8152600401610bdf90614a72565b610bf38363a9059cbb60e01b8484604051602401612f939291906145f5565b600054610100900460ff1680613d4b5750613d4b6132f4565b80613d59575060005460ff16155b613d755760405162461bcd60e51b8152600401610bdf90614830565b600054610100900460ff16158015613378576000805460ff1961ff0019909116610100171660011790558015612e18576000805461ff001916905550565b600054610100900460ff1680613dcc5750613dcc6132f4565b80613dda575060005460ff16155b613df65760405162461bcd60e51b8152600401610bdf90614830565b600054610100900460ff16158015613e21576000805460ff1961ff0019909116610100171660011790555b6000613e2b612f6e565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015612e18576000805461ff001916905550565b60006122b083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506140b2565b6000828201838110156122b05760405162461bcd60e51b8152600401610bdf90614726565b60006122b0838360126140de565b60006122b0838360126140fc565b805182516000911015613f2557506001610df8565b815183511015613f385750600019610df8565b50600092915050565b6000818303818312801590613f565750838113155b80613f6b5750600083128015613f6b57508381135b6122b05760405162461bcd60e51b8152600401610bdf90614a2e565b600082613f9657506000610df8565b82600019148015613faa5750600160ff1b82145b15613fc75760405162461bcd60e51b8152600401610bdf90614959565b82820282848281613fd457fe5b05146122b05760405162461bcd60e51b8152600401610bdf90614959565b60008261400157506000610df8565b8282028284828161400e57fe5b04146122b05760405162461bcd60e51b8152600401610bdf906148bf565b60006122b083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614115565b60006122b08383601261414c565b600061409b8361409561408e85613c0a565b8790613f87565b90614164565b949350505050565b606061409b84846000856141c8565b600081848411156140d65760405162461bcd60e51b8152600401610bdf9190614659565b505050900390565b600061409b6140ec83613c0a565b6140f68686613ff2565b9061402c565b600061409b836140f661410e85613c0a565b8790613ff2565b600081836141365760405162461bcd60e51b8152600401610bdf9190614659565b50600083858161414257fe5b0495945050505050565b600061409b61415a83613c0a565b6140958686613f87565b6000816141835760405162461bcd60e51b8152600401610bdf90614ae5565b816000191480156141975750600160ff1b83145b156141b45760405162461bcd60e51b8152600401610bdf9061487e565b60008284816141bf57fe5b05949350505050565b6060824710156141ea5760405162461bcd60e51b8152600401610bdf906147c5565b6141f385614289565b61420f5760405162461bcd60e51b8152600401610bdf906149d0565b60006060866001600160a01b0316858760405161422c91906145a1565b60006040518083038185875af1925050503d8060008114614269576040519150601f19603f3d011682016040523d82523d6000602084013e61426e565b606091505b509150915061427e82828661428f565b979650505050505050565b3b151590565b6060831561429e5750816122b0565b8251156142ae5782518084602001fd5b8160405162461bcd60e51b8152600401610bdf9190614659565b6040518060200160405280600081525090565b60405180606001604052806142ee6142c8565b81526020016142fb6142c8565b8152602001600081525090565b60405180604001604052806142fb6142c8565b803560028110610df857600080fd5b60006020828403121561433b578081fd5b6143456020614b7d565b9135825250919050565b600060208284031215614360578081fd5b61436a6020614b7d565b9151825250919050565b600060208284031215614385578081fd5b81356122b081614bda565b600080604083850312156143a2578081fd5b82356143ad81614bda565b915060208301356143bd81614bda565b809150509250929050565b600080604083850312156143da578182fd5b82356143e581614bda565b91506143f4846020850161431b565b90509250929050565b600080600060608486031215614411578081fd5b833561441c81614bda565b925061442b856020860161431b565b9150604084013590509250925092565b6000806040838503121561444d578182fd5b823561445881614bda565b91506143f4846020850161432a565b60008060408385031215614479578182fd5b823561448481614bda565b946020939093013593505050565b6000602082840312156144a3578081fd5b815180151581146122b0578182fd5b6000602082840312156144c3578081fd5b81516122b081614bda565b6000806000606084860312156144e2578283fd5b83356144ed81614bda565b925060208401356144fd81614bda565b915061450c856040860161432a565b90509250925092565b600080600060608486031215614529578081fd5b833561453481614bda565b92506144fd856020860161431b565b600060208284031215614554578081fd5b6122b0838361434f565b60008060408385031215614570578182fd5b61457a848461434f565b91506143f4846020850161434f565b60006020828403121561459a578081fd5b5051919050565b600082516145b3818460208701614ba4565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6020810161461b83614bd0565b91905290565b6060810161462e85614bd0565b9381526001600160a01b0392909216602083015260409091015290565b918252602082015260400190565b6000602082528251806020840152614678816040850160208701614ba4565b601f01601f19169190910160400192915050565b602080825260129082015271195e18da185b99d9481b9bdd08199bdd5b9960721b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252600e908201526d34b73b30b634b21031b0b63632b960911b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600d908201526c656d707479206164647265737360981b604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600b908201526a13534810985b9adc9d5c1d60aa1b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600a90820152690696e70757420697320360b41b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b602080825260169082015275696e76616c6964206d6178206c6f73732076616c756560501b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600d908201526c06f6e6c792073616b655065727609c1b604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600f908201526e08ceadcc840dcdee840cadcdeeaced608b1b604082015260600190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b9051815260200190565b9151825251602082015260400190565b91518252602082015260400190565b90815260200190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715614b9c57600080fd5b604052919050565b60005b83811015614bbf578181015183820152602001614ba7565b83811115612a7d5750506000910152565b60028110612e1857fe5b6001600160a01b0381168114612e1857600080fdfe4d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a26469706673582212202dbc13f0608770627e23b2e6f3d9822f0967ef73472308d52e3f82448804014d64736f6c634300060c0033

Deployed ByteCode Sourcemap

65669:29340:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87328:1048;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;77136:1608;;;;;;:::i;:::-;;:::i;:::-;;91317:349;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;90313:618::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;70365:212::-;;;;;;:::i;:::-;;:::i;68599:158::-;;;;;;:::i;:::-;;:::i;68258:209::-;;;;;;:::i;:::-;;:::i;69299:254::-;;;;;;:::i;:::-;;:::i;86267:345::-;;;;;;:::i;:::-;;:::i;73567:1573::-;;;;;;:::i;:::-;;:::i;93123:165::-;;;;;;:::i;:::-;;:::i;92851:264::-;;;;;;:::i;:::-;;:::i;67382:52::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;67284:37::-;;;:::i;:::-;;;;;;;:::i;92372:173::-;;;;;;:::i;:::-;;:::i;24859:148::-;;;:::i;69748:360::-;;;;;;:::i;:::-;;:::i;24217:79::-;;;:::i;75227:1155::-;;;:::i;67328:23::-;;;:::i;88384:251::-;;;;;;:::i;:::-;;:::i;84585:1674::-;;;;;;:::i;:::-;;:::i;86620:700::-;;;;;;:::i;:::-;;:::i;91674:690::-;;;;;;:::i;:::-;;:::i;84202:375::-;;;;;;:::i;:::-;;:::i;67485:78::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;89093:1212::-;;;;;;:::i;:::-;;:::i;78970:1328::-;;;;;;:::i;:::-;;:::i;93296:449::-;;;;;;:::i;:::-;;:::i;90939:370::-;;;;;;:::i;:::-;;:::i;68901:205::-;;;;;;:::i;:::-;;:::i;80459:1406::-;;;;;;:::i;:::-;;:::i;76591:325::-;;;;;;:::i;:::-;;:::i;88643:442::-;;;;;;:::i;:::-;;:::i;93795:447::-;;;;;;:::i;:::-;;:::i;25162:244::-;;;;;;:::i;:::-;;:::i;87328:1048::-;87434:17;87453:24;87496:46;;:::i;:::-;87544:50;;:::i;:::-;87611:57;87650:9;87662:5;87611:30;:57::i;:::-;87495:173;;;;87681:41;;:::i;:::-;87738:74;;;;;;;;87754:9;-1:-1:-1;;;;;87754:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;87754:36:0;;87791:5;87754:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;87754:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87738:74;;87681:131;-1:-1:-1;87827:27:0;87681:131;87827:25;:27::i;:::-;87823:546;;87903:22;:13;:11;:13::i;:::-;:20;:22::i;:::-;87876:50;;87961:22;:13;:11;:13::i;:22::-;87941:43;;87823:546;;;88017:53;;:::i;:::-;88090:65;88107:47;88136:9;88148:5;88107:20;:47::i;:::-;88090:11;;:16;:65::i;:::-;88017:138;-1:-1:-1;88190:73:0;:65;88236:18;88190:40;:15;88017:138;88190:20;:40::i;:::-;:45;;:65::i;:73::-;88170:93;-1:-1:-1;88291:66:0;:58;88330:18;88291:33;:15;88312:11;88291:20;:33::i;:66::-;88278:79;;87823:546;;87328:1048;;;;;;;;:::o;77136:1608::-;77287:32;77303:9;77314:4;77287:15;:32::i;:::-;77330:38;77350:17;77330:19;:38::i;:::-;-1:-1:-1;;;;;77409:32:0;;77381:25;77409:32;;;:12;:32;;;;;77381:25;77459:5;77451:14;;;;;;;;77409:57;;;;;;;;;;;77381:85;;77477:50;;:::i;:::-;77530:45;77557:9;77569:5;77530:18;:45::i;:::-;77477:98;;77588:41;;:::i;:::-;77645:74;;;;;;;;77661:9;-1:-1:-1;;;;;77661:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;77661:36:0;;77698:5;77661:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;77661:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77645:74;;77588:131;-1:-1:-1;77764:1:0;77734:27;77588:131;77734:25;:27::i;:::-;:31;77730:112;;;77782:48;77812:9;77824:5;77782:21;:48::i;:::-;77854:49;;:::i;:::-;77906:20;:18;:20::i;:::-;77854:72;;77941:27;:18;:25;:27::i;:::-;77937:327;;78007:43;78032:17;78007:24;:43::i;:::-;77990:60;;77937:327;;;78192:28;;;;;;;;;;;;;78100:152;;78192:45;;78221:15;78192:28;:45::i;:::-;78100:68;78149:18;78100:43;78125:17;78100:24;:43::i;:::-;:48;;:68::i;:::-;:73;;:152::i;:::-;78083:169;;77937:327;78302:28;;;;;;;;;;;;;:47;;78331:17;78302:28;:47::i;:::-;78276:73;;;78360:96;78400:12;:10;:12::i;:::-;78422:4;78429:26;:17;:24;:26::i;:::-;78360:9;-1:-1:-1;;;;;78360:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;78360:39:0;;:96;;:39;:96::i;:::-;78467:9;-1:-1:-1;;;;;78467:14:0;;78482:5;78489:12;:10;:12::i;:::-;78503:23;:14;:21;:23::i;:::-;78467:60;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78605:12;:10;:12::i;:::-;-1:-1:-1;;;;;78545:191:0;78580:9;-1:-1:-1;;;;;78545:191:0;;78640:5;78632:14;;;;;;;;78661:26;:17;:24;:26::i;:::-;78702:23;:14;:21;:23::i;:::-;78545:191;;;;;;;;:::i;:::-;;;;;;;;77136:1608;;;;;;;:::o;91317:349::-;91440:34;;:::i;:::-;91493:39;;:::i;:::-;91534:38;;:::i;:::-;91589:37;91616:9;91589:26;:37::i;:::-;91492:134;;-1:-1:-1;91492:134:0;-1:-1:-1;91644:14:0;91492:134;;91644:9;:14::i;:::-;91637:21;;;;91317:349;;;;:::o;90313:618::-;90423:34;;:::i;:::-;90459;;:::i;:::-;90512:48;;:::i;:::-;90562:47;;:::i;:::-;90626:37;90653:9;90626:26;:37::i;:::-;90511:152;;;;90675:52;;:::i;:::-;90729:51;;:::i;:::-;90797:32;90819:9;90797:21;:32::i;:::-;90674:155;;-1:-1:-1;90674:155:0;-1:-1:-1;90848:37:0;:13;90674:155;90848:18;:37::i;:::-;90887:35;:12;90905:16;90887:17;:35::i;:::-;90840:83;;;;;;;;90313:618;;;;:::o;70365:212::-;68173:8;;-1:-1:-1;;;;;68173:8:0;68157:12;:10;:12::i;:::-;-1:-1:-1;;;;;68157:24:0;;68149:50;;;;-1:-1:-1;;;68149:50:0;;;;;;;:::i;:::-;;;;;;;;;70529:40:::1;70539:9;70550;70561:7;70529:9;:40::i;:::-;70365:212:::0;;;:::o;68599: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;;;;;68677:23:0;::::1;68669:49;;;;-1:-1:-1::0;;;68669:49:0::1;;;;;;;:::i;:::-;68729:8;:20:::0;;-1:-1:-1;;;;;;68729:20:0::1;-1:-1:-1::0;;;;;68729:20:0;;;::::1;::::0;;;::::1;::::0;;68599:158::o;68258:209::-;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;68352:8:::1;:20:::0;;-1:-1:-1;;;;;68352:20:0;;::::1;-1:-1:-1::0;;;;;;68352:20:0;;::::1;;::::0;;;68383:14:::1;:49:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;68443:16:::1;:14;:16::i;:::-;20925:14:::0;20921:68;;;20972:5;20956:21;;-1:-1:-1;;20956:21:0;;;68258:209;;;:::o;69299:254::-;69422:7;:5;:7::i;:::-;-1:-1:-1;;;;;69406:23:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;69406:23:0;;:52;;;;69449:9;-1:-1:-1;;;;;69433:25:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;69433:25:0;;69406:52;69398:79;;;;-1:-1:-1;;;69398:79:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;69488:23:0;;;;;;;:12;:23;;;;;:47;;:57;69299:254::o;86267:345::-;86374:34;;:::i;:::-;86427:39;;:::i;:::-;86468:38;;:::i;:::-;86523:32;86545:9;86523:21;:32::i;:::-;86426:129;;-1:-1:-1;86426:129:0;-1:-1:-1;86582:9:0;86573:5;:18;;;;;;;;;:31;;86601:3;86573:31;;;86594:4;86573:31;86566:38;;;;86267:345;;;;;:::o;73567:1573::-;68173:8;;-1:-1:-1;;;;;68173:8:0;68157:12;:10;:12::i;:::-;-1:-1:-1;;;;;68157:24:0;;68149:50;;;;-1:-1:-1;;;68149:50:0;;;;;;;:::i;:::-;73810:14:::1;::::0;:42:::1;::::0;-1:-1:-1;;;73810:42:0;;73779:28:::1;::::0;-1:-1:-1;;;;;73810:14:0::1;::::0;:31:::1;::::0;:42:::1;::::0;73842:9;;73810:42:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73779:73;;73863:41;;:::i;:::-;73920:73;;;;;;;;73936:9;-1:-1:-1::0;;;;;73936:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;73936:32:0::1;;73977:13;73936:56;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73920:73:::0;;73863:130;-1:-1:-1;74004:39:0::1;;:::i;:::-;74046:14;:12;:14::i;:::-;74004:56;;74071:50;;:::i;:::-;74124:14;:12;:14::i;:::-;74071:67;;74149:43;;:::i;:::-;74195:14;:12;:14::i;:::-;74149:60;;74220:42;;:::i;:::-;74265:14;:12;:14::i;:::-;74220:59;;74327:17;:8;:15;:17::i;:::-;74296:27;:18;:25;:27::i;:::-;:48;74292:419;;74361:32;::::0;-1:-1:-1;;;74361:32:0;;-1:-1:-1;;;;;74361:22:0;::::1;::::0;::::1;::::0;:32:::1;::::0;74384:8;;74361:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;74438:8;74408:38;;74480:14;:12;:14::i;:::-;74461:33;;74292:419;;;74527:42;::::0;-1:-1:-1;;;74527:42:0;;-1:-1:-1;;;;;74527:22:0;::::1;::::0;::::1;::::0;:42:::1;::::0;74550:18;;74527:42:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;74614:18:0;;-1:-1:-1;74666:33:0::1;:8:::0;74614:18;74666:13:::1;:33::i;:::-;74647:52;;74292:419;74755:1;74727:25;:16;:23;:25::i;:::-;:29;74723:163;;;74819:55;74845:9;74857:16;74819:17;:55::i;:::-;74773:101:::0;;-1:-1:-1;74773:101:0;-1:-1:-1;74723:163:0::1;74941:9;-1:-1:-1::0;;;;;74903:229:0::1;;74966:17;:8;:15;:17::i;:::-;74998:36;:27;:34;:36::i;:::-;75049:29;:20;:27;:29::i;:::-;75093:28;:19;:26;:28::i;:::-;74903:229;;;;;;;;;:::i;:::-;;;;;;;;68210:1;;;;;;73567:1573:::0;;:::o;93123:165::-;-1:-1:-1;;;;;93223:23:0;93186:7;93223:23;;;:12;:23;;;;;:47;;;;67274:3;;93123:165::o;92851:264::-;-1:-1:-1;;;;;92962:23:0;92911:7;92962:23;;;:12;:23;;;;;;;;:52;;;;;;;;;:60;;;;;93078:8;93037:51;;;;;;;;:59;;92962:60;;92851:264::o;67382:52::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;67284:37::-;;;-1:-1:-1;;;;;67284:37:0;;:::o;92372:173::-;92456:22;;:::i;:::-;-1:-1:-1;;;;;;92498:23:0;;;;;:12;:23;;;;;;;;;92491:46;;;;;;;;92498:39;;;;92491:46;;;;92372:173::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;69748:360::-;69898:7;:5;:7::i;:::-;-1:-1:-1;;;;;69882:23:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;69882:23:0;;:52;;;;69925:9;-1:-1:-1;;;;;69909:25:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;69909:25:0;;69882:52;69874:79;;;;-1:-1:-1;;;69874:79:0;;;;;;;:::i;:::-;69979:1;69972:4;:8;:27;;;;;67274:3;69984:4;:15;;69972:27;69964:62;;;;-1:-1:-1;;;69964:62:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;70037:23:0;;;;;;:12;:23;;;;;70096:4;;70078:5;70070:14;;;;;;;;70037:48;;;;;;;;;;;-1:-1:-1;70037:48:0;:56;;:63;-1:-1:-1;;;69748:360:0:o;24217:79::-;24282:6;;-1:-1:-1;;;;;24282:6:0;24217:79;:::o;75227:1155::-;75283:17;75303:12;:10;:12::i;:::-;75334:14;;:54;;-1:-1:-1;;;75334:54:0;;75283:32;;-1:-1:-1;;;;;;75334:14:0;;:32;;:54;;75283:32;;75334:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;75326:85;;;;-1:-1:-1;;;75326:85:0;;;;;;;:::i;:::-;75423:33;;:::i;:::-;75458:32;;:::i;:::-;75494:23;75507:9;75494:12;:23::i;:::-;-1:-1:-1;;;;;75565:23:0;;75528:34;75565:23;;;:12;:23;;;;;;;;75627:42;;;;;;;;;;75738:8;75707:41;;;;75422:95;;-1:-1:-1;75422:95:0;;-1:-1:-1;75565:23:0;;75759:38;;:::i;:::-;-1:-1:-1;75759:70:0;;;;;;;;;75800:29;;;75759:70;;;75840:36;;:::i;:::-;75879:65;75917:26;:10;75933:9;75917:15;:26::i;:::-;75879:32;:15;75900:10;75879:20;:32::i;:::-;:37;;:65::i;:::-;75840:104;;75955:35;;:::i;:::-;75993;:15;76014:13;75993:20;:35::i;:::-;76065:28;;;;;;;;;;;;;75955:73;;-1:-1:-1;76065:43:0;;76094:13;76065:28;:43::i;:::-;76039:69;;;76144:27;;;;;;;;;;;;;:41;;76172:12;76144:27;:41::i;:::-;76119:66;;;76228:14;:12;:14::i;:::-;76196:46;:29;;;:46;76253:32;76275:9;76253:21;:32::i;:::-;76317:9;-1:-1:-1;;;;;76301:73:0;;76328:22;:13;:20;:22::i;:::-;76352:21;:12;:19;:21::i;:::-;76301:73;;;;;;;:::i;:::-;;;;;;;;75227:1155;;;;;;;;;:::o;67328:23::-;;;-1:-1:-1;;;;;67328:23:0;;:::o;88384:251::-;88505:34;;:::i;:::-;-1:-1:-1;;;;;88564:23:0;;;;;;:12;:23;;;;;;88605:5;88597:14;;;;;;;;88564:48;;;;;;;;;;;;;;-1:-1:-1;88564:48:0;88557:70;;;;;;;;;;;;88384:251;-1:-1:-1;;;88384:251:0:o;84585:1674::-;84683:34;;:::i;:::-;84719;;:::i;:::-;84772:33;;:::i;:::-;84807:32;;:::i;:::-;84843:23;84856:9;84843:12;:23::i;:::-;84771:95;;;;84877:55;;:::i;:::-;84935:45;84969:9;84935:23;:45::i;:::-;84877:103;;84995:28;:20;:26;:28::i;:::-;84991:117;;85053:20;:18;:20::i;:::-;85075;:18;:20::i;:::-;85045:51;;;;;;;;;84991:117;85120:52;;:::i;:::-;85188:70;85231:26;:10;85247:9;85231:15;:26::i;:::-;85188:37;:20;85214:10;85188:25;:37::i;:70::-;85120:138;;85269:51;;:::i;:::-;85323:44;:20;85349:17;85323:25;:44::i;:::-;85269:98;;85396:48;;:::i;:::-;85446:47;;:::i;:::-;85514:37;85541:9;85514:26;:37::i;:::-;85395:156;;;;85566:53;;:::i;:::-;85622:37;:13;85641:17;85622:18;:37::i;:::-;85566:93;;85674:52;;:::i;:::-;85729:35;:12;85747:16;85729:17;:35::i;:::-;85674:90;;85783:31;:18;:29;:31::i;:::-;85779:405;;;85855:27;:13;-1:-1:-1;;85855:23:0;:27::i;:::-;85835:47;-1:-1:-1;85920:44:0;:20;85835:47;85920:25;:44::i;:::-;85901:63;;85779:405;;;85990:30;:17;:28;:30::i;:::-;85986:198;;;86060:26;:12;-1:-1:-1;;86060:22:0;:26::i;:::-;86041:45;-1:-1:-1;86125:43:0;:20;86041:45;86125:25;:43::i;:::-;86105:63;;85986:198;-1:-1:-1;86215:17:0;;-1:-1:-1;86234:16:0;;-1:-1:-1;;;;;;;84585:1674:0;;;:::o;86620:700::-;86739:34;;:::i;:::-;86775;;:::i;:::-;86828:48;;:::i;:::-;86878:47;;:::i;:::-;86942:28;86960:9;86942:17;:28::i;:::-;86827:143;;;;86982:52;;:::i;:::-;87036:51;;:::i;:::-;87104:32;87126:9;87104:21;:32::i;:::-;86981:155;;;;87166:5;87153:18;;;;;;;;87149:164;;-1:-1:-1;87196:13:0;;-1:-1:-1;87211:17:0;;-1:-1:-1;87188:41:0;;-1:-1:-1;87188:41:0;87149:164;87270:12;;-1:-1:-1;87284:16:0;;-1:-1:-1;87262:39:0;;-1:-1:-1;;87262:39:0;86620:700;;;;;;:::o;91674:690::-;91765:22;;:::i;:::-;91800:38;;:::i;:::-;-1:-1:-1;;;;;;91841:23:0;;;;;;:12;:23;;;;;;;;;91800:80;;;;;;;;91841:39;;;;91800:80;;;91892:33;;:::i;:::-;91927:32;;:::i;:::-;91963:23;91976:9;91963:12;:23::i;:::-;91891:95;;-1:-1:-1;91891:95:0;-1:-1:-1;92001:35:0;:26;91891:95;;92001:15;:26::i;:35::-;91997:94;;92065:14;:12;:14::i;:::-;92058:21;;;;;;;91997:94;92101:36;;:::i;:::-;92140:65;92178:26;:10;92194:9;92178:15;:26::i;:::-;92140:32;:15;92161:10;92140:20;:32::i;:65::-;92101:104;;92216:35;;:::i;:::-;92254;:15;92275:13;92254:20;:35::i;:::-;92216:73;;92320:5;92307:18;;;;;;;;;:49;;92344:12;92307:49;;;92328:13;92307:49;92300:56;91674:690;-1:-1:-1;;;;;;;;91674:690:0:o;84202:375::-;84322:34;;:::i;:::-;84375:41;;:::i;:::-;84418:40;;:::i;:::-;84462:9;-1:-1:-1;;;;;84462:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84502:67;;-1:-1:-1;;;84502:67:0;;84374:110;;-1:-1:-1;84374:110:0;-1:-1:-1;;;;;;84502:28:0;;;;;:67;;84374:110;;;;84502:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;67485:78::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;89093:1212::-;89196:34;;:::i;:::-;89232;;:::i;:::-;89284:24;;:::i;:::-;-1:-1:-1;;;;;;89311:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;89284:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89284:79:0;;;;;;;;;;;;;;89374:23;;:::i;:::-;-1:-1:-1;;;;;89400:23:0;;;;;;:12;:23;;;;;;89441:8;89400:51;;;;;;;;;;;;;;-1:-1:-1;89400:51:0;89374:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89462:45:0;;:::i;:::-;89523:89;;;;;;;;89549:9;-1:-1:-1;;;;;89539:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89539:47:0;;89587:9;89539:58;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89539:70:0;;:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89523:89;;89462:150;-1:-1:-1;89623:44:0;;:::i;:::-;89683:88;;;;;;;;89709:9;-1:-1:-1;;;;;89699:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89699:47:0;;89747:8;89699:57;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;89699:69:0;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89683:88;;89623:148;-1:-1:-1;89782:42:0;;:::i;:::-;89840:69;89886:22;89840:40;89859:9;89870;89840:18;:40::i;:::-;:45;;:69::i;:::-;89782:127;;89920:41;;:::i;:::-;89964:67;90009:21;89964:39;89983:9;89994:8;89964:18;:39::i;:67::-;89920:111;;90042:48;;:::i;:::-;90093:23;;:49;;90122:19;90093:28;:49::i;:::-;90042:100;;90153:47;;:::i;:::-;90203:22;;:47;;90231:18;90203:27;:47::i;:::-;90269:13;;-1:-1:-1;90153:97:0;;-1:-1:-1;;;;;;;;89093:1212:0;;;:::o;78970:1328::-;79121:32;79137:9;79148:4;79121:15;:32::i;:::-;79164:35;79184:14;79164:19;:35::i;:::-;79210:48;79240:9;79252:5;79210:21;:48::i;:::-;-1:-1:-1;;;;;79299:32:0;;79271:25;79299:32;;;:12;:32;;;;;79271:25;79349:5;79341:14;;;;;;;;79299:57;;;;;;;;;;;79271:85;;79367:50;;:::i;:::-;79420:45;79447:9;79459:5;79420:18;:45::i;:::-;79367:98;;79476:41;;:::i;:::-;79533:74;;;;;;;;79549:9;-1:-1:-1;;;;;79549:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79549:36:0;;79586:5;79549:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79549:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79533:74;;79476:131;-1:-1:-1;79618:47:0;;:::i;:::-;79681:185;79796:55;79815:14;;;;;;;;;-1:-1:-1;;;;;79815:14:0;-1:-1:-1;;;;;79815:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79796:13;:11;:13::i;:::-;:18;;:55::i;:::-;79681:28;;;;;;;;;;;;;:91;;79753:18;;79681:66;;79732:14;;79681:91;;79710:15;79681:28;:45::i;:185::-;79905:28;;;;;;;;;;;;;79618:248;;-1:-1:-1;79905:42:0;;79618:248;79905:28;:42::i;:::-;79879:68;;;79958:54;79968:9;79979:12;:10;:12::i;:::-;79993:18;:12;:16;:18::i;:::-;79958:9;:54::i;:::-;80023:9;-1:-1:-1;;;;;80023:14:0;;80038:5;80045:12;:10;:12::i;:::-;80059:23;:14;:21;:23::i;:::-;80023:60;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80164:12;:10;:12::i;:::-;-1:-1:-1;;;;;80101:189:0;80139:9;-1:-1:-1;;;;;80101:189:0;;80199:5;80191:14;;;;;;;;80220:21;:12;:19;:21::i;:::-;80256:23;:14;:21;:23::i;93296:449::-;93376:22;;:::i;:::-;93411:31;;:::i;:::-;-1:-1:-1;;;;;93445:26:0;;;;;;:15;:26;;;;;;93480:5;93472:14;;;;;;;;93445:42;;;;;;;;;;;;;;-1:-1:-1;93445:42:0;93411:76;;;;;;;;;;;;-1:-1:-1;93502:17:0;93411:76;93502:15;:17::i;:::-;93498:214;;-1:-1:-1;;;;;93560:23:0;;93541:16;93560:23;;;:12;:23;;;;;93541:16;93601:5;93593:14;;;;;;;;93560:48;;;;;;;;;;;:56;;;93541:75;;93638:62;67274:3;93638:43;93672:8;67274:3;93662:18;93638:13;:11;:13::i;:::-;:23;;:43::i;:::-;:53;;:62::i;:::-;93631:69;;;;;;93498:214;93729:8;93296:449;-1:-1:-1;;;93296:449:0:o;90939:370::-;91017:34;;:::i;:::-;91064:24;;:::i;:::-;-1:-1:-1;;;;;;91091:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;91064:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91064:79:0;;;;;;;;;;;;;;91154:23;;:::i;:::-;-1:-1:-1;;;;;;91180:23:0;;;;;;:12;:23;;;;;;;;91221:8;91180:51;;;;;;;;;;91154:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91154:77:0;;;;;;;;;;;;;;;;91278:22;;91249:23;;:52;;:28;:52::i;68901: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;;;;;68991:29:0;::::1;68983:55;;;;-1:-1:-1::0;;;68983:55:0::1;;;;;;;:::i;:::-;69049:14;:49:::0;;-1:-1:-1;;;;;;69049:49:0::1;-1:-1:-1::0;;;;;69049:49:0;;;::::1;::::0;;;::::1;::::0;;68901:205::o;80459:1406::-;80549:33;80565:9;80576:5;80549:15;:33::i;:::-;-1:-1:-1;;;;;80623:32:0;;80595:25;80623:32;;;:12;:32;;;;;80595:25;80673:5;80665:14;;;;;;;;80623:57;;;;;;;;;;;80595:85;;80691:50;;:::i;:::-;80744:45;80771:9;80783:5;80744:18;:45::i;:::-;80691:98;;80800:47;;:::i;:::-;80850:28;;;;;;;;;;;;;:45;;80879:15;80850:28;:45::i;:::-;80800:95;;80933:1;80910:20;:12;:18;:20::i;:::-;:24;80906:952;;;80951:37;;:::i;:::-;81008:84;;;;;;;;81024:9;-1:-1:-1;;;;;81024:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81024:36:0;;81061:5;81024:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81024:53:0;;81078:12;:10;:12::i;:::-;81024:67;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81008:84;;80951:141;-1:-1:-1;81107:41:0;;:::i;:::-;81168:74;;;;;;;;81184:9;-1:-1:-1;;;;;81184:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81184:36:0;;81221:5;81184:43;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;81184:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81168:74;;81107:135;-1:-1:-1;81257:47:0;;:::i;:::-;81324:58;81363:18;81324:33;:12;81342:14;81324:17;:33::i;:58::-;81425:28;;;;;;;;;;;;;81257:125;;-1:-1:-1;81425:42:0;;81257:125;81425:28;:42::i;:::-;81399:68;;;-1:-1:-1;;;;;81482:14:0;;;81497:5;81504:12;:10;:12::i;:::-;81518:23;:14;:21;:23::i;:::-;81482:60;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81557:54;81567:9;81578:12;:10;:12::i;81557:54::-;81704:12;:10;:12::i;:::-;-1:-1:-1;;;;;81633:213:0;81675:9;-1:-1:-1;;;;;81633:213:0;;81743:5;81735:14;;;;;;;;81768:21;:12;:19;:21::i;:::-;81808:23;:14;:21;:23::i;:::-;81633:213;;;;;;;;:::i;:::-;;;;;;;;80906:952;;;;80459:1406;;;;;:::o;76591:325::-;68173:8;;-1:-1:-1;;;;;68173:8:0;68157:12;:10;:12::i;:::-;-1:-1:-1;;;;;68157:24:0;;68149:50;;;;-1:-1:-1;;;68149:50:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;76789:23:0;::::1;76752:34;76789:23:::0;;;:12:::1;:23;::::0;;;;;;;;76855:34;;;;::::1;::::0;;;:29:::1;::::0;::::1;:34:::0;;;:53:::1;::::0;76890:17;76855:34:::1;:53::i;:::-;76823:85:::0;:29:::1;::::0;;::::1;:85:::0;-1:-1:-1;;76591:325:0:o;88643:442::-;88755:34;;:::i;:::-;88791;;:::i;:::-;88843:24;;:::i;:::-;-1:-1:-1;;;;;;88870:23:0;;;;;;:12;:23;;;;;;;;:52;;;;;;;;;88843:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;88843:79:0;;;;;;;;;;;;;;88933:23;;:::i;:::-;-1:-1:-1;;;;;;88959:23:0;;;;;;;;:12;:23;;;;;;;;89000:8;88959:51;;;;;;;;;;88933:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;88933:77:0;;;;;;;;;;;;;;;;89029:23;;89054:22;;89029:23;;88643:442;-1:-1:-1;;88643:442:0:o;93795:447::-;93871:55;;:::i;:::-;93929:45;93963:9;93929:23;:45::i;:::-;93871:103;;93986:48;;:::i;:::-;94036:47;;:::i;:::-;94100:28;94118:9;94100:17;:28::i;:::-;93985:143;;-1:-1:-1;93985:143:0;-1:-1:-1;94217:1:0;94147:67;:59;93985:143;94147:40;:20;93985:143;94147:25;:40::i;:::-;:45;;:59::i;:67::-;:71;94139:95;;;;-1:-1:-1;;;94139:95:0;;;;;;;:::i;:::-;93795:447;;;;:::o;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;63305:304::-;63457:34;;:::i;:::-;63436:1;62788;:3;;;-1:-1:-1;;;;;62773:18:0;;62793:21;;;;;;;;;;;;;;;;;62765:50;;;;;-1:-1:-1;;;62765:50:0;;;;;;;;:::i;:::-;;63509:36:::1;;:::i;:::-;63577:3:::0;;63562;;:20:::1;::::0;:7:::1;:20::i;:::-;63556:26:::0;;;63305:304;-1:-1:-1;;;;63305: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;64889:304::-;65041:34;;:::i;:::-;65020:1;62788;:3;;;-1:-1:-1;;;;;62773:18:0;;62793:21;;;;;;;;;;;;;;;;;62765:50;;;;;-1:-1:-1;;;62765:50:0;;;;;;;;:::i;:::-;;65093:36:::1;;:::i;:::-;65144:22;65151:14;65163:1;65151:11;:14::i;:::-;65144:1:::0;;:6:::1;:22::i;94745:261::-:0;94835:14;;:43;;-1:-1:-1;;;94835:43:0;;-1:-1:-1;;;;;94835:14:0;;;;:32;;:43;;94868:9;;94835:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94827:74;;;;-1:-1:-1;;;94827:74:0;;;;;;;:::i;:::-;94929:9;-1:-1:-1;;;;;94929:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94920:25;;:5;:25;;;94947:5;:50;;;;;;;;;;;;;;;-1:-1:-1;;;94947:50:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;94947:50:0;;;;94912:86;;;;;-1:-1:-1;;;94912:86:0;;;;;;;;:::i;94598:139::-;94692:17;:8;:15;:17::i;:::-;94684:45;;;;-1:-1:-1;;;94684:45:0;;;;;;;:::i;:::-;94598:139;:::o;94250:340::-;94338:46;;:::i;:::-;94386:50;;:::i;:::-;94453:48;94484:9;94495:5;94453:30;:48::i;:::-;94337:164;;-1:-1:-1;94337:164:0;-1:-1:-1;94565:1:0;94520:41;:33;94337:164;;94520:20;:33::i;:41::-;:46;;94512:70;;;;-1:-1:-1;;;94512:70:0;;;;;;;:::i;37124:103::-;37163:20;;:::i;:::-;-1:-1:-1;37203:16:0;;;;;;;;;-1:-1:-1;37203:16:0;;37124:103;:::o;62843:228::-;62964:34;;:::i;:::-;62943:1;62788;:3;;;-1:-1:-1;;;;;62773:18:0;;62793:21;;;;;;;;;;;;;;;;;62765:50;;;;;-1:-1:-1;;;62765:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;63023:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;63058:3;;63023:40;;-1:-1:-1;63023:40:0;62843:228::o;64102:304::-;64254:34;;:::i;:::-;64233:1;62788;:3;;;-1:-1:-1;;;;;62773:18:0;;62793:21;;;;;;;;;;;;;;;;;62765:50;;;;;-1:-1:-1;;;62765:50:0;;;;;;;;:::i;:::-;;64306:36:::1;;:::i;:::-;64357:22;64364:14;64376:1;64364:11;:14::i;:::-;64357:1:::0;;:6:::1;:22::i;38786:197::-:0;38871:20;;:::i;:::-;38904:22;;:::i;:::-;38952:3;;38943;;:13;;:8;:13::i;22523:106::-;22611:10;22523:106;:::o;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;63079:121::-;63156:7;63183;:1;:5;:7::i;:::-;:9;;63079:121;-1:-1:-1;;63079:121:0:o;70585:877::-;70730:24;70757:9;-1:-1:-1;;;;;70757:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70730:49;;70790:40;;:::i;:::-;70833:48;;;;;;;;;;-1:-1:-1;;;70849:31:0;;;70833:48;-1:-1:-1;;;;;70849:16:0;;;:31;70874:4;70849:31;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70833:48;;70790:91;-1:-1:-1;70925:16:0;:7;:14;:16::i;:::-;70896:26;:17;:24;:26::i;:::-;:45;70892:502;;;70958:38;;:::i;:::-;70999:31;:7;71012:17;70999:12;:31::i;:::-;71076:14;;:42;;-1:-1:-1;;;71076:42:0;;70958:72;;-1:-1:-1;71045:28:0;;-1:-1:-1;;;;;71076:14:0;;;;:31;;:42;;71108:9;;71076:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71045:73;;71133:39;;:::i;:::-;71175:57;;;;;;;;;;-1:-1:-1;;;71191:40:0;;;71175:57;-1:-1:-1;;;;;71191:16:0;;;:40;71216:13;71191:40;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71175:57;;71133:99;-1:-1:-1;71284:24:0;:15;:22;:24::i;:::-;71255:25;:16;:23;:25::i;:::-;:53;;71247:81;;;;-1:-1:-1;;;71247:81:0;;;;;;;:::i;:::-;71343:39;;-1:-1:-1;;;71343:39:0;;-1:-1:-1;;;;;71343:22:0;;;;;:39;;71366:15;;71343:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;70892:502;;;;71406:48;71426:9;71437:16;:7;:14;:16::i;:::-;-1:-1:-1;;;;;71406:19:0;;;:48;:19;:48::i;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;31299:172::-;31372:14;;:::i;:::-;31399:16;;:::i;:::-;31440:3;;31432;;:12;;:7;:12::i;71470:1854::-;71585:22;;:::i;:::-;71609;;:::i;:::-;71649:43;;:::i;:::-;71695:14;:12;:14::i;:::-;71649:60;;71720:42;;:::i;:::-;71765:14;:12;:14::i;:::-;71720:59;;71793:48;;:::i;:::-;71843:47;;:::i;:::-;71907:44;71941:9;71907:33;:44::i;:::-;71792:159;;-1:-1:-1;71792:159:0;-1:-1:-1;72029:1:0;71970:55;:47;72008:8;71970:32;71792:159;;71970:18;:32::i;:::-;:37;;:47::i;:55::-;:60;;71962:84;;;;-1:-1:-1;;;71962:84:0;;;;;;;:::i;:::-;72060:33;;:::i;:::-;72095:32;;:::i;:::-;72131:23;72144:9;72131:12;:23::i;:::-;72059:95;;-1:-1:-1;72059:95:0;-1:-1:-1;72188:58:0;72219:26;72059:95;;72219:15;:26::i;:::-;72188:25;:8;72202:10;72188:13;:25::i;:58::-;72165:81;-1:-1:-1;72279:35:0;:8;72165:81;72279:13;:35::i;:::-;72257:57;;72327:54;;:::i;:::-;72384:40;:13;72403:20;72384:18;:40::i;:::-;72327:97;;72435:53;;:::i;:::-;72491:38;:12;72509:19;72491:17;:38::i;:::-;72435:94;;72544:32;:19;:30;:32::i;:::-;72540:361;;;72616:19;:13;:17;:19::i;:::-;72593:42;-1:-1:-1;72672:35:0;:8;72593:42;72672:13;:35::i;:::-;72650:57;;72540:361;;;72729:31;:18;:29;:31::i;:::-;72725:176;;;72799:18;:12;:16;:18::i;:::-;72777:40;-1:-1:-1;72855:34:0;:8;72777:40;72855:13;:34::i;:::-;72832:57;;72725:176;-1:-1:-1;;;;;72941:23:0;;72913:25;72941:23;;;:12;:23;;;;;;;;:52;;;;;;;;73072:8;73031:51;;;;;;73119:28;;;;;;;;;;;;73031:51;73119:50;;73148:20;73119:28;:50::i;:::-;73093:76;;;73205:27;;;;;;;;;;;;;:48;;73233:19;73205:27;:48::i;:::-;73180:73;;;-1:-1:-1;73274:20:0;;73296:19;;-1:-1:-1;71470:1854:0;;-1:-1:-1;;;;;;;;;71470:1854:0:o;92553:290::-;92617:22;;:::i;:::-;92641;;:::i;:::-;92676:33;;:::i;:::-;-1:-1:-1;;;;;;;;92712:23:0;;;;;:12;:23;;;;;;;;;92676:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92754:54;;;;;;;92770:37;;92754:54;;92810:24;;;;;;;;67274:3;92810:24;;92754:54;;92553:290::o;31083:172::-;31156:14;;:::i;:::-;31183:16;;:::i;:::-;31224:3;;31216;;:12;;:7;:12::i;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;81873:2282::-;81944:48;;:::i;:::-;81994:47;;:::i;:::-;82058:28;82076:9;82058:17;:28::i;:::-;81943:143;;;;82098:52;;:::i;:::-;82152:51;;:::i;:::-;82220:32;82242:9;82220:21;:32::i;:::-;82097:155;;;;82340:45;;:::i;:::-;82405:89;;;;;;;;82431:9;-1:-1:-1;;;;;82421:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;82421:47:0;;82469:9;82421:58;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;82421:70:0;;:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;82405:89;;82340:154;-1:-1:-1;82547:1:0;82513:31;82340:154;82513:29;:31::i;:::-;:35;82509:689;;;82569:33;;:::i;:::-;82626:72;:66;82669:22;82626:37;:13;82645:17;82626:18;:37::i;:66::-;:70;:72::i;:::-;-1:-1:-1;;;;;82736:23:0;;82717:16;82736:23;;;:12;:23;;;;;;;;:52;;;;;;;;:60;;;82569:129;;-1:-1:-1;82815:36:0;;:::i;:::-;82854:59;67274:3;82854:40;:10;82875:18;;;82854:20;:40::i;:59::-;82815:98;;82932:39;;:::i;:::-;82974:40;82993:9;83004;82974:18;:40::i;:::-;82932:82;-1:-1:-1;83075:1:0;83037:35;:13;82932:82;83037:17;:35::i;:::-;:39;;;83033:150;;;-1:-1:-1;;;;;83101:26:0;;;;;;:15;:26;;;;;;;;:46;;;;;;;;:62;;;;83033:150;82509:689;;;;;81873:2282;83295:44;;:::i;:::-;83359:88;;;;;;;;83385:9;-1:-1:-1;;;;;83375:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;83375:47:0;;83423:8;83375:57;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;83375:69:0;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83359:88;;83295:152;-1:-1:-1;83499:1:0;83466:30;83295:152;83466:28;:30::i;:::-;:34;83462:675;;;83521:32;;:::i;:::-;83577:69;:63;83618:21;83577:35;:12;83595:16;83577:17;:35::i;:69::-;-1:-1:-1;;;;;83684:23:0;;83665:16;83684:23;;;:12;:23;;;;;;;;83725:8;83684:51;;;;;;;:59;;;83521:125;;-1:-1:-1;83762:35:0;;:::i;:::-;83800:58;67274:3;83800:39;:9;83820:18;;;83800:19;:39::i;:58::-;83762:96;;83877:38;;:::i;:::-;83918:39;83937:9;83948:8;83918:18;:39::i;:::-;83877:80;-1:-1:-1;84016:1:0;83980:33;:12;83877:80;83980:16;:33::i;:::-;:37;;;83976:146;;;-1:-1:-1;;;;;84042:26:0;;;;;;:15;:26;;;;;;;;84077:8;84042:45;;;;;;;:60;;;;83976:146;83462:675;;;;;81873:2282;;;;;;:::o;38063:196::-;38148:20;;:::i;:::-;38181:22;;:::i;:::-;38228:3;;38220;;:12;;:7;:12::i;37342:165::-;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;38559:185::-;38635:20;;:::i;:::-;38668:22;;:::i;:::-;38707:3;;:10;;38715:1;38707:7;:10::i;63718:304::-;63870:34;;:::i;:::-;63849:1;62788;:3;;;-1:-1:-1;;;;;62773:18:0;;62793:21;;;;;;;;;;;;;;;;;62765:50;;;;;-1:-1:-1;;;62765:50:0;;;;;;;;:::i;:::-;;63922:36:::1;;:::i;:::-;63990:3:::0;;63975;;:20:::1;::::0;:7:::1;:20::i;37515:269::-:0;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;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;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;15983:188::-;16077:86;16097:5;16127:23;;;16152:2;16156:5;16104:58;;;;;;;;;:::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;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46: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;30822:222::-;30921:3;;30915;;30894:4;;-1:-1:-1;30911:107:0;;;-1:-1:-1;30948:1:0;30941:8;;30911:107;30977:3;;30971;;:9;30967:51;;;-1:-1:-1;;;30997:9:0;;30967:51;-1:-1:-1;31035:1:0;30822:222;;;;:::o;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;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;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;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;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;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;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;1192:148::-;1268:20;;41639:1;41629:12;;41619:2;;41655:1;;41645:12;1515:320;;1629:4;1617:9;1612:3;1608:19;1604:30;1601:2;;;-1:-1;;1637:12;1601:2;1665:20;1629:4;1665:20;:::i;:::-;2682;;1739:75;;-1:-1;1656:29;1595:240;-1:-1;1595:240::o;1871:342::-;;1996:4;1984:9;1979:3;1975:19;1971:30;1968:2;;;-1:-1;;2004:12;1968:2;2032:20;1996:4;2032:20;:::i;:::-;2830:13;;2106:86;;-1:-1;2023:29;1962:251;-1:-1;1962:251::o;2893:241::-;;2997:2;2985:9;2976:7;2972:23;2968:32;2965:2;;;-1:-1;;3003:12;2965:2;85:6;72:20;97:33;124:5;97:33;:::i;3141:366::-;;;3262:2;3250:9;3241:7;3237:23;3233:32;3230:2;;;-1:-1;;3268:12;3230:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3320:63;-1:-1;3420:2;3459:22;;72:20;97:33;72:20;97:33;:::i;:::-;3428:63;;;;3224:283;;;;;:::o;3514:384::-;;;3644:2;3632:9;3623:7;3619:23;3615:32;3612:2;;;-1:-1;;3650:12;3612:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3702:63;-1:-1;3820:62;3874:7;3802:2;3850:22;;3820:62;:::i;:::-;3810:72;;3606:292;;;;;:::o;3905:509::-;;;;4052:2;4040:9;4031:7;4027:23;4023:32;4020:2;;;-1:-1;;4058:12;4020:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4110:63;-1:-1;4228:62;4282:7;4210:2;4258:22;;4228:62;:::i;:::-;4218:72;;4327:2;4370:9;4366:22;2682:20;4335:63;;4014:400;;;;;:::o;4421:416::-;;;4567:2;4555:9;4546:7;4542:23;4538:32;4535:2;;;-1:-1;;4573:12;4535:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4625:63;-1:-1;4743:78;4813:7;4725:2;4789:22;;4743:78;:::i;4844:366::-;;;4965:2;4953:9;4944:7;4940:23;4936:32;4933:2;;;-1:-1;;4971:12;4933:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5023:63;5123:2;5162:22;;;;2682:20;;-1:-1;;;4927:283::o;5217:257::-;;5329:2;5317:9;5308:7;5304:23;5300:32;5297:2;;;-1:-1;;5335:12;5297:2;223:6;217:13;40690:5;37835:13;37828:21;40668:5;40665:32;40655:2;;-1:-1;;40701:12;5481:313;;5621:2;5609:9;5600:7;5596:23;5592:32;5589:2;;;-1:-1;;5627:12;5589:2;386:6;380:13;398:58;450:5;398:58;:::i;6401:577::-;;;;6582:2;6570:9;6561:7;6557:23;6553:32;6550:2;;;-1:-1;;6588:12;6550:2;753:6;740:20;765:51;810:5;765:51;:::i;:::-;6640:81;-1:-1;6758:2;6797:22;;72:20;97:33;72:20;97:33;:::i;:::-;6766:63;-1:-1;6884:78;6954:7;6866:2;6930:22;;6884:78;:::i;:::-;6874:88;;6544:434;;;;;:::o;7412:595::-;;;;7602:2;7590:9;7581:7;7577:23;7573:32;7570:2;;;-1:-1;;7608:12;7570:2;753:6;740:20;765:51;810:5;765:51;:::i;:::-;7660:81;-1:-1;7796:62;7850:7;7778:2;7826:22;;7796:62;:::i;9095:313::-;;9235:2;9223:9;9214:7;9210:23;9206:32;9203:2;;;-1:-1;;9241:12;9203:2;9303:89;9384:7;9360:22;9303:89;:::i;9415:499::-;;;9597:2;9585:9;9576:7;9572:23;9568:32;9565:2;;;-1:-1;;9603:12;9565:2;9665:89;9746:7;9722:22;9665:89;:::i;:::-;9655:99;;9809:89;9890:7;9791:2;9870:9;9866:22;9809:89;:::i;10253:263::-;;10368:2;10356:9;10347:7;10343:23;10339:32;10336:2;;;-1:-1;;10374:12;10336:2;-1:-1;2830:13;;10330:186;-1:-1;10330:186::o;20652:271::-;;10952:5;37176:12;11063:52;11108:6;11103:3;11096:4;11089:5;11085:16;11063:52;:::i;:::-;11127:16;;;;;20786:137;-1:-1;;20786:137::o;20930:222::-;-1:-1;;;;;38729:54;;;;10743:37;;21057:2;21042:18;;21028:124::o;21404:444::-;-1:-1;;;;;38729:54;;;10743:37;;38729:54;;;;21751:2;21736:18;;10743:37;21834:2;21819:18;;11711:36;;;;21587:2;21572:18;;21558:290::o;21855:333::-;-1:-1;;;;;38729:54;;;;10743:37;;22174:2;22159:18;;11711:36;22010:2;21995:18;;21981:207::o;22737:236::-;22871:2;22856:18;;38535:42;38571:5;38535:42;:::i;:::-;11583:57;;;22842:131;:::o;22980:474::-;23178:2;23163:18;;38535:42;38571:5;38535:42;:::i;:::-;11583:57;;;-1:-1;;;;;38729:54;;;;23357:2;23342:18;;10602:58;23440:2;23425:18;;;11711:36;23149:305;:::o;23461:325::-;11711:36;;;23772:2;23757:18;;11711:36;23612:2;23597:18;;23583:203::o;23793:310::-;;23940:2;23961:17;23954:47;12021:5;37176:12;37615:6;23940:2;23929:9;23925:18;37603:19;12115:52;12160:6;37643:14;23929:9;37643:14;23940:2;12141:5;12137:16;12115:52;:::i;:::-;40357:7;40341:14;-1:-1;;40337:28;12179:39;;;;37643:14;12179:39;;23911:192;-1:-1;;23911:192::o;24110:416::-;24310:2;24324:47;;;12455:2;24295:18;;;37603:19;-1:-1;;;37643:14;;;12471:41;12531:12;;;24281:245::o;24533:416::-;24733:2;24747:47;;;12782:2;24718:18;;;37603:19;12818:34;37643:14;;;12798:55;-1:-1;;;12873:12;;;12866:30;12915:12;;;24704:245::o;24956:416::-;25156:2;25170:47;;;13166:2;25141:18;;;37603:19;-1:-1;;;37643:14;;;13182:37;13238:12;;;25127:245::o;25379:416::-;25579:2;25593:47;;;13489:2;25564:18;;;37603:19;13525:29;37643:14;;;13505:50;13574:12;;;25550:245::o;25802:416::-;26002:2;26016:47;;;13825:2;25987:18;;;37603:19;13861:34;37643:14;;;13841:55;-1:-1;;;13916:12;;;13909:25;13953:12;;;25973:245::o;26225:416::-;26425:2;26439:47;;;14204:2;26410:18;;;37603:19;-1:-1;;;37643:14;;;14220:36;14275:12;;;26396:245::o;26648:416::-;26848:2;26862:47;;;14526:2;26833:18;;;37603:19;14562:34;37643:14;;;14542:55;-1:-1;;;14617:12;;;14610:30;14659:12;;;26819:245::o;27071:416::-;27271:2;27285:47;;;14910:2;27256:18;;;37603:19;-1:-1;;;37643:14;;;14926:34;14979:12;;;27242:245::o;27494:416::-;27694:2;27708:47;;;15230:2;27679:18;;;37603:19;15266:34;37643:14;;;15246:55;-1:-1;;;15321:12;;;15314:38;15371:12;;;27665:245::o;27917:416::-;28117:2;28131:47;;;15622:2;28102:18;;;37603:19;15658:34;37643:14;;;15638:55;-1:-1;;;15713:12;;;15706:25;15750:12;;;28088:245::o;28340:416::-;28540:2;28554:47;;;16001:2;28525:18;;;37603:19;16037:34;37643:14;;;16017:55;-1:-1;;;16092:12;;;16085:25;16129:12;;;28511:245::o;28763:416::-;28963:2;28977:47;;;16380:2;28948:18;;;37603:19;-1:-1;;;37643:14;;;16396:33;16448:12;;;28934:245::o;29186:416::-;29386:2;29400:47;;;29371:18;;;37603:19;16735:34;37643:14;;;16715:55;16789:12;;;29357:245::o;29609:416::-;29809:2;29823:47;;;17040:2;29794:18;;;37603:19;17076:34;37643:14;;;17056:55;-1:-1;;;17131:12;;;17124:31;17174:12;;;29780:245::o;30032:416::-;30232:2;30246:47;;;17425:2;30217:18;;;37603:19;-1:-1;;;37643:14;;;17441:45;17505:12;;;30203:245::o;30455:416::-;30655:2;30669:47;;;17756:2;30640:18;;;37603:19;17792:31;37643:14;;;17772:52;17843:12;;;30626:245::o;30878:416::-;31078:2;31092:47;;;18094:2;31063:18;;;37603:19;-1:-1;;;37643:14;;;18110:36;18165:12;;;31049:245::o;31301:416::-;31501:2;31515:47;;;18416:2;31486:18;;;37603:19;18452:34;37643:14;;;18432:55;-1:-1;;;18507:12;;;18500:28;18547:12;;;31472:245::o;31724:416::-;31924:2;31938:47;;;18798:2;31909:18;;;37603:19;18834:34;37643:14;;;18814:55;-1:-1;;;18889:12;;;18882:34;18935:12;;;31895:245::o;32147:416::-;32347:2;32361:47;;;19186:2;32332:18;;;37603:19;-1:-1;;;37643:14;;;19202:38;19259:12;;;32318:245::o;32570:416::-;32770:2;32784:47;;;32755:18;;;37603:19;19546:34;37643:14;;;19526:55;19600:12;;;32741:245::o;32993:322::-;19887:23;;11711:36;;33170:2;33155:18;;33141:174::o;33322:533::-;19887:23;;11711:36;;19887:23;33841:2;33826:18;;11711:36;33577:2;33562:18;;33548:307::o;33862:433::-;19887:23;;11711:36;;34281:2;34266:18;;11711:36;34067:2;34052:18;;34038:257::o;35243:222::-;11711:36;;;35370:2;35355:18;;35341:124::o;35812:444::-;11711:36;;;36159:2;36144:18;;11711:36;;;;36242:2;36227:18;;11711:36;35995:2;35980:18;;35966:290::o;36263:556::-;11711:36;;;36639:2;36624:18;;11711:36;;;;36722:2;36707:18;;11711:36;36805:2;36790:18;;11711:36;36474:3;36459:19;;36445:374::o;36826:256::-;36888:2;36882:9;36914:17;;;36989:18;36974:34;;37010:22;;;36971:62;36968:2;;;37046:1;;37036:12;36968:2;36888;37055:22;36866:216;;-1:-1;36866:216::o;39997:268::-;40062:1;40069:101;40083:6;40080:1;40077:13;40069:101;;;40150:11;;;40144:18;40131:11;;;40124:39;40105:2;40098:10;40069:101;;;40185:6;40182:1;40179:13;40176:2;;;-1:-1;;40062:1;40232:16;;40225:27;40046:219::o;40378:100::-;40456:1;40449:5;40446:12;40436:2;;40462:9;40485:117;-1:-1;;;;;38729:54;;40544:35;;40534:2;;40593:1;;40583:12

Swarm Source

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