Contract 0x7a11ab7fa91ae252d9630f20ad695fdeef06cf3e

Contract Overview

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

Contract Source Code Verified (Exact Match)

Contract Name:
CFD

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

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




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

    function setExchange(IExchange _exchange) external;

    function setBeneficiary(address _beneficiary) external;
}

// File: contracts/interface/ISystemSettings.sol





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

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

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

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

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

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

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

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

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

    function overnightFeePeriod() external view returns (uint256);

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

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

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

    function setNextOvernightFeeTime(IExchange _exchange) external;

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

// File: contracts/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/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/ICFDState.sol





interface ICFDState {
    struct TradingState {
        uint256  lastestLongTime;
        uint256  lastestShortTime;
    }

    struct RemainMarginInfo {
        Decimal.decimal remainMargin;
        Decimal.decimal badDebt;
        SignedDecimal.signedDecimal fundingPayment;
        Decimal.decimal overnightFee;
    }

    function checkWaitingPeriod(address _exchange, address _trader, ICFD.Side _side) external returns (bool);

    function updateOpenInterestNotional(IExchange _exchange, SignedDecimal.signedDecimal memory _amount) external;

    function getWhiteList() external view returns (address);

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

    function calcPositionAfterLiquidityMigration(
        IExchange _exchange,
        ICFD.Position memory _position,
        uint256 _latestLiquidityIndex
    ) external view returns (ICFD.Position memory);

    function calcRemainMarginWithFundingPaymentAndOvernightFee(
        IExchange _exchange,
        ICFD.Position memory _oldPosition,
        SignedDecimal.signedDecimal memory _marginDelta
    ) external view returns (
        RemainMarginInfo memory remainMarginInfo
    );
}

// File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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






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

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

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

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

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

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

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

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

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


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


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 * 
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 * 
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        // solhint-disable-next-line no-inline-assembly
        assembly { cs := extcodesize(self) }
        return cs == 0;
    }
}

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




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

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

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

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




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

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

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

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

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

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

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

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

// File: contracts/CFD.sol
















// note BaseRelayRecipient must come after OwnerPausableUpgradeSafe so its msg.sender takes precedence
// (yes, the ordering is reversed comparing to Python)
contract CFD is ICFD, OwnableUpgradeable, BlockContext {
    using Decimal for Decimal.decimal;
    using SignedDecimal for SignedDecimal.signedDecimal;
    using MixedDecimal for SignedDecimal.signedDecimal;
    using SafeERC20Upgradeable for IERC20Upgradeable;
    using SafeMathUpgradeable for uint256;
    //
    // EVENTS
    //
    event MarginChanged(
        address indexed sender,
        address indexed exchange,
        int256 amount,
        int256 fundingPayment,
        uint256 overnightFee
    );
    event PositionAdjusted(
        address indexed exchange,
        address indexed trader,
        int256 newPositionSize,
        uint256 oldLiquidityIndex,
        uint256 newLiquidityIndex
    );
    event PositionSettled(address indexed exchange, address indexed trader, uint256 valueTransferred);
    event RestrictionModeEntered(address exchange, uint256 blockNumber);

    /// @notice This event is emitted when position change
    /// @param trader the address which execute this transaction
    /// @param exchange IExchange address
    /// @param margin margin
    /// @param positionNotional margin * leverage
    /// @param exchangedPositionSize position size, e.g. ETHUSDC or LINKUSDC
    /// @param fee transaction fee
    /// @param positionSizeAfter position size after this transaction, might be increased or decreased
    /// @param realizedPnl realized pnl after this position changed
    /// @param unrealizedPnlAfter unrealized pnl after this position changed
    /// @param badDebt position change amount cleared by insurance funds
    /// @param liquidationPenalty amount of remaining margin lost due to liquidation
    /// @param spotPrice quote asset reserve / base asset reserve
    /// @param fundingPayment funding payment (+: trader paid, -: trader received)
    /// @param overnightPayment overnight payment
    event PositionChanged(
        address indexed trader,
        address indexed exchange,
        uint256 margin,
        uint256 positionNotional,
        int256 exchangedPositionSize,
        uint256 fee,
        int256 positionSizeAfter,
        int256 realizedPnl,
        int256 unrealizedPnlAfter,
        uint256 badDebt,
        uint256 liquidationPenalty,
        uint256 spotPrice,
        int256 fundingPayment,
        uint256 overnightPayment
    );

    /// @notice This event is emitted when position liquidated
    /// @param trader the account address being liquidated
    /// @param exchange IExchange address
    /// @param positionNotional liquidated position value minus liquidationFee
    /// @param positionSize liquidated position size
    /// @param liquidationFee liquidation fee to the liquidator
    /// @param liquidator the address which execute this transaction
    /// @param badDebt liquidation fee amount cleared by insurance funds
    event PositionLiquidated(
        address indexed trader,
        address indexed exchange,
        uint256 positionNotional,
        uint256 positionSize,
        uint256 liquidationFee,
        address liquidator,
        uint256 badDebt
    );

    /// @notice This event is emitted when overnight fee payed
    /// @param exchange exchange address
    /// @param totalOpenNotional the total open notional
    /// @param overnightFee the total overinight fee this time
    /// @param rate current overnight feerate
    event OvernightFeePayed(address indexed exchange, uint256 totalOpenNotional, uint256 overnightFee, uint256 rate);

    /// @notice This struct is used for avoiding stack too deep error when passing too many var between functions
    struct PositionResp {
        Position position;
        // the quote asset amount trader will send if open position, will receive if close
        Decimal.decimal exchangedQuoteAssetAmount;
        // if realizedPnl + realizedFundingPayment + margin is negative, it's the abs value of it
        Decimal.decimal badDebt;
        // the base asset amount trader will receive if open position, will send if close
        SignedDecimal.signedDecimal exchangedPositionSize;
        // funding payment incurred during this position response
        SignedDecimal.signedDecimal fundingPayment;
        // overnight payment incurred during this position response
        Decimal.decimal overnightFee;
        // realizedPnl = unrealizedPnl * closedRatio
        SignedDecimal.signedDecimal realizedPnl;
        // positive = trader transfer margin to vault, negative = trader receive margin from vault
        // it's 0 when internalReducePosition, its addedMargin when internalIncreasePosition
        // it's min(0, oldPosition + realizedFundingPayment + realizedPnl) when internalClosePosition
        SignedDecimal.signedDecimal marginToVault;
        // unrealized pnl after open position
        SignedDecimal.signedDecimal unrealizedPnlAfter;
    }

    struct ExchangeMap {
        // issue #1471
        // last block when it turn restriction mode on.
        // In restriction mode, no one can do multi open/close/liquidate position in the same block.
        // If any underwater position being closed (having a bad debt and make insuranceFund loss),
        // or any liquidation happened,
        // restriction mode is ON in that block and OFF(default) in the next block.
        // This design is to prevent the attacker being benefited from the multiple action in one block
        // in extreme cases
        uint256 lastRestrictionBlock;
        SignedDecimal.signedDecimal[] cumulativePremiumFractions;
        Decimal.decimal[] cumulativeOvernightFeerates;
        mapping(address => Position) positionMap;
        Decimal.decimal totalOpenNotional;
    }

    //**********************************************************//
    //    Can not change the order of below state variables     //
    //**********************************************************//
    // key by exchange address
    mapping(address => ExchangeMap) internal exchangeMap;

    ISystemSettings public systemSettings;

    ICFDVault public cfdVault;
    ICFDState public cfdState;

    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private status;
    bool public paused;
    //**********************************************************//
    //    Can not change the order of above state variables     //
    //**********************************************************//

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

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

    //
    // FUNCTIONS
    //
    // openzeppelin doesn't support struct input
    // https://github.com/OpenZeppelin/openzeppelin-sdk/issues/1523
    function initialize(
        address _systemsettings,
        address _cfdVault,
        address _cfdState
    ) public initializer {
        __Ownable_init();

        systemSettings = ISystemSettings(_systemsettings);
        cfdVault = ICFDVault(_cfdVault);
        cfdState = ICFDState(_cfdState);
        status = _NOT_ENTERED;
        paused = false;
    }

    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        status = _NOT_ENTERED;
    }

    modifier whenNotPaused() {
        require(!paused, "Pausable: paused");
        _;
    }

    //
    // External
    //
    /**
     * @dev set system settings
     */
    function setSystemSettings(ISystemSettings _systemSettings) external onlyOwner {
        systemSettings = _systemSettings;
    }

    /**
     * @notice add margin to increase margin ratio
     * @param _exchange IExchange address
     * @param _addedMargin added margin in 18 digits
     */
    function addMargin(IExchange _exchange, Decimal.decimal calldata _addedMargin)
        external
        whenNotPaused()
        nonReentrant()
    {
        // check condition
        requireExchange(_exchange, true);
        requireNonZeroInput(_addedMargin);

        // update margin part in personal position
        address trader = msg.sender;
        Position memory position = adjustPositionForLiquidityChanged(_exchange, trader);
        position.margin = position.margin.addD(_addedMargin);
        setPosition(_exchange, trader, position);

        // transfer token from trader
        IERC20Upgradeable(_exchange.quoteAsset()).safeTransferFrom(trader, address(cfdVault), _addedMargin.toUint());

        emit MarginChanged(trader, address(_exchange), int256(_addedMargin.toUint()), 0, 0);
    }

    /**
     * @notice remove margin to decrease margin ratio
     * @param _exchange IExchange address
     * @param _removedMargin removed margin in 18 digits
     */
    function removeMargin(IExchange _exchange, Decimal.decimal calldata _removedMargin)
        external
        whenNotPaused()
        nonReentrant()
    {
        // check condition
        requireExchange(_exchange, true);
        requireNonZeroInput(_removedMargin);

        // update margin part in personal position
        address trader = msg.sender;
        Position memory position = adjustPositionForLiquidityChanged(_exchange, trader);

        // realize funding payment if there's no bad debt
        SignedDecimal.signedDecimal memory marginDelta = MixedDecimal.fromDecimal(_removedMargin).mulScalar(-1);
        ICFDState.RemainMarginInfo memory remainMarginInfo =
            cfdState.calcRemainMarginWithFundingPaymentAndOvernightFee(_exchange, position, marginDelta);
        require(remainMarginInfo.badDebt.toUint() == 0, "margin is not enough");

        position.margin = remainMarginInfo.remainMargin;
        position.lastUpdatedCumulativePremiumFraction = getLatestCumulativePremiumFraction(_exchange);
        position.lastUpdatedCumulativeOvernightFeeRate = getLatestCumulativeOvernightFeeRate(_exchange);
        setPosition(_exchange, trader, position);

        // check margin ratio
        requireMoreMarginRatio(getMarginRatio(_exchange, trader), systemSettings.initMarginRatio(), true);

        // transfer token back to trader
        withdraw(_exchange, trader, _removedMargin);

        emit MarginChanged(
            trader,
            address(_exchange),
            marginDelta.toInt(),
            remainMarginInfo.fundingPayment.toInt(),
            remainMarginInfo.overnightFee.toUint()
        );
    }

    /**
     * @notice settle all the positions when exchange is shutdown. The settlement price is according to IExchange.settlementPrice
     * @param _exchange IExchange address
     */
    function settlePosition(IExchange _exchange) external nonReentrant() {
        // check condition
        requireExchange(_exchange, false);

        address trader = msg.sender;
        Position memory pos = getPosition(_exchange, trader);
        requirePositionSize(pos.size);

        // update position
        clearPosition(_exchange, trader);

        // calculate settledValue
        // If Settlement Price = 0, everyone takes back her collateral.
        // else Returned Fund = Position Size * (Settlement Price - Open Price) + Collateral
        Decimal.decimal memory settlementPrice = _exchange.getSettlementPrice();
        Decimal.decimal memory settledValue;
        if (settlementPrice.toUint() == 0) {
            settledValue = pos.margin;
        } else {
            // returnedFund = positionSize * (settlementPrice - openPrice) + positionMargin
            // openPrice = positionOpenNotional / positionSize.abs()
            SignedDecimal.signedDecimal memory returnedFund =
                pos
                    .size
                    .mulD(MixedDecimal.fromDecimal(settlementPrice).subD(pos.openNotional.divD(pos.size.abs())))
                    .addD(pos.margin);
            // if `returnedFund` is negative, trader can't get anything back
            if (returnedFund.toInt() > 0) {
                settledValue = returnedFund.abs();
            }
        }

        // transfer token based on settledValue. no insurance fund support
        if (settledValue.toUint() > 0) {
            withdraw(_exchange, trader, settledValue);
            //IERC20Upgradeable(_exchange.quoteAsset()).safeTransfer(trader, settledValue.toUint());
        }

        // emit event
        emit PositionSettled(address(_exchange), trader, settledValue.toUint());
    }

    // if increase position
    //   marginToVault = addMargin
    //   marginDiff = realizedFundingPayment + realizedPnl(0)
    //   pos.margin += marginToVault + marginDiff
    //   vault.margin += marginToVault + marginDiff
    //   required(enoughMarginRatio)
    // else if reduce position()
    //   marginToVault = 0
    //   marginDiff = realizedFundingPayment + realizedPnl
    //   pos.margin += marginToVault + marginDiff
    //   if pos.margin < 0, badDebt = abs(pos.margin), set pos.margin = 0
    //   vault.margin += marginToVault + marginDiff
    //   required(enoughMarginRatio)
    // else if close
    //   marginDiff = realizedFundingPayment + realizedPnl
    //   pos.margin += marginDiff
    //   if pos.margin < 0, badDebt = abs(pos.margin)
    //   marginToVault = -pos.margin
    //   set pos.margin = 0
    //   vault.margin += marginToVault + marginDiff
    // else if close and open a larger position in reverse side
    //   close()
    //   positionNotional -= exchangedQuoteAssetAmount
    //   newMargin = positionNotional / leverage
    //   internalIncreasePosition(newMargin, leverage)
    // else if liquidate
    //   close()
    //   pay liquidation fee to liquidator
    //   move the remain margin to insuranceFund

    /**
     * @notice open a position
     * @param _exchange exchange address
     * @param _side enum Side; BUY for long and SELL for short
     * @param _quoteAssetAmount quote asset amount in 18 digits. Can Not be 0
     * @param _leverage leverage  in 18 digits. Can Not be 0
     * @param _baseAssetAmountLimit minimum base asset amount expected to get to prevent from slippage.
     */
    function openPosition(
        IExchange _exchange,
        Side _side,
        Decimal.decimal calldata _quoteAssetAmount,
        Decimal.decimal calldata _leverage,
        Decimal.decimal calldata _baseAssetAmountLimit
    ) external whenNotPaused() nonReentrant() {
        requireExchange(_exchange, true);
        requireNonZeroInput(_quoteAssetAmount);
        requireNonZeroInput(_leverage);
        requireMoreMarginRatio(
            MixedDecimal.fromDecimal(Decimal.one()).divD(_leverage),
            systemSettings.initMarginRatio(),
            true
        );
        requireNotRestrictionMode(_exchange);

        address trader = msg.sender;
        require(
            cfdState.checkWaitingPeriod(address(_exchange), trader, _side),
            "cannot open position during waiting period"
        );

        PositionResp memory positionResp;
        {
            // add scope for stack too deep error
            int256 oldPositionSize = adjustPositionForLiquidityChanged(_exchange, trader).size.toInt();
            bool isNewPosition = oldPositionSize == 0 ? true : false;
            if (!isNewPosition) {
                requireMoreMarginRatio(
                    getMarginRatio(_exchange, trader),
                    systemSettings.maintenanceMarginRatio(),
                    true
                );
            }

            // increase or decrease position depends on old position's side and size
            if (isNewPosition || (oldPositionSize > 0 ? Side.BUY : Side.SELL) == _side) {
                positionResp = internalIncreasePosition(
                    _exchange,
                    _side,
                    _quoteAssetAmount.mulD(_leverage),
                    _baseAssetAmountLimit,
                    _leverage
                );
            } else {
                positionResp = openReversePosition(
                    _exchange,
                    _side,
                    _quoteAssetAmount,
                    _leverage,
                    _baseAssetAmountLimit
                );
            }

            // update the position state
            setPosition(_exchange, trader, positionResp.position);

            // to prevent attacker to leverage the bad debt to withdraw extra token from  insurance fund
            if (positionResp.badDebt.toUint() > 0) {
                enterRestrictionMode(_exchange);
            }

            //ransfer the actual token between trader and vault
            IERC20Upgradeable quoteToken = _exchange.quoteAsset();
            if (positionResp.marginToVault.toInt() > 0) {
                quoteToken.safeTransferFrom(trader, address(cfdVault), positionResp.marginToVault.abs().toUint());
            } else if (positionResp.marginToVault.toInt() < 0) {
                withdraw(_exchange, trader, positionResp.marginToVault.abs());
            }

            //check MM
            cfdVault.requireMMNotBankrupt(_exchange);
        }

        // calculate fee and transfer token for fees
        //@audit - can optimize by changing amm.swapInput/swapOutput's return type to (exchangedAmount, quoteToll, quoteSpread, quoteReserve, baseReserve) (@wraecca)
        Decimal.decimal memory transferredFee = transferFee(trader, _exchange, positionResp.exchangedQuoteAssetAmount);

        // emit event
        uint256 spotPrice = _exchange.getSpotPrice().toUint();
        int256 fundingPayment = positionResp.fundingPayment.toInt(); // pre-fetch for stack too deep error
        uint256 overnightFee = positionResp.overnightFee.toUint();
        emit PositionChanged(
            trader,
            address(_exchange),
            positionResp.position.margin.toUint(),
            positionResp.exchangedQuoteAssetAmount.toUint(),
            positionResp.exchangedPositionSize.toInt(),
            transferredFee.toUint(),
            positionResp.position.size.toInt(),
            positionResp.realizedPnl.toInt(),
            positionResp.unrealizedPnlAfter.toInt(),
            positionResp.badDebt.toUint(),
            0,
            spotPrice,
            fundingPayment,
            overnightFee
        );
    }

    /**
     * @notice close all the positions
     * @param _exchange IExchange address
     */
    function closePosition(IExchange _exchange, Decimal.decimal calldata _quoteAssetAmountLimit)
        external
        whenNotPaused()
        nonReentrant()
    {
        // check conditions
        requireExchange(_exchange, true);
        requireNotRestrictionMode(_exchange);

        // update position
        address trader = msg.sender;
        Position memory position = adjustPositionForLiquidityChanged(_exchange, trader);
        Side _side = position.size.isNegative() ? Side.BUY : Side.SELL;
        require(
            cfdState.checkWaitingPeriod(address(_exchange), trader, _side),
            "cannot close position during waiting period"
        );

        PositionResp memory positionResp = internalClosePosition(_exchange, trader, _quoteAssetAmountLimit, true);

        {
            // add scope for stack too deep error
            // transfer the actual token from trader and vault
            if (positionResp.badDebt.toUint() > 0) {
                enterRestrictionMode(_exchange);
                realizeBadDebt(_exchange, positionResp.badDebt);
            }
            withdraw(_exchange, trader, positionResp.marginToVault.abs());
        }

        //check MM
        cfdVault.requireMMNotBankrupt(_exchange);

        // calculate fee and transfer token for fees
        Decimal.decimal memory transferredFee = transferFee(trader, _exchange, positionResp.exchangedQuoteAssetAmount);

        {
            // avoid stack too deep
            // prepare event
            uint256 spotPrice = _exchange.getSpotPrice().toUint();
            int256 fundingPayment = positionResp.fundingPayment.toInt();
            uint256 overnightFee = positionResp.overnightFee.toUint();
            emit PositionChanged(
                trader,
                address(_exchange),
                0, // margin
                positionResp.exchangedQuoteAssetAmount.toUint(),
                positionResp.exchangedPositionSize.toInt(),
                transferredFee.toUint(),
                positionResp.position.size.toInt(),
                positionResp.realizedPnl.toInt(),
                0, // unrealizedPnl
                positionResp.badDebt.toUint(),
                0,
                spotPrice,
                fundingPayment,
                overnightFee
            );
        }
    }

    /**
     * @notice liquidate trader's underwater position. Require trader's margin ratio less than maintenance margin ratio
     * @dev liquidator can NOT open any positions in the same block to prevent from price manipulation.
     * @param _exchange IExchange address
     * @param _trader trader address
     */
    function liquidate(IExchange _exchange, address _trader) external nonReentrant() {
        // check conditions
        requireExchange(_exchange, true);
        requireMoreMarginRatio(getMarginRatio(_exchange, _trader), systemSettings.maintenanceMarginRatio(), false);

        // update states
        adjustPositionForLiquidityChanged(_exchange, _trader);
        PositionResp memory positionResp = internalClosePosition(_exchange, _trader, Decimal.zero(), false);
        enterRestrictionMode(_exchange);

        {
            // avoid stack too deep
            // Amount pay to liquidator
            Decimal.decimal memory liquidationFee =
                positionResp.exchangedQuoteAssetAmount.mulD(systemSettings.liquidationFeeRatio());
            if (liquidationFee.cmp(systemSettings.maxliquidationFee()) > 0) {
                liquidationFee = systemSettings.maxliquidationFee();
            }

            // neither trader nor liquidator should pay anything for liquidating position
            // in here, -marginToVault means remainMargin

            Decimal.decimal memory remainMargin = positionResp.marginToVault.abs();
            // add scope for stack too deep error
            // if the remainMargin is not enough for liquidationFee, count it as bad debt
            // else, then the rest will be transferred to insuranceFund
            Decimal.decimal memory liquidationBadDebt;
            Decimal.decimal memory totalBadDebt = positionResp.badDebt;
            SignedDecimal.signedDecimal memory totalMarginToVault = positionResp.marginToVault;
            if (liquidationFee.toUint() > remainMargin.toUint()) {
                liquidationBadDebt = liquidationFee.subD(remainMargin);
                totalBadDebt = totalBadDebt.addD(liquidationBadDebt);
            } else {
                totalMarginToVault = totalMarginToVault.addD(liquidationFee);
            }

            // transfer the actual token between trader and vault
            if (totalBadDebt.toUint() > 0) {
                realizeBadDebt(_exchange, totalBadDebt);
            }
            if (totalMarginToVault.toInt() < 0) {
                transferToInsuranceFund(_exchange, totalMarginToVault.abs());
            }
            withdraw(_exchange, msg.sender, liquidationFee);

            emit PositionLiquidated(
                _trader,
                address(_exchange),
                positionResp.exchangedQuoteAssetAmount.toUint(),
                positionResp.exchangedPositionSize.toUint(),
                liquidationFee.toUint(),
                msg.sender,
                liquidationBadDebt.toUint()
            );
        }

        {
            emit PositionChanged(
                _trader,
                address(_exchange),
                0,
                positionResp.exchangedQuoteAssetAmount.toUint(),
                positionResp.exchangedPositionSize.toInt(),
                0,
                0,
                positionResp.realizedPnl.toInt(),
                0,
                positionResp.badDebt.toUint(),
                positionResp.marginToVault.abs().toUint(),
                _exchange.getSpotPrice().toUint(),
                positionResp.fundingPayment.toInt(),
                positionResp.overnightFee.toUint()
            );
        }
    }

    /**
     * @notice if funding rate is positive, traders with long position pay traders with short position and vice versa.
     * @param _exchange IExchange address
     */
    function payFunding(IExchange _exchange) external {
        requireExchange(_exchange, true);

        // must copy the baseAssetDeltaThisFundingPeriod before settle funding
        SignedDecimal.signedDecimal memory baseAssetDeltaThisFundingPeriod =
            _exchange.getBaseAssetDeltaThisFundingPeriod();

        SignedDecimal.signedDecimal memory premiumFraction = _exchange.settleFunding();
        exchangeMap[address(_exchange)].cumulativePremiumFractions.push(
            premiumFraction.addD(getLatestCumulativePremiumFraction(_exchange))
        );

        // funding payment = premium fraction * position
        // eg. if alice takes 10 long position, baseAssetDeltaThisFundingPeriod = -10
        // if premiumFraction is positive: long pay short, amm get positive funding payment
        // if premiumFraction is negative: short pay long, amm get negative funding payment
        // if position side * premiumFraction > 0, funding payment is negative which means loss
        SignedDecimal.signedDecimal memory ammFundingPaymentLoss =
            premiumFraction.mulD(baseAssetDeltaThisFundingPeriod);

        if (ammFundingPaymentLoss.toInt() > 0) {
            realizeBadDebt(_exchange, ammFundingPaymentLoss.abs());
        } else {
            handleFundingFeeAndOvernightFee(
                _exchange,
                ammFundingPaymentLoss.abs(),
                systemSettings.fundingFeeLpShareRatio()
            );
            // address insuranceFundAddress = address(systemSettings.getInsuranceFund(_exchange));
            // require(insuranceFundAddress != address(0), "Invalid InsuranceFund");
            // Decimal.decimal memory insuranceFundFee =
            //     ammFundingPaymentLoss.abs().mulD(systemSettings.fundingFeeLpShareRatio());
            // cfdVault.withdraw(_exchange.quoteAsset(), insuranceFundAddress, insuranceFundFee);
            // Decimal.decimal memory fundingFee = ammFundingPaymentLoss.abs().subD(insuranceFundFee);
            // cfdVault.addCachedLiquidity(_exchange, fundingFee);
        }
    }

    /**
     * @notice if overnight fee rate is positive, traders with long position pay traders with short position and vice versa.
     * @param _exchange IExchange address
     */
    function payOvernightFee(IExchange _exchange) external {
        requireExchange(_exchange, true);
        systemSettings.setNextOvernightFeeTime(_exchange);

        Decimal.decimal memory overnightFeeRate = systemSettings.overnightFeeRatio();
        exchangeMap[address(_exchange)].cumulativeOvernightFeerates.push(
            overnightFeeRate.addD(getLatestCumulativeOvernightFeeRate(_exchange))
        );

        Decimal.decimal memory totalOpenNotional = exchangeMap[address(_exchange)].totalOpenNotional;
        Decimal.decimal memory exchageOvernightPayment = overnightFeeRate.mulD(totalOpenNotional);

        if (exchageOvernightPayment.toUint() > 0) {
            handleFundingFeeAndOvernightFee(
                _exchange,
                exchageOvernightPayment,
                systemSettings.overnightFeeLpShareRatio()
            );
        }

        emit OvernightFeePayed(
            address(_exchange),
            totalOpenNotional.toUint(),
            exchageOvernightPayment.toUint(),
            overnightFeeRate.toUint()
        );
    }

    /**
     * @notice adjust msg.sender's position when liquidity migration happened
     * @param _exchange Exchange address
     */
    function adjustPosition(IExchange _exchange) external {
        adjustPositionForLiquidityChanged(_exchange, msg.sender);
    }

    //
    // VIEW FUNCTIONS
    //
    /**
     * @notice get margin ratio, marginRatio = (margin + funding payments + unrealized Pnl) / openNotional
     * use spot and twap price to calculate unrealized Pnl, final unrealized Pnl depends on which one is higher
     * @param _exchange IExchange address
     * @param _trader trader address
     * @return margin ratio in 18 digits
     */
    function getMarginRatio(IExchange _exchange, address _trader)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        Position memory position = getPosition(_exchange, _trader);
        requirePositionSize(position.size);
        requireNonZeroInput(position.openNotional);

        (, SignedDecimal.signedDecimal memory spotPricePnl) =
            (getPositionNotionalAndUnrealizedPnl(_exchange, _trader, PnlCalcOption.SPOT_PRICE));

        (, SignedDecimal.signedDecimal memory twapPricePnl) =
            (getPositionNotionalAndUnrealizedPnl(_exchange, _trader, PnlCalcOption.TWAP));

        SignedDecimal.signedDecimal memory unrealizedPnl =
            spotPricePnl.toInt() > twapPricePnl.toInt() ? spotPricePnl : twapPricePnl;

        ICFDState.RemainMarginInfo memory remainMarginInfo =
            cfdState.calcRemainMarginWithFundingPaymentAndOvernightFee(_exchange, position, unrealizedPnl);
        return
            MixedDecimal.fromDecimal(remainMarginInfo.remainMargin).subD(remainMarginInfo.badDebt).divD(
                position.openNotional
            );
    }

    /**
     * @notice get personal position information, and adjust size if migration is necessary
     * @param _exchange IExchange address
     * @param _trader trader address
     * @return struct Position
     */
    function getPosition(IExchange _exchange, address _trader) public view override returns (Position memory) {
        Position memory pos = getUnadjustedPosition(_exchange, _trader);
        uint256 latestLiquidityIndex = _exchange.getLiquidityHistoryLength().sub(1);
        if (pos.liquidityHistoryIndex == latestLiquidityIndex) {
            return pos;
        }

        return cfdState.calcPositionAfterLiquidityMigration(_exchange, pos, latestLiquidityIndex);
    }

    /**
     * @notice get position notional and unrealized Pnl without fee expense and funding payment
     * @param _exchange IExchange address
     * @param _trader trader address
     * @param _pnlCalcOption enum PnlCalcOption, SPOT_PRICE for spot price and TWAP for twap price
     * @return positionNotional position notional
     * @return unrealizedPnl unrealized Pnl
     */
    function getPositionNotionalAndUnrealizedPnl(
        IExchange _exchange,
        address _trader,
        PnlCalcOption _pnlCalcOption
    )
        public
        view
        override
        returns (Decimal.decimal memory positionNotional, SignedDecimal.signedDecimal memory unrealizedPnl)
    {
        Position memory position = getPosition(_exchange, _trader);
        return cfdState.getPositionNotionalAndUnrealizedPnl(_exchange, position, _pnlCalcOption);
    }

    /**
     * @notice get latest cumulative premium fraction.
     * @param _exchange IExchange address
     * @return latest cumulative premium fraction in 18 digits
     */
    function getLatestCumulativePremiumFraction(IExchange _exchange)
        public
        view
        override
        returns (SignedDecimal.signedDecimal memory)
    {
        uint256 len = exchangeMap[address(_exchange)].cumulativePremiumFractions.length;
        if (len > 0) {
            return exchangeMap[address(_exchange)].cumulativePremiumFractions[len - 1];
        }
    }

    /**
     * @notice get latest cumulative overnight feerate.
     * @param _exchange IExchange address
     * @return latest cumulative overnight feerate in 18 digits
     */
    function getLatestCumulativeOvernightFeeRate(IExchange _exchange)
        public
        view
        override
        returns (Decimal.decimal memory)
    {
        uint256 len = exchangeMap[address(_exchange)].cumulativeOvernightFeerates.length;
        if (len > 0) {
            return exchangeMap[address(_exchange)].cumulativeOvernightFeerates[len - 1];
        }
    }

    /**
     * @notice get MM liquidity.
     * @param _exchange IExchange address
     * @return MM liquidity in 18 digits
     *
     */
    function getMMLiquidity(address _exchange) public view override returns (SignedDecimal.signedDecimal memory) {
        return cfdVault.getMMLiquidity(_exchange);
    }

    //
    // INTERNAL FUNCTIONS
    //

    function enterRestrictionMode(IExchange _exchange) internal {
        uint256 blockNumber = _blockNumber();
        exchangeMap[address(_exchange)].lastRestrictionBlock = blockNumber;
        emit RestrictionModeEntered(address(_exchange), blockNumber);
    }

    function setPosition(
        IExchange _exchange,
        address _trader,
        Position memory _position
    ) internal {
        Position storage positionStorage = exchangeMap[address(_exchange)].positionMap[_trader];
        exchangeMap[address(_exchange)].totalOpenNotional = exchangeMap[address(_exchange)].totalOpenNotional.subD(
            positionStorage.openNotional
        );
        positionStorage.size = _position.size;
        positionStorage.margin = _position.margin;
        positionStorage.openNotional = _position.openNotional;
        positionStorage.lastUpdatedCumulativePremiumFraction = _position.lastUpdatedCumulativePremiumFraction;
        positionStorage.lastUpdatedCumulativeOvernightFeeRate = _position.lastUpdatedCumulativeOvernightFeeRate;
        positionStorage.blockNumber = _position.blockNumber;
        positionStorage.liquidityHistoryIndex = _position.liquidityHistoryIndex;
        exchangeMap[address(_exchange)].totalOpenNotional = exchangeMap[address(_exchange)].totalOpenNotional.addD(
            positionStorage.openNotional
        );
    }

    function clearPosition(IExchange _exchange, address _trader) internal {
        Position memory position = exchangeMap[address(_exchange)].positionMap[_trader];
        exchangeMap[address(_exchange)].totalOpenNotional = exchangeMap[address(_exchange)].totalOpenNotional.subD(
            position.openNotional
        );

        // keep the record in order to retain the last updated block number
        exchangeMap[address(_exchange)].positionMap[_trader] = Position({
            size: SignedDecimal.zero(),
            margin: Decimal.zero(),
            openNotional: Decimal.zero(),
            lastUpdatedCumulativePremiumFraction: SignedDecimal.zero(),
            lastUpdatedCumulativeOvernightFeeRate: Decimal.zero(),
            blockNumber: _blockNumber(),
            liquidityHistoryIndex: 0
        });
    }

    // only called from openPosition and closeAndOpenReversePosition. caller need to ensure there's enough marginRatio
    function internalIncreasePosition(
        IExchange _exchange,
        Side _side,
        Decimal.decimal memory _openNotional,
        Decimal.decimal memory _minPositionSize,
        Decimal.decimal memory _leverage
    ) internal returns (PositionResp memory positionResp) {
        address trader = msg.sender;
        Position memory oldPosition = getUnadjustedPosition(_exchange, trader);
        positionResp.exchangedPositionSize = swapInput(_exchange, _side, _openNotional, _minPositionSize);
        SignedDecimal.signedDecimal memory newSize = oldPosition.size.addD(positionResp.exchangedPositionSize);
        // if size is 0 (means a new position), set the latest liquidity index
        uint256 liquidityHistoryIndex = oldPosition.liquidityHistoryIndex;
        if (oldPosition.size.toInt() == 0) {
            liquidityHistoryIndex = _exchange.getLiquidityHistoryLength().sub(1);
        }

        cfdState.updateOpenInterestNotional(_exchange, MixedDecimal.fromDecimal(_openNotional));
        // if the trader is not in the whitelist, check max position size
        if (trader != cfdState.getWhiteList()) {
            Decimal.decimal memory maxHoldingBaseAsset = _exchange.getMaxHoldingBaseAsset();
            if (maxHoldingBaseAsset.toUint() > 0) {
                // total position size should be less than `positionUpperBound`
                require(newSize.abs().cmp(maxHoldingBaseAsset) <= 0, "hit position size upper bound");
            }
        }

        Position memory position;
        {
            //avoid stakc too deep
            SignedDecimal.signedDecimal memory increaseMarginRequirement =
                MixedDecimal.fromDecimal(_openNotional.divD(_leverage));

            ICFDState.RemainMarginInfo memory remainMarginInfo =
                cfdState.calcRemainMarginWithFundingPaymentAndOvernightFee(
                    _exchange,
                    oldPosition,
                    increaseMarginRequirement
                );

            positionResp.marginToVault = increaseMarginRequirement;
            positionResp.fundingPayment = remainMarginInfo.fundingPayment;
            positionResp.overnightFee = remainMarginInfo.overnightFee;

            position.margin = remainMarginInfo.remainMargin;
        }

        {
            //avoid stack too deep
            (, SignedDecimal.signedDecimal memory unrealizedPnl) =
                getPositionNotionalAndUnrealizedPnl(_exchange, trader, PnlCalcOption.SPOT_PRICE);
            positionResp.unrealizedPnlAfter = unrealizedPnl;
        }

        // update positionResp
        positionResp.exchangedQuoteAssetAmount = _openNotional;
        position.size = newSize;
        position.openNotional = oldPosition.openNotional.addD(positionResp.exchangedQuoteAssetAmount);
        position.liquidityHistoryIndex = liquidityHistoryIndex;
        position.lastUpdatedCumulativePremiumFraction = getLatestCumulativePremiumFraction(_exchange);
        position.lastUpdatedCumulativeOvernightFeeRate = getLatestCumulativeOvernightFeeRate(_exchange);
        position.blockNumber = _blockNumber();
        positionResp.position = position;
    }

    function openReversePosition(
        IExchange _exchange,
        Side _side,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _leverage,
        Decimal.decimal memory _baseAssetAmountLimit
    ) internal returns (PositionResp memory) {
        Decimal.decimal memory openNotional = _quoteAssetAmount.mulD(_leverage);
        (Decimal.decimal memory oldPositionNotional, SignedDecimal.signedDecimal memory unrealizedPnl) =
            getPositionNotionalAndUnrealizedPnl(_exchange, msg.sender, PnlCalcOption.SPOT_PRICE);
        PositionResp memory positionResp;

        // reduce position if old position is larger
        if (oldPositionNotional.toUint() > openNotional.toUint()) {
            cfdState.updateOpenInterestNotional(_exchange, MixedDecimal.fromDecimal(openNotional).mulScalar(-1));
            Position memory oldPosition = getUnadjustedPosition(_exchange, msg.sender);
            positionResp.exchangedPositionSize = swapInput(_exchange, _side, openNotional, _baseAssetAmountLimit);

            // realizedPnl = unrealizedPnl * closedRatio
            // closedRatio = positionResp.exchangedPositionSiz / oldPosition.size
            if (oldPosition.size.toInt() != 0) {
                positionResp.realizedPnl = unrealizedPnl.mulD(positionResp.exchangedPositionSize.abs()).divD(
                    oldPosition.size.abs()
                );
            }

            //
            {
                //avoid stack too deep
                ICFDState.RemainMarginInfo memory remainMarginInfo =
                    cfdState.calcRemainMarginWithFundingPaymentAndOvernightFee(
                        _exchange,
                        oldPosition,
                        positionResp.realizedPnl
                    );

                positionResp.badDebt = remainMarginInfo.badDebt;
                positionResp.fundingPayment = remainMarginInfo.fundingPayment;
                positionResp.overnightFee = remainMarginInfo.overnightFee;
                positionResp.exchangedQuoteAssetAmount = openNotional;

                //stack too deep, temp use oldPosition
                oldPosition.margin = remainMarginInfo.remainMargin;
                //position.margin = remainMargin;
            }

            // positionResp.unrealizedPnlAfter = unrealizedPnl - realizedPnl
            positionResp.unrealizedPnlAfter = unrealizedPnl.subD(positionResp.realizedPnl);

            // calculate openNotional (it's different depends on long or short side)
            // long: unrealizedPnl = positionNotional - openNotional => openNotional = positionNotional - unrealizedPnl
            // short: unrealizedPnl = openNotional - positionNotional => openNotional = positionNotional + unrealizedPnl
            // positionNotional = oldPositionNotional - exchangedQuoteAssetAmount
            SignedDecimal.signedDecimal memory remainOpenNotional =
                oldPosition.size.toInt() > 0
                    ? MixedDecimal.fromDecimal(oldPositionNotional).subD(positionResp.exchangedQuoteAssetAmount).subD(
                        positionResp.unrealizedPnlAfter
                    )
                    : positionResp.unrealizedPnlAfter.addD(oldPositionNotional).subD(
                        positionResp.exchangedQuoteAssetAmount
                    );
            require(remainOpenNotional.toInt() > 0, "value of openNotional <= 0");

            {
                Position memory position;
                position.margin = oldPosition.margin;
                position.size = oldPosition.size.addD(positionResp.exchangedPositionSize);
                position.openNotional = remainOpenNotional.abs();
                position.liquidityHistoryIndex = oldPosition.liquidityHistoryIndex;
                position.lastUpdatedCumulativePremiumFraction = getLatestCumulativePremiumFraction(_exchange);
                position.lastUpdatedCumulativeOvernightFeeRate = getLatestCumulativeOvernightFeeRate(_exchange);
                position.blockNumber = _blockNumber();
                positionResp.position = position;
            }

            return positionResp;
        }

        return closeAndOpenReversePosition(_exchange, _side, _quoteAssetAmount, _leverage, _baseAssetAmountLimit);
    }

    function closeAndOpenReversePosition(
        IExchange _exchange,
        Side _side,
        Decimal.decimal memory _quoteAssetAmount,
        Decimal.decimal memory _leverage,
        Decimal.decimal memory _baseAssetAmountLimit
    ) internal returns (PositionResp memory positionResp) {
        // new position size is larger than or equal to the old position size
        // so either close or close then open a larger position
        PositionResp memory closePositionResp = internalClosePosition(_exchange, msg.sender, Decimal.zero(), true);
        // the old position is underwater. trader should close a position first
        require(closePositionResp.badDebt.toUint() == 0, "reduce an underwater position");

        // update open notional after closing position
        Decimal.decimal memory openNotional =
            _quoteAssetAmount.mulD(_leverage).subD(closePositionResp.exchangedQuoteAssetAmount);

        // if remain exchangedQuoteAssetAmount is too small (eg. 1wei) then the required margin might be 0
        // then the clearingHouse will stop opening position
        if (openNotional.divD(_leverage).toUint() == 0) {
            positionResp = closePositionResp;
        } else {
            Decimal.decimal memory updatedBaseAssetAmountLimit;
            if (_baseAssetAmountLimit.toUint() > closePositionResp.exchangedPositionSize.toUint()) {
                updatedBaseAssetAmountLimit = _baseAssetAmountLimit.subD(closePositionResp.exchangedPositionSize.abs());
            }

            PositionResp memory increasePositionResp =
                internalIncreasePosition(_exchange, _side, openNotional, updatedBaseAssetAmountLimit, _leverage);
            positionResp = PositionResp({
                position: increasePositionResp.position,
                exchangedQuoteAssetAmount: closePositionResp.exchangedQuoteAssetAmount.addD(
                    increasePositionResp.exchangedQuoteAssetAmount
                ),
                badDebt: closePositionResp.badDebt.addD(increasePositionResp.badDebt),
                fundingPayment: closePositionResp.fundingPayment.addD(increasePositionResp.fundingPayment),
                overnightFee: closePositionResp.overnightFee.addD(increasePositionResp.overnightFee),
                exchangedPositionSize: closePositionResp.exchangedPositionSize.addD(
                    increasePositionResp.exchangedPositionSize
                ),
                realizedPnl: closePositionResp.realizedPnl.addD(increasePositionResp.realizedPnl),
                unrealizedPnlAfter: SignedDecimal.zero(),
                marginToVault: closePositionResp.marginToVault.addD(increasePositionResp.marginToVault)
            });
        }
        return positionResp;
    }

    function internalClosePosition(
        IExchange _exchange,
        address _trader,
        Decimal.decimal memory _quoteAssetAmountLimit,
        bool _skipFluctuationCheck
    ) private returns (PositionResp memory positionResp) {
        // check conditions
        Position memory oldPosition = getUnadjustedPosition(_exchange, _trader);
        SignedDecimal.signedDecimal memory oldPositionSize = oldPosition.size;
        requirePositionSize(oldPositionSize);

        (, SignedDecimal.signedDecimal memory unrealizedPnl) =
            getPositionNotionalAndUnrealizedPnl(_exchange, _trader, PnlCalcOption.SPOT_PRICE);

        ICFDState.RemainMarginInfo memory remainMarginInfo =
            cfdState.calcRemainMarginWithFundingPaymentAndOvernightFee(_exchange, oldPosition, unrealizedPnl);

        positionResp.exchangedPositionSize = oldPositionSize.mulScalar(-1);
        positionResp.realizedPnl = unrealizedPnl;
        positionResp.badDebt = remainMarginInfo.badDebt;
        positionResp.fundingPayment = remainMarginInfo.fundingPayment;
        positionResp.overnightFee = remainMarginInfo.overnightFee;
        positionResp.marginToVault = MixedDecimal.fromDecimal(remainMarginInfo.remainMargin).mulScalar(-1);
        positionResp.exchangedQuoteAssetAmount = _exchange.swapOutput(
            oldPositionSize.toInt() > 0 ? IExchange.Dir.ADD_TO_AMM : IExchange.Dir.REMOVE_FROM_AMM,
            oldPositionSize.abs(),
            _quoteAssetAmountLimit,
            _skipFluctuationCheck
        );

        // bankrupt position's bad debt will be also consider as a part of the open interest
        cfdState.updateOpenInterestNotional(
            _exchange,
            unrealizedPnl.addD(remainMarginInfo.badDebt).addD(oldPosition.openNotional).mulScalar(-1)
        );
        clearPosition(_exchange, _trader);
    }

    function swapInput(
        IExchange _exchange,
        Side _side,
        Decimal.decimal memory _inputAmount,
        Decimal.decimal memory _minOutputAmount
    ) internal returns (SignedDecimal.signedDecimal memory) {
        IExchange.Dir dir = (_side == Side.BUY) ? IExchange.Dir.ADD_TO_AMM : IExchange.Dir.REMOVE_FROM_AMM;
        SignedDecimal.signedDecimal memory outputAmount =
            MixedDecimal.fromDecimal(_exchange.swapInput(dir, _inputAmount, _minOutputAmount));
        if (IExchange.Dir.REMOVE_FROM_AMM == dir) {
            return outputAmount.mulScalar(-1);
        }
        return outputAmount;
    }

    function transferFee(
        address _from,
        IExchange _exchange,
        Decimal.decimal memory _positionNotional
    ) internal returns (Decimal.decimal memory) {
        Decimal.decimal memory fee = _exchange.calcFee(_positionNotional);
        if (fee.toUint() > 0) {
            address insuranceFundAddress = address(systemSettings.getInsuranceFund(_exchange));
            require(insuranceFundAddress != address(0), "Invalid InsuranceFund");
            Decimal.decimal memory insuranceFundFee = fee.mulD(systemSettings.insuranceFundFeeRatio());
            IERC20Upgradeable(_exchange.quoteAsset()).safeTransferFrom(
                _from,
                address(insuranceFundAddress),
                insuranceFundFee.toUint()
            );
            Decimal.decimal memory lpFee = fee.subD(insuranceFundFee);
            IERC20Upgradeable(_exchange.quoteAsset()).safeTransferFrom(_from, address(cfdVault), lpFee.toUint());
            cfdVault.addCachedLiquidity(_exchange, lpFee);
            return fee;
        }

        return Decimal.zero();
    }

    function withdraw(
        IExchange _exchange,
        address _receiver,
        Decimal.decimal memory _amount
    ) internal {
        return cfdVault.withdraw(_exchange, _receiver, _amount);
    }

    function realizeBadDebt(IExchange _exchange, Decimal.decimal memory _badDebt) internal {
        return cfdVault.realizeBadDebt(_exchange, _badDebt);
    }

    function transferToInsuranceFund(IExchange _exchange, Decimal.decimal memory _amount) internal {
        IInsuranceFund insuranceFund = systemSettings.getInsuranceFund(_exchange);
        cfdVault.withdraw(_exchange, address(insuranceFund), _amount);
    }

    function handleFundingFeeAndOvernightFee(
        IExchange _exchange,
        Decimal.decimal memory _fee,
        Decimal.decimal memory _insuranceFundRatio
    ) internal {
        address insuranceFundAddress = address(systemSettings.getInsuranceFund(_exchange));
        require(insuranceFundAddress != address(0), "Invalid InsuranceFund");
        Decimal.decimal memory insuranceFundFee = _fee.mulD(_insuranceFundRatio);
        cfdVault.withdraw(_exchange, insuranceFundAddress, insuranceFundFee);
        Decimal.decimal memory vaultFee = _fee.subD(insuranceFundFee);
        cfdVault.addCachedLiquidity(_exchange, vaultFee);
    }

    //
    // INTERNAL VIEW FUNCTIONS
    //

    function adjustPositionForLiquidityChanged(IExchange _exchange, address _trader)
        internal
        returns (Position memory)
    {
        Position memory unadjustedPosition = getUnadjustedPosition(_exchange, _trader);
        if (unadjustedPosition.size.toInt() == 0) {
            return unadjustedPosition;
        }
        uint256 latestLiquidityIndex = _exchange.getLiquidityHistoryLength().sub(1);
        if (unadjustedPosition.liquidityHistoryIndex == latestLiquidityIndex) {
            return unadjustedPosition;
        }

        Position memory adjustedPosition =
            cfdState.calcPositionAfterLiquidityMigration(_exchange, unadjustedPosition, latestLiquidityIndex);
        setPosition(_exchange, _trader, adjustedPosition);
        emit PositionAdjusted(
            address(_exchange),
            _trader,
            adjustedPosition.size.toInt(),
            unadjustedPosition.liquidityHistoryIndex,
            adjustedPosition.liquidityHistoryIndex
        );
        return adjustedPosition;
    }

    function getUnadjustedPosition(IExchange _exchange, address _trader)
        public
        view
        override
        returns (Position memory position)
    {
        position = exchangeMap[address(_exchange)].positionMap[_trader];
    }

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

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

    function requirePositionSize(SignedDecimal.signedDecimal memory _size) private pure {
        require(_size.toInt() != 0, "positionSize is 0");
    }

    function requireNotRestrictionMode(IExchange _exchange) private view {
        uint256 currentBlock = _blockNumber();
        if (currentBlock == exchangeMap[address(_exchange)].lastRestrictionBlock) {
            require(
                getUnadjustedPosition(_exchange, msg.sender).blockNumber != currentBlock,
                "only one action allowed"
            );
        }
    }

    function requireMoreMarginRatio(
        SignedDecimal.signedDecimal memory _marginRatio,
        Decimal.decimal memory _baseMarginRatio,
        bool _largerThanOrEqualTo
    ) private pure {
        int256 remainingMarginRatio = _marginRatio.subD(_baseMarginRatio).toInt();
        require(
            _largerThanOrEqualTo ? remainingMarginRatio >= 0 : remainingMarginRatio < 0,
            "Margin ratio not meet criteria"
        );
    }

    //
    // Set System Open Flag
    //
    function pause(bool _pause) public onlyOwner {
        paused = _pause;
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"int256","name":"amount","type":"int256"},{"indexed":false,"internalType":"int256","name":"fundingPayment","type":"int256"},{"indexed":false,"internalType":"uint256","name":"overnightFee","type":"uint256"}],"name":"MarginChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalOpenNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"overnightFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"OvernightFeePayed","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":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int256","name":"newPositionSize","type":"int256"},{"indexed":false,"internalType":"uint256","name":"oldLiquidityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLiquidityIndex","type":"uint256"}],"name":"PositionAdjusted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"margin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionNotional","type":"uint256"},{"indexed":false,"internalType":"int256","name":"exchangedPositionSize","type":"int256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"int256","name":"positionSizeAfter","type":"int256"},{"indexed":false,"internalType":"int256","name":"realizedPnl","type":"int256"},{"indexed":false,"internalType":"int256","name":"unrealizedPnlAfter","type":"int256"},{"indexed":false,"internalType":"uint256","name":"badDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationPenalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"spotPrice","type":"uint256"},{"indexed":false,"internalType":"int256","name":"fundingPayment","type":"int256"},{"indexed":false,"internalType":"uint256","name":"overnightPayment","type":"uint256"}],"name":"PositionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionNotional","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"badDebt","type":"uint256"}],"name":"PositionLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exchange","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"valueTransferred","type":"uint256"}],"name":"PositionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"exchange","type":"address"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"RestrictionModeEntered","type":"event"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_addedMargin","type":"tuple"}],"name":"addMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"adjustPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cfdState","outputs":[{"internalType":"contract ICFDState","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cfdVault","outputs":[{"internalType":"contract ICFDVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_quoteAssetAmountLimit","type":"tuple"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"getLatestCumulativeOvernightFeeRate","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"getLatestCumulativePremiumFraction","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"}],"name":"getMMLiquidity","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"}],"name":"getMarginRatio","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"}],"name":"getPosition","outputs":[{"components":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"size","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"margin","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"openNotional","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"lastUpdatedCumulativePremiumFraction","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"lastUpdatedCumulativeOvernightFeeRate","type":"tuple"},{"internalType":"uint256","name":"liquidityHistoryIndex","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"internalType":"struct ICFD.Position","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"},{"internalType":"enum ICFD.PnlCalcOption","name":"_pnlCalcOption","type":"uint8"}],"name":"getPositionNotionalAndUnrealizedPnl","outputs":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"positionNotional","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"unrealizedPnl","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"}],"name":"getUnadjustedPosition","outputs":[{"components":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"size","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"margin","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"openNotional","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"lastUpdatedCumulativePremiumFraction","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"lastUpdatedCumulativeOvernightFeeRate","type":"tuple"},{"internalType":"uint256","name":"liquidityHistoryIndex","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"internalType":"struct ICFD.Position","name":"position","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_systemsettings","type":"address"},{"internalType":"address","name":"_cfdVault","type":"address"},{"internalType":"address","name":"_cfdState","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"internalType":"enum ICFD.Side","name":"_side","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":"_leverage","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_baseAssetAmountLimit","type":"tuple"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"payFunding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"payOvernightFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"_removedMargin","type":"tuple"}],"name":"removeMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISystemSettings","name":"_systemSettings","type":"address"}],"name":"setSystemSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"}],"name":"settlePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"systemSettings","outputs":[{"internalType":"contract ISystemSettings","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5061580180620000216000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c8063893d242d116100de578063b33dc19011610097578063e4d8074e11610071578063e4d8074e14610340578063ea0a45f914610353578063f2fde38b14610366578063fc0cc0a8146103795761018e565b8063b33dc19014610307578063c0c53b8b1461031a578063d14da4161461032d5761018e565b8063893d242d1461029d5780638bedf3bb146102b05780638c34b7ab146102d15780638da5cb5b146102d9578063a8c1b0bc146102e1578063ac06a96e146102f45761018e565b80635bcfc4c41161014b5780636891397b116101255780636891397b14610267578063715018a61461027a57806386b9d81f14610282578063882d74ec146102955761018e565b80635bcfc4c41461021d5780635c975abb1461023d57806360b42f12146102525761018e565b806302329a29146101935780630475db5a146101a85780632db33aa1146101d157806330e2ae65146101e457806336405257146101f75780633e09fa101461020a575b600080fd5b6101a66101a1366004614b2a565b61038c565b005b6101bb6101b6366004614b62565b6103dd565b6040516101c891906156ae565b60405180910390f35b6101a66101df366004614aa8565b61048c565b6101a66101f2366004614c44565b61049a565b6101a6610205366004614aa8565b61075e565b6101a6610218366004614aa8565b610942565b61023061022b366004614aa8565b610b65565b6040516101c891906156bc565b610245610be2565b6040516101c89190614ed2565b61025a610beb565b6040516101c89190614e52565b610230610275366004614aa8565b610bfa565b6101a6610c4f565b6101a6610290366004614b62565b610cce565b61025a611207565b6101a66102ab366004614bd9565b611216565b6102c36102be366004614b9a565b61178e565b6040516101c89291906156c6565b61025a611841565b61025a611850565b6101a66102ef366004614c44565b61185f565b6101a6610302366004614c44565b611b8b565b6101bb610315366004614b62565b611d41565b6101a6610328366004614ae0565b611e80565b61023061033b366004614aa8565b611f59565b6101a661034e366004614aa8565b611fe1565b610230610361366004614b62565b612038565b6101a6610374366004614aa8565b61217c565b6101a6610387366004614aa8565b612233565b610394612486565b6033546001600160a01b039081169116146103ca5760405162461bcd60e51b81526004016103c1906153fe565b60405180910390fd5b609c805460ff1916911515919091179055565b6103e5614970565b506001600160a01b0391821660009081526097602090815260408083209390941682526003928301815290839020835161010081018552815460e0820190815281528451808401865260018301548152818401528451808401865260028301548152818601528451808401865293820154845260608101939093528351918201909352600483015481526080820152600582015460a082015260069091015460c082015290565b610496813361248a565b5050565b609c5460ff16156104bd5760405162461bcd60e51b81526004016103c1906152a9565b6002609b5414156104e05760405162461bcd60e51b81526004016103c19061562c565b6002609b556104f0826001612619565b61050761050236839003830183614d6a565b6127af565b33610510614970565b61051a848361248a565b90506105246149cb565b61054760001961054161053c36889003880188614d6a565b6127d7565b9061283b565b90506105516149de565b609a54604051638b4a5bf360e01b81526001600160a01b0390911690638b4a5bf39061058590899087908790600401614f36565b60806040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d59190614d06565b90506105e48160200151612860565b156106015760405162461bcd60e51b81526004016103c190615109565b8051602084015261061186610bfa565b606084015261061f86610b65565b608084015261062f868585612864565b6106c961063c8786612038565b609860009054906101000a90046001600160a01b03166001600160a01b031663e57d56366040518163ffffffff1660e01b815260040160206040518083038186803b15801561068a57600080fd5b505afa15801561069e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c29190614d8f565b6001612978565b6106e286856106dd36899003890189614d6a565b6129b9565b856001600160a01b0316846001600160a01b03167f32ee06b7b87a4e31e03f5a752748014a342c37a10b2179a2c422d887c50889fd61072085612860565b61072d8560400151612860565b61073a8660600151612860565b60405161074993929190614fe6565b60405180910390a350506001609b5550505050565b6002609b5414156107815760405162461bcd60e51b81526004016103c19061562c565b6002609b55610791816000612619565b3361079a614970565b6107a48383611d41565b90506107b38160000151612a24565b6107bd8383612a49565b6107c56149cb565b836001600160a01b031663ec2c0e636040518163ffffffff1660e01b815260040160206040518083038186803b1580156107fe57600080fd5b505afa158015610812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108369190614d8f565b90506108406149cb565b61084982612860565b610858575060208201516108c7565b6108606149cb565b6108a684602001516108a061089861088961087e8960000151612c0e565b60408a015190612c3c565b610892886127d7565b90612c59565b875190612cc8565b90612ce5565b905060006108b382612860565b13156108c5576108c281612c0e565b91505b505b60006108d282612860565b11156108e3576108e38585836129b9565b836001600160a01b0316856001600160a01b03167fba70e8457921bdd49042182753cb6259c62f923e2b64216b68372cd85ec3af6c61092184612860565b60405161092e91906156d6565b60405180910390a350506001609b55505050565b61094d816001612619565b6109556149cb565b816001600160a01b031663e805d6fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561098e57600080fd5b505afa1580156109a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c69190614d8f565b90506109d06149cb565b826001600160a01b031663ed83d79c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a0b57600080fd5b505af1158015610a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a439190614d8f565b6001600160a01b0384166000908152609760205260409020909150600101610a74610a6d85610bfa565b8390612d4a565b8154600181018355600092835260209092209051910155610a936149cb565b610a9d8284612cc8565b90506000610aaa82612860565b1315610ac757610ac284610abd83612c0e565b612d67565b610b5f565b610b5f84610ad483612c0e565b609860009054906101000a90046001600160a01b03166001600160a01b0316635da7c8ec6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2257600080fd5b505afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a9190614d8f565b612dcf565b50505050565b610b6d6149cb565b6001600160a01b0382166000908152609760205260409020600201548015610bdb576001600160a01b038316600090815260976020526040902060020180546000198301908110610bba57fe5b6000918252602091829020604080519384019052015481529150610bdd9050565b505b919050565b609c5460ff1681565b6098546001600160a01b031681565b610c026149cb565b6001600160a01b0382166000908152609760205260409020600101548015610bdb576001600160a01b038316600090815260976020526040902060010180546000198301908110610bba57fe5b610c57612486565b6033546001600160a01b03908116911614610c845760405162461bcd60e51b81526004016103c1906153fe565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6002609b541415610cf15760405162461bcd60e51b81526004016103c19061562c565b6002609b55610d01826001612619565b610d9b610d0e8383612038565b609860009054906101000a90046001600160a01b03166001600160a01b03166383acb48a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d5c57600080fd5b505afa158015610d70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d949190614d8f565b6000612978565b610da5828261248a565b50610dae614a1d565b610dc28383610dbb612f70565b6000612f8b565b9050610dcd836131fc565b610dd56149cb565b6098546040805163cfe7110360e01b81529051610e5e926001600160a01b03169163cfe71103916004808301926020929190829003018186803b158015610e1b57600080fd5b505afa158015610e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e539190614d8f565b602084015190613262565b90506000610ef2609860009054906101000a90046001600160a01b03166001600160a01b03166359ba76086040518163ffffffff1660e01b815260040160206040518083038186803b158015610eb357600080fd5b505afa158015610ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eeb9190614d8f565b839061327f565b60000b1315610f8457609860009054906101000a90046001600160a01b03166001600160a01b03166359ba76086040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4957600080fd5b505afa158015610f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f819190614d8f565b90505b610f8c6149cb565b610f998360e00151612c0e565b9050610fa36149cb565b610fab6149cb565b506040840151610fb96149cb565b5060e0850151610fc884612860565b610fd186612860565b1115610ff457610fe185856132b0565b9250610fed82846132cd565b9150611001565b610ffe8186612ce5565b90505b600061100c83612860565b111561101c5761101c8883612d67565b600061102782612860565b121561103f5761103f8861103a83612c0e565b6132ea565b61104a8833876129b9565b876001600160a01b0316876001600160a01b03167f5225638a979dd133f201045ab4169ec2189874d864f2b5a10be72ac6e4b421b461108c8960200151612860565b6110998a606001516133a0565b6110a28a612860565b336110ac8a612860565b6040516110bd9594939291906156df565b60405180910390a35050505050826001600160a01b0316826001600160a01b03167f4f7b1ae1435976391e4c35674eb648f299111943bfb8a5c98bfdd1f59e2a73be600061110e8560200151612860565b61111b8660600151612860565b60008061112b8960c00151612860565b600061113a8b60400151612860565b61114f61114a8d60e00151612c0e565b612860565b6111c38f6001600160a01b031663dc76fabc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561118b57600080fd5b505afa15801561119f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114a9190614d8f565b6111d08e60800151612860565b6111dd8f60a00151612860565b6040516111f59c9b9a99989796959493929190614ffc565b60405180910390a350506001609b5550565b6099546001600160a01b031681565b609c5460ff16156112395760405162461bcd60e51b81526004016103c1906152a9565b6002609b54141561125c5760405162461bcd60e51b81526004016103c19061562c565b6002609b5561126c856001612619565b61127e61050236859003850185614d6a565b61129061050236849003840184614d6a565b6112b661063c6112a536859003850185614d6a565b6112b061053c6133b2565b906133d6565b6112bf85613441565b609a5460405163542cdc1b60e01b815233916001600160a01b03169063542cdc1b906112f390899085908a90600401614e66565b602060405180830381600087803b15801561130d57600080fd5b505af1158015611321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113459190614b46565b6113615760405162461bcd60e51b81526004016103c1906154b1565b611369614a1d565b600061137e611378898561248a565b51612860565b90506000811561138f576000611392565b60015b9050806113f4576113f46113a68a86612038565b609860009054906101000a90046001600160a01b03166001600160a01b03166383acb48a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561068a57600080fd5b8080611426575087600181111561140757fe5b60008313611416576001611419565b60005b600181111561142457fe5b145b156114815761147a8989611457611442368b90038b018b614d6a565b611451368d90038d018d614d6a565b90613262565b611466368a90038a018a614d6a565b611475368c90038c018c614d6a565b61349b565b92506114bb565b6114b88989611495368b90038b018b614d6a565b6114a4368b90038b018b614d6a565b6114b3368b90038b018b614d6a565b61385f565b92505b6114ca89858560000151612864565b60006114d98460400151612860565b11156114e8576114e8896131fc565b6000896001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561152357600080fd5b505afa158015611537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155b9190614ac4565b9050600061156c8560e00151612860565b13156115b3576115ae85609960009054906101000a90046001600160a01b031661159c61114a8860e00151612c0e565b6001600160a01b038516929190613b8f565b6115da565b60006115c28560e00151612860565b12156115da576115da8a866106dd8760e00151612c0e565b60995460405163f2a5dca360e01b81526001600160a01b039091169063f2a5dca39061160a908d90600401614e52565b600060405180830381600087803b15801561162457600080fd5b505af1158015611638573d6000803e3d6000fd5b505050505050506116476149cb565b61165683898460200151613be7565b90506000611696896001600160a01b031663dc76fabc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561118b57600080fd5b905060006116a78460800151612860565b905060006116b88560a00151612860565b90508a6001600160a01b0316866001600160a01b03167f4f7b1ae1435976391e4c35674eb648f299111943bfb8a5c98bfdd1f59e2a73be611700886000015160200151612860565b61170d8960200151612860565b61171a8a60600151612860565b6117238a612860565b8b515161172f90612860565b61173c8d60c00151612860565b61174a8e6101000151612860565b6117578f60400151612860565b60008e8e8e6040516117749c9b9a99989796959493929190614ffc565b60405180910390a350506001609b55505050505050505050565b6117966149cb565b61179e6149cb565b6117a6614970565b6117b08686611d41565b609a54604051637a7e522360e01b81529192506001600160a01b031690637a7e5223906117e590899085908990600401614f00565b604080518083038186803b1580156117fc57600080fd5b505afa158015611810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118349190614daa565b9250925050935093915050565b609a546001600160a01b031681565b6033546001600160a01b031690565b609c5460ff16156118825760405162461bcd60e51b81526004016103c1906152a9565b6002609b5414156118a55760405162461bcd60e51b81526004016103c19061562c565b6002609b556118b5826001612619565b6118be82613441565b336118c7614970565b6118d1848361248a565b905060006118e28260000151613ef1565b6118ed5760016118f0565b60005b609a5460405163542cdc1b60e01b81529192506001600160a01b03169063542cdc1b9061192590889087908690600401614e66565b602060405180830381600087803b15801561193f57600080fd5b505af1158015611953573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119779190614b46565b6119935760405162461bcd60e51b81526004016103c190615663565b61199b614a1d565b6119b686856119af36899003890189614d6a565b6001612f8b565b905060006119c78260400151612860565b11156119e4576119d6866131fc565b6119e4868260400151612d67565b6119f686856106dd8460e00151612c0e565b60995460405163f2a5dca360e01b81526001600160a01b039091169063f2a5dca390611a26908990600401614e52565b600060405180830381600087803b158015611a4057600080fd5b505af1158015611a54573d6000803e3d6000fd5b50505050611a606149cb565b611a6f85888460200151613be7565b90506000611aaf886001600160a01b031663dc76fabc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561118b57600080fd5b90506000611ac08460800151612860565b90506000611ad18560a00151612860565b9050896001600160a01b0316886001600160a01b03167f4f7b1ae1435976391e4c35674eb648f299111943bfb8a5c98bfdd1f59e2a73be6000611b178960200151612860565b611b248a60600151612860565b611b2d8a612860565b8b5151611b3990612860565b611b468d60c00151612860565b6000611b558f60400151612860565b60008e8e8e604051611b729c9b9a99989796959493929190614ffc565b60405180910390a350506001609b555050505050505050565b609c5460ff1615611bae5760405162461bcd60e51b81526004016103c1906152a9565b6002609b541415611bd15760405162461bcd60e51b81526004016103c19061562c565b6002609b55611be1826001612619565b611bf361050236839003830183614d6a565b33611bfc614970565b611c06848361248a565b9050611c25611c1a36859003850185614d6a565b6020830151906132cd565b6020820152611c35848383612864565b609954611cdb9083906001600160a01b0316611c5961114a36889003880188614d6a565b876001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9257600080fd5b505afa158015611ca6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cca9190614ac4565b6001600160a01b0316929190613b8f565b6001600160a01b038085169083167f32ee06b7b87a4e31e03f5a752748014a342c37a10b2179a2c422d887c50889fd611d1c61114a36889003880188614d6a565b600080604051611d2e93929190614fe6565b60405180910390a350506001609b555050565b611d49614970565b611d51614970565b611d5b84846103dd565b90506000611ddb6001866001600160a01b03166342b3198b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9d57600080fd5b505afa158015611db1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd59190614dd5565b90613f0f565b9050808260a001511415611df157509050611e7a565b609a546040516361d9282960e01b81526001600160a01b03909116906361d9282990611e2590889086908690600401614f64565b60e06040518083038186803b158015611e3d57600080fd5b505afa158015611e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e759190614c79565b925050505b92915050565b600054610100900460ff1680611e995750611e99613f51565b80611ea7575060005460ff16155b611ec35760405162461bcd60e51b81526004016103c19061530a565b600054610100900460ff16158015611eee576000805460ff1961ff0019909116610100171660011790555b611ef6613f57565b609880546001600160a01b038087166001600160a01b03199283161790925560998054868416908316179055609a8054928516929091169190911790556001609b55609c805460ff191690558015610b5f576000805461ff001916905550505050565b611f616149cb565b6099546040516368a6d20b60e11b81526001600160a01b039091169063d14da41690611f91908590600401614e52565b60206040518083038186803b158015611fa957600080fd5b505afa158015611fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7a9190614d8f565b611fe9612486565b6033546001600160a01b039081169116146120165760405162461bcd60e51b81526004016103c1906153fe565b609880546001600160a01b0319166001600160a01b0392909216919091179055565b6120406149cb565b612048614970565b6120528484611d41565b90506120618160000151612a24565b61206e81604001516127af565b6120766149cb565b6120828585600061178e565b91505061208d6149cb565b6120998686600161178e565b9150506120a46149cb565b6120ad82612860565b6120b684612860565b136120c157816120c3565b825b90506120cd6149de565b609a54604051638b4a5bf360e01b81526001600160a01b0390911690638b4a5bf390612101908b9089908790600401614f36565b60806040518083038186803b15801561211957600080fd5b505afa15801561212d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121519190614d06565b905061217085604001516112b0836020015161089285600001516127d7565b98975050505050505050565b612184612486565b6033546001600160a01b039081169116146121b15760405162461bcd60e51b81526004016103c1906153fe565b6001600160a01b0381166121d75760405162461bcd60e51b81526004016103c190615137565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b61223e816001612619565b60985460405163ed99da3160e01b81526001600160a01b039091169063ed99da319061226e908490600401614e52565b600060405180830381600087803b15801561228857600080fd5b505af115801561229c573d6000803e3d6000fd5b505050506122a86149cb565b609860009054906101000a90046001600160a01b03166001600160a01b031663e50bda386040518163ffffffff1660e01b815260040160206040518083038186803b1580156122f657600080fd5b505afa15801561230a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232e9190614d8f565b6001600160a01b038316600090815260976020526040902090915060020161235f61235884610b65565b83906132cd565b815460018101835560009283526020909220905191015561237e6149cb565b506001600160a01b038216600090815260976020908152604091829020825191820190925260049091015481526123b36149cb565b6123bd8383613262565b905060006123ca82612860565b1115612423576124238482609860009054906101000a90046001600160a01b03166001600160a01b031663575dc7b36040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2257600080fd5b836001600160a01b03167fcf30be51a3c535c7548ddbb34d9cb7e40064a002e0cf8872dce1d34e790cdd3a61245784612860565b61246084612860565b61246987612860565b60405161247893929190614fe6565b60405180910390a250505050565b3390565b612492614970565b61249a614970565b6124a484846103dd565b90506124b38160000151612860565b6124be579050611e7a565b60006124fe6001866001600160a01b03166342b3198b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9d57600080fd5b9050808260a00151141561251457509050611e7a565b61251c614970565b609a546040516361d9282960e01b81526001600160a01b03909116906361d928299061255090899087908790600401614f64565b60e06040518083038186803b15801561256857600080fd5b505afa15801561257c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a09190614c79565b90506125ad868683612864565b846001600160a01b0316866001600160a01b03167fdbb898e847eca1f5626ba536593caa10241fb631e7c8a1cb06dfdce8d3934f496125ef8460000151612860565b8660a001518560a0015160405161260893929190614fe6565b60405180910390a395945050505050565b6098546040516357de0c5b60e01b81526001600160a01b03909116906357de0c5b90612649908590600401614e52565b60206040518083038186803b15801561266157600080fd5b505afa158015612675573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126999190614b46565b6126b55760405162461bcd60e51b81526004016103c1906150dd565b816001600160a01b031663fcfff16f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126ee57600080fd5b505afa158015612702573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127269190614b46565b1515811515148161275f576040518060400160405280601081526020016f32bc31b430b733b29034b99037b832b760811b81525061278c565b60405180604001604052806013815260200172195e18da185b99d9481dd85cc818db1bdcd959606a1b8152505b906127aa5760405162461bcd60e51b81526004016103c19190615050565b505050565b6127b881612860565b6127d45760405162461bcd60e51b81526004016103c1906153da565b50565b6127df6149cb565b8180600001516001600160ff1b03101560405180606001604052806033815260200161579960339139906128265760405162461bcd60e51b81526004016103c19190615050565b50506040805160208101909152915182525090565b6128436149cb565b61284b6149cb565b83516128579084613fe9565b81529392505050565b5190565b6001600160a01b038084166000818152609760208181526040808420958816845260038601825280842081518084018352600282015481529590945291815281519081019091526004909301548352916128bd916132b0565b6001600160a01b03851660008181526097602081815260408084209551600496870190815588515188558883015151600189015588820151516002890181905560608a01515160038a015560808a0151519789019790975560c0890151600689015560a08901516005890155815180840183529687529490935290815281519081019091529054815261294f916132cd565b6001600160a01b0390941660009081526097602052604090209351600490940193909355505050565b600061298761114a8585612c59565b905081612997576000811261299d565b60008112155b610b5f5760405162461bcd60e51b81526004016103c190615272565b60995460405163038ef35760e41b81526001600160a01b03909116906338ef3570906129ed90869086908690600401614edd565b600060405180830381600087803b158015612a0757600080fd5b505af1158015612a1b573d6000803e3d6000fd5b50505050505050565b612a2d81612860565b6127d45760405162461bcd60e51b81526004016103c1906150b2565b612a51614970565b506001600160a01b038083166000818152609760208181526040808420958716845260038087018352818520825161010081018452815460e08201908152815283518086018552600183015481528186015283518086018552600283015481528185019081528451808701865293830154845260608201939093528351808601855260048084015482526080830191909152600583015460a083015260069092015460c08201529151969095529282528051918201905291909301548152612b18916132b0565b6001600160a01b038416600090815260976020526040908190209151600490920191909155805160e0810190915280612b4f612f70565b8152602001612b5c612f70565b8152602001612b69612f70565b8152602001612b76612f70565b8152602001612b83612f70565b815260200160008152602001612b97614054565b90526001600160a01b0393841660009081526097602090815260408083209590961682526003948501815290859020825151815590820151516001820155938101515160028501556060810151519284019290925550608081015151600483015560a0810151600583015560c00151600690910155565b612c166149cb565b612c1e6149cb565b825160001315612c345782516000038152611e7a565b915182525090565b612c446149cb565b612c4c6149cb565b8251845161285791614058565b612c616149cb565b8180600001516001600160ff1b0310156040518060600160405280603381526020016157996033913990612ca85760405162461bcd60e51b81526004016103c19190615050565b50612cb16149cb565b83518551612cbe91614066565b8152949350505050565b612cd06149cb565b612cd86149cb565b82518451612857916140ac565b612ced6149cb565b8180600001516001600160ff1b0310156040518060600160405280603381526020016157996033913990612d345760405162461bcd60e51b81526004016103c19190615050565b50612d3d6149cb565b83518551612cbe916140ba565b612d526149cb565b612d5a6149cb565b82518451612857916140ba565b609954604051630a16f8cb60e31b81526001600160a01b03909116906350b7c65890612d999085908590600401614f82565b600060405180830381600087803b158015612db357600080fd5b505af1158015612dc7573d6000803e3d6000fd5b505050505050565b609854604051633f694ac560e11b81526000916001600160a01b031690637ed2958a90612e00908790600401614e52565b60206040518083038186803b158015612e1857600080fd5b505afa158015612e2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e509190614ac4565b90506001600160a01b038116612e785760405162461bcd60e51b81526004016103c190615083565b612e806149cb565b612e8a8484613262565b60995460405163038ef35760e41b81529192506001600160a01b0316906338ef357090612ebf90889086908690600401614edd565b600060405180830381600087803b158015612ed957600080fd5b505af1158015612eed573d6000803e3d6000fd5b50505050612ef96149cb565b612f0385836132b0565b609954604051633aed6d0b60e21b81529192506001600160a01b03169063ebb5b42c90612f369089908590600401614f82565b600060405180830381600087803b158015612f5057600080fd5b505af1158015612f64573d6000803e3d6000fd5b50505050505050505050565b612f786149cb565b5060408051602081019091526000815290565b612f93614a1d565b612f9b614970565b612fa586866103dd565b9050612faf6149cb565b508051612fbb81612a24565b612fc36149cb565b612fcf8888600061178e565b915050612fda6149de565b609a54604051638b4a5bf360e01b81526001600160a01b0390911690638b4a5bf39061300e908c9088908790600401614f36565b60806040518083038186803b15801561302657600080fd5b505afa15801561303a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305e9190614d06565b905061306c8360001961283b565b60608087019190915260c086018390526020820151604080880191909152820151608087015281015160a086015280516130ad9060001990610541906127d7565b60e08601526001600160a01b03891663dc3184a060006130cc86612860565b136130d85760016130db565b60005b6130e486612c0e565b8a8a6040518563ffffffff1660e01b81526004016131059493929190614fbd565b602060405180830381600087803b15801561311f57600080fd5b505af1158015613133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131579190614d8f565b602080870191909152609a546040860151918301516001600160a01b03909116916302a3789e918c916131979160001991610541916108a0908a90612ce5565b6040518363ffffffff1660e01b81526004016131b4929190614f82565b600060405180830381600087803b1580156131ce57600080fd5b505af11580156131e2573d6000803e3d6000fd5b505050506131f08989612a49565b50505050949350505050565b6000613206614054565b6001600160a01b03831660009081526097602052604090819020829055519091507f97f920fec5d17ec336df7ad438ca8a76dcfd206ddc1d19b263b6f3e6ba3c4f31906132569084908490614eb9565b60405180910390a15050565b61326a6149cb565b6132726149cb565b8251845161285791614100565b80518251600091101561329457506001611e7a565b8151835110156132a75750600019611e7a565b50600092915050565b6132b86149cb565b6132c06149cb565b8251845161285791613f0f565b6132d56149cb565b6132dd6149cb565b825184516128579161410e565b609854604051633f694ac560e11b81526000916001600160a01b031690637ed2958a9061331b908690600401614e52565b60206040518083038186803b15801561333357600080fd5b505afa158015613347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336b9190614ac4565b60995460405163038ef35760e41b81529192506001600160a01b0316906338ef3570906129ed90869085908790600401614edd565b60006133ab82612c0e565b5192915050565b6133ba6149cb565b60405180602001604052806133cf6012614133565b9052905090565b6133de6149cb565b8180600001516001600160ff1b03101560405180606001604052806033815260200161579960339139906134255760405162461bcd60e51b81526004016103c19190615050565b5061342e6149cb565b611e7561343a856127d7565b869061413c565b600061344b614054565b6001600160a01b038316600090815260976020526040902054909150811415610496578061347983336103dd565b60c0015114156104965760405162461bcd60e51b81526004016103c19061523b565b6134a3614a1d565b336134ac614970565b6134b688836103dd565b90506134c488888888614159565b60608401526134d16149cb565b606084015182516134e191612d4a565b60a08301518351919250906134f590612860565b61353a5761353760018b6001600160a01b03166342b3198b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9d57600080fd5b90505b609a546001600160a01b03166302a3789e8b6135558b6127d7565b6040518363ffffffff1660e01b8152600401613572929190614f82565b600060405180830381600087803b15801561358c57600080fd5b505af11580156135a0573d6000803e3d6000fd5b50505050609a60009054906101000a90046001600160a01b03166001600160a01b03166309a9d76c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156135f257600080fd5b505afa158015613606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061362a9190614ac4565b6001600160a01b0316846001600160a01b0316146137065761364a6149cb565b8a6001600160a01b031663113773946040518163ffffffff1660e01b815260040160206040518083038186803b15801561368357600080fd5b505afa158015613697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136bb9190614d8f565b905060006136c882612860565b11156137045760006136e3826136dd86612c0e565b9061327f565b60000b13156137045760405162461bcd60e51b81526004016103c19061547a565b505b61370e614970565b6137166149cb565b61372361053c8b8a612c3c565b905061372d6149de565b609a60009054906101000a90046001600160a01b03166001600160a01b0316638b4a5bf38e88856040518463ffffffff1660e01b815260040161377293929190614f36565b60806040518083038186803b15801561378a57600080fd5b505afa15801561379e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c29190614d06565b60e08901929092525060408101516080880152606081015160a08801525160208201526137ed6149cb565b6137f98c87600061178e565b61010089015250506020860189815283825251604085015161381a916132cd565b604082015260a0810182905261382f8b610bfa565b606082015261383d8b610b65565b608082015261384a614054565b60c08201528552509298975050505050505050565b613867614a1d565b61386f6149cb565b6138798585613262565b90506138836149cb565b61388b6149cb565b6138978933600061178e565b915091506138a3614a1d565b6138ac84612860565b6138b584612860565b1115613b7257609a546001600160a01b03166302a3789e8b6138dc600019610541896127d7565b6040518363ffffffff1660e01b81526004016138f9929190614f82565b600060405180830381600087803b15801561391357600080fd5b505af1158015613927573d6000803e3d6000fd5b50505050613933614970565b61393d8b336103dd565b905061394b8b8b878a614159565b6060830152805161395b90612860565b1561398d576139876139708260000151612c0e565b6112b06139808560600151612c0e565b8690614246565b60c08301525b6139956149de565b609a60009054906101000a90046001600160a01b03166001600160a01b0316638b4a5bf38d848660c001516040518463ffffffff1660e01b81526004016139de93929190614f36565b60806040518083038186803b1580156139f657600080fd5b505afa158015613a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a2e9190614d06565b6020808201516040808701919091528201516080860152606082015160a08601528481018890529051908301525060c0820151613a6c9084906142b1565b610100830152613a7a6149cb565b6000613a898360000151612860565b13613ab357613aae836020015161089287866101000151612ce590919063ffffffff16565b613ad3565b613ad3836101000151613acd8560200151610892896127d7565b906142b1565b90506000613ae082612860565b13613afd5760405162461bcd60e51b81526004016103c1906152d3565b613b05614970565b6020808401519082015260608401518351613b1f91612d4a565b8152613b2a82612c0e565b604082015260a08084015190820152613b428d610bfa565b6060820152613b508d610b65565b6080820152613b5d614054565b60c0820152835250909450613b869350505050565b613b7f8a8a8a8a8a6142ce565b9450505050505b95945050505050565b610b5f846323b872dd60e01b858585604051602401613bb093929190614e95565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526144b8565b613bef6149cb565b613bf76149cb565b604051636226795560e01b81526001600160a01b03851690636226795590613c239086906004016156bc565b60206040518083038186803b158015613c3b57600080fd5b505afa158015613c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c739190614d8f565b90506000613c8082612860565b1115613ede57609854604051633f694ac560e11b81526000916001600160a01b031690637ed2958a90613cb7908890600401614e52565b60206040518083038186803b158015613ccf57600080fd5b505afa158015613ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d079190614ac4565b90506001600160a01b038116613d2f5760405162461bcd60e51b81526004016103c190615083565b613d376149cb565b609854604080516356d43c4760e11b81529051613dbc926001600160a01b03169163ada8788e916004808301926020929190829003018186803b158015613d7d57600080fd5b505afa158015613d91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db59190614d8f565b8490613262565b9050613e058783613dcc84612860565b896001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9257600080fd5b613e0d6149cb565b613e1784836132b0565b609954909150613e6e9089906001600160a01b0316613e3584612860565b8a6001600160a01b031663fdf262b76040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9257600080fd5b609954604051633aed6d0b60e21b81526001600160a01b039091169063ebb5b42c90613ea0908a908590600401614f82565b600060405180830381600087803b158015613eba57600080fd5b505af1158015613ece573d6000803e3d6000fd5b5050505083945050505050613eea565b613ee6612f70565b9150505b9392505050565b60008082600001511215613f0757506001610bdd565b506000919050565b6000613eea83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614547565b303b1590565b600054610100900460ff1680613f705750613f70613f51565b80613f7e575060005460ff16155b613f9a5760405162461bcd60e51b81526004016103c19061530a565b600054610100900460ff16158015613fc5576000805460ff1961ff0019909116610100171660011790555b613fcd614573565b613fd56145f4565b80156127d4576000805461ff001916905550565b600082613ff857506000611e7a565b8260001914801561400c5750600160ff1b82145b156140295760405162461bcd60e51b81526004016103c190615433565b8282028284828161403657fe5b0514613eea5760405162461bcd60e51b81526004016103c190615433565b4390565b6000613eea838360126146ce565b600081830381831280159061407b5750838113155b80614090575060008312801561409057508381135b613eea5760405162461bcd60e51b81526004016103c190615569565b6000613eea838360126146ed565b60008282018183128015906140cf5750838112155b806140e457506000831280156140e457508381125b613eea5760405162461bcd60e51b81526004016103c1906151b4565b6000613eea8383601261470b565b600082820183811015613eea5760405162461bcd60e51b81526004016103c19061517d565b60ff16600a0a90565b6141446149cb565b61414c6149cb565b8251845161285791614723565b6141616149cb565b60008085600181111561417057fe5b1461417c57600161417f565b60005b90506141896149cb565b604051639ffca62f60e01b815261420f906001600160a01b03891690639ffca62f906141bd9086908a908a90600401614f9c565b602060405180830381600087803b1580156141d757600080fd5b505af11580156141eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190614d8f565b905081600181111561421d57fe5b6001141561423a576142318160001961283b565b9250505061423e565b9150505b949350505050565b61424e6149cb565b8180600001516001600160ff1b03101560405180606001604052806033815260200161579960339139906142955760405162461bcd60e51b81526004016103c19190615050565b5061429e6149cb565b611e756142aa856127d7565b8690612cc8565b6142b96149cb565b6142c16149cb565b8251845161285791614066565b6142d6614a1d565b6142de614a1d565b6142eb87336119af612f70565b90506142fa8160400151612860565b156143175760405162461bcd60e51b81526004016103c1906154fb565b61431f6149cb565b6020820151614338906143328888613262565b906132b0565b905061434761114a8287612c3c565b614353578192506144ad565b61435b6149cb565b61436883606001516133a0565b61437186612860565b11156143915761438e6143878460600151612c0e565b86906132b0565b90505b614399614a1d565b6143a68a8a85858b61349b565b9050604051806101200160405280826000015181526020016143d9836020015187602001516132cd90919063ffffffff16565b81526020016143f9836040015187604001516132cd90919063ffffffff16565b815260200161441983606001518760600151612d4a90919063ffffffff16565b815260200161443983608001518760800151612d4a90919063ffffffff16565b81526020016144598360a001518760a001516132cd90919063ffffffff16565b81526020016144798360c001518760c00151612d4a90919063ffffffff16565b81526020016144998360e001518760e00151612d4a90919063ffffffff16565b81526020016144a6612f70565b9052945050505b505095945050505050565b606061450d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147319092919063ffffffff16565b8051909150156127aa578080602001905181019061452b9190614b46565b6127aa5760405162461bcd60e51b81526004016103c1906155ad565b6000818484111561456b5760405162461bcd60e51b81526004016103c19190615050565b505050900390565b600054610100900460ff168061458c575061458c613f51565b8061459a575060005460ff16155b6145b65760405162461bcd60e51b81526004016103c19061530a565b600054610100900460ff16158015613fd5576000805460ff1961ff00199091166101001716600117905580156127d4576000805461ff001916905550565b600054610100900460ff168061460d575061460d613f51565b8061461b575060005460ff16155b6146375760405162461bcd60e51b81526004016103c19061530a565b600054610100900460ff16158015614662576000805460ff1961ff0019909116610100171660011790555b600061466c612486565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156127d4576000805461ff001916905550565b600061423e836146e76146e085614133565b8790614740565b9061477a565b600061423e6146fb83614133565b6147058686613fe9565b906147bc565b600061423e61471983614133565b6146e78686614740565b6000613eea83836012614820565b606061423e8484600085614839565b60008261474f57506000611e7a565b8282028284828161475c57fe5b0414613eea5760405162461bcd60e51b81526004016103c190615399565b6000613eea83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506148fa565b6000816147db5760405162461bcd60e51b81526004016103c1906155f7565b816000191480156147ef5750600160ff1b83145b1561480c5760405162461bcd60e51b81526004016103c190615358565b600082848161481757fe5b05949350505050565b600061423e8361470561483285614133565b8790613fe9565b60608247101561485b5760405162461bcd60e51b81526004016103c1906151f5565b61486485614931565b6148805760405162461bcd60e51b81526004016103c190615532565b60006060866001600160a01b0316858760405161489d9190614e36565b60006040518083038185875af1925050503d80600081146148da576040519150601f19603f3d011682016040523d82523d6000602084013e6148df565b606091505b50915091506148ef828286614937565b979650505050505050565b6000818361491b5760405162461bcd60e51b81526004016103c19190615050565b50600083858161492757fe5b0495945050505050565b3b151590565b60608315614946575081613eea565b8251156149565782518084602001fd5b8160405162461bcd60e51b81526004016103c19190615050565b6040518060e001604052806149836149cb565b81526020016149906149cb565b815260200161499d6149cb565b81526020016149aa6149cb565b81526020016149b76149cb565b815260200160008152602001600081525090565b6040518060200160405280600081525090565b60405180608001604052806149f16149cb565b81526020016149fe6149cb565b8152602001614a0b6149cb565b8152602001614a186149cb565b905290565b604051806101200160405280614a31614970565b8152602001614a3e6149cb565b8152602001614a4b6149cb565b8152602001614a586149cb565b8152602001614a656149cb565b81526020016149f16149cb565b600060208284031215610bdb578081fd5b600060208284031215614a94578081fd5b614a9e602061570b565b9151825250919050565b600060208284031215614ab9578081fd5b8135613eea81615768565b600060208284031215614ad5578081fd5b8151613eea81615768565b600080600060608486031215614af4578182fd5b8335614aff81615768565b92506020840135614b0f81615768565b91506040840135614b1f81615768565b809150509250925092565b600060208284031215614b3b578081fd5b8135613eea8161577d565b600060208284031215614b57578081fd5b8151613eea8161577d565b60008060408385031215614b74578182fd5b8235614b7f81615768565b91506020830135614b8f81615768565b809150509250929050565b600080600060608486031215614bae578081fd5b8335614bb981615768565b92506020840135614bc981615768565b91506040840135614b1f8161578b565b600080600080600060a08688031215614bf0578283fd5b8535614bfb81615768565b94506020860135614c0b8161578b565b9350614c1a8760408801614a72565b9250614c298760608801614a72565b9150614c388760808801614a72565b90509295509295909350565b60008060408385031215614c56578182fd5b8235614c6181615768565b9150614c708460208501614a72565b90509250929050565b600060e08284031215614c8a578081fd5b614c9460e061570b565b614c9e8484614a83565b8152614cad8460208501614a83565b6020820152614cbf8460408501614a83565b6040820152614cd18460608501614a83565b6060820152614ce38460808501614a83565b608082015260a083015160a082015260c083015160c08201528091505092915050565b600060808284031215614d17578081fd5b614d21608061570b565b614d2b8484614a83565b8152614d3a8460208501614a83565b6020820152614d4c8460408501614a83565b6040820152614d5e8460608501614a83565b60608201529392505050565b600060208284031215614d7b578081fd5b614d85602061570b565b9135825250919050565b600060208284031215614da0578081fd5b613eea8383614a83565b60008060408385031215614dbc578182fd5b614dc68484614a83565b9150614c708460208501614a83565b600060208284031215614de6578081fd5b5051919050565b8051518252602081015151602083015260408101515160408301526060810151516060830152608081015151608083015260a081015160a083015260c081015160c08301525050565b60008251614e48818460208701615732565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0384811682528316602082015260608101614e878361575e565b826040830152949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6001600160a01b0393841681529190921660208201529051604082015260600190565b6001600160a01b03841681526101208101614f1e6020830185614ded565b614f278361575e565b82610100830152949350505050565b6001600160a01b03841681526101208101614f546020830185614ded565b8251610100830152949350505050565b6001600160a01b03841681526101208101614f276020830185614ded565b6001600160a01b0392909216825251602082015260400190565b60608101614fa98561575e565b938152915160208301525160409091015290565b60808101614fca8661575e565b9481529251602084015290516040830152151560609091015290565b9283526020830191909152604082015260600190565b9b8c5260208c019a909a5260408b019890985260608a0196909652608089019490945260a088019290925260c087015260e08601526101008501526101208401526101408301526101608201526101800190565b600060208252825180602084015261506f816040850160208701615732565b601f01601f19169190910160400192915050565b602080825260159082015274125b9d985b1a5908125b9cdd5c985b98d9519d5b99605a1b604082015260600190565b6020808252601190820152700706f736974696f6e53697a65206973203607c1b604082015260600190565b602080825260129082015271195e18da185b99d9481b9bdd08199bdd5b9960721b604082015260600190565b6020808252601490820152730dac2e4ced2dc40d2e640dcdee840cadcdeeaced60631b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b60208082526017908201527f6f6e6c79206f6e6520616374696f6e20616c6c6f776564000000000000000000604082015260600190565b6020808252601e908201527f4d617267696e20726174696f206e6f74206d6565742063726974657269610000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601a908201527f76616c7565206f66206f70656e4e6f74696f6e616c203c3d2030000000000000604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252600a90820152690696e70757420697320360b41b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b6020808252601d908201527f68697420706f736974696f6e2073697a6520757070657220626f756e64000000604082015260600190565b6020808252602a908201527f63616e6e6f74206f70656e20706f736974696f6e20647572696e6720776169746040820152691a5b99c81c195c9a5bd960b21b606082015260800190565b6020808252601d908201527f72656475636520616e20756e646572776174657220706f736974696f6e000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f63616e6e6f7420636c6f736520706f736974696f6e20647572696e672077616960408201526a1d1a5b99c81c195c9a5bd960aa1b606082015260800190565b60e08101611e7a8284614ded565b9051815260200190565b9151825251602082015260400190565b90815260200190565b948552602085019390935260408401919091526001600160a01b03166060830152608082015260a00190565b60405181810167ffffffffffffffff8111828210171561572a57600080fd5b604052919050565b60005b8381101561574d578181015183820152602001615735565b83811115610b5f5750506000910152565b600281106127d457fe5b6001600160a01b03811681146127d457600080fd5b80151581146127d457600080fd5b600281106127d457600080fdfe4d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a26469706673582212206df2718bfe884ab1d39d96e26676193782ff394e43462d2ab10d3f53f93d4c6264736f6c634300060c0033

Deployed ByteCode Sourcemap

51710:54357:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105985:79;;;;;;:::i;:::-;;:::i;:::-;;104204:248;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80592:129;;;;;;:::i;:::-;;:::i;61050:1686::-;;;;;;:::i;:::-;;:::i;62936:1826::-;;;;;;:::i;:::-;;:::i;77057:2099::-;;;;;;:::i;:::-;;:::i;84663:385::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;58023:18::-;;;:::i;:::-;;;;;;;:::i;57788:37::-;;;:::i;:::-;;;;;;;:::i;84078:394::-;;;;;;:::i;:::-;;:::i;50904:148::-;;;:::i;73499:3369::-;;;;;;:::i;:::-;;:::i;57834:25::-;;;:::i;66458:4225::-;;;;;;:::i;:::-;;:::i;83404:485::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;57866:25::-;;;:::i;50262:79::-;;;:::i;70792:2374::-;;;;;;:::i;:::-;;:::i;60042:826::-;;;;;;:::i;:::-;;:::i;82526:478::-;;;;;;:::i;:::-;;:::i;58709:374::-;;;;;;:::i;:::-;;:::i;85201:169::-;;;;;;:::i;:::-;;:::i;59737:130::-;;;;;;:::i;:::-;;:::i;81130:1164::-;;;;;;:::i;:::-;;:::i;51207:244::-;;;;;;:::i;:::-;;:::i;79351:1094::-;;;;;;:::i;:::-;;:::i;105985:79::-;50484:12;:10;:12::i;:::-;50474:6;;-1:-1:-1;;;;;50474:6:0;;;:22;;;50466:67;;;;-1:-1:-1;;;50466:67:0;;;;;;;:::i;:::-;;;;;;;;;106041:6:::1;:15:::0;;-1:-1:-1;;106041:15:0::1;::::0;::::1;;::::0;;;::::1;::::0;;105985:79::o;104204:248::-;104339:24;;:::i;:::-;-1:-1:-1;;;;;;104392:31:0;;;;;;;:11;:31;;;;;;;;:52;;;;;;:43;;;;:52;;;;;;104381:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;104381:63:0;;;;;;;;;;;104204:248::o;80592:129::-;80657:56;80691:9;80702:10;80657:33;:56::i;:::-;;80592:129;:::o;61050:1686::-;59598:6;;;;59597:7;59589:36;;;;-1:-1:-1;;;59589:36:0;;;;;;;:::i;:::-;57984:1:::1;59206:6;;:18;;59198:62;;;;-1:-1:-1::0;;;59198:62:0::1;;;;;;;:::i;:::-;57984:1;59338:6;:17:::0;61245:32:::2;61261:9:::0;61272:4:::2;61245:15;:32::i;:::-;61288:35;;;::::0;;::::2;::::0;::::2;61308:14:::0;61288:35:::2;:::i;:::-;:19;:35::i;:::-;61405:10;61426:24;;:::i;:::-;61453:52;61487:9;61498:6;61453:33;:52::i;:::-;61426:79;;61577:46;;:::i;:::-;61626:54;-1:-1:-1::0;;61626:40:0::2;;;::::0;;::::2;::::0;::::2;61651:14:::0;61626:40:::2;:::i;:::-;:24;:40::i;:::-;:50:::0;::::2;:54::i;:::-;61577:103;;61691:50;;:::i;:::-;61757:8;::::0;:92:::2;::::0;-1:-1:-1;;;61757:92:0;;-1:-1:-1;;;;;61757:8:0;;::::2;::::0;:58:::2;::::0;:92:::2;::::0;61816:9;;61827:8;;61837:11;;61757:92:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;61691:158;;61868:33;:16;:24;;;:31;:33::i;:::-;:38:::0;61860:71:::2;;;;-1:-1:-1::0;;;61860:71:0::2;;;;;;;:::i;:::-;61962:29:::0;;61944:15:::2;::::0;::::2;:47:::0;62050:45:::2;62085:9:::0;62050:34:::2;:45::i;:::-;62002;::::0;::::2;:93:::0;62155:46:::2;62191:9:::0;62155:35:::2;:46::i;:::-;62106;::::0;::::2;:95:::0;62212:40:::2;62224:9:::0;62235:6;62106:8;62212:11:::2;:40::i;:::-;62296:97;62319:33;62334:9;62345:6;62319:14;:33::i;:::-;62354:14;;;;;;;;;-1:-1:-1::0;;;;;62354:14:0::2;-1:-1:-1::0;;;;;62354:30:0::2;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;62388:4;62296:22;:97::i;:::-;62448:43;62457:9:::0;62468:6;62448:43:::2;;::::0;;::::2;::::0;::::2;62476:14:::0;62448:43:::2;:::i;:::-;:8;:43::i;:::-;62566:9;-1:-1:-1::0;;;;;62509:219:0::2;62537:6;-1:-1:-1::0;;;;;62509:219:0::2;;62591:19;:11;:17;:19::i;:::-;62625:39;:16;:31;;;:37;:39::i;:::-;62679:38;:16;:29;;;:36;:38::i;:::-;62509:219;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0::1;59516:6;:21:::0;-1:-1:-1;;;;61050:1686:0:o;62936:1826::-;57984:1;59206:6;;:18;;59198:62;;;;-1:-1:-1;;;59198:62:0;;;;;;;:::i;:::-;57984:1;59338:6;:17;63044:33:::1;63060:9:::0;63071:5:::1;63044:15;:33::i;:::-;63107:10;63128:19;;:::i;:::-;63150:30;63162:9;63173:6;63150:11;:30::i;:::-;63128:52;;63191:29;63211:3;:8;;;63191:19;:29::i;:::-;63261:32;63275:9;63286:6;63261:13;:32::i;:::-;63508:38;;:::i;:::-;63549:9;-1:-1:-1::0;;;;;63549:28:0::1;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63508:71;;63590:35;;:::i;:::-;63640:24;:15;:22;:24::i;:::-;63636:723;;-1:-1:-1::0;63701:10:0::1;::::0;::::1;::::0;63636:723:::1;;;63907:47;;:::i;:::-;63974:183;64146:3;:10;;;63974:144;64032:85;64079:37;64101:14;:3;:8;;;:12;:14::i;:::-;64079:16;::::0;::::1;::::0;;:21:::1;:37::i;:::-;64032:41;64057:15;64032:24;:41::i;:::-;:46:::0;::::1;:85::i;:::-;63974:30:::0;;;:57:::1;:144::i;:::-;:171:::0;::::1;:183::i;:::-;63907:250;;64277:1;64254:20;:12;:18;:20::i;:::-;:24;64250:98;;;64314:18;:12;:16;:18::i;:::-;64299:33;;64250:98;63636:723;;64475:1;64451:21;:12;:19;:21::i;:::-;:25;64447:201;;;64493:41;64502:9;64513:6;64521:12;64493:8;:41::i;:::-;64724:6;-1:-1:-1::0;;;;;64688:66:0::1;64712:9;-1:-1:-1::0;;;;;64688:66:0::1;;64732:21;:12;:19;:21::i;:::-;64688:66;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0;59516:6;:21;-1:-1:-1;;;62936:1826:0:o;77057:2099::-;77118:32;77134:9;77145:4;77118:15;:32::i;:::-;77243:66;;:::i;:::-;77325:9;-1:-1:-1;;;;;77325:44:0;;:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77243:128;;77384:50;;:::i;:::-;77437:9;-1:-1:-1;;;;;77437:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;77473:31:0;;;;;;:11;:31;;;;;77384:78;;-1:-1:-1;77473:58:0;;77551:67;77572:45;77493:9;77572:34;:45::i;:::-;77551:15;;:20;:67::i;:::-;77473:156;;;;;;;-1:-1:-1;77473:156:0;;;;;;;;;;;;78070:56;;:::i;:::-;78142:53;:15;78163:31;78142:20;:53::i;:::-;78070:125;;78244:1;78212:29;:21;:27;:29::i;:::-;:33;78208:941;;;78262:54;78277:9;78288:27;:21;:25;:27::i;:::-;78262:14;:54::i;:::-;78208:941;;;78349:178;78399:9;78427:27;:21;:25;:27::i;:::-;78473:14;;;;;;;;;-1:-1:-1;;;;;78473:14:0;-1:-1:-1;;;;;78473:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78349:31;:178::i;:::-;77057:2099;;;;:::o;84663:385::-;84795:22;;:::i;:::-;-1:-1:-1;;;;;84849:31:0;;84835:11;84849:31;;;:11;:31;;;;;:59;;:66;84930:7;;84926:115;;-1:-1:-1;;;;;84961:31:0;;;;;;:11;:31;;;;;:59;;:68;;-1:-1:-1;;85021:7:0;;;84961:68;;;;;;;;;;;;;;;84954:75;;;;;;;;84961:68;84954:75;;;;-1:-1:-1;84954:75:0;;-1:-1:-1;84954:75:0;84926:115;84663:385;;;;;:::o;58023:18::-;;;;;;:::o;57788:37::-;;;-1:-1:-1;;;;;57788:37:0;;:::o;84078:394::-;84209:34;;:::i;:::-;-1:-1:-1;;;;;84275:31:0;;84261:11;84275:31;;;:11;:31;;;;;:58;;:65;84355:7;;84351:114;;-1:-1:-1;;;;;84386:31:0;;;;;;:11;:31;;;;;:58;;:67;;-1:-1:-1;;84445:7:0;;;84386:67;;;;;50904:148;50484:12;:10;:12::i;:::-;50474:6;;-1:-1:-1;;;;;50474:6:0;;;:22;;;50466:67;;;;-1:-1:-1;;;50466:67:0;;;;;;;:::i;:::-;50995:6:::1;::::0;50974:40:::1;::::0;51011:1:::1;::::0;-1:-1:-1;;;;;50995:6:0::1;::::0;50974:40:::1;::::0;51011:1;;50974:40:::1;51025:6;:19:::0;;-1:-1:-1;;;;;;51025:19:0::1;::::0;;50904:148::o;73499:3369::-;57984:1;59206:6;;:18;;59198:62;;;;-1:-1:-1;;;59198:62:0;;;;;;;:::i;:::-;57984:1;59338:6;:17;73620:32:::1;73636:9:::0;73647:4:::1;73620:15;:32::i;:::-;73663:106;73686:34;73701:9;73712:7;73686:14;:34::i;:::-;73722:14;;;;;;;;;-1:-1:-1::0;;;;;73722:14:0::1;-1:-1:-1::0;;;;;73722:37:0::1;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73763:5;73663:22;:106::i;:::-;73808:53;73842:9;73853:7;73808:33;:53::i;:::-;;73872:32;;:::i;:::-;73907:64;73929:9;73940:7;73949:14;:12;:14::i;:::-;73965:5;73907:21;:64::i;:::-;73872:99;;73982:31;74003:9;73982:20;:31::i;:::-;74119:37;;:::i;:::-;74220:14;::::0;:36:::1;::::0;;-1:-1:-1;;;74220:36:0;;;;74176:81:::1;::::0;-1:-1:-1;;;;;74220:14:0::1;::::0;:34:::1;::::0;:36:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:14;:36;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74176:38;::::0;::::1;::::0;;:43:::1;:81::i;:::-;74119:138;;74333:1;74276:54;74295:14;;;;;;;;;-1:-1:-1::0;;;;;74295:14:0::1;-1:-1:-1::0;;;;;74295:32:0::1;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74276:14:::0;;:18:::1;:54::i;:::-;:58;;;74272:150;;;74372:14;;;;;;;;;-1:-1:-1::0;;;;;74372:14:0::1;-1:-1:-1::0;;;;;74372:32:0::1;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74355:51;;74272:150;74590:35;;:::i;:::-;74628:32;:12;:26;;;:30;:32::i;:::-;74590:70;;74890:41;;:::i;:::-;74946:35;;:::i;:::-;-1:-1:-1::0;74984:20:0::1;::::0;::::1;::::0;75019:53:::1;;:::i;:::-;-1:-1:-1::0;75075:26:0::1;::::0;::::1;::::0;75146:21:::1;:12:::0;:19:::1;:21::i;:::-;75120:23;:14;:21;:23::i;:::-;:47;75116:314;;;75209:33;:14:::0;75229:12;75209:19:::1;:33::i;:::-;75188:54:::0;-1:-1:-1;75276:37:0::1;:12:::0;75188:54;75276:17:::1;:37::i;:::-;75261:52;;75116:314;;;75375:39;:18:::0;75399:14;75375:23:::1;:39::i;:::-;75354:60;;75116:314;75541:1;75517:21;:12;:19;:21::i;:::-;:25;75513:105;;;75563:39;75578:9;75589:12;75563:14;:39::i;:::-;75665:1;75636:26;:18;:24;:26::i;:::-;:30;75632:131;;;75687:60;75711:9;75722:24;:18;:22;:24::i;:::-;75687:23;:60::i;:::-;75777:47;75786:9;75797:10;75809:14;75777:8;:47::i;:::-;75917:9;-1:-1:-1::0;;;;;75846:341:0::1;75883:7;-1:-1:-1::0;;;;;75846:341:0::1;;75946:47;:12;:38;;;:45;:47::i;:::-;76012:43;:12;:34;;;:41;:43::i;:::-;76074:23;:14;:21;:23::i;:::-;76116:10;76145:27;:18;:25;:27::i;:::-;75846:341;;;;;;;;;;:::i;:::-;;;;;;;;59368:1;;;;;76299:9;-1:-1:-1::0;;;;;76231:618:0::1;76265:7;-1:-1:-1::0;;;;;76231:618:0::1;;76328:1;76348:47;:12;:38;;;:45;:47::i;:::-;76414:42;:12;:34;;;:40;:42::i;:::-;76475:1;76495::::0;76515:32:::1;:12;:24;;;:30;:32::i;:::-;76566:1;76586:29;:12;:20;;;:27;:29::i;:::-;76634:41;:32;:12;:26;;;:30;:32::i;:::-;:39;:41::i;:::-;76694:33;:9;-1:-1:-1::0;;;;;76694:22:0::1;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:33::-;76746:35;:12;:27;;;:33;:35::i;:::-;76800:34;:12;:25;;;:32;:34::i;:::-;76231:618;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0;59516:6;:21;-1:-1:-1;73499:3369:0:o;57834:25::-;;;-1:-1:-1;;;;;57834:25:0;;:::o;66458:4225::-;59598:6;;;;59597:7;59589:36;;;;-1:-1:-1;;;59589:36:0;;;;;;;:::i;:::-;57984:1:::1;59206:6;;:18;;59198:62;;;;-1:-1:-1::0;;;59198:62:0::1;;;;;;;:::i;:::-;57984:1;59338:6;:17:::0;66744:32:::2;66760:9:::0;66771:4:::2;66744:15;:32::i;:::-;66787:38;;;::::0;;::::2;::::0;::::2;66807:17:::0;66787:38:::2;:::i;:::-;66836:30;;;::::0;;::::2;::::0;::::2;66856:9:::0;66836:30:::2;:::i;:::-;66877:169;66914:55;;;::::0;;::::2;::::0;::::2;66959:9:::0;66914:55:::2;:::i;:::-;:39;66939:13;:11;:13::i;66914:39::-;:44:::0;::::2;:55::i;66877:169::-;67057:36;67083:9;67057:25;:36::i;:::-;67166:8;::::0;:62:::2;::::0;-1:-1:-1;;;67166:62:0;;67123:10:::2;::::0;-1:-1:-1;;;;;67166:8:0::2;::::0;:27:::2;::::0;:62:::2;::::0;67202:9;;67123:10;;67222:5;;67166:62:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67144:154;;;;-1:-1:-1::0;;;67144:154:0::2;;;;;;;:::i;:::-;67311:32;;:::i;:::-;67420:22;67445:65;:52;67479:9;67490:6;67445:33;:52::i;:::-;:57:::0;:63:::2;:65::i;:::-;67420:90:::0;-1:-1:-1;67525:18:0::2;67546:20:::0;;:35:::2;;67576:5;67546:35;;;67569:4;67546:35;67525:56;;67601:13;67596:241;;67635:186;67680:33;67695:9;67706:6;67680:14;:33::i;:::-;67736:14;;;;;;;;;-1:-1:-1::0;;;;;67736:14:0::2;-1:-1:-1::0;;;;;67736:37:0::2;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;67635:186;67943:13;:70;;;;68008:5;67960:53;;;;;;;;67979:1;67961:15;:19;:42;;67994:9;67961:42;;;67983:8;67961:42;67960:53;;;;;;;;;67943:70;67939:631;;;68049:235;68096:9:::0;68128:5;68156:33:::2;;;::::0;;::::2;::::0;::::2;68179:9:::0;68156:33:::2;:::i;:::-;:22;;::::0;;::::2;::::0;::::2;:17:::0;:22:::2;:::i;:::-;::::0;::::2;:33::i;:::-;68049:235;;::::0;;::::2;::::0;::::2;68212:21:::0;68049:235:::2;:::i;:::-;;;::::0;;::::2;::::0;::::2;68256:9:::0;68049:235:::2;:::i;:::-;:24;:235::i;:::-;68034:250;;67939:631;;;68340:214;68382:9:::0;68414:5;68340:214:::2;;::::0;;::::2;::::0;::::2;68442:17:::0;68340:214:::2;:::i;:::-;;;::::0;;::::2;::::0;::::2;68482:9:::0;68340:214:::2;:::i;:::-;;;::::0;;::::2;::::0;::::2;68514:21:::0;68340:214:::2;:::i;:::-;:19;:214::i;:::-;68325:229;;67939:631;68628:53;68640:9;68651:6;68659:12;:21;;;68628:11;:53::i;:::-;68840:1;68808:29;:12;:20;;;:27;:29::i;:::-;:33;68804:105;;;68862:31;68883:9;68862:20;:31::i;:::-;68990:28;69021:9;-1:-1:-1::0;;;;;69021:20:0::2;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68990:53;;69099:1;69062:34;:12;:26;;;:32;:34::i;:::-;:38;69058:322;;;69121:97;69149:6;69165:8;;;;;;;;;-1:-1:-1::0;;;;;69165:8:0::2;69176:41;:32;:12;:26;;;:30;:32::i;:41::-;-1:-1:-1::0;;;;;69121:27:0;::::2;::::0;:97;;:27:::2;:97::i;:::-;69058:322;;;69281:1;69244:34;:12;:26;;;:32;:34::i;:::-;:38;69240:140;;;69303:61;69312:9;69323:6;69331:32;:12;:26;;;:30;:32::i;69303:61::-;69420:8;::::0;:40:::2;::::0;-1:-1:-1;;;69420:40:0;;-1:-1:-1;;;;;69420:8:0;;::::2;::::0;:29:::2;::::0;:40:::2;::::0;69450:9;;69420:40:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;59368:1;;;69705:37;;:::i;:::-;69745:70;69757:6;69765:9;69776:12;:38;;;69745:11;:70::i;:::-;69705:110;;69851:17;69871:33;:9;-1:-1:-1::0;;;;;69871:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;:33;69851:53;;69915:21;69939:35;:12;:27;;;:33;:35::i;:::-;69915:59;;70023:20;70046:34;:12;:25;;;:32;:34::i;:::-;70023:57;;70155:9;-1:-1:-1::0;;;;;70096:579:0::2;70126:6;-1:-1:-1::0;;;;;70096:579:0::2;;70180:37;:12;:21;;;:28;;;:35;:37::i;:::-;70232:47;:12;:38;;;:45;:47::i;:::-;70294:42;:12;:34;;;:40;:42::i;:::-;70351:23;:14;:21;:23::i;:::-;70389:21:::0;;:26;:34:::2;::::0;:32:::2;:34::i;:::-;70438:32;:12;:24;;;:30;:32::i;:::-;70485:39;:12;:31;;;:37;:39::i;:::-;70539:29;:12;:20;;;:27;:29::i;:::-;70583:1;70599:9;70623:14;70652:12;70096:579;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0::1;59516:6;:21:::0;-1:-1:-1;;;;;;;;;66458:4225:0:o;83404:485::-;83617:39;;:::i;:::-;83658:48;;:::i;:::-;83724:24;;:::i;:::-;83751:31;83763:9;83774:7;83751:11;:31::i;:::-;83800:8;;:81;;-1:-1:-1;;;83800:81:0;;83724:58;;-1:-1:-1;;;;;;83800:8:0;;:44;;:81;;83845:9;;83724:58;;83866:14;;83800:81;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83793:88;;;;;83404:485;;;;;;:::o;57866:25::-;;;-1:-1:-1;;;;;57866:25:0;;:::o;50262:79::-;50327:6;;-1:-1:-1;;;;;50327:6:0;50262:79;:::o;70792:2374::-;59598:6;;;;59597:7;59589:36;;;;-1:-1:-1;;;59589:36:0;;;;;;;:::i;:::-;57984:1:::1;59206:6;;:18;;59198:62;;;;-1:-1:-1::0;;;59198:62:0::1;;;;;;;:::i;:::-;57984:1;59338:6;:17:::0;70997:32:::2;71013:9:::0;71024:4:::2;70997:15;:32::i;:::-;71040:36;71066:9;71040:25;:36::i;:::-;71134:10;71155:24;;:::i;:::-;71182:52;71216:9;71227:6;71182:33;:52::i;:::-;71155:79;;71245:10;71258:26;:8;:13;;;:24;:26::i;:::-;:49;;71298:9;71258:49;;;71287:8;71258:49;71340:8;::::0;:62:::2;::::0;-1:-1:-1;;;71340:62:0;;71245;;-1:-1:-1;;;;;;71340:8:0::2;::::0;:27:::2;::::0;:62:::2;::::0;71376:9;;71388:6;;71245:62;;71340::::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71318:155;;;;-1:-1:-1::0;;;71318:155:0::2;;;;;;;:::i;:::-;71486:32;;:::i;:::-;71521:70;71543:9:::0;71554:6;71521:70:::2;;::::0;;::::2;::::0;::::2;71562:22:::0;71521:70:::2;:::i;:::-;71586:4;71521:21;:70::i;:::-;71486:105;;71770:1;71738:29;:12;:20;;;:27;:29::i;:::-;:33;71734:171;;;71792:31;71813:9;71792:20;:31::i;:::-;71842:47;71857:9;71868:12;:20;;;71842:14;:47::i;:::-;71919:61;71928:9;71939:6;71947:32;:12;:26;;;:30;:32::i;71919:61::-;72024:8;::::0;:40:::2;::::0;-1:-1:-1;;;72024:40:0;;-1:-1:-1;;;;;72024:8:0;;::::2;::::0;:29:::2;::::0;:40:::2;::::0;72054:9;;72024:40:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;72131:37;;:::i;:::-;72171:70;72183:6;72191:9;72202:12;:38;;;72171:11;:70::i;:::-;72131:110;;72336:17;72356:33;:9;-1:-1:-1::0;;;;;72356:22:0::2;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;:33;72336:53;;72404:21;72428:35;:12;:27;;;:33;:35::i;:::-;72404:59;;72478:20;72501:34;:12;:25;;;:32;:34::i;:::-;72478:57;;72622:9;-1:-1:-1::0;;;;;72555:592:0::2;72589:6;-1:-1:-1::0;;;;;72555:592:0::2;;72651:1;72681:47;:12;:38;;;:45;:47::i;:::-;72747:42;:12;:34;;;:40;:42::i;:::-;72808:23;:14;:21;:23::i;:::-;72850:21:::0;;:26;:34:::2;::::0;:32:::2;:34::i;:::-;72903:32;:12;:24;;;:30;:32::i;:::-;72954:1;72991:29;:12;:20;;;:27;:29::i;:::-;73039:1;73059:9;73087:14;73120:12;72555:592;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0::1;59516:6;:21:::0;-1:-1:-1;;;;;;;;70792:2374:0:o;60042:826::-;59598:6;;;;59597:7;59589:36;;;;-1:-1:-1;;;59589:36:0;;;;;;;:::i;:::-;57984:1:::1;59206:6;;:18;;59198:62;;;;-1:-1:-1::0;;;59198:62:0::1;;;;;;;:::i;:::-;57984:1;59338:6;:17:::0;60232:32:::2;60248:9:::0;60259:4:::2;60232:15;:32::i;:::-;60275:33;;;::::0;;::::2;::::0;::::2;60295:12:::0;60275:33:::2;:::i;:::-;60390:10;60411:24;;:::i;:::-;60438:52;60472:9;60483:6;60438:33;:52::i;:::-;60411:79:::0;-1:-1:-1;60519:34:0::2;;;::::0;;::::2;::::0;::::2;60540:12:::0;60519:34:::2;:::i;:::-;:15;::::0;::::2;::::0;;:20:::2;:34::i;:::-;60501:15;::::0;::::2;:52:::0;60564:40:::2;60576:9:::0;60587:6;60501:8;60564:11:::2;:40::i;:::-;60731:8;::::0;60656:108:::2;::::0;60715:6;;-1:-1:-1;;;;;60731:8:0::2;60742:21;:19;;::::0;;::::2;::::0;::::2;:12:::0;:19:::2;:::i;:21::-;60674:9;-1:-1:-1::0;;;;;60674:20:0::2;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;60656:58:0::2;::::0;:108;;:58:::2;:108::i;:::-;-1:-1:-1::0;;;;;60782:78:0;;::::2;::::0;;::::2;;60831:21;:19;;::::0;;::::2;::::0;::::2;:12:::0;:19:::2;:::i;:21::-;60855:1;60858::::0;60782:78:::2;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;57940:1:0::1;59516:6;:21:::0;-1:-1:-1;;60042:826:0:o;82526:478::-;82615:15;;:::i;:::-;82643:19;;:::i;:::-;82665:41;82687:9;82698:7;82665:21;:41::i;:::-;82643:63;;82717:28;82748:44;82790:1;82748:9;-1:-1:-1;;;;;82748:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;:44::i;:::-;82717:75;;82836:20;82807:3;:25;;;:49;82803:92;;;-1:-1:-1;82880:3:0;-1:-1:-1;82873:10:0;;82803:92;82914:8;;:82;;-1:-1:-1;;;82914:82:0;;-1:-1:-1;;;;;82914:8:0;;;;:44;;:82;;82959:9;;82970:3;;82975:20;;82914:82;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;82907:89;;;;82526:478;;;;;:::o;58709:374::-;46678:13;;;;;;;;:33;;;46695:16;:14;:16::i;:::-;46678:50;;;-1:-1:-1;46716:12:0;;;;46715:13;46678:50;46670:109;;;;-1:-1:-1;;;46670:109:0;;;;;;;:::i;:::-;46792:19;46815:13;;;;;;46814:14;46839:101;;;;46874:13;:20;;-1:-1:-1;;;;46874:20:0;;;;;46909:19;46890:4;46909:19;;;46839:101;58856:16:::1;:14;:16::i;:::-;58885:14;:49:::0;;-1:-1:-1;;;;;58885:49:0;;::::1;-1:-1:-1::0;;;;;;58885:49:0;;::::1;;::::0;;;58945:8:::1;:31:::0;;;;::::1;::::0;;::::1;;::::0;;58987:8:::1;:31:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;58885:49;59029:6:::1;:21:::0;59061:6:::1;:14:::0;;-1:-1:-1;;59061:14:0::1;::::0;;46966:68;;;;47017:5;47001:21;;-1:-1:-1;;47001:21:0;;;58709:374;;;;:::o;85201:169::-;85274:34;;:::i;:::-;85328:8;;:34;;-1:-1:-1;;;85328:34:0;;-1:-1:-1;;;;;85328:8:0;;;;:23;;:34;;85352:9;;85328:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;59737:130::-;50484:12;:10;:12::i;:::-;50474:6;;-1:-1:-1;;;;;50474:6:0;;;:22;;;50466:67;;;;-1:-1:-1;;;50466:67:0;;;;;;;:::i;:::-;59827:14:::1;:32:::0;;-1:-1:-1;;;;;;59827:32:0::1;-1:-1:-1::0;;;;;59827:32:0;;;::::1;::::0;;;::::1;::::0;;59737:130::o;81130:1164::-;81258:34;;:::i;:::-;81310:24;;:::i;:::-;81337:31;81349:9;81360:7;81337:11;:31::i;:::-;81310:58;;81379:34;81399:8;:13;;;81379:19;:34::i;:::-;81424:42;81444:8;:21;;;81424:19;:42::i;:::-;81482:47;;:::i;:::-;81547:81;81583:9;81594:7;81603:24;81547:35;:81::i;:::-;81479:150;;;81645:47;;:::i;:::-;81710:75;81746:9;81757:7;81766:18;81710:35;:75::i;:::-;81642:144;;;81799:48;;:::i;:::-;81886:20;:12;:18;:20::i;:::-;81863;:12;:18;:20::i;:::-;:43;:73;;81924:12;81863:73;;;81909:12;81863:73;81799:137;;81949:50;;:::i;:::-;82015:8;;:94;;-1:-1:-1;;;82015:94:0;;-1:-1:-1;;;;;82015:8:0;;;;:58;;:94;;82074:9;;82085:8;;82095:13;;82015:94;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81949:160;;82140:146;82250:8;:21;;;82140:86;82201:16;:24;;;82140:55;82165:16;:29;;;82140:24;:55::i;:146::-;82120:166;81130:1164;-1:-1:-1;;;;;;;;81130:1164:0:o;51207:244::-;50484:12;:10;:12::i;:::-;50474:6;;-1:-1:-1;;;;;50474:6:0;;;:22;;;50466:67;;;;-1:-1:-1;;;50466:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;51296:22:0;::::1;51288:73;;;;-1:-1:-1::0;;;51288:73:0::1;;;;;;;:::i;:::-;51398:6;::::0;51377:38:::1;::::0;-1:-1:-1;;;;;51377:38:0;;::::1;::::0;51398:6:::1;::::0;51377:38:::1;::::0;51398:6:::1;::::0;51377:38:::1;51426:6;:17:::0;;-1:-1:-1;;;;;;51426:17:0::1;-1:-1:-1::0;;;;;51426:17:0;;;::::1;::::0;;;::::1;::::0;;51207:244::o;79351:1094::-;79417:32;79433:9;79444:4;79417:15;:32::i;:::-;79460:14;;:49;;-1:-1:-1;;;79460:49:0;;-1:-1:-1;;;;;79460:14:0;;;;:38;;:49;;79499:9;;79460:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79522:39;;:::i;:::-;79564:14;;;;;;;;;-1:-1:-1;;;;;79564:14:0;-1:-1:-1;;;;;79564:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;79609:31:0;;;;;;:11;:31;;;;;79522:76;;-1:-1:-1;79609:59:0;;79688:69;79710:46;79629:9;79710:35;:46::i;:::-;79688:16;;:21;:69::i;:::-;79609:159;;;;;;;-1:-1:-1;79609:159:0;;;;;;;;;;;;79781:40;;:::i;:::-;-1:-1:-1;;;;;;79824:31:0;;;;;;:11;:31;;;;;;;;;79781:92;;;;;;;;79824:49;;;;79781:92;;;79884:46;;:::i;:::-;79933:40;:16;79955:17;79933:21;:40::i;:::-;79884:89;;80025:1;79990:32;:23;:30;:32::i;:::-;:36;79986:245;;;80043:176;80093:9;80121:23;80163:14;;;;;;;;;-1:-1:-1;;;;;80163:14:0;-1:-1:-1;;;;;80163:39:0;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80043:176;80288:9;-1:-1:-1;;;;;80248:189:0;;80313:26;:17;:24;:26::i;:::-;80354:32;:23;:30;:32::i;:::-;80401:25;:16;:23;:25::i;:::-;80248:189;;;;;;;;:::i;:::-;;;;;;;;79351:1094;;;;:::o;48568:106::-;48656:10;48568:106;:::o;103136:1060::-;103253:15;;:::i;:::-;103286:34;;:::i;:::-;103323:41;103345:9;103356:7;103323:21;:41::i;:::-;103286:78;;103379:31;:18;:23;;;:29;:31::i;:::-;103375:94;;103439:18;-1:-1:-1;103432:25:0;;103375:94;103479:28;103510:44;103552:1;103510:9;-1:-1:-1;;;;;103510:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;103479:75;;103613:20;103569:18;:40;;;:64;103565:122;;;-1:-1:-1;103657:18:0;-1:-1:-1;103650:25:0;;103565:122;103699:32;;:::i;:::-;103747:8;;:97;;-1:-1:-1;;;103747:97:0;;-1:-1:-1;;;;;103747:8:0;;;;:44;;:97;;103792:9;;103803:18;;103823:20;;103747:97;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103699:145;;103855:49;103867:9;103878:7;103887:16;103855:11;:49::i;:::-;103984:7;-1:-1:-1;;;;;103920:234:0;103959:9;-1:-1:-1;;;;;103920:234:0;;104006:29;:16;:21;;;:27;:29::i;:::-;104050:18;:40;;;104105:16;:38;;;103920:234;;;;;;;;:::i;:::-;;;;;;;;104172:16;103136:1060;-1:-1:-1;;;;;103136:1060:0:o;104502:261::-;104592:14;;:43;;-1:-1:-1;;;104592:43:0;;-1:-1:-1;;;;;104592:14:0;;;;:32;;:43;;104625:9;;104592:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104584:74;;;;-1:-1:-1;;;104584:74:0;;;;;;;:::i;:::-;104686:9;-1:-1:-1;;;;;104686:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104677:25;;:5;:25;;;104704:5;:50;;;;;;;;;;;;;;;-1:-1:-1;;;104704:50:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;104704:50:0;;;;104669:86;;;;;-1:-1:-1;;;104669:86:0;;;;;;;;:::i;:::-;;104502:261;;:::o;104771:139::-;104865:17;:8;:15;:17::i;:::-;104857:45;;;;-1:-1:-1;;;104857:45:0;;;;;;;:::i;:::-;104771:139;:::o;16937:228::-;17058:34;;:::i;:::-;17037:1;16882;:3;;;-1:-1:-1;;;;;16867:18:0;;16887:21;;;;;;;;;;;;;;;;;16859:50;;;;;-1:-1:-1;;;16859:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;17117:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;17152:3;;17117:40;;-1:-1:-1;17117:40:0;16937:228::o;15658:185::-;15734:20;;:::i;:::-;15767:22;;:::i;:::-;15806:3;;:10;;15814:1;15806:7;:10::i;:::-;15800:16;;;15658:185;-1:-1:-1;;;15658:185:0:o;7651:95::-;7735:3;;7651:95::o;85694:1111::-;-1:-1:-1;;;;;85869:31:0;;;85834:32;85869:31;;;:11;:31;;;;;;;;:52;;;;;:43;;;:52;;;;;85984:108;;;;;;;86053:28;;;85984:108;;;:31;;;;;;;:54;;;;;;;;:49;;;;:54;;;85869:52;85984:108;;:54;:108::i;:::-;-1:-1:-1;;;;;85932:31:0;;;;;;:11;:31;;;;;;;;:160;;:49;;;;:160;;;86126:14;;86103:37;;;86176:16;;;;86151:41;:22;;;:41;86234:22;;;;86203:53;:28;;;:53;;;86322:46;;;;86267:101;:52;;;:101;86435:47;;;;86379:103;:53;;;:103;;;;86523:21;;;;86493:27;;;:51;86595:31;;;;86555:37;;;:71;86689:108;;;;;;;;;;:31;;;;;;;:54;;;;;;;;;;;;:108;;:54;:108::i;:::-;-1:-1:-1;;;;;86637:31:0;;;;;;;:11;:31;;;;;:160;;:49;;;;:160;;;;-1:-1:-1;;;85694:1111:0:o;105478:454::-;105685:27;105715:43;:35;:12;105733:16;105715:17;:35::i;:43::-;105685:73;;105791:20;:75;;105865:1;105842:20;:24;105791:75;;;105838:1;105814:20;:25;;105791:75;105769:155;;;;-1:-1:-1;;;105769:155:0;;;;;;;:::i;101780:207::-;101931:8;;:48;;-1:-1:-1;;;101931:48:0;;-1:-1:-1;;;;;101931:8:0;;;;:17;;:48;;101949:9;;101960;;101971:7;;101931:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101780:207;;;:::o;104918:151::-;105021:13;:5;:11;:13::i;:::-;105013:48;;;;-1:-1:-1;;;105013:48:0;;;;;;;:::i;86813:841::-;86894:24;;:::i;:::-;-1:-1:-1;;;;;;86921:31:0;;;;;;;:11;:31;;;;;;;;:52;;;;;:43;;;;:52;;;;;86894:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;86894:79:0;;;;;;;;;;87105:21;;87036:31;;;;;;;:54;;;;;;;:49;;;;:54;;;:101;;:54;:101::i;:::-;-1:-1:-1;;;;;86984:31:0;;;;;;:11;:31;;;;;;;:153;;:49;;;;:153;;;;87282:364;;;;;;;;;87312:20;:18;:20::i;:::-;87282:364;;;;87355:14;:12;:14::i;:::-;87282:364;;;;87398:14;:12;:14::i;:::-;87282:364;;;;87465:20;:18;:20::i;:::-;87282:364;;;;87539:14;:12;:14::i;:::-;87282:364;;;;87633:1;87282:364;;;;87581:14;:12;:14::i;:::-;87282:364;;-1:-1:-1;;;;;87227:31:0;;;;;;;:11;:31;;;;;;;;:52;;;;;;:43;;;;:52;;;;;;:419;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87227:419:0;;;;;;;;;;;;;;;;;;;;;;;;;86813:841::o;14614:269::-;14674:22;;:::i;:::-;14709:24;;:::i;:::-;14748:3;;14754:1;-1:-1:-1;14744:113:0;;;14790:3;;;14786:7;14772:22;;14744:113;;;14841:3;;14827:18;;-1:-1:-1;14827:18:0;14614:269::o;9051:173::-;9124:14;;:::i;:::-;9151:16;;:::i;:::-;9193:3;;9184;;:13;;:8;:13::i;17812:304::-;17964:34;;:::i;:::-;17943:1;16882;:3;;;-1:-1:-1;;;;;16867:18:0;;16887:21;;;;;;;;;;;;;;;;;16859:50;;;;;-1:-1:-1;;;16859:50:0;;;;;;;;:::i;:::-;;18016:36:::1;;:::i;:::-;18084:3:::0;;18069;;:20:::1;::::0;:7:::1;:20::i;:::-;18063:26:::0;;;17812:304;-1:-1:-1;;;;17812:304:0:o;15402:197::-;15487:20;;:::i;:::-;15520:22;;:::i;:::-;15568:3;;15559;;:13;;:8;:13::i;17399:304::-;17551:34;;:::i;:::-;17530:1;16882;:3;;;-1:-1:-1;;;;;16867:18:0;;16887:21;;;;;;;;;;;;;;;;;16859:50;;;;;-1:-1:-1;;;16859:50:0;;;;;;;;:::i;:::-;;17603:36:::1;;:::i;:::-;17671:3:::0;;17656;;:20:::1;::::0;:7:::1;:20::i;14922:196::-:0;15007:20;;:::i;:::-;15040:22;;:::i;:::-;15087:3;;15079;;:12;;:7;:12::i;101995:157::-;102100:8;;:44;;-1:-1:-1;;;102100:44:0;;-1:-1:-1;;;;;102100:8:0;;;;:23;;:44;;102124:9;;102135:8;;102100:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101995:157;;:::o;102427:651::-;102655:14;;:42;;-1:-1:-1;;;102655:42:0;;102616:28;;-1:-1:-1;;;;;102655:14:0;;:31;;:42;;102687:9;;102655:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102616:82;-1:-1:-1;;;;;;102717:34:0;;102709:68;;;;-1:-1:-1;;;102709:68:0;;;;;;;:::i;:::-;102788:39;;:::i;:::-;102830:30;:4;102840:19;102830:9;:30::i;:::-;102871:8;;:68;;-1:-1:-1;;;102871:68:0;;102788:72;;-1:-1:-1;;;;;;102871:8:0;;:17;;:68;;102889:9;;102900:20;;102788:72;;102871:68;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102950:31;;:::i;:::-;102984:27;:4;102994:16;102984:9;:27::i;:::-;103022:8;;:48;;-1:-1:-1;;;103022:48:0;;102950:61;;-1:-1:-1;;;;;;103022:8:0;;:27;;:48;;103050:9;;102950:61;;103022:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102427:651;;;;;;:::o;7435:91::-;7474:14;;:::i;:::-;-1:-1:-1;7508:10:0;;;;;;;;;-1:-1:-1;7508:10:0;;7435:91;:::o;98139:1877::-;98343:32;;:::i;:::-;98417:27;;:::i;:::-;98447:41;98469:9;98480:7;98447:21;:41::i;:::-;98417:71;;98499:50;;:::i;:::-;-1:-1:-1;98552:16:0;;98579:36;98552:16;98579:19;:36::i;:::-;98631:48;;:::i;:::-;98696:81;98732:9;98743:7;98752:24;98696:35;:81::i;:::-;98628:149;;;98790:50;;:::i;:::-;98856:8;;:97;;-1:-1:-1;;;98856:97:0;;-1:-1:-1;;;;;98856:8:0;;;;:58;;:97;;98915:9;;98926:11;;98939:13;;98856:97;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98790:163;-1:-1:-1;99003:29:0;:15;-1:-1:-1;;99003:25:0;:29::i;:::-;98966:34;;;;:66;;;;99043:24;;;:40;;;99117:24;;;;99094:20;;;;:47;;;;99182:31;;;-1:-1:-1;99152:27:0;;:61;99252:29;;;99224:25;;;:57;99346:29;;99321:69;;-1:-1:-1;;99387:2:0;99321:55;;:24;:55::i;:69::-;99292:26;;;:98;-1:-1:-1;;;;;99442:20:0;;;99503:1;99477:23;:15;:21;:23::i;:::-;:27;:86;;99534:29;99477:86;;;99507:24;99477:86;99578:21;:15;:19;:21::i;:::-;99614:22;99651:21;99442:241;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99401:38;;;;:282;;;;99790:8;;99914:24;;;;99883;;;;-1:-1:-1;;;;;99790:8:0;;;;:35;;99840:9;;99864:89;;-1:-1:-1;;99950:2:0;99864:75;;:44;;:13;;:18;:44::i;:89::-;99790:174;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99975:33;99989:9;100000:7;99975:13;:33::i;:::-;98139:1877;;;;;;;;;;:::o;85423:263::-;85494:19;85516:14;:12;:14::i;:::-;-1:-1:-1;;;;;85541:31:0;;;;;;:11;:31;;;;;;;:66;;;85623:55;85494:36;;-1:-1:-1;85623:55:0;;;;85561:9;;85494:36;;85623:55;:::i;:::-;;;;;;;;85423:263;;:::o;8614:173::-;8687:14;;:::i;:::-;8714:16;;:::i;:::-;8756:3;;8747;;:13;;:8;:13::i;7921:222::-;8020:3;;8014;;7993:4;;-1:-1:-1;8010:107:0;;;-1:-1:-1;8047:1:0;8040:8;;8010:107;8076:3;;8070;;:9;8066:51;;;-1:-1:-1;;;8096:9:0;;8066:51;-1:-1:-1;8134:1:0;7921:222;;;;:::o;8398:172::-;8471:14;;:::i;:::-;8498:16;;:::i;:::-;8539:3;;8531;;:12;;:7;:12::i;8182:172::-;8255:14;;:::i;:::-;8282:16;;:::i;:::-;8323:3;;8315;;:12;;:7;:12::i;102160:259::-;102297:14;;:42;;-1:-1:-1;;;102297:42:0;;102266:28;;-1:-1:-1;;;;;102297:14:0;;:31;;:42;;102329:9;;102297:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102350:8;;:61;;-1:-1:-1;;;102350:61:0;;102266:73;;-1:-1:-1;;;;;;102350:8:0;;:17;;:61;;102368:9;;102266:73;;102403:7;;102350:61;;;:::i;17173:121::-;17250:7;17277;:1;:5;:7::i;:::-;:9;;17173:121;-1:-1:-1;;17173:121:0:o;7534:109::-;7572:14;;:::i;:::-;7606:29;;;;;;;;7614:20;7631:2;7614:16;:20::i;:::-;7606:29;;7599:36;-1:-1:-1;7534:109:0;:::o;18983:304::-;19135:34;;:::i;:::-;19114:1;16882;:3;;;-1:-1:-1;;;;;16867:18:0;;16887:21;;;;;;;;;;;;;;;;;16859:50;;;;;-1:-1:-1;;;16859:50:0;;;;;;;;:::i;:::-;;19187:36:::1;;:::i;:::-;19238:22;19245:14;19257:1;19245:11;:14::i;:::-;19238:1:::0;;:6:::1;:22::i;105077:393::-:0;105157:20;105180:14;:12;:14::i;:::-;-1:-1:-1;;;;;105225:31:0;;;;;;:11;:31;;;;;:52;105157:37;;-1:-1:-1;105209:68:0;;105205:258;;;105380:12;105320:44;105342:9;105353:10;105320:21;:44::i;:::-;:56;;;:72;;105294:157;;;;-1:-1:-1;;;105294:157:0;;;;;;;:::i;87782:3209::-;88032:32;;:::i;:::-;88094:10;88115:27;;:::i;:::-;88145:40;88167:9;88178:6;88145:21;:40::i;:::-;88115:70;;88233:60;88243:9;88254:5;88261:13;88276:16;88233:9;:60::i;:::-;88196:34;;;:97;88304:42;;:::i;:::-;88371:34;;;;88349:16;;:57;;:21;:57::i;:::-;88529:33;;;;88577:16;;88304:102;;-1:-1:-1;88529:33:0;88577:24;;:22;:24::i;:::-;88573:130;;88647:44;88689:1;88647:9;-1:-1:-1;;;;;88647:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:44;88623:68;;88573:130;88715:8;;-1:-1:-1;;;;;88715:8:0;:35;88751:9;88762:39;88787:13;88762:24;:39::i;:::-;88715:87;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88902:8;;;;;;;;;-1:-1:-1;;;;;88902:8:0;-1:-1:-1;;;;;88902:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;88892:33:0;:6;-1:-1:-1;;;;;88892:33:0;;88888:398;;88942:42;;:::i;:::-;88987:9;-1:-1:-1;;;;;88987:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88942:79;;89071:1;89040:28;:19;:26;:28::i;:::-;:32;89036:239;;;89224:1;89182:38;89200:19;89182:13;:7;:11;:13::i;:::-;:17;;:38::i;:::-;:43;;;;89174:85;;;;-1:-1:-1;;;89174:85:0;;;;;;;:::i;:::-;88888:398;;89298:24;;:::i;:::-;89384:60;;:::i;:::-;89464:55;89489:29;:13;89508:9;89489:18;:29::i;89464:55::-;89384:135;;89536:50;;:::i;:::-;89606:8;;;;;;;;;-1:-1:-1;;;;;89606:8:0;-1:-1:-1;;;;;89606:58:0;;89687:9;89719:11;89753:25;89606:191;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89814:26;;;:54;;;;-1:-1:-1;89913:31:0;;;;89883:27;;;:61;-1:-1:-1;89987:29:0;;;89959:25;;;:57;90051:29;90033:15;;;:47;90158:48;;:::i;:::-;90227:80;90263:9;90274:6;90282:24;90227:35;:80::i;:::-;90322:31;;;:47;-1:-1:-1;;90425:38:0;;;:54;;;90490:23;;;90578:38;90548:24;;;;:69;;:29;:69::i;:::-;90524:21;;;:93;90628:30;;;:54;;;90741:45;90776:9;90741:34;:45::i;:::-;90693;;;:93;90846:46;90882:9;90846:35;:46::i;:::-;90797;;;:95;90926:14;:12;:14::i;:::-;90903:20;;;:37;90951:32;;-1:-1:-1;90951:12:0;;87782:3209;-1:-1:-1;;;;;;;;87782:3209:0:o;90999:4335::-;91253:19;;:::i;:::-;91285:35;;:::i;:::-;91323:33;:17;91346:9;91323:22;:33::i;:::-;91285:71;;91368:42;;:::i;:::-;91412:48;;:::i;:::-;91477:84;91513:9;91524:10;91536:24;91477:35;:84::i;:::-;91367:194;;;;91572:32;;:::i;:::-;91706:21;:12;:19;:21::i;:::-;91675:28;:19;:26;:28::i;:::-;:52;91671:3538;;;91744:8;;-1:-1:-1;;;;;91744:8:0;:35;91780:9;91791:52;-1:-1:-1;;91791:38:0;91816:12;91791:24;:38::i;:52::-;91744:100;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91859:27;;:::i;:::-;91889:44;91911:9;91922:10;91889:21;:44::i;:::-;91859:74;;91985:64;91995:9;92006:5;92013:12;92027:21;91985:9;:64::i;:::-;91948:34;;;:101;92211:16;;:24;;:22;:24::i;:::-;:29;92207:226;;92288:129;92376:22;:11;:16;;;:20;:22::i;:::-;92288:60;92307:40;:12;:34;;;:38;:40::i;:::-;92288:13;;:18;:60::i;:129::-;92261:24;;;:156;92207:226;92524:50;;:::i;:::-;92598:8;;;;;;;;;-1:-1:-1;;;;;92598:8:0;-1:-1:-1;;;;;92598:58:0;;92683:9;92719:11;92757:12;:24;;;92598:206;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92848:24;;;;;92825:20;;;;:47;;;;92921:31;;;92891:27;;;:61;92999:29;;;;92971:25;;;:57;93047:38;;;:53;;;93198:29;;93177:18;;;:50;-1:-1:-1;93441:24:0;;;;93422:44;;:13;;:18;:44::i;:::-;93388:31;;;:78;93895:53;;:::i;:::-;93995:1;93968:24;:11;:16;;;:22;:24::i;:::-;:28;:402;;94220:150;94309:12;:38;;;94220:57;94257:19;94220:12;:31;;;:36;;:57;;;;:::i;:150::-;93968:402;;;94020:176;94142:12;:31;;;94020:90;94071:12;:38;;;94020:45;94045:19;94020:24;:45::i;:90::-;:95;;:176::i;:::-;93895:475;;94422:1;94393:26;:18;:24;:26::i;:::-;:30;94385:69;;;;-1:-1:-1;;;94385:69:0;;;;;;;:::i;:::-;94490:24;;:::i;:::-;94551:18;;;;;94533:15;;;:36;94626:34;;;;94604:16;;:57;;:21;:57::i;:::-;94588:73;;94704:24;:18;:22;:24::i;:::-;94680:21;;;:48;94780:33;;;;;94747:30;;;:66;94880:45;94915:9;94880:34;:45::i;:::-;94832;;;:93;94993:46;95029:9;94993:35;:46::i;:::-;94944;;;:95;95081:14;:12;:14::i;:::-;95058:20;;;:37;95114:32;;-1:-1:-1;95114:12:0;;-1:-1:-1;95178:19:0;;-1:-1:-1;;;;95178:19:0;91671:3538;95228:98;95256:9;95267:5;95274:17;95293:9;95304:21;95228:27;:98::i;:::-;95221:105;;;;;;90999:4335;;;;;;;;:::o;42224:216::-;42336:96;42356:5;42386:27;;;42415:4;42421:2;42425:5;42363:68;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;42363:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;42363:68:0;-1:-1:-1;;;;;;42363:68:0;;;;;;;;;;42336:19;:96::i;100674:1098::-;100825:22;;:::i;:::-;100860:26;;:::i;:::-;100889:36;;-1:-1:-1;;;100889:36:0;;-1:-1:-1;;;;;100889:17:0;;;;;:36;;100907:17;;100889:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100860:65;;100955:1;100940:12;:3;:10;:12::i;:::-;:16;100936:795;;;101012:14;;:42;;-1:-1:-1;;;101012:42:0;;100973:28;;-1:-1:-1;;;;;101012:14:0;;:31;;:42;;101044:9;;101012:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100973:82;-1:-1:-1;;;;;;101078:34:0;;101070:68;;;;-1:-1:-1;;;101070:68:0;;;;;;;:::i;:::-;101153:39;;:::i;:::-;101204:14;;:38;;;-1:-1:-1;;;101204:38:0;;;;101195:48;;-1:-1:-1;;;;;101204:14:0;;:36;;:38;;;;;;;;;;;;;;:14;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101195:3;;:8;:48::i;:::-;101153:90;;101258:189;101335:5;101367:20;101407:25;:16;:23;:25::i;:::-;101276:9;-1:-1:-1;;;;;101276:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101258:189;101462:28;;:::i;:::-;101493:26;:3;101502:16;101493:8;:26::i;:::-;101608:8;;101462:57;;-1:-1:-1;101534:100:0;;101593:5;;-1:-1:-1;;;;;101608:8:0;101619:14;101462:57;101619:12;:14::i;:::-;101552:9;-1:-1:-1;;;;;101552:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101534:100;101649:8;;:45;;-1:-1:-1;;;101649:45:0;;-1:-1:-1;;;;;101649:8:0;;;;:27;;:45;;101677:9;;101688:5;;101649:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101716:3;101709:10;;;;;;;;100936:795;101750:14;:12;:14::i;:::-;101743:21;;;100674:1098;;;;;;:::o;14441:165::-;14508:4;14535:1;14529;:3;;;:7;14525:51;;;-1:-1:-1;14560:4:0;14553:11;;14525:51;-1:-1:-1;14593:5:0;14441:165;;;:::o;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;47134:604::-;47576:4;47687:17;47723:7;47134:604;:::o;49848:129::-;46678:13;;;;;;;;:33;;;46695:16;:14;:16::i;:::-;46678:50;;;-1:-1:-1;46716:12:0;;;;46715:13;46678:50;46670:109;;;;-1:-1:-1;;;46670:109:0;;;;;;;:::i;:::-;46792:19;46815:13;;;;;;46814:14;46839:101;;;;46874:13;:20;;-1:-1:-1;;;;46874:20:0;;;;;46909:19;46890:4;46909:19;;;46839:101;49906:26:::1;:24;:26::i;:::-;49943;:24;:26::i;:::-;46970:14:::0;46966:68;;;47017:5;47001:21;;-1:-1:-1;;47001:21:0;;;49848:129;:::o;9991:568::-;10047:6;10291;10287:47;;-1:-1:-1;10321:1:0;10314:8;;10287:47;10356:1;-1:-1:-1;;10356:7:0;:27;;;;;-1:-1:-1;;;10367:1:0;:16;10356:27;10354:30;10346:82;;;;-1:-1:-1;;;10346:82:0;;;;;;;:::i;:::-;10452:5;;;10456:1;10452;:5;:1;10476:5;;;;;:10;10468:62;;;;-1:-1:-1;;;10468:62:0;;;;;;;:::i;20284:102::-;20366:12;20284:102;:::o;6844:108::-;6903:7;6930:14;6935:1;6938;6941:2;6930:4;:14::i;11555:218::-;11611:6;11641:5;;;11666:6;;;;;;:16;;;11681:1;11676;:6;;11666:16;11665:38;;;;11692:1;11688;:5;:14;;;;;11701:1;11697;:5;11688:14;11657:87;;;;-1:-1:-1;;;11657:87:0;;;;;;;:::i;13140:105::-;13197:6;13223:14;13228:1;13231;13234:2;13223:4;:14::i;12018:215::-;12074:6;12104:5;;;12129:6;;;;;;:16;;;12144:1;12139;:6;;12129:16;12128:38;;;;12155:1;12151;:5;:14;;;;;12164:1;12160;:5;12151:14;12120:84;;;;-1:-1:-1;;;12120:84:0;;;;;;;:::i;6369:108::-;6428:7;6455:14;6460:1;6463;6466:2;6455:4;:14::i;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46:0;;;;;;;:::i;5779:109::-;5863:17;;5859:2;:21;;5779:109::o;15885:197::-;15970:20;;:::i;:::-;16003:22;;:::i;:::-;16051:3;;16042;;:13;;:8;:13::i;100024:642::-;100215:34;;:::i;:::-;100262:17;;100283:5;:17;;;;;;;;;100282:78;;100331:29;100282:78;;;100304:24;100282:78;100262:98;;100371:47;;:::i;:::-;100459:56;;-1:-1:-1;;;100459:56:0;;100434:82;;-1:-1:-1;;;;;100459:19:0;;;;;:56;;100479:3;;100484:12;;100498:16;;100459:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;100434:82::-;100371:145;;100564:3;100531:36;;;;;;;;:29;:36;100527:102;;;100591:26;:12;-1:-1:-1;;100591:22:0;:26::i;:::-;100584:33;;;;;;100527:102;100646:12;-1:-1:-1;;100024:642:0;;;;;;;:::o;18196:304::-;18348:34;;:::i;:::-;18327:1;16882;:3;;;-1:-1:-1;;;;;16867:18:0;;16887:21;;;;;;;;;;;;;;;;;16859:50;;;;;-1:-1:-1;;;16859:50:0;;;;;;;;:::i;:::-;;18400:36:::1;;:::i;:::-;18451:22;18458:14;18470:1;18458:11;:14::i;:::-;18451:1:::0;;:6:::1;:22::i;15162:196::-:0;15247:20;;:::i;:::-;15280:22;;:::i;:::-;15327:3;;15319;;:12;;:7;:12::i;95342:2789::-;95604:32;;:::i;:::-;95793:37;;:::i;:::-;95833:66;95855:9;95866:10;95878:14;:12;:14::i;95833:66::-;95793:106;;95999:34;:17;:25;;;:32;:34::i;:::-;:39;95991:81;;;;-1:-1:-1;;;95991:81:0;;;;;;;:::i;:::-;96141:35;;:::i;:::-;96231:43;;;;96192:83;;:33;:17;96215:9;96192:22;:33::i;:::-;:38;;:83::i;:::-;96141:134;-1:-1:-1;96462:37:0;:28;96141:134;96480:9;96462:17;:28::i;:37::-;96458:1636;;96536:17;96521:32;;96458:1636;;;96586:50;;:::i;:::-;96688:48;:17;:39;;;:46;:48::i;:::-;96655:30;:21;:28;:30::i;:::-;:81;96651:225;;;96787:73;96814:45;:17;:39;;;:43;:45::i;:::-;96787:21;;:26;:73::i;:::-;96757:103;;96651:225;96892:40;;:::i;:::-;96952:96;96977:9;96988:5;96995:12;97009:27;97038:9;96952:24;:96::i;:::-;96892:156;;97078:1004;;;;;;;;97120:20;:29;;;97078:1004;;;;97195:136;97266:20;:46;;;97195:17;:43;;;:48;;:136;;;;:::i;:::-;97078:1004;;;;97359:60;97390:20;:28;;;97359:17;:25;;;:30;;:60;;;;:::i;:::-;97078:1004;;;;97673:128;97740:20;:42;;;97673:17;:39;;;:44;;:128;;;;:::i;:::-;97078:1004;;;;97454:74;97492:20;:35;;;97454:17;:32;;;:37;;:74;;;;:::i;:::-;97078:1004;;;;97561:70;97597:20;:33;;;97561:17;:30;;;:35;;:70;;;;:::i;:::-;97078:1004;;;;97833:68;97868:20;:32;;;97833:17;:29;;;:34;;:68;;;;:::i;:::-;97078:1004;;;;97994:72;98031:20;:34;;;97994:17;:31;;;:36;;:72;;;;:::i;:::-;97078:1004;;;;97940:20;:18;:20::i;:::-;97078:1004;;97063:1019;-1:-1:-1;;;96458:1636:0;98104:19;;95342:2789;;;;;;;:::o;44388:772::-;44823:23;44849:69;44877:4;44849:69;;;;;;;;;;;;;;;;;44857:5;-1:-1:-1;;;;;44849:27:0;;;:69;;;;;:::i;:::-;44933:17;;44823:95;;-1:-1:-1;44933:21:0;44929:224;;45075:10;45064:30;;;;;;;;;;;;:::i;:::-;45056:85;;;;-1:-1:-1;;;45056:85:0;;;;;;;:::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;48497:65::-;46678:13;;;;;;;;:33;;;46695:16;:14;:16::i;:::-;46678:50;;;-1:-1:-1;46716:12:0;;;;46715:13;46678:50;46670:109;;;;-1:-1:-1;;;46670:109:0;;;;;;;:::i;:::-;46792:19;46815:13;;;;;;46814:14;46839:101;;;;46874:13;:20;;-1:-1:-1;;;;46874:20:0;;;;;46909:19;46890:4;46909:19;;;46970:14;46966:68;;;47017:5;47001:21;;-1:-1:-1;;47001:21:0;;;48497:65;:::o;49985:196::-;46678:13;;;;;;;;:33;;;46695:16;:14;:16::i;:::-;46678:50;;;-1:-1:-1;46716:12:0;;;;46715:13;46678:50;46670:109;;;;-1:-1:-1;;;46670:109:0;;;;;;;:::i;:::-;46792:19;46815:13;;;;;;46814:14;46839:101;;;;46874:13;:20;;-1:-1:-1;;;;46874:20:0;;;;;46909:19;46890:4;46909:19;;;46839:101;50053:17:::1;50073:12;:10;:12::i;:::-;50096:6;:18:::0;;-1:-1:-1;;;;;;50096:18:0::1;-1:-1:-1::0;;;;;50096:18:0;::::1;::::0;;::::1;::::0;;;50130:43:::1;::::0;50096:18;;-1:-1:-1;50096:18:0;-1:-1:-1;;50130:43:0::1;::::0;-1:-1:-1;;50130:43:0::1;46952:1;46970:14:::0;46966:68;;;47017:5;47001:21;;-1:-1:-1;;47001:21:0;;;49985:196;:::o;7054:172::-;7163:7;7190:28;7216:1;7190:21;7196:14;7201:8;7196:4;:14::i;:::-;7190:1;;:5;:21::i;:::-;:25;;:28::i;13346:169::-;13453:6;13479:28;13492:14;13497:8;13492:4;:14::i;:::-;13479:8;:1;13485;13479:5;:8::i;:::-;:12;;:28::i;6578:172::-;6687:7;6714:28;6727:14;6732:8;6727:4;:14::i;:::-;6714:8;:1;6720;6714:5;:8::i;13609:105::-;13666:6;13692:14;13697:1;13700;13703:2;13692:4;:14::i;38004:195::-;38107:12;38139:52;38161:6;38169:4;38175:1;38178:12;38139:21;:52::i;2352:471::-;2410:7;2655:6;2651:47;;-1:-1:-1;2685:1:0;2678:8;;2651:47;2722:5;;;2726:1;2722;:5;:1;2746:5;;;;;:10;2738:56;;;;-1:-1:-1;;;2738:56:0;;;;;;;:::i;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;11033:271::-;11089:6;11116;11108:51;;;;-1:-1:-1;;;11108:51:0;;;;;;;:::i;:::-;11180:1;-1:-1:-1;;11180:7:0;:27;;;;;-1:-1:-1;;;11191:1:0;:16;11180:27;11178:30;11170:76;;;;-1:-1:-1;;;11170:76:0;;;;;;;:::i;:::-;11259:8;11274:1;11270;:5;;;;;;;11033:271;-1:-1:-1;;;;11033:271:0:o;13816:169::-;13923:6;13949:28;13975:1;13949:21;13955:14;13960:8;13955:4;:14::i;:::-;13949:1;;:5;:21::i;39056:530::-;39183:12;39241:5;39216:21;:30;;39208:81;;;;-1:-1:-1;;;39208:81:0;;;;;;;:::i;:::-;39308:18;39319:6;39308:10;:18::i;:::-;39300:60;;;;-1:-1:-1;;;39300:60:0;;;;;;;:::i;:::-;39434:12;39448:23;39475:6;-1:-1:-1;;;;;39475:11:0;39495:5;39503:4;39475:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39433:75;;;;39526:52;39544:7;39553:10;39565:12;39526:17;:52::i;:::-;39519:59;39056:530;-1:-1:-1;;;;;;;39056:530:0: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;35086:422::-;35453:20;35492:8;;;35086:422::o;40592:742::-;40707:12;40736:7;40732:595;;;-1:-1:-1;40767:10:0;40760:17;;40732:595;40881:17;;:21;40877:439;;41144:10;41138:17;41205:15;41192:10;41188:2;41184:19;41177:44;41092:148;41287:12;41280:20;;-1:-1:-1;;;41280:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;4326:157::-;;4436:2;4427:6;4422:3;4418:16;4414:25;4411:2;;;-1:-1;;4442:12;4874:341;;4998:4;4986:9;4981:3;4977:19;4973:30;4970:2;;;-1:-1;;5006:12;4970:2;5034:20;4998:4;5034:20;:::i;:::-;5831:13;;5108:86;;-1:-1;5025:29;4964:251;-1:-1;4964:251::o;5894:241::-;;5998:2;5986:9;5977:7;5973:23;5969:32;5966:2;;;-1:-1;;6004:12;5966:2;85:6;72:20;97:33;124:5;97:33;:::i;6142:263::-;;6257:2;6245:9;6236:7;6232:23;6228:32;6225:2;;;-1:-1;;6263:12;6225:2;226:6;220:13;238:33;265:5;238:33;:::i;6412:491::-;;;;6550:2;6538:9;6529:7;6525:23;6521:32;6518:2;;;-1:-1;;6556:12;6518:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6608:63;-1:-1;6708:2;6747:22;;72:20;97:33;72:20;97:33;:::i;:::-;6716:63;-1:-1;6816:2;6855:22;;72:20;97:33;72:20;97:33;:::i;:::-;6824:63;;;;6512:391;;;;;:::o;6910:235::-;;7011:2;6999:9;6990:7;6986:23;6982:32;6979:2;;;-1:-1;;7017:12;6979:2;360:6;347:20;372:30;396:5;372:30;:::i;7152:257::-;;7264:2;7252:9;7243:7;7239:23;7235:32;7232:2;;;-1:-1;;7270:12;7232:2;495:6;489:13;507:30;531:5;507:30;:::i;8022:402::-;;;8161:2;8149:9;8140:7;8136:23;8132:32;8129:2;;;-1:-1;;8167:12;8129:2;840:6;827:20;852:51;897:5;852:51;:::i;:::-;8219:81;-1:-1;8337:2;8376:22;;72:20;97:33;72:20;97:33;:::i;:::-;8345:63;;;;8123:301;;;;;:::o;8431:563::-;;;;8605:2;8593:9;8584:7;8580:23;8576:32;8573:2;;;-1:-1;;8611:12;8573:2;840:6;827:20;852:51;897:5;852:51;:::i;:::-;8663:81;-1:-1;8781:2;8820:22;;72:20;97:33;72:20;97:33;:::i;:::-;8789:63;-1:-1;8889:2;8946:22;;1372:20;1397:51;1372:20;1397:51;:::i;9001:953::-;;;;;;9278:3;9266:9;9257:7;9253:23;9249:33;9246:2;;;-1:-1;;9285:12;9246:2;840:6;827:20;852:51;897:5;852:51;:::i;:::-;9337:81;-1:-1;9455:2;9503:22;;1372:20;1397:51;1372:20;1397:51;:::i;:::-;9463:72;-1:-1;9590:79;9661:7;9572:2;9637:22;;9590:79;:::i;:::-;9580:89;;9724:79;9795:7;9706:2;9775:9;9771:22;9724:79;:::i;:::-;9714:89;;9859:79;9930:7;9840:3;9910:9;9906:22;9859:79;:::i;:::-;9849:89;;9240:714;;;;;;;;:::o;9961:454::-;;;10126:2;10114:9;10105:7;10101:23;10097:32;10094:2;;;-1:-1;;10132:12;10094:2;840:6;827:20;852:51;897:5;852:51;:::i;:::-;10184:81;-1:-1;10320:79;10391:7;10302:2;10367:22;;10320:79;:::i;:::-;10310:89;;10088:327;;;;;:::o;11034:316::-;;11175:3;11163:9;11154:7;11150:23;11146:33;11143:2;;;-1:-1;;11182:12;11143:2;1943:20;11175:3;1943:20;:::i;:::-;2045:90;2131:3;2107:22;2045:90;:::i;:::-;2027:16;2020:116;2232:84;2312:3;2199:2;2292:9;2288:22;2232:84;:::i;:::-;2199:2;2218:5;2214:16;2207:110;2419:84;2499:3;2386:2;2479:9;2475:22;2419:84;:::i;:::-;2386:2;2405:5;2401:16;2394:110;2630:90;2716:3;2597:2;2696:9;2692:22;2630:90;:::i;:::-;2597:2;2616:5;2612:16;2605:116;2849:84;2929:3;2815;2909:9;2905:22;2849:84;:::i;:::-;2815:3;2835:5;2831:16;2824:110;3012:3;3082:9;3078:22;5831:13;3012:3;3032:5;3028:16;3021:86;3175:3;3245:9;3241:22;5831:13;3175:3;3195:5;3191:16;3184:86;11234:100;;;;11137:213;;;;:::o;11357:332::-;;11506:3;11494:9;11485:7;11481:23;11477:33;11474:2;;;-1:-1;;11513:12;11474:2;3508:20;11506:3;3508:20;:::i;:::-;3618:84;3698:3;3674:22;3618:84;:::i;:::-;3600:16;3593:110;3800:84;3880:3;3767:2;3860:9;3856:22;3800:84;:::i;:::-;3767:2;3786:5;3782:16;3775:110;3989:90;4075:3;3956:2;4055:9;4051:22;3989:90;:::i;:::-;3956:2;3975:5;3971:16;3964:116;4182:84;4262:3;4149:2;4242:9;4238:22;4182:84;:::i;:::-;4149:2;4164:16;;4157:110;4168:5;11468:221;-1:-1;;;11468:221::o;11696:289::-;;11824:2;11812:9;11803:7;11799:23;11795:32;11792:2;;;-1:-1;;11830:12;11792:2;4668:20;11824:2;4668:20;:::i;:::-;5683;;4742:75;;-1:-1;4749:16;11786:199;-1:-1;11786:199::o;11992:311::-;;12131:2;12119:9;12110:7;12106:23;12102:32;12099:2;;;-1:-1;;12137:12;12099:2;12199:88;12279:7;12255:22;12199:88;:::i;12310:507::-;;;12496:2;12484:9;12475:7;12471:23;12467:32;12464:2;;;-1:-1;;12502:12;12464:2;12564:88;12644:7;12620:22;12564:88;:::i;:::-;12554:98;;12707:94;12793:7;12689:2;12773:9;12769:22;12707:94;:::i;13154:263::-;;13269:2;13257:9;13248:7;13244:23;13240:32;13237:2;;;-1:-1;;13275:12;13237:2;-1:-1;5831:13;;13231:186;-1:-1;13231:186::o;25800:1611::-;26017:16;26011:23;28451;15378:3;15371:36;26244:4;26237:5;26233:16;26227:23;27667;26244:4;26356:3;26352:14;15371:36;26454:4;26447:5;26443:16;26437:23;27667;26454:4;26566:3;26562:14;15371:36;26688:4;26681:5;26677:16;26671:23;28451;26688:4;26812:3;26808:14;15371:36;26935:4;26928:5;26924:16;26918:23;27667;26935:4;27047:3;27043:14;15371:36;27154:4;27147:5;27143:16;27137:23;27154:4;27218:3;27214:14;15371:36;27315:4;27308:5;27304:16;27298:23;27315:4;27379:3;27375:14;15371:36;25918:1493;;:::o;29212:271::-;;13964:5;58009:12;14075:52;14120:6;14115:3;14108:4;14101:5;14097:16;14075:52;:::i;:::-;14139:16;;;;;29346:137;-1:-1;;29346:137::o;29490:222::-;-1:-1;;;;;59726:54;;;;13644:37;;29617:2;29602:18;;29588:124::o;29719:458::-;-1:-1;;;;;59726:54;;;13644:37;;59726:54;;30073:2;30058:18;;13644:37;29909:2;29894:18;;59253:41;59288:5;59253:41;:::i;:::-;61577:33;30163:2;30152:9;30148:18;15243:57;29880:297;;;;;;:::o;30184:444::-;-1:-1;;;;;59726:54;;;13644:37;;59726:54;;;;30531:2;30516:18;;13644:37;30614:2;30599:18;;15371:36;;;;30367:2;30352:18;;30338:290::o;30635:333::-;-1:-1;;;;;59726:54;;;;13644:37;;30954:2;30939:18;;15371:36;30790:2;30775:18;;30761:207::o;30975:210::-;58668:13;;58661:21;13758:34;;31096:2;31081:18;;31067:118::o;31987:576::-;-1:-1;;;;;59726:54;;;14256:68;;59726:54;;;;32418:2;32403:18;;13644:37;27667:23;;32549:2;32534:18;;15371:36;32236:2;32221:18;;32207:356::o;32570:618::-;-1:-1;;;;;59726:54;;14256:68;;32839:3;32824:19;;32954:124;33074:2;33059:18;;33050:6;32954:124;:::i;:::-;59253:41;59288:5;59253:41;:::i;:::-;61437:42;33173:3;33162:9;33158:19;15087:66;32810:378;;;;;;:::o;33195:706::-;-1:-1;;;;;59726:54;;14256:68;;33508:3;33493:19;;33623:124;33743:2;33728:18;;33719:6;33623:124;:::i;:::-;28457:16;28451:23;33886:3;33875:9;33871:19;15371:36;33479:422;;;;;;:::o;33908:586::-;-1:-1;;;;;59726:54;;14256:68;;34161:3;34146:19;;34276:124;34396:2;34381:18;;34372:6;34276:124;:::i;34501:465::-;-1:-1;;;;;59726:54;;;;14256:68;;27667:23;34952:2;34937:18;;15371:36;34722:2;34707:18;;34693:273::o;35746:648::-;36031:2;36016:18;;59253:41;59288:5;59253:41;:::i;:::-;14932:56;;;27667:23;;36249:2;36234:18;;15371:36;27667:23;36380:2;36365:18;;;15371:36;36002:392;:::o;36401:748::-;36708:3;36693:19;;59253:41;59288:5;59253:41;:::i;:::-;14932:56;;;27667:23;;36927:2;36912:18;;15371:36;27667:23;;37058:2;37043:18;;15371:36;58668:13;58661:21;37135:2;37120:18;;;13758:34;36679:470;:::o;37156:436::-;15371:36;;;37495:2;37480:18;;15371:36;;;;37578:2;37563:18;;15371:36;37335:2;37320:18;;37306:286::o;38523:1504::-;15614:57;;;39157:2;39142:18;;15371:36;;;;39238:2;39223:18;;15371:36;;;;39329:2;39314:18;;15614:57;;;;39419:3;39404:19;;15614:57;;;;39501:3;39486:19;;15371:36;;;;39592:3;39577:19;;15614:57;39676:3;39661:19;;15371:36;39760:3;39745:19;;15371:36;39844:3;39829:19;;15371:36;39927:3;39912:19;;15371:36;40012:3;39997:19;;15371:36;38984:3;38969:19;;38955:1072::o;41527:310::-;;41674:2;41695:17;41688:47;15977:5;58009:12;58448:6;41674:2;41663:9;41659:18;58436:19;16071:52;16116:6;58476:14;41663:9;58476:14;41674:2;16097:5;16093:16;16071:52;:::i;:::-;62470:7;62454:14;-1:-1;;62450:28;16135:39;;;;58476:14;16135:39;;41645:192;-1:-1;;41645:192::o;41844:416::-;42044:2;42058:47;;;16411:2;42029:18;;;58436:19;-1:-1;;;58476:14;;;16427:44;16490:12;;;42015:245::o;42267:416::-;42467:2;42481:47;;;16741:2;42452:18;;;58436:19;-1:-1;;;58476:14;;;16757:40;16816:12;;;42438:245::o;42690:416::-;42890:2;42904:47;;;17067:2;42875:18;;;58436:19;-1:-1;;;58476:14;;;17083:41;17143:12;;;42861:245::o;43113:416::-;43313:2;43327:47;;;17394:2;43298:18;;;58436:19;-1:-1;;;58476:14;;;17410:43;17472:12;;;43284:245::o;43536:416::-;43736:2;43750:47;;;17723:2;43721:18;;;58436:19;17759:34;58476:14;;;17739:55;-1:-1;;;17814:12;;;17807:30;17856:12;;;43707:245::o;43959:416::-;44159:2;44173:47;;;18107:2;44144:18;;;58436:19;18143:29;58476:14;;;18123:50;18192:12;;;44130:245::o;44382:416::-;44582:2;44596:47;;;18443:2;44567:18;;;58436:19;18479:34;58476:14;;;18459:55;-1:-1;;;18534:12;;;18527:25;18571:12;;;44553:245::o;44805:416::-;45005:2;45019:47;;;18822:2;44990:18;;;58436:19;18858:34;58476:14;;;18838:55;-1:-1;;;18913:12;;;18906:30;18955:12;;;44976:245::o;45228:416::-;45428:2;45442:47;;;19206:2;45413:18;;;58436:19;19242:25;58476:14;;;19222:46;19287:12;;;45399:245::o;45651:416::-;45851:2;45865:47;;;19538:2;45836:18;;;58436:19;19574:32;58476:14;;;19554:53;19626:12;;;45822:245::o;46074:416::-;46274:2;46288:47;;;19877:2;46259:18;;;58436:19;-1:-1;;;58476:14;;;19893:39;19951:12;;;46245:245::o;46497:416::-;46697:2;46711:47;;;20202:2;46682:18;;;58436:19;20238:28;58476:14;;;20218:49;20286:12;;;46668:245::o;46920:416::-;47120:2;47134:47;;;20537:2;47105:18;;;58436:19;20573:34;58476:14;;;20553:55;-1:-1;;;20628:12;;;20621:38;20678:12;;;47091:245::o;47343:416::-;47543:2;47557:47;;;20929:2;47528:18;;;58436:19;20965:34;58476:14;;;20945:55;-1:-1;;;21020:12;;;21013:25;21057:12;;;47514:245::o;47766:416::-;47966:2;47980:47;;;21308:2;47951:18;;;58436:19;21344:34;58476:14;;;21324:55;-1:-1;;;21399:12;;;21392:25;21436:12;;;47937:245::o;48189:416::-;48389:2;48403:47;;;21687:2;48374:18;;;58436:19;-1:-1;;;58476:14;;;21703:33;21755:12;;;48360:245::o;48612:416::-;48812:2;48826:47;;;48797:18;;;58436:19;22042:34;58476:14;;;22022:55;22096:12;;;48783:245::o;49035:416::-;49235:2;49249:47;;;22347:2;49220:18;;;58436:19;22383:34;58476:14;;;22363:55;-1:-1;;;22438:12;;;22431:31;22481:12;;;49206:245::o;49458:416::-;49658:2;49672:47;;;22732:2;49643:18;;;58436:19;22768:31;58476:14;;;22748:52;22819:12;;;49629:245::o;49881:416::-;50081:2;50095:47;;;23070:2;50066:18;;;58436:19;23106:34;58476:14;;;23086:55;-1:-1;;;23161:12;;;23154:34;23207:12;;;50052:245::o;50304:416::-;50504:2;50518:47;;;23458:2;50489:18;;;58436:19;23494:31;58476:14;;;23474:52;23545:12;;;50475:245::o;50727:416::-;50927:2;50941:47;;;23796:2;50912:18;;;58436:19;23832:31;58476:14;;;23812:52;23883:12;;;50898:245::o;51150:416::-;51350:2;51364:47;;;24134:2;51335:18;;;58436:19;24170:34;58476:14;;;24150:55;-1:-1;;;24225:12;;;24218:28;24265:12;;;51321:245::o;51573:416::-;51773:2;51787:47;;;24516:2;51758:18;;;58436:19;24552:34;58476:14;;;24532:55;-1:-1;;;24607:12;;;24600:34;24653:12;;;51744:245::o;51996:416::-;52196:2;52210:47;;;52181:18;;;58436:19;24940:34;58476:14;;;24920:55;24994:12;;;52167:245::o;52419:416::-;52619:2;52633:47;;;25245:2;52604:18;;;58436:19;25281:33;58476:14;;;25261:54;25334:12;;;52590:245::o;52842:416::-;53042:2;53056:47;;;25585:2;53027:18;;;58436:19;25621:34;58476:14;;;25601:55;-1:-1;;;25676:12;;;25669:35;25723:12;;;53013:245::o;53265:327::-;53444:3;53429:19;;53459:123;53433:9;53555:6;53459:123;:::i;53599:318::-;27667:23;;15371:36;;53774:2;53759:18;;53745:172::o;53924:549::-;27667:23;;15371:36;;28451:23;54459:2;54444:18;;15371:36;54187:2;54172:18;;54158:315::o;54829:222::-;15371:36;;;54956:2;54941:18;;54927:124::o;56968:684::-;15371:36;;;57380:2;57365:18;;15371:36;;;;57463:2;57448:18;;15371:36;;;;-1:-1;;;;;59726:54;57554:2;57539:18;;13503:58;57637:3;57622:19;;15371:36;57215:3;57200:19;;57186:466::o;57659:256::-;57721:2;57715:9;57747:17;;;57822:18;57807:34;;57843:22;;;57804:62;57801:2;;;57879:1;;57869:12;57801:2;57721;57888:22;57699:216;;-1:-1;57699:216::o;62110:268::-;62175:1;62182:101;62196:6;62193:1;62190:13;62182:101;;;62263:11;;;62257:18;62244:11;;;62237:39;62218:2;62211:10;62182:101;;;62298:6;62295:1;62292:13;62289:2;;;-1:-1;;62175:1;62345:16;;62338:27;62159:219::o;62491:99::-;62568:1;62561:5;62558:12;62548:2;;62574:9;62820:117;-1:-1;;;;;59726:54;;62879:35;;62869:2;;62928:1;;62918:12;62944:111;63025:5;58668:13;58661:21;63003:5;63000:32;62990:2;;63046:1;;63036:12;63740:112;63827:1;63820:5;63817:12;63807:2;;63843:1;;63833:12

Swarm Source

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