Contract 0x0729b56c0893b80aeb0d3e2412b5cf7179db0304

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x8239a3c4c1b03ccc99369955d63450a0d516c94ac3eeba6ef069289ba67d6a4a0x6080604069848712021-03-11 5:14:33195 days 21 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.10104988
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x6d136504f7c25b16fb9d1495ca4fcd9c0c32141dbebefa8a471febe93f9f201487232982021-05-10 15:29:45135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x13783decf87cfb46dbf8dd3d141fd3a2874364756ab9d34142a60055f9f4519587232962021-05-10 15:29:39135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x81844595eaa8d4ca9367fa81e718c843a1052bf0f2ed0ddb9db09433931d989e87232962021-05-10 15:29:39135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xb935828437c3eac9b570e1868996e3e89a74063abc1eafbb128e8c54b1f16fa587232932021-05-10 15:29:30135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xae5904d90a58f3995453cbc0026609ad253444cb0efce87322d2339090bafbad87232922021-05-10 15:29:27135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x01f0ae1f111b6485aa791a906cc4356c52ce7f0cfd5b525810bca4a0b1d2e41587232902021-05-10 15:29:21135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x9eb999825c6cd6c30b9fb4d7367d25a19a0fa365fd089e84b10ddc6f003c71f587232882021-05-10 15:29:15135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xc4c4350c257237743d2b7fc4a9d9d4a80937f348c75a5616886e00daf207726287232862021-05-10 15:29:09135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x79a462f1739cc8535ef2b570348d383d523894cedfb10bf5355a7a7850e269ea87232852021-05-10 15:29:06135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xcc59720d946b317fbd5bc3e18efe3ab5ac6ae09aa1542b38774129507ed7f6c787232832021-05-10 15:29:00135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x3824f7758800f6727a688fa8ae806c5c983646e3b921ec56f2fc7a8951a5d2b587232812021-05-10 15:28:54135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x8a220e330e991c1802a822a6a91390bb3b6afd7a3293b89279d65eb7e83e110b87232812021-05-10 15:28:54135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x39f50602372d7ddfbce982cc5663835a47d7b2b5e0ad229f63866ef49e9b289f87232792021-05-10 15:28:48135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x51e55e6e27d8a79e3f5a15a7f1e6d3020d39a33384ec5b3a8ab01966b85073b687232772021-05-10 15:28:42135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x24c38ab1bcb30f180429490e6b601b5f51a331eef3e5ddcc07211586f65355f587232752021-05-10 15:28:36135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xa90b11b66c2e84765262ce9d7b43c27203e560d33fc297589f1ab8002f6ee70d87232742021-05-10 15:28:33135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x968f04a5b3eb79d6dd138f76f9c601a19bfd42b9319bacc5b1531a9da5bd64d687232712021-05-10 15:28:24135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x625edd805b5ac7a9c251db5a2a161834a6f19c94804427e24cc412256304166f87232702021-05-10 15:28:21135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xcd3c81994497861edfb7f225ce1406f7e4f961839561beca33b2f5ec93adbae187232682021-05-10 15:28:15135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x635b5dd0207b412fb37ef2d13bae7685bdabd4af78e409590b1007a9fd6698d187232662021-05-10 15:28:09135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x563848ea74d7ea9e47b3d850e129392aaca918cf4247da5759713d64e8ac180687232652021-05-10 15:28:06135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xb6b4e5829746b0f2a3d70b4082e8618203de6335784bdb027e2f34e66a6c6eea87232612021-05-10 15:27:54135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x5454bdcbeaefd3db11bab611c2102420886ba2ab16e709b6e51bdf6c890d9d1c87232602021-05-10 15:27:51135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0xca3ac9c7bc10558f71439eae8cf56bf52c2764419ecbe09b004c9d450b98149987232592021-05-10 15:27:48135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
0x1e901df356d1fd45c48a59a946231b2f991b85fa8822c8ebbcc25d2d5b08e4b487232572021-05-10 15:27:42135 days 11 hrs ago 0x002f0a794a41f90256e717887cc682f49e7a3b30 0x0729b56c0893b80aeb0d3e2412b5cf7179db03040 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Exchange

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-03-12
*/

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




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

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

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

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

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

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

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

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

// File: contracts/interface/IPriceFeed.sol


interface IPriceFeed {
    // get latest price
    function getPrice(bytes32 _priceFeedKey) external view returns (uint256);

    // get twap price depending on _period
    function getTwapPrice(bytes32 _priceFeedKey, uint256 _interval) external view returns (uint256);
}

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

pragma experimental ABIEncoderV2;




interface IExchange {
    /**
     * @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;
    }

    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 pure returns (Decimal.decimal memory);

    function getOutputPriceWithReserves(
        Dir _dir,
        Decimal.decimal memory _baseAssetAmount,
        Decimal.decimal memory _quoteAssetPoolAmount,
        Decimal.decimal memory _baseAssetPoolAmount
    ) external pure 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 getBaseAssetDeltaThisFundingPeriod() external view returns (SignedDecimal.signedDecimal 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(address account, uint256 amount) external;

    function burn(address account, uint256 amount) external;

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

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

// File: contracts/interface/ICFD.sol





interface ICFD {
    //
    // Struct and Enum
    //
    enum Side {BUY, SELL}
    enum PnlCalcOption {SPOT_PRICE, TWAP}

    /// @notice This struct records personal position information
    /// @param size denominated in amm.baseAsset
    /// @param margin isolated margin
    /// @param openNotional the quoteAsset value of position when opening position. the cost of the position
    /// @param lastUpdatedCumulativePremiumFraction for calculating funding payment, record at the moment every time when trader open/reduce/close position
    /// @param lastUpdatedCumulativeOvernightFeeRate for calculating holding fee, record at the moment every time when trader open/reduce/close position
    /// @param liquidityHistoryIndex
    /// @param blockNumber the block number of the last position
    struct Position {
        SignedDecimal.signedDecimal size;
        Decimal.decimal margin;
        Decimal.decimal openNotional;
        SignedDecimal.signedDecimal lastUpdatedCumulativePremiumFraction;
        Decimal.decimal lastUpdatedCumulativeOvernightFeeRate;
        uint256 liquidityHistoryIndex;
        uint256 blockNumber;
    }

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

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

    function getLatestCumulativeOvernightFeeRate(IExchange _exchange) external view returns (Decimal.decimal memory);

    function getPositionNotionalAndUnrealizedPnl(
        IExchange _exchange,
        address _trader,
        PnlCalcOption _pnlCalcOption
    ) external view returns (Decimal.decimal memory positionNotional, SignedDecimal.signedDecimal memory unrealizedPnl);

    function getPosition(IExchange _exchange, address _trader) external view returns (Position memory);

    function getUnadjustedPosition(IExchange _exchange, address _trader)
        external
        view
        returns (Position memory position);

    function getMarginRatio(IExchange _exchange, address _trader)
        external
        view
        returns (SignedDecimal.signedDecimal memory);
}

// File: contracts/interface/ICFDVault.sol






interface ICFDVault {
    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) external view returns (SignedDecimal.signedDecimal memory);

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

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

    function requireMMNotBankrupt(IExchange _exchange) external;
}

// File: contracts/utils/MixedDecimal.sol





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

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

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

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

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

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

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

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

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

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

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

// File: contracts/utils/BlockContext.sol


// wrap block.xxx functions for testing
// only support timestamp and number so far
abstract contract BlockContext {
    //◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//

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

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

    function _blockNumber() internal view virtual returns (uint256) {
        return block.number;
    }
}

// File: contracts/utils/Sqrt.sol


library Sqrt {
    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 y) internal pure returns (uint256) {
        if (y > 3) {
            uint256 z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
            return z;
        } else if (y != 0) {
            return 1;
        } else {
            return 0;
        }
    }
}

// File: contracts/Exchange.sol















contract Exchange is IExchange, OwnableUpgradeable, BlockContext, ERC20Upgradeable {
    using SafeMathUpgradeable for uint256;
    using Decimal for Decimal.decimal;
    using SignedDecimal for SignedDecimal.signedDecimal;
    using MixedDecimal for SignedDecimal.signedDecimal;
    using Sqrt for uint256;

    //
    // CONSTANT
    //
    // because position decimal rounding error,
    // if the position size is less than IGNORABLE_DIGIT_FOR_SHUTDOWN, it's equal size is 0
    uint256 private constant IGNORABLE_DIGIT_FOR_SHUTDOWN = 100;

    // a margin to prevent from rounding when calc liquidity multiplier limit
    uint256 private constant MARGIN_FOR_LIQUIDITY_MIGRATION_ROUNDING = 1e9;

    //
    // EVENTS
    //
    event SwapInput(Dir dir, uint256 quoteAssetAmount, uint256 baseAssetAmount);
    event SwapOutput(Dir dir, uint256 quoteAssetAmount, uint256 baseAssetAmount);
    event FundingRateUpdated(int256 rate, uint256 underlyingPrice);
    event ReserveSnapshotted(uint256 quoteAssetReserve, uint256 baseAssetReserve, uint256 timestamp);
    event LiquidityChanged(uint256 quoteReserve, uint256 baseReserve, int256 cumulativeNotional);
    event CapChanged(uint256 maxHoldingBaseAsset, uint256 openInterestNotionalCap);
    event Shutdown(uint256 settlementPrice);
    event MoveAMMPrice(
        uint256 ammPrice,
        uint256 oraclePrice,
        uint256 adjustPrice,
        int256 MMLiquidity,
        int256 MMPNL,
        bool moved
    );

    //
    // MODIFIERS
    //
    modifier onlyOpen() {
        require(open, "exchange was closed");
        _;
    }

    modifier onlyClose() {
        require(open == false, "exchange was open");
        _;
    }

    modifier onlyCounterParty() {
        require(address(CFD) == _msgSender(), "caller is not counterParty");
        _;
    }

    modifier onlyMinter() {
        require(address(CFDVault) == _msgSender(), "caller is not Minter");
        _;
    }

    //
    // enum and struct
    //
    struct ReserveSnapshot {
        Decimal.decimal quoteAssetReserve;
        Decimal.decimal baseAssetReserve;
        uint256 timestamp;
        uint256 blockNumber;
    }

    // internal usage
    enum QuoteAssetDir {QUOTE_IN, QUOTE_OUT}
    // internal usage
    enum TwapCalcOption {RESERVE_ASSET, INPUT_ASSET}

    // To record current base/quote asset to calculate TWAP

    struct TwapInputAsset {
        Dir dir;
        Decimal.decimal assetAmount;
        QuoteAssetDir inOrOut;
    }

    struct TwapPriceCalcParams {
        TwapCalcOption opt;
        uint256 snapshotIndex;
        TwapInputAsset asset;
    }

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

    // update during every swap and calculate total amm pnl per funding period
    SignedDecimal.signedDecimal private baseAssetDeltaThisFundingPeriod;

    // update during every swap
    Decimal.decimal public longPositionSize;
    Decimal.decimal public shortPositionSize;

    // update during every swap and used when shutting exchange down
    SignedDecimal.signedDecimal public totalPositionSize;

    // latest funding rate = ((twap market price - twap oracle price) / twap oracle price) / 24
    SignedDecimal.signedDecimal public fundingRate;

    SignedDecimal.signedDecimal private cumulativeNotional;

    Decimal.decimal private settlementPrice;
    Decimal.decimal public tradeLimitRatio;
    Decimal.decimal public quoteAssetReserve;
    Decimal.decimal public baseAssetReserve;
    Decimal.decimal public fluctuationLimitRatio;

    // owner can update
    Decimal.decimal public spreadRatio;
    Decimal.decimal public priceAdjustRatio;
    Decimal.decimal private maxHoldingBaseAsset;
    Decimal.decimal private openInterestNotionalCap;

    // init cumulativePositionMultiplier is 1, will be updated every time when amm reserve increase/decrease
    Decimal.decimal private cumulativePositionMultiplier;

    // snapshot of amm reserve when change liquidity's invariant
    LiquidityChangedSnapshot[] private liquidityChangedSnapshots;

    uint256 public spotPriceTwapInterval;
    uint256 public fundingPeriod;
    uint256 public fundingBufferPeriod;
    uint256 public nextFundingTime;
    bytes32 public priceFeedKey;
    ReserveSnapshot[] public reserveSnapshots;

    ICFDVault public CFDVault;
    IERC20Upgradeable public override quoteAsset;
    IPriceFeed public priceFeed;
    ICFD public CFD;
    bool public override open;
    uint256 public lastMoveAmmPriceTime;

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

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

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

    //
    // FUNCTIONS
    //
    function initialize(
        uint256 _quoteAssetReserve,
        uint256 _baseAssetReserve,
        uint256 _tradeLimitRatio,
        uint256 _fundingPeriod,
        IPriceFeed _priceFeed,
        ICFD _CFD,
        ICFDVault _CFDVault,
        bytes32 _priceFeedKey,
        address _quoteAsset,
        uint256 _fluctuationLimitRatio,
        uint256 _spreadRatio,
        uint256 _priceAdjustRatio
    ) public initializer {
        require(
            _quoteAssetReserve != 0 &&
                _tradeLimitRatio != 0 &&
                _baseAssetReserve != 0 &&
                _fundingPeriod != 0 &&
                address(_priceFeed) != address(0) &&
                address(_CFD) != address(0) &&
                address(_CFDVault) != address(0) &&
                _quoteAsset != address(0),
            "invalid input"
        );
        __Ownable_init();
        __ERC20_init("MM Liquidity Provider Token", "MLP");

        quoteAssetReserve = Decimal.decimal(_quoteAssetReserve);
        baseAssetReserve = Decimal.decimal(_baseAssetReserve);
        tradeLimitRatio = Decimal.decimal(_tradeLimitRatio);
        spreadRatio = Decimal.decimal(_spreadRatio);
        priceAdjustRatio = Decimal.decimal(_priceAdjustRatio);
        fluctuationLimitRatio = Decimal.decimal(_fluctuationLimitRatio);
        fundingPeriod = _fundingPeriod;
        fundingBufferPeriod = _fundingPeriod.div(2);
        spotPriceTwapInterval = 1 hours;
        priceFeedKey = _priceFeedKey;
        quoteAsset = IERC20Upgradeable(_quoteAsset);
        priceFeed = _priceFeed;
        CFD = _CFD;
        CFDVault = _CFDVault;
        cumulativePositionMultiplier = Decimal.one();
        liquidityChangedSnapshots.push(
            LiquidityChangedSnapshot({
                cumulativeNotional: SignedDecimal.zero(),
                baseAssetReserve: baseAssetReserve,
                quoteAssetReserve: quoteAssetReserve,
                totalPositionSize: SignedDecimal.zero()
            })
        );
        reserveSnapshots.push(ReserveSnapshot(quoteAssetReserve, baseAssetReserve, _blockTimestamp(), _blockNumber()));
        emit ReserveSnapshotted(quoteAssetReserve.toUint(), baseAssetReserve.toUint(), _blockTimestamp());
    }

    /**
     * @notice mint MLP for MM
     * @dev only CFD can call this function
     */
    function mint(address account, uint256 amount) external override onlyOpen onlyMinter {
        _mint(account, amount);
    }

    /**
     * @notice burn MLP
     * @dev only CFD can call this function
     */
    function burn(address account, uint256 amount) external override onlyMinter {
        _burn(account, amount);
    }

    /**
     * @notice Swap your quote asset to base asset, the impact of the price MUST be less than `fluctuationLimitRatio`
     * @dev Only clearingHouse can call this function
     * @param _dir ADD_TO_AMM for long, REMOVE_FROM_AMM for short
     * @param _quoteAssetAmount quote asset amount
     * @param _baseAssetAmountLimit minimum base asset amount expected to get to prevent front running
     * @return base asset amount
     */
    function swapInput(
        Dir _dir,
        Decimal.decimal calldata _quoteAssetAmount,
        Decimal.decimal calldata _baseAssetAmountLimit
    ) external override onlyOpen onlyCounterParty returns (Decimal.decimal memory) {
        if (_quoteAssetAmount.toUint() == 0) {
            return Decimal.zero();
        }
        if (_dir == Dir.REMOVE_FROM_AMM) {
            require(
                quoteAssetReserve.mulD(tradeLimitRatio).toUint() >= _quoteAssetAmount.toUint(),
                "over trading limit"
            );
        }

        Decimal.decimal memory baseAssetAmount = getInputPrice(_dir, _quoteAssetAmount);
        // If LONG, exchanged base amount should be more than _baseAssetAmountLimit,
        // otherwise(SHORT), exchanged base amount should be less than _baseAssetAmountLimit.
        // In SHORT case, more position means more debt so should not be larger than _baseAssetAmountLimit
        if (_baseAssetAmountLimit.toUint() != 0) {
            if (_dir == Dir.ADD_TO_AMM) {
                require(baseAssetAmount.toUint() >= _baseAssetAmountLimit.toUint(), "Less than minimal base token");
            } else {
                require(baseAssetAmount.toUint() <= _baseAssetAmountLimit.toUint(), "More than maximal base token");
            }
        }

        if (_dir == Dir.ADD_TO_AMM) {
            longPositionSize = longPositionSize.addD(baseAssetAmount);
        } else {
            shortPositionSize = shortPositionSize.addD(baseAssetAmount);
        }

        updateReserve(_dir, _quoteAssetAmount, baseAssetAmount, false);
        emit SwapInput(_dir, _quoteAssetAmount.toUint(), baseAssetAmount.toUint());
        return baseAssetAmount;
    }

    /**
     * @notice swap your base asset to quote asset; the impact of the price can be restricted with fluctuationLimitRatio
     * @dev only clearingHouse can call this function
     * @param _dir ADD_TO_AMM for short, REMOVE_FROM_AMM for long, opposite direction from swapInput
     * @param _baseAssetAmount base asset amount
     * @param _quoteAssetAmountLimit limit of quote asset amount; for slippage protection
     * @param _skipFluctuationCheck false for checking fluctuationLimitRatio; true for no limit, only when closePosition()
     * @return quote asset amount
     */
    function swapOutput(
        Dir _dir,
        Decimal.decimal calldata _baseAssetAmount,
        Decimal.decimal calldata _quoteAssetAmountLimit,
        bool _skipFluctuationCheck
    ) external override onlyOpen onlyCounterParty returns (Decimal.decimal memory) {
        return implSwapOutput(_dir, _baseAssetAmount, _quoteAssetAmountLimit, _skipFluctuationCheck);
    }

    /**
     * @notice update funding rate
     * @dev only allow to update while reaching `nextFundingTime`
     * @return premium fraction of this period in 18 digits
     */
    function settleFunding() external override onlyOpen onlyCounterParty returns (SignedDecimal.signedDecimal memory) {
        require(_blockTimestamp() >= nextFundingTime, "settle funding too early");
        SignedDecimal.signedDecimal memory premiumFraction = SignedDecimal.zero();
        Decimal.decimal memory underlyingPrice = getUnderlyingTwapPrice(spotPriceTwapInterval);

        // if AMM price has been moved before fundingTime, no need to this funding
        if (lastMoveAmmPriceTime.add(fundingPeriod) < nextFundingTime) {
            // premium = twapMarketPrice - twapIndexPrice
            // timeFraction = fundingPeriod(1 hour) / 1 day
            // premiumFraction = premium * timeFraction
            SignedDecimal.signedDecimal memory premium =
                MixedDecimal.fromDecimal(getTwapPrice(spotPriceTwapInterval)).subD(underlyingPrice);
            premiumFraction = premium.mulScalar(fundingPeriod).divScalar(int256(1 days));
        }

        // update funding rate = premiumFraction / twapIndexPrice
        updateFundingRate(premiumFraction, underlyingPrice);

        // in order to prevent multiple funding settlement during very short time after network congestion
        uint256 minNextValidFundingTime = _blockTimestamp().add(fundingBufferPeriod);

        // floor((nextFundingTime + fundingPeriod) / 3600) * 3600
        uint256 nextFundingTimeOnHourStart = nextFundingTime.add(fundingPeriod).div(1 hours).mul(1 hours);

        // max(nextFundingTimeOnHourStart, minNextValidFundingTime)
        nextFundingTime = nextFundingTimeOnHourStart > minNextValidFundingTime
            ? nextFundingTimeOnHourStart
            : minNextValidFundingTime;

        // reset funding related states
        baseAssetDeltaThisFundingPeriod = SignedDecimal.zero();

        return premiumFraction;
    }

    /**
     * @notice calculate the total long/short position size after migrate liquidity
     */
    function migratePosition(Decimal.decimal memory _quoteAsset, Decimal.decimal memory _baseAsset) private {
        Decimal.decimal memory longPositionSizeBefore = longPositionSize;
        Decimal.decimal memory shortPositionSizeBefore = shortPositionSize;
        Decimal.decimal memory _oldQuoteAssetUpdated;
        Decimal.decimal memory _oldBaseAssetUpdated;
        Decimal.decimal memory _newQuoteAssetUpdated;
        Decimal.decimal memory _newBaseAssetUpdated;

        if (longPositionSizeBefore.toUint() > 0) {
            // measure the trader position's notional value on the old curve
            // (by simulating closing the position)
            Decimal.decimal memory posNotional =
                getOutputPriceWithReserves(Dir.ADD_TO_AMM, longPositionSizeBefore, _quoteAsset, _baseAsset);

            // calculate and apply the required size on the new curve
            longPositionSize = getInputPrice(Dir.REMOVE_FROM_AMM, posNotional);
            _oldQuoteAssetUpdated = _quoteAsset.subD(posNotional);
            _oldBaseAssetUpdated = _baseAsset.addD(longPositionSizeBefore);
            _newQuoteAssetUpdated = quoteAssetReserve.subD(posNotional);
            _newBaseAssetUpdated = baseAssetReserve.addD(longPositionSize);
        }

        if (shortPositionSizeBefore.toUint() > 0) {
            // measure the trader position's notional value on the old curve
            // (by simulating closing the position)
            Decimal.decimal memory posNotional =
                getOutputPriceWithReserves(
                    Dir.REMOVE_FROM_AMM,
                    shortPositionSizeBefore,
                    _oldQuoteAssetUpdated,
                    _oldBaseAssetUpdated
                );

            // calculate and apply the required size on the new curve
            shortPositionSize = getInputPriceWithReserves(
                Dir.ADD_TO_AMM,
                posNotional,
                _newQuoteAssetUpdated,
                _newBaseAssetUpdated
            );
        }
    }

    function migrateLiquidity(
        Decimal.decimal calldata _liquidityMultiplier,
        Decimal.decimal calldata _fluctuationLimitRatio
    ) external override onlyOwner {
        require(_liquidityMultiplier.toUint() != Decimal.one().toUint(), "multiplier can't be 1");

        // check liquidity multiplier limit, have lower bound if position size is positive for now.
        checkLiquidityMultiplierLimit(totalPositionSize, _liquidityMultiplier);
        checkLiquidityMultiplierLimit(baseAssetDeltaThisFundingPeriod, _liquidityMultiplier);

        // #53 fix sandwich attack during liquidity migration
        checkFluctuationLimit(_fluctuationLimitRatio);

        // get current reserve values
        Decimal.decimal memory quoteAssetBeforeAddingLiquidity = quoteAssetReserve;
        Decimal.decimal memory baseAssetBeforeAddingLiquidity = baseAssetReserve;
        SignedDecimal.signedDecimal memory totalPositionSizeBefore = totalPositionSize;

        // migrate liquidity
        quoteAssetReserve = quoteAssetBeforeAddingLiquidity.mulD(_liquidityMultiplier);
        baseAssetReserve = baseAssetBeforeAddingLiquidity.mulD(_liquidityMultiplier);

        // MUST be called after liquidity migrated
        // baseAssetDeltaThisFundingPeriod is total position size(of a funding period) owned by Amm
        // That's why need to mulScalar(-1) when calculating the migrated size.
        baseAssetDeltaThisFundingPeriod = calcBaseAssetAfterLiquidityMigration(
            baseAssetDeltaThisFundingPeriod.mulScalar(-1),
            quoteAssetBeforeAddingLiquidity,
            baseAssetBeforeAddingLiquidity
        )
            .mulScalar(-1);

        totalPositionSize = calcBaseAssetAfterLiquidityMigration(
            totalPositionSizeBefore,
            quoteAssetBeforeAddingLiquidity,
            baseAssetBeforeAddingLiquidity
        );

        migratePosition(quoteAssetBeforeAddingLiquidity, baseAssetBeforeAddingLiquidity);

        // update snapshot
        liquidityChangedSnapshots.push(
            LiquidityChangedSnapshot({
                cumulativeNotional: cumulativeNotional,
                quoteAssetReserve: quoteAssetReserve,
                baseAssetReserve: baseAssetReserve,
                totalPositionSize: totalPositionSize
            })
        );

        emit LiquidityChanged(quoteAssetReserve.toUint(), baseAssetReserve.toUint(), cumulativeNotional.toInt());
    }

    function calcBaseAssetAfterLiquidityMigration(
        SignedDecimal.signedDecimal memory _baseAssetAmount,
        Decimal.decimal memory _fromQuoteReserve,
        Decimal.decimal memory _fromBaseReserve
    ) public view override returns (SignedDecimal.signedDecimal memory) {
        if (_baseAssetAmount.toUint() == 0) {
            return _baseAssetAmount;
        }

        bool isPositiveValue = _baseAssetAmount.toInt() > 0 ? true : false;

        // measure the trader position's notional value on the old curve
        // (by simulating closing the position)
        Decimal.decimal memory posNotional =
            getOutputPriceWithReserves(
                isPositiveValue ? Dir.ADD_TO_AMM : Dir.REMOVE_FROM_AMM,
                _baseAssetAmount.abs(),
                _fromQuoteReserve,
                _fromBaseReserve
            );

        // calculate and apply the required size on the new curve
        SignedDecimal.signedDecimal memory newBaseAsset =
            MixedDecimal.fromDecimal(
                getInputPrice(isPositiveValue ? Dir.REMOVE_FROM_AMM : Dir.ADD_TO_AMM, posNotional)
            );
        return newBaseAsset.mulScalar(isPositiveValue ? 1 : int256(-1));
    }

    /**
     * @notice shutdown exchange
     * @dev only owner can call this function
     */
    function shutdown() external override onlyOwner {
        SignedDecimal.signedDecimal memory MMUnrealizedPNL = getMMUnrealizedPNL(baseAssetReserve, quoteAssetReserve);
        SignedDecimal.signedDecimal memory MMLiquidity = CFD.getMMLiquidity(address(this));
        SignedDecimal.signedDecimal memory remainAmount = MMUnrealizedPNL.addD(MMLiquidity);
        Decimal.decimal memory deltaAmount;

        if (remainAmount.isNegative()) {
            deltaAmount = cumulativeNotional.addD(MMLiquidity).abs();
        } else {
            deltaAmount = cumulativeNotional.subD(MMUnrealizedPNL).abs();
        }

        SignedDecimal.signedDecimal memory deltaPositionSize =
            MixedDecimal.fromDecimal(longPositionSize).subD(shortPositionSize);

        // if total position size less than IGNORABLE_DIGIT_FOR_SHUTDOWN, treat it as 0 positions due to rounding error
        if (deltaPositionSize.toUint() > IGNORABLE_DIGIT_FOR_SHUTDOWN) {
            settlementPrice = deltaAmount.divD(deltaPositionSize.abs());
        }

        open = false;
        emit Shutdown(settlementPrice.toUint());
    }

    /**
     * @notice set counter party
     * @dev only owner can call this function
     * @param _counterParty address of counter party
     */
    function setCounterParty(address _counterParty) external onlyOwner {
        CFD = ICFD(_counterParty);
    }

    /**
     * @notice set minter
     * @dev only owner can call this function
     * @param _minter address of minter
     */
    function setMinter(address _minter) external onlyOwner {
        CFDVault = ICFDVault(_minter);
    }

    /**
     * @notice set fluctuation limit rate. Default value is `1 / max leverage`
     * @dev only owner can call this function
     * @param _fluctuationLimitRatio fluctuation limit rate in 18 digits, 0 means skip the checking
     */
    function setFluctuationLimitRatio(Decimal.decimal memory _fluctuationLimitRatio) public onlyOwner {
        fluctuationLimitRatio = _fluctuationLimitRatio;
    }

    /**
     * @notice set time interval for twap calculation, default is 1 hour
     * @dev only owner can call this function
     * @param _interval time interval in seconds
     */
    function setSpotPriceTwapInterval(uint256 _interval) external onlyOwner {
        require(_interval != 0, "can not set interval to 0");
        spotPriceTwapInterval = _interval;
    }

    /**
     * @notice set `open` flag. Amm is open to trade if `open` is true. Default is false.
     * @dev only owner can call this function
     * @param _open open to trade is true, otherwise is false.
     */
    function setOpen(bool _open) external onlyOwner {
        if (open == _open) return;

        open = _open;
        if (_open) {
            nextFundingTime = _blockTimestamp().add(fundingPeriod).div(1 hours).mul(1 hours);
        }
    }

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

    /**
     * @notice set new price adjust ratio
     * @dev only owner can call
     * @param _priceAdjustRatio new price adjust spread in 18 digits
     */
    function setPriceAdjustRatio(Decimal.decimal memory _priceAdjustRatio) public onlyOwner {
        require(_priceAdjustRatio.cmp(Decimal.one()) <= 0, "invalid ratio");
        priceAdjustRatio = _priceAdjustRatio;
    }

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

    /**
     * @notice set price feed address
     * @param _priceFeed new price feed address
     */
    function setPriceFeed(address _priceFeed) public override onlyOwner {
        require(_priceFeed != address(0), "invalid address");
        priceFeed = IPriceFeed(_priceFeed);
    }

    //
    // VIEW FUNCTIONS
    //

    /**
     * @notice get input twap amount.
     * returns how many base asset you will get with the input quote amount based on twap price.
     * @param _dir ADD_TO_AMM for long, REMOVE_FROM_AMM for short.
     * @param _quoteAssetAmount quote asset amount
     * @return base asset amount
     */
    function getInputTwap(Dir _dir, Decimal.decimal memory _quoteAssetAmount)
        public
        view
        override
        returns (Decimal.decimal memory)
    {
        return implGetInputAssetTwapPrice(_dir, _quoteAssetAmount, QuoteAssetDir.QUOTE_IN, 15 minutes);
    }

    /**
     * @notice get output twap amount.
     * return how many quote asset you will get with the input base amount on twap price.
     * @param _dir ADD_TO_AMM for short, REMOVE_FROM_AMM for long, opposite direction from `getInputTwap`.
     * @param _baseAssetAmount base asset amount
     * @return quote asset amount
     */
    function getOutputTwap(Dir _dir, Decimal.decimal memory _baseAssetAmount)
        public
        view
        override
        returns (Decimal.decimal memory)
    {
        return implGetInputAssetTwapPrice(_dir, _baseAssetAmount, QuoteAssetDir.QUOTE_OUT, 15 minutes);
    }

    /**
     * @notice get input amount. returns how many base asset you will get with the input quote amount.
     * @param _dir ADD_TO_AMM for long, REMOVE_FROM_AMM for short.
     * @param _quoteAssetAmount quote asset amount
     * @return base asset amount
     */
    function getInputPrice(Dir _dir, Decimal.decimal memory _quoteAssetAmount)
        public
        view
        override
        returns (Decimal.decimal memory)
    {
        return getInputPriceWithReserves(_dir, _quoteAssetAmount, quoteAssetReserve, baseAssetReserve);
    }

    /**
     * @notice get output price. return how many quote asset you will get with the input base amount
     * @param _dir ADD_TO_AMM for short, REMOVE_FROM_AMM for long, opposite direction from `getInput`.
     * @param _baseAssetAmount base asset amount
     * @return quote asset amount
     */
    function getOutputPrice(Dir _dir, Decimal.decimal memory _baseAssetAmount)
        public
        view
        override
        returns (Decimal.decimal memory)
    {
        return getOutputPriceWithReserves(_dir, _baseAssetAmount, quoteAssetReserve, baseAssetReserve);
    }

    /**
     * @notice get underlying price provided by oracle
     * @return underlying price
     */
    function getUnderlyingPrice() public view returns (Decimal.decimal memory) {
        return Decimal.decimal(priceFeed.getPrice(priceFeedKey));
    }

    /**
     * @notice get underlying twap price provided by oracle
     * @return underlying price
     */
    function getUnderlyingTwapPrice(uint256 _intervalInSeconds) public view returns (Decimal.decimal memory) {
        return Decimal.decimal(priceFeed.getTwapPrice(priceFeedKey, _intervalInSeconds));
    }

    /**
     * @notice get spot price based on current quote/base asset reserve.
     * @return spot price
     */
    function getSpotPrice() public view override returns (Decimal.decimal memory) {
        return quoteAssetReserve.divD(baseAssetReserve);
    }

    /**
     * @notice get twap price
     */
    function getTwapPrice(uint256 _intervalInSeconds) public view returns (Decimal.decimal memory) {
        return implGetReserveTwapPrice(_intervalInSeconds);
    }

    /**
     * @notice get current quote/base asset reserve.
     * @return (quote asset reserve, base asset reserve)
     */
    function getReserve() external view override returns (Decimal.decimal memory, Decimal.decimal memory) {
        return (quoteAssetReserve, baseAssetReserve);
    }

    //@audit - no one use this anymore, can be remove (@wraecca).
    // If we remove this, we should make reserveSnapshots private.
    // If we need reserveSnapshots, should keep this. (@Kimi)
    function getSnapshotLen() external view returns (uint256) {
        return reserveSnapshots.length;
    }

    function getLiquidityHistoryLength() external view override returns (uint256) {
        return liquidityChangedSnapshots.length;
    }

    function getCumulativeNotional() external view override returns (SignedDecimal.signedDecimal memory) {
        return cumulativeNotional;
    }

    function getLatestLiquidityChangedSnapshots() public view returns (LiquidityChangedSnapshot memory) {
        return liquidityChangedSnapshots[liquidityChangedSnapshots.length.sub(1)];
    }

    function getLiquidityChangedSnapshots(uint256 i) external view override returns (LiquidityChangedSnapshot memory) {
        require(i < liquidityChangedSnapshots.length, "incorrect index");
        return liquidityChangedSnapshots[i];
    }

    function getSettlementPrice() external view override returns (Decimal.decimal memory) {
        return settlementPrice;
    }

    function getBaseAssetDeltaThisFundingPeriod() external view override returns (SignedDecimal.signedDecimal memory) {
        return baseAssetDeltaThisFundingPeriod;
    }

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

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

    function getPositionSize() external view override returns (Decimal.decimal memory, Decimal.decimal memory) {
        return (longPositionSize, shortPositionSize);
    }

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

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

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

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

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

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

        return baseAssetBought;
    }

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

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

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

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

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

        return quoteAssetSold;
    }

    //
    // INTERNAL FUNCTIONS
    //
    // update funding rate = premiumFraction / twapIndexPrice
    function updateFundingRate(
        SignedDecimal.signedDecimal memory _premiumFraction,
        Decimal.decimal memory _underlyingPrice
    ) private {
        fundingRate = _premiumFraction.divD(_underlyingPrice);
        emit FundingRateUpdated(fundingRate.toInt(), _underlyingPrice.toUint());
    }

    function addReserveSnapshot() internal {
        uint256 currentBlock = _blockNumber();
        ReserveSnapshot storage latestSnapshot = reserveSnapshots[reserveSnapshots.length - 1];
        // update values in snapshot if in the same block
        if (currentBlock == latestSnapshot.blockNumber) {
            latestSnapshot.quoteAssetReserve = quoteAssetReserve;
            latestSnapshot.baseAssetReserve = baseAssetReserve;
        } else {
            reserveSnapshots.push(
                ReserveSnapshot(quoteAssetReserve, baseAssetReserve, _blockTimestamp(), currentBlock)
            );
        }
        emit ReserveSnapshotted(quoteAssetReserve.toUint(), baseAssetReserve.toUint(), _blockTimestamp());
    }

    function implSwapOutput(
        Dir _dir,
        Decimal.decimal memory _baseAssetAmount,
        Decimal.decimal memory _quoteAssetAmountLimit,
        bool _skipFluctuationCheck
    ) internal returns (Decimal.decimal memory) {
        if (_baseAssetAmount.toUint() == 0) {
            return Decimal.zero();
        }
        if (_dir == Dir.REMOVE_FROM_AMM) {
            require(baseAssetReserve.mulD(tradeLimitRatio).toUint() >= _baseAssetAmount.toUint(), "over trading limit");
            shortPositionSize = shortPositionSize.subD(_baseAssetAmount);
        } else {
            longPositionSize = longPositionSize.subD(_baseAssetAmount);
        }

        Decimal.decimal memory quoteAssetAmount = getOutputPrice(_dir, _baseAssetAmount);
        // If SHORT, exchanged quote amount should be less than _quoteAssetAmountLimit,
        // otherwise(LONG), exchanged base amount should be more than _quoteAssetAmountLimit.
        // In the SHORT case, more quote assets means more payment so should not be more than _quoteAssetAmountLimit
        if (_quoteAssetAmountLimit.toUint() != 0) {
            if (_dir == Dir.ADD_TO_AMM) {
                // SHORT
                require(quoteAssetAmount.toUint() >= _quoteAssetAmountLimit.toUint(), "Less than minimal quote token");
            } else {
                // LONG
                require(quoteAssetAmount.toUint() <= _quoteAssetAmountLimit.toUint(), "More than maximal quote token");
            }
        }

        // If the price impact of one single tx is larger than priceFluctuation, skip the check
        // only for liquidate()
        if (!_skipFluctuationCheck) {
            _skipFluctuationCheck = isSingleTxOverFluctuation(_dir, quoteAssetAmount, _baseAssetAmount);
        }

        updateReserve(
            _dir == Dir.ADD_TO_AMM ? Dir.REMOVE_FROM_AMM : Dir.ADD_TO_AMM,
            quoteAssetAmount,
            _baseAssetAmount,
            _skipFluctuationCheck
        );

        emit SwapOutput(_dir, quoteAssetAmount.toUint(), _baseAssetAmount.toUint());
        return quoteAssetAmount;
    }

    function updateReserve(
        Dir _dir,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _baseAssetAmount,
        bool _skipFluctuationCheck
    ) internal {
        if (_dir == Dir.ADD_TO_AMM) {
            quoteAssetReserve = quoteAssetReserve.addD(_quoteAssetAmount);
            baseAssetReserve = baseAssetReserve.subD(_baseAssetAmount);
            baseAssetDeltaThisFundingPeriod = baseAssetDeltaThisFundingPeriod.subD(_baseAssetAmount);
            totalPositionSize = totalPositionSize.addD(_baseAssetAmount);
            cumulativeNotional = cumulativeNotional.addD(_quoteAssetAmount);
        } else {
            quoteAssetReserve = quoteAssetReserve.subD(_quoteAssetAmount);
            baseAssetReserve = baseAssetReserve.addD(_baseAssetAmount);
            baseAssetDeltaThisFundingPeriod = baseAssetDeltaThisFundingPeriod.addD(_baseAssetAmount);
            totalPositionSize = totalPositionSize.subD(_baseAssetAmount);
            cumulativeNotional = cumulativeNotional.subD(_quoteAssetAmount);
        }

        // check if it's over fluctuationLimitRatio
        if (!_skipFluctuationCheck) {
            checkFluctuationLimit(fluctuationLimitRatio);
        }

        // addReserveSnapshot must be after checking price fluctuation
        addReserveSnapshot();
    }

    function implGetInputAssetTwapPrice(
        Dir _dir,
        Decimal.decimal memory _assetAmount,
        QuoteAssetDir _inOut,
        uint256 _interval
    ) internal view returns (Decimal.decimal memory) {
        TwapPriceCalcParams memory params;
        params.opt = TwapCalcOption.INPUT_ASSET;
        params.snapshotIndex = reserveSnapshots.length.sub(1);
        params.asset.dir = _dir;
        params.asset.assetAmount = _assetAmount;
        params.asset.inOrOut = _inOut;
        return calcTwap(params, _interval);
    }

    function implGetReserveTwapPrice(uint256 _interval) internal view returns (Decimal.decimal memory) {
        TwapPriceCalcParams memory params;
        params.opt = TwapCalcOption.RESERVE_ASSET;
        params.snapshotIndex = reserveSnapshots.length.sub(1);
        return calcTwap(params, _interval);
    }

    function calcTwap(TwapPriceCalcParams memory _params, uint256 _interval)
        internal
        view
        returns (Decimal.decimal memory)
    {
        Decimal.decimal memory currentPrice = getPriceWithSpecificSnapshot(_params);
        if (_interval == 0) {
            return currentPrice;
        }

        uint256 baseTimestamp = _blockTimestamp().sub(_interval);
        ReserveSnapshot memory currentSnapshot = reserveSnapshots[_params.snapshotIndex];
        // return the latest snapshot price directly
        // if only one snapshot or the timestamp of latest snapshot is earlier than asking for
        if (reserveSnapshots.length == 1 || currentSnapshot.timestamp <= baseTimestamp) {
            return currentPrice;
        }

        uint256 previousTimestamp = currentSnapshot.timestamp;
        uint256 period = _blockTimestamp().sub(previousTimestamp);
        Decimal.decimal memory weightedPrice = currentPrice.mulScalar(period);
        while (true) {
            // if snapshot history is too short
            if (_params.snapshotIndex == 0) {
                return weightedPrice.divScalar(period);
            }

            _params.snapshotIndex = _params.snapshotIndex.sub(1);
            currentSnapshot = reserveSnapshots[_params.snapshotIndex];
            currentPrice = getPriceWithSpecificSnapshot(_params);

            // check if current round timestamp is earlier than target timestamp
            if (currentSnapshot.timestamp <= baseTimestamp) {
                // weighted time period will be (target timestamp - previous timestamp). For example,
                // now is 1000, _interval is 100, then target timestamp is 900. If timestamp of current round is 970,
                // and timestamp of NEXT round is 880, then the weighted time period will be (970 - 900) = 70,
                // instead of (970 - 880)
                weightedPrice = weightedPrice.addD(currentPrice.mulScalar(previousTimestamp.sub(baseTimestamp)));
                break;
            }

            uint256 timeFraction = previousTimestamp.sub(currentSnapshot.timestamp);
            weightedPrice = weightedPrice.addD(currentPrice.mulScalar(timeFraction));
            period = period.add(timeFraction);
            previousTimestamp = currentSnapshot.timestamp;
        }
        return weightedPrice.divScalar(_interval);
    }

    function getPriceWithSpecificSnapshot(TwapPriceCalcParams memory params)
        internal
        view
        virtual
        returns (Decimal.decimal memory)
    {
        ReserveSnapshot memory snapshot = reserveSnapshots[params.snapshotIndex];

        // RESERVE_ASSET means price comes from quoteAssetReserve/baseAssetReserve
        // INPUT_ASSET means getInput/Output price with snapshot's reserve
        if (params.opt == TwapCalcOption.RESERVE_ASSET) {
            return snapshot.quoteAssetReserve.divD(snapshot.baseAssetReserve);
        } else if (params.opt == TwapCalcOption.INPUT_ASSET) {
            if (params.asset.assetAmount.toUint() == 0) {
                return Decimal.zero();
            }
            if (params.asset.inOrOut == QuoteAssetDir.QUOTE_IN) {
                return
                    getInputPriceWithReserves(
                        params.asset.dir,
                        params.asset.assetAmount,
                        snapshot.quoteAssetReserve,
                        snapshot.baseAssetReserve
                    );
            } else if (params.asset.inOrOut == QuoteAssetDir.QUOTE_OUT) {
                return
                    getOutputPriceWithReserves(
                        params.asset.dir,
                        params.asset.assetAmount,
                        snapshot.quoteAssetReserve,
                        snapshot.baseAssetReserve
                    );
            }
        }
        revert("not supported option");
    }

    function isSingleTxOverFluctuation(
        Dir _dir,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _baseAssetAmount
    ) internal view returns (bool) {
        Decimal.decimal memory priceAfterReserveUpdated =
            (_dir == Dir.ADD_TO_AMM)
                ? quoteAssetReserve.subD(_quoteAssetAmount).divD(baseAssetReserve.addD(_baseAssetAmount))
                : quoteAssetReserve.addD(_quoteAssetAmount).divD(baseAssetReserve.subD(_baseAssetAmount));
        return
            isOverFluctuationLimit(
                priceAfterReserveUpdated,
                fluctuationLimitRatio,
                reserveSnapshots[reserveSnapshots.length.sub(1)]
            );
    }

    function checkFluctuationLimit(Decimal.decimal memory _fluctuationLimitRatio) internal view {
        // Skip the check if the limit is 0
        if (_fluctuationLimitRatio.toUint() > 0) {
            uint256 len = reserveSnapshots.length;
            ReserveSnapshot memory latestSnapshot = reserveSnapshots[len - 1];

            // if the latest snapshot is the same as current block, get the previous one
            if (latestSnapshot.blockNumber == _blockNumber() && len > 1) {
                latestSnapshot = reserveSnapshots[len - 2];
            }

            require(
                !isOverFluctuationLimit(
                    quoteAssetReserve.divD(baseAssetReserve),
                    _fluctuationLimitRatio,
                    latestSnapshot
                ),
                "price is over fluctuation limit"
            );
        }
    }

    function checkLiquidityMultiplierLimit(
        SignedDecimal.signedDecimal memory _positionSize,
        Decimal.decimal memory _liquidityMultiplier
    ) internal view {
        // have lower bound when position size is long
        if (_positionSize.toInt() > 0) {
            Decimal.decimal memory liquidityMultiplierLowerBound =
                _positionSize
                    .addD(Decimal.decimal(MARGIN_FOR_LIQUIDITY_MIGRATION_ROUNDING))
                    .divD(baseAssetReserve)
                    .abs();
            require(_liquidityMultiplier.cmp(liquidityMultiplierLowerBound) >= 0, "illegal liquidity multiplier");
        }
    }

    function isOverFluctuationLimit(
        Decimal.decimal memory _price,
        Decimal.decimal memory _fluctuationLimitRatio,
        ReserveSnapshot memory _snapshot
    ) internal pure returns (bool) {
        Decimal.decimal memory lastPrice = _snapshot.quoteAssetReserve.divD(_snapshot.baseAssetReserve);
        Decimal.decimal memory upperLimit = lastPrice.mulD(Decimal.one().addD(_fluctuationLimitRatio));
        Decimal.decimal memory lowerLimit = lastPrice.mulD(Decimal.one().subD(_fluctuationLimitRatio));

        if (_price.cmp(upperLimit) <= 0 && _price.cmp(lowerLimit) >= 0) {
            return false;
        }
        return true;
    }

    function moveAMMPriceToOracle(uint256 _oraclePrice, bytes32 _priceFeedKey) public override {
        require(owner() == _msgSender() || address(priceFeed) == _msgSender(), "illegal operator");
        if (!open || priceAdjustRatio.toUint() == 0) return;
        require(_oraclePrice > 0, "invalid oracle price");
        require(priceFeedKey == _priceFeedKey, "illegal price feed key");
        Decimal.decimal memory oraclePrice = Decimal.decimal(_oraclePrice);
        Decimal.decimal memory invariant = quoteAssetReserve.mulD(baseAssetReserve);
        Decimal.decimal memory AMMPrice = quoteAssetReserve.divD(baseAssetReserve);
        if (AMMPrice.cmp(oraclePrice) == 0) {
            CFDVault.modifyLiquidity();
            return;
        }
        Decimal.decimal memory adjustPrice =
            MixedDecimal
                .fromDecimal(AMMPrice)
                .addD(MixedDecimal.fromDecimal(oraclePrice).subD(AMMPrice).mulD(priceAdjustRatio))
                .abs();

        // baseAssetReserve * oraclePrice * baseAssetReserve = invariant
        uint256 basePow = invariant.divD(adjustPrice).toUint().mul(Decimal.one().toUint());
        Decimal.decimal memory _baseAssetReserve = Decimal.decimal(basePow.sqrt());
        Decimal.decimal memory _quoteAssetReserve = invariant.divD(_baseAssetReserve);

        SignedDecimal.signedDecimal memory MMPNL = getMMUnrealizedPNL(_baseAssetReserve, _quoteAssetReserve);
        SignedDecimal.signedDecimal memory MMLiquidity = CFD.getMMLiquidity(address(this));
        // negative means MM can't pay for this price movement
        if (MMPNL.addD(MMLiquidity).isNegative()) {
            emit MoveAMMPrice(
                AMMPrice.toUint(),
                _oraclePrice,
                adjustPrice.toUint(),
                MMLiquidity.toInt(),
                MMPNL.toInt(),
                false
            );
        } else {
            baseAssetReserve = _baseAssetReserve;
            quoteAssetReserve = _quoteAssetReserve;
            lastMoveAmmPriceTime = _blockTimestamp();

            // addReserveSnapshot must be after checking price fluctuation
            addReserveSnapshot();
            CFDVault.modifyLiquidity();

            emit MoveAMMPrice(
                AMMPrice.toUint(),
                _oraclePrice,
                adjustPrice.toUint(),
                MMLiquidity.toInt(),
                MMPNL.toInt(),
                true
            );
        }
    }

    /**
     * @notice get MM unrealized PNL
     */
    function getMMUnrealizedPNL(Decimal.decimal memory _baseAssetReserve, Decimal.decimal memory _quoteAssetReserve)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        Decimal.decimal memory invariant = _baseAssetReserve.mulD(_quoteAssetReserve);
        // close all long position
        Decimal.decimal memory unrealizedLongQuoteAssetAmout =
            getOutputPriceWithReserves(Dir.ADD_TO_AMM, longPositionSize, _quoteAssetReserve, _baseAssetReserve);
        _baseAssetReserve = _baseAssetReserve.addD(longPositionSize);
        _quoteAssetReserve = invariant.divD(_baseAssetReserve);
        // close all short position
        Decimal.decimal memory unrealizedShortQuoteAssetAmout =
            getOutputPriceWithReserves(Dir.REMOVE_FROM_AMM, shortPositionSize, _quoteAssetReserve, _baseAssetReserve);

        // MMUnrealizedPNL = - (unrealizedLongQuoteAssetAmout - longQuoteAssetCostAmout + shortQuoteAssetCostAmout - unrealizedShortQuoteAssetAmout)
        // MMUnrealizedPNL = longQuoteAssetCostAmout - shortQuoteAssetCostAmout + unrealizedShortQuoteAssetAmout - unrealizedLongQuoteAssetAmout
        // cumulativeNotional = longQuoteAssetCostAmout - shortQuoteAssetCostAmout
        return cumulativeNotional.addD(unrealizedShortQuoteAssetAmout).subD(unrealizedLongQuoteAssetAmout);
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxHoldingBaseAsset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"openInterestNotionalCap","type":"uint256"}],"name":"CapChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int256","name":"rate","type":"int256"},{"indexed":false,"internalType":"uint256","name":"underlyingPrice","type":"uint256"}],"name":"FundingRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"quoteReserve","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseReserve","type":"uint256"},{"indexed":false,"internalType":"int256","name":"cumulativeNotional","type":"int256"}],"name":"LiquidityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ammPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oraclePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustPrice","type":"uint256"},{"indexed":false,"internalType":"int256","name":"MMLiquidity","type":"int256"},{"indexed":false,"internalType":"int256","name":"MMPNL","type":"int256"},{"indexed":false,"internalType":"bool","name":"moved","type":"bool"}],"name":"MoveAMMPrice","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"quoteAssetReserve","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAssetReserve","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ReserveSnapshotted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementPrice","type":"uint256"}],"name":"Shutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IExchange.Dir","name":"dir","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"quoteAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAssetAmount","type":"uint256"}],"name":"SwapInput","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IExchange.Dir","name":"dir","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"quoteAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAssetAmount","type":"uint256"}],"name":"SwapOutput","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CFD","outputs":[{"internalType":"contract ICFD","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CFDVault","outputs":[{"internalType":"contract ICFDVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseAssetReserve","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"_baseAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_fromQuoteReserve","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_fromBaseReserve","type":"tuple"}],"name":"calcBaseAssetAfterLiquidityMigration","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"}],"name":"calcFee","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fluctuationLimitRatio","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingBufferPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingRate","outputs":[{"internalType":"int256","name":"d","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseAssetDeltaThisFundingPeriod","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCumulativeNotional","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"}],"name":"getInputPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetPoolAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetPoolAmount","type":"tuple"}],"name":"getInputPriceWithReserves","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"}],"name":"getInputTwap","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestLiquidityChangedSnapshots","outputs":[{"components":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"cumulativeNotional","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"quoteAssetReserve","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"baseAssetReserve","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"totalPositionSize","type":"tuple"}],"internalType":"struct IExchange.LiquidityChangedSnapshot","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"getLiquidityChangedSnapshots","outputs":[{"components":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"cumulativeNotional","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"quoteAssetReserve","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"baseAssetReserve","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"totalPositionSize","type":"tuple"}],"internalType":"struct IExchange.LiquidityChangedSnapshot","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLiquidityHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetReserve","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetReserve","type":"tuple"}],"name":"getMMUnrealizedPNL","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxHoldingBaseAsset","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpenInterestNotionalCap","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmount","type":"tuple"}],"name":"getOutputPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetPoolAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetPoolAmount","type":"tuple"}],"name":"getOutputPriceWithReserves","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmount","type":"tuple"}],"name":"getOutputTwap","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPositionSize","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserve","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSettlementPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSnapshotLen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSpotPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_intervalInSeconds","type":"uint256"}],"name":"getTwapPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnderlyingPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_intervalInSeconds","type":"uint256"}],"name":"getUnderlyingTwapPrice","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quoteAssetReserve","type":"uint256"},{"internalType":"uint256","name":"_baseAssetReserve","type":"uint256"},{"internalType":"uint256","name":"_tradeLimitRatio","type":"uint256"},{"internalType":"uint256","name":"_fundingPeriod","type":"uint256"},{"internalType":"contract IPriceFeed","name":"_priceFeed","type":"address"},{"internalType":"contract ICFD","name":"_CFD","type":"address"},{"internalType":"contract ICFDVault","name":"_CFDVault","type":"address"},{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"},{"internalType":"address","name":"_quoteAsset","type":"address"},{"internalType":"uint256","name":"_fluctuationLimitRatio","type":"uint256"},{"internalType":"uint256","name":"_spreadRatio","type":"uint256"},{"internalType":"uint256","name":"_priceAdjustRatio","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastMoveAmmPriceTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"longPositionSize","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_liquidityMultiplier","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_fluctuationLimitRatio","type":"tuple"}],"name":"migrateLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oraclePrice","type":"uint256"},{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"}],"name":"moveAMMPriceToOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextFundingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"open","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceAdjustRatio","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteAsset","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteAssetReserve","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveSnapshots","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"quoteAssetReserve","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"baseAssetReserve","type":"tuple"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_maxHoldingBaseAsset","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_openInterestNotionalCap","type":"tuple"}],"name":"setCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_counterParty","type":"address"}],"name":"setCounterParty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_fluctuationLimitRatio","type":"tuple"}],"name":"setFluctuationLimitRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_open","type":"bool"}],"name":"setOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_priceAdjustRatio","type":"tuple"}],"name":"setPriceAdjustRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceFeed","type":"address"}],"name":"setPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_interval","type":"uint256"}],"name":"setSpotPriceTwapInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_spreadRatio","type":"tuple"}],"name":"setSpreadRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleFunding","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shortPositionSize","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spotPriceTwapInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spreadRatio","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmountLimit","type":"tuple"}],"name":"swapInput","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IExchange.Dir","name":"_dir","type":"uint8"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmount","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmountLimit","type":"tuple"},{"internalType":"bool","name":"_skipFluctuationCheck","type":"bool"}],"name":"swapOutput","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPositionSize","outputs":[{"internalType":"int256","name":"d","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeLimitRatio","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50615a6280620000216000396000f3fe608060405234801561001057600080fd5b506004361061046a5760003560e01c80636fdca5e01161024c578063c9566fcc11610146578063ec2c0e63116100c3578063f2fde38b11610087578063f2fde38b146108bc578063fc0e74d1146108cf578063fca3b5aa146108d7578063fcfff16f146108ea578063fdf262b7146108f25761046a565b8063ec2c0e631461087e578063ed83d79c14610886578063eebd72e01461088e578063f1b5df86146108a1578063f1e28650146108b45761046a565b8063dd62ed3e1161010a578063dd62ed3e14610840578063e0037a6c14610853578063e1f1027f1461085b578063e4bc2eb91461086e578063e805d6fc146108765761046a565b8063c9566fcc14610802578063ca62270e1461080a578063da0c592714610812578063dc3184a014610825578063dc76fabc146108385761046a565b80638f40d932116101d45780639ffca62f116101985780639ffca62f146107ae578063a457c2d7146107c1578063a8f8be4e146107d4578063a9059cbb146107e7578063c2de442f146107fa5761046a565b80638f40d9321461076557806395d89b411461076d5780639bf5d1d4146107755780639dc29fac146107885780639ece77c81461079b5761046a565b8063724e78da1161021b578063724e78da14610727578063741bef1a1461073a57806374d7c62b14610742578063774810241461074a5780638da5cb5b1461075d5761046a565b80636fdca5e0146106f15780636febdd501461070457806370a082311461070c578063715018a61461071f5761046a565b806341d3c84c1161036857806352545410116102e55780635f1ba1fd116102a95780635f1ba1fd1461069d57806362267955146106a557806362e7a176146106b85780636316930e146106cb5780636fa42ede146106de5761046a565b8063525454101461066a5780635834db901461067257806358a4c3dc1461068557806359bf5d391461068d5780635ecd62ec146106955761046a565b80634894d1831161032c5780634894d183146106135780634c0de7b1146106265780634cb876f21461063c57806350799c8114610644578063524f15a1146106575761046a565b806341d3c84c146105de578063429f24bc146105e657806342b3198b146105ee578063468f02d2146105f65780634821e630146105fe5761046a565b806321e00985116103f6578063313ce567116103ba578063313ce5671461057d578063349532491461059257806339509351146105a557806340c10f19146105b857806340d71cd9146105cb5761046a565b806321e0098514610524578063237f17ee1461054757806323b872dd1461055a578063251bc11c1461056d57806329f9b17b146105755761046a565b8063113773941161043d57806311377394146104d757806318160ddd146104ec5780631b584d6c146104f45780631d3acb441461050957806320855f05146105115761046a565b806306fdde031461046f578063095ea7b31461048d5780630d451c8f146104ad5780630dd68c70146104c2575b600080fd5b6104776108fa565b6040516104849190614fa5565b60405180910390f35b6104a061049b366004614bed565b610990565b6040516104849190614f61565b6104b56109ae565b6040516104849190614f6c565b6104d56104d0366004614dbf565b6109b4565b005b6104df610a6a565b604051610484919061588a565b6104b5610a86565b6104fc610a8c565b604051610484919061585b565b6104b5610b14565b6104df61051f366004614dbf565b610b1a565b610537610532366004614e4f565b610be1565b60405161048494939291906158a4565b6104fc610555366004614e4f565b610c2f565b6104a0610568366004614bad565b610ccf565b6104b5610d57565b6104df610d5d565b610585610d79565b60405161048491906158ff565b6104df6105a0366004614e4f565b610d82565b6104a06105b3366004614bed565b610e21565b6104d56105c6366004614bed565b610e6f565b6104df6105d9366004614e00565b610edb565b6104b5610f8f565b6104b5610f95565b6104b5610f9b565b6104df610fa1565b61060661103e565b6040516104849190614f4d565b6104df610621366004614cd2565b61104d565b61062e611064565b604051610484929190615894565b6104b5611096565b6104df610652366004614d06565b61109c565b6104d5610665366004614da4565b6111dd565b6104df611218565b6104d5610680366004614d79565b611234565b6104b5611567565b61062e61156d565b61060661159f565b6104b56115ae565b6104df6106b3366004614d5e565b6115b4565b6104d56106c6366004614e4f565b61160a565b6104d56106d9366004614ea0565b611661565b6104df6106ec366004614cd2565b611a38565b6104d56106ff366004614c18565b611a4f565b6104b5611af7565b6104b561071a366004614b59565b611afd565b6104d5611b18565b6104d5610735366004614b59565b611b97565b610606611c14565b6104b5611c23565b6104d5610758366004614da4565b611c29565b610606611c99565b6104b5611ca8565b610477611cae565b6104df610783366004614d06565b611d0f565b6104d5610796366004614bed565b611dcf565b6104d56107a9366004614b59565b611e0e565b6104df6107bc366004614c34565b611e65565b6104a06107cf366004614bed565b6120ea565b6104d56107e2366004614da4565b612152565b6104a06107f5366004614bed565b61218d565b6104b56121a1565b6104b56121a7565b6104b56121ad565b6104df610820366004614cd2565b6121b3565b6104df610833366004614c79565b6121e5565b6104df61227c565b6104b561084e366004614b75565b6122b0565b6104b56122db565b6104df610869366004614cd2565b6122e1565b6104b5612313565b6104df612319565b6104df612335565b6104df612351565b6104d561089c366004614e7f565b6124d3565b6104df6108af366004614e4f565b612952565b6104b5612963565b6104d56108ca366004614b59565b612969565b6104d5612a20565b6104d56108e5366004614b59565b612c31565b6104a0612c88565b610606612c98565b609a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109865780601f1061095b57610100808354040283529160200191610986565b820191906000526020600020905b81548152906001019060200180831161096957829003601f168201915b5050505050905090565b60006109a461099d612ca7565b8484612cab565b5060015b92915050565b60df5490565b6109bc612ca7565b6033546001600160a01b039081169116146109f25760405162461bcd60e51b81526004016109e990615489565b60405180910390fd5b815160d6819055815160d75560408051602081019091529081527f7338f3784ceb8f9456bac0c4a69f1c6354dc325fa6455e3e3f6a8a9bf9249a7c90610a3790612d5f565b604080516020810190915260d7548152610a5090612d5f565b604051610a5e929190614f75565b60405180910390a15050565b610a726149af565b50604080516020810190915260d654815290565b60995490565b610a946149c2565b60d98054610aa3906001612d63565b81548110610aad57fe5b60009182526020918290206040805160a0810182526004909302909101805460808401908152835281518085018352600182015481528385015281518085018352600282015481528383015281519384019091526003015482526060810191909152905090565b60d35481565b610b226149af565b610b2a6149af565b610b348484612da5565b9050610b3e6149af565b604080516020810190915260ca548152610b5c906000908688611d0f565b604080516020810190915260ca548152909150610b7a908690612dcb565b9450610b868286612de8565b9350610b906149af565b604080516020810190915260cb548152610bae906001908789611d0f565b604080516020810190915260ce548152909150610bd7908390610bd19084612e05565b90612e74565b9695505050505050565b60df8181548110610bee57fe5b600091825260209182902060408051808501825260049093029091018054835281519384019091526001810154835260028101546003909101549193509084565b610c376149c2565b60d9548210610c585760405162461bcd60e51b81526004016109e9906152c2565b60d98281548110610c6557fe5b60009182526020918290206040805160a081018252600490930290910180546080840190815283528151808501835260018201548152838501528151808501835260028201548152838301528151938401909152600301548252606081019190915290505b919050565b6000610cdc848484612ed9565b610d4c84610ce8612ca7565b610d47856040518060600160405280602881526020016159e0602891396001600160a01b038a16600090815260986020526040812090610d26612ca7565b6001600160a01b031681526020810191909152604001600020549190612fee565b612cab565b5060015b9392505050565b60cb5481565b610d656149af565b50604080516020810190915260ce54815290565b609c5460ff1690565b610d8a6149af565b60408051602081019182905260e25460de54632885cf7d60e21b909352909182916001600160a01b03169063a2173df490610dc9908760248601614f75565b60206040518083038186803b158015610de157600080fd5b505afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190614e67565b905292915050565b60006109a4610e2e612ca7565b84610d478560986000610e3f612ca7565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061301a565b60e354600160a01b900460ff16610e985760405162461bcd60e51b81526004016109e9906155e0565b610ea0612ca7565b60e0546001600160a01b03908116911614610ecd5760405162461bcd60e51b81526004016109e9906154be565b610ed7828261303f565b5050565b610ee36149af565b610eec846130ff565b610ef7575082610d50565b600080610f0386612d5f565b13610f0f576000610f12565b60015b9050610f1c6149af565b610f3e82610f2b576001610f2e565b60005b610f3788613111565b8787611d0f565b9050610f486149af565b610f68610f6384610f5a576000610f5d565b60015b846122e1565b61313f565b9050610f8483610f7a57600019610f7d565b60015b82906131a3565b979650505050505050565b60cd5481565b60e45481565b60d95490565b610fa96149af565b60408051602081019182905260e25460de546331d98b3f60e01b909352909182916001600160a01b0316906331d98b3f90610fe79060248501614f6c565b60206040518083038186803b158015610fff57600080fd5b505afa158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190614e67565b9052905090565b60e3546001600160a01b031681565b6110556149af565b610d50838360006103846131bf565b61106c6149af565b6110746149af565b5050604080516020808201835260ca548252825190810190925260cb54825291565b60cc5481565b6110a46149af565b6110ad84612d5f565b6110c0576110b961323b565b90506111d5565b6000808660018111156110cf57fe5b1490506110da6149af565b6110e7610f638686612da5565b90506110f16149af565b6110f96149af565b6111016149af565b841561111857611111888a612dcb565b9150611125565b611122888a613256565b91505b61112e82612d5f565b61114a5760405162461bcd60e51b81526004016109e9906156bf565b6111548483613273565b92506111686111638489612e74565b613111565b90506111856111808361117a87613111565b906132de565b612d5f565b156111ce5784156111b1576040805160208101909152600181526111aa908290613256565b90506111ce565b6040805160208101909152600181526111cb908290612dcb565b90505b9450505050505b949350505050565b6111e5612ca7565b6033546001600160a01b039081169116146112125760405162461bcd60e51b81526004016109e990615489565b5160d455565b6112206149af565b50604080516020810190915260d754815290565b61123c612ca7565b6033546001600160a01b039081169116146112695760405162461bcd60e51b81526004016109e990615489565b61127461118061331c565b61128661118036859003850185614da4565b14156112a45760405162461bcd60e51b81526004016109e99061506a565b604080516020810190915260cc5481526112cc906112c736859003850185614da4565b613339565b604080516020810190915260c95481526112ef906112c736859003850185614da4565b61130661130136839003830183614da4565b6133bf565b61130e6149af565b50604080516020810190915260d15481526113276149af565b50604080516020810190915260d25481526113406149af565b50604080516020810190915260cc54815261136a61136336879003870187614da4565b8490612da5565b5160d15561138761138036879003870187614da4565b8390612da5565b5160d255604080516020810190915260c95481526113be90600019906113b8906113b190836131a3565b8686610edb565b906131a3565b5160c9556113cd818484610edb565b5160cc556113db838361350f565b6040805160a08101825260ce5460808201908152815281516020808201845260d1805483528184019283528451808301865260d25481528486019081528551808401875260cc5481526060860190815260d980546001810182556000919091529551517fcc6782fd46dd71c5f512301ab049782450b4eaf79fdac5443d93d274d39167866004909702968701559351517fcc6782fd46dd71c5f512301ab049782450b4eaf79fdac5443d93d274d391678786015551517fcc6782fd46dd71c5f512301ab049782450b4eaf79fdac5443d93d274d39167888501559151517fcc6782fd46dd71c5f512301ab049782450b4eaf79fdac5443d93d274d3916789909301929092558251918201909252905481527feba648fc83514e32ba75e27696ee5fa3610ebc7a77460a3ac3e8724ffa1be4cc9061151790612d5f565b604080516020810190915260d254815261153090612d5f565b604080516020810190915260ce54815261154990612d5f565b604051611558939291906158bf565b60405180910390a15050505050565b60de5481565b6115756149af565b61157d6149af565b5050604080516020808201835260d1548252825190810190925260d254825291565b60e0546001600160a01b031681565b60da5481565b6115bc6149af565b6115ce61118036849003840184614da4565b6115e1576115da61323b565b9050610cca565b604080516020810190915260d45481526109a89061160436859003850185614da4565b90612da5565b611612612ca7565b6033546001600160a01b0390811691161461163f5760405162461bcd60e51b81526004016109e990615489565b8061165c5760405162461bcd60e51b81526004016109e9906151b0565b60da55565b600054610100900460ff168061167a575061167a61363d565b80611688575060005460ff16155b6116a45760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff161580156116cf576000805460ff1961ff0019909116610100171660011790555b8c158015906116dd57508a15155b80156116e857508b15155b80156116f357508915155b801561170757506001600160a01b03891615155b801561171b57506001600160a01b03881615155b801561172f57506001600160a01b03871615155b801561174357506001600160a01b03851615155b61175f5760405162461bcd60e51b81526004016109e990615756565b611767613643565b6117c16040518060400160405280601b81526020017f4d4d204c69717569646974792050726f766964657220546f6b656e00000000008152506040518060400160405280600381526020016204d4c560ec1b8152506136d5565b6040805160208082018352908f905260d18f9055815180820183528e905260d28e9055815180820183528d905260d08d90558151808201835285905260d48590558151808201835284905260d5849055815190810190915284905260d384905560db8a90556118318a600261376b565b60dc55610e1060da5560de86905560e180546001600160a01b038088166001600160a01b03199283161790925560e280548c841690831617905560e380548b841690831617905560e08054928a169290911691909117905561189161331c565b5160d855604080516080810190915260d990806118ac61323b565b8152604080516020818101835260d1548252808401919091528151908101825260d2548152908201526060016118e061323b565b9052815460018181018455600093845260209384902083515160049093020191825583830151519082015560408083015151600283015560609092015151600390910155805160a08101825260d1546080820190815281528151808401835260d25481529281019290925260df919081016119596137ad565b81526020016119666137b1565b9052815460018181018455600093845260209384902083515160049093020191825583830151519082015560408083015160028301556060909201516003909101558051918201905260d15481527f3a3348362552c3897fd1f06a3233519ebd8bd76ad6e99a418a9741155fe90515906119df90612d5f565b604080516020810190915260d25481526119f890612d5f565b611a006137ad565b604051611a0f939291906158bf565b60405180910390a18015611a29576000805461ff00191690555b50505050505050505050505050565b611a406149af565b610d50838360016103846131bf565b611a57612ca7565b6033546001600160a01b03908116911614611a845760405162461bcd60e51b81526004016109e990615489565b60e35460ff600160a01b9091041615158115151415611aa257611af4565b60e3805482158015600160a01b0260ff60a01b1990921691909117909155611af457611af0610e10611aea610e10611ae460db54611ade6137ad565b9061301a565b9061376b565b906137b5565b60dd555b50565b60d45481565b6001600160a01b031660009081526097602052604090205490565b611b20612ca7565b6033546001600160a01b03908116911614611b4d5760405162461bcd60e51b81526004016109e990615489565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b611b9f612ca7565b6033546001600160a01b03908116911614611bcc5760405162461bcd60e51b81526004016109e990615489565b6001600160a01b038116611bf25760405162461bcd60e51b81526004016109e9906152eb565b60e280546001600160a01b0319166001600160a01b0392909216919091179055565b60e2546001600160a01b031681565b60db5481565b611c31612ca7565b6033546001600160a01b03908116911614611c5e5760405162461bcd60e51b81526004016109e990615489565b6000611c72611c6b61331c565b83906137ef565b60000b1315611c935760405162461bcd60e51b81526004016109e9906155b9565b5160d555565b6033546001600160a01b031690565b60d05481565b609b8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109865780601f1061095b57610100808354040283529160200191610986565b611d176149af565b611d2084612d5f565b611d2c576110b961323b565b600080866001811115611d3b57fe5b149050611d466149af565b611d53610f638686612da5565b9050611d5d6149af565b611d656149af565b611d6d6149af565b8415611d8457611d7d878a612dcb565b9150611d91565b611d8e878a613256565b91505b611d9a82612d5f565b611db65760405162461bcd60e51b81526004016109e99061503b565b611dc08483613273565b9250611168611163848a612e74565b611dd7612ca7565b60e0546001600160a01b03908116911614611e045760405162461bcd60e51b81526004016109e9906154be565b610ed78282613820565b611e16612ca7565b6033546001600160a01b03908116911614611e435760405162461bcd60e51b81526004016109e990615489565b60e380546001600160a01b0319166001600160a01b0392909216919091179055565b611e6d6149af565b60e354600160a01b900460ff16611e965760405162461bcd60e51b81526004016109e9906155e0565b611e9e612ca7565b60e3546001600160a01b03908116911614611ecb5760405162461bcd60e51b81526004016109e9906151e7565b611edd61118036859003850185614da4565b611ef057611ee961323b565b9050610d50565b6001846001811115611efe57fe5b1415611f5e57611f1661118036859003850185614da4565b604080516020808201835260d0548252825190810190925260d1548252611f409161118091612da5565b1015611f5e5760405162461bcd60e51b81526004016109e99061525f565b611f666149af565b611f798561086936879003870187614da4565b9050611f8d61118036859003850185614da4565b1561201d576000856001811115611fa057fe5b1415611fe457611fb861118036859003850185614da4565b611fc182612d5f565b1015611fdf5760405162461bcd60e51b81526004016109e990615452565b61201d565b611ff661118036859003850185614da4565b611fff82612d5f565b111561201d5760405162461bcd60e51b81526004016109e990615644565b600085600181111561202b57fe5b141561205457604080516020810190915260ca54815261204b9082612dcb565b5160ca55612073565b604080516020810190915260cb54815261206e9082612dcb565b5160cb555b61208e8561208636879003870187614da4565b8360006138f6565b7fae6a2b946841d9afc0e1e19a94ae4af26f01125b87b5095bbfb177a9741a2ede856120c261118036889003880188614da4565b6120cb84612d5f565b6040516120da93929190614f83565b60405180910390a1949350505050565b60006109a46120f7612ca7565b84610d4785604051806060016040528060258152602001615a086025913960986000612121612ca7565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612fee565b61215a612ca7565b6033546001600160a01b039081169116146121875760405162461bcd60e51b81526004016109e990615489565b5160d355565b60006109a461219a612ca7565b8484612ed9565b60dc5481565b60d25481565b60ca5481565b6121bb6149af565b604080516020808201835260d1548252825190810190925260d2548252610d509185918591611d0f565b6121ed6149af565b60e354600160a01b900460ff166122165760405162461bcd60e51b81526004016109e9906155e0565b61221e612ca7565b60e3546001600160a01b0390811691161461224b5760405162461bcd60e51b81526004016109e9906151e7565b6122738561225e36879003870187614da4565b61226d36879003870187614da4565b85613a68565b95945050505050565b6122846149af565b604080516020808201835260d2548252825190810190925260d15482526122ab9190612de8565b905090565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b60dd5481565b6122e96149af565b604080516020808201835260d1548252825190810190925260d2548252610d50918591859161109c565b60d15481565b6123216149af565b50604080516020810190915260c954815290565b61233d6149af565b50604080516020810190915260cf54815290565b6123596149af565b60e354600160a01b900460ff166123825760405162461bcd60e51b81526004016109e9906155e0565b61238a612ca7565b60e3546001600160a01b039081169116146123b75760405162461bcd60e51b81526004016109e9906151e7565b60dd546123c26137ad565b10156123e05760405162461bcd60e51b81526004016109e9906156ef565b6123e86149af565b6123f061323b565b90506123fa6149af565b61240560da54610d82565b905060dd5461242160db5460e45461301a90919063ffffffff16565b10156124695761242f6149af565b61244182610bd1610f6360da54612952565b90506124656201518061245f60db5484613c5690919063ffffffff16565b90613cb3565b9250505b6124738282613ccf565b600061248360dc54611ade6137ad565b905060006124aa610e10611aea610e10611ae460db5460dd5461301a90919063ffffffff16565b90508181116124b957816124bb565b805b60dd556124c661323b565b5160c95550919250505090565b6124db612ca7565b6001600160a01b03166124ec611c99565b6001600160a01b031614806125165750612504612ca7565b60e2546001600160a01b039081169116145b6125325760405162461bcd60e51b81526004016109e990615099565b60e354600160a01b900460ff1615806125615750604080516020810190915260d554815261255f90612d5f565b155b1561256b57610ed7565b6000821161258b5760405162461bcd60e51b81526004016109e9906157c1565b8060de54146125ac5760405162461bcd60e51b81526004016109e990615726565b6125b46149af565b5060408051602081019091528281526125cb6149af565b604080516020808201835260d2548252825190810190925260d15482526125f29190612da5565b90506125fc6149af565b604080516020808201835260d2548252825190810190925260d15482526126239190612de8565b905061262f81846137ef565b60000b6126a65760e060009054906101000a90046001600160a01b03166001600160a01b0316638df3fab36040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561268657600080fd5b505af115801561269a573d6000803e3d6000fd5b50505050505050610ed7565b6126ae6149af565b604080516020810190915260d55481526126ec90611163906126dd906126d786610bd18a61313f565b90613d21565b6126e68561313f565b90613d8c565b9050600061270b6126fe61118061331c565b611aea6111808786612de8565b90506127156149af565b604051806020016040528061272984613da9565b905290506127356149af565b61273f8683612de8565b90506127496149af565b6127538383610b1a565b905061275d6149af565b60e3546040516368a6d20b60e11b81526001600160a01b039091169063d14da4169061278d903090600401614f4d565b60206040518083038186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190614ddb565b90506127f16127ec8383613d8c565b613e03565b1561285d577f2ad23a1b94bd43bf2d22d82564f2f357d4428e8146810a57fbaef7b88ddc6fba61282088612d5f565b8c61282a89612d5f565b61283385612d5f565b61283c87612d5f565b6000604051612850969594939291906158d5565b60405180910390a1612945565b835160d255825160d15561286f6137ad565b60e45561287a613e21565b60e060009054906101000a90046001600160a01b03166001600160a01b0316638df3fab36040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156128ca57600080fd5b505af11580156128de573d6000803e3d6000fd5b505050507f2ad23a1b94bd43bf2d22d82564f2f357d4428e8146810a57fbaef7b88ddc6fba61290c88612d5f565b8c61291689612d5f565b61291f85612d5f565b61292887612d5f565b600160405161293c969594939291906158d5565b60405180910390a15b5050505050505050505050565b61295a6149af565b6109a882613f59565b60d55481565b612971612ca7565b6033546001600160a01b0390811691161461299e5760405162461bcd60e51b81526004016109e990615489565b6001600160a01b0381166129c45760405162461bcd60e51b81526004016109e9906150f1565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b612a28612ca7565b6033546001600160a01b03908116911614612a555760405162461bcd60e51b81526004016109e990615489565b612a5d6149af565b604080516020808201835260d2548252825190810190925260d1548252612a8391610b1a565b9050612a8d6149af565b60e3546040516368a6d20b60e11b81526001600160a01b039091169063d14da41690612abd903090600401614f4d565b60206040518083038186803b158015612ad557600080fd5b505afa158015612ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0d9190614ddb565b9050612b176149af565b612b218383613d8c565b9050612b2b6149af565b612b3482613e03565b15612b5e57604080516020810190915260ce548152612b57906111639085613d8c565b9050612b7f565b604080516020810190915260ce548152612b7c906111639086613f8a565b90505b612b876149af565b604080516020808201835260cb548252825190810190925260ca548252612bb191610bd19061313f565b90506064612bbe826130ff565b1115612bdc57612bd7612bd082613111565b8390612de8565b5160cf555b60e3805460ff60a01b19169055604080516020810190915260cf5481527f574214b195bf5273a95bb4498e35cf1fde0ce327c727a95ec2ab359f7ba4e11a90612c2490612d5f565b6040516115589190614f6c565b612c39612ca7565b6033546001600160a01b03908116911614612c665760405162461bcd60e51b81526004016109e990615489565b60e080546001600160a01b0319166001600160a01b0392909216919091179055565b60e354600160a01b900460ff1681565b60e1546001600160a01b031681565b3390565b6001600160a01b038316612cd15760405162461bcd60e51b81526004016109e99061567b565b6001600160a01b038216612cf75760405162461bcd60e51b81526004016109e990615137565b6001600160a01b0380841660008181526098602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612d52908590614f6c565b60405180910390a3505050565b5190565b6000610d5083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612fee565b612dad6149af565b612db56149af565b82518451612dc291613fa7565b81529392505050565b612dd36149af565b612ddb6149af565b82518451612dc29161301a565b612df06149af565b612df86149af565b82518451612dc291613fb5565b612e0d6149af565b8180600001516001600160ff1b0310156040518060600160405280603381526020016159ad6033913990612e545760405162461bcd60e51b81526004016109e99190614fa5565b50612e5d6149af565b83518551612e6a91613fc3565b8152949350505050565b612e7c6149af565b8180600001516001600160ff1b0310156040518060600160405280603381526020016159ad6033913990612ec35760405162461bcd60e51b81526004016109e99190614fa5565b50612ecc6149af565b83518551612e6a91614009565b6001600160a01b038316612eff5760405162461bcd60e51b81526004016109e990615574565b6001600160a01b038216612f255760405162461bcd60e51b81526004016109e990614ff8565b612f308383836133ba565b612f6d81604051806060016040528060268152602001615987602691396001600160a01b0386166000908152609760205260409020549190612fee565b6001600160a01b038085166000908152609760205260408082209390935590841681522054612f9c908261301a565b6001600160a01b0380841660008181526097602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612d52908590614f6c565b600081848411156130125760405162461bcd60e51b81526004016109e99190614fa5565b505050900390565b600082820183811015610d505760405162461bcd60e51b81526004016109e990615179565b6001600160a01b0382166130655760405162461bcd60e51b81526004016109e990615824565b613071600083836133ba565b60995461307e908261301a565b6099556001600160a01b0382166000908152609760205260409020546130a4908261301a565b6001600160a01b0383166000818152609760205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130f3908590614f6c565b60405180910390a35050565b600061310a82613111565b5192915050565b6131196149af565b6131216149af565b82516000131561313757825160000381526109a8565b915182525090565b6131476149af565b8180600001516001600160ff1b0310156040518060600160405280603381526020016159ad603391399061318e5760405162461bcd60e51b81526004016109e99190614fa5565b50506040805160208101909152915182525090565b6131ab6149af565b6131b36149af565b8351612dc2908461404f565b6131c76149af565b6131cf614a01565b600180825260df546131e091612d63565b602082015260408101518660018111156131f657fe5b9081600181111561320357fe5b90525060408082018051602001879052510184600181111561322157fe5b9081600181111561322e57fe5b905250610bd781846140ba565b6132436149af565b5060408051602081019091526000815290565b61325e6149af565b6132666149af565b82518451612dc291612d63565b61327b6149af565b8180600001516001600160ff1b0310156040518060600160405280603381526020016159ad60339139906132c25760405162461bcd60e51b81526004016109e99190614fa5565b506132cb6149af565b6122736132d78561313f565b86906142e5565b6132e66149af565b6040518060200160405280836000015161330b6133036012614302565b8751906137b5565b8161331257fe5b0690529392505050565b6133246149af565b60405180602001604052806110376012614302565b600061334483612d5f565b1315610ed7576133526149af565b604080516020808201835260d25482528251908101909252633b9aca00825261338b916111639190613385908790612e05565b90613273565b9050600061339983836137ef565b60000b12156133ba5760405162461bcd60e51b81526004016109e99061528b565b505050565b60006133ca82612d5f565b1115611af45760df546133db614a20565b60df60018303815481106133eb57fe5b60009182526020918290206040805160a08101825260049093029091018054608084019081528352815180850183526001820154815293830193909352600283015490820152600390910154606082015290506134466137b1565b81606001511480156134585750600182115b156134c15760df600283038154811061346d57fe5b60009182526020918290206040805160a08101825260049093029091018054608084019081528352815180850183526001820154815293830193909352600283015490820152600390910154606082015290505b604080516020808201835260d2548252825190810190925260d15482526134f2916134eb91612de8565b848361430b565b156133ba5760405162461bcd60e51b81526004016109e990615314565b6135176149af565b50604080516020810190915260ca5481526135306149af565b50604080516020810190915260cb5481526135496149af565b6135516149af565b6135596149af565b6135616149af565b600061356c87612d5f565b11156135f85761357a6149af565b6135876000888b8b611d0f565b90506135946001826122e1565b5160ca556135a28982613256565b94506135ae8888612dcb565b604080516020810190915260d15481529094506135cb9082613256565b604080516020808201835260ca548252825190810190925260d25482529194506135f491612dcb565b9150505b600061360386612d5f565b1115613633576136116149af565b61361e6001878787611d0f565b905061362d600082858561109c565b5160cb55505b5050505050505050565b303b1590565b600054610100900460ff168061365c575061365c61363d565b8061366a575060005460ff16155b6136865760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff161580156136b1576000805460ff1961ff0019909116610100171660011790555b6136b96143ad565b6136c161442e565b8015611af4576000805461ff001916905550565b600054610100900460ff16806136ee57506136ee61363d565b806136fc575060005460ff16155b6137185760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff16158015613743576000805460ff1961ff0019909116610100171660011790555b61374b6143ad565b6137558383614508565b80156133ba576000805461ff0019169055505050565b6000610d5083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506145c1565b4290565b4390565b6000826137c4575060006109a8565b828202828482816137d157fe5b0414610d505760405162461bcd60e51b81526004016109e990615411565b805182516000911015613804575060016109a8565b81518351101561381757506000196109a8565b50600092915050565b6001600160a01b0382166138465760405162461bcd60e51b81526004016109e990615533565b613852826000836133ba565b61388f81604051806060016040528060228152602001615965602291396001600160a01b0385166000908152609760205260409020549190612fee565b6001600160a01b0383166000908152609760205260409020556099546138b59082612d63565b6099556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906130f3908590614f6c565b600084600181111561390457fe5b14156139a557604080516020810190915260d15481526139249084612dcb565b5160d155604080516020810190915260d25481526139429083613256565b5160d255604080516020810190915260c95481526139609083612e74565b5160c955604080516020810190915260cc54815261397e9083612e05565b5160cc55604080516020810190915260ce54815261399c9084612e05565b5160ce55613a3c565b604080516020810190915260d15481526139bf9084613256565b5160d155604080516020810190915260d25481526139dd9083612dcb565b5160d255604080516020810190915260c95481526139fb9083612e05565b5160c955604080516020810190915260cc548152613a199083612e74565b5160cc55604080516020810190915260ce548152613a379084612e74565b5160ce555b80613a5a57604080516020810190915260d3548152613a5a906133bf565b613a62613e21565b50505050565b613a706149af565b613a7984612d5f565b613a85576110b961323b565b6001856001811115613a9357fe5b1415613b0d57613aa284612d5f565b604080516020808201835260d0548252825190810190925260d2548252613acc9161118091612da5565b1015613aea5760405162461bcd60e51b81526004016109e99061525f565b604080516020810190915260cb548152613b049085613256565b5160cb55613b2c565b604080516020810190915260ca548152613b279085613256565b5160ca555b613b346149af565b613b3e86866121b3565b9050613b4984612d5f565b15613bc7576000866001811115613b5c57fe5b1415613b9757613b6b84612d5f565b613b7482612d5f565b1015613b925760405162461bcd60e51b81526004016109e9906153da565b613bc7565b613ba084612d5f565b613ba982612d5f565b1115613bc75760405162461bcd60e51b81526004016109e99061560d565b82613bda57613bd78682876145f8565b92505b613c026000876001811115613beb57fe5b14613bf7576000613bfa565b60015b8287866138f6565b7f0dd4066b1a6ce97fb670c3e4201e908c644193f38cbdaffd0229d7e26da3e53386613c2d83612d5f565b613c3688612d5f565b604051613c4593929190614f83565b60405180910390a195945050505050565b613c5e6149af565b816001600160ff1b0310156040518060600160405280603381526020016159ad6033913990613ca05760405162461bcd60e51b81526004016109e99190614fa5565b50613ca96149af565b6111d584846131a3565b613cbb6149af565b613cc36149af565b8351612dc2908461471a565b613cd98282613273565b5160cd81905560408051602081019091529081527fd2805fe76d30598332a67c1061cee82e2e102b0f59f5457b1729bce028a054a090613d1890612d5f565b610a5083612d5f565b613d296149af565b8180600001516001600160ff1b0310156040518060600160405280603381526020016159ad6033913990613d705760405162461bcd60e51b81526004016109e99190614fa5565b50613d796149af565b612273613d858561313f565b869061477e565b613d946149af565b613d9c6149af565b82518451612dc291613fc3565b60006003821115613ded5781600160028204015b81811015613de557809150600281828681613dd457fe5b040181613ddd57fe5b049050613dbd565b509050610cca565b8115613dfb57506001610cca565b506000610cca565b60008082600001511215613e1957506001610cca565b506000919050565b6000613e2b6137b1565b60df80549192506000916000198101908110613e4357fe5b906000526020600020906004020190508060030154821415613e715760d154815560d2546001820155613eee565b6040805160a08101825260d15460808201908152815281516020818101845260d254825282015260df918101613ea56137ad565b8152602090810185905282546001818101855560009485529382902083515160049092020190815590820151519281019290925560408101516002830155606001516003909101555b604080516020810190915260d15481527f3a3348362552c3897fd1f06a3233519ebd8bd76ad6e99a418a9741155fe9051590613f2990612d5f565b604080516020810190915260d2548152613f4290612d5f565b613f4a6137ad565b604051610a5e939291906158bf565b613f616149af565b613f69614a01565b6000815260df54613f7b906001612d63565b6020820152610d5081846140ba565b613f926149af565b613f9a6149af565b82518451612dc291614009565b6000610d508383601261479b565b6000610d50838360126147b3565b6000828201818312801590613fd85750838112155b80613fed5750600083128015613fed57508381125b610d505760405162461bcd60e51b81526004016109e99061521e565b600081830381831280159061401e5750838113155b80614033575060008312801561403357508381135b610d505760405162461bcd60e51b81526004016109e99061577d565b60008261405e575060006109a8565b826000191480156140725750600160ff1b82145b1561408f5760405162461bcd60e51b81526004016109e9906154ec565b8282028284828161409c57fe5b0514610d505760405162461bcd60e51b81526004016109e9906154ec565b6140c26149af565b6140ca6149af565b6140d3846147cc565b9050826140e15790506109a8565b60006140f5846140ef6137ad565b90612d63565b90506140ff614a20565b60df86602001518154811061411057fe5b60009182526020918290206040805160a081018252600490930290910180546080840190815283528151808501835260018083015482529484015260028101549183019190915260030154606082015260df549092501480614176575081816040015111155b15614186578293505050506109a8565b60408101516000614199826140ef6137ad565b90506141a36149af565b6141ad8683614924565b90505b60208901516141d0576141c38183614940565b96505050505050506109a8565b60208901516141e0906001612d63565b60208a0181905260df805490919081106141f657fe5b60009182526020918290206040805160a0810182526004909302909101805460808401908152835281518085018352600182015481529383019390935260028301549082015260039091015460608201529350614252896147cc565b9550848460400151116142845761427d61427661426f8588612d63565b8890614924565b8290612dcb565b90506142ce565b600061429d856040015185612d6390919063ffffffff16565b90506142b36142ac8883614924565b8390612dcb565b91506142bf838261301a565b925084604001519350506141b0565b6142d88189614940565b9998505050505050505050565b6142ed6149af565b6142f56149af565b82518451612dc29161495c565b60ff16600a0a90565b60006143156149af565b6020830151835161432591612de8565b905061432f6149af565b6143446113808661433e61331c565b90612dcb565b905061434e6149af565b6143636113638761435d61331c565b90613256565b9050600061437188846137ef565b60000b1315801561438f5750600061438988836137ef565b60000b12155b156143a05760009350505050610d50565b5060019695505050505050565b600054610100900460ff16806143c657506143c661363d565b806143d4575060005460ff16155b6143f05760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff161580156136c1576000805460ff1961ff0019909116610100171660011790558015611af4576000805461ff001916905550565b600054610100900460ff1680614447575061444761363d565b80614455575060005460ff16155b6144715760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff1615801561449c576000805460ff1961ff0019909116610100171660011790555b60006144a6612ca7565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015611af4576000805461ff001916905550565b600054610100900460ff1680614521575061452161363d565b8061452f575060005460ff16155b61454b5760405162461bcd60e51b81526004016109e99061534b565b600054610100900460ff16158015614576576000805460ff1961ff0019909116610100171660011790555b825161458990609a906020860190614a54565b50815161459d90609b906020850190614a54565b50609c805460ff1916601217905580156133ba576000805461ff0019169055505050565b600081836145e25760405162461bcd60e51b81526004016109e99190614fa5565b5060008385816145ee57fe5b0495945050505050565b60006146026149af565b600085600181111561461057fe5b1461465857604080516020810190915260d2548152614653906146339085613256565b604080516020810190915260d154815261464d9087612dcb565b90612de8565b614690565b604080516020810190915260d2548152614690906146769085612dcb565b604080516020810190915260d154815261464d9087613256565b604080516020810190915260d354815260df805492935061227392849291906146ba906001612d63565b815481106146c457fe5b60009182526020918290206040805160a08101825260049093029091018054608084019081528352815180850183526001820154815293830193909352600283015490820152600390910154606082015261430b565b6000816147395760405162461bcd60e51b81526004016109e9906157ef565b8160001914801561474d5750600160ff1b83145b1561476a5760405162461bcd60e51b81526004016109e990615399565b600082848161477557fe5b05949350505050565b6147866149af565b61478e6149af565b82518451612dc29161496a565b60006111d56147a983614302565b611ae486866137b5565b60006111d583611ae46147c585614302565b87906137b5565b6147d46149af565b6147dc614a20565b60df8360200151815481106147ed57fe5b600091825260208083206040805160a0810182526004909402909101805460808501908152845281518084018352600182015481529284019290925260028201549083015260030154606082015291508351600181111561484a57fe5b1415614868576020810151815161486091612de8565b915050610cca565b60018351600181111561487757fe5b141561490c5761488e836040015160200151612d5f565b61489a5761486061323b565b600083604001516040015160018111156148b057fe5b14156148d35760408301518051602091820151835192840151614860939061109c565b600183604001516040015160018111156148e957fe5b141561490c57604083015180516020918201518351928401516148609390611d0f565b60405162461bcd60e51b81526004016109e9906150c3565b61492c6149af565b6149346149af565b8351612dc290846137b5565b6149486149af565b6149506149af565b8351612dc2908461376b565b6000610d5083836012614978565b6000610d5083836012614997565b60006111d58361499161498a85614302565b879061404f565b9061471a565b60006111d56149a583614302565b614991868661404f565b6040518060200160405280600081525090565b60405180608001604052806149d56149af565b81526020016149e26149af565b81526020016149ef6149af565b81526020016149fc6149af565b905290565b60408051606081018252600080825260208201529081016149fc614ad2565b6040518060800160405280614a336149af565b8152602001614a406149af565b815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a9557805160ff1916838001178555614ac2565b82800160010185558215614ac2579182015b82811115614ac2578251825591602001919060010190614aa7565b50614ace929150614af9565b5090565b60408051606081019091528060008152602001614aed6149af565b815260200160006149fc565b5b80821115614ace5760008155600101614afa565b8035600281106109a857600080fd5b600060208284031215614b2e578081fd5b50919050565b600060208284031215614b45578081fd5b614b4f602061590d565b9135825250919050565b600060208284031215614b6a578081fd5b8135610d5081615934565b60008060408385031215614b87578081fd5b8235614b9281615934565b91506020830135614ba281615934565b809150509250929050565b600080600060608486031215614bc1578081fd5b8335614bcc81615934565b92506020840135614bdc81615934565b929592945050506040919091013590565b60008060408385031215614bff578182fd5b8235614c0a81615934565b946020939093013593505050565b600060208284031215614c29578081fd5b8135610d5081615949565b600080600060608486031215614c48578283fd5b614c528585614b0e565b9250614c618560208601614b1d565b9150614c708560408601614b1d565b90509250925092565b60008060008060808587031215614c8e578081fd5b8435614c9981615957565b9350614ca88660208701614b1d565b9250614cb78660408701614b1d565b91506060850135614cc781615949565b939692955090935050565b60008060408385031215614ce4578182fd5b614cee8484614b0e565b9150614cfd8460208501614b34565b90509250929050565b60008060008060808587031215614d1b578384fd5b8435614d2681615957565b9350614d358660208701614b34565b9250614d448660408701614b34565b9150614d538660608701614b34565b905092959194509250565b600060208284031215614d6f578081fd5b610d508383614b1d565b60008060408385031215614d8b578182fd5b614d958484614b1d565b9150614cfd8460208501614b1d565b600060208284031215614db5578081fd5b610d508383614b34565b60008060408385031215614dd1578182fd5b614cee8484614b34565b600060208284031215614dec578081fd5b614df6602061590d565b9151825250919050565b60008060008385036060811215614e15578182fd5b6020811215614e22578182fd5b50614e2d602061590d565b843581529250614e408560208601614b34565b9150614c708560408601614b34565b600060208284031215614e60578081fd5b5035919050565b600060208284031215614e78578081fd5b5051919050565b60008060408385031215614e91578182fd5b50508035926020909101359150565b6000806000806000806000806000806000806101808d8f031215614ec257898afd5b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135614ee981615934565b975060a08d0135614ef981615934565b965060c08d0135614f0981615934565b955060e08d013594506101008d0135614f2181615934565b809450506101208d013592506101408d013591506101608d013590509295989b509295989b509295989b565b6001600160a01b0391909116815260200190565b901515815260200190565b90815260200190565b918252602082015260400190565b6060810160028510614f9157fe5b938152602081019290925260409091015290565b6000602080835283518082850152825b81811015614fd157858101830151858201604001528201614fb5565b81811115614fe25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b602080825260159082015274062617365206173736574206166746572206973203605c1b604082015260600190565b6020808252601590820152746d756c7469706c6965722063616e2774206265203160581b604082015260600190565b60208082526010908201526f34b63632b3b0b61037b832b930ba37b960811b604082015260600190565b6020808252601490820152733737ba1039bab83837b93a32b21037b83a34b7b760611b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526019908201527f63616e206e6f742073657420696e74657276616c20746f203000000000000000604082015260600190565b6020808252601a908201527f63616c6c6572206973206e6f7420636f756e7465725061727479000000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601290820152711bdd995c881d1c98591a5b99c81b1a5b5a5d60721b604082015260600190565b6020808252601c908201527f696c6c6567616c206c6971756964697479206d756c7469706c69657200000000604082015260600190565b6020808252600f908201526e0d2dcc6dee4e4cac6e840d2dcc8caf608b1b604082015260600190565b6020808252600f908201526e696e76616c6964206164647265737360881b604082015260600190565b6020808252601f908201527f7072696365206973206f76657220666c756374756174696f6e206c696d697400604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601d908201527f4c657373207468616e206d696e696d616c2071756f746520746f6b656e000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601c908201527f4c657373207468616e206d696e696d616c206261736520746f6b656e00000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526014908201527331b0b63632b91034b9903737ba1026b4b73a32b960611b604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600d908201526c696e76616c696420726174696f60981b604082015260600190565b602080825260139082015272195e18da185b99d9481dd85cc818db1bdcd959606a1b604082015260600190565b6020808252601d908201527f4d6f7265207468616e206d6178696d616c2071756f746520746f6b656e000000604082015260600190565b6020808252601c908201527f4d6f7265207468616e206d6178696d616c206261736520746f6b656e00000000604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b602080825260169082015275071756f746520617373657420616674657220697320360541b604082015260600190565b60208082526018908201527f736574746c652066756e64696e6720746f6f206561726c790000000000000000604082015260600190565b602080825260169082015275696c6c6567616c2070726963652066656564206b657960501b604082015260600190565b6020808252600d908201526c1a5b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b602080825260149082015273696e76616c6964206f7261636c6520707269636560601b604082015260600190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b815151815260208083015151908201526040808301515190820152606091820151519181019190915260800190565b9051815260200190565b9151825251602082015260400190565b93518452915160208401526040830152606082015260800190565b9283526020830191909152604082015260600190565b9586526020860194909452604085019290925260608401526080830152151560a082015260c00190565b60ff91909116815260200190565b60405181810167ffffffffffffffff8111828210171561592c57600080fd5b604052919050565b6001600160a01b0381168114611af457600080fd5b8015158114611af457600080fd5b60028110611af457600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d415845524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212204919f04b18a213b874f6c6887f4fd0a7cdce8a12ad0a47b2b31d26d109126a3764736f6c634300060c0033

Deployed ByteCode Sourcemap

49712:50529:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14494:83;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16600:169;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;77678:107::-;;;:::i;:::-;;;;;;;:::i;72989:362::-;;;;;;:::i;:::-;;:::i;:::-;;78855:135;;;:::i;:::-;;;;;;;:::i;15569:100::-;;;:::i;78090:192::-;;;:::i;:::-;;;;;;;:::i;53434:44::-;;;:::i;98859:1379::-;;;;;;:::i;:::-;;:::i;54201:41::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;78290:243::-;;;;;;:::i;:::-;;:::i;17251:321::-;;;;;;:::i;:::-;;:::i;52855:40::-;;;:::i;77937:145::-;;;:::i;15421:83::-;;;:::i;:::-;;;;;;;:::i;76473:204::-;;;;;;:::i;:::-;;:::i;17981:218::-;;;;;;:::i;:::-;;:::i;57387:126::-;;;;;;:::i;:::-;;:::i;67622:1234::-;;;;;;:::i;:::-;;:::i;53132:46::-;;;:::i;54422:35::-;;;:::i;77793:136::-;;;:::i;76203:150::-;;;:::i;54368:15::-;;;:::i;:::-;;;;;;;:::i;74007:282::-;;;;;;:::i;:::-;;:::i;79149:170::-;;;:::i;:::-;;;;;;;;:::i;52974:52::-;;;:::i;80676:1569::-;;;;;;:::i;:::-;;:::i;72035:123::-;;;;;;:::i;:::-;;:::i;78998:143::-;;;:::i;65141:2473::-;;;;;;:::i;:::-;;:::i;54167:27::-;;;:::i;77307:165::-;;;:::i;54251:25::-;;;:::i;54011:36::-;;;:::i;79487:314::-;;;;;;:::i;:::-;;:::i;71223:187::-;;;;;;:::i;:::-;;:::i;55008:2276::-;;;;;;:::i;:::-;;:::i;74639:282::-;;;;;;:::i;:::-;;:::i;71638:245::-;;;;;;:::i;:::-;;:::i;53512:34::-;;;:::i;15732:119::-;;;;;;:::i;:::-;;:::i;25301:148::-;;;:::i;73465:184::-;;;;;;:::i;:::-;;:::i;54334:27::-;;;:::i;54054:28::-;;;:::i;72330:221::-;;;;;;:::i;:::-;;:::i;24659:79::-;;;:::i;53296:38::-;;;:::i;14696:87::-;;;:::i;82253:1556::-;;;;;;:::i;:::-;;:::i;57609:117::-;;;;;;:::i;:::-;;:::i;70254:111::-;;;;;;:::i;:::-;;:::i;58183:1732::-;;;;;;:::i;:::-;;:::i;18702:269::-;;;;;;:::i;:::-;;:::i;70863:163::-;;;;;;:::i;:::-;;:::i;16064:175::-;;;;;;:::i;:::-;;:::i;54089:34::-;;;:::i;53388:39::-;;;:::i;52809:::-;;;:::i;75805:283::-;;;;;;:::i;:::-;;:::i;60520:381::-;;;;;;:::i;:::-;;:::i;76804:144::-;;;:::i;16302:151::-;;;;;;:::i;:::-;;:::i;54130:30::-;;;:::i;75205:283::-;;;;;;:::i;:::-;;:::i;53341:40::-;;;:::i;78676:171::-;;;:::i;78541:127::-;;;:::i;61091:1867::-;;;:::i;96291:2504::-;;;;;;:::i;:::-;;:::i;77005:164::-;;;;;;:::i;:::-;;:::i;53553:39::-;;;:::i;25604:244::-;;;;;;:::i;:::-;;:::i;68963:1130::-;;;:::i;70506:103::-;;;;;;:::i;:::-;;:::i;54390:25::-;;;:::i;54283:44::-;;;:::i;14494:83::-;14564:5;14557:12;;;;;;;;-1:-1:-1;;14557:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14531:13;;14557:12;;14564:5;;14557:12;;14564:5;14557:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14494:83;:::o;16600:169::-;16683:4;16700:39;16709:12;:10;:12::i;:::-;16723:7;16732:6;16700:8;:39::i;:::-;-1:-1:-1;16757:4:0;16600:169;;;;;:::o;77678:107::-;77754:16;:23;77678:107;:::o;72989:362::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;;;;;;;;;73150:42;;:19:::1;:42:::0;;;73203:50;;:23:::1;:50:::0;73280:26:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;73269:74:::1;::::0;73280:28:::1;::::0;:26:::1;:28::i;:::-;73310:30;::::0;;::::1;::::0;::::1;::::0;;;:23:::1;:30:::0;;;:32:::1;::::0;:30:::1;:32::i;:::-;73269:74;;;;;;;:::i;:::-;;;;;;;;72989:362:::0;;:::o;78855:135::-;78921:22;;:::i;:::-;-1:-1:-1;78956:26:0;;;;;;;;;78963:19;78956:26;;;78855:135;:::o;15569:100::-;15649:12;;15569:100;:::o;78090:192::-;78157:31;;:::i;:::-;78208:25;78234:32;;:39;;78271:1;78234:36;:39::i;:::-;78208:66;;;;;;;;;;;;;;;;;78201:73;;;;;;;;78208:66;;;;;;;78201:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;78201:73:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78090:192:0;:::o;53434:44::-;;;;:::o;98859:1379::-;99038:34;;:::i;:::-;99090:32;;:::i;:::-;99125:42;:17;99148:18;99125:22;:42::i;:::-;99090:77;;99214:52;;:::i;:::-;99282:99;;;;;;;;;99325:16;99282:99;;;;;99309:14;;99343:18;99363:17;99282:26;:99::i;:::-;99412:40;;;;;;;;;99435:16;99412:40;;;99214:167;;-1:-1:-1;99412:40:0;;:17;;:22;:40::i;:::-;99392:60;-1:-1:-1;99484:33:0;:9;99392:60;99484:14;:33::i;:::-;99463:54;;99565:53;;:::i;:::-;99634:105;;;;;;;;;99682:17;99634:105;;;;;99661:19;;99701:18;99721:17;99634:26;:105::i;:::-;100139:23;;;;;;;;;:18;:23;;;99565:174;;-1:-1:-1;100139:91:0;;100200:29;;100139:55;;99565:174;100139:23;:55::i;:::-;:60;;:91::i;:::-;100132:98;98859:1379;-1:-1:-1;;;;;;98859:1379:0:o;54201:41::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54201:41:0;;:::o;78290:243::-;78371:31;;:::i;:::-;78427:25;:32;78423:36;;78415:64;;;;-1:-1:-1;;;78415:64:0;;;;;;;:::i;:::-;78497:25;78523:1;78497:28;;;;;;;;;;;;;;;;;78490:35;;;;;;;;78497:28;;;;;;;78490:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;78490:35:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78290:243:0;;;;:::o;17251:321::-;17357:4;17374:36;17384:6;17392:9;17403:6;17374:9;:36::i;:::-;17421:121;17430:6;17438:12;:10;:12::i;:::-;17452:89;17490:6;17452:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;17452:19:0;;;;;;:11;:19;;;;;;17472:12;:10;:12::i;:::-;-1:-1:-1;;;;;17452:33:0;;;;;;;;;;;;-1:-1:-1;17452:33:0;;;:89;:37;:89::i;:::-;17421:8;:121::i;:::-;-1:-1:-1;17560:4:0;17251:321;;;;;;:::o;52855:40::-;;;;:::o;77937:145::-;78002:34;;:::i;:::-;-1:-1:-1;78049:25:0;;;;;;;;;78056:18;78049:25;;;77937:145;:::o;15421:83::-;15487:9;;;;15421:83;:::o;76473:204::-;76554:22;;:::i;:::-;76596:73;;;;;;;;;;76612:9;;76635:12;;-1:-1:-1;;;76612:56:0;;;76596:73;;;;-1:-1:-1;;;;;76612:9:0;;:22;;:56;;76649:18;76612:56;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76596:73;;76589:80;76473:204;-1:-1:-1;;76473:204:0:o;17981:218::-;18069:4;18086:83;18095:12;:10;:12::i;:::-;18109:7;18118:50;18157:10;18118:11;:25;18130:12;:10;:12::i;:::-;-1:-1:-1;;;;;18118:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;18118:25:0;;;:34;;;;;;;;;;;:38;:50::i;57387:126::-;51298:4;;-1:-1:-1;;;51298:4:0;;;;51290:36;;;;-1:-1:-1;;;51290:36:0;;;;;;;:::i;:::-;51653:12:::1;:10;:12::i;:::-;51640:8;::::0;-1:-1:-1;;;;;51640:8:0;;::::1;51632:33:::0;::::1;;51624:66;;;;-1:-1:-1::0;;;51624:66:0::1;;;;;;;:::i;:::-;57483:22:::2;57489:7;57498:6;57483:5;:22::i;:::-;57387:126:::0;;:::o;67622:1234::-;67868:34;;:::i;:::-;67919:25;:16;:23;:25::i;:::-;67915:86;;-1:-1:-1;67973:16:0;67966:23;;67915:86;68013:20;68063:1;68036:24;:16;:22;:24::i;:::-;:28;:43;;68074:5;68036:43;;;68067:4;68036:43;68013:66;;68215:34;;:::i;:::-;68265:226;68310:15;:54;;68345:19;68310:54;;;68328:14;68310:54;68383:22;:16;:20;:22::i;:::-;68424:17;68460:16;68265:26;:226::i;:::-;68215:276;;68571:47;;:::i;:::-;68634:140;68677:82;68691:15;:54;;68731:14;68691:54;;;68709:19;68691:54;68747:11;68677:13;:82::i;:::-;68634:24;:140::i;:::-;68571:203;;68792:56;68815:15;:32;;-1:-1:-1;;68815:32:0;;;68833:1;68815:32;68792:12;;:22;:56::i;:::-;68785:63;67622:1234;-1:-1:-1;;;;;;;67622:1234:0:o;53132:46::-;;;;:::o;54422:35::-;;;;:::o;77793:136::-;77889:25;:32;77793:136;:::o;76203:150::-;76254:22;;:::i;:::-;76296:49;;;;;;;;;;76312:9;;76331:12;;-1:-1:-1;;;76312:32:0;;;76296:49;;;;-1:-1:-1;;;;;76312:9:0;;:18;;:32;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;76296:49;;76289:56;-1:-1:-1;76203:150:0;:::o;54368:15::-;;;-1:-1:-1;;;;;54368:15:0;;:::o;74007:282::-;74147:22;;:::i;:::-;74194:87;74221:4;74227:17;74246:22;74270:10;74194:26;:87::i;79149:170::-;79208:22;;:::i;:::-;79232;;:::i;:::-;-1:-1:-1;;79267:44:0;;;;;;;;;79275:16;79267:44;;;;;;;;;;;79293:17;79267:44;;;79149:170;:::o;52974:52::-;;;;:::o;80676:1569::-;80927:22;;:::i;:::-;80966:26;:17;:24;:26::i;:::-;80962:85;;81021:14;:12;:14::i;:::-;81014:21;;;;80962:85;81059:15;;81077:4;:22;;;;;;;;;81059:40;;81110:44;;:::i;:::-;81170:74;81195:48;:21;81222:20;81195:26;:48::i;81170:74::-;81110:134;;81255:49;;:::i;:::-;81315:38;;:::i;:::-;81364;;:::i;:::-;81417:10;81413:202;;;81462:45;:21;81489:17;81462:26;:45::i;:::-;81444:63;;81413:202;;;81558:45;:21;81585:17;81558:26;:45::i;:::-;81540:63;;81413:202;81633:24;:15;:22;:24::i;:::-;81625:64;;;;-1:-1:-1;;;81625:64:0;;;;;;;:::i;:::-;81719:31;:9;81734:15;81719:14;:31::i;:::-;81702:48;-1:-1:-1;81779:47:0;:41;81702:48;81799:20;81779:19;:41::i;:::-;:45;:47::i;:::-;81761:65;;81916:46;:37;81937:15;81916;:9;:13;:15::i;:::-;:20;;:37::i;:::-;:44;:46::i;:::-;:51;81912:291;;81988:10;81984:208;;;82058:18;;;;;;;;;82074:1;82058:18;;82037:40;;:15;;:20;:40::i;:::-;82019:58;;81984:208;;;82157:18;;;;;;;;;82173:1;82157:18;;82136:40;;:15;;:20;:40::i;:::-;82118:58;;81984:208;82222:15;-1:-1:-1;;;;;80676:1569:0;;;;;;;:::o;72035:123::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;72124:26;:11:::1;:26:::0;72035:123::o;78998:143::-;79068:22;;:::i;:::-;-1:-1:-1;79103:30:0;;;;;;;;;79110:23;79103:30;;;78998:143;:::o;65141:2473::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;65368:22:::1;:13;:11;:13::i;:22::-;65335:29;:27;;::::0;;::::1;::::0;::::1;:20:::0;:27:::1;:::i;:29::-;:55;;65327:89;;;;-1:-1:-1::0;;;65327:89:0::1;;;;;;;:::i;:::-;65530:70;::::0;;::::1;::::0;::::1;::::0;;;65560:17:::1;65530:70:::0;;;::::1;::::0;::::1;;::::0;;::::1;::::0;::::1;65579:20:::0;65530:70:::1;:::i;:::-;:29;:70::i;:::-;65611:84;::::0;;::::1;::::0;::::1;::::0;;;65641:31:::1;65611:84:::0;;;::::1;::::0;::::1;;::::0;;::::1;::::0;::::1;65674:20:::0;65611:84:::1;:::i;:::-;65771:45;;;::::0;;::::1;::::0;::::1;65793:22:::0;65771:45:::1;:::i;:::-;:21;:45::i;:::-;65868:54;;:::i;:::-;-1:-1:-1::0;65868:74:0::1;::::0;;::::1;::::0;::::1;::::0;;;65925:17:::1;65868:74:::0;;;65953:53:::1;;:::i;:::-;-1:-1:-1::0;65953:72:0::1;::::0;;::::1;::::0;::::1;::::0;;;66009:16:::1;65953:72:::0;;;66036:58:::1;;:::i;:::-;-1:-1:-1::0;66036:78:0::1;::::0;;::::1;::::0;::::1;::::0;;;66097:17:::1;66036:78:::0;;;66177:58:::1;;;::::0;;::::1;::::0;::::1;66214:20:::0;66177:58:::1;:::i;:::-;:31:::0;;:36:::1;:58::i;:::-;66157:78:::0;:17:::1;:78:::0;66265:57:::1;;;::::0;;::::1;::::0;::::1;66301:20:::0;66265:57:::1;:::i;:::-;:30:::0;;:35:::1;:57::i;:::-;66246:76:::0;:16:::1;:76:::0;66654:41:::1;::::0;;::::1;::::0;::::1;::::0;;;:31:::1;:41:::0;;;66603:226:::1;::::0;-1:-1:-1;;66826:2:0;66603:198:::1;::::0;66654:45:::1;::::0;66826:2;66654:41:::1;:45::i;:::-;66714:31;66760:30;66603:36;:198::i;:::-;:222:::0;::::1;:226::i;:::-;66569:260:::0;:31:::1;:260:::0;66862:176:::1;66913:23:::0;66951:31;66997:30;66862:36:::1;:176::i;:::-;66842:196:::0;:17:::1;:196:::0;67051:80:::1;67067:31:::0;67100:30;67051:15:::1;:80::i;:::-;67217:261;::::0;;;;;;;67281:18:::1;67217:261:::0;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;67337:17:::1;67217:261:::0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;67391:16:::1;67217:261:::0;;;-1:-1:-1;;;67217:261:0;;;;;;;::::1;::::0;;67445:17:::1;67217:261:::0;;;;;;;;;67172:25:::1;:317:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;67172:317:0;;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;67524:24;;;;::::1;::::0;;;;;;;67507:99:::1;::::0;67524:26:::1;::::0;:24:::1;:26::i;:::-;67552:23;::::0;;::::1;::::0;::::1;::::0;;;:16:::1;:23:::0;;;:25:::1;::::0;:23:::1;:25::i;:::-;67579:24;::::0;;::::1;::::0;::::1;::::0;;;:18:::1;:24:::0;;;:26:::1;::::0;:24:::1;:26::i;:::-;67507:99;;;;;;;;:::i;:::-;;;;;;;;24941:1;;;65141:2473:::0;;:::o;54167:27::-;;;;:::o;77307:165::-;77361:22;;:::i;:::-;77385;;:::i;:::-;-1:-1:-1;;77420:44:0;;;;;;;;;77428:17;77420:44;;;;;;;;;;;77447:16;77420:44;;;77307:165;:::o;54251:25::-;;;-1:-1:-1;;;;;54251:25:0;;:::o;54011:36::-;;;;:::o;79487:314::-;79616:22;;:::i;:::-;79660:26;:24;;;;;;;:17;:24;:::i;:26::-;79656:85;;79715:14;:12;:14::i;:::-;79708:21;;;;79656:85;79758:35;;;;;;;;;79781:11;79758:35;;;;;:22;;;;;;;:17;:22;:::i;:::-;;;:35::i;71223:187::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;71314:14;71306:52:::1;;;;-1:-1:-1::0;;;71306:52:0::1;;;;;;;:::i;:::-;71369:21;:33:::0;71223:187::o;55008:2276::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;9940:101;55480:23;;;::::1;::::0;:65:::1;;-1:-1:-1::0;55524:21:0;;::::1;55480:65;:108;;;;-1:-1:-1::0;55566:22:0;;::::1;55480:108;:148;;;;-1:-1:-1::0;55609:19:0;;::::1;55480:148;:202;;;;-1:-1:-1::0;;;;;;55649:33:0;::::1;::::0;::::1;55480:202;:250;;;;-1:-1:-1::0;;;;;;55703:27:0;::::1;::::0;::::1;55480:250;:303;;;;-1:-1:-1::0;;;;;;55751:32:0;::::1;::::0;::::1;55480:303;:349;;;;-1:-1:-1::0;;;;;;55804:25:0;::::1;::::0;::::1;55480:349;55458:412;;;;-1:-1:-1::0;;;55458:412:0::1;;;;;;;:::i;:::-;55881:16;:14;:16::i;:::-;55908:50;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;-1:-1:-1::0;;;55908:50:0::1;;::::0;:12:::1;:50::i;:::-;55991:35;::::0;;::::1;::::0;;::::1;::::0;;;;;;55971:17:::1;:55:::0;;;56056:34;;;;::::1;::::0;;;;;56037:16:::1;:53:::0;;;56119:33;;;;::::1;::::0;;;;;56101:15:::1;:51:::0;;;56177:29;;;;::::1;::::0;;;;;56163:11:::1;:43:::0;;;56236:34;;;;::::1;::::0;;;;;56217:16:::1;:53:::0;;;56305:39;;;;::::1;::::0;;;;;;56281:21:::1;:63:::0;;;56355:13:::1;:30:::0;;;56418:21:::1;56371:14:::0;-1:-1:-1;56418:18:0::1;:21::i;:::-;56396:19;:43:::0;56474:7:::1;56450:21;:31:::0;56492:12:::1;:28:::0;;;56531:10:::1;:43:::0;;-1:-1:-1;;;;;56531:43:0;;::::1;-1:-1:-1::0;;;;;;56531:43:0;;::::1;;::::0;;;56585:9:::1;:22:::0;;;;::::1;::::0;;::::1;;::::0;;56618:3:::1;:10:::0;;;;::::1;::::0;;::::1;;::::0;;56639:8:::1;:20:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;56701:13:::1;:11;:13::i;:::-;56670:44:::0;:28:::1;:44:::0;56770:266:::1;::::0;;::::1;::::0;::::1;::::0;;;56725:25:::1;::::0;56770:266;56834:20:::1;:18;:20::i;:::-;56770:266:::0;;::::1;::::0;;::::1;::::0;;::::1;::::0;;56945:17:::1;56770:266:::0;;;;;::::1;::::0;;;;;;;;::::1;::::0;;56891:16:::1;56770:266:::0;;;;;;;;;57000:20:::1;:18;:20::i;:::-;56770:266:::0;;56725:322;;::::1;::::0;;::::1;::::0;;-1:-1:-1;56725:322:0;;;::::1;::::0;;;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;;::::1;::::0;57080:87;;;;;;;57096:17:::1;57080:87:::0;::::1;::::0;::::1;::::0;;;;;;;;;::::1;::::0;;57115:16:::1;57080:87:::0;;;;;::::1;::::0;;;;57058:16:::1;::::0;57080:87;-1:-1:-1;;57133:17:0::1;:15;:17::i;:::-;57080:87;;;;57152:14;:12;:14::i;:::-;57080:87:::0;;57058:110;;::::1;::::0;;::::1;::::0;;-1:-1:-1;57058:110:0;;;::::1;::::0;;;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;57203:24;;;;::::1;::::0;;:17:::1;:24:::0;;;57184:92:::1;::::0;57203:26:::1;::::0;:24:::1;:26::i;:::-;57231:23;::::0;;::::1;::::0;::::1;::::0;;;:16:::1;:23:::0;;;:25:::1;::::0;:23:::1;:25::i;:::-;57258:17;:15;:17::i;:::-;57184:92;;;;;;;;:::i;:::-;;;;;;;;10071:14:::0;10067:68;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;10067:68;55008:2276;;;;;;;;;;;;;:::o;74639:282::-;74779:22;;:::i;:::-;74826:87;74853:4;74859:16;74877:23;74902:10;74826:26;:87::i;71638:245::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;71701:4:::1;::::0;::::1;-1:-1:-1::0;;;71701:4:0;;::::1;;:13;;::::0;::::1;;;71697:26;;;71716:7;;71697:26;71735:4;:12:::0;;;::::1;::::0;::::1;-1:-1:-1::0;;;71735:12:0::1;-1:-1:-1::0;;;;71735:12:0;;::::1;::::0;;;::::1;::::0;;;71758:118:::1;;71802:62;71856:7;71802:49;71843:7;71802:36;71824:13;;71802:17;:15;:17::i;:::-;:21:::0;::::1;:36::i;:::-;:40:::0;::::1;:49::i;:::-;:53:::0;::::1;:62::i;:::-;71784:15;:80:::0;71758:118:::1;71638:245:::0;:::o;53512:34::-;;;;:::o;15732:119::-;-1:-1:-1;;;;;15825:18:0;15798:7;15825:18;;;:9;:18;;;;;;;15732:119::o;25301:148::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;25392:6:::1;::::0;25371:40:::1;::::0;25408:1:::1;::::0;-1:-1:-1;;;;;25392:6:0::1;::::0;25371:40:::1;::::0;25408:1;;25371:40:::1;25422:6;:19:::0;;-1:-1:-1;;;;;;25422:19:0::1;::::0;;25301:148::o;73465:184::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;73552:24:0;::::1;73544:52;;;;-1:-1:-1::0;;;73544:52:0::1;;;;;;;:::i;:::-;73607:9;:34:::0;;-1:-1:-1;;;;;;73607:34:0::1;-1:-1:-1::0;;;;;73607:34:0;;;::::1;::::0;;;::::1;::::0;;73465:184::o;54334:27::-;;;-1:-1:-1;;;;;54334:27:0;;:::o;54054:28::-;;;;:::o;72330:221::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;72477:1:::1;72437:36;72459:13;:11;:13::i;:::-;72437:17:::0;;:21:::1;:36::i;:::-;:41;;;;72429:67;;;;-1:-1:-1::0;;;72429:67:0::1;;;;;;;:::i;:::-;72507:36:::0;:16:::1;:36:::0;72330:221::o;24659:79::-;24724:6;;-1:-1:-1;;;;;24724:6:0;24659:79;:::o;53296:38::-;;;;:::o;14696:87::-;14768:7;14761:14;;;;;;;;-1:-1:-1;;14761:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14735:13;;14761:14;;14768:7;;14761:14;;14768:7;14761:14;;;;;;;;;;;;;;;;;;;;;;;;82253:1556;82504:22;;:::i;:::-;82543:25;:16;:23;:25::i;:::-;82539:84;;82597:14;:12;:14::i;82539:84::-;82635:15;;82653:4;:22;;;;;;;;;82635:40;;82686:44;;:::i;:::-;82746:74;82771:48;:21;82798:20;82771:26;:48::i;82746:74::-;82686:134;;82831:50;;:::i;:::-;82892:37;;:::i;:::-;82940;;:::i;:::-;82994:10;82990:196;;;83038:43;:20;83064:16;83038:25;:43::i;:::-;83021:60;;82990:196;;;83131:43;:20;83157:16;83131:25;:43::i;:::-;83114:60;;82990:196;83204:23;:14;:21;:23::i;:::-;83196:62;;;;-1:-1:-1;;;83196:62:0;;;;;;;:::i;:::-;83289:30;:9;83304:14;83289;:30::i;:::-;83271:48;-1:-1:-1;83347:49:0;:43;83271:48;83368:21;83347:20;:43::i;57609:117::-;51653:12;:10;:12::i;:::-;51640:8;;-1:-1:-1;;;;;51640:8:0;;;51632:33;;;51624:66;;;;-1:-1:-1;;;51624:66:0;;;;;;;:::i;:::-;57696:22:::1;57702:7;57711:6;57696:5;:22::i;70254:111::-:0;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;70332:3:::1;:25:::0;;-1:-1:-1;;;;;;70332:25:0::1;-1:-1:-1::0;;;;;70332:25:0;;;::::1;::::0;;;::::1;::::0;;70254:111::o;58183:1732::-;58391:22;;:::i;:::-;51298:4;;-1:-1:-1;;;51298:4:0;;;;51290:36;;;;-1:-1:-1;;;51290:36:0;;;;;;;:::i;:::-;51520:12:::1;:10;:12::i;:::-;51512:3;::::0;-1:-1:-1;;;;;51512:3:0;;::::1;51504:28:::0;::::1;;51496:67;;;;-1:-1:-1::0;;;51496:67:0::1;;;;;;;:::i;:::-;58430:26:::2;:24;;::::0;;::::2;::::0;::::2;:17:::0;:24:::2;:::i;:26::-;58426:85;;58485:14;:12;:14::i;:::-;58478:21;;;;58426:85;58533:19;58525:4;:27;;;;;;;;;58521:218;;;58647:26;:24;;::::0;;::::2;::::0;::::2;:17:::0;:24:::2;:::i;:26::-;58595:39;::::0;;::::2;::::0;;::::2;::::0;;58618:15:::2;58595:39:::0;;;:22;;;;::::2;::::0;;;:17:::2;:22:::0;;;:48:::2;::::0;:39:::2;::::0;:22:::2;:39::i;:48::-;:78;;58569:158;;;;-1:-1:-1::0;;;58569:158:0::2;;;;;;;:::i;:::-;58751:38;;:::i;:::-;58792;58806:4:::0;58792:38:::2;;::::0;;::::2;::::0;::::2;58812:17:::0;58792:38:::2;:::i;:::-;58751:79:::0;-1:-1:-1;59134:30:0::2;:28;;::::0;;::::2;::::0;::::2;:21:::0;:28:::2;:::i;:30::-;:35:::0;59130:369:::2;;59198:14;59190:4;:22;;;;;;;;;59186:302;;;59269:30;:28;;::::0;;::::2;::::0;::::2;:21:::0;:28:::2;:::i;:30::-;59241:24;:15;:22;:24::i;:::-;:58;;59233:99;;;;-1:-1:-1::0;;;59233:99:0::2;;;;;;;:::i;:::-;59186:302;;;59409:30;:28;;::::0;;::::2;::::0;::::2;:21:::0;:28:::2;:::i;:30::-;59381:24;:15;:22;:24::i;:::-;:58;;59373:99;;;;-1:-1:-1::0;;;59373:99:0::2;;;;;;;:::i;:::-;59523:14;59515:4;:22;;;;;;;;;59511:204;;;59573:21;::::0;;::::2;::::0;::::2;::::0;;;:16:::2;:21:::0;;;:38:::2;::::0;59595:15;59573:21:::2;:38::i;:::-;59554:57:::0;:16:::2;:57:::0;59511:204:::2;;;59664:22;::::0;;::::2;::::0;::::2;::::0;;;:17:::2;:22:::0;;;:39:::2;::::0;59687:15;59664:22:::2;:39::i;:::-;59644:59:::0;:17:::2;:59:::0;59511:204:::2;59727:62;59741:4:::0;59727:62:::2;;::::0;;::::2;::::0;::::2;59747:17:::0;59727:62:::2;:::i;:::-;59766:15;59783:5;59727:13;:62::i;:::-;59805:69;59815:4:::0;59821:26:::2;:24;;::::0;;::::2;::::0;::::2;:17:::0;:24:::2;:::i;:26::-;59849:24;:15;:22;:24::i;:::-;59805:69;;;;;;;;:::i;:::-;;;;;;;;59892:15:::0;58183:1732;-1:-1:-1;;;;58183:1732:0:o;18702:269::-;18795:4;18812:129;18821:12;:10;:12::i;:::-;18835:7;18844:96;18883:15;18844:96;;;;;;;;;;;;;;;;;:11;:25;18856:12;:10;:12::i;:::-;-1:-1:-1;;;;;18844:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;18844:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;70863:163::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;70972:46;:21:::1;:46:::0;70863:163::o;16064:175::-;16150:4;16167:42;16177:12;:10;:12::i;:::-;16191:9;16202:6;16167:9;:42::i;54089:34::-;;;;:::o;53388:39::-;;;;:::o;52809:::-;;;;:::o;75805:283::-;75946:22;;:::i;:::-;75993:87;;;;;;;;;76044:17;75993:87;;;;;;;;;;;76063:16;75993:87;;;;;76020:4;;76026:16;;75993:26;:87::i;60520:381::-;60766:22;;:::i;:::-;51298:4;;-1:-1:-1;;;51298:4:0;;;;51290:36;;;;-1:-1:-1;;;51290:36:0;;;;;;;:::i;:::-;51520:12:::1;:10;:12::i;:::-;51512:3;::::0;-1:-1:-1;;;;;51512:3:0;;::::1;51504:28:::0;::::1;;51496:67;;;;-1:-1:-1::0;;;51496:67:0::1;;;;;;;:::i;:::-;60808:85:::2;60823:4:::0;60808:85:::2;;::::0;;::::2;::::0;::::2;60829:16:::0;60808:85:::2;:::i;:::-;;;::::0;;::::2;::::0;::::2;60847:22:::0;60808:85:::2;:::i;:::-;60871:21;60808:14;:85::i;:::-;60801:92:::0;60520:381;-1:-1:-1;;;;;60520:381:0:o;76804:144::-;76858:22;;:::i;:::-;76900:40;;;;;;;;;76923:16;76900:40;;;:22;;;;;;;;:17;:22;;;:40;;:22;;:40::i;:::-;76893:47;;76804:144;:::o;16302:151::-;-1:-1:-1;;;;;16418:18:0;;;16391:7;16418:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;16302:151::o;54130:30::-;;;;:::o;75205:283::-;75346:22;;:::i;:::-;75393:87;;;;;;;;;75444:17;75393:87;;;;;;;;;;;75463:16;75393:87;;;;;75419:4;;75425:17;;75393:25;:87::i;53341:40::-;;;;:::o;78676:171::-;78754:34;;:::i;:::-;-1:-1:-1;78801:38:0;;;;;;;;;78808:31;78801:38;;;78676:171;:::o;78541:127::-;78603:22;;:::i;:::-;-1:-1:-1;78638:22:0;;;;;;;;;78645:15;78638:22;;;78541:127;:::o;61091:1867::-;61169:34;;:::i;:::-;51298:4;;-1:-1:-1;;;51298:4:0;;;;51290:36;;;;-1:-1:-1;;;51290:36:0;;;;;;;:::i;:::-;51520:12:::1;:10;:12::i;:::-;51512:3;::::0;-1:-1:-1;;;;;51512:3:0;;::::1;51504:28:::0;::::1;;51496:67;;;;-1:-1:-1::0;;;51496:67:0::1;;;;;;;:::i;:::-;61245:15:::2;;61224:17;:15;:17::i;:::-;:36;;61216:73;;;;-1:-1:-1::0;;;61216:73:0::2;;;;;;;:::i;:::-;61300:50;;:::i;:::-;61353:20;:18;:20::i;:::-;61300:73;;61384:38;;:::i;:::-;61425:45;61448:21;;61425:22;:45::i;:::-;61384:86;;61613:15;;61571:39;61596:13;;61571:20;;:24;;:39;;;;:::i;:::-;:57;61567:503;;;61822:42;;:::i;:::-;61884:83;61951:15;61884:61;61909:35;61922:21;;61909:12;:35::i;61884:83::-;61822:145;;62000:58;62050:6;62000:32;62018:13;;62000:7;:17;;:32;;;;:::i;:::-;:42:::0;::::2;:58::i;:::-;61982:76;;61567:503;;62149:51;62167:15;62184;62149:17;:51::i;:::-;62321:31;62355:42;62377:19;;62355:17;:15;:17::i;:42::-;62321:76;;62477:34;62514:60;62566:7;62514:47;62553:7;62514:34;62534:13;;62514:15;;:19;;:34;;;;:::i;:60::-;62477:97;;62703:23;62674:26;:52;:133;;62784:23;62674:133;;;62742:26;62674:133;62656:15;:151:::0;62895:20:::2;:18;:20::i;:::-;62861:54:::0;:31:::2;:54:::0;-1:-1:-1;62935:15:0;;-1:-1:-1;;;61091:1867:0;:::o;96291:2504::-;96412:12;:10;:12::i;:::-;-1:-1:-1;;;;;96401:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;96401:23:0;;:61;;;;96450:12;:10;:12::i;:::-;96436:9;;-1:-1:-1;;;;;96436:9:0;;;96428:34;;;96401:61;96393:90;;;;-1:-1:-1;;;96393:90:0;;;;;;;:::i;:::-;96499:4;;-1:-1:-1;;;96499:4:0;;;;96498:5;;:39;;-1:-1:-1;96507:23:0;;;;;;;;;:16;:23;;;:25;;:23;:25::i;:::-;:30;96498:39;96494:52;;;96539:7;;96494:52;96579:1;96564:12;:16;96556:49;;;;-1:-1:-1;;;96556:49:0;;;;;;;:::i;:::-;96640:13;96624:12;;:29;96616:64;;;;-1:-1:-1;;;96616:64:0;;;;;;;:::i;:::-;96691:34;;:::i;:::-;-1:-1:-1;96728:29:0;;;;;;;;;;;;96768:32;;:::i;:::-;96803:40;;;;;;;;;96826:16;96803:40;;;:22;;;;;;;;:17;:22;;;:40;;:22;;:40::i;:::-;96768:75;;96854:31;;:::i;:::-;96888:40;;;;;;;;;96911:16;96888:40;;;:22;;;;;;;;:17;:22;;;:40;;:22;;:40::i;:::-;96854:74;-1:-1:-1;96943:25:0;96854:74;96956:11;96943:12;:25::i;:::-;:30;;96939:110;;96990:8;;;;;;;;;-1:-1:-1;;;;;96990:8:0;-1:-1:-1;;;;;96990:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97031:7;;;;;96939:110;97059:34;;:::i;:::-;97185:75;;;;;;;;;97243:16;97185:75;;;97109:176;;:152;;97185:75;;:52;97228:8;97185:37;97210:11;97185:24;:37::i;:52::-;:57;;:75::i;:::-;97109:52;97152:8;97109:42;:52::i;:::-;:75;;:152::i;:176::-;97059:226;;97372:15;97390:64;97431:22;:13;:11;:13::i;:22::-;97390:36;:27;:9;97405:11;97390:14;:27::i;:64::-;97372:82;;97465:40;;:::i;:::-;97508:31;;;;;;;;97524:14;:7;:12;:14::i;:::-;97508:31;;97465:74;-1:-1:-1;97550:41:0;;:::i;:::-;97594:33;:9;97609:17;97594:14;:33::i;:::-;97550:77;;97640:40;;:::i;:::-;97683:57;97702:17;97721:18;97683;:57::i;:::-;97640:100;;97751:46;;:::i;:::-;97800:3;;:33;;-1:-1:-1;;;97800:33:0;;-1:-1:-1;;;;;97800:3:0;;;;:18;;:33;;97827:4;;97800:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97751:82;-1:-1:-1;97912:36:0;:23;:5;97751:82;97912:10;:23::i;:::-;:34;:36::i;:::-;97908:880;;;97970:227;98001:17;:8;:15;:17::i;:::-;98037:12;98068:20;:11;:18;:20::i;:::-;98107:19;:11;:17;:19::i;:::-;98145:13;:5;:11;:13::i;:::-;98177:5;97970:227;;;;;;;;;;;:::i;:::-;;;;;;;;97908:880;;;98230:36;;:16;:36;98281:38;;:17;:38;98357:17;:15;:17::i;:::-;98334:20;:40;98467:20;:18;:20::i;:::-;98502:8;;;;;;;;;-1:-1:-1;;;;;98502:8:0;-1:-1:-1;;;;;98502:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98550:226;98581:17;:8;:15;:17::i;:::-;98617:12;98648:20;:11;:18;:20::i;:::-;98687:19;:11;:17;:19::i;:::-;98725:13;:5;:11;:13::i;:::-;98757:4;98550:226;;;;;;;;;;;:::i;:::-;;;;;;;;97908:880;96291:2504;;;;;;;;;;;:::o;77005:164::-;77076:22;;:::i;:::-;77118:43;77142:18;77118:23;:43::i;53553:39::-;;;;:::o;25604:244::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;25693:22:0;::::1;25685:73;;;;-1:-1:-1::0;;;25685:73:0::1;;;;;;;:::i;:::-;25795:6;::::0;25774:38:::1;::::0;-1:-1:-1;;;;;25774:38:0;;::::1;::::0;25795:6:::1;::::0;25774:38:::1;::::0;25795:6:::1;::::0;25774:38:::1;25823:6;:17:::0;;-1:-1:-1;;;;;;25823:17:0::1;-1:-1:-1::0;;;;;25823:17:0;;;::::1;::::0;;;::::1;::::0;;25604:244::o;68963:1130::-;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;69022:50:::1;;:::i;:::-;69075:55;::::0;;::::1;::::0;;::::1;::::0;;69094:16:::1;69075:55:::0;;;;;;;::::1;::::0;;;69112:17:::1;69075:55:::0;;;::::1;::::0;:18:::1;:55::i;:::-;69022:108;;69141:46;;:::i;:::-;69190:3;::::0;:33:::1;::::0;-1:-1:-1;;;69190:33:0;;-1:-1:-1;;;;;69190:3:0;;::::1;::::0;:18:::1;::::0;:33:::1;::::0;69217:4:::1;::::0;69190:33:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69141:82;;69234:47;;:::i;:::-;69284:33;:15:::0;69305:11;69284:20:::1;:33::i;:::-;69234:83;;69328:34;;:::i;:::-;69379:25;:12;:23;:25::i;:::-;69375:207;;;69435:23;::::0;;::::1;::::0;::::1;::::0;;;:18:::1;:23:::0;;;:42:::1;::::0;:36:::1;::::0;69459:11;69435:23:::1;:36::i;:42::-;69421:56;;69375:207;;;69524:23;::::0;;::::1;::::0;::::1;::::0;;;:18:::1;:23:::0;;;:46:::1;::::0;:40:::1;::::0;69548:15;69524:23:::1;:40::i;:46::-;69510:60;;69375:207;69594:52;;:::i;:::-;69662:66;::::0;;::::1;::::0;;::::1;::::0;;69710:17:::1;69662:66:::0;;;:42;;;;::::1;::::0;;;69687:16:::1;69662:42:::0;;;:66:::1;::::0;:42:::1;::::0;:24:::1;:42::i;:66::-;69594:134;;50263:3;69866:26;:17;:24;:26::i;:::-;:57;69862:149;;;69958:41;69975:23;:17;:21;:23::i;:::-;69958:11:::0;;:16:::1;:41::i;:::-;69940:59:::0;:15:::1;:59:::0;69862:149:::1;70023:4;:12:::0;;-1:-1:-1;;;;70023:12:0::1;::::0;;70060:22:::1;::::0;;::::1;::::0;::::1;::::0;;;:15:::1;:22:::0;;;70051:34:::1;::::0;70060:24:::1;::::0;:22:::1;:24::i;:::-;70051:34;;;;;;:::i;70506:103::-:0;24881:12;:10;:12::i;:::-;24871:6;;-1:-1:-1;;;;;24871:6:0;;;:22;;;24863:67;;;;-1:-1:-1;;;24863:67:0;;;;;;;:::i;:::-;70572:8:::1;:29:::0;;-1:-1:-1;;;;;;70572:29:0::1;-1:-1:-1::0;;;;;70572:29:0;;;::::1;::::0;;;::::1;::::0;;70506:103::o;54390:25::-;;;-1:-1:-1;;;54390:25:0;;;;;:::o;54283:44::-;;;-1:-1:-1;;;;;54283:44:0;;:::o;11669:106::-;11757:10;11669:106;:::o;21849:346::-;-1:-1:-1;;;;;21951:19:0;;21943:68;;;;-1:-1:-1;;;21943:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;22030:21:0;;22022:68;;;;-1:-1:-1;;;22022:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;22103:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;;:36;;;22155:32;;;;;22133:6;;22155:32;:::i;:::-;;;;;;;;21849:346;;;:::o;28410:95::-;28494:3;;28410:95::o;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;29373:173::-;29446:14;;:::i;:::-;29473:16;;:::i;:::-;29515:3;;29506;;:13;;:8;:13::i;:::-;29500:19;;;29373:173;-1:-1:-1;;;29373:173:0:o;28941:172::-;29014:14;;:::i;:::-;29041:16;;:::i;:::-;29082:3;;29074;;:12;;:7;:12::i;29810:173::-;29883:14;;:::i;:::-;29910:16;;:::i;:::-;29952:3;;29943;;:13;;:8;:13::i;46094:304::-;46246:34;;:::i;:::-;46225:1;45577;:3;;;-1:-1:-1;;;;;45562:18:0;;45582:21;;;;;;;;;;;;;;;;;45554:50;;;;;-1:-1:-1;;;45554:50:0;;;;;;;;:::i;:::-;;46298:36:::1;;:::i;:::-;46366:3:::0;;46351;;:20:::1;::::0;:7:::1;:20::i;:::-;46345:26:::0;;;46094:304;-1:-1:-1;;;;46094:304:0:o;46507:::-;46659:34;;:::i;:::-;46638:1;45577;:3;;;-1:-1:-1;;;;;45562:18:0;;45582:21;;;;;;;;;;;;;;;;;45554:50;;;;;-1:-1:-1;;;45554:50:0;;;;;;;;:::i;:::-;;46711:36:::1;;:::i;:::-;46779:3:::0;;46764;;:20:::1;::::0;:7:::1;:20::i;19461:539::-:0;-1:-1:-1;;;;;19567:20:0;;19559:70;;;;-1:-1:-1;;;19559:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;19648:23:0;;19640:71;;;;-1:-1:-1;;;19640:71:0;;;;;;;:::i;:::-;19724:47;19745:6;19753:9;19764:6;19724:20;:47::i;:::-;19804:71;19826:6;19804:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19804:17:0;;;;;;:9;:17;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;19784:17:0;;;;;;;:9;:17;;;;;;:91;;;;19909:20;;;;;;;:32;;19934:6;19909:24;:32::i;:::-;-1:-1:-1;;;;;19886:20:0;;;;;;;:9;:20;;;;;;;:55;;;;19957:35;;;;;;;;;;19985:6;;19957:35;:::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;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46:0;;;;;;;:::i;20282:378::-;-1:-1:-1;;;;;20366:21:0;;20358:65;;;;-1:-1:-1;;;20358:65:0;;;;;;;:::i;:::-;20436:49;20465:1;20469:7;20478:6;20436:20;:49::i;:::-;20513:12;;:24;;20530:6;20513:16;:24::i;:::-;20498:12;:39;-1:-1:-1;;;;;20569:18:0;;;;;;:9;:18;;;;;;:30;;20592:6;20569:22;:30::i;:::-;-1:-1:-1;;;;;20548:18:0;;;;;;:9;:18;;;;;;:51;;;;20615:37;;20548:18;;;20615:37;;;;20645:6;;20615:37;:::i;:::-;;;;;;;;20282:378;;:::o;45868:121::-;45945:7;45972;:1;:5;:7::i;:::-;:9;;45868:121;-1:-1:-1;;45868:121:0:o;35373:269::-;35433:22;;:::i;:::-;35468:24;;:::i;:::-;35507:3;;35513:1;-1:-1:-1;35503:113:0;;;35549:3;;;35545:7;35531:22;;35503:113;;;35600:3;;35586:18;;-1:-1:-1;35586:18:0;35373:269::o;45632:228::-;45753:34;;:::i;:::-;45732:1;45577;:3;;;-1:-1:-1;;;;;45562:18:0;;45582:21;;;;;;;;;;;;;;;;;45554:50;;;;;-1:-1:-1;;;45554:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;45812:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;45847:3;;45812:40;;-1:-1:-1;45812:40:0;45632:228::o;36417:185::-;36493:20;;:::i;:::-;36526:22;;:::i;:::-;36565:3;;:10;;36573:1;36565:7;:10::i;88481:549::-;88671:22;;:::i;:::-;88706:33;;:::i;:::-;88763:26;88750:39;;;88823:16;:23;:30;;:27;:30::i;:::-;88800:20;;;:53;88864:12;;;;88883:4;88864:23;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88898:12:0;;;;;;:24;;:39;;;88948:12;:20;88971:6;88948:29;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88995:27:0;89004:6;89012:9;88995:8;:27::i;28194:91::-;28233:14;;:::i;:::-;-1:-1:-1;28267:10:0;;;;;;;;;-1:-1:-1;28267:10:0;;28194:91;:::o;29157:172::-;29230:14;;:::i;:::-;29257:16;;:::i;:::-;29298:3;;29290;;:12;;:7;:12::i;47678:304::-;47830:34;;:::i;:::-;47809:1;45577;:3;;;-1:-1:-1;;;;;45562:18:0;;45582:21;;;;;;;;;;;;;;;;;45554:50;;;;;-1:-1:-1;;;45554:50:0;;;;;;;;:::i;:::-;;47882:36:::1;;:::i;:::-;47933:22;47940:14;47952:1;47940:11;:14::i;:::-;47933:1:::0;;:6:::1;:22::i;28513:159::-:0;28586:14;;:::i;:::-;28620:44;;;;;;;;28660:1;:3;;;28628:29;28636:20;28653:2;28636:16;:20::i;:::-;28628:3;;;:7;:29::i;:::-;:35;;;;;;28620:44;;28613:51;28513:159;-1:-1:-1;;;28513:159:0:o;28293:109::-;28331:14;;:::i;:::-;28365:29;;;;;;;;28373:20;28390:2;28373:16;:20::i;94943:664::-;95211:1;95187:21;:13;:19;:21::i;:::-;:25;95183:417;;;95229:52;;:::i;:::-;95301:143;;;;;;;;;95427:16;95301:143;;;95342:56;;;;;;;;50421:3;95342:56;;95301:171;;:143;;;:98;;:13;;:40;:98::i;:::-;:125;;:143::i;:171::-;95229:243;-1:-1:-1;95554:1:0;95495:55;:20;95229:243;95495:24;:55::i;:::-;:60;;;;95487:101;;;;-1:-1:-1;;;95487:101:0;;;;;;;:::i;:::-;95183:417;94943:664;;:::o;94054:881::-;94240:1;94206:31;:22;:29;:31::i;:::-;:35;94202:726;;;94272:16;:23;94310:37;;:::i;:::-;94350:16;94373:1;94367:3;:7;94350:25;;;;;;;;;;;;;;;;;94310:65;;;;;;;;94350:25;;;;;;;94310:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;94310:65:0;;;;;;;;;;;-1:-1:-1;94516:14:0;:12;:14::i;:::-;94486;:26;;;:44;:55;;;;;94540:1;94534:3;:7;94486:55;94482:138;;;94579:16;94602:1;94596:3;:7;94579:25;;;;;;;;;;;;;;;;;94562:42;;;;;;;;94579:25;;;;;;;94562:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;94562:42:0;;;;;;;;;;;-1:-1:-1;94482:138:0;94708:40;;;;;;;;;94731:16;94708:40;;;:22;;;;;;;;:17;:22;;;94663:186;;94708:40;;:22;:40::i;:::-;94771:22;94816:14;94663:22;:186::i;:::-;94662:187;94636:280;;;;-1:-1:-1;;;94636:280:0;;;;;;;:::i;63069:2064::-;63184:45;;:::i;:::-;-1:-1:-1;63184:64:0;;;;;;;;;63232:16;63184:64;;;63259:46;;:::i;:::-;-1:-1:-1;63259:66:0;;;;;;;;;63308:17;63259:66;;;63336:44;;:::i;:::-;63391:43;;:::i;:::-;63445:44;;:::i;:::-;63500:43;;:::i;:::-;63594:1;63560:31;:22;:29;:31::i;:::-;:35;63556:794;;;63743:34;;:::i;:::-;63797:91;63824:14;63840:22;63864:11;63877:10;63797:26;:91::i;:::-;63743:145;;63995:47;64009:19;64030:11;63995:13;:47::i;:::-;63976:66;:16;:66;64081:29;:11;64098;64081:16;:29::i;:::-;64057:53;-1:-1:-1;64148:39:0;:10;64164:22;64148:15;:39::i;:::-;64226:22;;;;;;;;;:17;:22;;;64125:62;;-1:-1:-1;64226:35:0;;64249:11;64226:22;:35::i;:::-;64299:39;;;;;;;;;64321:16;64299:39;;;:21;;;;;;;;:16;:21;;;64202:59;;-1:-1:-1;64299:39:0;;:21;:39::i;:::-;64276:62;;63556:794;;64401:1;64366:32;:23;:30;:32::i;:::-;:36;64362:764;;;64550:34;;:::i;:::-;64604:220;64653:19;64695:23;64741:21;64785:20;64604:26;:220::i;:::-;64550:274;;64932:182;64976:14;65009:11;65039:21;65079:20;64932:25;:182::i;:::-;64912:202;:17;:202;-1:-1:-1;64362:764:0;63069:2064;;;;;;;;:::o;10235:604::-;10677:4;10788:17;10824:7;10235:604;:::o;24245:129::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;9940:101;24303:26:::1;:24;:26::i;:::-;24340;:24;:26::i;:::-;10071:14:::0;10067:68;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;24245:129;:::o;14053:181::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;9940:101;14151:26:::1;:24;:26::i;:::-;14188:38;14211:5;14218:7;14188:22;:38::i;:::-;10071:14:::0;10067:68;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;14053:181;;;:::o;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;48863:108::-;48948:15;48863:108;:::o;48979:102::-;49061:12;48979:102;:::o;2352:471::-;2410:7;2655:6;2651:47;;-1:-1:-1;2685:1:0;2678:8;;2651:47;2722:5;;;2726:1;2722;:5;:1;2746:5;;;;;:10;2738:56;;;;-1:-1:-1;;;2738:56:0;;;;;;;:::i;28680:222::-;28779:3;;28773;;28752:4;;-1:-1:-1;28769:107:0;;;-1:-1:-1;28806:1:0;28799:8;;28769:107;28835:3;;28829;;:9;28825:51;;;-1:-1:-1;;;28855:9:0;;28825:51;-1:-1:-1;28893:1:0;28680:222;;;;:::o;20993:418::-;-1:-1:-1;;;;;21077:21:0;;21069:67;;;;-1:-1:-1;;;21069:67:0;;;;;;;:::i;:::-;21149:49;21170:7;21187:1;21191:6;21149:20;:49::i;:::-;21232:68;21255:6;21232:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;21232:18:0;;;;;;:9;:18;;;;;;;:68;:22;:68::i;:::-;-1:-1:-1;;;;;21211:18:0;;;;;;:9;:18;;;;;:89;21326:12;;:24;;21343:6;21326:16;:24::i;:::-;21311:12;:39;21366:37;;21392:1;;-1:-1:-1;;;;;21366:37:0;;;;;;;21396:6;;21366:37;:::i;87122:1351::-;87341:14;87333:4;:22;;;;;;;;;87329:868;;;87392:22;;;;;;;;;:17;:22;;;:41;;87415:17;87392:22;:41::i;:::-;87372:61;:17;:61;87467:21;;;;;;;;;:16;:21;;;:39;;87489:16;87467:21;:39::i;:::-;87448:58;:16;:58;87555:36;;;;;;;;;:31;:36;;;:54;;87592:16;87555:36;:54::i;:::-;87521:88;:31;:88;87644:22;;;;;;;;;:17;:22;;;:40;;87667:16;87644:22;:40::i;:::-;87624:60;:17;:60;87720:23;;;;;;;;;:18;:23;;;:42;;87744:17;87720:23;:42::i;:::-;87699:63;:18;:63;87329:868;;;87815:22;;;;;;;;;:17;:22;;;:41;;87838:17;87815:22;:41::i;:::-;87795:61;:17;:61;87890:21;;;;;;;;;:16;:21;;;:39;;87912:16;87890:21;:39::i;:::-;87871:58;:16;:58;87978:36;;;;;;;;;:31;:36;;;:54;;88015:16;87978:36;:54::i;:::-;87944:88;:31;:88;88067:22;;;;;;;;;:17;:22;;;:40;;88090:16;88067:22;:40::i;:::-;88047:60;:17;:60;88143:23;;;;;;;;;:18;:23;;;:42;;88167:17;88143:23;:42::i;:::-;88122:63;:18;:63;87329:868;88267:21;88262:99;;88305:44;;;;;;;;;88327:21;88305:44;;;;;:21;:44::i;:::-;88445:20;:18;:20::i;:::-;87122:1351;;;;:::o;84981:2133::-;85192:22;;:::i;:::-;85231:25;:16;:23;:25::i;:::-;85227:84;;85285:14;:12;:14::i;85227:84::-;85333:19;85325:4;:27;;;;;;;;;85321:333;;;85428:25;:16;:23;:25::i;:::-;85377:38;;;;;;;;;85399:15;85377:38;;;:21;;;;;;;;:16;:21;;;:47;;:38;;:21;:38::i;:47::-;:76;;85369:107;;;;-1:-1:-1;;;85369:107:0;;;;;;;:::i;:::-;85511:22;;;;;;;;;:17;:22;;;:40;;85534:16;85511:22;:40::i;:::-;85491:60;:17;:60;85321:333;;;85603:21;;;;;;;;;:16;:21;;;:39;;85625:16;85603:21;:39::i;:::-;85584:58;:16;:58;85321:333;85666:39;;:::i;:::-;85708:38;85723:4;85729:16;85708:14;:38::i;:::-;85666:80;;86063:31;:22;:29;:31::i;:::-;:36;86059:427;;86128:14;86120:4;:22;;;;;;;;;86116:359;;;86226:31;:22;:29;:31::i;:::-;86197:25;:16;:23;:25::i;:::-;:60;;86189:102;;;;-1:-1:-1;;;86189:102:0;;;;;;;:::i;:::-;86116:359;;;86394:31;:22;:29;:31::i;:::-;86365:25;:16;:23;:25::i;:::-;:60;;86357:102;;;;-1:-1:-1;;;86357:102:0;;;;;;;:::i;:::-;86633:21;86628:146;;86695:67;86721:4;86727:16;86745;86695:25;:67::i;:::-;86671:91;;86628:146;86786:198;86822:14;86814:4;:22;;;;;;;;;:61;;86861:14;86814:61;;;86839:19;86814:61;86890:16;86921;86952:21;86786:13;:198::i;:::-;87002:70;87013:4;87019:25;:16;:23;:25::i;:::-;87046;:16;:23;:25::i;:::-;87002:70;;;;;;;;:::i;:::-;;;;;;;;87090:16;84981:2133;-1:-1:-1;;;;;84981:2133:0:o;47269:329::-;47387:34;;:::i;:::-;47462:1;-1:-1:-1;;;;;47447:16:0;;47465:21;;;;;;;;;;;;;;;;;47439:48;;;;;-1:-1:-1;;;47439:48:0;;;;;;;;:::i;:::-;;47498:36;;:::i;:::-;47549:22;:1;47568;47549:11;:22::i;36898:185::-;36974:20;;:::i;:::-;37007:22;;:::i;:::-;37046:3;;:10;;37054:1;37046:7;:10::i;83923:308::-;84102:39;:16;84124;84102:21;:39::i;:::-;84088:53;:11;:53;;;84176:17;;;;;;;;;;;;84157:66;;84176:19;;:17;:19::i;:::-;84197:25;:16;:23;:25::i;46891:304::-;47043:34;;:::i;:::-;47022:1;45577;:3;;;-1:-1:-1;;;;;45562:18:0;;45582:21;;;;;;;;;;;;;;;;;45554:50;;;;;-1:-1:-1;;;45554:50:0;;;;;;;;:::i;:::-;;47095:36:::1;;:::i;:::-;47146:22;47153:14;47165:1;47153:11;:14::i;:::-;47146:1:::0;;:6:::1;:22::i;35681:196::-:0;35766:20;;:::i;:::-;35799:22;;:::i;:::-;35846:3;;35838;;:12;;:7;:12::i;49257:385::-;49305:7;49333:1;49329;:5;49325:310;;;49363:1;49399;49395;49391:5;;:9;49415:92;49426:1;49422;:5;49415:92;;;49452:1;49448:5;;49490:1;49485;49481;49477;:5;;;;;;:9;49476:15;;;;;;49472:19;;49415:92;;;-1:-1:-1;49528:1:0;-1:-1:-1;49521:8:0;;49325:310;49551:6;;49547:88;;-1:-1:-1;49581:1:0;49574:8;;49547:88;-1:-1:-1;49622:1:0;49615:8;;35200:165;35267:4;35294:1;35288;:3;;;:7;35284:51;;;-1:-1:-1;35319:4:0;35312:11;;35284:51;-1:-1:-1;35352:5:0;35200:165;;;:::o;84239:734::-;84289:20;84312:14;:12;:14::i;:::-;84378:16;84395:23;;84289:37;;-1:-1:-1;84337:38:0;;-1:-1:-1;;84395:27:0;;;84378:45;;;;;;;;;;;;;;;;84337:86;;84513:14;:26;;;84497:12;:42;84493:365;;;84591:17;84556:52;;;84657:16;84623:50;:31;;;:50;84493:365;;;84746:85;;;;;;;;84762:17;84746:85;;;;;;;;;;;;;;;;;84781:16;84746:85;;;;;;84706:16;;-1:-1:-1;;84799:17:0;:15;:17::i;:::-;84746:85;;;;;;;;;84706:140;;;;;;;;-1:-1:-1;84706:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84493:365;84892:24;;;;;;;;;:17;:24;;;84873:92;;84892:26;;:24;:26::i;:::-;84920:23;;;;;;;;;:16;:23;;;:25;;:23;:25::i;:::-;84947:17;:15;:17::i;:::-;84873:92;;;;;;;;:::i;89038:312::-;89113:22;;:::i;:::-;89148:33;;:::i;:::-;89205:28;89192:41;;89267:16;:23;:30;;89295:1;89267:27;:30::i;:::-;89244:20;;;:53;89315:27;89244:6;89332:9;89315:8;:27::i;35921:196::-;36006:20;;:::i;:::-;36039:22;;:::i;:::-;36086:3;;36078;;:12;;:7;:12::i;27128:108::-;27187:7;27214:14;27219:1;27222;27225:2;27214:4;:14::i;27603:108::-;27662:7;27689:14;27694:1;27697;27700:2;27689:4;:14::i;32777:215::-;32833:6;32863:5;;;32888:6;;;;;;:16;;;32903:1;32898;:6;;32888:16;32887:38;;;;32914:1;32910;:5;:14;;;;;32923:1;32919;:5;32910:14;32879:84;;;;-1:-1:-1;;;32879:84:0;;;;;;;:::i;32314:218::-;32370:6;32400:5;;;32425:6;;;;;;:16;;;32440:1;32435;:6;;32425:16;32424:38;;;;32451:1;32447;:5;:14;;;;;32460:1;32456;:5;32447:14;32416:87;;;;-1:-1:-1;;;32416:87:0;;;;;;;:::i;30750:568::-;30806:6;31050;31046:47;;-1:-1:-1;31080:1:0;31073:8;;31046:47;31115:1;-1:-1:-1;;31115:7:0;:27;;;;;-1:-1:-1;;;31126:1:0;:16;31115:27;31113:30;31105:82;;;;-1:-1:-1;;;31105:82:0;;;;;;;:::i;:::-;31211:5;;;31215:1;31211;:5;:1;31235:5;;;;;:10;31227:62;;;;-1:-1:-1;;;31227:62:0;;;;;;;:::i;89358:2406::-;89481:22;;:::i;:::-;89521:35;;:::i;:::-;89559:37;89588:7;89559:28;:37::i;:::-;89521:75;-1:-1:-1;89611:14:0;89607:66;;89649:12;-1:-1:-1;89642:19:0;;89607:66;89685:21;89709:32;89731:9;89709:17;:15;:17::i;:::-;:21;;:32::i;:::-;89685:56;;89752:38;;:::i;:::-;89793:16;89810:7;:21;;;89793:39;;;;;;;;;;;;;;;;;89752:80;;;;;;;;89793:39;;;;;;;89752:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89752:80:0;;;;;;;;;;;89997:16;:23;89752:80;;-1:-1:-1;89997:28:0;;:74;;;90058:13;90029:15;:25;;;:42;;89997:74;89993:126;;;90095:12;90088:19;;;;;;;89993:126;90159:25;;;;90131;90212:40;90159:25;90212:17;:15;:17::i;:40::-;90195:57;;90263:36;;:::i;:::-;90302:30;:12;90325:6;90302:22;:30::i;:::-;90263:69;;90343:1362;90424:21;;;;90420:105;;90478:31;:13;90502:6;90478:23;:31::i;:::-;90471:38;;;;;;;;;;90420:105;90565:21;;;;:28;;90591:1;90565:25;:28::i;:::-;90541:21;;;:52;;;90626:16;:39;;:16;;90541:52;90626:39;;;;;;;;;;;;;;;90608:57;;;;;;;;90626:39;;;;;;;90608:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;90608:57:0;;;;;;;;;;;-1:-1:-1;90695:37:0;90724:7;90695:28;:37::i;:::-;90680:52;;90864:13;90835:15;:25;;;:42;90831:580;;91291:80;91310:60;91333:36;:17;91355:13;91333:21;:36::i;:::-;91310:12;;:22;:60::i;:::-;91291:13;;:18;:80::i;:::-;91275:96;;91390:5;;90831:580;91427:20;91450:48;91472:15;:25;;;91450:17;:21;;:48;;;;:::i;:::-;91427:71;-1:-1:-1;91529:56:0;91548:36;:12;91427:71;91548:22;:36::i;:::-;91529:13;;:18;:56::i;:::-;91513:72;-1:-1:-1;91609:24:0;:6;91620:12;91609:10;:24::i;:::-;91600:33;;91668:15;:25;;;91648:45;;90343:1362;;;;91722:34;:13;91746:9;91722:23;:34::i;:::-;91715:41;89358:2406;-1:-1:-1;;;;;;;;;89358:2406:0:o;36644:197::-;36729:20;;:::i;:::-;36762:22;;:::i;:::-;36810:3;;36801;;:13;;:8;:13::i;26538:109::-;26622:17;;26618:2;:21;;26538:109::o;95615:668::-;95816:4;95833:32;;:::i;:::-;95901:26;;;;95868:27;;:60;;:32;:60::i;:::-;95833:95;;95939:33;;:::i;:::-;95975:58;95990:42;96009:22;95990:13;:11;:13::i;:::-;:18;;:42::i;95975:58::-;95939:94;;96044:33;;:::i;:::-;96080:58;96095:42;96114:22;96095:13;:11;:13::i;:::-;:18;;:42::i;96080:58::-;96044:94;-1:-1:-1;96181:1:0;96155:22;:6;96166:10;96155;:22::i;:::-;:27;;;;:58;;;;-1:-1:-1;96212:1:0;96186:22;:6;96197:10;96186;:22::i;:::-;:27;;;;96155:58;96151:103;;;96237:5;96230:12;;;;;;;96151:103;-1:-1:-1;96271:4:0;;95615:668;-1:-1:-1;;;;;;95615:668:0:o;11598:65::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;10071:14;10067:68;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;11598:65;:::o;24382:196::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;9940:101;24450:17:::1;24470:12;:10;:12::i;:::-;24493:6;:18:::0;;-1:-1:-1;;;;;;24493:18:0::1;-1:-1:-1::0;;;;;24493:18:0;::::1;::::0;;::::1;::::0;;;24527:43:::1;::::0;24493:18;;-1:-1:-1;24493:18:0;-1:-1:-1;;24527:43:0::1;::::0;-1:-1:-1;;24527:43:0::1;10053:1;10071:14:::0;10067:68;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;24382:196;:::o;14242:182::-;9779:13;;;;;;;;:33;;;9796:16;:14;:16::i;:::-;9779:50;;;-1:-1:-1;9817:12:0;;;;9816:13;9779:50;9771:109;;;;-1:-1:-1;;;9771:109:0;;;;;;;:::i;:::-;9893:19;9916:13;;;;;;9915:14;9940:101;;;;9975:13;:20;;-1:-1:-1;;;;9975:20:0;;;;;10010:19;9991:4;10010:19;;;9940:101;14350:13;;::::1;::::0;:5:::1;::::0;:13:::1;::::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;14374:17:0;;::::1;::::0;:7:::1;::::0;:17:::1;::::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;14402:9:0::1;:14:::0;;-1:-1:-1;;14402:14:0::1;14414:2;14402:14;::::0;;10067:68;;;;10118:5;10102:21;;-1:-1:-1;;10102:21:0;;;14242:182;;;:::o;3927:278::-;4013:7;4048:12;4041:5;4033:28;;;;-1:-1:-1;;;4033:28:0;;;;;;;;:::i;:::-;;4072:9;4088:1;4084;:5;;;;;;;3927:278;-1:-1:-1;;;;;3927:278:0:o;93317:729::-;93502:4;93519:47;;:::i;:::-;93591:14;93583:4;:22;;;;;;;;;93582:238;;93780:21;;;;;;;;;:16;:21;;;93733:87;;93780:39;;93802:16;93780:21;:39::i;:::-;93733:22;;;;;;;;;:17;:22;;;:41;;93756:17;93733:22;:41::i;:::-;:46;;:87::i;:::-;93582:238;;;93673:21;;;;;;;;;:16;:21;;;93626:87;;93673:39;;93695:16;93673:21;:39::i;:::-;93626:22;;;;;;;;;:17;:22;;;:41;;93649:17;93626:22;:41::i;:87::-;93851:187;;;;;;;;;93935:21;93851:187;;;93975:16;93992:23;;93519:301;;-1:-1:-1;93851:187:0;;93519:301;;93851:187;93975:16;93992:30;;94020:1;93992:27;:30::i;:::-;93975:48;;;;;;;;;;;;;;;;;93851:187;;;;;;;;93975:48;;;;;;;93851:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93851:187:0;;;;;;;;;;:22;:187::i;31792:271::-;31848:6;31875;31867:51;;;;-1:-1:-1;;;31867:51:0;;;;;;;:::i;:::-;31939:1;-1:-1:-1;;31939:7:0;:27;;;;;-1:-1:-1;;;31950:1:0;:16;31939:27;31937:30;31929:76;;;;-1:-1:-1;;;31929:76:0;;;;;;;:::i;:::-;32018:8;32033:1;32029;:5;;;;;;;31792:271;-1:-1:-1;;;;31792:271:0:o;36161:197::-;36246:20;;:::i;:::-;36279:22;;:::i;:::-;36327:3;;36318;;:13;;:8;:13::i;27337:172::-;27446:7;27473:28;27486:14;27491:8;27486:4;:14::i;:::-;27473:8;:1;27479;27473:5;:8::i;27813:172::-;27922:7;27949:28;27975:1;27949:21;27955:14;27960:8;27955:4;:14::i;:::-;27949:1;;:5;:21::i;91772:1537::-;91912:22;;:::i;:::-;91952:31;;:::i;:::-;91986:16;92003:6;:20;;;91986:38;;;;;;;;;;;;;;;;91952:72;;;;;;;;91986:38;;;;;;;91952:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;91952:72:0;;;;;;;;;-1:-1:-1;92201:10:0;;:42;;;;;;;;;92197:1064;;;92299:25;;;;92267:26;;:58;;:31;:58::i;:::-;92260:65;;;;;92197:1064;92361:26;92347:10;;:40;;;;;;;;;92343:918;;;92408:33;:6;:12;;;:24;;;:31;:33::i;:::-;92404:100;;92474:14;:12;:14::i;92404:100::-;92546:22;92522:6;:12;;;:20;;;:46;;;;;;;;;92518:732;;;92669:12;;;;:16;;92712:24;;;;;92763:26;;92816:25;;;;92617:247;;92763:26;92617:25;:247::i;92518:732::-;92914:23;92890:6;:12;;;:20;;;:47;;;;;;;;;92886:364;;;93039:12;;;;:16;;93082:24;;;;;93133:26;;93186:25;;;;92986:248;;93133:26;92986;:248::i;92886:364::-;93271:30;;-1:-1:-1;;;93271:30:0;;;;;;;:::i;29600:168::-;29671:14;;:::i;:::-;29698:16;;:::i;:::-;29731:3;;:10;;29739:1;29731:7;:10::i;30035:168::-;30106:14;;:::i;:::-;30133:16;;:::i;:::-;30166:3;;:10;;30174:1;30166:7;:10::i;34368:105::-;34425:6;34451:14;34456:1;34459;34462:2;34451:4;:14::i;33899:105::-;33956:6;33982:14;33987:1;33990;33993:2;33982:4;:14::i;34575:169::-;34682:6;34708:28;34734:1;34708:21;34714:14;34719:8;34714:4;:14::i;:::-;34708:1;;:5;:21::i;:::-;:25;;:28::i;34105:169::-;34212:6;34238:28;34251:14;34256:8;34251:4;:14::i;:::-;34238:8;:1;34244;34238:5;:8::i;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;921:146;996:20;;60030:1;60020:12;;60010:2;;60046:1;;60036:12;1379:158;;1490:2;1481:6;1476:3;1472:16;1468:25;1465:2;;;-1:-1;;1496:12;1465:2;-1:-1;1516:15;1458:79;-1:-1;1458:79::o;1573:320::-;;1687:4;1675:9;1670:3;1666:19;1662:30;1659:2;;;-1:-1;;1695:12;1659:2;1723:20;1687:4;1723:20;:::i;:::-;2735;;1797:75;;-1:-1;1714:29;1653:240;-1:-1;1653:240::o;2946:241::-;;3050:2;3038:9;3029:7;3025:23;3021:32;3018:2;;;-1:-1;;3056:12;3018:2;85:6;72:20;97:33;124:5;97:33;:::i;3194:366::-;;;3315:2;3303:9;3294:7;3290:23;3286:32;3283:2;;;-1:-1;;3321:12;3283:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3373:63;-1:-1;3473:2;3512:22;;72:20;97:33;72:20;97:33;:::i;:::-;3481:63;;;;3277:283;;;;;:::o;3567:491::-;;;;3705:2;3693:9;3684:7;3680:23;3676:32;3673:2;;;-1:-1;;3711:12;3673:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3763:63;-1:-1;3863:2;3902:22;;72:20;97:33;72:20;97:33;:::i;:::-;3667:391;;3871:63;;-1:-1;;;3971:2;4010:22;;;;2735:20;;3667:391::o;4065:366::-;;;4186:2;4174:9;4165:7;4161:23;4157:32;4154:2;;;-1:-1;;4192:12;4154:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4244:63;4344:2;4383:22;;;;2735:20;;-1:-1;;;4148:283::o;4438:235::-;;4539:2;4527:9;4518:7;4514:23;4510:32;4507:2;;;-1:-1;;4545:12;4507:2;219:6;206:20;231:30;255:5;231:30;:::i;4680:615::-;;;;4880:2;4868:9;4859:7;4855:23;4851:32;4848:2;;;-1:-1;;4886:12;4848:2;4948:61;5001:7;4977:22;4948:61;:::i;:::-;4938:71;;5064:80;5136:7;5046:2;5116:9;5112:22;5064:80;:::i;:::-;5054:90;;5199:80;5271:7;5181:2;5251:9;5247:22;5199:80;:::i;:::-;5189:90;;4842:453;;;;;:::o;5302:735::-;;;;;5516:3;5504:9;5495:7;5491:23;5487:33;5484:2;;;-1:-1;;5523:12;5484:2;1009:6;996:20;1021:41;1056:5;1021:41;:::i;:::-;5575:71;-1:-1;5701:80;5773:7;5683:2;5749:22;;5701:80;:::i;:::-;5691:90;;5836:80;5908:7;5818:2;5888:9;5884:22;5836:80;:::i;:::-;5826:90;;5953:2;5993:9;5989:22;206:20;231:30;255:5;231:30;:::i;:::-;5478:559;;;;-1:-1;5478:559;;-1:-1;;5478:559::o;6044:432::-;;;6198:2;6186:9;6177:7;6173:23;6169:32;6166:2;;;-1:-1;;6204:12;6166:2;6266:61;6319:7;6295:22;6266:61;:::i;:::-;6256:71;;6382:78;6452:7;6364:2;6432:9;6428:22;6382:78;:::i;:::-;6372:88;;6160:316;;;;;:::o;6483:783::-;;;;;6721:3;6709:9;6700:7;6696:23;6692:33;6689:2;;;-1:-1;;6728:12;6689:2;1009:6;996:20;1021:41;1056:5;1021:41;:::i;:::-;6780:71;-1:-1;6906:78;6976:7;6888:2;6952:22;;6906:78;:::i;:::-;6896:88;;7039:78;7109:7;7021:2;7089:9;7085:22;7039:78;:::i;:::-;7029:88;;7172:78;7242:7;7154:2;7222:9;7218:22;7172:78;:::i;:::-;7162:88;;6683:583;;;;;;;:::o;7273:295::-;;7404:2;7392:9;7383:7;7379:23;7375:32;7372:2;;;-1:-1;;7410:12;7372:2;7472:80;7544:7;7520:22;7472:80;:::i;7575:474::-;;;7750:2;7738:9;7729:7;7725:23;7721:32;7718:2;;;-1:-1;;7756:12;7718:2;7818:80;7890:7;7866:22;7818:80;:::i;:::-;7808:90;;7953:80;8025:7;7935:2;8005:9;8001:22;7953:80;:::i;8056:291::-;;8185:2;8173:9;8164:7;8160:23;8156:32;8153:2;;;-1:-1;;8191:12;8153:2;8253:78;8323:7;8299:22;8253:78;:::i;8354:466::-;;;8525:2;8513:9;8504:7;8500:23;8496:32;8493:2;;;-1:-1;;8531:12;8493:2;8593:78;8663:7;8639:22;8593:78;:::i;8827:325::-;;8973:2;8961:9;8952:7;8948:23;8944:32;8941:2;;;-1:-1;;8979:12;8941:2;2481:20;8973:2;2481:20;:::i;:::-;1286:13;;2555:85;;-1:-1;2562:16;8935:217;-1:-1;8935:217::o;9159:653::-;;;;9366:9;9357:7;9353:23;9378:2;9353:23;9349:32;9346:2;;;-1:-1;;9384:12;9346:2;2061:4;2040:19;2036:30;2033:2;;;-1:-1;;2069:12;2033:2;;2097:20;2061:4;2097:20;:::i;:::-;1140;;2171:74;;2178:16;-1:-1;9585:78;9655:7;2061:4;9631:22;;9585:78;:::i;:::-;9575:88;;9718:78;9788:7;9700:2;9768:9;9764:22;9718:78;:::i;9819:241::-;;9923:2;9911:9;9902:7;9898:23;9894:32;9891:2;;;-1:-1;;9929:12;9891:2;-1:-1;2735:20;;9885:175;-1:-1;9885:175::o;10067:263::-;;10182:2;10170:9;10161:7;10157:23;10153:32;10150:2;;;-1:-1;;10188:12;10150:2;-1:-1;2883:13;;10144:186;-1:-1;10144:186::o;10337:366::-;;;10458:2;10446:9;10437:7;10433:23;10429:32;10426:2;;;-1:-1;;10464:12;10426:2;-1:-1;;2735:20;;;10616:2;10655:22;;;340:20;;-1:-1;10420:283::o;10710:1729::-;;;;;;;;;;;;;11053:3;11041:9;11032:7;11028:23;11024:33;11021:2;;;-1:-1;;11060:12;11021:2;2748:6;2735:20;11112:63;;11212:2;11255:9;11251:22;2735:20;11220:63;;11320:2;11363:9;11359:22;2735:20;11328:63;;11428:2;11471:9;11467:22;2735:20;11436:63;;11536:3;11599:9;11595:22;72:20;97:33;124:5;97:33;:::i;:::-;11545:82;-1:-1;11664:3;11717:22;;72:20;97:33;72:20;97:33;:::i;:::-;11673:76;-1:-1;11786:3;11844:22;;72:20;97:33;72:20;97:33;:::i;:::-;11795:81;-1:-1;11913:3;11953:22;;340:20;;-1:-1;12022:3;12062:22;;72:20;97:33;72:20;97:33;:::i;:::-;12031:63;;;;12131:3;12175:9;12171:22;2735:20;12140:63;;12240:3;12285:9;12281:22;2735:20;12249:64;;12350:3;12395:9;12391:22;2735:20;12359:64;;11015:1424;;;;;;;;;;;;;;:::o;30865:222::-;-1:-1;;;;;57068:54;;;;12517:37;;30992:2;30977:18;;30963:124::o;31094:210::-;56350:13;;56343:21;12631:34;;31215:2;31200:18;;31186:118::o;31311:222::-;12748:37;;;31438:2;31423:18;;31409:124::o;31540:333::-;12748:37;;;31859:2;31844:18;;12748:37;31695:2;31680:18;;31666:207::o;32946:456::-;33135:2;33120:18;;59086:1;59076:12;;59066:2;;59092:9;59066:2;13556:56;;;33305:2;33290:18;;12748:37;;;;33388:2;33373:18;;;12748:37;33106:296;:::o;33970:310::-;;34117:2;;34138:17;34131:47;13993:5;55973:12;56130:6;34117:2;34106:9;34102:18;56118:19;-1:-1;58700:101;58714:6;58711:1;58708:13;58700:101;;;58781:11;;;;;58775:18;58762:11;;;56158:14;58762:11;58755:39;58729:10;;58700:101;;;58816:6;58813:1;58810:13;58807:2;;;-1:-1;56158:14;58872:6;34106:9;58863:16;;58856:27;58807:2;-1:-1;58988:7;58972:14;-1:-1;;58968:28;14151:39;;;;56158:14;14151:39;;34088:192;-1:-1;;;34088:192::o;34287:416::-;34487:2;34501:47;;;14427:2;34472:18;;;56118:19;14463:34;56158:14;;;14443:55;-1:-1;;;14518:12;;;14511:27;14557:12;;;34458:245::o;34710:416::-;34910:2;34924:47;;;14808:2;34895:18;;;56118:19;-1:-1;;;56158:14;;;14824:44;14887:12;;;34881:245::o;35133:416::-;35333:2;35347:47;;;15138:2;35318:18;;;56118:19;-1:-1;;;56158:14;;;15154:44;15217:12;;;35304:245::o;35556:416::-;35756:2;35770:47;;;15468:2;35741:18;;;56118:19;-1:-1;;;56158:14;;;15484:39;15542:12;;;35727:245::o;35979:416::-;36179:2;36193:47;;;15793:2;36164:18;;;56118:19;-1:-1;;;56158:14;;;15809:43;15871:12;;;36150:245::o;36402:416::-;36602:2;36616:47;;;16122:2;36587:18;;;56118:19;16158:34;56158:14;;;16138:55;-1:-1;;;16213:12;;;16206:30;16255:12;;;36573:245::o;36825:416::-;37025:2;37039:47;;;16506:2;37010:18;;;56118:19;16542:34;56158:14;;;16522:55;-1:-1;;;16597:12;;;16590:26;16635:12;;;36996:245::o;37248:416::-;37448:2;37462:47;;;16886:2;37433:18;;;56118:19;16922:29;56158:14;;;16902:50;16971:12;;;37419:245::o;37671:416::-;37871:2;37885:47;;;17222:2;37856:18;;;56118:19;17258:27;56158:14;;;17238:48;17305:12;;;37842:245::o;38094:416::-;38294:2;38308:47;;;17556:2;38279:18;;;56118:19;17592:28;56158:14;;;17572:49;17640:12;;;38265:245::o;38517:416::-;38717:2;38731:47;;;17891:2;38702:18;;;56118:19;17927:34;56158:14;;;17907:55;-1:-1;;;17982:12;;;17975:25;18019:12;;;38688:245::o;38940:416::-;39140:2;39154:47;;;18270:2;39125:18;;;56118:19;-1:-1;;;56158:14;;;18286:41;18346:12;;;39111:245::o;39363:416::-;39563:2;39577:47;;;18597:2;39548:18;;;56118:19;18633:30;56158:14;;;18613:51;18683:12;;;39534:245::o;39786:416::-;39986:2;40000:47;;;18934:2;39971:18;;;56118:19;-1:-1;;;56158:14;;;18950:38;19007:12;;;39957:245::o;40209:416::-;40409:2;40423:47;;;19258:2;40394:18;;;56118:19;-1:-1;;;56158:14;;;19274:38;19331:12;;;40380:245::o;40632:416::-;40832:2;40846:47;;;19582:2;40817:18;;;56118:19;19618:33;56158:14;;;19598:54;19671:12;;;40803:245::o;41055:416::-;41255:2;41269:47;;;19922:2;41240:18;;;56118:19;19958:34;56158:14;;;19938:55;-1:-1;;;20013:12;;;20006:38;20063:12;;;41226:245::o;41478:416::-;41678:2;41692:47;;;20314:2;41663:18;;;56118:19;20350:34;56158:14;;;20330:55;-1:-1;;;20405:12;;;20398:25;20442:12;;;41649:245::o;41901:416::-;42101:2;42115:47;;;20693:2;42086:18;;;56118:19;20729:31;56158:14;;;20709:52;20780:12;;;42072:245::o;42324:416::-;42524:2;42538:47;;;21031:2;42509:18;;;56118:19;21067:34;56158:14;;;21047:55;-1:-1;;;21122:12;;;21115:25;21159:12;;;42495:245::o;42747:416::-;42947:2;42961:47;;;21410:2;42932:18;;;56118:19;21446:30;56158:14;;;21426:51;21496:12;;;42918:245::o;43170:416::-;43370:2;43384:47;;;43355:18;;;56118:19;21783:34;56158:14;;;21763:55;21837:12;;;43341:245::o;43593:416::-;43793:2;43807:47;;;22088:2;43778:18;;;56118:19;-1:-1;;;56158:14;;;22104:43;22166:12;;;43764:245::o;44016:416::-;44216:2;44230:47;;;22417:2;44201:18;;;56118:19;22453:34;56158:14;;;22433:55;-1:-1;;;22508:12;;;22501:31;22551:12;;;44187:245::o;44439:416::-;44639:2;44653:47;;;22802:2;44624:18;;;56118:19;22838:34;56158:14;;;22818:55;-1:-1;;;22893:12;;;22886:25;22930:12;;;44610:245::o;44862:416::-;45062:2;45076:47;;;23181:2;45047:18;;;56118:19;23217:34;56158:14;;;23197:55;-1:-1;;;23272:12;;;23265:29;23313:12;;;45033:245::o;45285:416::-;45485:2;45499:47;;;23564:2;45470:18;;;56118:19;-1:-1;;;56158:14;;;23580:36;23635:12;;;45456:245::o;45708:416::-;45908:2;45922:47;;;23886:2;45893:18;;;56118:19;-1:-1;;;56158:14;;;23902:42;23963:12;;;45879:245::o;46131:416::-;46331:2;46345:47;;;24214:2;46316:18;;;56118:19;24250:31;56158:14;;;24230:52;24301:12;;;46302:245::o;46554:416::-;46754:2;46768:47;;;24552:2;46739:18;;;56118:19;24588:30;56158:14;;;24568:51;24638:12;;;46725:245::o;46977:416::-;47177:2;47191:47;;;24889:2;47162:18;;;56118:19;24925:34;56158:14;;;24905:55;-1:-1;;;24980:12;;;24973:28;25020:12;;;47148:245::o;47400:416::-;47600:2;47614:47;;;25271:2;47585:18;;;56118:19;-1:-1;;;56158:14;;;25287:45;25351:12;;;47571:245::o;47823:416::-;48023:2;48037:47;;;25602:2;48008:18;;;56118:19;25638:26;56158:14;;;25618:47;25684:12;;;47994:245::o;48246:416::-;48446:2;48460:47;;;25935:2;48431:18;;;56118:19;-1:-1;;;56158:14;;;25951:45;26015:12;;;48417:245::o;48669:416::-;48869:2;48883:47;;;26266:2;48854:18;;;56118:19;-1:-1;;;56158:14;;;26282:36;26337:12;;;48840:245::o;49092:416::-;49292:2;49306:47;;;26588:2;49277:18;;;56118:19;26624:34;56158:14;;;26604:55;-1:-1;;;26679:12;;;26672:28;26719:12;;;49263:245::o;49515:416::-;49715:2;49729:47;;;26970:2;49700:18;;;56118:19;-1:-1;;;56158:14;;;26986:43;27048:12;;;49686:245::o;49938:416::-;50138:2;50152:47;;;50123:18;;;56118:19;27335:34;56158:14;;;27315:55;27389:12;;;50109:245::o;50361:416::-;50561:2;50575:47;;;27640:2;50546:18;;;56118:19;27676:33;56158:14;;;27656:54;27729:12;;;50532:245::o;50784:391::-;28105:23;;29988;12748:37;;28351:4;28340:16;;;28334:23;29200;28461:14;;;12748:37;28567:4;28556:16;;;28550:23;29200;28677:14;;;12748:37;28784:4;28773:16;;;28767:23;29988;28906:14;;;12748:37;;;;50995:3;50980:19;;50966:209::o;51182:322::-;29200:23;;12748:37;;51359:2;51344:18;;51330:174::o;51511:533::-;29200:23;;12748:37;;29200:23;52030:2;52015:18;;12748:37;51766:2;51751:18;;51737:307::o;52051:756::-;29200:23;;12748:37;;29200:23;;52627:2;52612:18;;12748:37;52710:2;52695:18;;12748:37;52793:2;52778:18;;12748:37;52362:3;52347:19;;52333:474::o;53736:440::-;12748:37;;;54081:2;54066:18;;12748:37;;;;54162:2;54147:18;;12748:37;53917:2;53902:18;;53888:288::o;54634:760::-;12748:37;;;55056:2;55041:18;;12748:37;;;;55139:2;55124:18;;12748:37;;;;55220:2;55205:18;;12748:37;55301:3;55286:19;;12748:37;56350:13;56343:21;55379:3;55364:19;;12631:34;54891:3;54876:19;;54862:532::o;55401:214::-;57284:4;57273:16;;;;30818:35;;55524:2;55509:18;;55495:120::o;55622:256::-;55684:2;55678:9;55710:17;;;55785:18;55770:34;;55806:22;;;55767:62;55764:2;;;55842:1;;55832:12;55764:2;55684;55851:22;55662:216;;-1:-1;55662:216::o;59115:117::-;-1:-1;;;;;57068:54;;59174:35;;59164:2;;59223:1;;59213:12;59239:111;59320:5;56350:13;56343:21;59298:5;59295:32;59285:2;;59341:1;;59331:12;59953:102;60030:1;60023:5;60020:12;60010:2;;60046:1;;60036:12

Swarm Source

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