Contract 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d3 7

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x22cf57a51221d74dd944da7f8894390c24035142cec164606f40d3d5b61b68cb0x60806040536148272023-01-17 4:50:42437 days 2 hrs agoOpenOcean: Deployer 1 IN  Create: OpenOceanExchange0 ETH0.00105106 0.1
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xe4dc2a535e5a809d32440b5cbdb88bf00bddcabd94083f2e617a4f4994d3e8ec720855652023-03-21 10:14:14373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x7396bea325118a920c458a7e954a8aeaa043137b31f65ad7abe8a9e7173d4716720845512023-03-21 10:10:02373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x9ad2f23c379fa33805902211ee07ef51773fcf71ea8ba426b40f3e046ae1775a720841932023-03-21 10:08:32373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x6c90c22b8bd2a568ab75113f36e313412592859a605bc45d035b69a0cfb1c60d720840362023-03-21 10:07:52373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x09ca0ea12f5214779cfb9ad539b100c81967b8a11034c9475af824a067ec22bf720836322023-03-21 10:06:10373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x6487fd769cb41d75f6ca13abdddcfd157c73a9edb49ecc5c49843c40e50cfb4c720836112023-03-21 10:06:05373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x32883552ca2898f2ca41a46f07d27e9b0c5fa4fd8f19d28e5299c1cf1e3ae479720834552023-03-21 10:05:25373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x22e4ba852132a9155609f8bccc698bdd8dfdda9c435f2da64f9217223aa7e263720833882023-03-21 10:05:16373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x1bd93d6e8222209eb772d25111e726cc41b3b1042303fc9728a205b5890c8c99720832912023-03-21 10:04:52373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0xe6b7ff0ce7712c2c1a21fc9817166c132aa0c63f942c0911be00acf47db1a542720832442023-03-21 10:04:40373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x53327c3c3445538c71f3bb04dd0560fd94cc9361a38bdc23ec344b2ef81fb81f720832062023-03-21 10:04:30373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x8bde5399728e9f22d02541a5bffc98d8faf19cef7700b9c7f8e509dae549df4b720830332023-03-21 10:03:47373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x25478f9393f73ce4671caf29fca500cb98f9e3a491cfec184af24b4d8f22d729720826762023-03-21 10:02:17373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0xcc0cb5c91543f3efbdfe1609390a0c1f0bfbecec9319d0dc39a1e9c6a4d4d28e720824242023-03-21 10:01:13373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x208dc58f65ea0cbd263e3e0b7d369ee4de792bd2297191d2efbe2c41befa5ba8720823592023-03-21 10:00:57373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x5b974810ad7c9666e04302551407517991f1def5f96c8e973dc160e359a0168a720823392023-03-21 10:00:52373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x1127f7919dc9548b8488d682a36596506f2044f0c29e7267832d5c40a33b9fbe720820332023-03-21 9:59:35373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0xfc9e8f4d117217236dad55aa87077cefe5bf2fcfb9e2ea4fd9b5a6f89fc67489720816242023-03-21 9:57:58373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x76c190429eab56ad80d4573850c4749f2334517e7ad781ff219d6dade709d755720815102023-03-21 9:57:29373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0xfc33a6088e79130219997abe83c3a6bf0e2e39ab3b4a3ae1be10827c085e07d8720814552023-03-21 9:57:15373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x34b62e087240deb9dd06d215d3ff9ed4ac31b5b89b2980482e73daca1e7ce3e1720812952023-03-21 9:56:35373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x34b62e087240deb9dd06d215d3ff9ed4ac31b5b89b2980482e73daca1e7ce3e1720812952023-03-21 9:56:35373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x01eef774a4b764f8ed7052ae90a427dae9f79901d95af1701bb6fa5b1024aac0720812742023-03-21 9:56:30373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x09154d7892905a0796a7657bf8a1ee966a5314d7b47d5066676b138eec196ce5720812022023-03-21 9:56:11373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
0x5c43f371806a82ba9119af374e8f2ca301ae959d6ec44b206051f4ebca986686720808282023-03-21 9:54:37373 days 21 hrs ago OpenOcean: Exchange V2 0xfe9a934a8607ef020adf22d4431d6ce6005aa4d30 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OpenOceanExchange

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 Arbiscan.io on 2023-01-17
*/

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;


/**
 * @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) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

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



pragma solidity >=0.6.0 <0.8.0;


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



pragma solidity >=0.6.0 <0.8.0;


/**
 * @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 virtual returns (address) {
        return _owner;
    }

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

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

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

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol



pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: @openzeppelin/contracts/math/SafeMath.sol



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 SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * 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);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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/utils/Address.sol



pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol



pragma solidity >=0.6.0 <0.8.0;




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

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

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

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

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

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

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

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

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



pragma solidity >=0.6.0 <0.8.0;



/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal initializer {
        __Context_init_unchained();
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal initializer {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
    uint256[49] private __gap;
}

// File: contracts/interfaces/IOpenOceanCaller.sol


pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

interface IOpenOceanCaller {
    struct CallDescription {
        uint256 target;
        uint256 gasLimit;
        uint256 value;
        bytes data;
    }

    function makeCall(CallDescription memory desc) external;

    function makeCalls(CallDescription[] memory desc) external payable;
}

// File: contracts/libraries/RevertReasonParser.sol


pragma solidity ^0.6.0;

library RevertReasonParser {
    function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
        // https://solidity.readthedocs.io/en/latest/control-structures.html#revert
        // We assume that revert reason is abi-encoded as Error(string)

        // 68 = 4-byte selector 0x08c379a0 + 32 bytes offset + 32 bytes length
        if (data.length >= 68 && data[0] == "\x08" && data[1] == "\xc3" && data[2] == "\x79" && data[3] == "\xa0") {
            string memory reason;
            // solhint-disable no-inline-assembly
            assembly {
                // 68 = 32 bytes data length + 4-byte selector + 32 bytes offset
                reason := add(data, 68)
            }
            /*
                revert reason is padded up to 32 bytes with ABI encoder: Error(string)
                also sometimes there is extra 32 bytes of zeros padded in the end:
                https://github.com/ethereum/solidity/issues/10170
                because of that we can't check for equality and instead check
                that string length + extra 68 bytes is less than overall data length
            */
            require(data.length >= 68 + bytes(reason).length, "Invalid revert reason");
            return string(abi.encodePacked(prefix, "Error(", reason, ")"));
        }
        // 36 = 4-byte selector 0x4e487b71 + 32 bytes integer
        else if (data.length == 36 && data[0] == "\x4e" && data[1] == "\x48" && data[2] == "\x7b" && data[3] == "\x71") {
            uint256 code;
            // solhint-disable no-inline-assembly
            assembly {
                // 36 = 32 bytes data length + 4-byte selector
                code := mload(add(data, 36))
            }
            return string(abi.encodePacked(prefix, "Panic(", _toHex(code), ")"));
        }

        return string(abi.encodePacked(prefix, "Unknown()"));
    }

    function _toHex(uint256 value) private pure returns(string memory) {
        return _toHex(abi.encodePacked(value));
    }

    function _toHex(bytes memory data) private pure returns(string memory) {
        bytes memory alphabet = "0123456789abcdef";
        bytes memory str = new bytes(2 + data.length * 2);
        str[0] = "0";
        str[1] = "x";
        for (uint256 i = 0; i < data.length; i++) {
            str[2 * i + 2] = alphabet[uint8(data[i] >> 4)];
            str[2 * i + 3] = alphabet[uint8(data[i] & 0x0f)];
        }
        return string(str);
    }
}

// File: contracts/libraries/UniversalERC20.sol


pragma solidity ^0.6.0;




library UniversalERC20 {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    IERC20 internal constant ZERO_ADDRESS = IERC20(0x0000000000000000000000000000000000000000);
    IERC20 internal constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
    IERC20 internal constant MATIC_ADDRESS = IERC20(0x0000000000000000000000000000000000001010);

    function universalTransfer(
        IERC20 token,
        address payable to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (isETH(token)) {
                (bool result, ) = to.call{value: amount, gas: 10000}("");
                require(result, "Failed to transfer ETH");
            } else {
                token.safeTransfer(to, amount);
            }
        }
    }

    function universalApprove(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        require(!isETH(token), "Approve called on ETH");

        if (amount == 0) {
            token.safeApprove(to, 0);
        } else {
            uint256 allowance = token.allowance(address(this), to);
            if (allowance < amount) {
                if (allowance > 0) {
                    token.safeApprove(to, 0);
                }
                token.safeApprove(to, amount);
            }
        }
    }

    function universalBalanceOf(IERC20 token, address account) internal view returns (uint256) {
        if (isETH(token)) {
            return account.balance;
        } else {
            return token.balanceOf(account);
        }
    }

    function isETH(IERC20 token) internal pure returns (bool) {
        return
            address(token) == address(ETH_ADDRESS) ||
            address(token) == address(MATIC_ADDRESS) ||
            address(token) == address(ZERO_ADDRESS);
    }
}

// File: contracts/libraries/EthRejector.sol


pragma solidity ^0.6.12;

abstract contract EthRejector {
    receive() external payable {
        require(msg.sender != tx.origin, "ETH deposit rejected");
    }
}

// File: @openzeppelin/contracts/drafts/IERC20Permit.sol



pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
     * given `owner`'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// File: contracts/libraries/Permitable.sol


pragma solidity ^0.6.12;



/// @title Interface for DAI-style permits
interface IDaiLikePermit {
    function permit(
        address holder,
        address spender,
        uint256 nonce,
        uint256 expiry,
        bool allowed,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

/// @title Base contract with common permit handling logics
contract Permitable {
    function _permit(address token, bytes calldata permit) internal {
        if (permit.length > 0) {
            bool success;
            bytes memory result;
            if (permit.length == 32 * 7) {
                // solhint-disable-next-line avoid-low-level-calls
                (success, result) = token.call(abi.encodePacked(IERC20Permit.permit.selector, permit));
            } else if (permit.length == 32 * 8) {
                // solhint-disable-next-line avoid-low-level-calls
                (success, result) = token.call(abi.encodePacked(IDaiLikePermit.permit.selector, permit));
            } else {
                revert("Wrong permit length");
            }
            if (!success) {
                revert(RevertReasonParser.parse(result, "Permit failed: "));
            }
        }
    }
}

// File: contracts/UniswapV2Exchange.sol



pragma solidity ^0.6.12;




contract UniswapV2Exchange is EthRejector, Permitable {
    uint256 private constant TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
    uint256 private constant WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000;
    uint256 private constant WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000;
    uint256 private constant ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;
    uint256 private constant ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
    uint256 private constant REVERSE_MASK = 0x8000000000000000000000000000000000000000000000000000000000000000;
    uint256 private constant WETH_MASK = 0x4000000000000000000000000000000000000000000000000000000000000000;
    uint256 private constant NUMERATOR_MASK = 0x0000000000000000ffffffff0000000000000000000000000000000000000000;
    uint256 private constant WETH = 0x00000000000000000000000082aF49447D8a07e3bd95BD0d56f35241523fBab1;
    uint256 private constant UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32 =
        0x0902f1ac00000000000000000000000000000000000000000000000000000000;
    uint256 private constant UNISWAP_PAIR_SWAP_CALL_SELECTOR_32 =
        0x022c0d9f00000000000000000000000000000000000000000000000000000000;
    uint256 private constant DENOMINATOR = 1000000000;
    uint256 private constant NUMERATOR_OFFSET = 160;

    function callUniswapToWithPermit(
        IERC20 srcToken,
        uint256 amount,
        uint256 minReturn,
        bytes32[] calldata pools,
        bytes calldata permit,
        address payable recipient
    ) external returns (uint256 returnAmount) {
        _permit(address(srcToken), permit);
        return callUniswapTo(srcToken, amount, minReturn, pools, recipient);
    }

    function callUniswapWithPermit(
        IERC20 srcToken,
        uint256 amount,
        uint256 minReturn,
        bytes32[] calldata pools,
        bytes calldata permit
    ) external returns (uint256 returnAmount) {
        _permit(address(srcToken), permit);
        return callUniswap(srcToken, amount, minReturn, pools);
    }

    function callUniswapTo(
        IERC20 srcToken,
        uint256 amount,
        uint256 minReturn,
        bytes32[] calldata, /* pools */
        address payable recipient
    ) public payable returns (uint256 returnAmount) {
        assembly {
            // solhint-disable-line no-inline-assembly
            function reRevert() {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            function revertWithReason(m, len) {
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, m)
                revert(0, len)
            }

            function swap(emptyPtr, swapAmount, pair, reversed, numerator, dst) -> ret {
                mstore(emptyPtr, UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32)
                if iszero(staticcall(gas(), pair, emptyPtr, 0x4, emptyPtr, 0x40)) {
                    reRevert()
                }

                let reserve0 := mload(emptyPtr)
                let reserve1 := mload(add(emptyPtr, 0x20))
                if reversed {
                    let tmp := reserve0
                    reserve0 := reserve1
                    reserve1 := tmp
                }
                ret := mul(swapAmount, numerator)
                ret := div(mul(ret, reserve1), add(ret, mul(reserve0, DENOMINATOR)))

                mstore(emptyPtr, UNISWAP_PAIR_SWAP_CALL_SELECTOR_32)
                switch reversed
                case 0 {
                    mstore(add(emptyPtr, 0x04), 0)
                    mstore(add(emptyPtr, 0x24), ret)
                }
                default {
                    mstore(add(emptyPtr, 0x04), ret)
                    mstore(add(emptyPtr, 0x24), 0)
                }
                mstore(add(emptyPtr, 0x44), dst)
                mstore(add(emptyPtr, 0x64), 0x80)
                mstore(add(emptyPtr, 0x84), 0)
                if iszero(call(gas(), pair, 0, emptyPtr, 0xa4, 0, 0)) {
                    reRevert()
                }
            }

            function callSwap(emptyPtr, token, srcAmount, swapCaller, reciever) -> ret {
                let poolsOffset := add(calldataload(0x64), 0x4)
                let poolsEndOffset := calldataload(poolsOffset)
                poolsOffset := add(poolsOffset, 0x20)
                poolsEndOffset := add(poolsOffset, mul(0x20, poolsEndOffset))
                let rawPair := calldataload(poolsOffset)
                switch token
                case 0 {
                    if iszero(eq(srcAmount, callvalue())) {
                        revertWithReason(0x00000011696e76616c6964206d73672e76616c75650000000000000000000000, 0x55) // "invalid msg.value"
                    }

                    mstore(emptyPtr, WETH_DEPOSIT_CALL_SELECTOR_32)
                    if iszero(call(gas(), WETH, srcAmount, emptyPtr, 0x4, 0, 0)) {
                        reRevert()
                    }

                    mstore(emptyPtr, ERC20_TRANSFER_CALL_SELECTOR_32)
                    mstore(add(emptyPtr, 0x4), and(rawPair, ADDRESS_MASK))
                    mstore(add(emptyPtr, 0x24), srcAmount)
                    if iszero(call(gas(), WETH, 0, emptyPtr, 0x44, 0, 0)) {
                        reRevert()
                    }
                }
                default {
                    if callvalue() {
                        revertWithReason(0x00000011696e76616c6964206d73672e76616c75650000000000000000000000, 0x55) // "invalid msg.value"
                    }

                    mstore(emptyPtr, TRANSFER_FROM_CALL_SELECTOR_32)
                    mstore(add(emptyPtr, 0x4), swapCaller)
                    mstore(add(emptyPtr, 0x24), and(rawPair, ADDRESS_MASK))
                    mstore(add(emptyPtr, 0x44), srcAmount)
                    if iszero(call(gas(), token, 0, emptyPtr, 0x64, 0, 0)) {
                        reRevert()
                    }
                }

                ret := srcAmount

                for {
                    let i := add(poolsOffset, 0x20)
                } lt(i, poolsEndOffset) {
                    i := add(i, 0x20)
                } {
                    let nextRawPair := calldataload(i)

                    ret := swap(
                        emptyPtr,
                        ret,
                        and(rawPair, ADDRESS_MASK),
                        and(rawPair, REVERSE_MASK),
                        shr(NUMERATOR_OFFSET, and(rawPair, NUMERATOR_MASK)),
                        and(nextRawPair, ADDRESS_MASK)
                    )

                    rawPair := nextRawPair
                }

                switch and(rawPair, WETH_MASK)
                case 0 {
                    ret := swap(
                        emptyPtr,
                        ret,
                        and(rawPair, ADDRESS_MASK),
                        and(rawPair, REVERSE_MASK),
                        shr(NUMERATOR_OFFSET, and(rawPair, NUMERATOR_MASK)),
                        reciever
                    )
                }
                default {
                    ret := swap(
                        emptyPtr,
                        ret,
                        and(rawPair, ADDRESS_MASK),
                        and(rawPair, REVERSE_MASK),
                        shr(NUMERATOR_OFFSET, and(rawPair, NUMERATOR_MASK)),
                        address()
                    )

                    mstore(emptyPtr, WETH_WITHDRAW_CALL_SELECTOR_32)
                    mstore(add(emptyPtr, 0x04), ret)
                    if iszero(call(gas(), WETH, 0, emptyPtr, 0x24, 0, 0)) {
                        reRevert()
                    }

                    if iszero(call(gas(), reciever, ret, 0, 0, 0, 0)) {
                        reRevert()
                    }
                }
            }

            let emptyPtr := mload(0x40)
            mstore(0x40, add(emptyPtr, 0xc0))

            returnAmount := callSwap(emptyPtr, srcToken, amount, caller(), recipient)

            if lt(returnAmount, minReturn) {
                revertWithReason(0x000000164d696e2072657475726e206e6f742072656163686564000000000000, 0x5a) // "Min return not reached"
            }
        }
    }

    function callUniswap(
        IERC20 srcToken,
        uint256 amount,
        uint256 minReturn,
        bytes32[] calldata pools
    ) public payable returns (uint256 returnAmount) {
        return callUniswapTo(srcToken, amount, minReturn, pools, msg.sender);
    }
}

// File: @openzeppelin/contracts/utils/SafeCast.sol



pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such 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.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// File: contracts/interfaces/IUniswapV3.sol


pragma solidity ^0.6.12;

interface IUniswapV3Pool {
    /// @notice Swap token0 for token1, or token1 for token0
    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback
    /// @param recipient The address to receive the output of the swap
    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0
    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this
    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap
    /// @param data Any data to be passed through to the callback
    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive
    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);

    /// @notice The first of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token0() external view returns (address);

    /// @notice The second of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token1() external view returns (address);

    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
    /// @return The fee
    function fee() external view returns (uint24);
}

/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
    /// @dev In the implementation you must pay the pool tokens owed for the swap.
    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

/// @title Callback for IAlgebraPoolActions#swap
/// @notice Any contract that calls IAlgebraPoolActions#swap must implement this interface
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraSwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.
    /// @dev In the implementation you must pay the pool tokens owed for the swap.
    /// The caller of this method must be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.
    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
    /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call
    function algebraSwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

interface IiZiSwapFactory {
    /// @notice Get pool of (tokenX, tokenY, fee), address(0) for not exists.
    /// @param tokenX address of tokenX
    /// @param tokenY address of tokenY
    /// @param fee fee amount
    /// @return address of pool
    function pool(
        address tokenX,
        address tokenY,
        uint24 fee
    ) external view returns (address);
}

interface IiZiSwapCallback {
    /// @notice Called to msg.sender in iZiSwapPool#swapY2X(DesireX) call.
    /// @param x Amount of tokenX trader will acquire
    /// @param y Amount of tokenY trader will pay
    /// @param data Any dadta passed though by the msg.sender via the iZiSwapPool#swapY2X(DesireX) call
    function swapY2XCallback(
        uint256 x,
        uint256 y,
        bytes calldata data
    ) external;

    /// @notice Called to msg.sender in iZiSwapPool#swapX2Y(DesireY) call.
    /// @param x Amount of tokenX trader will pay
    /// @param y Amount of tokenY trader will require
    /// @param data Any dadta passed though by the msg.sender via the iZiSwapPool#swapX2Y(DesireY) call
    function swapX2YCallback(
        uint256 x,
        uint256 y,
        bytes calldata data
    ) external;
}

interface IiZiSwapPool {
    function pointDelta() external view returns (int24);

    /// @notice Point status in the pool.
    /// @param point the point
    /// @return liquidSum the total amount of liquidity that uses the point either as left endpoint or right endpoint
    /// @return liquidDelta how much liquidity changes when the pool price crosses the point from left to right
    /// @return accFeeXOut_128 the fee growth on the other side of the point from the current point in tokenX
    /// @return accFeeYOut_128 the fee growth on the other side of the point from the current point in tokenY
    /// @return isEndpt whether the point is an endpoint of a some miner's liquidity, true if liquidSum > 0
    function points(int24 point)
        external
        view
        returns (
            uint128 liquidSum,
            int128 liquidDelta,
            uint256 accFeeXOut_128,
            uint256 accFeeYOut_128,
            bool isEndpt
        );

    /// @notice Returns 256 packed point (statusVal>0) boolean values. See PointBitmap for more information.
    function pointBitmap(int16 wordPosition) external view returns (uint256);

    /// @notice Swap tokenY for tokenX, given max amount of tokenY user willing to pay.
    /// @param recipient the address to receive tokenX
    /// @param amount the max amount of tokenY user willing to pay
    /// @param highPt the highest point(price) of x/y during swap
    /// @param data any data to be passed through to the callback
    /// @return amountX amount of tokenX payed
    /// @return amountY amount of tokenY acquired
    function swapY2X(
        address recipient,
        uint128 amount,
        int24 highPt,
        bytes calldata data
    ) external returns (uint256 amountX, uint256 amountY);

    /// @notice Swap tokenY for tokenX, given amount of tokenX user desires.
    /// @param recipient the address to receive tokenX
    /// @param desireX the amount of tokenX user desires
    /// @param highPt the highest point(price) of x/y during swap
    /// @param data any data to be passed through to the callback
    /// @return amountX amount of tokenX payed
    /// @return amountY amount of tokenY acquired
    function swapY2XDesireX(
        address recipient,
        uint128 desireX,
        int24 highPt,
        bytes calldata data
    ) external returns (uint256 amountX, uint256 amountY);

    /// @notice Swap tokenX for tokenY, given max amount of tokenX user willing to pay.
    /// @param recipient the address to receive tokenY
    /// @param amount the max amount of tokenX user willing to pay
    /// @param lowPt the lowest point(price) of x/y during swap
    /// @param data any data to be passed through to the callback
    /// @return amountX amount of tokenX acquired
    /// @return amountY amount of tokenY payed
    function swapX2Y(
        address recipient,
        uint128 amount,
        int24 lowPt,
        bytes calldata data
    ) external returns (uint256 amountX, uint256 amountY);

    /// @notice Swap tokenX for tokenY, given amount of tokenY user desires.
    /// @param recipient the address to receive tokenY
    /// @param desireY the amount of tokenY user desires
    /// @param lowPt the lowest point(price) of x/y during swap
    /// @param data any data to be passed through to the callback
    /// @return amountX amount of tokenX acquired
    /// @return amountY amount of tokenY payed
    function swapX2YDesireY(
        address recipient,
        uint128 desireY,
        int24 lowPt,
        bytes calldata data
    ) external returns (uint256 amountX, uint256 amountY);
}

// File: contracts/interfaces/IWETH.sol


pragma solidity ^0.6.12;


/// @title Interface for WETH tokens
interface IWETH is IERC20 {
    function deposit() external payable;

    function withdraw(uint256 amount) external;
}

// File: contracts/UniswapV3Exchange.sol


pragma solidity ^0.6.12;







contract UniswapV3Exchange is EthRejector, Permitable, IUniswapV3SwapCallback {
    using Address for address payable;
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    uint256 private constant _ONE_FOR_ZERO_MASK = 1 << 255;
    uint256 private constant _WETH_WRAP_MASK = 1 << 254;
    uint256 private constant _WETH_UNWRAP_MASK = 1 << 253;
    bytes32 private constant _POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
    bytes32 private constant _FF_FACTORY = 0xff1F98431c8aD98523631AE4a59f267346ea31F9840000000000000000000000;
    bytes32 private constant _SELECTORS = 0x0dfe1681d21220a7ddca3f430000000000000000000000000000000000000000;
    uint256 private constant _ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
    uint160 private constant _MIN_SQRT_RATIO = 4295128739 + 1;
    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
    uint160 private constant _MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342 - 1;
    /// @dev Change for different chains
    address private constant _WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;

    /// @notice Same as `uniswapV3SwapTo` but calls permit first,
    /// allowing to approve token spending and make a swap in one transaction.
    /// @param recipient Address that will receive swap funds
    /// @param srcToken Source token
    /// @param amount Amount of source tokens to swap
    /// @param minReturn Minimal allowed returnAmount to make transaction commit
    /// @param pools Pools chain used for swaps. Pools src and dst tokens should match to make swap happen
    /// @param permit Should contain valid permit that can be used in `IERC20Permit.permit` calls.
    /// See tests for examples
    function uniswapV3SwapToWithPermit(
        address payable recipient,
        IERC20 srcToken,
        uint256 amount,
        uint256 minReturn,
        uint256[] calldata pools,
        bytes calldata permit
    ) external returns (uint256 returnAmount) {
        _permit(address(srcToken), permit);
        return uniswapV3SwapTo(recipient, amount, minReturn, pools);
    }

    /// @notice Same as `uniswapV3SwapTo` but uses `msg.sender` as recipient
    /// @param amount Amount of source tokens to swap
    /// @param minReturn Minimal allowed returnAmount to make transaction commit
    /// @param pools Pools chain used for swaps. Pools src and dst tokens should match to make swap happen
    function uniswapV3Swap(
        uint256 amount,
        uint256 minReturn,
        uint256[] calldata pools
    ) external payable returns (uint256 returnAmount) {
        return uniswapV3SwapTo(msg.sender, amount, minReturn, pools);
    }

    /// @notice Performs swap using Uniswap V3 exchange. Wraps and unwraps ETH if required.
    /// Sending non-zero `msg.value` for anything but ETH swaps is prohibited
    /// @param recipient Address that will receive swap funds
    /// @param amount Amount of source tokens to swap
    /// @param minReturn Minimal allowed returnAmount to make transaction commit
    /// @param pools Pools chain used for swaps. Pools src and dst tokens should match to make swap happen
    function uniswapV3SwapTo(
        address payable recipient,
        uint256 amount,
        uint256 minReturn,
        uint256[] calldata pools
    ) public payable returns (uint256 returnAmount) {
        uint256 len = pools.length;
        require(len > 0, "UniswapV3: empty pools");
        uint256 lastIndex = len - 1;
        returnAmount = amount;
        bool wrapWeth = pools[0] & _WETH_WRAP_MASK > 0;
        bool unwrapWeth = pools[lastIndex] & _WETH_UNWRAP_MASK > 0;
        if (wrapWeth) {
            require(msg.value == amount, "UniswapV3: wrong msg.value");
            IWETH(_WETH).deposit{value: amount}();
        } else {
            require(msg.value == 0, "UniswapV3: msg.value should be 0");
        }
        if (len > 1) {
            returnAmount = _makeSwap(address(this), wrapWeth ? address(this) : msg.sender, pools[0], returnAmount);

            for (uint256 i = 1; i < lastIndex; i++) {
                returnAmount = _makeSwap(address(this), address(this), pools[i], returnAmount);
            }
            returnAmount = _makeSwap(unwrapWeth ? address(this) : recipient, address(this), pools[lastIndex], returnAmount);
        } else {
            returnAmount = _makeSwap(
                unwrapWeth ? address(this) : recipient,
                wrapWeth ? address(this) : msg.sender,
                pools[0],
                returnAmount
            );
        }

        require(returnAmount >= minReturn, "UniswapV3: min return");

        if (unwrapWeth) {
            IWETH(_WETH).withdraw(returnAmount);
            recipient.sendValue(returnAmount);
        }
    }

    /// @inheritdoc IUniswapV3SwapCallback
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata /* data */
    ) external override {
        IERC20 token0;
        IERC20 token1;
        bytes32 ffFactoryAddress = _FF_FACTORY;
        bytes32 poolInitCodeHash = _POOL_INIT_CODE_HASH;
        address payer;

        assembly {
            // solhint-disable-line no-inline-assembly
            function reRevert() {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            function revertWithReason(m, len) {
                mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, m)
                revert(0, len)
            }

            let emptyPtr := mload(0x40)
            let resultPtr := add(emptyPtr, 0x20)
            mstore(emptyPtr, _SELECTORS)

            if iszero(staticcall(gas(), caller(), emptyPtr, 0x4, resultPtr, 0x20)) {
                reRevert()
            }
            token0 := mload(resultPtr)
            if iszero(staticcall(gas(), caller(), add(emptyPtr, 0x4), 0x4, resultPtr, 0x20)) {
                reRevert()
            }
            token1 := mload(resultPtr)
            if iszero(staticcall(gas(), caller(), add(emptyPtr, 0x8), 0x4, resultPtr, 0x20)) {
                reRevert()
            }
            let fee := mload(resultPtr)

            let p := emptyPtr
            mstore(p, ffFactoryAddress)
            p := add(p, 21)
            // Compute the inner hash in-place
            mstore(p, token0)
            mstore(add(p, 32), token1)
            mstore(add(p, 64), fee)
            mstore(p, keccak256(p, 96))
            p := add(p, 32)
            mstore(p, poolInitCodeHash)
            let pool := and(keccak256(emptyPtr, 85), _ADDRESS_MASK)

            if iszero(eq(pool, caller())) {
                revertWithReason(0x00000010554e495633523a2062616420706f6f6c000000000000000000000000, 0x54) // UniswapV3: bad pool
            }

            calldatacopy(emptyPtr, 0x84, 0x20)
            payer := mload(emptyPtr)
        }

        if (amount0Delta > 0) {
            if (payer == address(this)) {
                token0.safeTransfer(msg.sender, uint256(amount0Delta));
            } else {
                token0.safeTransferFrom(payer, msg.sender, uint256(amount0Delta));
            }
        }
        if (amount1Delta > 0) {
            if (payer == address(this)) {
                token1.safeTransfer(msg.sender, uint256(amount1Delta));
            } else {
                token1.safeTransferFrom(payer, msg.sender, uint256(amount1Delta));
            }
        }
    }

    function _makeSwap(
        address recipient,
        address payer,
        uint256 pool,
        uint256 amount
    ) private returns (uint256) {
        bool zeroForOne = pool & _ONE_FOR_ZERO_MASK == 0;
        if (zeroForOne) {
            (, int256 amount1) = IUniswapV3Pool(pool).swap(
                recipient,
                zeroForOne,
                SafeCast.toInt256(amount),
                _MIN_SQRT_RATIO,
                abi.encode(payer)
            );
            return SafeCast.toUint256(-amount1);
        } else {
            (int256 amount0, ) = IUniswapV3Pool(pool).swap(
                recipient,
                zeroForOne,
                SafeCast.toInt256(amount),
                _MAX_SQRT_RATIO,
                abi.encode(payer)
            );
            return SafeCast.toUint256(-amount0);
        }
    }
}

// File: contracts/OpenOceanExchange.sol



pragma solidity ^0.6.12;










contract OpenOceanExchange is OwnableUpgradeable, PausableUpgradeable, UniswapV2Exchange, UniswapV3Exchange {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using UniversalERC20 for IERC20;

    uint256 private constant _PARTIAL_FILL = 0x01;
    uint256 private constant _SHOULD_CLAIM = 0x02;

    struct SwapDescription {
        IERC20 srcToken;
        IERC20 dstToken;
        address srcReceiver;
        address dstReceiver;
        uint256 amount;
        uint256 minReturnAmount;
        uint256 guaranteedAmount;
        uint256 flags;
        address referrer;
        bytes permit;
    }

    event Swapped(
        address indexed sender,
        IERC20 indexed srcToken,
        IERC20 indexed dstToken,
        address dstReceiver,
        uint256 amount,
        uint256 spentAmount,
        uint256 returnAmount,
        uint256 minReturnAmount,
        uint256 guaranteedAmount,
        address referrer
    );

    function initialize() public initializer {
        OwnableUpgradeable.__Ownable_init();
        PausableUpgradeable.__Pausable_init();
    }

    function swap(
        IOpenOceanCaller caller,
        SwapDescription calldata desc,
        IOpenOceanCaller.CallDescription[] calldata calls
    ) external payable whenNotPaused returns (uint256 returnAmount) {
        require(desc.minReturnAmount > 0, "Min return should not be 0");
        require(calls.length > 0, "Call data should exist");

        uint256 flags = desc.flags;
        IERC20 srcToken = desc.srcToken;
        IERC20 dstToken = desc.dstToken;

        require(msg.value == (srcToken.isETH() ? desc.amount : 0), "Invalid msg.value");

        if (flags & _SHOULD_CLAIM != 0) {
            require(!srcToken.isETH(), "Claim token is ETH");
            _claim(srcToken, desc.srcReceiver, desc.amount, desc.permit);
        }

        address dstReceiver = (desc.dstReceiver == address(0)) ? msg.sender : desc.dstReceiver;
        uint256 initialSrcBalance = (flags & _PARTIAL_FILL != 0) ? srcToken.universalBalanceOf(msg.sender) : 0;
        uint256 initialDstBalance = dstToken.universalBalanceOf(dstReceiver);

        caller.makeCalls{value: msg.value}(calls);

        uint256 spentAmount = desc.amount;
        returnAmount = dstToken.universalBalanceOf(dstReceiver).sub(initialDstBalance);

        if (flags & _PARTIAL_FILL != 0) {
            spentAmount = initialSrcBalance.add(desc.amount).sub(srcToken.universalBalanceOf(msg.sender));
            require(returnAmount.mul(desc.amount) >= desc.minReturnAmount.mul(spentAmount), "Return amount is not enough");
        } else {
            require(returnAmount >= desc.minReturnAmount, "Return amount is not enough");
        }

        _emitSwapped(desc, srcToken, dstToken, dstReceiver, spentAmount, returnAmount);
    }

    function _emitSwapped(
        SwapDescription calldata desc,
        IERC20 srcToken,
        IERC20 dstToken,
        address dstReceiver,
        uint256 spentAmount,
        uint256 returnAmount
    ) private {
        emit Swapped(
            msg.sender,
            srcToken,
            dstToken,
            dstReceiver,
            desc.amount,
            spentAmount,
            returnAmount,
            desc.minReturnAmount,
            desc.guaranteedAmount,
            desc.referrer
        );
    }

    function _claim(
        IERC20 token,
        address dst,
        uint256 amount,
        bytes calldata permit
    ) private {
        _permit(address(token), permit);
        token.safeTransferFrom(msg.sender, dst, amount);
    }

    function rescueFunds(IERC20 token, uint256 amount) external onlyOwner {
        token.universalTransfer(msg.sender, amount);
    }

    function pause() external onlyOwner {
        _pause();
    }
}

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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"srcToken","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"dstToken","type":"address"},{"indexed":false,"internalType":"address","name":"dstReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"spentAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"returnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minReturnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"guaranteedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"referrer","type":"address"}],"name":"Swapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"bytes32[]","name":"pools","type":"bytes32[]"}],"name":"callUniswap","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"address payable","name":"recipient","type":"address"}],"name":"callUniswapTo","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"bytes32[]","name":"pools","type":"bytes32[]"},{"internalType":"bytes","name":"permit","type":"bytes"},{"internalType":"address payable","name":"recipient","type":"address"}],"name":"callUniswapToWithPermit","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"bytes32[]","name":"pools","type":"bytes32[]"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"callUniswapWithPermit","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOpenOceanCaller","name":"caller","type":"address"},{"components":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"contract IERC20","name":"dstToken","type":"address"},{"internalType":"address","name":"srcReceiver","type":"address"},{"internalType":"address","name":"dstReceiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturnAmount","type":"uint256"},{"internalType":"uint256","name":"guaranteedAmount","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"bytes","name":"permit","type":"bytes"}],"internalType":"struct OpenOceanExchange.SwapDescription","name":"desc","type":"tuple"},{"components":[{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IOpenOceanCaller.CallDescription[]","name":"calls","type":"tuple[]"}],"name":"swap","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"pools","type":"uint256[]"}],"name":"uniswapV3Swap","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"pools","type":"uint256[]"}],"name":"uniswapV3SwapTo","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"pools","type":"uint256[]"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"uniswapV3SwapToWithPermit","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50612f07806100206000396000f3fe6080604052600436106100f75760003560e01c80638980041a1161008a578063d57360fc11610059578063d57360fc14610271578063e449022e14610291578063f2fde38b146102a4578063fa461e33146102c457610127565b80638980041a146102165780638da5cb5b1461022957806390411a321461024b578063bc80f1a81461025e57610127565b8063715018a6116100c6578063715018a6146101b757806378e3214f146101cc5780638129fc1c146101ec5780638456cb591461020157610127565b806322dca3d71461012c5780632521b930146101625780635c975abb146101825780636b58f2f0146101a457610127565b3661012757333214156101255760405162461bcd60e51b815260040161011c90612968565b60405180910390fd5b005b600080fd5b34801561013857600080fd5b5061014c610147366004612369565b6102e4565b6040516101599190612698565b60405180910390f35b34801561016e57600080fd5b5061014c61017d366004612108565b61030c565b34801561018e57600080fd5b50610197610326565b604051610159919061283a565b61014c6101b236600461225e565b61032f565b3480156101c357600080fd5b50610125610692565b3480156101d857600080fd5b506101256101e7366004612233565b61071b565b3480156101f857600080fd5b50610125610772565b34801561020d57600080fd5b50610125610805565b61014c6102243660046121ac565b61084e565b34801561023557600080fd5b5061023e61085e565b60405161015991906126a1565b61014c61025936600461240e565b61086d565b61014c61026c3660046121ac565b610b50565b34801561027d57600080fd5b5061014c61028c3660046122d7565b610db3565b61014c61029f36600461250a565b610dd9565b3480156102b057600080fd5b506101256102bf3660046120ec565b610df3565b3480156102d057600080fd5b506101256102df3660046124ae565b610eb4565b60006102f189858561105a565b6102ff89898989898761032f565b9998505050505050505050565b600061031988848461105a565b6102ff8988888888610b50565b60655460ff1690565b6000610648565b3d6000803e3d6000fd5b62461bcd60e51b600052600160e51b60205280604052816000fd5b6000630240bc6b60e21b8252604082600484875afa61037c5761037c610336565b81516020830151861561038b57905b63022c0d9f60e01b8452878502633b9aca0092909202820191020490508480156103c157816004840152600060248401526103cf565b600060048401528160248401525b50866044830152608060648301526000608483015260008060a4846000885af16103fb576103fb610336565b9695505050505050565b600060643560248181019160048101356020020101813585801561048a5734156104495761044960557111696e76616c6964206d73672e76616c756560581b610340565b6323b872dd60e01b86528860048701526001600160a01b038216602487015287604487015260008060648860008b5af161048557610485610336565b61052f565b3488146104b1576104b160557111696e76616c6964206d73672e76616c756560581b610340565b630d0e30db60e41b86526000806004888b7382af49447d8a07e3bd95bd0d56f35241523fbab15af16104e5576104e5610336565b63a9059cbb60e01b86526001600160a01b038216600487015287602487015260008060448860007382af49447d8a07e3bd95bd0d56f35241523fbab15af161052f5761052f610336565b50869350602083015b828110156105805780356105746001600160a01b03821663ffffffff60a01b851660a01c600160ff1b86166001600160a01b0387168a8c61035b565b95509150602001610538565b50600160fe1b8116801561060f576105b73063ffffffff60a01b841660a01c600160ff1b85166001600160a01b038616898b61035b565b9450632e1a7d4d60e01b865284600487015260008060248860007382af49447d8a07e3bd95bd0d56f35241523fbab15af16105f4576105f4610336565b600080600080888e5af161060a5761060a610336565b61063b565b6106388a63ffffffff60a01b841660a01c600160ff1b85166001600160a01b038616898b61035b565b94505b5050505095945050505050565b60405160c0810160405261065f8333898b85610405565b915050848110156103fb576103fb605a7c164d696e2072657475726e206e6f742072656163686564000000000000610340565b61069a61119b565b6001600160a01b03166106ab61085e565b6001600160a01b0316146106d15760405162461bcd60e51b815260040161011c90612c5d565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b61072361119b565b6001600160a01b031661073461085e565b6001600160a01b03161461075a5760405162461bcd60e51b815260040161011c90612c5d565b61076e6001600160a01b038316338361119f565b5050565b600054610100900460ff168061078b575061078b61124e565b80610799575060005460ff16155b6107b55760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156107e0576000805460ff1961ff0019909116610100171660011790555b6107e861125f565b6107f06112dd565b8015610802576000805461ff00191690555b50565b61080d61119b565b6001600160a01b031661081e61085e565b6001600160a01b0316146108445760405162461bcd60e51b815260040161011c90612c5d565b61084c61135b565b565b60006103fb86868686863361032f565b6033546001600160a01b031690565b6000610877610326565b156108945760405162461bcd60e51b815260040161011c90612ad2565b60008460a00135116108b85760405162461bcd60e51b815260040161011c90612be5565b816108d55760405162461bcd60e51b815260040161011c90612e1c565b60e084013560006108e960208701876120ec565b905060006108fd60408801602089016120ec565b9050610911826001600160a01b03166113cd565b61091c576000610922565b86608001355b34146109405760405162461bcd60e51b815260040161011c90612996565b60028316156109a45761095b826001600160a01b03166113cd565b156109785760405162461bcd60e51b815260040161011c90612858565b6109a48261098c60608a0160408b016120ec565b60808a013561099f6101208c018c612e4c565b61141c565b6000806109b760808a0160608b016120ec565b6001600160a01b0316146109da576109d56080890160608a016120ec565b6109dc565b335b90506000600185166109ef576000610a02565b610a026001600160a01b0385163361143c565b90506000610a196001600160a01b0385168461143c565b90508a6001600160a01b031663a8920d2b348b8b6040518463ffffffff1660e01b8152600401610a4a92919061276a565b6000604051808303818588803b158015610a6357600080fd5b505af1158015610a77573d6000803e3d6000fd5b5050505060808b01359050610a9f82610a996001600160a01b0388168761143c565b906114e0565b97506001871615610b0f57610ace610ac06001600160a01b0388163361143c565b610a998560808f0135611508565b9050610ade60a08c01358261152d565b610aec8960808e013561152d565b1015610b0a5760405162461bcd60e51b815260040161011c90612bae565b610b33565b8a60a00135881015610b335760405162461bcd60e51b815260040161011c90612bae565b610b418b878787858d611567565b50505050505050949350505050565b60008180610b705760405162461bcd60e51b815260040161011c90612938565b8591506000198101600080600160fe1b87878381610b8a57fe5b9050602002013516119050600080600160fd1b888886818110610ba957fe5b90506020020135161190508115610c4657883414610bd95760405162461bcd60e51b815260040161011c90612901565b7382af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c2857600080fd5b505af1158015610c3c573d6000803e3d6000fd5b5050505050610c64565b3415610c645760405162461bcd60e51b815260040161011c90612d9d565b6001841115610cf257610c983083610c7c5733610c7e565b305b89896000818110610c8b57fe5b90506020020135886115ef565b945060015b83811015610ccd57610cc330308a8a85818110610cb657fe5b90506020020135896115ef565b9550600101610c9d565b50610ceb81610cdc578a610cde565b305b30898987818110610c8b57fe5b9450610d10565b610d0d81610d00578a610d02565b305b83610c7c5733610c7e565b94505b87851015610d305760405162461bcd60e51b815260040161011c90612afc565b801561063b57604051632e1a7d4d60e01b81527382af49447d8a07e3bd95bd0d56f35241523fbab190632e1a7d4d90610d6d908890600401612698565b600060405180830381600087803b158015610d8757600080fd5b505af1158015610d9b573d6000803e3d6000fd5b5061063b925050506001600160a01b038b168661179b565b6000610dc088848461105a565b610dcd888888888861084e565b98975050505050505050565b6000610de83386868686610b50565b90505b949350505050565b610dfb61119b565b6001600160a01b0316610e0c61085e565b6001600160a01b031614610e325760405162461bcd60e51b815260040161011c90612c5d565b6001600160a01b038116610e585760405162461bcd60e51b815260040161011c90612884565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6000807fff1f98431c8ad98523631ae4a59f267346ea31f98400000000000000000000007fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5482604051602081016b0dfe1681d21220a7ddca3f4360a01b8252602081600484335afa610f2857610f28610336565b805196506020816004808501335afa610f4357610f43610336565b80519550602081600460088501335afa610f5f57610f5f610336565b5184825260158201878152603583018781526055808501939093526060822090915284905281206001600160a01b0316338114610fb557610fb560547004155392558cd48e88189859081c1bdbdb60621b610340565b506020608482375190506000891315611007576001600160a01b038116301415610ff257610fed6001600160a01b038616338b611837565b611007565b6110076001600160a01b03861682338c61188d565b600088131561104f576001600160a01b03811630141561103a576110356001600160a01b038516338a611837565b61104f565b61104f6001600160a01b03851682338b61188d565b505050505050505050565b8015611196576000606060e08314156110fb576040516001600160a01b038616906110949063d505accf60e01b90879087906020016125a4565b60408051601f19818403018152908290526110ae916125c8565b6000604051808303816000865af19150503d80600081146110eb576040519150601f19603f3d011682016040523d82523d6000602084013e6110f0565b606091505b509092509050611144565b61010083141561112c576040516001600160a01b03861690611094906323f2ebc360e21b90879087906020016125a4565b60405162461bcd60e51b815260040161011c90612cc2565b816111935761117a816040518060400160405280600f81526020016e02832b936b4ba103330b4b632b21d1608d1b8152506118b4565b60405162461bcd60e51b815260040161011c9190612845565b50505b505050565b3390565b8015611196576111ae836113cd565b1561123a576000826001600160a01b031682612710906040516111d090612695565b600060405180830381858888f193505050503d806000811461120e576040519150601f19603f3d011682016040523d82523d6000602084013e611213565b606091505b50509050806112345760405162461bcd60e51b815260040161011c90612c92565b50611196565b6111966001600160a01b0384168383611837565b600061125930611ac2565b15905090565b600054610100900460ff1680611278575061127861124e565b80611286575060005460ff16155b6112a25760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156112cd576000805460ff1961ff0019909116610100171660011790555b6112d5611ac8565b6107f0611b49565b600054610100900460ff16806112f657506112f661124e565b80611304575060005460ff16155b6113205760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff1615801561134b576000805460ff1961ff0019909116610100171660011790555b611353611ac8565b6107f0611c23565b611363610326565b156113805760405162461bcd60e51b815260040161011c90612ad2565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586113b661119b565b6040516113c391906126a1565b60405180910390a1565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148061140457506001600160a01b038216611010145b8061141657506001600160a01b038216155b92915050565b61142785838361105a565b6111936001600160a01b03861633868661188d565b6000611447836113cd565b1561145d57506001600160a01b03811631611416565b6040516370a0823160e01b81526001600160a01b038416906370a08231906114899085906004016126a1565b60206040518083038186803b1580156114a157600080fd5b505afa1580156114b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d991906124f2565b9392505050565b6000828211156115025760405162461bcd60e51b815260040161011c906129c1565b50900390565b6000828201838110156114d95760405162461bcd60e51b815260040161011c906128ca565b60008261153c57506000611416565b8282028284828161154957fe5b04146114d95760405162461bcd60e51b815260040161011c90612c1c565b836001600160a01b0316856001600160a01b0316336001600160a01b03167f76af224a143865a50b41496e1a73622698692c565c1214bc862f18e22d829c5e868a6080013587878d60a001358e60c001358f6101000160208101906115cc91906120ec565b6040516115df979695949392919061272d565b60405180910390a4505050505050565b6000600160ff1b83161580156116ca576000846001600160a01b031663128acb08888461161b88611caf565b6401000276a48b60405160200161163291906126a1565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016116619594939291906126d9565b6040805180830381600087803b15801561167a57600080fd5b505af115801561168e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b2919061248b565b9150506116c181600003611cd8565b92505050610deb565b6000846001600160a01b031663128acb0888846116e688611caf565b73fffd8963efd1fc6a506488495d951d5263988d258b60405160200161170c91906126a1565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161173b9594939291906126d9565b6040805180830381600087803b15801561175457600080fd5b505af1158015611768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178c919061248b565b5090506116c181600003611cd8565b804710156117bb5760405162461bcd60e51b815260040161011c90612a55565b6000826001600160a01b0316826040516117d490612695565b60006040518083038185875af1925050503d8060008114611811576040519150601f19603f3d011682016040523d82523d6000602084013e611816565b606091505b50509050806111965760405162461bcd60e51b815260040161011c906129f8565b6111968363a9059cbb60e01b8484604051602401611856929190612714565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611cfa565b6118ae846323b872dd60e01b858585604051602401611856939291906126b5565b50505050565b606060448351101580156118e75750826000815181106118d057fe5b6020910101516001600160f81b031916600160fb1b145b80156119125750826001815181106118fb57fe5b6020910101516001600160f81b03191660c360f81b145b801561193d57508260028151811061192657fe5b6020910101516001600160f81b031916607960f81b145b801561196857508260038151811061195157fe5b6020910101516001600160f81b031916600560fd1b145b156119c457606060448401905080516044018451101561199a5760405162461bcd60e51b815260040161011c90612cef565b82816040516020016119ad929190612660565b604051602081830303815290604052915050611416565b825160241480156119f45750826000815181106119dd57fe5b6020910101516001600160f81b031916602760f91b145b8015611a1f575082600181518110611a0857fe5b6020910101516001600160f81b031916600960fb1b145b8015611a4a575082600281518110611a3357fe5b6020910101516001600160f81b031916607b60f81b145b8015611a75575082600381518110611a5e57fe5b6020910101516001600160f81b031916607160f81b145b15611a9a57602483015182611a8982611d89565b6040516020016119ad929190612611565b81604051602001611aab91906125e4565b604051602081830303815290604052905092915050565b3b151590565b600054610100900460ff1680611ae15750611ae161124e565b80611aef575060005460ff16155b611b0b5760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156107f0576000805460ff1961ff0019909116610100171660011790558015610802576000805461ff001916905550565b600054610100900460ff1680611b625750611b6261124e565b80611b70575060005460ff16155b611b8c5760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff16158015611bb7576000805460ff1961ff0019909116610100171660011790555b6000611bc161119b565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015610802576000805461ff001916905550565b600054610100900460ff1680611c3c5750611c3c61124e565b80611c4a575060005460ff16155b611c665760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff16158015611c91576000805460ff1961ff0019909116610100171660011790555b6065805460ff191690558015610802576000805461ff001916905550565b6000600160ff1b8210611cd45760405162461bcd60e51b815260040161011c90612d55565b5090565b600080821215611cd45760405162461bcd60e51b815260040161011c90612b2b565b6060611d4f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611db39092919063ffffffff16565b8051909150156111965780806020019051810190611d6d9190612213565b6111965760405162461bcd60e51b815260040161011c90612dd2565b606061141682604051602001611d9f9190612698565b604051602081830303815290604052611dc2565b6060610deb8484600085611f6b565b6060806040518060400160405280601081526020016f181899199a1a9b1b9c1cb0b131b232b360811b8152509050606083516002026002016001600160401b0381118015611e0f57600080fd5b506040519080825280601f01601f191660200182016040528015611e3a576020820181803683370190505b509050600360fc1b81600081518110611e4f57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611e7857fe5b60200101906001600160f81b031916908160001a90535060005b8451811015611f6357826004868381518110611eaa57fe5b016020015182516001600160f81b031990911690911c60f81c908110611ecc57fe5b602001015160f81c60f81b828260020260020181518110611ee957fe5b60200101906001600160f81b031916908160001a90535082858281518110611f0d57fe5b602091010151815160f89190911c600f16908110611f2757fe5b602001015160f81c60f81b828260020260030181518110611f4457fe5b60200101906001600160f81b031916908160001a905350600101611e92565b509392505050565b606082471015611f8d5760405162461bcd60e51b815260040161011c90612a8c565b611f9685611ac2565b611fb25760405162461bcd60e51b815260040161011c90612d1e565b60006060866001600160a01b03168587604051611fcf91906125c8565b60006040518083038185875af1925050503d806000811461200c576040519150601f19603f3d011682016040523d82523d6000602084013e612011565b606091505b509150915061202182828661202c565b979650505050505050565b6060831561203b5750816114d9565b82511561204b5782518084602001fd5b8160405162461bcd60e51b815260040161011c9190612845565b60008083601f840112612076578182fd5b5081356001600160401b0381111561208c578182fd5b60208301915083602080830285010111156120a657600080fd5b9250929050565b60008083601f8401126120be578182fd5b5081356001600160401b038111156120d4578182fd5b6020830191508360208285010111156120a657600080fd5b6000602082840312156120fd578081fd5b81356114d981612ebc565b60008060008060008060008060c0898b031215612123578384fd5b883561212e81612ebc565b9750602089013561213e81612ebc565b9650604089013595506060890135945060808901356001600160401b0380821115612167578586fd5b6121738c838d01612065565b909650945060a08b013591508082111561218b578384fd5b506121988b828c016120ad565b999c989b5096995094979396929594505050565b6000806000806000608086880312156121c3578081fd5b85356121ce81612ebc565b9450602086013593506040860135925060608601356001600160401b038111156121f6578182fd5b61220288828901612065565b969995985093965092949392505050565b600060208284031215612224578081fd5b815180151581146114d9578182fd5b60008060408385031215612245578182fd5b823561225081612ebc565b946020939093013593505050565b60008060008060008060a08789031215612276578182fd5b863561228181612ebc565b9550602087013594506040870135935060608701356001600160401b038111156122a9578283fd5b6122b589828a01612065565b90945092505060808701356122c981612ebc565b809150509295509295509295565b600080600080600080600060a0888a0312156122f1578081fd5b87356122fc81612ebc565b9650602088013595506040880135945060608801356001600160401b0380821115612325578283fd5b6123318b838c01612065565b909650945060808a0135915080821115612349578283fd5b506123568a828b016120ad565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215612384578182fd5b883561238f81612ebc565b9750602089013596506040890135955060608901356001600160401b03808211156123b8578384fd5b6123c48c838d01612065565b909750955060808b01359150808211156123dc578384fd5b506123e98b828c016120ad565b90945092505060a08901356123fd81612ebc565b809150509295985092959890939650565b60008060008060608587031215612423578182fd5b843561242e81612ebc565b935060208501356001600160401b0380821115612449578384fd5b90860190610140828903121561245d578384fd5b90935060408601359080821115612472578384fd5b5061247f87828801612065565b95989497509550505050565b6000806040838503121561249d578182fd5b505080516020909101519092909150565b600080600080606085870312156124c3578182fd5b843593506020850135925060408501356001600160401b038111156124e6578283fd5b61247f878288016120ad565b600060208284031215612503578081fd5b5051919050565b6000806000806060858703121561251f578182fd5b843593506020850135925060408501356001600160401b03811115612542578283fd5b61247f87828801612065565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452612590816020860160208601612e90565b601f01601f19169290920160200192915050565b6001600160e01b031984168152600082846004840137910160040190815292915050565b600082516125da818460208701612e90565b9190910192915050565b600082516125f6818460208701612e90565b68556e6b6e6f776e282960b81b920191825250600901919050565b60008351612623818460208801612e90565b650a0c2dcd2c6560d31b9083019081528351612646816006840160208801612e90565b602960f81b60069290910191820152600701949350505050565b60008351612672818460208801612e90565b6508ae4e4dee4560d31b9083019081528351612646816006840160208801612e90565b90565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0386811682528515156020830152604082018590528316606082015260a06080820181905260009061202190830184612578565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039788168152602081019690965260408601949094526060850192909252608084015260a083015290911660c082015260e00190565b602080825281810183905260009060408084018583028501820187855b8881101561282c57878303603f190184528135368b9003607e190181126127ac578788fd5b8a018035845286810135878501528581013586850152608060608083013536849003601e190181126127dc578a8bfd5b830180356001600160401b038111156127f3578b8cfd5b803603851315612801578b8cfd5b8383890152612815848901828d850161254e565b988b01989750505093880193505050600101612787565b509098975050505050505050565b901515815260200190565b6000602082526114d96020830184612578565b602080825260129082015271086d8c2d2da40e8ded6cadc40d2e6408aa8960731b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601a908201527f556e697377617056333a2077726f6e67206d73672e76616c7565000000000000604082015260600190565b602080825260169082015275556e697377617056333a20656d70747920706f6f6c7360501b604082015260600190565b6020808252601490820152731155120819195c1bdcda5d081c995a9958dd195960621b604082015260600190565b602080825260119082015270496e76616c6964206d73672e76616c756560781b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252603a908201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260408201527f6563697069656e74206d61792068617665207265766572746564000000000000606082015260800190565b6020808252601d908201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601590820152742ab734b9bbb0b82b199d1036b4b7103932ba3ab93760591b604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601b908201527f52657475726e20616d6f756e74206973206e6f7420656e6f7567680000000000604082015260600190565b6020808252601a908201527f4d696e2072657475726e2073686f756c64206e6f742062652030000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526016908201527508cc2d2d8cac840e8de40e8e4c2dce6cccae4408aa8960531b604082015260600190565b6020808252601390820152720aee4dedcce40e0cae4dad2e840d8cadccee8d606b1b604082015260600190565b60208082526015908201527424b73b30b634b2103932bb32b93a103932b0b9b7b760591b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b6020808252818101527f556e697377617056333a206d73672e76616c75652073686f756c642062652030604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526016908201527510d85b1b0819185d18481cda1bdd5b1908195e1a5cdd60521b604082015260600190565b6000808335601e19843603018112612e62578283fd5b8301803591506001600160401b03821115612e7b578283fd5b6020019150368190038213156120a657600080fd5b60005b83811015612eab578181015183820152602001612e93565b838111156118ae5750506000910152565b6001600160a01b038116811461080257600080fdfea2646970667358221220876629cfe1567383e5c95b259a804464609b178622e5f5d989ab082a14a156c164736f6c634300060c0033

Deployed Bytecode

0x6080604052600436106100f75760003560e01c80638980041a1161008a578063d57360fc11610059578063d57360fc14610271578063e449022e14610291578063f2fde38b146102a4578063fa461e33146102c457610127565b80638980041a146102165780638da5cb5b1461022957806390411a321461024b578063bc80f1a81461025e57610127565b8063715018a6116100c6578063715018a6146101b757806378e3214f146101cc5780638129fc1c146101ec5780638456cb591461020157610127565b806322dca3d71461012c5780632521b930146101625780635c975abb146101825780636b58f2f0146101a457610127565b3661012757333214156101255760405162461bcd60e51b815260040161011c90612968565b60405180910390fd5b005b600080fd5b34801561013857600080fd5b5061014c610147366004612369565b6102e4565b6040516101599190612698565b60405180910390f35b34801561016e57600080fd5b5061014c61017d366004612108565b61030c565b34801561018e57600080fd5b50610197610326565b604051610159919061283a565b61014c6101b236600461225e565b61032f565b3480156101c357600080fd5b50610125610692565b3480156101d857600080fd5b506101256101e7366004612233565b61071b565b3480156101f857600080fd5b50610125610772565b34801561020d57600080fd5b50610125610805565b61014c6102243660046121ac565b61084e565b34801561023557600080fd5b5061023e61085e565b60405161015991906126a1565b61014c61025936600461240e565b61086d565b61014c61026c3660046121ac565b610b50565b34801561027d57600080fd5b5061014c61028c3660046122d7565b610db3565b61014c61029f36600461250a565b610dd9565b3480156102b057600080fd5b506101256102bf3660046120ec565b610df3565b3480156102d057600080fd5b506101256102df3660046124ae565b610eb4565b60006102f189858561105a565b6102ff89898989898761032f565b9998505050505050505050565b600061031988848461105a565b6102ff8988888888610b50565b60655460ff1690565b6000610648565b3d6000803e3d6000fd5b62461bcd60e51b600052600160e51b60205280604052816000fd5b6000630240bc6b60e21b8252604082600484875afa61037c5761037c610336565b81516020830151861561038b57905b63022c0d9f60e01b8452878502633b9aca0092909202820191020490508480156103c157816004840152600060248401526103cf565b600060048401528160248401525b50866044830152608060648301526000608483015260008060a4846000885af16103fb576103fb610336565b9695505050505050565b600060643560248181019160048101356020020101813585801561048a5734156104495761044960557111696e76616c6964206d73672e76616c756560581b610340565b6323b872dd60e01b86528860048701526001600160a01b038216602487015287604487015260008060648860008b5af161048557610485610336565b61052f565b3488146104b1576104b160557111696e76616c6964206d73672e76616c756560581b610340565b630d0e30db60e41b86526000806004888b7382af49447d8a07e3bd95bd0d56f35241523fbab15af16104e5576104e5610336565b63a9059cbb60e01b86526001600160a01b038216600487015287602487015260008060448860007382af49447d8a07e3bd95bd0d56f35241523fbab15af161052f5761052f610336565b50869350602083015b828110156105805780356105746001600160a01b03821663ffffffff60a01b851660a01c600160ff1b86166001600160a01b0387168a8c61035b565b95509150602001610538565b50600160fe1b8116801561060f576105b73063ffffffff60a01b841660a01c600160ff1b85166001600160a01b038616898b61035b565b9450632e1a7d4d60e01b865284600487015260008060248860007382af49447d8a07e3bd95bd0d56f35241523fbab15af16105f4576105f4610336565b600080600080888e5af161060a5761060a610336565b61063b565b6106388a63ffffffff60a01b841660a01c600160ff1b85166001600160a01b038616898b61035b565b94505b5050505095945050505050565b60405160c0810160405261065f8333898b85610405565b915050848110156103fb576103fb605a7c164d696e2072657475726e206e6f742072656163686564000000000000610340565b61069a61119b565b6001600160a01b03166106ab61085e565b6001600160a01b0316146106d15760405162461bcd60e51b815260040161011c90612c5d565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b61072361119b565b6001600160a01b031661073461085e565b6001600160a01b03161461075a5760405162461bcd60e51b815260040161011c90612c5d565b61076e6001600160a01b038316338361119f565b5050565b600054610100900460ff168061078b575061078b61124e565b80610799575060005460ff16155b6107b55760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156107e0576000805460ff1961ff0019909116610100171660011790555b6107e861125f565b6107f06112dd565b8015610802576000805461ff00191690555b50565b61080d61119b565b6001600160a01b031661081e61085e565b6001600160a01b0316146108445760405162461bcd60e51b815260040161011c90612c5d565b61084c61135b565b565b60006103fb86868686863361032f565b6033546001600160a01b031690565b6000610877610326565b156108945760405162461bcd60e51b815260040161011c90612ad2565b60008460a00135116108b85760405162461bcd60e51b815260040161011c90612be5565b816108d55760405162461bcd60e51b815260040161011c90612e1c565b60e084013560006108e960208701876120ec565b905060006108fd60408801602089016120ec565b9050610911826001600160a01b03166113cd565b61091c576000610922565b86608001355b34146109405760405162461bcd60e51b815260040161011c90612996565b60028316156109a45761095b826001600160a01b03166113cd565b156109785760405162461bcd60e51b815260040161011c90612858565b6109a48261098c60608a0160408b016120ec565b60808a013561099f6101208c018c612e4c565b61141c565b6000806109b760808a0160608b016120ec565b6001600160a01b0316146109da576109d56080890160608a016120ec565b6109dc565b335b90506000600185166109ef576000610a02565b610a026001600160a01b0385163361143c565b90506000610a196001600160a01b0385168461143c565b90508a6001600160a01b031663a8920d2b348b8b6040518463ffffffff1660e01b8152600401610a4a92919061276a565b6000604051808303818588803b158015610a6357600080fd5b505af1158015610a77573d6000803e3d6000fd5b5050505060808b01359050610a9f82610a996001600160a01b0388168761143c565b906114e0565b97506001871615610b0f57610ace610ac06001600160a01b0388163361143c565b610a998560808f0135611508565b9050610ade60a08c01358261152d565b610aec8960808e013561152d565b1015610b0a5760405162461bcd60e51b815260040161011c90612bae565b610b33565b8a60a00135881015610b335760405162461bcd60e51b815260040161011c90612bae565b610b418b878787858d611567565b50505050505050949350505050565b60008180610b705760405162461bcd60e51b815260040161011c90612938565b8591506000198101600080600160fe1b87878381610b8a57fe5b9050602002013516119050600080600160fd1b888886818110610ba957fe5b90506020020135161190508115610c4657883414610bd95760405162461bcd60e51b815260040161011c90612901565b7382af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c2857600080fd5b505af1158015610c3c573d6000803e3d6000fd5b5050505050610c64565b3415610c645760405162461bcd60e51b815260040161011c90612d9d565b6001841115610cf257610c983083610c7c5733610c7e565b305b89896000818110610c8b57fe5b90506020020135886115ef565b945060015b83811015610ccd57610cc330308a8a85818110610cb657fe5b90506020020135896115ef565b9550600101610c9d565b50610ceb81610cdc578a610cde565b305b30898987818110610c8b57fe5b9450610d10565b610d0d81610d00578a610d02565b305b83610c7c5733610c7e565b94505b87851015610d305760405162461bcd60e51b815260040161011c90612afc565b801561063b57604051632e1a7d4d60e01b81527382af49447d8a07e3bd95bd0d56f35241523fbab190632e1a7d4d90610d6d908890600401612698565b600060405180830381600087803b158015610d8757600080fd5b505af1158015610d9b573d6000803e3d6000fd5b5061063b925050506001600160a01b038b168661179b565b6000610dc088848461105a565b610dcd888888888861084e565b98975050505050505050565b6000610de83386868686610b50565b90505b949350505050565b610dfb61119b565b6001600160a01b0316610e0c61085e565b6001600160a01b031614610e325760405162461bcd60e51b815260040161011c90612c5d565b6001600160a01b038116610e585760405162461bcd60e51b815260040161011c90612884565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b6000807fff1f98431c8ad98523631ae4a59f267346ea31f98400000000000000000000007fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5482604051602081016b0dfe1681d21220a7ddca3f4360a01b8252602081600484335afa610f2857610f28610336565b805196506020816004808501335afa610f4357610f43610336565b80519550602081600460088501335afa610f5f57610f5f610336565b5184825260158201878152603583018781526055808501939093526060822090915284905281206001600160a01b0316338114610fb557610fb560547004155392558cd48e88189859081c1bdbdb60621b610340565b506020608482375190506000891315611007576001600160a01b038116301415610ff257610fed6001600160a01b038616338b611837565b611007565b6110076001600160a01b03861682338c61188d565b600088131561104f576001600160a01b03811630141561103a576110356001600160a01b038516338a611837565b61104f565b61104f6001600160a01b03851682338b61188d565b505050505050505050565b8015611196576000606060e08314156110fb576040516001600160a01b038616906110949063d505accf60e01b90879087906020016125a4565b60408051601f19818403018152908290526110ae916125c8565b6000604051808303816000865af19150503d80600081146110eb576040519150601f19603f3d011682016040523d82523d6000602084013e6110f0565b606091505b509092509050611144565b61010083141561112c576040516001600160a01b03861690611094906323f2ebc360e21b90879087906020016125a4565b60405162461bcd60e51b815260040161011c90612cc2565b816111935761117a816040518060400160405280600f81526020016e02832b936b4ba103330b4b632b21d1608d1b8152506118b4565b60405162461bcd60e51b815260040161011c9190612845565b50505b505050565b3390565b8015611196576111ae836113cd565b1561123a576000826001600160a01b031682612710906040516111d090612695565b600060405180830381858888f193505050503d806000811461120e576040519150601f19603f3d011682016040523d82523d6000602084013e611213565b606091505b50509050806112345760405162461bcd60e51b815260040161011c90612c92565b50611196565b6111966001600160a01b0384168383611837565b600061125930611ac2565b15905090565b600054610100900460ff1680611278575061127861124e565b80611286575060005460ff16155b6112a25760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156112cd576000805460ff1961ff0019909116610100171660011790555b6112d5611ac8565b6107f0611b49565b600054610100900460ff16806112f657506112f661124e565b80611304575060005460ff16155b6113205760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff1615801561134b576000805460ff1961ff0019909116610100171660011790555b611353611ac8565b6107f0611c23565b611363610326565b156113805760405162461bcd60e51b815260040161011c90612ad2565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586113b661119b565b6040516113c391906126a1565b60405180910390a1565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148061140457506001600160a01b038216611010145b8061141657506001600160a01b038216155b92915050565b61142785838361105a565b6111936001600160a01b03861633868661188d565b6000611447836113cd565b1561145d57506001600160a01b03811631611416565b6040516370a0823160e01b81526001600160a01b038416906370a08231906114899085906004016126a1565b60206040518083038186803b1580156114a157600080fd5b505afa1580156114b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d991906124f2565b9392505050565b6000828211156115025760405162461bcd60e51b815260040161011c906129c1565b50900390565b6000828201838110156114d95760405162461bcd60e51b815260040161011c906128ca565b60008261153c57506000611416565b8282028284828161154957fe5b04146114d95760405162461bcd60e51b815260040161011c90612c1c565b836001600160a01b0316856001600160a01b0316336001600160a01b03167f76af224a143865a50b41496e1a73622698692c565c1214bc862f18e22d829c5e868a6080013587878d60a001358e60c001358f6101000160208101906115cc91906120ec565b6040516115df979695949392919061272d565b60405180910390a4505050505050565b6000600160ff1b83161580156116ca576000846001600160a01b031663128acb08888461161b88611caf565b6401000276a48b60405160200161163291906126a1565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016116619594939291906126d9565b6040805180830381600087803b15801561167a57600080fd5b505af115801561168e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b2919061248b565b9150506116c181600003611cd8565b92505050610deb565b6000846001600160a01b031663128acb0888846116e688611caf565b73fffd8963efd1fc6a506488495d951d5263988d258b60405160200161170c91906126a1565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161173b9594939291906126d9565b6040805180830381600087803b15801561175457600080fd5b505af1158015611768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178c919061248b565b5090506116c181600003611cd8565b804710156117bb5760405162461bcd60e51b815260040161011c90612a55565b6000826001600160a01b0316826040516117d490612695565b60006040518083038185875af1925050503d8060008114611811576040519150601f19603f3d011682016040523d82523d6000602084013e611816565b606091505b50509050806111965760405162461bcd60e51b815260040161011c906129f8565b6111968363a9059cbb60e01b8484604051602401611856929190612714565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611cfa565b6118ae846323b872dd60e01b858585604051602401611856939291906126b5565b50505050565b606060448351101580156118e75750826000815181106118d057fe5b6020910101516001600160f81b031916600160fb1b145b80156119125750826001815181106118fb57fe5b6020910101516001600160f81b03191660c360f81b145b801561193d57508260028151811061192657fe5b6020910101516001600160f81b031916607960f81b145b801561196857508260038151811061195157fe5b6020910101516001600160f81b031916600560fd1b145b156119c457606060448401905080516044018451101561199a5760405162461bcd60e51b815260040161011c90612cef565b82816040516020016119ad929190612660565b604051602081830303815290604052915050611416565b825160241480156119f45750826000815181106119dd57fe5b6020910101516001600160f81b031916602760f91b145b8015611a1f575082600181518110611a0857fe5b6020910101516001600160f81b031916600960fb1b145b8015611a4a575082600281518110611a3357fe5b6020910101516001600160f81b031916607b60f81b145b8015611a75575082600381518110611a5e57fe5b6020910101516001600160f81b031916607160f81b145b15611a9a57602483015182611a8982611d89565b6040516020016119ad929190612611565b81604051602001611aab91906125e4565b604051602081830303815290604052905092915050565b3b151590565b600054610100900460ff1680611ae15750611ae161124e565b80611aef575060005460ff16155b611b0b5760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff161580156107f0576000805460ff1961ff0019909116610100171660011790558015610802576000805461ff001916905550565b600054610100900460ff1680611b625750611b6261124e565b80611b70575060005460ff16155b611b8c5760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff16158015611bb7576000805460ff1961ff0019909116610100171660011790555b6000611bc161119b565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015610802576000805461ff001916905550565b600054610100900460ff1680611c3c5750611c3c61124e565b80611c4a575060005460ff16155b611c665760405162461bcd60e51b815260040161011c90612b60565b600054610100900460ff16158015611c91576000805460ff1961ff0019909116610100171660011790555b6065805460ff191690558015610802576000805461ff001916905550565b6000600160ff1b8210611cd45760405162461bcd60e51b815260040161011c90612d55565b5090565b600080821215611cd45760405162461bcd60e51b815260040161011c90612b2b565b6060611d4f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611db39092919063ffffffff16565b8051909150156111965780806020019051810190611d6d9190612213565b6111965760405162461bcd60e51b815260040161011c90612dd2565b606061141682604051602001611d9f9190612698565b604051602081830303815290604052611dc2565b6060610deb8484600085611f6b565b6060806040518060400160405280601081526020016f181899199a1a9b1b9c1cb0b131b232b360811b8152509050606083516002026002016001600160401b0381118015611e0f57600080fd5b506040519080825280601f01601f191660200182016040528015611e3a576020820181803683370190505b509050600360fc1b81600081518110611e4f57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611e7857fe5b60200101906001600160f81b031916908160001a90535060005b8451811015611f6357826004868381518110611eaa57fe5b016020015182516001600160f81b031990911690911c60f81c908110611ecc57fe5b602001015160f81c60f81b828260020260020181518110611ee957fe5b60200101906001600160f81b031916908160001a90535082858281518110611f0d57fe5b602091010151815160f89190911c600f16908110611f2757fe5b602001015160f81c60f81b828260020260030181518110611f4457fe5b60200101906001600160f81b031916908160001a905350600101611e92565b509392505050565b606082471015611f8d5760405162461bcd60e51b815260040161011c90612a8c565b611f9685611ac2565b611fb25760405162461bcd60e51b815260040161011c90612d1e565b60006060866001600160a01b03168587604051611fcf91906125c8565b60006040518083038185875af1925050503d806000811461200c576040519150601f19603f3d011682016040523d82523d6000602084013e612011565b606091505b509150915061202182828661202c565b979650505050505050565b6060831561203b5750816114d9565b82511561204b5782518084602001fd5b8160405162461bcd60e51b815260040161011c9190612845565b60008083601f840112612076578182fd5b5081356001600160401b0381111561208c578182fd5b60208301915083602080830285010111156120a657600080fd5b9250929050565b60008083601f8401126120be578182fd5b5081356001600160401b038111156120d4578182fd5b6020830191508360208285010111156120a657600080fd5b6000602082840312156120fd578081fd5b81356114d981612ebc565b60008060008060008060008060c0898b031215612123578384fd5b883561212e81612ebc565b9750602089013561213e81612ebc565b9650604089013595506060890135945060808901356001600160401b0380821115612167578586fd5b6121738c838d01612065565b909650945060a08b013591508082111561218b578384fd5b506121988b828c016120ad565b999c989b5096995094979396929594505050565b6000806000806000608086880312156121c3578081fd5b85356121ce81612ebc565b9450602086013593506040860135925060608601356001600160401b038111156121f6578182fd5b61220288828901612065565b969995985093965092949392505050565b600060208284031215612224578081fd5b815180151581146114d9578182fd5b60008060408385031215612245578182fd5b823561225081612ebc565b946020939093013593505050565b60008060008060008060a08789031215612276578182fd5b863561228181612ebc565b9550602087013594506040870135935060608701356001600160401b038111156122a9578283fd5b6122b589828a01612065565b90945092505060808701356122c981612ebc565b809150509295509295509295565b600080600080600080600060a0888a0312156122f1578081fd5b87356122fc81612ebc565b9650602088013595506040880135945060608801356001600160401b0380821115612325578283fd5b6123318b838c01612065565b909650945060808a0135915080821115612349578283fd5b506123568a828b016120ad565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215612384578182fd5b883561238f81612ebc565b9750602089013596506040890135955060608901356001600160401b03808211156123b8578384fd5b6123c48c838d01612065565b909750955060808b01359150808211156123dc578384fd5b506123e98b828c016120ad565b90945092505060a08901356123fd81612ebc565b809150509295985092959890939650565b60008060008060608587031215612423578182fd5b843561242e81612ebc565b935060208501356001600160401b0380821115612449578384fd5b90860190610140828903121561245d578384fd5b90935060408601359080821115612472578384fd5b5061247f87828801612065565b95989497509550505050565b6000806040838503121561249d578182fd5b505080516020909101519092909150565b600080600080606085870312156124c3578182fd5b843593506020850135925060408501356001600160401b038111156124e6578283fd5b61247f878288016120ad565b600060208284031215612503578081fd5b5051919050565b6000806000806060858703121561251f578182fd5b843593506020850135925060408501356001600160401b03811115612542578283fd5b61247f87828801612065565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452612590816020860160208601612e90565b601f01601f19169290920160200192915050565b6001600160e01b031984168152600082846004840137910160040190815292915050565b600082516125da818460208701612e90565b9190910192915050565b600082516125f6818460208701612e90565b68556e6b6e6f776e282960b81b920191825250600901919050565b60008351612623818460208801612e90565b650a0c2dcd2c6560d31b9083019081528351612646816006840160208801612e90565b602960f81b60069290910191820152600701949350505050565b60008351612672818460208801612e90565b6508ae4e4dee4560d31b9083019081528351612646816006840160208801612e90565b90565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0386811682528515156020830152604082018590528316606082015260a06080820181905260009061202190830184612578565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039788168152602081019690965260408601949094526060850192909252608084015260a083015290911660c082015260e00190565b602080825281810183905260009060408084018583028501820187855b8881101561282c57878303603f190184528135368b9003607e190181126127ac578788fd5b8a018035845286810135878501528581013586850152608060608083013536849003601e190181126127dc578a8bfd5b830180356001600160401b038111156127f3578b8cfd5b803603851315612801578b8cfd5b8383890152612815848901828d850161254e565b988b01989750505093880193505050600101612787565b509098975050505050505050565b901515815260200190565b6000602082526114d96020830184612578565b602080825260129082015271086d8c2d2da40e8ded6cadc40d2e6408aa8960731b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601a908201527f556e697377617056333a2077726f6e67206d73672e76616c7565000000000000604082015260600190565b602080825260169082015275556e697377617056333a20656d70747920706f6f6c7360501b604082015260600190565b6020808252601490820152731155120819195c1bdcda5d081c995a9958dd195960621b604082015260600190565b602080825260119082015270496e76616c6964206d73672e76616c756560781b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252603a908201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260408201527f6563697069656e74206d61792068617665207265766572746564000000000000606082015260800190565b6020808252601d908201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601590820152742ab734b9bbb0b82b199d1036b4b7103932ba3ab93760591b604082015260600190565b6020808252818101527f53616665436173743a2076616c7565206d75737420626520706f736974697665604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601b908201527f52657475726e20616d6f756e74206973206e6f7420656e6f7567680000000000604082015260600190565b6020808252601a908201527f4d696e2072657475726e2073686f756c64206e6f742062652030000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526016908201527508cc2d2d8cac840e8de40e8e4c2dce6cccae4408aa8960531b604082015260600190565b6020808252601390820152720aee4dedcce40e0cae4dad2e840d8cadccee8d606b1b604082015260600190565b60208082526015908201527424b73b30b634b2103932bb32b93a103932b0b9b7b760591b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526028908201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604082015267371034b73a191a9b60c11b606082015260800190565b6020808252818101527f556e697377617056333a206d73672e76616c75652073686f756c642062652030604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526016908201527510d85b1b0819185d18481cda1bdd5b1908195e1a5cdd60521b604082015260600190565b6000808335601e19843603018112612e62578283fd5b8301803591506001600160401b03821115612e7b578283fd5b6020019150368190038213156120a657600080fd5b60005b83811015612eab578181015183820152602001612e93565b838111156118ae5750506000910152565b6001600160a01b038116811461080257600080fdfea2646970667358221220876629cfe1567383e5c95b259a804464609b178622e5f5d989ab082a14a156c164736f6c634300060c0033

Deployed ByteCode Sourcemap

80979:3886:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42809:10;42823:9;42809:23;;42801:56;;;;-1:-1:-1;;;42801:56:0;;;;;;;:::i;:::-;;;;;;;;;80979:3886;;;;;47996:393;;;;;;;;;;-1:-1:-1;47996:393:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73994:387;;;;;;;;;;-1:-1:-1;73994:387:0;;;;;:::i;:::-;;:::i;36424:86::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;48747:6454::-;;;;;;:::i;:::-;;:::i;12467:148::-;;;;;;;;;;;;;:::i;84659:132::-;;;;;;;;;;-1:-1:-1;84659:132:0;;;;;:::i;:::-;;:::i;81967:143::-;;;;;;;;;;;;;:::i;84799:63::-;;;;;;;;;;;;;:::i;55209:275::-;;;;;;:::i;:::-;;:::i;11816:87::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;82118:1739::-;;;;;;:::i;:::-;;:::i;75445:1649::-;;;;;;:::i;:::-;;:::i;48397:342::-;;;;;;;;;;-1:-1:-1;48397:342:0;;;;;:::i;:::-;;:::i;74712:245::-;;;;;;:::i;:::-;;:::i;12770:244::-;;;;;;;;;;-1:-1:-1;12770:244:0;;;;;:::i;:::-;;:::i;77146:2855::-;;;;;;;;;;-1:-1:-1;77146:2855:0;;;;;:::i;:::-;;:::i;47996:393::-;48236:20;48269:34;48285:8;48296:6;;48269:7;:34::i;:::-;48321:60;48335:8;48345:6;48353:9;48364:5;;48371:9;48321:13;:60::i;:::-;48314:67;47996:393;-1:-1:-1;;;;;;;;;47996:393:0:o;73994:387::-;74236:20;74269:34;74285:8;74296:6;;74269:7;:34::i;:::-;74321:52;74337:9;74348:6;74356:9;74367:5;;74321:15;:52::i;36424:86::-;36495:7;;;;36424:86;:::o;48747:6454::-;48957:20;49070:137;;;49130:16;49127:1;49124;49109:38;49175:16;49172:1;49165:27;49223:308;-1:-1:-1;;;49283:1:0;49276:77;-1:-1:-1;;;49378:4:0;49371:80;49482:1;49476:4;49469:15;49512:3;49509:1;49502:14;49547:1400;;-1:-1:-1;;;49648:8:0;49641:56;49774:4;49764:8;49759:3;49749:8;49743:4;49736:5;49725:54;49715:2;;49804:10;;:::i;:::-;49875:8;49869:15;49938:4;49928:8;49924:19;49918:26;49965:8;49962:2;;;50050:8;49962:2;-1:-1:-1;;;50271:52:0;;50139:26;;;50237:11;50223:26;;;;50214:36;;50194:18;;50190:61;;-1:-1:-1;50348:8:0;50374:133;;;;50584:3;50577:4;50567:8;50563:19;50556:32;50638:1;50631:4;50621:8;50617:19;50610:30;50341:318;;50374:133;50432:1;50425:4;50415:8;50411:19;50404:30;50484:3;50477:4;50467:8;50463:19;50456:32;50341:318;;50705:3;50698:4;50688:8;50684:19;50677:32;50755:4;50748;50738:8;50734:19;50727:33;50806:1;50799:4;50789:8;50785:19;50778:30;50876:1;50873;50867:4;50857:8;50854:1;50848:4;50841:5;50836:42;50826:2;;50903:10;;:::i;:::-;49622:1325;;;;;;;;:::o;50963:3842::-;;51093:4;51080:18;51202:22;;;;;51100:3;51076:28;;51144:25;51219:4;51277:25;51260:43;;51336:25;;51386:5;51409:809;;;;52270:11;52267:2;;;52309:90;52394:4;-1:-1:-1;;;52309:90:0;:::i;:::-;-1:-1:-1;;;52476:8:0;52469:48;52566:10;52560:3;52550:8;52546:18;52539:38;-1:-1:-1;;;;;52631:7:0;52627:26;52620:4;52610:8;52606:19;52599:55;52704:9;52697:4;52687:8;52683:19;52676:38;52787:1;52784;52778:4;52768:8;52765:1;52758:5;52751;52746:43;52736:2;;52818:10;;:::i;:::-;51379:1491;;51409:809;51463:11;51452:9;51449:26;51439:2;;51504:90;51589:4;-1:-1:-1;;;51504:90:0;:::i;:::-;-1:-1:-1;;;51671:8:0;51664:47;51790:1;51787;51782:3;51772:8;51761:9;51755:4;51748:5;51743:49;51733:2;;51821:10;;:::i;:::-;-1:-1:-1;;;51885:8:0;51878:49;-1:-1:-1;;;;;51980:7:0;51976:26;51970:3;51960:8;51956:18;51949:54;52053:9;52046:4;52036:8;52032:19;52025:38;52135:1;52132;52126:4;52116:8;52113:1;52107:4;52100:5;52095:42;52085:2;;52166:10;;:::i;:::-;51379:1491;52897:9;52890:16;;52979:4;52966:11;52962:22;52926:646;53010:14;53007:1;53004:21;52926:646;;;53141:1;53128:15;53174:333;-1:-1:-1;;;;;53458:11:0;53454:30;-1:-1:-1;;;53402:7:0;53398:28;53380:16;53376:51;-1:-1:-1;;;53327:7:0;53323:26;-1:-1:-1;;;;;53274:7:0;53270:26;53240:3;53205:8;53174:333;:::i;:::-;53167:340;-1:-1:-1;53542:11:0;-1:-1:-1;53061:4:0;53054:12;52926:646;;;-1:-1:-1;;;;53599:23:0;;53640:367;;;;54063:312;54343:9;-1:-1:-1;;;54291:7:0;54287:28;54269:16;54265:51;-1:-1:-1;;;54216:7:0;54212:26;-1:-1:-1;;;;;54163:7:0;54159:26;54129:3;54094:8;54063:312;:::i;:::-;54056:319;;-1:-1:-1;;;54406:8:0;54399:48;54497:3;54490:4;54480:8;54476:19;54469:32;54573:1;54570;54564:4;54554:8;54551:1;54545:4;54538:5;54533:42;54523:2;;54604:10;;:::i;:::-;54707:1;54704;54701;54698;54693:3;54683:8;54676:5;54671:38;54661:2;;54738:10;;:::i;:::-;53592:1198;;53640:367;53677:311;53957:8;-1:-1:-1;;;53905:7:0;53901:28;53883:16;53879:51;-1:-1:-1;;;53830:7:0;53826:26;-1:-1:-1;;;;;53777:7:0;53773:26;53743:3;53708:8;53677:311;:::i;:::-;53670:318;;53592:1198;;;;;51038:3767;;;;;;;:::o;:::-;54843:4;54837:11;54889:4;54879:8;54875:19;54869:4;54862:33;54927:57;54974:9;54964:8;54956:6;54946:8;54936;54927:57;:::i;:::-;54911:73;;;55020:9;55006:12;55003:27;55000:2;;;55050:90;55135:4;55067:66;55050:90;:::i;12467:148::-;12047:12;:10;:12::i;:::-;-1:-1:-1;;;;;12036:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;12036:23:0;;12028:68;;;;-1:-1:-1;;;12028:68:0;;;;;;;:::i;:::-;12558:6:::1;::::0;12537:40:::1;::::0;12574:1:::1;::::0;-1:-1:-1;;;;;12558:6:0::1;::::0;12537:40:::1;::::0;12574:1;;12537:40:::1;12588:6;:19:::0;;-1:-1:-1;;;;;;12588:19:0::1;::::0;;12467:148::o;84659:132::-;12047:12;:10;:12::i;:::-;-1:-1:-1;;;;;12036:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;12036:23:0;;12028:68;;;;-1:-1:-1;;;12028:68:0;;;;;;;:::i;:::-;84740:43:::1;-1:-1:-1::0;;;;;84740:23:0;::::1;84764:10;84776:6:::0;84740:23:::1;:43::i;:::-;84659:132:::0;;:::o;81967:143::-;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8800:101;82019:35:::1;:33;:35::i;:::-;82065:37;:35;:37::i;:::-;8931:14:::0;8927:68;;;8978:5;8962:21;;-1:-1:-1;;8962:21:0;;;8927:68;81967:143;:::o;84799:63::-;12047:12;:10;:12::i;:::-;-1:-1:-1;;;;;12036:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;12036:23:0;;12028:68;;;;-1:-1:-1;;;12028:68:0;;;;;;;:::i;:::-;84846:8:::1;:6;:8::i;:::-;84799:63::o:0;55209:275::-;55375:20;55415:61;55429:8;55439:6;55447:9;55458:5;;55465:10;55415:13;:61::i;11816:87::-;11889:6;;-1:-1:-1;;;;;11889:6:0;11816:87;:::o;82118:1739::-;82313:20;36750:8;:6;:8::i;:::-;36749:9;36741:38;;;;-1:-1:-1;;;36741:38:0;;;;;;;:::i;:::-;82377:1:::1;82354:4;:20;;;:24;82346:63;;;;-1:-1:-1::0;;;82346:63:0::1;;;;;;;:::i;:::-;82428:16:::0;82420:51:::1;;;;-1:-1:-1::0;;;82420:51:0::1;;;;;;;:::i;:::-;82500:10;::::0;::::1;;82484:13;82539;;::::0;::::1;82500:4:::0;82539:13:::1;:::i;:::-;82521:31:::0;-1:-1:-1;82563:15:0::1;82581:13;::::0;;;::::1;::::0;::::1;;:::i;:::-;82563:31;;82629:16;:8;-1:-1:-1::0;;;;;82629:14:0::1;;:16::i;:::-;:34;;82662:1;82629:34;;;82648:4;:11;;;82629:34;82615:9;:49;82607:79;;;;-1:-1:-1::0;;;82607:79:0::1;;;;;;;:::i;:::-;81293:4;82703:21:::0;::::1;:26:::0;82699:182:::1;;82755:16;:8;-1:-1:-1::0;;;;;82755:14:0::1;;:16::i;:::-;82754:17;82746:48;;;;-1:-1:-1::0;;;82746:48:0::1;;;;;;;:::i;:::-;82809:60;82816:8:::0;82826:16:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;82844:11;::::0;::::1;;82857;;::::0;::::1;82844:4:::0;82857:11:::1;:::i;:::-;82809:6;:60::i;:::-;82893:19;::::0;82916:16:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;82916:30:0::1;;82915:64;;82963:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;82915:64;;;82950:10;82915:64;82893:86:::0;-1:-1:-1;82990:25:0::1;81241:4;83019:21:::0;::::1;83018:74;;83091:1;83018:74;;;83049:39;-1:-1:-1::0;;;;;83049:27:0;::::1;83077:10;83049:27;:39::i;:::-;82990:102:::0;-1:-1:-1;83103:25:0::1;83131:40;-1:-1:-1::0;;;;;83131:27:0;::::1;83159:11:::0;83131:27:::1;:40::i;:::-;83103:68;;83184:6;-1:-1:-1::0;;;;;83184:16:0::1;;83208:9;83219:5;;83184:41;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;;;83260:11:0::1;::::0;::::1;;::::0;-1:-1:-1;83297:63:0::1;83342:17:::0;83297:40:::1;-1:-1:-1::0;;;;;83297:27:0;::::1;83325:11:::0;83297:27:::1;:40::i;:::-;:44:::0;::::1;:63::i;:::-;83282:78:::0;-1:-1:-1;81241:4:0::1;83377:21:::0;::::1;:26:::0;83373:386:::1;;83434:79;83473:39;-1:-1:-1::0;;;;;83473:27:0;::::1;83501:10;83473:27;:39::i;:::-;83434:34;:17:::0;83456:11:::1;::::0;::::1;;83434:21;:34::i;:79::-;83420:93:::0;-1:-1:-1;83569:37:0::1;:20;::::0;::::1;;83420:93:::0;83569:24:::1;:37::i;:::-;83536:29;:12:::0;83553:11:::1;::::0;::::1;;83536:16;:29::i;:::-;:70;;83528:110;;;;-1:-1:-1::0;;;83528:110:0::1;;;;;;;:::i;:::-;83373:386;;;83695:4;:20;;;83679:12;:36;;83671:76;;;;-1:-1:-1::0;;;83671:76:0::1;;;;;;;:::i;:::-;83771:78;83784:4;83790:8;83800;83810:11;83823;83836:12;83771;:78::i;:::-;36790:1;;;;;;;82118:1739:::0;;;;;;:::o;75445:1649::-;75625:20;75672:5;75703:7;75695:42;;;;-1:-1:-1;;;75695:42:0;;;;;;;:::i;:::-;75801:6;;-1:-1:-1;;;75768:7:0;;75748:17;;-1:-1:-1;;;75834:5:0;;75748:17;75834:8;;;;;;;;;;;:26;:30;75818:46;;75875:15;75932:1;-1:-1:-1;;;75893:5:0;;75899:9;75893:16;;;;;;;;;;;;;:36;:40;75875:58;;75948:8;75944:243;;;75994:6;75981:9;:19;75973:58;;;;-1:-1:-1;;;75973:58:0;;;;;;;:::i;:::-;73318:42;-1:-1:-1;;;;;76046:20:0;;76074:6;76046:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75944:243;;;76124:9;:14;76116:59;;;;-1:-1:-1;;;76116:59:0;;;;;;;:::i;:::-;76207:1;76201:3;:7;76197:680;;;76240:87;76258:4;76265:8;:37;;76292:10;76265:37;;;76284:4;76265:37;76304:5;;76310:1;76304:8;;;;;;;;;;;;;76314:12;76240:9;:87::i;:::-;76225:102;-1:-1:-1;76361:1:0;76344:153;76368:9;76364:1;:13;76344:153;;;76418:63;76436:4;76451;76458:5;;76464:1;76458:8;;;;;;;;;;;;;76468:12;76418:9;:63::i;:::-;76403:78;-1:-1:-1;76379:3:0;;76344:153;;;;76526:96;76536:10;:38;;76565:9;76536:38;;;76557:4;76536:38;76584:4;76591:5;;76597:9;76591:16;;;;;;76526:96;76511:111;;76197:680;;;76670:195;76698:10;:38;;76727:9;76698:38;;;76719:4;76698:38;76755:8;:37;;76782:10;76755:37;;76670:195;76655:210;;76197:680;76913:9;76897:12;:25;;76889:59;;;;-1:-1:-1;;;76889:59:0;;;;;;;:::i;:::-;76965:10;76961:126;;;76992:35;;-1:-1:-1;;;76992:35:0;;73318:42;;76992:21;;:35;;77014:12;;76992:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;77042:33:0;;-1:-1:-1;;;;;;;;77042:19:0;;77062:12;77042:19;:33::i;48397:342::-;48599:20;48632:34;48648:8;48659:6;;48632:7;:34::i;:::-;48684:47;48696:8;48706:6;48714:9;48725:5;;48684:11;:47::i;:::-;48677:54;48397:342;-1:-1:-1;;;;;;;;48397:342:0:o;74712:245::-;74856:20;74896:53;74912:10;74924:6;74932:9;74943:5;;74896:15;:53::i;:::-;74889:60;;74712:245;;;;;;;:::o;12770:244::-;12047:12;:10;:12::i;:::-;-1:-1:-1;;;;;12036:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;12036:23:0;;12028:68;;;;-1:-1:-1;;;12028:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;12859:22:0;::::1;12851:73;;;;-1:-1:-1::0;;;12851:73:0::1;;;;;;;:::i;:::-;12961:6;::::0;12940:38:::1;::::0;-1:-1:-1;;;;;12940:38:0;;::::1;::::0;12961:6:::1;::::0;12940:38:::1;::::0;12961:6:::1;::::0;12940:38:::1;12989:6;:17:::0;;-1:-1:-1;;;;;;12989:17:0::1;-1:-1:-1::0;;;;;12989:17:0;;;::::1;::::0;;;::::1;::::0;;12770:244::o;77146:2855::-;77309:13;;72534:66;72422;77309:13;78072:4;78066:11;78122:4;78112:8;78108:19;-1:-1:-1;;;78148:8:0;78141:28;78249:4;78238:9;78233:3;78223:8;78213;78206:5;78195:59;78185:2;;78275:10;;:::i;:::-;78330:9;78324:16;78314:26;;78428:4;78417:9;78412:3;78406;78396:8;78392:18;78382:8;78375:5;78364:69;78354:2;;78454:10;;:::i;:::-;78509:9;78503:16;78493:26;;78607:4;78596:9;78591:3;78585;78575:8;78571:18;78561:8;78554:5;78543:69;78533:2;;78633:10;;:::i;:::-;78683:16;78746:27;;;78799:2;78792:10;;78864:17;;;78902:10;;;78895:26;;;78942:10;;;;78935:23;;;;78995:2;78982:16;;78972:27;;;79042;;;79099:23;;-1:-1:-1;;;;;79095:43:0;79173:8;79164:18;;79154:2;;79203:90;79288:4;-1:-1:-1;;;79203:90:0;:::i;:::-;79154:2;79376:4;79370;79360:8;79347:34;79404:15;;-1:-1:-1;79461:1:0;79446:16;;79442:271;;;-1:-1:-1;;;;;79483:22:0;;79500:4;79483:22;79479:223;;;79526:54;-1:-1:-1;;;;;79526:19:0;;79546:10;79566:12;79526:19;:54::i;:::-;79479:223;;;79621:65;-1:-1:-1;;;;;79621:23:0;;79645:5;79652:10;79672:12;79621:23;:65::i;:::-;79742:1;79727:12;:16;79723:271;;;-1:-1:-1;;;;;79764:22:0;;79781:4;79764:22;79760:223;;;79807:54;-1:-1:-1;;;;;79807:19:0;;79827:10;79847:12;79807:19;:54::i;:::-;79760:223;;;79902:65;-1:-1:-1;;;;;79902:23:0;;79926:5;79933:10;79953:12;79902:23;:65::i;:::-;77146:2855;;;;;;;;;:::o;45534:828::-;45613:17;;45609:746;;45647:12;45674:19;45729:6;45712:23;;45708:514;;;45855:54;;-1:-1:-1;;;;;45844:10:0;;;45855:54;;-1:-1:-1;;;45872:28:0;45902:6;;;;45855:54;;;:::i;:::-;;;;-1:-1:-1;;45855:54:0;;;;;;;;;;45844:66;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45824:86:0;;-1:-1:-1;45824:86:0;-1:-1:-1;45708:514:0;;;45953:6;45936:23;;45932:290;;;46079:56;;-1:-1:-1;;;;;46068:10:0;;;46079:56;;-1:-1:-1;;;46096:30:0;46128:6;;;;46079:56;;;:::i;45932:290::-;46177:29;;-1:-1:-1;;;46177:29:0;;;;;;;:::i;45932:290::-;46241:7;46236:108;;46276:51;46301:6;46276:51;;;;;;;;;;;;;-1:-1:-1;;;46276:51:0;;;:24;:51::i;:::-;46269:59;;-1:-1:-1;;;46269:59:0;;;;;;;;:::i;46236:108::-;45609:746;;;45534:828;;;:::o;10087:106::-;10175:10;10087:106;:::o;41159:420::-;41294:10;;41290:282;;41325:12;41331:5;41325;:12::i;:::-;41321:240;;;41359:11;41376:2;-1:-1:-1;;;;;41376:7:0;41391:6;41404:5;41376:38;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41358:56;;;41441:6;41433:41;;;;-1:-1:-1;;;41433:41:0;;;;;;;:::i;:::-;41321:240;;;;41515:30;-1:-1:-1;;;;;41515:18:0;;41534:2;41538:6;41515:18;:30::i;9095:125::-;9143:4;9168:44;9206:4;9168:29;:44::i;:::-;9167:45;9160:52;;9095:125;:::o;11402:129::-;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8800:101;11460:26:::1;:24;:26::i;:::-;11497;:24;:26::i;36093:131::-:0;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8800:101;36152:26:::1;:24;:26::i;:::-;36189:27;:25;:27::i;37224:118::-:0;36750:8;:6;:8::i;:::-;36749:9;36741:38;;;;-1:-1:-1;;;36741:38:0;;;;;;;:::i;:::-;37284:7:::1;:14:::0;;-1:-1:-1;;37284:14:0::1;37294:4;37284:14;::::0;;37314:20:::1;37321:12;:10;:12::i;:::-;37314:20;;;;;;:::i;:::-;;;;;;;;37224:118::o:0;42393:248::-;42445:4;-1:-1:-1;;;;;42482:38:0;;41009:42;42482:38;;:95;;-1:-1:-1;;;;;;42537:40:0;;41107:42;42537:40;42482:95;:151;;;-1:-1:-1;;;;;;42594:39:0;;;42482:151;42462:171;42393:248;-1:-1:-1;;42393:248:0:o;84410:241::-;84554:31;84570:5;84578:6;;84554:7;:31::i;:::-;84596:47;-1:-1:-1;;;;;84596:22:0;;84619:10;84631:3;84636:6;84596:22;:47::i;42145:240::-;42227:7;42251:12;42257:5;42251;:12::i;:::-;42247:131;;;-1:-1:-1;;;;;;42287:15:0;;;42280:22;;42247:131;42342:24;;-1:-1:-1;;;42342:24:0;;-1:-1:-1;;;;;42342:15:0;;;;;:24;;42358:7;;42342:24;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42335:31;42145:240;-1:-1:-1;;;42145:240:0:o;19123:158::-;19181:7;19214:1;19209;:6;;19201:49;;;;-1:-1:-1;;;19201:49:0;;;;;;;:::i;:::-;-1:-1:-1;19268:5:0;;;19123:158::o;18661:179::-;18719:7;18751:5;;;18775:6;;;;18767:46;;;;-1:-1:-1;;;18767:46:0;;;;;;;:::i;19540:220::-;19598:7;19622:6;19618:20;;-1:-1:-1;19637:1:0;19630:8;;19618:20;19661:5;;;19665:1;19661;:5;:1;19685:5;;;;;:10;19677:56;;;;-1:-1:-1;;;19677:56:0;;;;;;;:::i;83865:537::-;84171:8;-1:-1:-1;;;;;84101:293:0;84148:8;-1:-1:-1;;;;;84101:293:0;84123:10;-1:-1:-1;;;;;84101:293:0;;84194:11;84220:4;:11;;;84246;84272:12;84299:4;:20;;;84334:4;:21;;;84370:4;:13;;;;;;;;;;:::i;:::-;84101:293;;;;;;;;;;;;:::i;:::-;;;;;;;;83865:537;;;;;;:::o;80009:869::-;80152:7;-1:-1:-1;;;80190:25:0;;:30;80231:640;;;;80265:14;80298:4;-1:-1:-1;;;;;80283:25:0;;80327:9;80355:10;80384:25;80402:6;80384:17;:25::i;:::-;72997:14;80473:5;80462:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;80283:211;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80262:232;;;80516:28;80536:7;80535:8;;80516:18;:28::i;:::-;80509:35;;;;;;80231:640;80578:14;80613:4;-1:-1:-1;;;;;80598:25:0;;80642:9;80670:10;80699:25;80717:6;80699:17;:25::i;:::-;73183:53;80788:5;80777:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;80598:211;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;80577:232;;;80831:28;80851:7;80850:8;;80831:18;:28::i;25459:397::-;25574:6;25549:21;:31;;25541:73;;;;-1:-1:-1;;;25541:73:0;;;;;;;:::i;:::-;25706:12;25724:9;-1:-1:-1;;;;;25724:14:0;25747:6;25724:35;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25705:54;;;25778:7;25770:78;;;;-1:-1:-1;;;25770:78:0;;;;;;;:::i;32027:177::-;32110:86;32130:5;32160:23;;;32185:2;32189:5;32137:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;32137:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;32137:58:0;-1:-1:-1;;;;;;32137:58:0;;;;;;;;;;32110:19;:86::i;32212:205::-;32313:96;32333:5;32363:27;;;32392:4;32398:2;32402:5;32340:68;;;;;;;;;;:::i;32313:96::-;32212:205;;;;:::o;38187:1893::-;38266:13;38551:2;38536:4;:11;:17;;:38;;;;;38557:4;38562:1;38557:7;;;;;;;;;;;;;-1:-1:-1;;;;;;38557:7:0;-1:-1:-1;;;38557:17:0;38536:38;:59;;;;;38578:4;38583:1;38578:7;;;;;;;;;;;;;-1:-1:-1;;;;;;38578:7:0;-1:-1:-1;;;38578:17:0;38536:59;:80;;;;;38599:4;38604:1;38599:7;;;;;;;;;;;;;-1:-1:-1;;;;;;38599:7:0;-1:-1:-1;;;38599:17:0;38536:80;:101;;;;;38620:4;38625:1;38620:7;;;;;;;;;;;;;-1:-1:-1;;;;;;38620:7:0;-1:-1:-1;;;38620:17:0;38536:101;38532:1476;;;38654:20;38870:2;38864:4;38860:13;38850:23;;39372:6;39366:20;39361:2;:25;39346:4;:11;:40;;39338:74;;;;-1:-1:-1;;;39338:74:0;;;;;;;:::i;:::-;39458:6;39476;39441:47;;;;;;;;;:::i;:::-;;;;;;;;;;;;;39427:62;;;;;38532:1476;39583:4;:11;39598:2;39583:17;:38;;;;;39604:4;39609:1;39604:7;;;;;;;;;;;;;-1:-1:-1;;;;;;39604:7:0;-1:-1:-1;;;39604:17:0;39583:38;:59;;;;;39625:4;39630:1;39625:7;;;;;;;;;;;;;-1:-1:-1;;;;;;39625:7:0;-1:-1:-1;;;39625:17:0;39583:59;:80;;;;;39646:4;39651:1;39646:7;;;;;;;;;;;;;-1:-1:-1;;;;;;39646:7:0;-1:-1:-1;;;39646:17:0;39583:80;:101;;;;;39667:4;39672:1;39667:7;;;;;;;;;;;;;-1:-1:-1;;;;;;39667:7:0;-1:-1:-1;;;39667:17:0;39583:101;39579:429;;;39895:2;39885:13;;39879:20;39959:6;39977:12;39879:20;39977:6;:12::i;:::-;39942:53;;;;;;;;;:::i;39579:429::-;40051:6;40034:37;;;;;;;;:::i;:::-;;;;;;;;;;;;;40020:52;;38187:1893;;;;:::o;839:422::-;1206:20;1245:8;;;839:422::o;10016:65::-;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8931:14;8927:68;;;8978:5;8962:21;;-1:-1:-1;;8962:21:0;;;10016:65;:::o;11539:196::-;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8800:101;11607:17:::1;11627:12;:10;:12::i;:::-;11650:6;:18:::0;;-1:-1:-1;;;;;;11650:18:0::1;-1:-1:-1::0;;;;;11650:18:0;::::1;::::0;;::::1;::::0;;;11684:43:::1;::::0;11650:18;;-1:-1:-1;11650:18:0;-1:-1:-1;;11684:43:0::1;::::0;-1:-1:-1;;11684:43:0::1;8913:1;8931:14:::0;8927:68;;;8978:5;8962:21;;-1:-1:-1;;8962:21:0;;;11539:196;:::o;36232:92::-;8639:13;;;;;;;;:33;;;8656:16;:14;:16::i;:::-;8639:50;;;-1:-1:-1;8677:12:0;;;;8676:13;8639:50;8631:109;;;;-1:-1:-1;;;8631:109:0;;;;;;;:::i;:::-;8753:19;8776:13;;;;;;8775:14;8800:101;;;;8835:13;:20;;-1:-1:-1;;;;8835:20:0;;;;;8870:19;8851:4;8870:19;;;8800:101;36301:7:::1;:15:::0;;-1:-1:-1;;36301:15:0::1;::::0;;8927:68;;;;8978:5;8962:21;;-1:-1:-1;;8962:21:0;;;36232:92;:::o;62083:181::-;62139:6;-1:-1:-1;;;62166:5:0;:14;62158:67;;;;-1:-1:-1;;;62158:67:0;;;;;;;:::i;:::-;-1:-1:-1;62250:5:0;62083:181::o;58901:171::-;58957:7;58994:1;58985:5;:10;;58977:55;;;;-1:-1:-1;;;58977:55:0;;;;;;;:::i;34332:761::-;34756:23;34782:69;34810:4;34782:69;;;;;;;;;;;;;;;;;34790:5;-1:-1:-1;;;;;34782:27:0;;;:69;;;;;:::i;:::-;34866:17;;34756:95;;-1:-1:-1;34866:21:0;34862:224;;35008:10;34997:30;;;;;;;;;;;;:::i;:::-;34989:85;;;;-1:-1:-1;;;34989:85:0;;;;;;;:::i;40088:124::-;40140:13;40173:31;40197:5;40180:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;40173:6;:31::i;27020:195::-;27123:12;27155:52;27177:6;27185:4;27191:1;27194:12;27155:21;:52::i;40220:455::-;40276:13;40302:21;:42;;;;;;;;;;;;;-1:-1:-1;;;40302:42:0;;;;;40355:16;40388:4;:11;40402:1;40388:15;40384:1;:19;-1:-1:-1;;;;;40374:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;40374:30:0;;40355:49;;-1:-1:-1;;;40415:3:0;40419:1;40415:6;;;;;;;;;;;:12;-1:-1:-1;;;;;40415:12:0;;;;;;;;;-1:-1:-1;;;40438:3:0;40442:1;40438:6;;;;;;;;;;;:12;-1:-1:-1;;;;;40438:12:0;;;;;;;;;40466:9;40461:178;40485:4;:11;40481:1;:15;40461:178;;;40535:8;40561:1;40550:4;40555:1;40550:7;;;;;;;;;;;;40535:29;;-1:-1:-1;;;;;;40550:7:0;;;:12;;;:7;40544:19;;40535:29;;;;;;;;;;;;;;40518:3;40526:1;40522;:5;40530:1;40522:9;40518:14;;;;;;;;;;;:46;-1:-1:-1;;;;;40518:46:0;;;;;;;;;40596:8;40611:4;40616:1;40611:7;;;;;;;;;;;;;40596:31;;40611:7;;;;;40621:4;40605:21;;40596:31;;;;;;;;;;;;;;40579:3;40587:1;40583;:5;40591:1;40583:9;40579:14;;;;;;;;;;;:48;-1:-1:-1;;;;;40579:48:0;;;;;;;;-1:-1:-1;40498:3:0;;40461:178;;;-1:-1:-1;40663:3:0;40220:455;-1:-1:-1;;;40220:455:0:o;28072:530::-;28199:12;28257:5;28232:21;:30;;28224:81;;;;-1:-1:-1;;;28224:81:0;;;;;;;:::i;:::-;28324:18;28335:6;28324:10;:18::i;:::-;28316:60;;;;-1:-1:-1;;;28316:60:0;;;;;;;:::i;:::-;28450:12;28464:23;28491:6;-1:-1:-1;;;;;28491:11:0;28511:5;28519:4;28491:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28449:75;;;;28542:52;28560:7;28569:10;28581:12;28542:17;:52::i;:::-;28535:59;28072:530;-1:-1:-1;;;;;;;28072:530:0:o;30612:742::-;30727:12;30756:7;30752:595;;;-1:-1:-1;30787:10:0;30780:17;;30752:595;30901:17;;:21;30897:439;;31164:10;31158:17;31225:15;31212:10;31208:2;31204:19;31197:44;31112:148;31307:12;31300:20;;-1:-1:-1;;;31300:20:0;;;;;;;;:::i;313:352:-1:-;;;443:3;436:4;428:6;424:17;420:27;410:2;;-1:-1;;451:12;410:2;-1:-1;481:20;;-1:-1;;;;;510:30;;507:2;;;-1:-1;;543:12;507:2;587:4;579:6;575:17;563:29;;638:3;587:4;;622:6;618:17;579:6;604:32;;601:41;598:2;;;655:1;;645:12;598:2;403:262;;;;;:::o;1645:336::-;;;1759:3;1752:4;1744:6;1740:17;1736:27;1726:2;;-1:-1;;1767:12;1726:2;-1:-1;1797:20;;-1:-1;;;;;1826:30;;1823:2;;;-1:-1;;1859:12;1823:2;1903:4;1895:6;1891:17;1879:29;;1954:3;1903:4;1934:17;1895:6;1920:32;;1917:41;1914:2;;;1971:1;;1961:12;3116:241;;3220:2;3208:9;3199:7;3195:23;3191:32;3188:2;;;-1:-1;;3226:12;3188:2;85:6;72:20;97:33;124:5;97:33;:::i;3364:1193::-;;;;;;;;;3629:3;3617:9;3608:7;3604:23;3600:33;3597:2;;;-1:-1;;3636:12;3597:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;3688:71;-1:-1;3796:2;3849:22;;2070:20;2095:47;2070:20;2095:47;:::i;:::-;3804:77;-1:-1;3918:2;3957:22;;2905:20;;-1:-1;4026:2;4065:22;;2905:20;;-1:-1;4162:3;4147:19;;4134:33;-1:-1;;;;;4176:30;;;4173:2;;;-1:-1;;4209:12;4173:2;4247:80;4319:7;4310:6;4299:9;4295:22;4247:80;:::i;:::-;4229:98;;-1:-1;4229:98;-1:-1;4392:3;4377:19;;4364:33;;-1:-1;4406:30;;;4403:2;;;-1:-1;;4439:12;4403:2;;4477:64;4533:7;4524:6;4513:9;4509:22;4477:64;:::i;:::-;3591:966;;;;-1:-1;3591:966;;-1:-1;3591:966;;;;;;4459:82;-1:-1;;;3591:966::o;4564:789::-;;;;;;4762:3;4750:9;4741:7;4737:23;4733:33;4730:2;;;-1:-1;;4769:12;4730:2;230:6;217:20;242:41;277:5;242:41;:::i;:::-;4821:71;-1:-1;4929:2;4968:22;;2905:20;;-1:-1;5037:2;5076:22;;2905:20;;-1:-1;5173:2;5158:18;;5145:32;-1:-1;;;;;5186:30;;5183:2;;;-1:-1;;5219:12;5183:2;5257:80;5329:7;5320:6;5309:9;5305:22;5257:80;:::i;:::-;4724:629;;;;-1:-1;4724:629;;-1:-1;5239:98;;;4724:629;-1:-1;;;4724:629::o;5360:257::-;;5472:2;5460:9;5451:7;5447:23;5443:32;5440:2;;;-1:-1;;5478:12;5440:2;1577:6;1571:13;55096:5;52978:13;52971:21;55074:5;55071:32;55061:2;;-1:-1;;55107:12;5900:394;;;6035:2;6023:9;6014:7;6010:23;6006:32;6003:2;;;-1:-1;;6041:12;6003:2;2083:6;2070:20;2095:47;2136:5;2095:47;:::i;:::-;6093:77;6207:2;6246:22;;;;2905:20;;-1:-1;;;5997:297::o;7109:943::-;;;;;;;7338:3;7326:9;7317:7;7313:23;7309:33;7306:2;;;-1:-1;;7345:12;7306:2;2083:6;2070:20;2095:47;2136:5;2095:47;:::i;:::-;7397:77;-1:-1;7511:2;7550:22;;2905:20;;-1:-1;7619:2;7658:22;;2905:20;;-1:-1;7755:2;7740:18;;7727:32;-1:-1;;;;;7768:30;;7765:2;;;-1:-1;;7801:12;7765:2;7839:80;7911:7;7902:6;7891:9;7887:22;7839:80;:::i;:::-;7821:98;;-1:-1;7821:98;-1:-1;;7956:3;8004:22;;217:20;242:41;217:20;242:41;:::i;:::-;7965:71;;;;7300:752;;;;;;;;:::o;8059:1051::-;;;;;;;;8299:3;8287:9;8278:7;8274:23;8270:33;8267:2;;;-1:-1;;8306:12;8267:2;2083:6;2070:20;2095:47;2136:5;2095:47;:::i;:::-;8358:77;-1:-1;8472:2;8511:22;;2905:20;;-1:-1;8580:2;8619:22;;2905:20;;-1:-1;8716:2;8701:18;;8688:32;-1:-1;;;;;8729:30;;;8726:2;;;-1:-1;;8762:12;8726:2;8800:80;8872:7;8863:6;8852:9;8848:22;8800:80;:::i;:::-;8782:98;;-1:-1;8782:98;-1:-1;8945:3;8930:19;;8917:33;;-1:-1;8959:30;;;8956:2;;;-1:-1;;8992:12;8956:2;;9030:64;9086:7;9077:6;9066:9;9062:22;9030:64;:::i;:::-;8261:849;;;;-1:-1;8261:849;;-1:-1;8261:849;;;;9012:82;;-1:-1;;;8261:849::o;9117:1193::-;;;;;;;;;9382:3;9370:9;9361:7;9357:23;9353:33;9350:2;;;-1:-1;;9389:12;9350:2;2083:6;2070:20;2095:47;2136:5;2095:47;:::i;:::-;9441:77;-1:-1;9555:2;9594:22;;2905:20;;-1:-1;9663:2;9702:22;;2905:20;;-1:-1;9799:2;9784:18;;9771:32;-1:-1;;;;;9812:30;;;9809:2;;;-1:-1;;9845:12;9809:2;9883:80;9955:7;9946:6;9935:9;9931:22;9883:80;:::i;:::-;9865:98;;-1:-1;9865:98;-1:-1;10028:3;10013:19;;10000:33;;-1:-1;10042:30;;;10039:2;;;-1:-1;;10075:12;10039:2;;10113:64;10169:7;10160:6;10149:9;10145:22;10113:64;:::i;:::-;10095:82;;-1:-1;10095:82;-1:-1;;10214:3;10262:22;;217:20;242:41;217:20;242:41;:::i;:::-;10223:71;;;;9344:966;;;;;;;;;;;:::o;10317:923::-;;;;;10585:2;10573:9;10564:7;10560:23;10556:32;10553:2;;;-1:-1;;10591:12;10553:2;2259:6;2246:20;2271:58;2323:5;2271:58;:::i;:::-;10643:88;-1:-1;10796:2;10781:18;;10768:32;-1:-1;;;;;10809:30;;;10806:2;;;-1:-1;;10842:12;10806:2;10928:22;;;;2783:3;2765:16;;;2761:26;2758:2;;;-1:-1;;2790:12;2758:2;10862:98;;-1:-1;11025:2;11010:18;;10997:32;;11038:30;;;11035:2;;;-1:-1;;11071:12;11035:2;;11109:115;11216:7;11207:6;11196:9;11192:22;11109:115;:::i;:::-;10547:693;;;;-1:-1;11091:133;-1:-1;;;;10547:693::o;11247:395::-;;;11377:2;11365:9;11356:7;11352:23;11348:32;11345:2;;;-1:-1;;11383:12;11345:2;-1:-1;;2553:13;;11545:2;11594:22;;;2553:13;;;;;-1:-1;11339:303::o;11649:611::-;;;;;11804:2;11792:9;11783:7;11779:23;11775:32;11772:2;;;-1:-1;;11810:12;11772:2;2420:6;2407:20;11862:62;;11961:2;12003:9;11999:22;2407:20;11969:62;;12096:2;12085:9;12081:18;12068:32;-1:-1;;;;;12112:6;12109:30;12106:2;;;-1:-1;;12142:12;12106:2;12180:64;12236:7;12227:6;12216:9;12212:22;12180:64;:::i;12267:263::-;;12382:2;12370:9;12361:7;12357:23;12353:32;12350:2;;;-1:-1;;12388:12;12350:2;-1:-1;3053:13;;12344:186;-1:-1;12344:186::o;12537:647::-;;;;;12710:2;12698:9;12689:7;12685:23;12681:32;12678:2;;;-1:-1;;12716:12;12678:2;2918:6;2905:20;12768:63;;12868:2;12911:9;12907:22;2905:20;12876:63;;13004:2;12993:9;12989:18;12976:32;-1:-1;;;;;13020:6;13017:30;13014:2;;;-1:-1;;13050:12;13014:2;13088:80;13160:7;13151:6;13140:9;13136:22;13088:80;:::i;15247:277::-;;50883:6;50878:3;50871:19;54136:6;54131:3;50920:4;50915:3;50911:14;54113:30;-1:-1;50920:4;54183:6;50915:3;54174:16;;54167:27;50920:4;54730:7;;54734:2;15510:6;54714:14;54710:28;50915:3;15479:39;;15472:46;;15337:187;;;;;:::o;15873:343::-;;16015:5;50397:12;50883:6;50878:3;50871:19;16108:52;16153:6;50920:4;50915:3;50911:14;50920:4;16134:5;16130:16;16108:52;:::i;:::-;54730:7;54714:14;-1:-1;;54710:28;16172:39;;;;50920:4;16172:39;;15963:253;-1:-1;;15963:253::o;30154:425::-;-1:-1;;;;;;53065:78;;15156:56;;30154:425;54136:6;54131:3;30431:1;30422:11;;54113:30;54174:16;;30431:1;54174:16;54167:27;;;54174:16;30324:255;-1:-1;;30324:255::o;30586:271::-;;16383:5;50397:12;16494:52;16539:6;16534:3;16527:4;16520:5;16516:16;16494:52;:::i;:::-;16558:16;;;;;30720:137;-1:-1;;30720:137::o;30864:542::-;;16383:5;50397:12;16494:52;16539:6;16534:3;16527:4;16520:5;16516:16;16494:52;:::i;:::-;-1:-1;;;16558:16;;18027:32;;;-1:-1;18012:1;18078:11;;31101:305;-1:-1;31101:305::o;31413:970::-;;16383:5;50397:12;16494:52;16539:6;16534:3;16527:4;16520:5;16516:16;16494:52;:::i;:::-;-1:-1;;;16558:16;;;22554:29;;;50397:12;;16494:52;50397:12;22539:1;22602:11;;16527:4;16516:16;;16494:52;:::i;:::-;-1:-1;;;22539:1;16558:16;;;;;;;21885:24;21928:11;;;31799:584;-1:-1;;;;31799:584::o;32390:970::-;;16383:5;50397:12;16494:52;16539:6;16534:3;16527:4;16520:5;16516:16;16494:52;:::i;:::-;-1:-1;;;16558:16;;;28435:29;;;50397:12;;16494:52;50397:12;28420:1;28483:11;;16527:4;16516:16;;16494:52;:::i;33367:379::-;33731:10;33555:191::o;33753:253::-;16655:36;;;33978:2;33969:12;;33869:137::o;34013:222::-;-1:-1;;;;;53530:54;;;;13709:37;;34140:2;34125:18;;34111:124::o;34487:444::-;-1:-1;;;;;53530:54;;;13709:37;;53530:54;;;;34834:2;34819:18;;13709:37;34917:2;34902:18;;16655:36;;;;34670:2;34655:18;;34641:290::o;34938:736::-;-1:-1;;;;;53530:54;;;13709:37;;52978:13;;52971:21;35346:2;35331:18;;15023:34;35427:2;35412:18;;16655:36;;;53530:54;;35510:2;35495:18;;29716:37;53541:42;35547:3;35532:19;;35525:49;;;34938:736;;35588:76;;35172:19;;35650:6;35588:76;:::i;35681:333::-;-1:-1;;;;;53530:54;;;;13709:37;;36000:2;35985:18;;16655:36;35836:2;35821:18;;35807:207::o;36021:892::-;-1:-1;;;;;53530:54;;;13709:37;;36481:2;36466:18;;16655:36;;;;36564:2;36549:18;;16655:36;;;;36647:2;36632:18;;16655:36;;;;36730:3;36715:19;;16655:36;53541:42;36799:19;;16655:36;53530:54;;;36898:3;36883:19;;13709:37;36316:3;36301:19;;36287:626::o;36920:526::-;37175:2;37189:47;;;37160:18;;;50871:19;;;36920:526;;50911:14;;;;14247:17;;;14238:27;;;;14385:21;36920:526;14412:499;14437:6;14434:1;14431:13;14412:499;;;14489:20;;;-1:-1;;14489:20;14477:33;;52388:17;;52453:14;52449:29;;;-1:-1;;52445:48;52421:73;;52411:2;;-1:-1;;52498:12;52411:2;52527:33;;2905:20;;16655:36;;52681:12;;;2905:20;29113:14;;;16655:36;29224:16;;;2905:20;29295:14;;;16655:36;28756:4;29441;29430:16;;;51862:17;52453:14;51923:29;;;-1:-1;;51919:48;51895:73;;51885:2;;-1:-1;;51972:12;51885:2;52001:33;;52056:19;;-1:-1;;;;;52115:30;;52112:2;;;-1:-1;;52148:12;52112:2;52205:17;52453:14;52185:38;52175:8;52171:53;52168:2;;;-1:-1;;52227:12;52168:2;28756:4;29441;29471:3;29467:14;29460:38;29513:87;28756:4;28751:3;28747:14;29581:12;37175:2;52094:5;52090:16;29513:87;:::i;:::-;14890:14;;;;14622:140;-1:-1;;;50693:14;;;;-1:-1;;;14459:1;14452:9;14412:499;;;-1:-1;37242:194;;37146:300;-1:-1;;;;;;;;37146:300::o;37453:210::-;52978:13;;52971:21;15023:34;;37574:2;37559:18;;37545:118::o;37670:310::-;;37817:2;37838:17;37831:47;37892:78;37817:2;37806:9;37802:18;37956:6;37892:78;:::i;37987:416::-;38187:2;38201:47;;;17649:2;38172:18;;;50871:19;-1:-1;;;50911:14;;;17665:41;17725:12;;;38158:245::o;38410:416::-;38610:2;38624:47;;;18328:2;38595:18;;;50871:19;18364:34;50911:14;;;18344:55;-1:-1;;;18419:12;;;18412:30;18461:12;;;38581:245::o;38833:416::-;39033:2;39047:47;;;18712:2;39018:18;;;50871:19;18748:29;50911:14;;;18728:50;18797:12;;;39004:245::o;39256:416::-;39456:2;39470:47;;;19048:2;39441:18;;;50871:19;19084:28;50911:14;;;19064:49;19132:12;;;39427:245::o;39679:416::-;39879:2;39893:47;;;19383:2;39864:18;;;50871:19;-1:-1;;;50911:14;;;19399:45;19463:12;;;39850:245::o;40102:416::-;40302:2;40316:47;;;19714:2;40287:18;;;50871:19;-1:-1;;;50911:14;;;19730:43;19792:12;;;40273:245::o;40525:416::-;40725:2;40739:47;;;20043:2;40710:18;;;50871:19;-1:-1;;;50911:14;;;20059:40;20118:12;;;40696:245::o;40948:416::-;41148:2;41162:47;;;20369:2;41133:18;;;50871:19;20405:32;50911:14;;;20385:53;20457:12;;;41119:245::o;41371:416::-;41571:2;41585:47;;;20708:2;41556:18;;;50871:19;20744:34;50911:14;;;20724:55;20813:28;20799:12;;;20792:50;20861:12;;;41542:245::o;41794:416::-;41994:2;42008:47;;;21112:2;41979:18;;;50871:19;21148:31;50911:14;;;21128:52;21199:12;;;41965:245::o;42217:416::-;42417:2;42431:47;;;21450:2;42402:18;;;50871:19;21486:34;50911:14;;;21466:55;-1:-1;;;21541:12;;;21534:30;21583:12;;;42388:245::o;42640:416::-;42840:2;42854:47;;;22178:2;42825:18;;;50871:19;-1:-1;;;50911:14;;;22194:39;22252:12;;;42811:245::o;43063:416::-;43263:2;43277:47;;;22852:2;43248:18;;;50871:19;-1:-1;;;50911:14;;;22868:44;22931:12;;;43234:245::o;43486:416::-;43686:2;43700:47;;;43671:18;;;50871:19;23218:34;50911:14;;;23198:55;23272:12;;;43657:245::o;43909:416::-;44109:2;44123:47;;;23523:2;44094:18;;;50871:19;23559:34;50911:14;;;23539:55;-1:-1;;;23614:12;;;23607:38;23664:12;;;44080:245::o;44332:416::-;44532:2;44546:47;;;23915:2;44517:18;;;50871:19;23951:29;50911:14;;;23931:50;24000:12;;;44503:245::o;44755:416::-;44955:2;44969:47;;;24251:2;44940:18;;;50871:19;24287:28;50911:14;;;24267:49;24335:12;;;44926:245::o;45178:416::-;45378:2;45392:47;;;24586:2;45363:18;;;50871:19;24622:34;50911:14;;;24602:55;-1:-1;;;24677:12;;;24670:25;24714:12;;;45349:245::o;45601:416::-;45801:2;45815:47;;;45786:18;;;50871:19;25001:34;50911:14;;;24981:55;25055:12;;;45772:245::o;46024:416::-;46224:2;46238:47;;;25306:2;46209:18;;;50871:19;-1:-1;;;50911:14;;;25322:45;25386:12;;;46195:245::o;46447:416::-;46647:2;46661:47;;;25637:2;46632:18;;;50871:19;-1:-1;;;50911:14;;;25653:42;25714:12;;;46618:245::o;46870:416::-;47070:2;47084:47;;;25965:2;47055:18;;;50871:19;-1:-1;;;50911:14;;;25981:44;26044:12;;;47041:245::o;47293:416::-;47493:2;47507:47;;;26600:2;47478:18;;;50871:19;26636:31;50911:14;;;26616:52;26687:12;;;47464:245::o;47716:416::-;47916:2;47930:47;;;26938:2;47901:18;;;50871:19;26974:34;50911:14;;;26954:55;-1:-1;;;27029:12;;;27022:32;27073:12;;;47887:245::o;48139:416::-;48339:2;48353:47;;;48324:18;;;50871:19;27360:34;50911:14;;;27340:55;27414:12;;;48310:245::o;48562:416::-;48762:2;48776:47;;;27665:2;48747:18;;;50871:19;27701:34;50911:14;;;27681:55;-1:-1;;;27756:12;;;27749:34;27802:12;;;48733:245::o;48985:416::-;49185:2;49199:47;;;28053:2;49170:18;;;50871:19;-1:-1;;;50911:14;;;28069:45;28133:12;;;49156:245::o;49637:506::-;;;49772:11;49759:25;51919:48;;49847:8;49831:14;49827:29;49823:48;49803:18;49799:73;49789:2;;-1:-1;;49876:12;49789:2;49903:33;;49957:18;;;-1:-1;;;;;;49984:30;;49981:2;;;-1:-1;;50017:12;49981:2;49862:4;50045:13;;-1:-1;49831:14;50077:38;;;50067:49;;50064:2;;;50129:1;;50119:12;54209:268;54274:1;54281:101;54295:6;54292:1;54289:13;54281:101;;;54362:11;;;54356:18;54343:11;;;54336:39;54317:2;54310:10;54281:101;;;54397:6;54394:1;54391:13;54388:2;;;-1:-1;;54274:1;54444:16;;54437:27;54258:219::o;54751:117::-;-1:-1;;;;;53530:54;;54810:35;;54800:2;;54859:1;;54849:12

Metadata Hash

876629cfe1567383e5c95b259a804464609b178622e5f5d989ab082a14a156c1
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.