Contract 0x9b35eb8567a8b43bec640cc4f507642f195c3846

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xc5ae8a2f4f279a89e09060464193d249f38f563d15e318262fc35dc3299350220x6080604087369052021-05-11 2:50:06138 days 3 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.02192006
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xb36fa260f2894a83bb88379d72ce1968a3ba903cbeece1e223ed9a9ebb31cda1105236212021-07-12 9:22:0775 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0xc6cd851133272278f4b248f225a89603c41f27f762155353365d71f8c566ce5a105235742021-07-12 9:19:4675 days 20 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
0x320d70178a0bd532a9f8459c49c88c14f50dcbd615d2ab369e7f6269f291989f105234202021-07-12 9:12:0475 days 21 hrs ago 0x5c09902dd82fbd091e6154a9ec3577fa76d604a2 0x9b35eb8567a8b43bec640cc4f507642f195c38460 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SakePerpState

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

// File: @openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMathUpgradeable {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

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


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


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

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

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

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

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

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

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

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




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

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

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

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




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

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

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

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

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

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

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

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

// File: contracts/utils/DecimalMath.sol



/// @dev Implements simple fixed point math add, sub, mul and div operations.
/// @author Alberto Cuesta Cañada
library DecimalMath {
    using SafeMathUpgradeable for uint256;

    /// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
    function unit(uint8 decimals) internal pure returns (uint256) {
        return 10**uint256(decimals);
    }

    /// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
    function addd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.add(y);
    }

    /// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
    function subd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.sub(y);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
    function muld(uint256 x, uint256 y) internal pure returns (uint256) {
        return muld(x, y, 18);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
    function muld(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(y).div(unit(decimals));
    }

    /// @dev Divides x between y, assuming they are both fixed point with 18 digits.
    function divd(uint256 x, uint256 y) internal pure returns (uint256) {
        return divd(x, y, 18);
    }

    /// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
    function divd(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(unit(decimals)).div(y);
    }
}

// File: contracts/utils/Decimal.sol




library Decimal {
    using DecimalMath for uint256;
    using SafeMathUpgradeable for uint256;

    struct decimal {
        uint256 d;
    }

    function zero() internal pure returns (decimal memory) {
        return decimal(0);
    }

    function one() internal pure returns (decimal memory) {
        return decimal(DecimalMath.unit(18));
    }

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

    function modD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        return decimal(x.d.mul(DecimalMath.unit(18)) % y.d);
    }

    function cmp(decimal memory x, decimal memory y) internal pure returns (int8) {
        if (x.d > y.d) {
            return 1;
        } else if (x.d < y.d) {
            return -1;
        }
        return 0;
    }

    /// @dev add two decimals
    function addD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.add(y.d);
        return t;
    }

    /// @dev subtract two decimals
    function subD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.sub(y.d);
        return t;
    }

    /// @dev multiple two decimals
    function mulD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.muld(y.d);
        return t;
    }

    /// @dev multiple a decimal by a uint256
    function mulScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.mul(y);
        return t;
    }

    /// @dev divide two decimals
    function divD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.divd(y.d);
        return t;
    }

    /// @dev divide a decimal by a uint256
    function divScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.div(y);
        return t;
    }
}

// File: @openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol



/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMathUpgradeable {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

        return c;
    }
}

// File: contracts/utils/SignedDecimalMath.sol



/// @dev Implements simple signed fixed point math add, sub, mul and div operations.
library SignedDecimalMath {
    using SignedSafeMathUpgradeable for int256;

    /// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
    function unit(uint8 decimals) internal pure returns (int256) {
        return int256(10**uint256(decimals));
    }

    /// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
    function addd(int256 x, int256 y) internal pure returns (int256) {
        return x.add(y);
    }

    /// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
    function subd(int256 x, int256 y) internal pure returns (int256) {
        return x.sub(y);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
    function muld(int256 x, int256 y) internal pure returns (int256) {
        return muld(x, y, 18);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
    function muld(
        int256 x,
        int256 y,
        uint8 decimals
    ) internal pure returns (int256) {
        return x.mul(y).div(unit(decimals));
    }

    /// @dev Divides x between y, assuming they are both fixed point with 18 digits.
    function divd(int256 x, int256 y) internal pure returns (int256) {
        return divd(x, y, 18);
    }

    /// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
    function divd(
        int256 x,
        int256 y,
        uint8 decimals
    ) internal pure returns (int256) {
        return x.mul(unit(decimals)).div(y);
    }
}

// File: contracts/utils/SignedDecimal.sol





library SignedDecimal {
    using SignedDecimalMath for int256;
    using SignedSafeMathUpgradeable for int256;

    struct signedDecimal {
        int256 d;
    }

    function zero() internal pure returns (signedDecimal memory) {
        return signedDecimal(0);
    }

    function toInt(signedDecimal memory x) internal pure returns (int256) {
        return x.d;
    }

    function isNegative(signedDecimal memory x) internal pure returns (bool) {
        if (x.d < 0) {
            return true;
        }
        return false;
    }

    function abs(signedDecimal memory x) internal pure returns (Decimal.decimal memory) {
        Decimal.decimal memory t;
        if (x.d < 0) {
            t.d = uint256(0 - x.d);
        } else {
            t.d = uint256(x.d);
        }
        return t;
    }

    /// @dev add two decimals
    function addD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.add(y.d);
        return t;
    }

    /// @dev subtract two decimals
    function subD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.sub(y.d);
        return t;
    }

    /// @dev multiple two decimals
    function mulD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.muld(y.d);
        return t;
    }

    /// @dev multiple a signedDecimal by a int256
    function mulScalar(signedDecimal memory x, int256 y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.mul(y);
        return t;
    }

    /// @dev divide two decimals
    function divD(signedDecimal memory x, signedDecimal memory y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.divd(y.d);
        return t;
    }

    /// @dev divide a signedDecimal by a int256
    function divScalar(signedDecimal memory x, int256 y) internal pure returns (signedDecimal memory) {
        signedDecimal memory t;
        t.d = x.d.div(y);
        return t;
    }
}

// File: contracts/types/ISakePerpTypes.sol

pragma experimental ABIEncoderV2;



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

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

// 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/types/ISakePerpVaultTypes.sol


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

// File: contracts/types/IExchangeTypes.sol




interface IExchangeTypes {
    /**
     * @notice asset direction, used in getInputPrice, getOutputPrice, swapInput and swapOutput
     * @param ADD_TO_AMM add asset to Amm
     * @param REMOVE_FROM_AMM remove asset from Amm
     */
    enum Dir {ADD_TO_AMM, REMOVE_FROM_AMM}

    struct LiquidityChangedSnapshot {
        SignedDecimal.signedDecimal cumulativeNotional;
        // the base/quote reserve of amm right before liquidity changed
        Decimal.decimal quoteAssetReserve;
        Decimal.decimal baseAssetReserve;
        // total position size owned by amm after last snapshot taken
        // `totalPositionSize` = currentBaseAssetReserve - lastLiquidityChangedHistoryItem.baseAssetReserve + prevTotalPositionSize
        SignedDecimal.signedDecimal totalPositionSize;
    }
}

// File: contracts/interface/IExchange.sol







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

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

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

    function shutdown() external;

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

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

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

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

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

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

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

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

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

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

    function getLiquidityHistoryLength() external view returns (uint256);

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

    function open() external view returns (bool);

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

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

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

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

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

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

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

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

    function moveAMMPriceToOracle(uint256 _oraclePrice, bytes32 _priceFeedKey) external;

    function setPriceFeed(address _priceFeed) external;

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

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

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

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

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

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

    function priceFeedKey() external view returns (bytes32);

    function tradeLimitRatio() external view returns (uint256);

    function priceAdjustRatio() external view returns (uint256);

    function fluctuationLimitRatio() external view returns (uint256);

    function fundingPeriod() external view returns (uint256);

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

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

    function getExchangeState() external view returns (address);

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

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

// File: contracts/interface/ISakePerpState.sol




interface ISakePerpState {
    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,
        ISakePerpTypes.Side _side
    ) external returns (bool);

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

    function getWhiteList() external view returns (address);

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

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

    function calcPositionAfterLiquidityMigrationWithoutNew(
        IExchange _exchange,
        ISakePerpTypes.Position memory _position,
        uint256 _latestLiquidityIndex
    ) external returns (SignedDecimal.signedDecimal memory);

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

// File: contracts/interface/ISakePerp.sol






interface ISakePerp is ISakePerpTypes {
    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/utils/BlockContext.sol


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

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

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

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

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













contract SakePerpState is ISakePerpState, OwnableUpgradeable, BlockContext {
    using SafeMathUpgradeable for uint256;
    using Decimal for Decimal.decimal;
    using SignedDecimal for SignedDecimal.signedDecimal;
    using MixedDecimal for SignedDecimal.signedDecimal;

    mapping(address => mapping(address => TradingState)) public tradingState;
    address public SakePerp;
    uint256 public waitingPeriodSecs;

    // key by amm address. will be deprecated or replaced after guarded period.
    // it's not an accurate open interest, just a rough way to control the unexpected loss at the beginning
    mapping(address => Decimal.decimal) public openInterestNotionalMap;
    mapping(uint256 => SignedDecimal.signedDecimal) public snapshotDeltaPosNotional;

    // designed for arbitragers who can hold unlimited positions. will be removed after guarded period
    address internal whitelist;

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

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

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

    modifier onlySakePerp() {
        require(SakePerp == _msgSender(), "caller is not SakePerp");
        _;
    }

    function initialize(address _SakePerp, uint256 _waitingPeriodSecs) public initializer {
        __Ownable_init();

        SakePerp = _SakePerp;
        waitingPeriodSecs = _waitingPeriodSecs;
    }

    /**
     * @notice trader can't do the reverse operation during waiting period
     */
    function checkWaitingPeriod(
        address _exchange,
        address _trader,
        ISakePerpTypes.Side _side
    ) public override onlySakePerp returns (bool) {
        if (_side == ISakePerpTypes.Side.BUY) {
            uint256 lastestShortTime = tradingState[_exchange][_trader].lastestShortTime;
            if (lastestShortTime.add(waitingPeriodSecs) > _blockTimestamp()) {
                return false;
            }
            tradingState[_exchange][_trader].lastestLongTime = _blockTimestamp();
        } else {
            uint256 lastestLongTime = tradingState[_exchange][_trader].lastestLongTime;
            if (lastestLongTime.add(waitingPeriodSecs) > _blockTimestamp()) {
                return false;
            }
            tradingState[_exchange][_trader].lastestShortTime = _blockTimestamp();
        }
        return true;
    }

    /**
     * @notice set max waiting period
     * @dev only owner can call
     * @param _waitingPeriodSecs new max waiting period in seconds
     */
    function setWaitingPeriodSecs(uint256 _waitingPeriodSecs) public onlyOwner {
        waitingPeriodSecs = _waitingPeriodSecs;
    }

    /**
     * @notice add an address in the whitelist. People in the whitelist can hold unlimited positions.
     * @dev only owner can call
     * @param _whitelist an address
     */
    function setWhitelist(address _whitelist) public onlyOwner {
        whitelist = _whitelist;
    }

    function getWhiteList() public view override returns (address) {
        return whitelist;
    }

    /**
     * @dev assume this will be removes soon once the guarded period has ended. caller need to ensure amm exist
     */
    function updateOpenInterestNotional(IExchange _exchange, SignedDecimal.signedDecimal memory _amount)
        public
        override
        onlySakePerp
    {
        // when cap = 0 means no cap
        uint256 cap = _exchange.getOpenInterestNotionalCap().toUint();
        address ammAddr = address(_exchange);
        if (cap > 0) {
            SignedDecimal.signedDecimal memory updatedOpenInterestNotional =
                _amount.addD(openInterestNotionalMap[ammAddr]);
            // the reduced open interest can be larger than total when profit is too high and other position are bankrupt
            if (updatedOpenInterestNotional.toInt() < 0) {
                updatedOpenInterestNotional = SignedDecimal.zero();
            }
            if (_amount.toInt() > 0) {
                // whitelist won't be restrict by open interest cap
                require(updatedOpenInterestNotional.toUint() <= cap || msg.sender == whitelist, "over limit");
            }
            openInterestNotionalMap[ammAddr] = updatedOpenInterestNotional.abs();
        }
    }

    /**
     * @notice get position notional and unrealized Pnl without fee expense and funding payment
     * @param _exchange IExchange address
     * @param _position trader position
     * @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,
        ISakePerpTypes.Position memory _position,
        ISakePerpTypes.PnlCalcOption _pnlCalcOption
    )
        public
        view
        override
        onlySakePerp
        returns (Decimal.decimal memory positionNotional, SignedDecimal.signedDecimal memory unrealizedPnl)
    {
        Decimal.decimal memory positionSizeAbs = _position.size.abs();
        if (positionSizeAbs.toUint() != 0) {
            bool isShortPosition = _position.size.toInt() < 0;
            IExchangeTypes.Dir dir =
                isShortPosition ? IExchangeTypes.Dir.REMOVE_FROM_AMM : IExchangeTypes.Dir.ADD_TO_AMM;
            if (_pnlCalcOption == ISakePerpTypes.PnlCalcOption.TWAP) {
                positionNotional = _exchange.getOutputTwap(dir, positionSizeAbs);
            }  else if (_pnlCalcOption == ISakePerpTypes.PnlCalcOption.SPOT_PRICE) {
                positionNotional = _exchange.getOutputPrice(dir, positionSizeAbs);
            } else {
                Decimal.decimal memory oraclePrice = _exchange.getUnderlyingPrice();
                positionNotional = positionSizeAbs.mulD(oraclePrice);
            }
            // unrealizedPnlForLongPosition = positionNotional - openNotional
            // unrealizedPnlForShortPosition = positionNotionalWhenBorrowed - positionNotionalWhenReturned =
            // openNotional - positionNotional = unrealizedPnlForLongPosition * -1
            unrealizedPnl = isShortPosition
                ? MixedDecimal.fromDecimal(_position.openNotional).subD(positionNotional)
                : MixedDecimal.fromDecimal(positionNotional).subD(_position.openNotional);
        }
    }

    function calcPositionAfterLiquidityMigration(
        IExchange _exchange,
        ISakePerpTypes.Position memory _position,
        uint256 _latestLiquidityIndex
    ) public view override onlySakePerp returns (ISakePerpTypes.Position memory) {
        if (_position.size.toInt() == 0) {
            _position.liquidityHistoryIndex = _latestLiquidityIndex;
            return _position;
        }

        // get the change in exchange notional value
        // notionalDelta = current cumulative notional - cumulative notional of last snapshot
        IExchange.LiquidityChangedSnapshot memory lastSnapshot =
            _exchange.getLiquidityChangedSnapshots(_position.liquidityHistoryIndex);
        SignedDecimal.signedDecimal memory notionalDelta =
            _exchange.getCumulativeNotional().subD(lastSnapshot.cumulativeNotional);

        // update the old curve's reserve
        // by applying notionalDelta to the old curve
        Decimal.decimal memory updatedOldBaseReserve;
        Decimal.decimal memory updatedOldQuoteReserve;
        if (notionalDelta.toInt() != 0) {
            Decimal.decimal memory baseAssetWorth =
                _exchange.getInputPriceWithReserves(
                    notionalDelta.toInt() > 0 ? IExchangeTypes.Dir.ADD_TO_AMM : IExchangeTypes.Dir.REMOVE_FROM_AMM,
                    notionalDelta.abs(),
                    lastSnapshot.quoteAssetReserve,
                    lastSnapshot.baseAssetReserve
                );
            updatedOldQuoteReserve = notionalDelta.addD(lastSnapshot.quoteAssetReserve).abs();
            if (notionalDelta.toInt() > 0) {
                updatedOldBaseReserve = lastSnapshot.baseAssetReserve.subD(baseAssetWorth);
            } else {
                updatedOldBaseReserve = lastSnapshot.baseAssetReserve.addD(baseAssetWorth);
            }
        } else {
            updatedOldQuoteReserve = lastSnapshot.quoteAssetReserve;
            updatedOldBaseReserve = lastSnapshot.baseAssetReserve;
        }

        // calculate the new position size
        _position.size = _exchange.calcBaseAssetAfterLiquidityMigration(
            _position.size,
            updatedOldQuoteReserve,
            updatedOldBaseReserve
        );
        _position.liquidityHistoryIndex = _latestLiquidityIndex;
        return _position;
    }

    function calcPositionAfterLiquidityMigrationWithoutNew(
        IExchange _exchange,
        ISakePerpTypes.Position memory _position,
        uint256 _latestLiquidityIndex
    ) public override onlySakePerp returns (SignedDecimal.signedDecimal memory) {
        IExchange.LiquidityChangedSnapshot memory latestSnapshot =
            _exchange.getLiquidityChangedSnapshots(_latestLiquidityIndex);
        SignedDecimal.signedDecimal memory notionalDelta = snapshotDeltaPosNotional[_position.liquidityHistoryIndex];
        bool isPositiveValue = _position.size.toInt() > 0 ? true : false;
        Decimal.decimal memory posNotional;

        {
            IExchange.LiquidityChangedSnapshot memory lastSnapshot =
                _exchange.getLiquidityChangedSnapshots(_position.liquidityHistoryIndex);
            SignedDecimal.signedDecimal memory totalDelta =
                latestSnapshot.cumulativeNotional.subD(lastSnapshot.cumulativeNotional).addD(notionalDelta);

            // update the old curve's reserve
            // by applying totalDelta to the old curve
            Decimal.decimal memory updatedOldBaseReserve;
            Decimal.decimal memory updatedOldQuoteReserve;
            if (totalDelta.toInt() != 0) {
                Decimal.decimal memory baseAssetWorth =
                    _exchange.getInputPriceWithReserves(
                        totalDelta.toInt() > 0 ? IExchangeTypes.Dir.ADD_TO_AMM : IExchangeTypes.Dir.REMOVE_FROM_AMM,
                        totalDelta.abs(),
                        lastSnapshot.quoteAssetReserve,
                        lastSnapshot.baseAssetReserve
                    );
                updatedOldQuoteReserve = totalDelta.addD(lastSnapshot.quoteAssetReserve).abs();
                if (totalDelta.toInt() > 0) {
                    updatedOldBaseReserve = lastSnapshot.baseAssetReserve.subD(baseAssetWorth);
                } else {
                    updatedOldBaseReserve = lastSnapshot.baseAssetReserve.addD(baseAssetWorth);
                }
            } else {
                updatedOldQuoteReserve = lastSnapshot.quoteAssetReserve;
                updatedOldBaseReserve = lastSnapshot.baseAssetReserve;
            }

            // measure the trader position's notional value on the old curve
            // (by simulating closing the position)
            posNotional = _exchange.getOutputPriceWithReserves(
                isPositiveValue ? IExchangeTypes.Dir.ADD_TO_AMM : IExchangeTypes.Dir.REMOVE_FROM_AMM,
                _position.size.abs(),
                updatedOldQuoteReserve,
                updatedOldBaseReserve
            );

            SignedDecimal.signedDecimal memory _posNotional = MixedDecimal.fromDecimal(posNotional);
            if (isPositiveValue) {
                _posNotional = _posNotional.mulScalar(-1);
            }
            snapshotDeltaPosNotional[_position.liquidityHistoryIndex] = snapshotDeltaPosNotional[
                _position.liquidityHistoryIndex
            ]
                .addD(_posNotional);
        }

        {
            Decimal.decimal memory updatedNewBaseReserve;
            Decimal.decimal memory updatedNewQuoteReserve;
            if (notionalDelta.toInt() != 0) {
                Decimal.decimal memory baseAssetWorth =
                    _exchange.getInputPriceWithReserves(
                        notionalDelta.toInt() > 0 ? IExchangeTypes.Dir.ADD_TO_AMM : IExchangeTypes.Dir.REMOVE_FROM_AMM,
                        notionalDelta.abs(),
                        latestSnapshot.quoteAssetReserve,
                        latestSnapshot.baseAssetReserve
                    );
                updatedNewQuoteReserve = notionalDelta.addD(latestSnapshot.quoteAssetReserve).abs();
                if (notionalDelta.toInt() > 0) {
                    updatedNewBaseReserve = latestSnapshot.baseAssetReserve.subD(baseAssetWorth);
                } else {
                    updatedNewBaseReserve = latestSnapshot.baseAssetReserve.addD(baseAssetWorth);
                }
            } else {
                updatedNewQuoteReserve = latestSnapshot.quoteAssetReserve;
                updatedNewBaseReserve = latestSnapshot.baseAssetReserve;
            }

            // calculate and apply the required size on the new curve
            SignedDecimal.signedDecimal memory newBaseAsset =
                MixedDecimal.fromDecimal(
                    _exchange.getInputPriceWithReserves(
                        isPositiveValue ? IExchangeTypes.Dir.REMOVE_FROM_AMM : IExchangeTypes.Dir.ADD_TO_AMM,
                        posNotional,
                        updatedNewQuoteReserve,
                        updatedNewBaseReserve
                    )
                );

            return newBaseAsset.mulScalar(isPositiveValue ? 1 : int256(-1));
        }
    }

    function calcRemainMarginWithFundingPaymentAndOvernightFee(
        IExchange _exchange,
        ISakePerpTypes.Position memory _oldPosition,
        SignedDecimal.signedDecimal memory _marginDelta
    ) public view override onlySakePerp returns (RemainMarginInfo memory remainMarginInfo) {
        // calculate funding payment
        SignedDecimal.signedDecimal memory latestCumulativePremiumFraction =
            ISakePerp(SakePerp).getLatestCumulativePremiumFraction(_exchange);
        if (_oldPosition.size.toInt() != 0) {
            remainMarginInfo.fundingPayment = latestCumulativePremiumFraction
                .subD(_oldPosition.lastUpdatedCumulativePremiumFraction)
                .mulD(_oldPosition.size);
        }

        // calculate overnight feerate
        // Overnight Fee = openNotional * overnight fee rate
        Decimal.decimal memory latestCumulativeOvernightFeeRate =
            ISakePerp(SakePerp).getLatestCumulativeOvernightFeeRate(_exchange);
        if (_oldPosition.size.toInt() != 0) {
            remainMarginInfo.overnightFee = latestCumulativeOvernightFeeRate
                .subD(_oldPosition.lastUpdatedCumulativeOvernightFeeRate)
                .mulD(_oldPosition.openNotional);
        }

        // calculate remain margin
        SignedDecimal.signedDecimal memory signedRemainMargin =
            _marginDelta.subD(remainMarginInfo.fundingPayment).subD(remainMarginInfo.overnightFee).addD(
                _oldPosition.margin
            );

        // if remain margin is negative, set to zero and leave the rest to bad debt
        if (signedRemainMargin.toInt() < 0) {
            remainMarginInfo.badDebt = signedRemainMargin.abs();
        } else {
            remainMarginInfo.remainMargin = signedRemainMargin.abs();
        }
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"SakePerp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"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 ISakePerpTypes.Position","name":"_position","type":"tuple"},{"internalType":"uint256","name":"_latestLiquidityIndex","type":"uint256"}],"name":"calcPositionAfterLiquidityMigration","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 ISakePerpTypes.Position","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"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 ISakePerpTypes.Position","name":"_position","type":"tuple"},{"internalType":"uint256","name":"_latestLiquidityIndex","type":"uint256"}],"name":"calcPositionAfterLiquidityMigrationWithoutNew","outputs":[{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"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 ISakePerpTypes.Position","name":"_oldPosition","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"_marginDelta","type":"tuple"}],"name":"calcRemainMarginWithFundingPaymentAndOvernightFee","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"remainMargin","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"badDebt","type":"tuple"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"fundingPayment","type":"tuple"},{"components":[{"internalType":"uint256","name":"d","type":"uint256"}],"internalType":"struct Decimal.decimal","name":"overnightFee","type":"tuple"}],"internalType":"struct ISakePerpState.RemainMarginInfo","name":"remainMarginInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exchange","type":"address"},{"internalType":"address","name":"_trader","type":"address"},{"internalType":"enum ISakePerpTypes.Side","name":"_side","type":"uint8"}],"name":"checkWaitingPeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"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 ISakePerpTypes.Position","name":"_position","type":"tuple"},{"internalType":"enum ISakePerpTypes.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":[],"name":"getWhiteList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_SakePerp","type":"address"},{"internalType":"uint256","name":"_waitingPeriodSecs","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"openInterestNotionalMap","outputs":[{"internalType":"uint256","name":"d","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_waitingPeriodSecs","type":"uint256"}],"name":"setWaitingPeriodSecs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_whitelist","type":"address"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"snapshotDeltaPosNotional","outputs":[{"internalType":"int256","name":"d","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tradingState","outputs":[{"internalType":"uint256","name":"lastestLongTime","type":"uint256"},{"internalType":"uint256","name":"lastestShortTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExchange","name":"_exchange","type":"address"},{"components":[{"internalType":"int256","name":"d","type":"int256"}],"internalType":"struct SignedDecimal.signedDecimal","name":"_amount","type":"tuple"}],"name":"updateOpenInterestNotional","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"waitingPeriodSecs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506126af806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80637a7e5223116100a25780638da5cb5b116100715780638da5cb5b1461025b578063b0ac5f2f14610263578063cc0ace0a14610276578063cd6dc68714610289578063f2fde38b1461029c57610116565b80637a7e5223146101f2578063854cff2f1461021357806389257117146102265780638b4a5bf31461023b57610116565b806359b8c599116100e957806359b8c5991461018e57806361d92829146101af578063635a3872146101cf5780636886925e146101e2578063715018a6146101ea57610116565b806302a3789e1461011b57806309a9d76c146101305780632f1d1bb21461014e578063542cdc1b1461016e575b600080fd5b61012e6101293660046120db565b6102af565b005b610138610445565b60405161014591906121a7565b60405180910390f35b61016161015c36600461209b565b610454565b60405161014591906125d0565b61018161017c366004611f98565b610a70565b60405161014591906121bb565b6101a161019c366004611f60565b610bc7565b6040516101459291906125f1565b6101c26101bd36600461209b565b610beb565b604051610145919061253e565b61012e6101dd36600461218f565b610f29565b610138610f63565b61012e610f72565b610205610200366004612010565b610ff1565b6040516101459291906125c0565b61012e610221366004611f44565b611223565b61022e61127a565b604051610145919061220b565b61024e610249366004612053565b611280565b6040516101459190612591565b6101386114b4565b61022e610271366004611f44565b6114c3565b61022e61028436600461218f565b6114d5565b61012e610297366004611fe5565b6114e7565b61012e6102aa366004611f44565b611594565b6102b761164b565b6098546001600160a01b039081169116146102ed5760405162461bcd60e51b81526004016102e490612349565b60405180910390fd5b6000610368836001600160a01b031663525454106040518163ffffffff1660e01b815260040160206040518083038186803b15801561032b57600080fd5b505afa15801561033f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103639190612174565b61164f565b905082811561043f57610379611dc2565b6001600160a01b0382166000908152609a60209081526040918290208251918201909252905481526103ac908590611657565b905060006103b98261164f565b12156103ca576103c76116c6565b90505b60006103d58561164f565b131561041857826103e5826116e1565b1115806103fc5750609c546001600160a01b031633145b6104185760405162461bcd60e51b81526004016102e490612267565b610421816116f3565b6001600160a01b0383166000908152609a6020526040902090519055505b50505050565b609c546001600160a01b031690565b61045c611dc2565b61046461164b565b6098546001600160a01b039081169116146104915760405162461bcd60e51b81526004016102e490612349565b610499611dd5565b6040516311bf8bf760e11b81526001600160a01b0386169063237f17ee906104c590869060040161220b565b60806040518083038186803b1580156104dd57600080fd5b505afa1580156104f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105159190612110565b905061051f611dc2565b5060a08401516000908152609b602090815260408083208151928301909152548152855190919081906105519061164f565b1361055d576000610560565b60015b905061056a611dc2565b610572611dd5565b60a08801516040516311bf8bf760e11b81526001600160a01b038b169163237f17ee916105a2919060040161220b565b60806040518083038186803b1580156105ba57600080fd5b505afa1580156105ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f29190612110565b90506105fc611dc2565b8151865161061591879161060f91611724565b9061174a565b905061061f611dc2565b610627611dc2565b6106308361164f565b1561074a5761063d611dc2565b8c6001600160a01b03166350799c8160006106578761164f565b13610663576001610666565b60005b61066f876116f3565b886020015189604001516040518563ffffffff1660e01b815260040161069894939291906121e2565b60206040518083038186803b1580156106b057600080fd5b505afa1580156106c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e89190612174565b905061070961070486602001518661165790919063ffffffff16565b6116f3565b915060006107168561164f565b131561073257604085015161072b9082611767565b9250610744565b60408501516107419082611784565b92505b50610758565b505060208201516040830151905b8b6001600160a01b0316639bf5d1d487610773576001610776565b60005b8d51610781906116f3565b84866040518563ffffffff1660e01b81526004016107a294939291906121e2565b60206040518083038186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f29190612174565b94506107fc611dc2565b610805866117a1565b9050861561081c5761081981600019611805565b90505b60a08c01516000908152609b6020908152604091829020825191820190925290548152610849908261174a565b60a08d01516000908152609b60205260409020905190555061086f9350611dc292505050565b610877611dc2565b6108808561164f565b156109955761088d611dc2565b8a6001600160a01b03166350799c8160006108a78961164f565b136108b35760016108b6565b60005b6108bf896116f3565b8a602001518b604001516040518563ffffffff1660e01b81526004016108e894939291906121e2565b60206040518083038186803b15801561090057600080fd5b505afa158015610914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109389190612174565b905061095461070488602001518861165790919063ffffffff16565b915060006109618761164f565b131561097d5760408701516109769082611767565b925061098f565b604087015161098c9082611784565b92505b506109a3565b505060208401516040850151905b6109ab611dc2565b610a438b6001600160a01b03166350799c81876109c95760006109cc565b60015b8786886040518563ffffffff1660e01b81526004016109ee94939291906121e2565b60206040518083038186803b158015610a0657600080fd5b505afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190612174565b6117a1565b9050610a5f85610a5557600019610a58565b60015b8290611805565b9750505050505050505b9392505050565b6000610a7a61164b565b6098546001600160a01b03908116911614610aa75760405162461bcd60e51b81526004016102e490612349565b6000826001811115610ab557fe5b1415610b3e576001600160a01b03808516600090815260976020908152604080832093871683529290522060010154610aec611821565b609954610afa908390611825565b1115610b0a576000915050610a69565b610b12611821565b6001600160a01b0380871660009081526097602090815260408083209389168352929052205550610bbd565b6001600160a01b03808516600090815260976020908152604080832093871683529290522054610b6c611821565b609954610b7a908390611825565b1115610b8a576000915050610a69565b610b92611821565b6001600160a01b03808716600090815260976020908152604080832093891683529290522060010155505b5060019392505050565b60976020908152600092835260408084209091529082529020805460019091015482565b610bf3611e14565b610bfb61164b565b6098546001600160a01b03908116911614610c285760405162461bcd60e51b81526004016102e490612349565b8251610c339061164f565b610c45575060a0820181905281610a69565b610c4d611dd5565b60a08401516040516311bf8bf760e11b81526001600160a01b0387169163237f17ee91610c7d919060040161220b565b60806040518083038186803b158015610c9557600080fd5b505afa158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd9190612110565b9050610cd7611dc2565b610d568260000151876001600160a01b03166329f9b17b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1857600080fd5b505afa158015610d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d509190612174565b90611724565b9050610d60611dc2565b610d68611dc2565b610d718361164f565b15610e8657610d7e611dc2565b886001600160a01b03166350799c816000610d988761164f565b13610da4576001610da7565b60005b610db0876116f3565b886020015189604001516040518563ffffffff1660e01b8152600401610dd994939291906121e2565b60206040518083038186803b158015610df157600080fd5b505afa158015610e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e299190612174565b9050610e4561070486602001518661165790919063ffffffff16565b91506000610e528561164f565b1315610e6e576040850151610e679082611767565b9250610e80565b6040850151610e7d9082611784565b92505b50610e94565b505060208201516040830151905b86516040516340d71cd960e01b81526001600160a01b038a16916340d71cd991610ec59190859087906004016125da565b60206040518083038186803b158015610edd57600080fd5b505afa158015610ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f159190612174565b87525050505060a083019190915250919050565b610f3161164b565b6033546001600160a01b03908116911614610f5e5760405162461bcd60e51b81526004016102e490612449565b609955565b6098546001600160a01b031681565b610f7a61164b565b6033546001600160a01b03908116911614610fa75760405162461bcd60e51b81526004016102e490612449565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b610ff9611dc2565b611001611dc2565b61100961164b565b6098546001600160a01b039081169116146110365760405162461bcd60e51b81526004016102e490612349565b61103e611dc2565b8451611049906116f3565b90506110548161164f565b1561121a57600080611069876000015161164f565b12905060008161107a57600061107d565b60015b9050600186600281111561108d57fe5b1415611118576040516337d2176f60e11b81526001600160a01b03891690636fa42ede906110c190849087906004016121c6565b60206040518083038186803b1580156110d957600080fd5b505afa1580156110ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111119190612174565b94506111e3565b600086600281111561112657fe5b141561115a5760405163da0c592760e01b81526001600160a01b0389169063da0c5927906110c190849087906004016121c6565b611162611dc2565b886001600160a01b031663468f02d26040518163ffffffff1660e01b815260040160206040518083038186803b15801561119b57600080fd5b505afa1580156111af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d39190612174565b90506111df848261184a565b9550505b81611204576111ff87604001516111f9876117a1565b90611867565b611215565b611215856111f989604001516117a1565b935050505b50935093915050565b61122b61164b565b6033546001600160a01b039081169116146112585760405162461bcd60e51b81526004016102e490612449565b609c80546001600160a01b0319166001600160a01b0392909216919091179055565b60995481565b611288611dd5565b61129061164b565b6098546001600160a01b039081169116146112bd5760405162461bcd60e51b81526004016102e490612349565b6112c5611dc2565b609854604051636891397b60e01b81526001600160a01b0390911690636891397b906112f59088906004016121a7565b60206040518083038186803b15801561130d57600080fd5b505afa158015611321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113459190612174565b9050611354846000015161164f565b1561137c57835160608501516113769190611370908490611724565b906118cc565b60408301525b611384611dc2565b6098546040516316f3f13160e21b81526001600160a01b0390911690635bcfc4c4906113b49089906004016121a7565b60206040518083038186803b1580156113cc57600080fd5b505afa1580156113e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114049190612174565b9050611413856000015161164f565b156114435761143d856040015161143787608001518461176790919063ffffffff16565b9061184a565b60608401525b61144b611dc2565b611478866020015161147286606001516111f988604001518a61172490919063ffffffff16565b90611657565b905060006114858261164f565b121561149e57611494816116f3565b60208501526114aa565b6114a7816116f3565b84525b5050509392505050565b6033546001600160a01b031690565b609a6020526000908152604090205481565b609b6020526000908152604090205481565b600054610100900460ff168061150057506115006118e9565b8061150e575060005460ff16155b61152a5760405162461bcd60e51b81526004016102e490612379565b600054610100900460ff16158015611555576000805460ff1961ff0019909116610100171660011790555b61155d6118ef565b609880546001600160a01b0319166001600160a01b0385161790556099829055801561158f576000805461ff00191690555b505050565b61159c61164b565b6033546001600160a01b039081169116146115c95760405162461bcd60e51b81526004016102e490612449565b6001600160a01b0381166115ef5760405162461bcd60e51b81526004016102e49061228b565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b80515b919050565b61165f611dc2565b8180600001516001600160ff1b03101560405180606001604052806033815260200161264760339139906116a65760405162461bcd60e51b81526004016102e49190612214565b506116af611dc2565b835185516116bc91611982565b8152949350505050565b6116ce611dc2565b5060408051602081019091526000815290565b60006116ec826116f3565b5192915050565b6116fb611dc2565b611703611dc2565b825160001315611719578251600003815261171e565b825181525b92915050565b61172c611dc2565b611734611dc2565b82518451611741916119c8565b81529392505050565b611752611dc2565b61175a611dc2565b8251845161174191611982565b61176f611dc2565b611777611dc2565b8251845161174191611a0e565b61178c611dc2565b611794611dc2565b8251845161174191611825565b6117a9611dc2565b8180600001516001600160ff1b03101560405180606001604052806033815260200161264760339139906117f05760405162461bcd60e51b81526004016102e49190612214565b50506040805160208101909152915182525090565b61180d611dc2565b611815611dc2565b83516117419084611a50565b4290565b600082820183811015610a695760405162461bcd60e51b81526004016102e4906122d1565b611852611dc2565b61185a611dc2565b8251845161174191611abb565b61186f611dc2565b8180600001516001600160ff1b03101560405180606001604052806033815260200161264760339139906118b65760405162461bcd60e51b81526004016102e49190612214565b506118bf611dc2565b835185516116bc916119c8565b6118d4611dc2565b6118dc611dc2565b8251845161174191611ac9565b303b1590565b600054610100900460ff168061190857506119086118e9565b80611916575060005460ff16155b6119325760405162461bcd60e51b81526004016102e490612379565b600054610100900460ff1615801561195d576000805460ff1961ff0019909116610100171660011790555b611965611ad7565b61196d611b58565b801561197f576000805461ff00191690555b50565b60008282018183128015906119975750838112155b806119ac57506000831280156119ac57508381125b610a695760405162461bcd60e51b81526004016102e490612308565b60008183038183128015906119dd5750838113155b806119f257506000831280156119f257508381135b610a695760405162461bcd60e51b81526004016102e4906124c5565b6000610a6983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611c32565b600082611a5f5750600061171e565b82600019148015611a735750600160ff1b82145b15611a905760405162461bcd60e51b81526004016102e49061247e565b82820282848281611a9d57fe5b0514610a695760405162461bcd60e51b81526004016102e49061247e565b6000610a6983836012611c5e565b6000610a6983836012611c84565b600054610100900460ff1680611af05750611af06118e9565b80611afe575060005460ff16155b611b1a5760405162461bcd60e51b81526004016102e490612379565b600054610100900460ff1615801561196d576000805460ff1961ff001990911661010017166001179055801561197f576000805461ff001916905550565b600054610100900460ff1680611b715750611b716118e9565b80611b7f575060005460ff16155b611b9b5760405162461bcd60e51b81526004016102e490612379565b600054610100900460ff16158015611bc6576000805460ff1961ff0019909116610100171660011790555b6000611bd061164b565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350801561197f576000805461ff001916905550565b60008184841115611c565760405162461bcd60e51b81526004016102e49190612214565b505050900390565b6000611c7c611c6c83611ca2565b611c768686611cab565b90611ce5565b949350505050565b6000611c7c611c9283611ca2565b611c9c8686611a50565b90611d27565b60ff16600a0a90565b600082611cba5750600061171e565b82820282848281611cc757fe5b0414610a695760405162461bcd60e51b81526004016102e490612408565b6000610a6983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611d8b565b600081611d465760405162461bcd60e51b81526004016102e490612509565b81600019148015611d5a5750600160ff1b83145b15611d775760405162461bcd60e51b81526004016102e4906123c7565b6000828481611d8257fe5b05949350505050565b60008183611dac5760405162461bcd60e51b81526004016102e49190612214565b506000838581611db857fe5b0495945050505050565b6040518060200160405280600081525090565b6040518060800160405280611de8611dc2565b8152602001611df5611dc2565b8152602001611e02611dc2565b8152602001611e0f611dc2565b905290565b6040518060e00160405280611e27611dc2565b8152602001611e34611dc2565b8152602001611e41611dc2565b8152602001611e4e611dc2565b8152602001611e5b611dc2565b815260200160008152602001600081525090565b600060e08284031215611e80578081fd5b611e8a60e06125ff565b9050611e968383611efa565b8152611ea58360208401611efa565b6020820152611eb78360408401611efa565b6040820152611ec98360608401611efa565b6060820152611edb8360808401611efa565b608082015260a082013560a082015260c082013560c082015292915050565b600060208284031215611f0b578081fd5b611f1560206125ff565b9135825250919050565b600060208284031215611f30578081fd5b611f3a60206125ff565b9151825250919050565b600060208284031215611f55578081fd5b8135610a6981612631565b60008060408385031215611f72578081fd5b8235611f7d81612631565b91506020830135611f8d81612631565b809150509250929050565b600080600060608486031215611fac578081fd5b8335611fb781612631565b92506020840135611fc781612631565b9150604084013560028110611fda578182fd5b809150509250925092565b60008060408385031215611ff7578182fd5b823561200281612631565b946020939093013593505050565b60008060006101208486031215612025578283fd5b833561203081612631565b925061203f8560208601611e6f565b915061010084013560038110611fda578182fd5b60008060006101208486031215612068578283fd5b833561207381612631565b92506120828560208601611e6f565b9150612092856101008601611efa565b90509250925092565b600080600061012084860312156120b0578283fd5b83356120bb81612631565b92506120ca8560208601611e6f565b915061010084013590509250925092565b600080604083850312156120ed578182fd5b82356120f881612631565b91506121078460208501611efa565b90509250929050565b600060808284031215612121578081fd5b61212b60806125ff565b6121358484611f1f565b81526121448460208501611f1f565b60208201526121568460408501611f1f565b60408201526121688460608501611f1f565b60608201529392505050565b600060208284031215612185578081fd5b610a698383611f1f565b6000602082840312156121a0578081fd5b5035919050565b6001600160a01b0391909116815260200190565b901515815260200190565b604081016121d384612626565b82529151602090910152919050565b608081016121ef86612626565b8252935160208201529151604083015251606090910152919050565b90815260200190565b6000602080835283518082850152825b8181101561224057858101830151858201604001528201612224565b818111156122515783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600a90820152691bdd995c881b1a5b5a5d60b21b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526021908201527f5369676e6564536166654d6174683a206164646974696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260169082015275063616c6c6572206973206e6f742053616b65506572760541b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f5369676e6564536166654d6174683a206469766973696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526027908201527f5369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f604082015266766572666c6f7760c81b606082015260800190565b60208082526024908201527f5369676e6564536166654d6174683a207375627472616374696f6e206f766572604082015263666c6f7760e01b606082015260800190565b6020808252818101527f5369676e6564536166654d6174683a206469766973696f6e206279207a65726f604082015260600190565b600060e0820190508251518252602083015151602083015260408301515160408301526060830151516060830152608083015151608083015260a083015160a083015260c083015160c083015292915050565b815151815260208083015151908201526040808301515190820152606091820151519181019190915260800190565b9151825251602082015260400190565b9051815260200190565b925183529051602083015251604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff8111828210171561261e57600080fd5b604052919050565b806002811061165257fe5b6001600160a01b038116811461197f57600080fdfe4d69786564446563696d616c3a2075696e742076616c756520697320626967676572207468616e205f494e543235365f4d4158a2646970667358221220c0b69a262adceb05a8de76766ef77a8c1800c16734d78d9f099ad6640ae9582464736f6c634300060c0033

Deployed ByteCode Sourcemap

40201:15919:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43776:1091;;;;;;:::i;:::-;;:::i;:::-;;43539:98;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49382:4900;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;42059:875::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;40484:72::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;47011:2363::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;43100:132::-;;;;;;:::i;:::-;;:::i;40563:23::-;;;:::i;11195:148::-;;;:::i;45270:1733::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;43431:100::-;;;;;;:::i;:::-;;:::i;40593:32::-;;;:::i;:::-;;;;;;;:::i;54290:1827::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;10553:79::-;;;:::i;40824:66::-;;;;;;:::i;:::-;;:::i;40897:79::-;;;;;;:::i;:::-;;:::i;41754:203::-;;;;;;:::i;:::-;;:::i;11498:244::-;;;;;;:::i;:::-;;:::i;43776:1091::-;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;;;;;;;;;43987:11:::1;44001:47;:9;-1:-1:-1::0;;;;;44001:36:0::1;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;:47::i;:::-;43987:61:::0;-1:-1:-1;44085:9:0;44110:7;;44106:754:::1;;44134:62;;:::i;:::-;-1:-1:-1::0;;;;;44229:32:0;::::1;;::::0;;;:23:::1;:32;::::0;;;;;;;;44216:46;;;;::::1;::::0;;;;;;;::::1;::::0;:7;;:12:::1;:46::i;:::-;44134:128;;44442:1;44404:35;:27;:33;:35::i;:::-;:39;44400:130;;;44494:20;:18;:20::i;:::-;44464:50;;44400:130;44566:1;44548:15;:7;:13;:15::i;:::-;:19;44544:222;;;44705:3;44665:36;:27;:34;:36::i;:::-;:43;;:70;;;-1:-1:-1::0;44726:9:0::1;::::0;-1:-1:-1;;;;;44726:9:0::1;44712:10;:23;44665:70;44657:93;;;;-1:-1:-1::0;;;44657:93:0::1;;;;;;;:::i;:::-;44815:33;:27;:31;:33::i;:::-;-1:-1:-1::0;;;;;44780:32:0;::::1;;::::0;;;:23:::1;:32;::::0;;;;:68;;;;-1:-1:-1;44106:754:0::1;41737:1;;43776:1091:::0;;:::o;43539:98::-;43620:9;;-1:-1:-1;;;;;43620:9:0;43539:98;:::o;49382:4900::-;49603:34;;:::i;:::-;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;49650:56:::1;;:::i;:::-;49722:61;::::0;-1:-1:-1;;;49722:61:0;;-1:-1:-1;;;;;49722:38:0;::::1;::::0;::::1;::::0;:61:::1;::::0;49761:21;;49722:61:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49650:133;;49794:48;;:::i;:::-;-1:-1:-1::0;49870:31:0::1;::::0;::::1;::::0;49845:57:::1;::::0;;;:24:::1;:57;::::0;;;;;;;49794:108;;;;::::1;::::0;;;;;;49936:14;;49794:108;;49845:57;;;49936:22:::1;::::0;:20:::1;:22::i;:::-;:26;:41;;49972:5;49936:41;;;49965:4;49936:41;49913:64;;49988:34;;:::i;:::-;50050:54;;:::i;:::-;50163:31;::::0;::::1;::::0;50124:71:::1;::::0;-1:-1:-1;;;50124:71:0;;-1:-1:-1;;;;;50124:38:0;::::1;::::0;::::1;::::0;:71:::1;::::0;50163:31;50124:71:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50050:145;;50210:45;;:::i;:::-;50314:31:::0;;50275:33;;:91:::1;::::0;50352:13;;50275:71:::1;::::0;:38:::1;:71::i;:::-;:76:::0;::::1;:91::i;:::-;50210:156;;50486:44;;:::i;:::-;50545:45;;:::i;:::-;50609:18;:10;:16;:18::i;:::-;:23:::0;50605:1008:::1;;50653:37;;:::i;:::-;50714:9;-1:-1:-1::0;;;;;50714:35:0::1;;50797:1;50776:18;:10;:16;:18::i;:::-;:22;:91;;50833:34;50776:91;;;50801:29;50776:91;50894:16;:10;:14;:16::i;:::-;50937:12;:30;;;50994:12;:29;;;50714:332;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50653:393;;51090:53;:47;51106:12;:30;;;51090:10;:15;;:47;;;;:::i;:::-;:51;:53::i;:::-;51065:78;;51187:1;51166:18;:10;:16;:18::i;:::-;:22;51162:268;;;51237:29;::::0;::::1;::::0;:50:::1;::::0;51272:14;51237:34:::1;:50::i;:::-;51213:74;;51162:268;;;51360:29;::::0;::::1;::::0;:50:::1;::::0;51395:14;51360:34:::1;:50::i;:::-;51336:74;;51162:268;50605:1008;;;;-1:-1:-1::0;;51495:30:0::1;::::0;::::1;::::0;51568:29:::1;::::0;::::1;::::0;;50605:1008:::1;51774:9;-1:-1:-1::0;;;;;51774:36:0::1;;51829:15;:84;;51879:34;51829:84;;;51847:29;51829:84;51932:14:::0;;:20:::1;::::0;:18:::1;:20::i;:::-;51971:22;52012:21;51774:274;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51760:288;;52065:47;;:::i;:::-;52115:37;52140:11;52115:24;:37::i;:::-;52065:87;;52171:15;52167:97;;;52222:26;:12:::0;-1:-1:-1;;52222:22:0::1;:26::i;:::-;52207:41;;52167:97;52381:31;::::0;::::1;::::0;52338:89:::1;::::0;;;:24:::1;:89;::::0;;;;;;;;:112;;;;::::1;::::0;;;;;;;:126:::1;::::0;52451:12;52338:112:::1;:126::i;:::-;52303:31;::::0;::::1;::::0;52278:57:::1;::::0;;;:24:::1;:57;::::0;;;;:186;;;;-1:-1:-1;52503:44:0::1;::::0;-1:-1:-1;52503:44:0::1;::::0;-1:-1:-1;;;52503:44:0:i:1;:::-;52562:45;;:::i;:::-;52626:21;:13;:19;:21::i;:::-;:26:::0;52622:1037:::1;;52673:37;;:::i;:::-;52734:9;-1:-1:-1::0;;;;;52734:35:0::1;;52820:1;52796:21;:13;:19;:21::i;:::-;:25;:94;;52856:34;52796:94;;;52824:29;52796:94;52917:19;:13;:17;:19::i;:::-;52963:14;:32;;;53022:14;:31;;;52734:342;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52673:403;;53120:58;:52;53139:14;:32;;;53120:13;:18;;:52;;;;:::i;:58::-;53095:83;;53225:1;53201:21;:13;:19;:21::i;:::-;:25;53197:275;;;53275:31;::::0;::::1;::::0;:52:::1;::::0;53312:14;53275:36:::1;:52::i;:::-;53251:76;;53197:275;;;53400:31;::::0;::::1;::::0;:52:::1;::::0;53437:14;53400:36:::1;:52::i;:::-;53376:76;;53197:275;52622:1037;;;;-1:-1:-1::0;;53537:32:0::1;::::0;::::1;::::0;53612:31:::1;::::0;::::1;::::0;;52622:1037:::1;53746:47;;:::i;:::-;53813:370;53860:9;-1:-1:-1::0;;;;;53860:35:0::1;;53922:15;:84;;53977:29;53922:84;;;53940:34;53922:84;54033:11;54071:22;54120:21;53860:304;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53813:24;:370::i;:::-;53746:437;;54207:56;54230:15;:32;;-1:-1:-1::0;;54230:32:0::1;;;54248:1;54230:32;54207:12:::0;;:22:::1;:56::i;:::-;54200:63;;;;;;;;;41737:1;49382:4900:::0;;;;;:::o;42059:875::-;42222:4;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;42252:23:::1;42243:5;:32;;;;;;;;;42239:666;;;-1:-1:-1::0;;;;;42319:23:0;;::::1;42292:24;42319:23:::0;;;:12:::1;:23;::::0;;;;;;;:32;;::::1;::::0;;;;;;:49:::1;;::::0;42429:17:::1;:15;:17::i;:::-;42408;::::0;42387:39:::1;::::0;:16;;:20:::1;:39::i;:::-;:59;42383:112;;;42474:5;42467:12;;;;;42383:112;42560:17;:15;:17::i;:::-;-1:-1:-1::0;;;;;42509:23:0;;::::1;;::::0;;;:12:::1;:23;::::0;;;;;;;:32;;::::1;::::0;;;;;;:68;-1:-1:-1;42239:666:0::1;;;-1:-1:-1::0;;;;;42636:23:0;;::::1;42610;42636::::0;;;:12:::1;:23;::::0;;;;;;;:32;;::::1;::::0;;;;;;:48;42744:17:::1;:15;:17::i;:::-;42723;::::0;42703:38:::1;::::0;:15;;:19:::1;:38::i;:::-;:58;42699:111;;;42789:5;42782:12;;;;;42699:111;42876:17;:15;:17::i;:::-;-1:-1:-1::0;;;;;42824:23:0;;::::1;;::::0;;;:12:::1;:23;::::0;;;;;;;:32;;::::1;::::0;;;;;;:49:::1;;:69:::0;-1:-1:-1;42239:666:0::1;-1:-1:-1::0;42922:4:0::1;42059:875:::0;;;;;:::o;40484:72::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;47011:2363::-;47227:30;;:::i;:::-;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;47274:14;;:22:::1;::::0;:20:::1;:22::i;:::-;47270:146;;-1:-1:-1::0;47318:31:0::1;::::0;::::1;:55:::0;;;:9;47388:16:::1;;47270:146;47577:54;;:::i;:::-;47686:31;::::0;::::1;::::0;47647:71:::1;::::0;-1:-1:-1;;;47647:71:0;;-1:-1:-1;;;;;47647:38:0;::::1;::::0;::::1;::::0;:71:::1;::::0;47686:31;47647:71:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47577:141;;47729:48;;:::i;:::-;47793:71;47832:12;:31;;;47793:9;-1:-1:-1::0;;;;;47793:31:0::1;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38:::0;::::1;:71::i;:::-;47729:135;;47975:44;;:::i;:::-;48030:45;;:::i;:::-;48090:21;:13;:19;:21::i;:::-;:26:::0;48086:955:::1;;48133:37;;:::i;:::-;48190:9;-1:-1:-1::0;;;;;48190:35:0::1;;48272:1;48248:21;:13;:19;:21::i;:::-;:25;:94;;48308:34;48248:94;;;48276:29;48248:94;48365:19;:13;:17;:19::i;:::-;48407:12;:30;;;48460:12;:29;;;48190:318;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48133:375;;48548:56;:50;48567:12;:30;;;48548:13;:18;;:50;;;;:::i;:56::-;48523:81;;48647:1;48623:21;:13;:19;:21::i;:::-;:25;48619:255;;;48693:29;::::0;::::1;::::0;:50:::1;::::0;48728:14;48693:34:::1;:50::i;:::-;48669:74;;48619:255;;;48808:29;::::0;::::1;::::0;:50:::1;::::0;48843:14;48808:34:::1;:50::i;:::-;48784:74;;48619:255;48086:955;;;;-1:-1:-1::0;;48931:30:0::1;::::0;::::1;::::0;49000:29:::1;::::0;::::1;::::0;;48086:955:::1;49175:14:::0;;49114:159:::1;::::0;-1:-1:-1;;;49114:159:0;;-1:-1:-1;;;;;49114:46:0;::::1;::::0;::::1;::::0;:159:::1;::::0;49175:14;49204:22;;49241:21;;49114:159:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49097:176:::0;;-1:-1:-1;;;;49284:31:0::1;::::0;::::1;:55:::0;;;;-1:-1:-1;49097:176:0;47011:2363;-1:-1:-1;47011:2363:0:o;43100:132::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;43186:17:::1;:38:::0;43100:132::o;40563:23::-;;;-1:-1:-1;;;;;40563:23:0;;:::o;11195:148::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;11286:6:::1;::::0;11265:40:::1;::::0;11302:1:::1;::::0;-1:-1:-1;;;;;11286:6:0::1;::::0;11265:40:::1;::::0;11302:1;;11265:40:::1;11316:6;:19:::0;;-1:-1:-1;;;;;;11316:19:0::1;::::0;;11195:148::o;45270:1733::-;45545:39;;:::i;:::-;45586:48;;:::i;:::-;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;45652:38:::1;;:::i;:::-;45693:14:::0;;:20:::1;::::0;:18:::1;:20::i;:::-;45652:61;;45728:24;:15;:22;:24::i;:::-;:29:::0;45724:1272:::1;;45774:20;45822:1:::0;45797:22:::1;:9;:14;;;:20;:22::i;:::-;:26;45774:49;;45838:22;45880:15;:84;;45935:29;45880:84;;;45898:34;45880:84;45838:126:::0;-1:-1:-1;46001:33:0::1;45983:14;:51;;;;;;;;;45979:505;;;46074:45;::::0;-1:-1:-1;;;46074:45:0;;-1:-1:-1;;;;;46074:23:0;::::1;::::0;::::1;::::0;:45:::1;::::0;46098:3;;46103:15;;46074:45:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46055:64;;45979:505;;;46164:39;46146:14;:57;;;;;;;;;46142:342;;;46243:46;::::0;-1:-1:-1;;;46243:46:0;;-1:-1:-1;;;;;46243:24:0;::::1;::::0;::::1;::::0;:46:::1;::::0;46268:3;;46273:15;;46243:46:::1;;;:::i;46142:342::-;46330:34;;:::i;:::-;46367:9;-1:-1:-1::0;;;;;46367:28:0::1;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46330:67:::0;-1:-1:-1;46435:33:0::1;:15:::0;46330:67;46435:20:::1;:33::i;:::-;46416:52;;46142:342;;46787:15;:197;;46913:71;46961:9;:22;;;46913:42;46938:16;46913:24;:42::i;:::-;:47:::0;::::1;:71::i;:::-;46787:197;;;46822:71;46876:16;46822:48;46847:9;:22;;;46822:24;:48::i;:71::-;46771:213;;45724:1272;;;41737:1;45270:1733:::0;;;;;;:::o;43431:100::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;43501:9:::1;:22:::0;;-1:-1:-1;;;;;;43501:22:0::1;-1:-1:-1::0;;;;;43501:22:0;;;::::1;::::0;;;::::1;::::0;;43431:100::o;40593:32::-;;;;:::o;54290:1827::-;54541:40;;:::i;:::-;41687:12;:10;:12::i;:::-;41675:8;;-1:-1:-1;;;;;41675:8:0;;;:24;;;41667:59;;;;-1:-1:-1;;;41667:59:0;;;;;;;:::i;:::-;54632:66:::1;;:::i;:::-;54724:8;::::0;54714:65:::1;::::0;-1:-1:-1;;;54714:65:0;;-1:-1:-1;;;;;54724:8:0;;::::1;::::0;54714:54:::1;::::0;:65:::1;::::0;54769:9;;54714:65:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54632:147;;54794:25;:12;:17;;;:23;:25::i;:::-;:30:::0;54790:244:::1;;55004:17:::0;;54930:49:::1;::::0;::::1;::::0;54875:147:::1;::::0;55004:17;54875:105:::1;::::0;:31;;:54:::1;:105::i;:::-;:128:::0;::::1;:147::i;:::-;54841:31;::::0;::::1;:181:::0;54790:244:::1;55148:55;;:::i;:::-;55229:8;::::0;55219:66:::1;::::0;-1:-1:-1;;;55219:66:0;;-1:-1:-1;;;;;55229:8:0;;::::1;::::0;55219:55:::1;::::0;:66:::1;::::0;55275:9;;55219:66:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;55148:137;;55300:25;:12;:17;;;:23;:25::i;:::-;:30:::0;55296:252:::1;;55379:157;55510:12;:25;;;55379:107;55435:12;:50;;;55379:32;:55;;:107;;;;:::i;:::-;:130:::0;::::1;:157::i;:::-;55347:29;::::0;::::1;:189:::0;55296:252:::1;55596:53;;:::i;:::-;55665:144;55775:12;:19;;;55665:86;55721:16;:29;;;55665:50;55683:16;:31;;;55665:12;:17;;:50;;;;:::i;:86::-;:91:::0;::::1;:144::i;:::-;55596:213;;55940:1;55911:26;:18;:24;:26::i;:::-;:30;55907:203;;;55985:24;:18;:22;:24::i;:::-;55958;::::0;::::1;:51:::0;55907:203:::1;;;56074:24;:18;:22;:24::i;:::-;56042:56:::0;;55907:203:::1;41737:1;;;54290:1827:::0;;;;;:::o;10553:79::-;10618:6;;-1:-1:-1;;;;;10618:6:0;10553:79;:::o;40824:66::-;;;;;;;;;;;;;:::o;40897:79::-;;;;;;;;;;;;;:::o;41754:203::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;41851:16:::1;:14;:16::i;:::-;41880:8;:20:::0;;-1:-1:-1;;;;;;41880:20:0::1;-1:-1:-1::0;;;;;41880:20:0;::::1;;::::0;;41911:17:::1;:38:::0;;;7257:68;;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;7257:68;41754:203;;;:::o;11498:244::-;10775:12;:10;:12::i;:::-;10765:6;;-1:-1:-1;;;;;10765:6:0;;;:22;;;10757:67;;;;-1:-1:-1;;;10757:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;11587:22:0;::::1;11579:73;;;;-1:-1:-1::0;;;11579:73:0::1;;;;;;;:::i;:::-;11689:6;::::0;11668:38:::1;::::0;-1:-1:-1;;;;;11668:38:0;;::::1;::::0;11689:6:::1;::::0;11668:38:::1;::::0;11689:6:::1;::::0;11668:38:::1;11717:6;:17:::0;;-1:-1:-1;;;;;;11717:17:0::1;-1:-1:-1::0;;;;;11717:17:0;;;::::1;::::0;;;::::1;::::0;;11498:244::o;8859:106::-;8947:10;8859:106;:::o;13974:95::-;14058:3;;13974:95;;;;:::o;37841:304::-;37993:34;;:::i;:::-;37972:1;37324;:3;;;-1:-1:-1;;;;;37309:18:0;;37329:21;;;;;;;;;;;;;;;;;37301:50;;;;;-1:-1:-1;;;37301:50:0;;;;;;;;:::i;:::-;;38045:36:::1;;:::i;:::-;38113:3:::0;;38098;;:20:::1;::::0;:7:::1;:20::i;:::-;38092:26:::0;;;37841:304;-1:-1:-1;;;;37841:304:0:o;20546:103::-;20585:20;;:::i;:::-;-1:-1:-1;20625:16:0;;;;;;;;;-1:-1:-1;20625:16:0;;20546:103;:::o;37615:121::-;37692:7;37719;:1;:5;:7::i;:::-;:9;;37615:121;-1:-1:-1;;37615:121:0:o;20937:269::-;20997:22;;:::i;:::-;21032:24;;:::i;:::-;21071:3;;21077:1;-1:-1:-1;21067:113:0;;;21113:3;;;21109:7;21095:22;;21067:113;;;21164:3;;21150:18;;21067:113;21197:1;20937:269;-1:-1:-1;;20937:269:0:o;21485:196::-;21570:20;;:::i;:::-;21603:22;;:::i;:::-;21650:3;;21642;;:12;;:7;:12::i;:::-;21636:18;;;21485:196;-1:-1:-1;;;21485:196:0:o;21245:::-;21330:20;;:::i;:::-;21363:22;;:::i;:::-;21410:3;;21402;;:12;;:7;:12::i;14721:172::-;14794:14;;:::i;:::-;14821:16;;:::i;:::-;14862:3;;14854;;:12;;:7;:12::i;14505:172::-;14578:14;;:::i;:::-;14605:16;;:::i;:::-;14646:3;;14638;;:12;;:7;:12::i;37379:228::-;37500:34;;:::i;:::-;37479:1;37324;:3;;;-1:-1:-1;;;;;37309:18:0;;37329:21;;;;;;;;;;;;;;;;;37301:50;;;;;-1:-1:-1;;;37301:50:0;;;;;;;;:::i;:::-;-1:-1:-1;;37559:40:0::1;::::0;;::::1;::::0;::::1;::::0;;;37594:3;;37559:40;;-1:-1:-1;37559:40:0;37379:228::o;21981:185::-;22057:20;;:::i;:::-;22090:22;;:::i;:::-;22129:3;;:10;;22137:1;22129:7;:10::i;36548:108::-;36633:15;36548:108;:::o;998:181::-;1056:7;1088:5;;;1112:6;;;;1104:46;;;;-1:-1:-1;;;1104:46:0;;;;;;;:::i;14937:173::-;15010:14;;:::i;:::-;15037:16;;:::i;:::-;15079:3;;15070;;:13;;:8;:13::i;38254:304::-;38406:34;;:::i;:::-;38385:1;37324;:3;;;-1:-1:-1;;;;;37309:18:0;;37329:21;;;;;;;;;;;;;;;;;37301:50;;;;;-1:-1:-1;;;37301:50:0;;;;;;;;:::i;:::-;;38458:36:::1;;:::i;:::-;38526:3:::0;;38511;;:20:::1;::::0;:7:::1;:20::i;21725:197::-:0;21810:20;;:::i;:::-;21843:22;;:::i;:::-;21891:3;;21882;;:13;;:8;:13::i;7425:604::-;7867:4;7978:17;8014:7;7425:604;:::o;10139:129::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;10197:26:::1;:24;:26::i;:::-;10234;:24;:26::i;:::-;7261:14:::0;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;7257:68;10139:129;:::o;18341:215::-;18397:6;18427:5;;;18452:6;;;;;;:16;;;18467:1;18462;:6;;18452:16;18451:38;;;;18478:1;18474;:5;:14;;;;;18487:1;18483;:5;18474:14;18443:84;;;;-1:-1:-1;;;18443:84:0;;;;;;;:::i;17878:218::-;17934:6;17964:5;;;17989:6;;;;;;:16;;;18004:1;17999;:6;;17989:16;17988:38;;;;18015:1;18011;:5;:14;;;;;18024:1;18020;:5;18011:14;17980:87;;;;-1:-1:-1;;;17980:87:0;;;;;;;:::i;1462:136::-;1520:7;1547:43;1551:1;1554;1547:43;;;;;;;;;;;;;;;;;:3;:43::i;16314:568::-;16370:6;16614;16610:47;;-1:-1:-1;16644:1:0;16637:8;;16610:47;16679:1;-1:-1:-1;;16679:7:0;:27;;;;;-1:-1:-1;;;16690:1:0;:16;16679:27;16677:30;16669:82;;;;-1:-1:-1;;;16669:82:0;;;;;;;:::i;:::-;16775:5;;;16779:1;16775;:5;:1;16799:5;;;;;:10;16791:62;;;;-1:-1:-1;;;16791:62:0;;;;;;;:::i;12692:108::-;12751:7;12778:14;12783:1;12786;12789:2;12778:4;:14::i;19463:105::-;19520:6;19546:14;19551:1;19554;19557:2;19546:4;:14::i;8788:65::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7261:14;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;8788:65;:::o;10276:196::-;6969:13;;;;;;;;:33;;;6986:16;:14;:16::i;:::-;6969:50;;;-1:-1:-1;7007:12:0;;;;7006:13;6969:50;6961:109;;;;-1:-1:-1;;;6961:109:0;;;;;;;:::i;:::-;7083:19;7106:13;;;;;;7105:14;7130:101;;;;7165:13;:20;;-1:-1:-1;;;;7165:20:0;;;;;7200:19;7181:4;7200:19;;;7130:101;10344:17:::1;10364:12;:10;:12::i;:::-;10387:6;:18:::0;;-1:-1:-1;;;;;;10387:18:0::1;-1:-1:-1::0;;;;;10387:18:0;::::1;::::0;;::::1;::::0;;;10421:43:::1;::::0;10387:18;;-1:-1:-1;10387:18:0;-1:-1:-1;;10421:43:0::1;::::0;-1:-1:-1;;10421:43:0::1;7243:1;7261:14:::0;7257:68;;;7308:5;7292:21;;-1:-1:-1;;7292:21:0;;;10276:196;:::o;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;12901:172::-;13010:7;13037:28;13050:14;13055:8;13050:4;:14::i;:::-;13037:8;:1;13043;13037:5;:8::i;:::-;:12;;:28::i;:::-;13030:35;12901:172;-1:-1:-1;;;;12901:172:0:o;19669:169::-;19776:6;19802:28;19815:14;19820:8;19815:4;:14::i;:::-;19802:8;:1;19808;19802:5;:8::i;:::-;:12;;:28::i;12102:109::-;12186:17;;12182:2;:21;;12102:109::o;2352:471::-;2410:7;2655:6;2651:47;;-1:-1:-1;2685:1:0;2678:8;;2651:47;2722:5;;;2726:1;2722;:5;:1;2746:5;;;;;:10;2738:56;;;;-1:-1:-1;;;2738:56:0;;;;;;;:::i;3299:132::-;3357:7;3384:39;3388:1;3391;3384:39;;;;;;;;;;;;;;;;;:3;:39::i;17356:271::-;17412:6;17439;17431:51;;;;-1:-1:-1;;;17431:51:0;;;;;;;:::i;:::-;17503:1;-1:-1:-1;;17503:7:0;:27;;;;;-1:-1:-1;;;17514:1:0;:16;17503:27;17501:30;17493:76;;;;-1:-1:-1;;;17493:76:0;;;;;;;:::i;:::-;17582:8;17597:1;17593;:5;;;;;;;17356:271;-1:-1:-1;;;;17356:271:0:o;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;-1:-1:-1:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;2003:1424::-;;2118:4;2106:9;2101:3;2097:19;2093:30;2090:2;;;-1:-1;;2126:12;2090:2;2154:20;2118:4;2154:20;:::i;:::-;2145:29;;2256:80;2332:3;2308:22;2256:80;:::i;:::-;2238:16;2231:106;2433:73;2502:3;2400:2;2482:9;2478:22;2433:73;:::i;:::-;2400:2;2419:5;2415:16;2408:99;2609:73;2678:3;2576:2;2658:9;2654:22;2609:73;:::i;:::-;2576:2;2595:5;2591:16;2584:99;2809:80;2885:3;2776:2;2865:9;2861:22;2809:80;:::i;:::-;2776:2;2795:5;2791:16;2784:106;3018:73;3087:3;2984;3067:9;3063:22;3018:73;:::i;:::-;2984:3;3004:5;3000:16;2993:99;3170:3;3229:9;3225:22;5001:20;3170:3;3190:5;3186:16;3179:75;3322:3;3381:9;3377:22;5001:20;3322:3;3342:5;3338:16;3331:75;2084:1343;;;;:::o;3463:319::-;;3576:4;3564:9;3559:3;3555:19;3551:30;3548:2;;;-1:-1;;3584:12;3548:2;3612:20;3576:4;3612:20;:::i;:::-;5001;;3686:75;;-1:-1;3603:29;3542:240;-1:-1;3542:240::o;3818:341::-;;3942:4;3930:9;3925:3;3921:19;3917:30;3914:2;;;-1:-1;;3950:12;3914:2;3978:20;3942:4;3978:20;:::i;:::-;5149:13;;4052:86;;-1:-1;3969:29;3908:251;-1:-1;3908:251::o;5212:241::-;;5316:2;5304:9;5295:7;5291:23;5287:32;5284:2;;;-1:-1;;5322:12;5284:2;85:6;72:20;97:33;124:5;97:33;:::i;5460:366::-;;;5581:2;5569:9;5560:7;5556:23;5552:32;5549:2;;;-1:-1;;5587:12;5549:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5639:63;-1:-1;5739:2;5778:22;;72:20;97:33;72:20;97:33;:::i;:::-;5747:63;;;;5543:283;;;;;:::o;5833:509::-;;;;5980:2;5968:9;5959:7;5955:23;5951:32;5948:2;;;-1:-1;;5986:12;5948:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6038:63;-1:-1;6138:2;6177:22;;72:20;97:33;72:20;97:33;:::i;:::-;6146:63;-1:-1;6246:2;6294:22;;564:20;33669:1;33659:12;;33649:2;;-1:-1;;33675:12;33649:2;6254:72;;;;5942:400;;;;;:::o;6349:366::-;;;6470:2;6458:9;6449:7;6445:23;6441:32;6438:2;;;-1:-1;;6476:12;6438:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6528:63;6628:2;6667:22;;;;5001:20;;-1:-1;;;6432:283::o;6722:617::-;;;;6922:3;6910:9;6901:7;6897:23;6893:33;6890:2;;;-1:-1;;6929:12;6890:2;240:6;227:20;252:51;297:5;252:51;:::i;:::-;6981:81;-1:-1;7117:79;7188:7;7099:2;7164:22;;7117:79;:::i;:::-;7107:89;;7233:3;7295:9;7291:22;400:20;33559:1;33552:5;33549:12;33539:2;;-1:-1;;33565:12;7346:643;;;;7559:3;7547:9;7538:7;7534:23;7530:33;7527:2;;;-1:-1;;7566:12;7527:2;240:6;227:20;252:51;297:5;252:51;:::i;:::-;7618:81;-1:-1;7754:79;7825:7;7736:2;7801:22;;7754:79;:::i;:::-;7744:89;;7889:84;7965:7;7870:3;7945:9;7941:22;7889:84;:::i;:::-;7879:94;;7521:468;;;;;:::o;7996:581::-;;;;8178:3;8166:9;8157:7;8153:23;8149:33;8146:2;;;-1:-1;;8185:12;8146:2;240:6;227:20;252:51;297:5;252:51;:::i;:::-;8237:81;-1:-1;8373:79;8444:7;8355:2;8420:22;;8373:79;:::i;:::-;8363:89;;8489:3;8533:9;8529:22;5001:20;8498:63;;8140:437;;;;;:::o;8584:464::-;;;8754:2;8742:9;8733:7;8729:23;8725:32;8722:2;;;-1:-1;;8760:12;8722:2;240:6;227:20;252:51;297:5;252:51;:::i;:::-;8812:81;-1:-1;8948:84;9024:7;8930:2;9000:22;;8948:84;:::i;:::-;8938:94;;8716:332;;;;;:::o;9055:348::-;;9212:3;9200:9;9191:7;9187:23;9183:33;9180:2;;;-1:-1;;9219:12;9180:2;1148:20;9212:3;1148:20;:::i;:::-;1264:91;1351:3;1327:22;1264:91;:::i;:::-;1246:16;1239:117;1463:84;1543:3;1430:2;1523:9;1519:22;1463:84;:::i;:::-;1430:2;1449:5;1445:16;1438:110;1654:84;1734:3;1621:2;1714:9;1710:22;1654:84;:::i;:::-;1621:2;1640:5;1636:16;1629:110;1846:91;1933:3;1813:2;1913:9;1909:22;1846:91;:::i;:::-;1813:2;1828:16;;1821:117;1832:5;9174:229;-1:-1;;;9174:229::o;9410:311::-;;9549:2;9537:9;9528:7;9524:23;9520:32;9517:2;;;-1:-1;;9555:12;9517:2;9617:88;9697:7;9673:22;9617:88;:::i;10060:241::-;;10164:2;10152:9;10143:7;10139:23;10135:32;10132:2;;;-1:-1;;10170:12;10132:2;-1:-1;5001:20;;10126:175;-1:-1;10126:175::o;20401:222::-;-1:-1;;;;;32129:54;;;;10379:37;;20528:2;20513:18;;20499:124::o;20630:210::-;31718:13;;31711:21;10493:34;;20751:2;20736:18;;20722:118::o;21112:441::-;21321:2;21306:18;;32656:32;10834:5;32656:32;:::i;:::-;10785:56;;18852:23;;21539:2;21524:18;;;10912:36;21292:261;;-1:-1;21292:261::o;21560:856::-;21921:3;21906:19;;32656:32;10834:5;32656:32;:::i;:::-;10785:56;;18852:23;;22140:2;22125:18;;10912:36;18852:23;;22271:2;22256:18;;10912:36;18852:23;22402:2;22387:18;;;10912:36;21892:524;;-1:-1;21892:524::o;22423:218::-;10912:36;;;22548:2;22533:18;;22519:122::o;22648:310::-;;22795:2;;22816:17;22809:47;11222:5;31341:12;31498:6;22795:2;22784:9;22780:18;31486:19;-1:-1;32773:101;32787:6;32784:1;32781:13;32773:101;;;32854:11;;;;;32848:18;32835:11;;;31526:14;32835:11;32828:39;32802:10;;32773:101;;;32889:6;32886:1;32883:13;32880:2;;;-1:-1;31526:14;32945:6;22784:9;32936:16;;32929:27;32880:2;-1:-1;33061:7;33045:14;-1:-1;;33041:28;11380:39;;;;31526:14;11380:39;;22766:192;-1:-1;;;22766:192::o;22965:416::-;23165:2;23179:47;;;11656:2;23150:18;;;31486:19;-1:-1;;;31526:14;;;11672:33;11724:12;;;23136:245::o;23388:416::-;23588:2;23602:47;;;11975:2;23573:18;;;31486:19;12011:34;31526:14;;;11991:55;-1:-1;;;12066:12;;;12059:30;12108:12;;;23559:245::o;23811:416::-;24011:2;24025:47;;;12359:2;23996:18;;;31486:19;12395:29;31526:14;;;12375:50;12444:12;;;23982:245::o;24234:416::-;24434:2;24448:47;;;12695:2;24419:18;;;31486:19;12731:34;31526:14;;;12711:55;-1:-1;;;12786:12;;;12779:25;12823:12;;;24405:245::o;24657:416::-;24857:2;24871:47;;;13074:2;24842:18;;;31486:19;-1:-1;;;31526:14;;;13090:45;13154:12;;;24828:245::o;25080:416::-;25280:2;25294:47;;;13405:2;25265:18;;;31486:19;13441:34;31526:14;;;13421:55;-1:-1;;;13496:12;;;13489:38;13546:12;;;25251:245::o;25503:416::-;25703:2;25717:47;;;13797:2;25688:18;;;31486:19;13833:34;31526:14;;;13813:55;-1:-1;;;13888:12;;;13881:25;13925:12;;;25674:245::o;25926:416::-;26126:2;26140:47;;;14176:2;26111:18;;;31486:19;14212:34;31526:14;;;14192:55;-1:-1;;;14267:12;;;14260:25;14304:12;;;26097:245::o;26349:416::-;26549:2;26563:47;;;26534:18;;;31486:19;14591:34;31526:14;;;14571:55;14645:12;;;26520:245::o;26772:416::-;26972:2;26986:47;;;14896:2;26957:18;;;31486:19;14932:34;31526:14;;;14912:55;-1:-1;;;14987:12;;;14980:31;15030:12;;;26943:245::o;27195:416::-;27395:2;27409:47;;;15281:2;27380:18;;;31486:19;15317:34;31526:14;;;15297:55;-1:-1;;;15372:12;;;15365:28;15412:12;;;27366:245::o;27618:416::-;27818:2;27832:47;;;27803:18;;;31486:19;15699:34;31526:14;;;15679:55;15753:12;;;27789:245::o;28041:327::-;;28220:3;28209:9;28205:19;28197:27;;16067:16;16061:23;19638;10919:3;10912:36;16296:4;16289:5;16285:16;16279:23;18852;16296:4;16408:3;16404:14;10912:36;16506:4;16499:5;16495:16;16489:23;18852;16506:4;16618:3;16614:14;10912:36;16740:4;16733:5;16729:16;16723:23;19638;16740:4;16866:3;16862:14;10912:36;16989:4;16982:5;16978:16;16972:23;18852;16989:4;17101:3;17097:14;10912:36;17208:4;17201:5;17197:16;17191:23;17208:4;17272:3;17268:14;10912:36;17369:4;17362:5;17358:16;17352:23;17369:4;17433:3;17429:14;10912:36;28191:177;;;;:::o;28375:359::-;17794:23;;18852;10912:36;;18016:4;18005:16;;;17999:23;18852;18124:14;;;10912:36;18228:4;18217:16;;;18211:23;18852;18350:14;;;10912:36;18452:4;18441:16;;;18435:23;18852;18560:14;;;10912:36;;;;28570:3;28555:19;;28541:193::o;28741:553::-;18852:23;;10912:36;;19638:23;29280:2;29265:18;;10912:36;29006:2;28991:18;;28977:317::o;29301:346::-;19638:23;;10912:36;;29490:2;29475:18;;29461:186::o;29654:760::-;19638:23;;10912:36;;18852:23;;30269:2;30254:18;;10912:36;18852:23;30400:2;30385:18;;10912:36;29995:2;29980:18;;29966:448::o;30650:333::-;10912:36;;;30969:2;30954:18;;10912:36;30805:2;30790:18;;30776:207::o;30990:256::-;31052:2;31046:9;31078:17;;;31153:18;31138:34;;31174:22;;;31135:62;31132:2;;;31210:1;;31200:12;31132:2;31052;31219:22;31030:216;;-1:-1;31030:216::o;31860:122::-;31919:16;33159:1;33149:12;;33139:2;;33165:9;33188:117;-1:-1;;;;;32129:54;;33247:35;;33237:2;;33296:1;;33286:12

Swarm Source

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