ETH Price: $2,063.11 (+4.16%)

Token

ERC20 ***

Overview

Max Total Supply

0.000000000034002349 ERC20 ***

Holders

82

Total Transfers

-

Market

Price

$0.00 @ 0.000000 ETH

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
Hypervisor

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at zkevm.polygonscan.com on 2023-05-02
*/

pragma solidity =0.7.6;
pragma abicoder v2;

// Sources flattened with hardhat v2.13.0 https://hardhat.org

// File @openzeppelin/contracts/cryptography/[email protected]



/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            revert("ECDSA: invalid signature length");
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        return recover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
        require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}


// File @openzeppelin/contracts/drafts/[email protected]



/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;
    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) internal {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = _getChainId();
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view virtual returns (bytes32) {
        if (_getChainId() == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {
        return keccak256(
            abi.encode(
                typeHash,
                name,
                version,
                _getChainId(),
                address(this)
            )
        );
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
    }

    function _getChainId() private view returns (uint256 chainId) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        // solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }
    }
}


// File @openzeppelin/contracts/drafts/[email protected]



/**
 * @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 @openzeppelin/contracts/math/[email protected]



/**
 * @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/token/ERC20/[email protected]



/**
 * @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/utils/[email protected]



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


// File @openzeppelin/contracts/token/ERC20/[email protected]





/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal virtual {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}


// File @openzeppelin/contracts/utils/[email protected]



/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
 * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
 * directly accessed.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        // The {SafeMath} overflow check can be skipped here, see the comment at the top
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}


// File @openzeppelin/contracts/drafts/[email protected]







/**
 * @dev Implementation 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.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping (address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private immutable _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) internal EIP712(name, "1") {
    }

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
        // solhint-disable-next-line not-rely-on-time
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(
            abi.encode(
                _PERMIT_TYPEHASH,
                owner,
                spender,
                value,
                _nonces[owner].current(),
                deadline
            )
        );

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _nonces[owner].increment();
        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }
}


// File @openzeppelin/contracts/utils/[email protected]



/**
 * @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/[email protected]





/**
 * @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 @uniswap/v3-core/contracts/libraries/[email protected]


/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
    uint8 internal constant RESOLUTION = 96;
    uint256 internal constant Q96 = 0x1000000000000000000000000;
}


// File @uniswap/v3-core/contracts/libraries/[email protected]


/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 512-bit multiply [prod1 prod0] = a * b
        // Compute the product mod 2**256 and mod 2**256 - 1
        // then use the Chinese Remainder Theorem to reconstruct
        // the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2**256 + prod0
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(a, b, not(0))
            prod0 := mul(a, b)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        // Handle non-overflow cases, 256 by 256 division
        if (prod1 == 0) {
            require(denominator > 0);
            assembly {
                result := div(prod0, denominator)
            }
            return result;
        }

        // Make sure the result is less than 2**256.
        // Also prevents denominator == 0
        require(denominator > prod1);

        ///////////////////////////////////////////////
        // 512 by 256 division.
        ///////////////////////////////////////////////

        // Make division exact by subtracting the remainder from [prod1 prod0]
        // Compute remainder using mulmod
        uint256 remainder;
        assembly {
            remainder := mulmod(a, b, denominator)
        }
        // Subtract 256 bit number from 512 bit number
        assembly {
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }

        // Factor powers of two out of denominator
        // Compute largest power of two divisor of denominator.
        // Always >= 1.
        uint256 twos = -denominator & denominator;
        // Divide denominator by power of two
        assembly {
            denominator := div(denominator, twos)
        }

        // Divide [prod1 prod0] by the factors of two
        assembly {
            prod0 := div(prod0, twos)
        }
        // Shift in bits from prod1 into prod0. For this we need
        // to flip `twos` such that it is 2**256 / twos.
        // If twos is zero, then it becomes one
        assembly {
            twos := add(div(sub(0, twos), twos), 1)
        }
        prod0 |= prod1 * twos;

        // Invert denominator mod 2**256
        // Now that denominator is an odd number, it has an inverse
        // modulo 2**256 such that denominator * inv = 1 mod 2**256.
        // Compute the inverse by starting with a seed that is correct
        // correct for four bits. That is, denominator * inv = 1 mod 2**4
        uint256 inv = (3 * denominator) ^ 2;
        // Now use Newton-Raphson iteration to improve the precision.
        // Thanks to Hensel's lifting lemma, this also works in modular
        // arithmetic, doubling the correct bits in each step.
        inv *= 2 - denominator * inv; // inverse mod 2**8
        inv *= 2 - denominator * inv; // inverse mod 2**16
        inv *= 2 - denominator * inv; // inverse mod 2**32
        inv *= 2 - denominator * inv; // inverse mod 2**64
        inv *= 2 - denominator * inv; // inverse mod 2**128
        inv *= 2 - denominator * inv; // inverse mod 2**256

        // Because the division is now exact we can divide by multiplying
        // with the modular inverse of denominator. This will give us the
        // correct result modulo 2**256. Since the precoditions guarantee
        // that the outcome is less than 2**256, this is the final result.
        // We don't need to compute the high bits of the result and prod1
        // is no longer required.
        result = prod0 * inv;
        return result;
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        result = mulDiv(a, b, denominator);
        if (mulmod(a, b, denominator) > 0) {
            require(result < type(uint256).max);
            result++;
        }
    }
}


// File @uniswap/v3-periphery/contracts/libraries/[email protected]



/// @title Liquidity amount functions
/// @notice Provides functions for computing liquidity amounts from token amounts and prices
library LiquidityAmounts {
    /// @notice Downcasts uint256 to uint128
    /// @param x The uint258 to be downcasted
    /// @return y The passed value, downcasted to uint128
    function toUint128(uint256 x) private pure returns (uint128 y) {
        require((y = uint128(x)) == x);
    }

    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range
    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount0 The amount0 being sent in
    /// @return liquidity The amount of returned liquidity
    function getLiquidityForAmount0(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount0
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
        uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);
        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));
    }

    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range
    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount1 The amount1 being sent in
    /// @return liquidity The amount of returned liquidity
    function getLiquidityForAmount1(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount1
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));
    }

    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current
    /// pool prices and the prices at the tick boundaries
    /// @param sqrtRatioX96 A sqrt price representing the current pool prices
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param amount0 The amount of token0 being sent in
    /// @param amount1 The amount of token1 being sent in
    /// @return liquidity The maximum amount of liquidity received
    function getLiquidityForAmounts(
        uint160 sqrtRatioX96,
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint256 amount0,
        uint256 amount1
    ) internal pure returns (uint128 liquidity) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        if (sqrtRatioX96 <= sqrtRatioAX96) {
            liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
        } else if (sqrtRatioX96 < sqrtRatioBX96) {
            uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
            uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);

            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
        } else {
            liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
        }
    }

    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount0 The amount of token0
    function getAmount0ForLiquidity(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount0) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        return
            FullMath.mulDiv(
                uint256(liquidity) << FixedPoint96.RESOLUTION,
                sqrtRatioBX96 - sqrtRatioAX96,
                sqrtRatioBX96
            ) / sqrtRatioAX96;
    }

    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount1 The amount of token1
    function getAmount1ForLiquidity(
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount1) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);
    }

    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current
    /// pool prices and the prices at the tick boundaries
    /// @param sqrtRatioX96 A sqrt price representing the current pool prices
    /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
    /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
    /// @param liquidity The liquidity being valued
    /// @return amount0 The amount of token0
    /// @return amount1 The amount of token1
    function getAmountsForLiquidity(
        uint160 sqrtRatioX96,
        uint160 sqrtRatioAX96,
        uint160 sqrtRatioBX96,
        uint128 liquidity
    ) internal pure returns (uint256 amount0, uint256 amount1) {
        if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

        if (sqrtRatioX96 <= sqrtRatioAX96) {
            amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
        } else if (sqrtRatioX96 < sqrtRatioBX96) {
            amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);
            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);
        } else {
            amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
        }
    }
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolActions.sol


/// @title Permissionless pool actions
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolActions {
  /**
   * @notice Sets the initial price for the pool
   * @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value
   * @param price the initial sqrt price of the pool as a Q64.96
   */
  function initialize(uint160 price) external;

  /**
   * @notice Adds liquidity for the given recipient/bottomTick/topTick position
   * @dev The caller of this method receives a callback in the form of IAlgebraMintCallback# AlgebraMintCallback
   * in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends
   * on bottomTick, topTick, the amount of liquidity, and the current price.
   * @param sender The address which will receive potential surplus of paid tokens
   * @param recipient The address for which the liquidity will be created
   * @param bottomTick The lower tick of the position in which to add liquidity
   * @param topTick The upper tick of the position in which to add liquidity
   * @param amount The desired amount of liquidity to mint
   * @param data Any data that should be passed through to the callback
   * @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback
   * @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback
   * @return liquidityActual The actual minted amount of liquidity
   */
  function mint(
    address sender,
    address recipient,
    int24 bottomTick,
    int24 topTick,
    uint128 amount,
    bytes calldata data
  )
    external
    returns (
      uint256 amount0,
      uint256 amount1,
      uint128 liquidityActual
    );

  /**
   * @notice Collects tokens owed to a position
   * @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.
   * Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or
   * amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the
   * actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.
   * @param recipient The address which should receive the fees collected
   * @param bottomTick The lower tick of the position for which to collect fees
   * @param topTick The upper tick of the position for which to collect fees
   * @param amount0Requested How much token0 should be withdrawn from the fees owed
   * @param amount1Requested How much token1 should be withdrawn from the fees owed
   * @return amount0 The amount of fees collected in token0
   * @return amount1 The amount of fees collected in token1
   */
  function collect(
    address recipient,
    int24 bottomTick,
    int24 topTick,
    uint128 amount0Requested,
    uint128 amount1Requested
  ) external returns (uint128 amount0, uint128 amount1);

  /**
   * @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position
   * @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0
   * @dev Fees must be collected separately via a call to #collect
   * @param bottomTick The lower tick of the position for which to burn liquidity
   * @param topTick The upper tick of the position for which to burn liquidity
   * @param amount How much liquidity to burn
   * @return amount0 The amount of token0 sent to the recipient
   * @return amount1 The amount of token1 sent to the recipient
   */
  function burn(
    int24 bottomTick,
    int24 topTick,
    uint128 amount
  ) external returns (uint256 amount0, uint256 amount1);

  /**
   * @notice Swap token0 for token1, or token1 for token0
   * @dev The caller of this method receives a callback in the form of IAlgebraSwapCallback# AlgebraSwapCallback
   * @param recipient The address to receive the output of the swap
   * @param zeroToOne 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 limitSqrtPrice 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. If using the Router it should contain
   * SwapRouter#SwapCallbackData
   * @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 zeroToOne,
    int256 amountSpecified,
    uint160 limitSqrtPrice,
    bytes calldata data
  ) external returns (int256 amount0, int256 amount1);

  /**
   * @notice Swap token0 for token1, or token1 for token0 (tokens that have fee on transfer)
   * @dev The caller of this method receives a callback in the form of I AlgebraSwapCallback# AlgebraSwapCallback
   * @param sender The address called this function (Comes from the Router)
   * @param recipient The address to receive the output of the swap
   * @param zeroToOne 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 limitSqrtPrice 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. If using the Router it should contain
   * SwapRouter#SwapCallbackData
   * @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 swapSupportingFeeOnInputTokens(
    address sender,
    address recipient,
    bool zeroToOne,
    int256 amountSpecified,
    uint160 limitSqrtPrice,
    bytes calldata data
  ) external returns (int256 amount0, int256 amount1);

  /**
   * @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
   * @dev The caller of this method receives a callback in the form of IAlgebraFlashCallback# AlgebraFlashCallback
   * @dev All excess tokens paid in the callback are distributed to liquidity providers as an additional fee. So this method can be used
   * to donate underlying tokens to currently in-range liquidity providers by calling with 0 amount{0,1} and sending
   * the donation amount(s) from the callback
   * @param recipient The address which will receive the token0 and token1 amounts
   * @param amount0 The amount of token0 to send
   * @param amount1 The amount of token1 to send
   * @param data Any data to be passed through to the callback
   */
  function flash(
    address recipient,
    uint256 amount0,
    uint256 amount1,
    bytes calldata data
  ) external;
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolDerivedState.sol


/**
 * @title Pool state that is not stored
 * @notice Contains view functions to provide information about the pool that is computed rather than stored on the
 * blockchain. The functions here may have variable gas costs.
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPoolDerivedState {
  /**
   * @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp
   * @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing
   * the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,
   * you must call it with secondsAgos = [3600, 0].
   * @dev The time weighted average tick represents the geometric time weighted average price of the pool, in
   * log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.
   * @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned
   * @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp
   * @return secondsPerLiquidityCumulatives Cumulative seconds per liquidity-in-range value as of each `secondsAgos`
   * from the current block timestamp
   * @return volatilityCumulatives Cumulative standard deviation as of each `secondsAgos`
   * @return volumePerAvgLiquiditys Cumulative swap volume per liquidity as of each `secondsAgos`
   */
  function getTimepoints(uint32[] calldata secondsAgos)
    external
    view
    returns (
      int56[] memory tickCumulatives,
      uint160[] memory secondsPerLiquidityCumulatives,
      uint112[] memory volatilityCumulatives,
      uint256[] memory volumePerAvgLiquiditys
    );

  /**
   * @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range
   * @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.
   * I.e., snapshots cannot be compared if a position is not held for the entire period between when the first
   * snapshot is taken and the second snapshot is taken.
   * @param bottomTick The lower tick of the range
   * @param topTick The upper tick of the range
   * @return innerTickCumulative The snapshot of the tick accumulator for the range
   * @return innerSecondsSpentPerLiquidity The snapshot of seconds per liquidity for the range
   * @return innerSecondsSpent The snapshot of the number of seconds during which the price was in this range
   */
  function getInnerCumulatives(int24 bottomTick, int24 topTick)
    external
    view
    returns (
      int56 innerTickCumulative,
      uint160 innerSecondsSpentPerLiquidity,
      uint32 innerSecondsSpent
    );
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolEvents.sol


/// @title Events emitted by a pool
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolEvents {
  /**
   * @notice Emitted exactly once by a pool when #initialize is first called on the pool
   * @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize
   * @param price The initial sqrt price of the pool, as a Q64.96
   * @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool
   */
  event Initialize(uint160 price, int24 tick);

  /**
   * @notice Emitted when liquidity is minted for a given position
   * @param sender The address that minted the liquidity
   * @param owner The owner of the position and recipient of any minted liquidity
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param liquidityAmount The amount of liquidity minted to the position range
   * @param amount0 How much token0 was required for the minted liquidity
   * @param amount1 How much token1 was required for the minted liquidity
   */
  event Mint(
    address sender,
    address indexed owner,
    int24 indexed bottomTick,
    int24 indexed topTick,
    uint128 liquidityAmount,
    uint256 amount0,
    uint256 amount1
  );

  /**
   * @notice Emitted when fees are collected by the owner of a position
   * @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees
   * @param owner The owner of the position for which fees are collected
   * @param recipient The address that received fees
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param amount0 The amount of token0 fees collected
   * @param amount1 The amount of token1 fees collected
   */
  event Collect(address indexed owner, address recipient, int24 indexed bottomTick, int24 indexed topTick, uint128 amount0, uint128 amount1);

  /**
   * @notice Emitted when a position's liquidity is removed
   * @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect
   * @param owner The owner of the position for which liquidity is removed
   * @param bottomTick The lower tick of the position
   * @param topTick The upper tick of the position
   * @param liquidityAmount The amount of liquidity to remove
   * @param amount0 The amount of token0 withdrawn
   * @param amount1 The amount of token1 withdrawn
   */
  event Burn(address indexed owner, int24 indexed bottomTick, int24 indexed topTick, uint128 liquidityAmount, uint256 amount0, uint256 amount1);

  /**
   * @notice Emitted by the pool for any swaps between token0 and token1
   * @param sender The address that initiated the swap call, and that received the callback
   * @param recipient The address that received the output of the swap
   * @param amount0 The delta of the token0 balance of the pool
   * @param amount1 The delta of the token1 balance of the pool
   * @param price The sqrt(price) of the pool after the swap, as a Q64.96
   * @param liquidity The liquidity of the pool after the swap
   * @param tick The log base 1.0001 of price of the pool after the swap
   */
  event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 price, uint128 liquidity, int24 tick);

  /**
   * @notice Emitted by the pool for any flashes of token0/token1
   * @param sender The address that initiated the swap call, and that received the callback
   * @param recipient The address that received the tokens from flash
   * @param amount0 The amount of token0 that was flashed
   * @param amount1 The amount of token1 that was flashed
   * @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee
   * @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee
   */
  event Flash(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1);

  /**
   * @notice Emitted when the community fee is changed by the pool
   * @param communityFee0New The updated value of the token0 community fee percent
   * @param communityFee1New The updated value of the token1 community fee percent
   */
  event CommunityFee(uint8 communityFee0New, uint8 communityFee1New);

  /**
   * @notice Emitted when new activeIncentive is set
   * @param virtualPoolAddress The address of a virtual pool associated with the current active incentive
   */
  event Incentive(address indexed virtualPoolAddress);

  /**
   * @notice Emitted when the fee changes
   * @param fee The value of the token fee
   */
  event Fee(uint16 fee);

  /**
   * @notice Emitted when the LiquidityCooldown changes
   * @param liquidityCooldown The value of locktime for added liquidity
   */
  event LiquidityCooldown(uint32 liquidityCooldown);
}


// File contracts/algebra/libraries/Constants.sol


library Constants {
  uint8 internal constant RESOLUTION = 96;
  uint256 internal constant Q96 = 0x1000000000000000000000000;
  uint256 internal constant Q128 = 0x100000000000000000000000000000000;
  // fee value in hundredths of a bip, i.e. 1e-6
  uint16 internal constant BASE_FEE = 100;
  int24 internal constant TICK_SPACING = 60;

  // max(uint128) / ( (MAX_TICK - MIN_TICK) / TICK_SPACING )
  uint128 internal constant MAX_LIQUIDITY_PER_TICK = 11505743598341114571880798222544994;

  uint32 internal constant MAX_LIQUIDITY_COOLDOWN = 1 days;
  uint8 internal constant MAX_COMMUNITY_FEE = 250;
  uint256 internal constant COMMUNITY_FEE_DENOMINATOR = 1000;
}


// File contracts/algebra/libraries/AdaptiveFee.sol


/// @title AdaptiveFee
/// @notice Calculates fee based on combination of sigmoids
library AdaptiveFee {
  // alpha1 + alpha2 + baseFee must be <= type(uint16).max
  struct Configuration {
    uint16 alpha1; // max value of the first sigmoid
    uint16 alpha2; // max value of the second sigmoid
    uint32 beta1; // shift along the x-axis for the first sigmoid
    uint32 beta2; // shift along the x-axis for the second sigmoid
    uint16 gamma1; // horizontal stretch factor for the first sigmoid
    uint16 gamma2; // horizontal stretch factor for the second sigmoid
    uint32 volumeBeta; // shift along the x-axis for the outer volume-sigmoid
    uint16 volumeGamma; // horizontal stretch factor the outer volume-sigmoid
    uint16 baseFee; // minimum possible fee
  }

  /// @notice Calculates fee based on formula:
  /// baseFee + sigmoidVolume(sigmoid1(volatility, volumePerLiquidity) + sigmoid2(volatility, volumePerLiquidity))
  /// maximum value capped by baseFee + alpha1 + alpha2
  function getFee(
    uint88 volatility,
    uint256 volumePerLiquidity,
    Configuration memory config
  ) internal pure returns (uint16 fee) {
    uint256 sumOfSigmoids = sigmoid(volatility, config.gamma1, config.alpha1, config.beta1) +
      sigmoid(volatility, config.gamma2, config.alpha2, config.beta2);

    if (sumOfSigmoids > type(uint16).max) {
      // should be impossible, just in case
      sumOfSigmoids = type(uint16).max;
    }

    return uint16(config.baseFee + sigmoid(volumePerLiquidity, config.volumeGamma, uint16(sumOfSigmoids), config.volumeBeta)); // safe since alpha1 + alpha2 + baseFee _must_ be <= type(uint16).max
  }

  /// @notice calculates α / (1 + e^( (β-x) / γ))
  /// that is a sigmoid with a maximum value of α, x-shifted by β, and stretched by γ
  /// @dev returns uint256 for fuzzy testing. Guaranteed that the result is not greater than alpha
  function sigmoid(
    uint256 x,
    uint16 g,
    uint16 alpha,
    uint256 beta
  ) internal pure returns (uint256 res) {
    if (x > beta) {
      x = x - beta;
      if (x >= 6 * uint256(g)) return alpha; // so x < 19 bits
      uint256 g8 = uint256(g)**8; // < 128 bits (8*16)
      uint256 ex = exp(x, g, g8); // < 155 bits
      res = (alpha * ex) / (g8 + ex); // in worst case: (16 + 155 bits) / 155 bits
      // so res <= alpha
    } else {
      x = beta - x;
      if (x >= 6 * uint256(g)) return 0; // so x < 19 bits
      uint256 g8 = uint256(g)**8; // < 128 bits (8*16)
      uint256 ex = g8 + exp(x, g, g8); // < 156 bits
      res = (alpha * g8) / ex; // in worst case: (16 + 128 bits) / 156 bits
      // g8 <= ex, so res <= alpha
    }
  }

  /// @notice calculates e^(x/g) * g^8 in a series, since (around zero):
  /// e^x = 1 + x + x^2/2 + ... + x^n/n! + ...
  /// e^(x/g) = 1 + x/g + x^2/(2*g^2) + ... + x^(n)/(g^n * n!) + ...
  function exp(
    uint256 x,
    uint16 g,
    uint256 gHighestDegree
  ) internal pure returns (uint256 res) {
    // calculating:
    // g**8 + x * g**7 + (x**2 * g**6) / 2 + (x**3 * g**5) / 6 + (x**4 * g**4) / 24 + (x**5 * g**3) / 120 + (x**6 * g^2) / 720 + x**7 * g / 5040 + x**8 / 40320

    // x**8 < 152 bits (19*8) and g**8 < 128 bits (8*16)
    // so each summand < 152 bits and res < 155 bits
    uint256 xLowestDegree = x;
    res = gHighestDegree; // g**8

    gHighestDegree /= g; // g**7
    res += xLowestDegree * gHighestDegree;

    gHighestDegree /= g; // g**6
    xLowestDegree *= x; // x**2
    res += (xLowestDegree * gHighestDegree) / 2;

    gHighestDegree /= g; // g**5
    xLowestDegree *= x; // x**3
    res += (xLowestDegree * gHighestDegree) / 6;

    gHighestDegree /= g; // g**4
    xLowestDegree *= x; // x**4
    res += (xLowestDegree * gHighestDegree) / 24;

    gHighestDegree /= g; // g**3
    xLowestDegree *= x; // x**5
    res += (xLowestDegree * gHighestDegree) / 120;

    gHighestDegree /= g; // g**2
    xLowestDegree *= x; // x**6
    res += (xLowestDegree * gHighestDegree) / 720;

    xLowestDegree *= x; // x**7
    res += (xLowestDegree * g) / 5040 + (xLowestDegree * x) / (40320);
  }
}


// File contracts/algebra/interfaces/IDataStorageOperator.sol


interface IDataStorageOperator {
  event FeeConfiguration(AdaptiveFee.Configuration feeConfig);

  /**
   * @notice Returns data belonging to a certain timepoint
   * @param index The index of timepoint in the array
   * @dev There is more convenient function to fetch a timepoint: observe(). Which requires not an index but seconds
   * @return initialized Whether the timepoint has been initialized and the values are safe to use,
   * blockTimestamp The timestamp of the observation,
   * tickCumulative The tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp,
   * secondsPerLiquidityCumulative The seconds per in range liquidity for the life of the pool as of the timepoint timestamp,
   * volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp,
   * averageTick Time-weighted average tick,
   * volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp
   */
  function timepoints(uint256 index)
    external
    view
    returns (
      bool initialized,
      uint32 blockTimestamp,
      int56 tickCumulative,
      uint160 secondsPerLiquidityCumulative,
      uint88 volatilityCumulative,
      int24 averageTick,
      uint144 volumePerLiquidityCumulative
    );

  /// @notice Initialize the dataStorage array by writing the first slot. Called once for the lifecycle of the timepoints array
  /// @param time The time of the dataStorage initialization, via block.timestamp truncated to uint32
  /// @param tick Initial tick
  function initialize(uint32 time, int24 tick) external;

  /// @dev Reverts if an timepoint at or before the desired timepoint timestamp does not exist.
  /// 0 may be passed as `secondsAgo' to return the current cumulative values.
  /// If called with a timestamp falling between two timepoints, returns the counterfactual accumulator values
  /// at exactly the timestamp between the two timepoints.
  /// @param time The current block timestamp
  /// @param secondsAgo The amount of time to look back, in seconds, at which point to return an timepoint
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return tickCumulative The cumulative tick since the pool was first initialized, as of `secondsAgo`
  /// @return secondsPerLiquidityCumulative The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of `secondsAgo`
  /// @return volatilityCumulative The cumulative volatility value since the pool was first initialized, as of `secondsAgo`
  /// @return volumePerAvgLiquidity The cumulative volume per liquidity value since the pool was first initialized, as of `secondsAgo`
  function getSingleTimepoint(
    uint32 time,
    uint32 secondsAgo,
    int24 tick,
    uint16 index,
    uint128 liquidity
  )
    external
    view
    returns (
      int56 tickCumulative,
      uint160 secondsPerLiquidityCumulative,
      uint112 volatilityCumulative,
      uint256 volumePerAvgLiquidity
    );

  /// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos`
  /// @dev Reverts if `secondsAgos` > oldest timepoint
  /// @param time The current block.timestamp
  /// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an timepoint
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return tickCumulatives The cumulative tick since the pool was first initialized, as of each `secondsAgo`
  /// @return secondsPerLiquidityCumulatives The cumulative seconds / max(1, liquidity) since the pool was first initialized, as of each `secondsAgo`
  /// @return volatilityCumulatives The cumulative volatility values since the pool was first initialized, as of each `secondsAgo`
  /// @return volumePerAvgLiquiditys The cumulative volume per liquidity values since the pool was first initialized, as of each `secondsAgo`
  function getTimepoints(
    uint32 time,
    uint32[] memory secondsAgos,
    int24 tick,
    uint16 index,
    uint128 liquidity
  )
    external
    view
    returns (
      int56[] memory tickCumulatives,
      uint160[] memory secondsPerLiquidityCumulatives,
      uint112[] memory volatilityCumulatives,
      uint256[] memory volumePerAvgLiquiditys
    );

  /// @notice Returns average volatility in the range from time-WINDOW to time
  /// @param time The current block.timestamp
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return TWVolatilityAverage The average volatility in the recent range
  /// @return TWVolumePerLiqAverage The average volume per liquidity in the recent range
  function getAverages(
    uint32 time,
    int24 tick,
    uint16 index,
    uint128 liquidity
  ) external view returns (uint112 TWVolatilityAverage, uint256 TWVolumePerLiqAverage);

  /// @notice Writes an dataStorage timepoint to the array
  /// @dev Writable at most once per block. Index represents the most recently written element. index must be tracked externally.
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param blockTimestamp The timestamp of the new timepoint
  /// @param tick The active tick at the time of the new timepoint
  /// @param liquidity The total in-range liquidity at the time of the new timepoint
  /// @param volumePerLiquidity The gmean(volumes)/liquidity at the time of the new timepoint
  /// @return indexUpdated The new index of the most recently written element in the dataStorage array
  function write(
    uint16 index,
    uint32 blockTimestamp,
    int24 tick,
    uint128 liquidity,
    uint128 volumePerLiquidity
  ) external returns (uint16 indexUpdated);

  /// @notice Changes fee configuration for the pool
  function changeFeeConfiguration(AdaptiveFee.Configuration calldata feeConfig) external;

  /// @notice Calculates gmean(volume/liquidity) for block
  /// @param liquidity The current in-range pool liquidity
  /// @param amount0 Total amount of swapped token0
  /// @param amount1 Total amount of swapped token1
  /// @return volumePerLiquidity gmean(volume/liquidity) capped by 100000 << 64
  function calculateVolumePerLiquidity(
    uint128 liquidity,
    int256 amount0,
    int256 amount1
  ) external pure returns (uint128 volumePerLiquidity);

  /// @return windowLength Length of window used to calculate averages
  function window() external view returns (uint32 windowLength);

  /// @notice Calculates fee based on combination of sigmoids
  /// @param time The current block.timestamp
  /// @param tick The current tick
  /// @param index The index of the timepoint that was most recently written to the timepoints array
  /// @param liquidity The current in-range pool liquidity
  /// @return fee The fee in hundredths of a bip, i.e. 1e-6
  function getFee(
    uint32 time,
    int24 tick,
    uint16 index,
    uint128 liquidity
  ) external view returns (uint16 fee);
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolImmutables.sol


/// @title Pool state that never changes
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolImmutables {
  /**
   * @notice The contract that stores all the timepoints and can perform actions with them
   * @return The operator address
   */
  function dataStorageOperator() external view returns (address);

  /**
   * @notice The contract that deployed the pool, which must adhere to the IAlgebraFactory interface
   * @return The contract address
   */
  function factory() external view returns (address);

  /**
   * @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 tick spacing
   * @dev Ticks can only be used at multiples of this value
   * e.g.: a tickSpacing of 60 means ticks can be initialized every 60th tick, i.e., ..., -120, -60, 0, 60, 120, ...
   * This value is an int24 to avoid casting even though it is always positive.
   * @return The tick spacing
   */
  function tickSpacing() external view returns (int24);

  /**
   * @notice The maximum amount of position liquidity that can use any tick in the range
   * @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and
   * also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
   * @return The max amount of liquidity per tick
   */
  function maxLiquidityPerTick() external view returns (uint128);
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolPermissionedActions.sol


/**
 * @title Permissioned pool actions
 * @notice Contains pool methods that may only be called by the factory owner or tokenomics
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPoolPermissionedActions {
  /**
   * @notice Set the community's % share of the fees. Cannot exceed 25% (250)
   * @param communityFee0 new community fee percent for token0 of the pool in thousandths (1e-3)
   * @param communityFee1 new community fee percent for token1 of the pool in thousandths (1e-3)
   */
  function setCommunityFee(uint8 communityFee0, uint8 communityFee1) external;

  /**
   * @notice Sets an active incentive
   * @param virtualPoolAddress The address of a virtual pool associated with the incentive
   */
  function setIncentive(address virtualPoolAddress) external;

  /**
   * @notice Sets new lock time for added liquidity
   * @param newLiquidityCooldown The time in seconds
   */
  function setLiquidityCooldown(uint32 newLiquidityCooldown) external;
}


// File contracts/algebra/interfaces/pool/IAlgebraPoolState.sol


/// @title Pool state that can change
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
interface IAlgebraPoolState {
  /**
   * @notice The globalState structure in the pool stores many values but requires only one slot
   * and is exposed as a single method to save gas when accessed externally.
   * @return price The current price of the pool as a sqrt(token1/token0) Q64.96 value;
   * Returns tick The current tick of the pool, i.e. according to the last tick transition that was run;
   * Returns This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(price) if the price is on a tick
   * boundary;
   * Returns fee The last pool fee value in hundredths of a bip, i.e. 1e-6;
   * Returns timepointIndex The index of the last written timepoint;
   * Returns communityFeeToken0 The community fee percentage of the swap fee in thousandths (1e-3) for token0;
   * Returns communityFeeToken1 The community fee percentage of the swap fee in thousandths (1e-3) for token1;
   * Returns unlocked Whether the pool is currently locked to reentrancy;
   */
  function globalState()
    external
    view
    returns (
      uint160 price,
      int24 tick,
      uint16 fee,
      uint16 timepointIndex,
      uint8 communityFeeToken0,
      uint8 communityFeeToken1,
      bool unlocked
    );

  /**
   * @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
   * @dev This value can overflow the uint256
   */
  function totalFeeGrowth0Token() external view returns (uint256);

  /**
   * @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
   * @dev This value can overflow the uint256
   */
  function totalFeeGrowth1Token() external view returns (uint256);

  /**
   * @notice The currently in range liquidity available to the pool
   * @dev This value has no relationship to the total liquidity across all ticks.
   * Returned value cannot exceed type(uint128).max
   */
  function liquidity() external view returns (uint128);

  /**
   * @notice Look up information about a specific tick in the pool
   * @dev This is a public structure, so the `return` natspec tags are omitted.
   * @param tick The tick to look up
   * @return liquidityTotal the total amount of position liquidity that uses the pool either as tick lower or
   * tick upper;
   * Returns liquidityDelta how much liquidity changes when the pool price crosses the tick;
   * Returns outerFeeGrowth0Token the fee growth on the other side of the tick from the current tick in token0;
   * Returns outerFeeGrowth1Token the fee growth on the other side of the tick from the current tick in token1;
   * Returns outerTickCumulative the cumulative tick value on the other side of the tick from the current tick;
   * Returns outerSecondsPerLiquidity the seconds spent per liquidity on the other side of the tick from the current tick;
   * Returns outerSecondsSpent the seconds spent on the other side of the tick from the current tick;
   * Returns initialized Set to true if the tick is initialized, i.e. liquidityTotal is greater than 0
   * otherwise equal to false. Outside values can only be used if the tick is initialized.
   * In addition, these values are only relative and must be used only in comparison to previous snapshots for
   * a specific position.
   */
  function ticks(int24 tick)
    external
    view
    returns (
      uint128 liquidityTotal,
      int128 liquidityDelta,
      uint256 outerFeeGrowth0Token,
      uint256 outerFeeGrowth1Token,
      int56 outerTickCumulative,
      uint160 outerSecondsPerLiquidity,
      uint32 outerSecondsSpent,
      bool initialized
    );

  /** @notice Returns 256 packed tick initialized boolean values. See TickTable for more information */
  function tickTable(int16 wordPosition) external view returns (uint256);

  /**
   * @notice Returns the information about a position by the position's key
   * @dev This is a public mapping of structures, so the `return` natspec tags are omitted.
   * @param key The position's key is a hash of a preimage composed by the owner, bottomTick and topTick
   * @return liquidityAmount The amount of liquidity in the position;
   * Returns lastLiquidityAddTimestamp Timestamp of last adding of liquidity;
   * Returns innerFeeGrowth0Token Fee growth of token0 inside the tick range as of the last mint/burn/poke;
   * Returns innerFeeGrowth1Token Fee growth of token1 inside the tick range as of the last mint/burn/poke;
   * Returns fees0 The computed amount of token0 owed to the position as of the last mint/burn/poke;
   * Returns fees1 The computed amount of token1 owed to the position as of the last mint/burn/poke
   */
  function positions(bytes32 key)
    external
    view
    returns (
      uint128 liquidityAmount,
      uint32 lastLiquidityAddTimestamp,
      uint256 innerFeeGrowth0Token,
      uint256 innerFeeGrowth1Token,
      uint128 fees0,
      uint128 fees1
    );

  /**
   * @notice Returns data about a specific timepoint index
   * @param index The element of the timepoints array to fetch
   * @dev You most likely want to use #getTimepoints() instead of this method to get an timepoint as of some amount of time
   * ago, rather than at a specific index in the array.
   * This is a public mapping of structures, so the `return` natspec tags are omitted.
   * @return initialized whether the timepoint has been initialized and the values are safe to use;
   * Returns blockTimestamp The timestamp of the timepoint;
   * Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the timepoint timestamp;
   * Returns secondsPerLiquidityCumulative the seconds per in range liquidity for the life of the pool as of the timepoint timestamp;
   * Returns volatilityCumulative Cumulative standard deviation for the life of the pool as of the timepoint timestamp;
   * Returns averageTick Time-weighted average tick;
   * Returns volumePerLiquidityCumulative Cumulative swap volume per liquidity for the life of the pool as of the timepoint timestamp;
   */
  function timepoints(uint256 index)
    external
    view
    returns (
      bool initialized,
      uint32 blockTimestamp,
      int56 tickCumulative,
      uint160 secondsPerLiquidityCumulative,
      uint88 volatilityCumulative,
      int24 averageTick,
      uint144 volumePerLiquidityCumulative
    );

  /**
   * @notice Returns the information about active incentive
   * @dev if there is no active incentive at the moment, virtualPool,endTimestamp,startTimestamp would be equal to 0
   * @return virtualPool The address of a virtual pool associated with the current active incentive
   */
  function activeIncentive() external view returns (address virtualPool);

  /**
   * @notice Returns the lock time for added liquidity
   */
  function liquidityCooldown() external view returns (uint32 cooldownInSeconds);
}


// File contracts/algebra/interfaces/IAlgebraPool.sol







/**
 * @title The interface for a Algebra Pool
 * @dev The pool interface is broken up into many smaller pieces.
 * Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraPool is
  IAlgebraPoolImmutables,
  IAlgebraPoolState,
  IAlgebraPoolDerivedState,
  IAlgebraPoolActions,
  IAlgebraPoolPermissionedActions,
  IAlgebraPoolEvents
{
  // used only for combining interfaces
}


// File @openzeppelin/contracts/math/[email protected]



/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}


// File @openzeppelin/contracts/math/[email protected]



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

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

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

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

        return c;
    }

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

        int256 c = a / b;

        return c;
    }

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

        return c;
    }

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

        return c;
    }
}


// File @openzeppelin/contracts/utils/[email protected]



/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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


// File contracts/algebra/interfaces/callback/IAlgebraMintCallback.sol


/// @title Callback for IAlgebraPoolActions#mint
/// @notice Any contract that calls IAlgebraPoolActions#mint 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 IAlgebraMintCallback {
  /// @notice Called to `msg.sender` after minting liquidity to a position from IAlgebraPool#mint.
  /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity.
  /// The caller of this method must be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.
  /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity
  /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity
  /// @param data Any data passed through by the caller via the IAlgebraPoolActions#mint call
  function algebraMintCallback(
    uint256 amount0Owed,
    uint256 amount1Owed,
    bytes calldata data
  ) external;
}


// File contracts/algebra/libraries/TickMath.sol


/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
/// @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
/// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries
library TickMath {
  /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
  int24 internal constant MIN_TICK = -887272;
  /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
  int24 internal constant MAX_TICK = -MIN_TICK;

  /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
  uint160 internal constant MIN_SQRT_RATIO = 4295128739;
  /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
  uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

  /// @notice Calculates sqrt(1.0001^tick) * 2^96
  /// @dev Throws if |tick| > max tick
  /// @param tick The input tick for the above formula
  /// @return price A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
  /// at the given tick
  function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 price) {
    // get abs value
    int24 mask = tick >> (24 - 1);
    uint256 absTick = uint256((tick ^ mask) - mask);
    require(absTick <= uint256(MAX_TICK), 'T');

    uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
    if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
    if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
    if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
    if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
    if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
    if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
    if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
    if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
    if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
    if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
    if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
    if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
    if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
    if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
    if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
    if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
    if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
    if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
    if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

    if (tick > 0) ratio = type(uint256).max / ratio;

    // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
    // we then downcast because we know the result always fits within 160 bits due to our tick input constraint
    // we round up in the division so getTickAtSqrtRatio of the output price is always consistent
    price = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
  }

  /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
  /// @dev Throws in case price < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
  /// ever return.
  /// @param price The sqrt ratio for which to compute the tick as a Q64.96
  /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
  function getTickAtSqrtRatio(uint160 price) internal pure returns (int24 tick) {
    // second inequality must be < because the price can never reach the price at the max tick
    require(price >= MIN_SQRT_RATIO && price < MAX_SQRT_RATIO, 'R');
    uint256 ratio = uint256(price) << 32;

    uint256 r = ratio;
    uint256 msb = 0;

    assembly {
      let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(5, gt(r, 0xFFFFFFFF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(4, gt(r, 0xFFFF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(3, gt(r, 0xFF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(2, gt(r, 0xF))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := shl(1, gt(r, 0x3))
      msb := or(msb, f)
      r := shr(f, r)
    }
    assembly {
      let f := gt(r, 0x1)
      msb := or(msb, f)
    }

    if (msb >= 128) r = ratio >> (msb - 127);
    else r = ratio << (127 - msb);

    int256 log_2 = (int256(msb) - 128) << 64;

    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(63, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(62, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(61, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(60, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(59, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(58, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(57, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(56, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(55, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(54, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(53, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(52, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(51, f))
      r := shr(f, r)
    }
    assembly {
      r := shr(127, mul(r, r))
      let f := shr(128, r)
      log_2 := or(log_2, shl(50, f))
    }

    int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number

    int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
    int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);

    tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= price ? tickHi : tickLow;
  }
}


// File contracts/Hypervisor.sol













/// @title Hypervisor 1.3.1
/// @notice A Uniswap V2-like interface with fungible liquidity to Quickswap
/// which allows for arbitrary liquidity provision: one-sided, lop-sided, and balanced
contract Hypervisor is IAlgebraMintCallback, ERC20Permit, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;
    using SignedSafeMath for int256;

    IAlgebraPool public pool;
    IERC20 public token0;
    IERC20 public token1;
    uint8 public fee = 7;
    int24 public tickSpacing;

    int24 public baseLower;
    int24 public baseUpper;
    int24 public limitLower;
    int24 public limitUpper;

    address public owner;
    uint256 public deposit0Max;
    uint256 public deposit1Max;
    uint256 public maxTotalSupply;
    address public whitelistedAddress;
    address public feeRecipient;
    bool public directDeposit; /// enter uni on deposit (avoid if client uses public rpc)

    uint256 public constant PRECISION = 1e36;

    bool mintCalled;

   event Deposit(
        address indexed sender,
        address indexed to,
        uint256 shares,
        uint256 amount0,
        uint256 amount1
    );

    event Withdraw(
        address indexed sender,
        address indexed to,
        uint256 shares,
        uint256 amount0,
        uint256 amount1
    );

    event Rebalance(
        int24 tick,
        uint256 totalAmount0,
        uint256 totalAmount1,
        uint256 feeAmount0,
        uint256 feeAmount1,
        uint256 totalSupply
    );

    event ZeroBurn(uint8 fee, uint256 fees0, uint256 fees1);
    event SetFee(uint8 newFee);


    /// @param _pool Uniswap V3 pool for which liquidity is managed
    /// @param _owner Owner of the Hypervisor
    constructor(
        address _pool,
        address _owner,
        string memory name,
        string memory symbol
    ) ERC20Permit(name) ERC20(name, symbol) {
        require(_pool != address(0));
        require(_owner != address(0));
        pool = IAlgebraPool(_pool);
        token0 = IERC20(pool.token0());
        token1 = IERC20(pool.token1());
        require(address(token0) != address(0));
        require(address(token1) != address(0));
        tickSpacing = pool.tickSpacing();

        owner = _owner;

        maxTotalSupply = 0; /// no cap
        deposit0Max = uint256(-1);
        deposit1Max = uint256(-1);
    }

    /// @notice Deposit tokens
    /// @param deposit0 Amount of token0 transfered from sender to Hypervisor
    /// @param deposit1 Amount of token1 transfered from sender to Hypervisor
    /// @param to Address to which liquidity tokens are minted
    /// @param from Address from which asset tokens are transferred
    /// @param inMin min spend for directDeposit is true 
    /// @return shares Quantity of liquidity tokens minted as a result of deposit
    function deposit(
        uint256 deposit0,
        uint256 deposit1,
        address to,
        address from,
        uint256[4] memory inMin
    ) nonReentrant external returns (uint256 shares) {
        require(deposit0 > 0 || deposit1 > 0);
        require(deposit0 <= deposit0Max && deposit1 <= deposit1Max);
        require(to != address(0) && to != address(this), "to");
        require(msg.sender == whitelistedAddress, "WHE");

        /// update fees
        zeroBurn();

        uint160 sqrtPrice = TickMath.getSqrtRatioAtTick(currentTick());
        uint256 price = FullMath.mulDiv(uint256(sqrtPrice).mul(uint256(sqrtPrice)), PRECISION, 2**(96 * 2));

        (uint256 pool0, uint256 pool1) = getTotalAmounts();

        shares = deposit1.add(deposit0.mul(price).div(PRECISION));

        if (deposit0 > 0) {
          token0.safeTransferFrom(from, address(this), deposit0);
        }
        if (deposit1 > 0) {
          token1.safeTransferFrom(from, address(this), deposit1);
        }

        uint256 total = totalSupply();
        if (total != 0) {
          uint256 pool0PricedInToken1 = pool0.mul(price).div(PRECISION);
          shares = shares.mul(total).div(pool0PricedInToken1.add(pool1));
          if (directDeposit) {
            uint128 liquidity = _liquidityForAmounts(
              baseLower,
              baseUpper, 
              token0.balanceOf(address(this)),
              token1.balanceOf(address(this))
            );
            _mintLiquidity(baseLower, baseUpper, liquidity, address(this), inMin[0], inMin[1]);
            liquidity = _liquidityForAmounts(
              limitLower,
              limitUpper, 
              token0.balanceOf(address(this)),
              token1.balanceOf(address(this))
            );
            _mintLiquidity(limitLower, limitUpper, liquidity, address(this), inMin[2], inMin[3]);
          }
        }
        _mint(to, shares);
        emit Deposit(from, to, shares, deposit0, deposit1);
        /// Check total supply cap not exceeded. A value of 0 means no limit.
        require(maxTotalSupply == 0 || total <= maxTotalSupply, "max");
    }

    function _zeroBurn(int24 tickLower, int24 tickUpper) internal returns(uint128 liquidity) {
      /// update fees for inclusion
      (liquidity, ,) = _position(tickLower, tickUpper);
      if(liquidity > 0) {
        pool.burn(tickLower, tickUpper, 0);
        (uint256 owed0, uint256 owed1) = pool.collect(address(this), tickLower, tickUpper, type(uint128).max, type(uint128).max);
        emit ZeroBurn(fee, owed0, owed1);
        if (owed0.div(fee) > 0 && token0.balanceOf(address(this)) > 0) token0.safeTransfer(feeRecipient, owed0.div(fee));
        if (owed1.div(fee) > 0 && token1.balanceOf(address(this)) > 0) token1.safeTransfer(feeRecipient, owed1.div(fee));
      }      
    }

    /// @notice Update fees of the positions
    /// @return baseLiquidity Fee of base position
    /// @return limitLiquidity Fee of limit position
    function zeroBurn() internal returns(uint128 baseLiquidity, uint128 limitLiquidity) {
      baseLiquidity = _zeroBurn(baseLower, baseUpper);
      limitLiquidity = _zeroBurn(limitLower, limitUpper); 
    }

    /// @notice Pull liquidity tokens from liquidity and receive the tokens
    /// @param shares Number of liquidity tokens to pull from liquidity
    /// @param tickLower lower tick
    /// @param tickUpper upper tick
    /// @param amountMin min outs 
    /// @return amount0 amount of token0 received from base position
    /// @return amount1 amount of token1 received from base position
    function pullLiquidity(
        int24 tickLower,
        int24 tickUpper,
        uint128 shares,
        uint256[2] memory amountMin
    ) external onlyOwner returns (uint256 amount0, uint256 amount1) {
        _zeroBurn(tickLower, tickUpper);
        (amount0, amount1) = _burnLiquidity(
          tickLower,
          tickUpper,
          _liquidityForShares(tickLower, tickUpper, shares),
          address(this),
          false,
          amountMin[0],
          amountMin[1]
        );
    }

    /// @param shares Number of liquidity tokens to redeem as pool assets
    /// @param to Address to which redeemed pool assets are sent
    /// @param from Address from which liquidity tokens are sent
    /// @param minAmounts min amount0,1 returned for shares of liq 
    /// @return amount0 Amount of token0 redeemed by the submitted liquidity tokens
    /// @return amount1 Amount of token1 redeemed by the submitted liquidity tokens
    function withdraw(
        uint256 shares,
        address to,
        address from,
        uint256[4] memory minAmounts
    ) nonReentrant external returns (uint256 amount0, uint256 amount1) {
        require(shares > 0, "shares");
        require(to != address(0), "to");

        /// update fees
        zeroBurn();

        /// Withdraw liquidity from Uniswap pool
        (uint256 base0, uint256 base1) = _burnLiquidity(
            baseLower,
            baseUpper,
            _liquidityForShares(baseLower, baseUpper, shares),
            to,
            false,
            minAmounts[0],
            minAmounts[1]
        );
        (uint256 limit0, uint256 limit1) = _burnLiquidity(
            limitLower,
            limitUpper,
            _liquidityForShares(limitLower, limitUpper, shares),
            to,
            false,
            minAmounts[2],
            minAmounts[3]
        );

        // Push tokens proportional to unused balances
        uint256 unusedAmount0 = token0.balanceOf(address(this)).mul(shares).div(totalSupply());
        uint256 unusedAmount1 = token1.balanceOf(address(this)).mul(shares).div(totalSupply());
        if (unusedAmount0 > 0) token0.safeTransfer(to, unusedAmount0);
        if (unusedAmount1 > 0) token1.safeTransfer(to, unusedAmount1);

        amount0 = base0.add(limit0).add(unusedAmount0);
        amount1 = base1.add(limit1).add(unusedAmount1);

        require( from == msg.sender, "own");
        _burn(from, shares);

        emit Withdraw(from, to, shares, amount0, amount1);
    }

    /// @param _baseLower The lower tick of the base position
    /// @param _baseUpper The upper tick of the base position
    /// @param _limitLower The lower tick of the limit position
    /// @param _limitUpper The upper tick of the limit position
    /// @param  inMin min spend 
    /// @param  outMin min amount0,1 returned for shares of liq 
    /// @param _feeRecipient Address of recipient of 10% of earned fees since last rebalance
    function rebalance(
        int24 _baseLower,
        int24 _baseUpper,
        int24 _limitLower,
        int24 _limitUpper,
        address _feeRecipient,
        uint256[4] memory inMin, 
        uint256[4] memory outMin
    ) nonReentrant external onlyOwner {
        require(
            _baseLower < _baseUpper &&
                _baseLower % tickSpacing == 0 &&
                _baseUpper % tickSpacing == 0
        );
        require(
            _limitLower < _limitUpper &&
                _limitLower % tickSpacing == 0 &&
                _limitUpper % tickSpacing == 0
        );
        require(
          _limitUpper != _baseUpper ||
          _limitLower != _baseLower
        );
        require(_feeRecipient != address(0));
        feeRecipient = _feeRecipient;

        /// update fees
        zeroBurn();

        /// Withdraw all liquidity and collect all fees from Uniswap pool
        (uint128 baseLiquidity, uint256 feesLimit0, uint256 feesLimit1) = _position(baseLower, baseUpper);
        (uint128 limitLiquidity, uint256 feesBase0, uint256 feesBase1) = _position(limitLower, limitUpper);

        _burnLiquidity(baseLower, baseUpper, baseLiquidity, address(this), true, outMin[0], outMin[1]);
        _burnLiquidity(limitLower, limitUpper, limitLiquidity, address(this), true, outMin[2], outMin[3]);

        emit Rebalance(
            currentTick(),
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this)),
            feesBase0.add(feesLimit0),
            feesBase1.add(feesLimit1),
            totalSupply()
        );

        baseLower = _baseLower;
        baseUpper = _baseUpper;
        baseLiquidity = _liquidityForAmounts(
          baseLower,
          baseUpper, 
          token0.balanceOf(address(this)),
          token1.balanceOf(address(this))
        );
        _mintLiquidity(baseLower, baseUpper, baseLiquidity, address(this), inMin[0], inMin[1]);

        limitLower = _limitLower;
        limitUpper = _limitUpper;
        limitLiquidity = _liquidityForAmounts(
          limitLower,
          limitUpper, 
          token0.balanceOf(address(this)),
          token1.balanceOf(address(this))
        );
        _mintLiquidity(limitLower, limitUpper, limitLiquidity, address(this), inMin[2], inMin[3]);
    }

    /// @notice Compound pending fees
    /// @param inMin min spend 
    /// @return baseToken0Owed Pending fees of base token0
    /// @return baseToken1Owed Pending fees of base token1
    /// @return limitToken0Owed Pending fees of limit token0
    /// @return limitToken1Owed Pending fees of limit token1
    function compound(uint256[4] memory inMin) external onlyOwner returns (
        uint128 baseToken0Owed,
        uint128 baseToken1Owed,
        uint128 limitToken0Owed,
        uint128 limitToken1Owed 
    ) {
        // update fees for compounding
        zeroBurn();

        uint128 liquidity = _liquidityForAmounts(
          baseLower,
          baseUpper, 
          token0.balanceOf(address(this)),
          token1.balanceOf(address(this))
        );
        _mintLiquidity(baseLower, baseUpper, liquidity, address(this), inMin[0], inMin[1]);

        liquidity = _liquidityForAmounts(
          limitLower,
          limitUpper, 
          token0.balanceOf(address(this)),
          token1.balanceOf(address(this))
        );
        _mintLiquidity(limitLower, limitUpper, liquidity, address(this), inMin[2], inMin[3]);
    }

    /// @notice Add Liquidity
    function addLiquidity(
        int24 tickLower,
        int24 tickUpper,
        uint256 amount0,
        uint256 amount1,
        uint256[2] memory inMin
    ) public onlyOwner {        
        _zeroBurn(tickLower, tickUpper);
        uint128 liquidity = _liquidityForAmounts(tickLower, tickUpper, amount0, amount1);
        _mintLiquidity(tickLower, tickUpper, liquidity, address(this), inMin[0], inMin[1]);
    }

    /// @notice Adds the liquidity for the given position
    /// @param tickLower The lower tick of the position in which to add liquidity
    /// @param tickUpper The upper tick of the position in which to add liquidity
    /// @param liquidity The amount of liquidity to mint
    /// @param payer Payer Data
    /// @param amount0Min Minimum amount of token0 that should be paid
    /// @param amount1Min Minimum amount of token1 that should be paid
    function _mintLiquidity(
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity,
        address payer,
        uint256 amount0Min,
        uint256 amount1Min
    ) internal {
        if (liquidity > 0) {
            mintCalled = true;
            (uint256 amount0, uint256 amount1, ) = pool.mint(
                address(this),
                address(this),
                tickLower,
                tickUpper,
                liquidity,
                abi.encode(payer)
            );
            require(amount0 >= amount0Min && amount1 >= amount1Min, 'PSC');
        }
    }

    /// @notice Burn liquidity from the sender and collect tokens owed for the liquidity
    /// @param tickLower The lower tick of the position for which to burn liquidity
    /// @param tickUpper The upper tick of the position for which to burn liquidity
    /// @param liquidity The amount of liquidity to burn
    /// @param to The address which should receive the fees collected
    /// @param collectAll If true, collect all tokens owed in the pool, else collect the owed tokens of the burn
    /// @return amount0 The amount of fees collected in token0
    /// @return amount1 The amount of fees collected in token1
    function _burnLiquidity(
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity,
        address to,
        bool collectAll,
        uint256 amount0Min,
        uint256 amount1Min
    ) internal returns (uint256 amount0, uint256 amount1) {
        if (liquidity > 0) {
            /// Burn liquidity
            (uint256 owed0, uint256 owed1) = pool.burn(tickLower, tickUpper, liquidity);
            require(owed0 >= amount0Min && owed1 >= amount1Min, "PSC");

            // Collect amount owed
            uint128 collect0 = collectAll ? type(uint128).max : _uint128Safe(owed0);
            uint128 collect1 = collectAll ? type(uint128).max : _uint128Safe(owed1);
            if (collect0 > 0 || collect1 > 0) {
                (amount0, amount1) = pool.collect(to, tickLower, tickUpper, collect0, collect1);
            }
        }
    }

    /// @notice Get the liquidity amount for given liquidity tokens
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param shares Shares of position
    /// @return The amount of liquidity toekn for shares
    function _liquidityForShares(
        int24 tickLower,
        int24 tickUpper,
        uint256 shares
    ) internal view returns (uint128) {
        (uint128 position, , ) = _position(tickLower, tickUpper);
        return _uint128Safe(uint256(position).mul(shares).div(totalSupply()));
    }

    /// @notice Get the info of the given position
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @return liquidity The amount of liquidity of the position
    /// @return tokensOwed0 Amount of token0 owed
    /// @return tokensOwed1 Amount of token1 owed
    function _position(int24 tickLower, int24 tickUpper)
        internal
        view
        returns (
            uint128 liquidity,
            uint128 tokensOwed0,
            uint128 tokensOwed1
        )
    {
      bytes32 positionKey;
      address This = address(this);
      assembly {
        positionKey := or(shl(24, or(shl(24, This), and(tickLower, 0xFFFFFF))), and(tickUpper, 0xFFFFFF))
      }
        (liquidity, , , , tokensOwed0, tokensOwed1) = pool.positions(positionKey);
    }

    /// @notice Callback function of uniswapV3Pool mint
    function algebraMintCallback(
        uint256 amount0,
        uint256 amount1,
        bytes calldata data
    ) external override {
        require(msg.sender == address(pool));
        require(mintCalled == true);
        mintCalled = false;

        if (amount0 > 0) token0.safeTransfer(msg.sender, amount0);
        if (amount1 > 0) token1.safeTransfer(msg.sender, amount1);
    }

    /// @return total0 Quantity of token0 in both positions and unused in the Hypervisor
    /// @return total1 Quantity of token1 in both positions and unused in the Hypervisor
    function getTotalAmounts() public view returns (uint256 total0, uint256 total1) {
        (, uint256 base0, uint256 base1) = getBasePosition();
        (, uint256 limit0, uint256 limit1) = getLimitPosition();
        total0 = token0.balanceOf(address(this)).add(base0).add(limit0);
        total1 = token1.balanceOf(address(this)).add(base1).add(limit1);
    }

    /// @return liquidity Amount of total liquidity in the base position
    /// @return amount0 Estimated amount of token0 that could be collected by
    /// burning the base position
    /// @return amount1 Estimated amount of token1 that could be collected by
    /// burning the base position
    function getBasePosition()
        public
        view
        returns (
            uint128 liquidity,
            uint256 amount0,
            uint256 amount1
        )
    {
        (uint128 positionLiquidity, uint128 tokensOwed0, uint128 tokensOwed1) = _position(
            baseLower,
            baseUpper
        );
        (amount0, amount1) = _amountsForLiquidity(baseLower, baseUpper, positionLiquidity);
        amount0 = amount0.add(uint256(tokensOwed0));
        amount1 = amount1.add(uint256(tokensOwed1));
        liquidity = positionLiquidity;
    }

    /// @return liquidity Amount of total liquidity in the limit position
    /// @return amount0 Estimated amount of token0 that could be collected by
    /// burning the limit position
    /// @return amount1 Estimated amount of token1 that could be collected by
    /// burning the limit position
    function getLimitPosition()
        public
        view
        returns (
            uint128 liquidity,
            uint256 amount0,
            uint256 amount1
        )
    {
        (uint128 positionLiquidity, uint128 tokensOwed0, uint128 tokensOwed1) = _position(
            limitLower,
            limitUpper
        );
        (amount0, amount1) = _amountsForLiquidity(limitLower, limitUpper, positionLiquidity);
        amount0 = amount0.add(uint256(tokensOwed0));
        amount1 = amount1.add(uint256(tokensOwed1));
        liquidity = positionLiquidity;
    }

    /// @notice Get the amounts of the given numbers of liquidity tokens
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param liquidity The amount of liquidity tokens
    /// @return Amount of token0 and token1
    function _amountsForLiquidity(
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity
    ) internal view returns (uint256, uint256) {
        (uint160 sqrtRatioX96, , , , , , ) = pool.globalState();
        return
            LiquidityAmounts.getAmountsForLiquidity(
                sqrtRatioX96,
                TickMath.getSqrtRatioAtTick(tickLower),
                TickMath.getSqrtRatioAtTick(tickUpper),
                liquidity
            );
    }

    /// @notice Get the liquidity amount of the given numbers of token0 and token1
    /// @param tickLower The lower tick of the position
    /// @param tickUpper The upper tick of the position
    /// @param amount0 The amount of token0
    /// @param amount0 The amount of token1
    /// @return Amount of liquidity tokens
    function _liquidityForAmounts(
        int24 tickLower,
        int24 tickUpper,
        uint256 amount0,
        uint256 amount1
    ) internal view returns (uint128) {
        (uint160 sqrtRatioX96, , , , , , ) = pool.globalState();
        return
            LiquidityAmounts.getLiquidityForAmounts(
                sqrtRatioX96,
                TickMath.getSqrtRatioAtTick(tickLower),
                TickMath.getSqrtRatioAtTick(tickUpper),
                amount0,
                amount1
            );
    }

    /// @return tick Uniswap pool's current price tick
    function currentTick() public view returns (int24 tick) {
        (, tick, , , , , ) = pool.globalState();
    }

    function _uint128Safe(uint256 x) internal pure returns (uint128) {
        assert(x <= type(uint128).max);
        return uint128(x);
    }

    /// @param _address Array of addresses to be appended
    function setWhitelist(address _address) external onlyOwner {
        whitelistedAddress = _address;
    }

    /// @notice Remove Whitelisted
    function removeWhitelisted() external onlyOwner {
        whitelistedAddress = address(0);
    }

    /// @notice set fee 
    function setFee(uint8 newFee) external onlyOwner {
        fee = newFee;
        emit SetFee(fee);
    }

    /// @notice Toggle Direct Deposit
    function toggleDirectDeposit() external onlyOwner {
        directDeposit = !directDeposit;
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0));
        owner = newOwner;
    }

    modifier onlyOwner {
        require(msg.sender == owner, "only owner");
        _;
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int24","name":"tick","type":"int24"},{"indexed":false,"internalType":"uint256","name":"totalAmount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalAmount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"Rebalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"newFee","type":"uint8"}],"name":"SetFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"fee","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fees0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees1","type":"uint256"}],"name":"ZeroBurn","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"uint256[2]","name":"inMin","type":"uint256[2]"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"algebraMintCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[4]","name":"inMin","type":"uint256[4]"}],"name":"compound","outputs":[{"internalType":"uint128","name":"baseToken0Owed","type":"uint128"},{"internalType":"uint128","name":"baseToken1Owed","type":"uint128"},{"internalType":"uint128","name":"limitToken0Owed","type":"uint128"},{"internalType":"uint128","name":"limitToken1Owed","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentTick","outputs":[{"internalType":"int24","name":"tick","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"deposit0","type":"uint256"},{"internalType":"uint256","name":"deposit1","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[4]","name":"inMin","type":"uint256[4]"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit0Max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit1Max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBasePosition","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLimitPosition","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalAmounts","outputs":[{"internalType":"uint256","name":"total0","type":"uint256"},{"internalType":"uint256","name":"total1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"limitLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IAlgebraPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint128","name":"shares","type":"uint128"},{"internalType":"uint256[2]","name":"amountMin","type":"uint256[2]"}],"name":"pullLiquidity","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int24","name":"_baseLower","type":"int24"},{"internalType":"int24","name":"_baseUpper","type":"int24"},{"internalType":"int24","name":"_limitLower","type":"int24"},{"internalType":"int24","name":"_limitUpper","type":"int24"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"uint256[4]","name":"inMin","type":"uint256[4]"},{"internalType":"uint256[4]","name":"outMin","type":"uint256[4]"}],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newFee","type":"uint8"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tickSpacing","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleDirectDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelistedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[4]","name":"minAmounts","type":"uint256[4]"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

6101406040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c961012052600a805460ff60a01b1916600760a01b1790553480156200004a57600080fd5b5060405162004d3c38038062004d3c8339810160408190526200006d916200058f565b8180604051806040016040528060018152602001603160f81b81525084848160039080519060200190620000a392919062000407565b508051620000b990600490602084019062000407565b50506005805460ff1916601217905550815160208084019190912082519183019190912060c082905260e08190527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f62000112620003be565b60a05262000122818484620003c2565b60805261010052505060016007555050506001600160a01b0384166200014757600080fd5b6001600160a01b0383166200015b57600080fd5b600880546001600160a01b0319166001600160a01b03868116919091179182905560408051630dfe168160e01b815290519290911691630dfe168191600480820192602092909190829003018186803b158015620001b857600080fd5b505afa158015620001cd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001f391906200056b565b600980546001600160a01b0319166001600160a01b039283161790556008546040805163d21220a760e01b81529051919092169163d21220a7916004808301926020929190829003018186803b1580156200024d57600080fd5b505afa15801562000262573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028891906200056b565b600a80546001600160a01b0319166001600160a01b0392831617905560095416620002b257600080fd5b600a546001600160a01b0316620002c857600080fd5b600860009054906101000a90046001600160a01b03166001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200031757600080fd5b505afa1580156200032c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035291906200061c565b600a805460029290920b62ffffff16600160a81b0262ffffff60a81b199092169190911790555050600b80546001600160a01b03909216660100000000000002600160301b600160d01b0319909216919091179055506000600e55600019600c819055600d556200066b565b4690565b6000838383620003d1620003be565b30604051602001620003e89594939291906200063f565b6040516020818303038152906040528051906020012090509392505050565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200043f57600085556200048a565b82601f106200045a57805160ff19168380011785556200048a565b828001600101855582156200048a579182015b828111156200048a5782518255916020019190600101906200046d565b50620004989291506200049c565b5090565b5b808211156200049857600081556001016200049d565b80516001600160a01b0381168114620004cb57600080fd5b919050565b600082601f830112620004e1578081fd5b81516001600160401b0380821115620004f657fe5b6040516020601f8401601f19168201810183811183821017156200051657fe5b60405283825285840181018710156200052d578485fd5b8492505b8383101562000550578583018101518284018201529182019162000531565b838311156200056157848185840101525b5095945050505050565b6000602082840312156200057d578081fd5b6200058882620004b3565b9392505050565b60008060008060808587031215620005a5578283fd5b620005b085620004b3565b9350620005c060208601620004b3565b60408601519093506001600160401b0380821115620005dd578384fd5b620005eb88838901620004d0565b9350606087015191508082111562000601578283fd5b506200061087828801620004d0565b91505092959194509250565b6000602082840312156200062e578081fd5b81518060020b811462000588578182fd5b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b60805160a05160c05160e0516101005161012051614687620006b560003980611c7552508061206c5250806120ae52508061208d52508061201352508061204352506146876000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c806385919c5d11610167578063b1a3d533116100ce578063d2eabcfc11610087578063d2eabcfc14610518578063d505accf14610520578063dd62ed3e14610533578063ddca3f4314610546578063f2fde38b1461054e578063fa0827431461056157610295565b8063b1a3d533146104dd578063c4a7761e146104e5578063c5241e29146104ed578063cb122a09146104f5578063d0c93a7c14610508578063d21220a71461051057610295565b806395d89b411161012057806395d89b411461047d578063a049de6b14610485578063a457c2d71461049c578063a8559872146104af578063a9059cbb146104c2578063aaf5eb68146104d557610295565b806385919c5d1461041e57806386a2908114610431578063888a9134146104395780638da5cb5b146104415780638e3c92e414610449578063952356561461045c57610295565b8063395093511161020b57806363e96836116101c457806363e96836146103c2578063648cab85146103d55780636d90a39c146103dd57806370a08231146103e55780637ecebe00146103f8578063854cff2f1461040b57610295565b8063395093511461035f5780633dd657c51461037257806346904840146103875780634d461fbb1461038f578063513ea8841461039757806351e87af7146103ba57610295565b806316f0115b1161025d57806316f0115b1461030a57806318160ddd1461031257806323b872dd146103275780632ab4d0521461033a578063313ce567146103425780633644e5151461035757610295565b8063065e53601461029a57806306fdde03146102b8578063095ea7b3146102cd5780630dfe1681146102ed5780630f35bcac14610302575b600080fd5b6102a2610569565b6040516102af9190613eb6565b60405180910390f35b6102c06105f2565b6040516102af9190613f17565b6102e06102db366004613868565b610689565b6040516102af9190613e24565b6102f56106a7565b6040516102af9190613d3d565b6102a26106b6565b6102f56106c6565b61031a6106d5565b6040516102af9190613e2f565b6102e06103353660046137b8565b6106db565b61031a610763565b61034a610769565b6040516102af919061451c565b61031a610772565b6102e061036d366004613868565b610781565b610385610380366004613c0b565b6107cf565b005b6102f561084e565b61031a61085d565b6103aa6103a5366004613893565b610863565b6040516102af94939291906144ac565b6102a2610a99565b6103856103d03660046139b5565b610aa2565b61031a610b0d565b6102e0610b13565b61031a6103f3366004613764565b610b23565b61031a610406366004613764565b610b42565b610385610419366004613764565b610b63565b61038561042c3660046138c8565b610bb6565b6102f561112a565b6102a2611139565b6102f5611149565b61031a610457366004613bbb565b61115f565b61046f61046a36600461395b565b6114e2565b6040516102af9291906144f8565b6102c0611558565b61048d6115b9565b6040516102af939291906144d7565b6102e06104aa366004613868565b61163f565b61046f6104bd366004613b52565b6116a7565b6102e06104d0366004613868565b61197c565b61031a611990565b6103856119a3565b61046f6119f5565b610385611aed565b610385610503366004613cbe565b611b30565b6102a2611bc0565b6102f5611bd0565b61048d611bdf565b61038561052e3660046137f8565b611c3b565b61031a610541366004613780565b611d58565b61034a611d83565b61038561055c366004613764565b611d93565b6102a2611e06565b600854604080516339db007960e21b815290516000926001600160a01b03169163e76c01e49160048083019260e0929190829003018186803b1580156105ae57600080fd5b505afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190613ab9565b50939695505050505050565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561067e5780601f106106535761010080835404028352916020019161067e565b820191906000526020600020905b81548152906001019060200180831161066157829003601f168201915b505050505090505b90565b600061069d610696611e16565b8484611e1a565b5060015b92915050565b6009546001600160a01b031681565b600b546301000000900460020b81565b6008546001600160a01b031681565b60025490565b60006106e8848484611ece565b610758846106f4611e16565b61075385604051806060016040528060288152602001614605602891396001600160a01b038a16600090815260016020526040812090610732611e16565b6001600160a01b031681526020810191909152604001600020549190611fe3565b611e1a565b5060015b9392505050565b600e5481565b60055460ff1690565b600061077c61200f565b905090565b600061069d61078e611e16565b84610753856001600061079f611e16565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906120d9565b6008546001600160a01b031633146107e657600080fd5b601054600160a81b900460ff16151560011461080157600080fd5b6010805460ff60a81b19169055831561082b5760095461082b906001600160a01b031633866120fe565b821561084857600a54610848906001600160a01b031633856120fe565b50505050565b6010546001600160a01b031681565b600d5481565b600080600080600b60069054906101000a90046001600160a01b03166001600160a01b0316336001600160a01b0316146108b85760405162461bcd60e51b81526004016108af90614275565b60405180910390fd5b6108c0612159565b5050600a546009546040516370a0823160e01b81526000926109e992600160c01b8204600290810b93600160d81b909304900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b60206040518083038186803b15801561092c57600080fd5b505afa158015610940573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109649190613b3a565b600a546040516370a0823160e01b81526001600160a01b03909116906370a0823190610994903090600401613d3d565b60206040518083038186803b1580156109ac57600080fd5b505afa1580156109c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e49190613b3a565b6121a4565b600a548751919250610a1e91600160c01b8204600290810b92600160d81b9004900b90849030908b60015b602002015161225c565b600b546009546040516370a0823160e01b8152610a6692600281810b936301000000909204900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600b546040880151919250610a9191600282810b9263010000009004900b90849030908b6003610a14565b509193509193565b600b5460020b81565b600b54600160301b90046001600160a01b03163314610ad35760405162461bcd60e51b81526004016108af90614275565b610add8585612370565b506000610aec868686866121a4565b9050610b05868683308660006020020151876001610a14565b505050505050565b600c5481565b601054600160a01b900460ff1681565b6001600160a01b0381166000908152602081905260409020545b919050565b6001600160a01b03811660009081526006602052604081206106a1906126e3565b600b54600160301b90046001600160a01b03163314610b945760405162461bcd60e51b81526004016108af90614275565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b60026007541415610bd95760405162461bcd60e51b81526004016108af9061443e565b6002600755600b54600160301b90046001600160a01b03163314610c0f5760405162461bcd60e51b81526004016108af90614275565b8560020b8760020b128015610c415750600a54600160a81b9004600290810b810b9088900b81610c3b57fe5b0760020b155b8015610c6a5750600a54600160a81b9004600290810b810b9087900b81610c6457fe5b0760020b155b610c7357600080fd5b8360020b8560020b128015610ca55750600a54600160a81b9004600290810b810b9086900b81610c9f57fe5b0760020b155b8015610cce5750600a54600160a81b9004600290810b810b9085900b81610cc857fe5b0760020b155b610cd757600080fd5b8560020b8460020b141580610cf257508660020b8560020b14155b610cfb57600080fd5b6001600160a01b038316610d0e57600080fd5b601080546001600160a01b0319166001600160a01b038516179055610d31612159565b5050600a5460009081908190610d5c90600160c01b8104600290810b91600160d81b9004900b6126e7565b600b549295506001600160801b03918216945016915060009081908190610d9190600281810b9163010000009004900b6126e7565b600a549295506001600160801b039182169450169150610ddb90600160c01b8104600290810b91600160d81b9004900b883060018c600060200201518d60015b602002015161279b565b5050600b54610e0b90600281810b9163010000009004810b90869030906001908d905b60200201518d6003610dd1565b50507fbc4c20ad04f161d631d9ce94d27659391196415aa3c42f6a71c62e905ece782d610e36610569565b6009546040516370a0823160e01b81526001600160a01b03909116906370a0823190610e66903090600401613d3d565b60206040518083038186803b158015610e7e57600080fd5b505afa158015610e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb69190613b3a565b600a546040516370a0823160e01b81526001600160a01b03909116906370a0823190610ee6903090600401613d3d565b60206040518083038186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f369190613b3a565b610f40868a6120d9565b610f4a868a6120d9565b610f526106d5565b604051610f6496959493929190613eea565b60405180910390a18c600a60186101000a81548162ffffff021916908360020b62ffffff1602179055508b600a601b6101000a81548162ffffff021916908360020b62ffffff160217905550611014600a60189054906101000a900460020b600a601b9054906101000a900460020b600960009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109149190613d3d565b600a54895191975061104391600160c01b8204600290810b92600160d81b9004900b90899030908d6001610a14565b8a600b60006101000a81548162ffffff021916908360020b62ffffff16021790555089600b60036101000a81548162ffffff021916908360020b62ffffff1602179055506110eb600b60009054906101000a900460020b600b60039054906101000a900460020b600960009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109149190613d3d565b600b5460408a015191945061111691600282810b9263010000009004900b90869030908d6003610a14565b505060016007555050505050505050505050565b600f546001600160a01b031681565b600a54600160d81b900460020b81565b600b54600160301b90046001600160a01b031681565b6000600260075414156111845760405162461bcd60e51b81526004016108af9061443e565b6002600755851515806111975750600085115b6111a057600080fd5b600c5486111580156111b45750600d548511155b6111bd57600080fd5b6001600160a01b038416158015906111de57506001600160a01b0384163014155b6111fa5760405162461bcd60e51b81526004016108af90613fa4565b600f546001600160a01b031633146112245760405162461bcd60e51b81526004016108af9061435c565b61122c612159565b5050600061124061123b610569565b612989565b9050600061127461125a6001600160a01b03841680612c95565b6ec097ce7bc90715b34b9f1000000000600160c01b612ccf565b90506000806112816119f5565b90925090506112b36112ac6ec097ce7bc90715b34b9f10000000006112a68d87612c95565b90612d7e565b8a906120d9565b945089156112d3576009546112d3906001600160a01b031688308d612db0565b88156112f157600a546112f1906001600160a01b031688308c612db0565b60006112fb6106d5565b905080156114485760006113226ec097ce7bc90715b34b9f10000000006112a68688612c95565b905061133b61133182856120d9565b6112a68985612c95565b601054909750600160a01b900460ff161561144657600a546009546040516370a0823160e01b81526000926113a292600160c01b8204600290810b93600160d81b909304900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600a548a519192506113d191600160c01b8204600290810b92600160d81b9004900b90849030908e6001610a14565b600b546009546040516370a0823160e01b815261141992600281810b936301000000909204900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600b5460408b015191925061144491600282810b9263010000009004900b90849030908e6003610a14565b505b505b6114528987612dd1565b886001600160a01b0316886001600160a01b03167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f6888e8e60405161149993929190614506565b60405180910390a3600e5415806114b25750600e548111155b6114ce5760405162461bcd60e51b81526004016108af906142fa565b505060016007555091979650505050505050565b600b546000908190600160301b90046001600160a01b031633146115185760405162461bcd60e51b81526004016108af90614275565b6115228686612370565b5061154b868661153c8989896001600160801b0316612e91565b86513090600090896001610dd1565b9097909650945050505050565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561067e5780601f106106535761010080835404028352916020019161067e565b600b54600090819081908190819081906115e190600281810b9163010000009004900b6126e7565b600b54929550909350915061160590600281810b9163010000009004900b85612ed1565b909550935061161d856001600160801b0384166120d9565b9450611632846001600160801b0383166120d9565b9350829550505050909192565b600061069d61164c611e16565b846107538560405180606001604052806025815260200161462d6025913960016000611676611e16565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611fe3565b600080600260075414156116cd5760405162461bcd60e51b81526004016108af9061443e565b6002600755856116ef5760405162461bcd60e51b81526004016108af90614299565b6001600160a01b0385166117155760405162461bcd60e51b81526004016108af90613fa4565b61171d612159565b5050600a54600090819061175b90600160c01b8104600290810b91600160d81b9004900b61174c82828d612e91565b88518b906000908b6001610dd1565b600b549193509150600090819061179190600281810b9163010000009004900b61178682828f612e91565b8c60008c6002610dfe565b91509150600061182e6117a26106d5565b6009546040516370a0823160e01b81526112a6918f916001600160a01b03909116906370a08231906117d8903090600401613d3d565b60206040518083038186803b1580156117f057600080fd5b505afa158015611804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118289190613b3a565b90612c95565b9050600061188261183d6106d5565b6112a68e600a60009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016117d89190613d3d565b905081156118a1576009546118a1906001600160a01b03168c846120fe565b80156118be57600a546118be906001600160a01b03168c836120fe565b6118d2826118cc88876120d9565b906120d9565b97506118e2816118cc87866120d9565b96506001600160a01b038a16331461190c5760405162461bcd60e51b81526004016108af90614039565b6119168a8d612f8d565b8a6001600160a01b03168a6001600160a01b03167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8e8b8b60405161195d93929190614506565b60405180910390a3505050505050600160078190555094509492505050565b600061069d611989611e16565b8484611ece565b6ec097ce7bc90715b34b9f100000000081565b600b54600160301b90046001600160a01b031633146119d45760405162461bcd60e51b81526004016108af90614275565b6010805460ff60a01b198116600160a01b9182900460ff1615909102179055565b600080600080611a03611bdf565b9250925050600080611a136115b9565b6009546040516370a0823160e01b8152929550909350611aa6925084916118cc9188916001600160a01b03909116906370a0823190611a56903090600401613d3d565b60206040518083038186803b158015611a6e57600080fd5b505afa158015611a82573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cc9190613b3a565b600a546040516370a0823160e01b8152919750611ae39183916118cc9187916001600160a01b0316906370a0823190611a56903090600401613d3d565b9450505050509091565b600b54600160301b90046001600160a01b03163314611b1e5760405162461bcd60e51b81526004016108af90614275565b600f80546001600160a01b0319169055565b600b54600160301b90046001600160a01b03163314611b615760405162461bcd60e51b81526004016108af90614275565b600a805460ff60a01b1916600160a01b60ff848116820292909217928390556040517f91f2ade82ab0e77bb6823899e6daddc07e3da0e3ad998577e7c09c2f38943c4393611bb5939290049091169061451c565b60405180910390a150565b600a54600160a81b900460020b81565b600a546001600160a01b031681565b600080600080600080611c10600a60189054906101000a900460020b600a601b9054906101000a900460020b6126e7565b600a54929550909350915061160590600160c01b8104600290810b91600160d81b9004900b85612ed1565b83421115611c5b5760405162461bcd60e51b81526004016108af90614056565b6001600160a01b03871660009081526006602052604081207f000000000000000000000000000000000000000000000000000000000000000090899089908990611ca4906126e3565b89604051602001611cba96959493929190613e38565b6040516020818303038152906040528051906020012090506000611cdd82613063565b90506000611ced8287878761309c565b9050896001600160a01b0316816001600160a01b031614611d205760405162461bcd60e51b81526004016108af90614221565b6001600160a01b038a166000908152600660205260409020611d4190613189565b611d4c8a8a8a611e1a565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600a54600160a01b900460ff1681565b600b54600160301b90046001600160a01b03163314611dc45760405162461bcd60e51b81526004016108af90614275565b6001600160a01b038116611dd757600080fd5b600b80546001600160a01b03909216600160301b026601000000000000600160d01b0319909216919091179055565b600a54600160c01b900460020b81565b3390565b6001600160a01b038316611e405760405162461bcd60e51b81526004016108af90614379565b6001600160a01b038216611e665760405162461bcd60e51b81526004016108af90613fc0565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611ec1908590613e2f565b60405180910390a3505050565b6001600160a01b038316611ef45760405162461bcd60e51b81526004016108af90614317565b6001600160a01b038216611f1a5760405162461bcd60e51b81526004016108af90613f61565b611f25838383612154565b611f62816040518060600160405280602681526020016145df602691396001600160a01b0386166000908152602081905260409020549190611fe3565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611f9190826120d9565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611ec1908590613e2f565b600081848411156120075760405162461bcd60e51b81526004016108af9190613f17565b505050900390565b60007f000000000000000000000000000000000000000000000000000000000000000061203a613192565b141561206757507f0000000000000000000000000000000000000000000000000000000000000000610686565b6120d27f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000613196565b9050610686565b60008282018381101561075c5760405162461bcd60e51b81526004016108af90614002565b6121548363a9059cbb60e01b848460405160240161211d929190613e0b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131d7565b505050565b600a54600090819061218090600160c01b8104600290810b91600160d81b9004900b612370565b600b5490925061219e90600281810b9163010000009004900b612370565b90509091565b600080600860009054906101000a90046001600160a01b03166001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b1580156121f557600080fd5b505afa158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613ab9565b50505050505090506122528161224288612989565b61224b88612989565b8787613266565b9695505050505050565b6001600160801b03841615610b05576010805460ff60a81b1916600160a81b17905560085460405160009182916001600160a01b039091169063aafe29c090309081908c908c908c906122b3908d90602001613d3d565b6040516020818303038152906040526040518763ffffffff1660e01b81526004016122e396959493929190613d51565b606060405180830381600087803b1580156122fd57600080fd5b505af1158015612311573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123359190613c86565b509150915083821015801561234a5750828110155b6123665760405162461bcd60e51b81526004016108af90614258565b5050505050505050565b600061237c83836126e7565b50909150506001600160801b038116156106a15760085460405163a34123a760e01b81526001600160a01b039091169063a34123a7906123c59086908690600090600401613ec4565b6040805180830381600087803b1580156123de57600080fd5b505af11580156123f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124169190613b98565b50506008546040516309e3d67b60e31b815260009182916001600160a01b0390911690634f1eb3d89061245c903090899089906001600160801b03908190600401613dce565b6040805180830381600087803b15801561247557600080fd5b505af1158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190613a10565b6001600160801b031691506001600160801b031691507f4606b8a47eb284e8e80929101ece6ab5fe8d4f8735acc56bd0c92ca872f2cfe7600a60149054906101000a900460ff1683836040516125059392919061452a565b60405180910390a1600a54600090612528908490600160a01b900460ff16612d7e565b1180156125b357506009546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612561903090600401613d3d565b60206040518083038186803b15801561257957600080fd5b505afa15801561258d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b19190613b3a565b115b156125f457601054600a546125f4916001600160a01b0316906125e1908590600160a01b900460ff16612d7e565b6009546001600160a01b031691906120fe565b600a5460009061260f908390600160a01b900460ff16612d7e565b11801561269a5750600a546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612648903090600401613d3d565b60206040518083038186803b15801561266057600080fd5b505afa158015612674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126989190613b3a565b115b156126db57601054600a546126db916001600160a01b0316906126c8908490600160a01b900460ff16612d7e565b600a546001600160a01b031691906120fe565b505092915050565b5490565b60085460405163514ea4bf60e01b81526000918291829130601881811b62ffffff8a81169190911790911b908816179290916001600160a01b03169063514ea4bf90612737908590600401613e2f565b60c06040518083038186803b15801561274f57600080fd5b505afa158015612763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127879190613a3e565b949c909b5093995092975050505050505050565b6000806001600160801b0387161561297d5760085460405163a34123a760e01b815260009182916001600160a01b039091169063a34123a7906127e6908e908e908e90600401613ec4565b6040805180830381600087803b1580156127ff57600080fd5b505af1158015612813573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128379190613b98565b9150915085821015801561284b5750848110155b6128675760405162461bcd60e51b81526004016108af90614258565b60008761287c576128778361331e565b612885565b6001600160801b035b905060008861289c576128978361331e565b6128a5565b6001600160801b035b90506000826001600160801b031611806128c857506000816001600160801b0316115b1561297857600860009054906101000a90046001600160a01b03166001600160a01b0316634f1eb3d88b8f8f86866040518663ffffffff1660e01b8152600401612916959493929190613dce565b6040805180830381600087803b15801561292f57600080fd5b505af1158015612943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129679190613a10565b6001600160801b0391821697501694505b505050505b97509795505050505050565b6000600282810b60171d90818418829003900b620d89e88111156129bf5760405162461bcd60e51b81526004016108af90614183565b6000600182166129d357600160801b6129e5565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612a19576ffff97272373d413259a46990580e213a0260801c5b6004821615612a38576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612a57576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612a76576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612a95576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ab4576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ad3576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612af3576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612b13576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612b33576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612b53576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612b73576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612b93576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612bb3576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612bd3576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612bf4576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615612c14576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615612c33576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615612c50576b048a170391f7dc42444e8fa20260801c5b60008560020b1315612c6b578060001981612c6757fe5b0490505b640100000000810615612c7f576001612c82565b60005b60ff16602082901c019350505050919050565b600082612ca4575060006106a1565b82820282848281612cb157fe5b041461075c5760405162461bcd60e51b81526004016108af906141e0565b6000808060001985870986860292508281109083900303905080612d055760008411612cfa57600080fd5b50829004905061075c565b808411612d1157600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6000808211612d9f5760405162461bcd60e51b81526004016108af9061414c565b818381612da857fe5b049392505050565b610848846323b872dd60e01b85858560405160240161211d93929190613daa565b6001600160a01b038216612df75760405162461bcd60e51b81526004016108af90614475565b612e0360008383612154565b600254612e1090826120d9565b6002556001600160a01b038216600090815260208190526040902054612e3690826120d9565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e85908590613e2f565b60405180910390a35050565b600080612e9e85856126e7565b50509050612ec8612ec3612eb06106d5565b6112a66001600160801b03851687612c95565b61331e565b95945050505050565b6000806000600860009054906101000a90046001600160a01b03166001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b158015612f2457600080fd5b505afa158015612f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5c9190613ab9565b5050505050509050612f8081612f7188612989565b612f7a88612989565b87613335565b9250925050935093915050565b6001600160a01b038216612fb35760405162461bcd60e51b81526004016108af906142b9565b612fbf82600083612154565b612ffc816040518060600160405280602281526020016145bd602291396001600160a01b0385166000908152602081905260409020549190611fe3565b6001600160a01b03831660009081526020819052604090205560025461302290826133d1565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e85908590613e2f565b600061306d61200f565b8260405160200161307f929190613d22565b604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156130de5760405162461bcd60e51b81526004016108af906140c4565b8360ff16601b14806130f357508360ff16601c145b61310f5760405162461bcd60e51b81526004016108af9061419e565b6000600186868686604051600081526020016040526040516131349493929190613e98565b6020604051602081039080840390855afa158015613156573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612ec85760405162461bcd60e51b81526004016108af90613f2a565b80546001019055565b4690565b60008383836131a3613192565b306040516020016131b8959493929190613e6c565b6040516020818303038152906040528051906020012090509392505050565b600061322c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133f99092919063ffffffff16565b805190915015612154578080602001905181019061324a91906138ae565b6121545760405162461bcd60e51b81526004016108af906143f4565b6000836001600160a01b0316856001600160a01b03161115613286579293925b846001600160a01b0316866001600160a01b0316116132b1576132aa858585613410565b9050612ec8565b836001600160a01b0316866001600160a01b031610156133135760006132d8878686613410565b905060006132e7878986613473565b9050806001600160801b0316826001600160801b031610613308578061330a565b815b92505050612ec8565b612252858584613473565b60006001600160801b0382111561333157fe5b5090565b600080836001600160a01b0316856001600160a01b03161115613356579293925b846001600160a01b0316866001600160a01b0316116133815761337a8585856134b0565b91506133c8565b836001600160a01b0316866001600160a01b031610156133ba576133a68685856134b0565b91506133b3858785613519565b90506133c8565b6133c5858585613519565b90505b94509492505050565b6000828211156133f35760405162461bcd60e51b81526004016108af9061408d565b50900390565b6060613408848460008561355c565b949350505050565b6000826001600160a01b0316846001600160a01b03161115613430579192915b6000613453856001600160a01b0316856001600160a01b0316600160601b612ccf565b9050612ec861346e84838888036001600160a01b0316612ccf565b61361c565b6000826001600160a01b0316846001600160a01b03161115613493579192915b61340861346e83600160601b8787036001600160a01b0316612ccf565b6000826001600160a01b0316846001600160a01b031611156134d0579192915b836001600160a01b0316613509606060ff16846001600160801b0316901b8686036001600160a01b0316866001600160a01b0316612ccf565b8161351057fe5b04949350505050565b6000826001600160a01b0316846001600160a01b03161115613539579192915b613408826001600160801b03168585036001600160a01b0316600160601b612ccf565b60608247101561357e5760405162461bcd60e51b81526004016108af90614106565b61358785613632565b6135a35760405162461bcd60e51b81526004016108af906143bd565b600080866001600160a01b031685876040516135bf9190613d06565b60006040518083038185875af1925050503d80600081146135fc576040519150601f19603f3d011682016040523d82523d6000602084013e613601565b606091505b5091509150613611828286613638565b979650505050505050565b806001600160801b0381168114610b3d57600080fd5b3b151590565b6060831561364757508161075c565b8251156136575782518084602001fd5b8160405162461bcd60e51b81526004016108af9190613f17565b600082601f830112613681578081fd5b6040516040810181811067ffffffffffffffff8211171561369e57fe5b80604052508083856040860111156136b4578384fd5b835b60028110156136d55781358352602092830192909101906001016136b6565b509195945050505050565b600082601f8301126136f0578081fd5b6040516080810181811067ffffffffffffffff8211171561370d57fe5b604052808360808101861015613721578384fd5b835b60048110156136d5578135835260209283019290910190600101613723565b80518015158114610b3d57600080fd5b805161ffff81168114610b3d57600080fd5b600060208284031215613775578081fd5b813561075c81614571565b60008060408385031215613792578081fd5b823561379d81614571565b915060208301356137ad81614571565b809150509250929050565b6000806000606084860312156137cc578081fd5b83356137d781614571565b925060208401356137e781614571565b929592945050506040919091013590565b600080600080600080600060e0888a031215613812578283fd5b873561381d81614571565b9650602088013561382d81614571565b95506040880135945060608801359350608088013561384b816145ad565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561387a578182fd5b823561388581614571565b946020939093013593505050565b6000608082840312156138a4578081fd5b61075c83836136e0565b6000602082840312156138bf578081fd5b61075c82613742565b60008060008060008060006101a0888a0312156138e3578081fd5b87356138ee81614589565b965060208801356138fe81614589565b9550604088013561390e81614589565b9450606088013561391e81614589565b9350608088013561392e81614571565b925061393d8960a08a016136e0565b915061394d896101208a016136e0565b905092959891949750929550565b60008060008060a08587031215613970578182fd5b843561397b81614589565b9350602085013561398b81614589565b9250604085013561399b81614598565b91506139aa8660608701613671565b905092959194509250565b600080600080600060c086880312156139cc578283fd5b85356139d781614589565b945060208601356139e781614589565b93506040860135925060608601359150613a048760808801613671565b90509295509295909350565b60008060408385031215613a22578182fd5b8251613a2d81614598565b60208401519092506137ad81614598565b60008060008060008060c08789031215613a56578384fd5b8651613a6181614598565b602088015190965063ffffffff81168114613a7a578485fd5b8095505060408701519350606087015192506080870151613a9a81614598565b60a0880151909250613aab81614598565b809150509295509295509295565b600080600080600080600060e0888a031215613ad3578081fd5b8751613ade81614571565b6020890151909750613aef81614589565b9550613afd60408901613752565b9450613b0b60608901613752565b93506080880151613b1b816145ad565b60a0890151909350613b2c816145ad565b915061394d60c08901613742565b600060208284031215613b4b578081fd5b5051919050565b60008060008060e08587031215613b67578182fd5b843593506020850135613b7981614571565b92506040850135613b8981614571565b91506139aa86606087016136e0565b60008060408385031215613baa578182fd5b505080516020909101519092909150565b60008060008060006101008688031215613bd3578283fd5b85359450602086013593506040860135613bec81614571565b92506060860135613bfc81614571565b9150613a0487608088016136e0565b60008060008060608587031215613c20578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115613c45578384fd5b818701915087601f830112613c58578384fd5b813581811115613c66578485fd5b886020828501011115613c77578485fd5b95989497505060200194505050565b600080600060608486031215613c9a578081fd5b83519250602084015191506040840151613cb381614598565b809150509250925092565b600060208284031215613ccf578081fd5b813561075c816145ad565b60008151808452613cf2816020860160208601614545565b601f01601f19169290920160200192915050565b60008251613d18818460208701614545565b9190910192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b03878116825286166020820152600285810b604083015284900b60608201526001600160801b038316608082015260c060a08201819052600090613d9e90830184613cda565b98975050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03959095168552600293840b60208601529190920b60408401526001600160801b03918216606084015216608082015260a00190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b60029190910b815260200190565b600293840b81529190920b60208201526001600160801b03909116604082015260600190565b60029690960b8652602086019490945260408501929092526060840152608083015260a082015260c00190565b60006020825261075c6020830184613cda565b60208082526018908201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b602080825260029082015261746f60f01b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526003908201526237bbb760e91b604082015260600190565b6020808252601d908201527f45524332305065726d69743a206578706972656420646561646c696e65000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600190820152601560fa1b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601e908201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604082015260600190565b60208082526003908201526250534360e81b604082015260600190565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b60208082526006908201526573686172657360d01b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600390820152620dac2f60eb1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526003908201526257484560e81b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526020830191909152604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b60ff91909116815260200190565b60ff9390931683526020830191909152604082015260600190565b60005b83811015614560578181015183820152602001614548565b838111156108485750506000910152565b6001600160a01b038116811461458657600080fd5b50565b8060020b811461458657600080fd5b6001600160801b038116811461458657600080fd5b60ff8116811461458657600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220f940bb264bc082a145ef6482d9ea4b8dfde70bdab78aa145c9422d379a4c17ec64736f6c63430007060033000000000000000000000000fc4a3a7dc6b62bd2ea595b106392f5e006083b83000000000000000000000000ade38bd2e8d5a52e60047affe6e595bb5e61923a000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a61574554482d5742544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a61574554482d5742544300000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102955760003560e01c806385919c5d11610167578063b1a3d533116100ce578063d2eabcfc11610087578063d2eabcfc14610518578063d505accf14610520578063dd62ed3e14610533578063ddca3f4314610546578063f2fde38b1461054e578063fa0827431461056157610295565b8063b1a3d533146104dd578063c4a7761e146104e5578063c5241e29146104ed578063cb122a09146104f5578063d0c93a7c14610508578063d21220a71461051057610295565b806395d89b411161012057806395d89b411461047d578063a049de6b14610485578063a457c2d71461049c578063a8559872146104af578063a9059cbb146104c2578063aaf5eb68146104d557610295565b806385919c5d1461041e57806386a2908114610431578063888a9134146104395780638da5cb5b146104415780638e3c92e414610449578063952356561461045c57610295565b8063395093511161020b57806363e96836116101c457806363e96836146103c2578063648cab85146103d55780636d90a39c146103dd57806370a08231146103e55780637ecebe00146103f8578063854cff2f1461040b57610295565b8063395093511461035f5780633dd657c51461037257806346904840146103875780634d461fbb1461038f578063513ea8841461039757806351e87af7146103ba57610295565b806316f0115b1161025d57806316f0115b1461030a57806318160ddd1461031257806323b872dd146103275780632ab4d0521461033a578063313ce567146103425780633644e5151461035757610295565b8063065e53601461029a57806306fdde03146102b8578063095ea7b3146102cd5780630dfe1681146102ed5780630f35bcac14610302575b600080fd5b6102a2610569565b6040516102af9190613eb6565b60405180910390f35b6102c06105f2565b6040516102af9190613f17565b6102e06102db366004613868565b610689565b6040516102af9190613e24565b6102f56106a7565b6040516102af9190613d3d565b6102a26106b6565b6102f56106c6565b61031a6106d5565b6040516102af9190613e2f565b6102e06103353660046137b8565b6106db565b61031a610763565b61034a610769565b6040516102af919061451c565b61031a610772565b6102e061036d366004613868565b610781565b610385610380366004613c0b565b6107cf565b005b6102f561084e565b61031a61085d565b6103aa6103a5366004613893565b610863565b6040516102af94939291906144ac565b6102a2610a99565b6103856103d03660046139b5565b610aa2565b61031a610b0d565b6102e0610b13565b61031a6103f3366004613764565b610b23565b61031a610406366004613764565b610b42565b610385610419366004613764565b610b63565b61038561042c3660046138c8565b610bb6565b6102f561112a565b6102a2611139565b6102f5611149565b61031a610457366004613bbb565b61115f565b61046f61046a36600461395b565b6114e2565b6040516102af9291906144f8565b6102c0611558565b61048d6115b9565b6040516102af939291906144d7565b6102e06104aa366004613868565b61163f565b61046f6104bd366004613b52565b6116a7565b6102e06104d0366004613868565b61197c565b61031a611990565b6103856119a3565b61046f6119f5565b610385611aed565b610385610503366004613cbe565b611b30565b6102a2611bc0565b6102f5611bd0565b61048d611bdf565b61038561052e3660046137f8565b611c3b565b61031a610541366004613780565b611d58565b61034a611d83565b61038561055c366004613764565b611d93565b6102a2611e06565b600854604080516339db007960e21b815290516000926001600160a01b03169163e76c01e49160048083019260e0929190829003018186803b1580156105ae57600080fd5b505afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e69190613ab9565b50939695505050505050565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561067e5780601f106106535761010080835404028352916020019161067e565b820191906000526020600020905b81548152906001019060200180831161066157829003601f168201915b505050505090505b90565b600061069d610696611e16565b8484611e1a565b5060015b92915050565b6009546001600160a01b031681565b600b546301000000900460020b81565b6008546001600160a01b031681565b60025490565b60006106e8848484611ece565b610758846106f4611e16565b61075385604051806060016040528060288152602001614605602891396001600160a01b038a16600090815260016020526040812090610732611e16565b6001600160a01b031681526020810191909152604001600020549190611fe3565b611e1a565b5060015b9392505050565b600e5481565b60055460ff1690565b600061077c61200f565b905090565b600061069d61078e611e16565b84610753856001600061079f611e16565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252902054906120d9565b6008546001600160a01b031633146107e657600080fd5b601054600160a81b900460ff16151560011461080157600080fd5b6010805460ff60a81b19169055831561082b5760095461082b906001600160a01b031633866120fe565b821561084857600a54610848906001600160a01b031633856120fe565b50505050565b6010546001600160a01b031681565b600d5481565b600080600080600b60069054906101000a90046001600160a01b03166001600160a01b0316336001600160a01b0316146108b85760405162461bcd60e51b81526004016108af90614275565b60405180910390fd5b6108c0612159565b5050600a546009546040516370a0823160e01b81526000926109e992600160c01b8204600290810b93600160d81b909304900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b60206040518083038186803b15801561092c57600080fd5b505afa158015610940573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109649190613b3a565b600a546040516370a0823160e01b81526001600160a01b03909116906370a0823190610994903090600401613d3d565b60206040518083038186803b1580156109ac57600080fd5b505afa1580156109c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e49190613b3a565b6121a4565b600a548751919250610a1e91600160c01b8204600290810b92600160d81b9004900b90849030908b60015b602002015161225c565b600b546009546040516370a0823160e01b8152610a6692600281810b936301000000909204900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600b546040880151919250610a9191600282810b9263010000009004900b90849030908b6003610a14565b509193509193565b600b5460020b81565b600b54600160301b90046001600160a01b03163314610ad35760405162461bcd60e51b81526004016108af90614275565b610add8585612370565b506000610aec868686866121a4565b9050610b05868683308660006020020151876001610a14565b505050505050565b600c5481565b601054600160a01b900460ff1681565b6001600160a01b0381166000908152602081905260409020545b919050565b6001600160a01b03811660009081526006602052604081206106a1906126e3565b600b54600160301b90046001600160a01b03163314610b945760405162461bcd60e51b81526004016108af90614275565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b60026007541415610bd95760405162461bcd60e51b81526004016108af9061443e565b6002600755600b54600160301b90046001600160a01b03163314610c0f5760405162461bcd60e51b81526004016108af90614275565b8560020b8760020b128015610c415750600a54600160a81b9004600290810b810b9088900b81610c3b57fe5b0760020b155b8015610c6a5750600a54600160a81b9004600290810b810b9087900b81610c6457fe5b0760020b155b610c7357600080fd5b8360020b8560020b128015610ca55750600a54600160a81b9004600290810b810b9086900b81610c9f57fe5b0760020b155b8015610cce5750600a54600160a81b9004600290810b810b9085900b81610cc857fe5b0760020b155b610cd757600080fd5b8560020b8460020b141580610cf257508660020b8560020b14155b610cfb57600080fd5b6001600160a01b038316610d0e57600080fd5b601080546001600160a01b0319166001600160a01b038516179055610d31612159565b5050600a5460009081908190610d5c90600160c01b8104600290810b91600160d81b9004900b6126e7565b600b549295506001600160801b03918216945016915060009081908190610d9190600281810b9163010000009004900b6126e7565b600a549295506001600160801b039182169450169150610ddb90600160c01b8104600290810b91600160d81b9004900b883060018c600060200201518d60015b602002015161279b565b5050600b54610e0b90600281810b9163010000009004810b90869030906001908d905b60200201518d6003610dd1565b50507fbc4c20ad04f161d631d9ce94d27659391196415aa3c42f6a71c62e905ece782d610e36610569565b6009546040516370a0823160e01b81526001600160a01b03909116906370a0823190610e66903090600401613d3d565b60206040518083038186803b158015610e7e57600080fd5b505afa158015610e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb69190613b3a565b600a546040516370a0823160e01b81526001600160a01b03909116906370a0823190610ee6903090600401613d3d565b60206040518083038186803b158015610efe57600080fd5b505afa158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f369190613b3a565b610f40868a6120d9565b610f4a868a6120d9565b610f526106d5565b604051610f6496959493929190613eea565b60405180910390a18c600a60186101000a81548162ffffff021916908360020b62ffffff1602179055508b600a601b6101000a81548162ffffff021916908360020b62ffffff160217905550611014600a60189054906101000a900460020b600a601b9054906101000a900460020b600960009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109149190613d3d565b600a54895191975061104391600160c01b8204600290810b92600160d81b9004900b90899030908d6001610a14565b8a600b60006101000a81548162ffffff021916908360020b62ffffff16021790555089600b60036101000a81548162ffffff021916908360020b62ffffff1602179055506110eb600b60009054906101000a900460020b600b60039054906101000a900460020b600960009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109149190613d3d565b600b5460408a015191945061111691600282810b9263010000009004900b90869030908d6003610a14565b505060016007555050505050505050505050565b600f546001600160a01b031681565b600a54600160d81b900460020b81565b600b54600160301b90046001600160a01b031681565b6000600260075414156111845760405162461bcd60e51b81526004016108af9061443e565b6002600755851515806111975750600085115b6111a057600080fd5b600c5486111580156111b45750600d548511155b6111bd57600080fd5b6001600160a01b038416158015906111de57506001600160a01b0384163014155b6111fa5760405162461bcd60e51b81526004016108af90613fa4565b600f546001600160a01b031633146112245760405162461bcd60e51b81526004016108af9061435c565b61122c612159565b5050600061124061123b610569565b612989565b9050600061127461125a6001600160a01b03841680612c95565b6ec097ce7bc90715b34b9f1000000000600160c01b612ccf565b90506000806112816119f5565b90925090506112b36112ac6ec097ce7bc90715b34b9f10000000006112a68d87612c95565b90612d7e565b8a906120d9565b945089156112d3576009546112d3906001600160a01b031688308d612db0565b88156112f157600a546112f1906001600160a01b031688308c612db0565b60006112fb6106d5565b905080156114485760006113226ec097ce7bc90715b34b9f10000000006112a68688612c95565b905061133b61133182856120d9565b6112a68985612c95565b601054909750600160a01b900460ff161561144657600a546009546040516370a0823160e01b81526000926113a292600160c01b8204600290810b93600160d81b909304900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600a548a519192506113d191600160c01b8204600290810b92600160d81b9004900b90849030908e6001610a14565b600b546009546040516370a0823160e01b815261141992600281810b936301000000909204900b916001600160a01b03909116906370a0823190610914903090600401613d3d565b600b5460408b015191925061144491600282810b9263010000009004900b90849030908e6003610a14565b505b505b6114528987612dd1565b886001600160a01b0316886001600160a01b03167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f6888e8e60405161149993929190614506565b60405180910390a3600e5415806114b25750600e548111155b6114ce5760405162461bcd60e51b81526004016108af906142fa565b505060016007555091979650505050505050565b600b546000908190600160301b90046001600160a01b031633146115185760405162461bcd60e51b81526004016108af90614275565b6115228686612370565b5061154b868661153c8989896001600160801b0316612e91565b86513090600090896001610dd1565b9097909650945050505050565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561067e5780601f106106535761010080835404028352916020019161067e565b600b54600090819081908190819081906115e190600281810b9163010000009004900b6126e7565b600b54929550909350915061160590600281810b9163010000009004900b85612ed1565b909550935061161d856001600160801b0384166120d9565b9450611632846001600160801b0383166120d9565b9350829550505050909192565b600061069d61164c611e16565b846107538560405180606001604052806025815260200161462d6025913960016000611676611e16565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190611fe3565b600080600260075414156116cd5760405162461bcd60e51b81526004016108af9061443e565b6002600755856116ef5760405162461bcd60e51b81526004016108af90614299565b6001600160a01b0385166117155760405162461bcd60e51b81526004016108af90613fa4565b61171d612159565b5050600a54600090819061175b90600160c01b8104600290810b91600160d81b9004900b61174c82828d612e91565b88518b906000908b6001610dd1565b600b549193509150600090819061179190600281810b9163010000009004900b61178682828f612e91565b8c60008c6002610dfe565b91509150600061182e6117a26106d5565b6009546040516370a0823160e01b81526112a6918f916001600160a01b03909116906370a08231906117d8903090600401613d3d565b60206040518083038186803b1580156117f057600080fd5b505afa158015611804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118289190613b3a565b90612c95565b9050600061188261183d6106d5565b6112a68e600a60009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016117d89190613d3d565b905081156118a1576009546118a1906001600160a01b03168c846120fe565b80156118be57600a546118be906001600160a01b03168c836120fe565b6118d2826118cc88876120d9565b906120d9565b97506118e2816118cc87866120d9565b96506001600160a01b038a16331461190c5760405162461bcd60e51b81526004016108af90614039565b6119168a8d612f8d565b8a6001600160a01b03168a6001600160a01b03167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8e8b8b60405161195d93929190614506565b60405180910390a3505050505050600160078190555094509492505050565b600061069d611989611e16565b8484611ece565b6ec097ce7bc90715b34b9f100000000081565b600b54600160301b90046001600160a01b031633146119d45760405162461bcd60e51b81526004016108af90614275565b6010805460ff60a01b198116600160a01b9182900460ff1615909102179055565b600080600080611a03611bdf565b9250925050600080611a136115b9565b6009546040516370a0823160e01b8152929550909350611aa6925084916118cc9188916001600160a01b03909116906370a0823190611a56903090600401613d3d565b60206040518083038186803b158015611a6e57600080fd5b505afa158015611a82573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cc9190613b3a565b600a546040516370a0823160e01b8152919750611ae39183916118cc9187916001600160a01b0316906370a0823190611a56903090600401613d3d565b9450505050509091565b600b54600160301b90046001600160a01b03163314611b1e5760405162461bcd60e51b81526004016108af90614275565b600f80546001600160a01b0319169055565b600b54600160301b90046001600160a01b03163314611b615760405162461bcd60e51b81526004016108af90614275565b600a805460ff60a01b1916600160a01b60ff848116820292909217928390556040517f91f2ade82ab0e77bb6823899e6daddc07e3da0e3ad998577e7c09c2f38943c4393611bb5939290049091169061451c565b60405180910390a150565b600a54600160a81b900460020b81565b600a546001600160a01b031681565b600080600080600080611c10600a60189054906101000a900460020b600a601b9054906101000a900460020b6126e7565b600a54929550909350915061160590600160c01b8104600290810b91600160d81b9004900b85612ed1565b83421115611c5b5760405162461bcd60e51b81526004016108af90614056565b6001600160a01b03871660009081526006602052604081207f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c990899089908990611ca4906126e3565b89604051602001611cba96959493929190613e38565b6040516020818303038152906040528051906020012090506000611cdd82613063565b90506000611ced8287878761309c565b9050896001600160a01b0316816001600160a01b031614611d205760405162461bcd60e51b81526004016108af90614221565b6001600160a01b038a166000908152600660205260409020611d4190613189565b611d4c8a8a8a611e1a565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600a54600160a01b900460ff1681565b600b54600160301b90046001600160a01b03163314611dc45760405162461bcd60e51b81526004016108af90614275565b6001600160a01b038116611dd757600080fd5b600b80546001600160a01b03909216600160301b026601000000000000600160d01b0319909216919091179055565b600a54600160c01b900460020b81565b3390565b6001600160a01b038316611e405760405162461bcd60e51b81526004016108af90614379565b6001600160a01b038216611e665760405162461bcd60e51b81526004016108af90613fc0565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611ec1908590613e2f565b60405180910390a3505050565b6001600160a01b038316611ef45760405162461bcd60e51b81526004016108af90614317565b6001600160a01b038216611f1a5760405162461bcd60e51b81526004016108af90613f61565b611f25838383612154565b611f62816040518060600160405280602681526020016145df602691396001600160a01b0386166000908152602081905260409020549190611fe3565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611f9190826120d9565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611ec1908590613e2f565b600081848411156120075760405162461bcd60e51b81526004016108af9190613f17565b505050900390565b60007f000000000000000000000000000000000000000000000000000000000000044d61203a613192565b141561206757507fdb0935b5bd521c385a8a7d0c64ea75e669d85c9bb308f0ef2364553fcadbca5f610686565b6120d27f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f9da7d00d7dbe36bf27d5370f8eb1ec90fedffeaa0cd39fca7a35acf6aa6ecf6e7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6613196565b9050610686565b60008282018381101561075c5760405162461bcd60e51b81526004016108af90614002565b6121548363a9059cbb60e01b848460405160240161211d929190613e0b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131d7565b505050565b600a54600090819061218090600160c01b8104600290810b91600160d81b9004900b612370565b600b5490925061219e90600281810b9163010000009004900b612370565b90509091565b600080600860009054906101000a90046001600160a01b03166001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b1580156121f557600080fd5b505afa158015612209573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222d9190613ab9565b50505050505090506122528161224288612989565b61224b88612989565b8787613266565b9695505050505050565b6001600160801b03841615610b05576010805460ff60a81b1916600160a81b17905560085460405160009182916001600160a01b039091169063aafe29c090309081908c908c908c906122b3908d90602001613d3d565b6040516020818303038152906040526040518763ffffffff1660e01b81526004016122e396959493929190613d51565b606060405180830381600087803b1580156122fd57600080fd5b505af1158015612311573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123359190613c86565b509150915083821015801561234a5750828110155b6123665760405162461bcd60e51b81526004016108af90614258565b5050505050505050565b600061237c83836126e7565b50909150506001600160801b038116156106a15760085460405163a34123a760e01b81526001600160a01b039091169063a34123a7906123c59086908690600090600401613ec4565b6040805180830381600087803b1580156123de57600080fd5b505af11580156123f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124169190613b98565b50506008546040516309e3d67b60e31b815260009182916001600160a01b0390911690634f1eb3d89061245c903090899089906001600160801b03908190600401613dce565b6040805180830381600087803b15801561247557600080fd5b505af1158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190613a10565b6001600160801b031691506001600160801b031691507f4606b8a47eb284e8e80929101ece6ab5fe8d4f8735acc56bd0c92ca872f2cfe7600a60149054906101000a900460ff1683836040516125059392919061452a565b60405180910390a1600a54600090612528908490600160a01b900460ff16612d7e565b1180156125b357506009546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612561903090600401613d3d565b60206040518083038186803b15801561257957600080fd5b505afa15801561258d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b19190613b3a565b115b156125f457601054600a546125f4916001600160a01b0316906125e1908590600160a01b900460ff16612d7e565b6009546001600160a01b031691906120fe565b600a5460009061260f908390600160a01b900460ff16612d7e565b11801561269a5750600a546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612648903090600401613d3d565b60206040518083038186803b15801561266057600080fd5b505afa158015612674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126989190613b3a565b115b156126db57601054600a546126db916001600160a01b0316906126c8908490600160a01b900460ff16612d7e565b600a546001600160a01b031691906120fe565b505092915050565b5490565b60085460405163514ea4bf60e01b81526000918291829130601881811b62ffffff8a81169190911790911b908816179290916001600160a01b03169063514ea4bf90612737908590600401613e2f565b60c06040518083038186803b15801561274f57600080fd5b505afa158015612763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127879190613a3e565b949c909b5093995092975050505050505050565b6000806001600160801b0387161561297d5760085460405163a34123a760e01b815260009182916001600160a01b039091169063a34123a7906127e6908e908e908e90600401613ec4565b6040805180830381600087803b1580156127ff57600080fd5b505af1158015612813573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128379190613b98565b9150915085821015801561284b5750848110155b6128675760405162461bcd60e51b81526004016108af90614258565b60008761287c576128778361331e565b612885565b6001600160801b035b905060008861289c576128978361331e565b6128a5565b6001600160801b035b90506000826001600160801b031611806128c857506000816001600160801b0316115b1561297857600860009054906101000a90046001600160a01b03166001600160a01b0316634f1eb3d88b8f8f86866040518663ffffffff1660e01b8152600401612916959493929190613dce565b6040805180830381600087803b15801561292f57600080fd5b505af1158015612943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129679190613a10565b6001600160801b0391821697501694505b505050505b97509795505050505050565b6000600282810b60171d90818418829003900b620d89e88111156129bf5760405162461bcd60e51b81526004016108af90614183565b6000600182166129d357600160801b6129e5565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612a19576ffff97272373d413259a46990580e213a0260801c5b6004821615612a38576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612a57576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612a76576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612a95576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ab4576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ad3576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612af3576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612b13576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612b33576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612b53576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612b73576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612b93576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612bb3576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612bd3576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612bf4576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615612c14576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615612c33576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615612c50576b048a170391f7dc42444e8fa20260801c5b60008560020b1315612c6b578060001981612c6757fe5b0490505b640100000000810615612c7f576001612c82565b60005b60ff16602082901c019350505050919050565b600082612ca4575060006106a1565b82820282848281612cb157fe5b041461075c5760405162461bcd60e51b81526004016108af906141e0565b6000808060001985870986860292508281109083900303905080612d055760008411612cfa57600080fd5b50829004905061075c565b808411612d1157600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6000808211612d9f5760405162461bcd60e51b81526004016108af9061414c565b818381612da857fe5b049392505050565b610848846323b872dd60e01b85858560405160240161211d93929190613daa565b6001600160a01b038216612df75760405162461bcd60e51b81526004016108af90614475565b612e0360008383612154565b600254612e1090826120d9565b6002556001600160a01b038216600090815260208190526040902054612e3690826120d9565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e85908590613e2f565b60405180910390a35050565b600080612e9e85856126e7565b50509050612ec8612ec3612eb06106d5565b6112a66001600160801b03851687612c95565b61331e565b95945050505050565b6000806000600860009054906101000a90046001600160a01b03166001600160a01b031663e76c01e46040518163ffffffff1660e01b815260040160e06040518083038186803b158015612f2457600080fd5b505afa158015612f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5c9190613ab9565b5050505050509050612f8081612f7188612989565b612f7a88612989565b87613335565b9250925050935093915050565b6001600160a01b038216612fb35760405162461bcd60e51b81526004016108af906142b9565b612fbf82600083612154565b612ffc816040518060600160405280602281526020016145bd602291396001600160a01b0385166000908152602081905260409020549190611fe3565b6001600160a01b03831660009081526020819052604090205560025461302290826133d1565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e85908590613e2f565b600061306d61200f565b8260405160200161307f929190613d22565b604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156130de5760405162461bcd60e51b81526004016108af906140c4565b8360ff16601b14806130f357508360ff16601c145b61310f5760405162461bcd60e51b81526004016108af9061419e565b6000600186868686604051600081526020016040526040516131349493929190613e98565b6020604051602081039080840390855afa158015613156573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612ec85760405162461bcd60e51b81526004016108af90613f2a565b80546001019055565b4690565b60008383836131a3613192565b306040516020016131b8959493929190613e6c565b6040516020818303038152906040528051906020012090509392505050565b600061322c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133f99092919063ffffffff16565b805190915015612154578080602001905181019061324a91906138ae565b6121545760405162461bcd60e51b81526004016108af906143f4565b6000836001600160a01b0316856001600160a01b03161115613286579293925b846001600160a01b0316866001600160a01b0316116132b1576132aa858585613410565b9050612ec8565b836001600160a01b0316866001600160a01b031610156133135760006132d8878686613410565b905060006132e7878986613473565b9050806001600160801b0316826001600160801b031610613308578061330a565b815b92505050612ec8565b612252858584613473565b60006001600160801b0382111561333157fe5b5090565b600080836001600160a01b0316856001600160a01b03161115613356579293925b846001600160a01b0316866001600160a01b0316116133815761337a8585856134b0565b91506133c8565b836001600160a01b0316866001600160a01b031610156133ba576133a68685856134b0565b91506133b3858785613519565b90506133c8565b6133c5858585613519565b90505b94509492505050565b6000828211156133f35760405162461bcd60e51b81526004016108af9061408d565b50900390565b6060613408848460008561355c565b949350505050565b6000826001600160a01b0316846001600160a01b03161115613430579192915b6000613453856001600160a01b0316856001600160a01b0316600160601b612ccf565b9050612ec861346e84838888036001600160a01b0316612ccf565b61361c565b6000826001600160a01b0316846001600160a01b03161115613493579192915b61340861346e83600160601b8787036001600160a01b0316612ccf565b6000826001600160a01b0316846001600160a01b031611156134d0579192915b836001600160a01b0316613509606060ff16846001600160801b0316901b8686036001600160a01b0316866001600160a01b0316612ccf565b8161351057fe5b04949350505050565b6000826001600160a01b0316846001600160a01b03161115613539579192915b613408826001600160801b03168585036001600160a01b0316600160601b612ccf565b60608247101561357e5760405162461bcd60e51b81526004016108af90614106565b61358785613632565b6135a35760405162461bcd60e51b81526004016108af906143bd565b600080866001600160a01b031685876040516135bf9190613d06565b60006040518083038185875af1925050503d80600081146135fc576040519150601f19603f3d011682016040523d82523d6000602084013e613601565b606091505b5091509150613611828286613638565b979650505050505050565b806001600160801b0381168114610b3d57600080fd5b3b151590565b6060831561364757508161075c565b8251156136575782518084602001fd5b8160405162461bcd60e51b81526004016108af9190613f17565b600082601f830112613681578081fd5b6040516040810181811067ffffffffffffffff8211171561369e57fe5b80604052508083856040860111156136b4578384fd5b835b60028110156136d55781358352602092830192909101906001016136b6565b509195945050505050565b600082601f8301126136f0578081fd5b6040516080810181811067ffffffffffffffff8211171561370d57fe5b604052808360808101861015613721578384fd5b835b60048110156136d5578135835260209283019290910190600101613723565b80518015158114610b3d57600080fd5b805161ffff81168114610b3d57600080fd5b600060208284031215613775578081fd5b813561075c81614571565b60008060408385031215613792578081fd5b823561379d81614571565b915060208301356137ad81614571565b809150509250929050565b6000806000606084860312156137cc578081fd5b83356137d781614571565b925060208401356137e781614571565b929592945050506040919091013590565b600080600080600080600060e0888a031215613812578283fd5b873561381d81614571565b9650602088013561382d81614571565b95506040880135945060608801359350608088013561384b816145ad565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561387a578182fd5b823561388581614571565b946020939093013593505050565b6000608082840312156138a4578081fd5b61075c83836136e0565b6000602082840312156138bf578081fd5b61075c82613742565b60008060008060008060006101a0888a0312156138e3578081fd5b87356138ee81614589565b965060208801356138fe81614589565b9550604088013561390e81614589565b9450606088013561391e81614589565b9350608088013561392e81614571565b925061393d8960a08a016136e0565b915061394d896101208a016136e0565b905092959891949750929550565b60008060008060a08587031215613970578182fd5b843561397b81614589565b9350602085013561398b81614589565b9250604085013561399b81614598565b91506139aa8660608701613671565b905092959194509250565b600080600080600060c086880312156139cc578283fd5b85356139d781614589565b945060208601356139e781614589565b93506040860135925060608601359150613a048760808801613671565b90509295509295909350565b60008060408385031215613a22578182fd5b8251613a2d81614598565b60208401519092506137ad81614598565b60008060008060008060c08789031215613a56578384fd5b8651613a6181614598565b602088015190965063ffffffff81168114613a7a578485fd5b8095505060408701519350606087015192506080870151613a9a81614598565b60a0880151909250613aab81614598565b809150509295509295509295565b600080600080600080600060e0888a031215613ad3578081fd5b8751613ade81614571565b6020890151909750613aef81614589565b9550613afd60408901613752565b9450613b0b60608901613752565b93506080880151613b1b816145ad565b60a0890151909350613b2c816145ad565b915061394d60c08901613742565b600060208284031215613b4b578081fd5b5051919050565b60008060008060e08587031215613b67578182fd5b843593506020850135613b7981614571565b92506040850135613b8981614571565b91506139aa86606087016136e0565b60008060408385031215613baa578182fd5b505080516020909101519092909150565b60008060008060006101008688031215613bd3578283fd5b85359450602086013593506040860135613bec81614571565b92506060860135613bfc81614571565b9150613a0487608088016136e0565b60008060008060608587031215613c20578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115613c45578384fd5b818701915087601f830112613c58578384fd5b813581811115613c66578485fd5b886020828501011115613c77578485fd5b95989497505060200194505050565b600080600060608486031215613c9a578081fd5b83519250602084015191506040840151613cb381614598565b809150509250925092565b600060208284031215613ccf578081fd5b813561075c816145ad565b60008151808452613cf2816020860160208601614545565b601f01601f19169290920160200192915050565b60008251613d18818460208701614545565b9190910192915050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b03878116825286166020820152600285810b604083015284900b60608201526001600160801b038316608082015260c060a08201819052600090613d9e90830184613cda565b98975050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03959095168552600293840b60208601529190920b60408401526001600160801b03918216606084015216608082015260a00190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b60029190910b815260200190565b600293840b81529190920b60208201526001600160801b03909116604082015260600190565b60029690960b8652602086019490945260408501929092526060840152608083015260a082015260c00190565b60006020825261075c6020830184613cda565b60208082526018908201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b602080825260029082015261746f60f01b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526003908201526237bbb760e91b604082015260600190565b6020808252601d908201527f45524332305065726d69743a206578706972656420646561646c696e65000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600190820152601560fa1b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601e908201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604082015260600190565b60208082526003908201526250534360e81b604082015260600190565b6020808252600a908201526937b7363c9037bbb732b960b11b604082015260600190565b60208082526006908201526573686172657360d01b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600390820152620dac2f60eb1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526003908201526257484560e81b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526020830191909152604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b60ff91909116815260200190565b60ff9390931683526020830191909152604082015260600190565b60005b83811015614560578181015183820152602001614548565b838111156108485750506000910152565b6001600160a01b038116811461458657600080fd5b50565b8060020b811461458657600080fd5b6001600160801b038116811461458657600080fd5b60ff8116811461458657600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220f940bb264bc082a145ef6482d9ea4b8dfde70bdab78aa145c9422d379a4c17ec64736f6c63430007060033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000fc4a3a7dc6b62bd2ea595b106392f5e006083b83000000000000000000000000ade38bd2e8d5a52e60047affe6e595bb5e61923a000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a61574554482d5742544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a61574554482d5742544300000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _pool (address): 0xFC4A3A7dc6b62bd2EA595b106392f5E006083b83
Arg [1] : _owner (address): 0xADE38bd2E8D5A52E60047AfFe6E595bB5E61923A
Arg [2] : name (string): aWETH-WBTC
Arg [3] : symbol (string): aWETH-WBTC

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000fc4a3a7dc6b62bd2ea595b106392f5e006083b83
Arg [1] : 000000000000000000000000ade38bd2e8d5a52e60047affe6e595bb5e61923a
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [5] : 61574554482d5742544300000000000000000000000000000000000000000000
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [7] : 61574554482d5742544300000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

116672:23087:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138640:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;24419:91;;;:::i;:::-;;;;;;;:::i;26565:169::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116890:20::-;;;:::i;:::-;;;;;;;:::i;117092:23::-;;;:::i;116859:24::-;;;:::i;25518:108::-;;;:::i;:::-;;;;;;;:::i;27216:321::-;;;;;;:::i;:::-;;:::i;117217:29::-;;;:::i;25362:91::-;;;:::i;:::-;;;;;;;:::i;37294:115::-;;;:::i;27946:218::-;;;;;;:::i;:::-;;:::i;134176:396::-;;;;;;:::i;:::-;;:::i;:::-;;117293:27;;;:::i;117184:26::-;;;:::i;128731:858::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;117062:23::-;;;:::i;129628:426::-;;;;;;:::i;:::-;;:::i;117151:26::-;;;:::i;117327:25::-;;;:::i;25689:127::-;;;;;;:::i;:::-;;:::i;37044:120::-;;;;;;:::i;:::-;;:::i;138971:107::-;;;;;;:::i;:::-;;:::i;126053:2354::-;;;;;;:::i;:::-;;:::i;117253:33::-;;;:::i;117033:22::-;;;:::i;117124:20::-;;;:::i;119373:2178::-;;;;;;:::i;:::-;;:::i;123033:514::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;24629:95::-;;;:::i;136331:588::-;;;:::i;:::-;;;;;;;;;:::i;28667:269::-;;;;;;:::i;:::-;;:::i;124001:1594::-;;;;;;:::i;:::-;;:::i;26029:175::-;;;;;;:::i;:::-;;:::i;117420:40::-;;;:::i;139408:99::-;;;:::i;134760:365::-;;;:::i;139122:98::-;;;:::i;139254:107::-;;;;;;:::i;:::-;;:::i;116971:24::-;;;:::i;116917:20::-;;;:::i;135435:583::-;;;:::i;36162:816::-;;;;;;:::i;:::-;;:::i;26267:151::-;;;;;;:::i;:::-;;:::i;116944:20::-;;;:::i;139515:141::-;;;;;;:::i;:::-;;:::i;117004:22::-;;;:::i;138640:114::-;138728:4;;:18;;;-1:-1:-1;;;138728:18:0;;;;138684:10;;-1:-1:-1;;;;;138728:4:0;;:16;;:18;;;;;;;;;;;;;;:4;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;138707:39:0;;138640:114;-1:-1:-1;;;;;;138640:114:0:o;24419:91::-;24497:5;24490:12;;;;;;;;-1:-1:-1;;24490:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24464:13;;24490:12;;24497:5;;24490:12;;24497:5;24490:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24419:91;;:::o;26565:169::-;26648:4;26665:39;26674:12;:10;:12::i;:::-;26688:7;26697:6;26665:8;:39::i;:::-;-1:-1:-1;26722:4:0;26565:169;;;;;:::o;116890:20::-;;;-1:-1:-1;;;;;116890:20:0;;:::o;117092:23::-;;;;;;;;;:::o;116859:24::-;;;-1:-1:-1;;;;;116859:24:0;;:::o;25518:108::-;25606:12;;25518:108;:::o;27216:321::-;27322:4;27339:36;27349:6;27357:9;27368:6;27339:9;:36::i;:::-;27386:121;27395:6;27403:12;:10;:12::i;:::-;27417:89;27455:6;27417:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;27417:19:0;;;;;;:11;:19;;;;;;27437:12;:10;:12::i;:::-;-1:-1:-1;;;;;27417:33:0;;;;;;;;;;;;-1:-1:-1;27417:33:0;;;:89;:37;:89::i;:::-;27386:8;:121::i;:::-;-1:-1:-1;27525:4:0;27216:321;;;;;;:::o;117217:29::-;;;;:::o;25362:91::-;25436:9;;;;25362:91;:::o;37294:115::-;37354:7;37381:20;:18;:20::i;:::-;37374:27;;37294:115;:::o;27946:218::-;28034:4;28051:83;28060:12;:10;:12::i;:::-;28074:7;28083:50;28122:10;28083:11;:25;28095:12;:10;:12::i;:::-;-1:-1:-1;;;;;28083:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;28083:25:0;;;:34;;;;;;;;;;;:38;:50::i;134176:396::-;134353:4;;-1:-1:-1;;;;;134353:4:0;134331:10;:27;134323:36;;;;;;134378:10;;-1:-1:-1;;;134378:10:0;;;;:18;;134392:4;134378:18;134370:27;;;;;;134408:10;:18;;-1:-1:-1;;;;134408:18:0;;;134443:11;;134439:57;;134456:6;;:40;;-1:-1:-1;;;;;134456:6:0;134476:10;134488:7;134456:19;:40::i;:::-;134511:11;;134507:57;;134524:6;;:40;;-1:-1:-1;;;;;134524:6:0;134544:10;134556:7;134524:19;:40::i;:::-;134176:396;;;;:::o;117293:27::-;;;-1:-1:-1;;;;;117293:27:0;;:::o;117184:26::-;;;;:::o;128731:858::-;128812:22;128845;128878:23;128912;139716:5;;;;;;;;;-1:-1:-1;;;;;139716:5:0;-1:-1:-1;;;;;139702:19:0;:10;-1:-1:-1;;;;;139702:19:0;;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;;;;;;;;;128995:10:::1;:8;:10::i;:::-;-1:-1:-1::0;;129071:9:0::1;::::0;129116:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;129116:31:0;;129018:17:::1;::::0;129038:164:::1;::::0;-1:-1:-1;;;129071:9:0;::::1;;::::0;;::::1;::::0;-1:-1:-1;;;129093:9:0;;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;129116:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;129141:4:::1;::::0;129116:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129160:6;::::0;:31:::1;::::0;-1:-1:-1;;;129160:31:0;;-1:-1:-1;;;;;129160:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;129185:4:::1;::::0;129160:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129038:20;:164::i;:::-;129228:9;::::0;129276:8;;129018:184;;-1:-1:-1;129213:82:0::1;::::0;-1:-1:-1;;;129228:9:0;::::1;;::::0;;::::1;::::0;-1:-1:-1;;;129239:9:0;::::1;::::0;::::1;::::0;129018:184;;129269:4:::1;::::0;129276:5;129292:1:::1;129286:8;;;;;129213:14;:82::i;:::-;129353:10;::::0;129400:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;129400:31:0;;129320:166:::1;::::0;129353:10:::1;::::0;;::::1;::::0;129376;;;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;129400:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;129425:4:::1;::::0;129400:31:::1;;;:::i;129320:166::-;129512:10;::::0;129562:8;;::::1;::::0;129308:178;;-1:-1:-1;129497:84:0::1;::::0;129512:10:::1;::::0;;::::1;::::0;129524;;::::1;::::0;::::1;::::0;129308:178;;129555:4:::1;::::0;129562:5;129578:1:::1;129572:8;::::0;129497:84:::1;139747:1;128731:858:::0;;;;;:::o;117062:23::-;;;;;;:::o;129628:426::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;129831:31:::1;129841:9;129852;129831;:31::i;:::-;;129873:17;129893:60;129914:9;129925;129936:7;129945;129893:20;:60::i;:::-;129873:80:::0;-1:-1:-1;129964:82:0::1;129979:9:::0;129990;129873:80;130020:4:::1;130027:5:::0;130033:1:::1;130027:8;;;::::0;130037:5;130043:1:::1;130037:8;::::0;129964:82:::1;139747:1;129628:426:::0;;;;;:::o;117151:26::-;;;;:::o;117327:25::-;;;-1:-1:-1;;;117327:25:0;;;;;:::o;25689:127::-;-1:-1:-1;;;;;25790:18:0;;25763:7;25790:18;;;;;;;;;;;25689:127;;;;:::o;37044:120::-;-1:-1:-1;;;;;37132:14:0;;37105:7;37132:14;;;:7;:14;;;;;:24;;:22;:24::i;138971:107::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;139041:18:::1;:29:::0;;-1:-1:-1;;;;;;139041:29:0::1;-1:-1:-1::0;;;;;139041:29:0;;;::::1;::::0;;;::::1;::::0;;138971:107::o;126053:2354::-;106286:1;106892:7;;:19;;106884:63;;;;-1:-1:-1;;;106884:63:0;;;;;;;:::i;:::-;106286:1;107025:7;:18;139716:5:::1;::::0;-1:-1:-1;;;139716:5:0;::::1;-1:-1:-1::0;;;;;139716:5:0::1;139702:10;:19;139694:42;;;;-1:-1:-1::0;;;139694:42:0::1;;;;;;;:::i;:::-;126369:10:::2;126356:23;;:10;:23;;;:73;;;;-1:-1:-1::0;126413:11:0::2;::::0;-1:-1:-1;;;126413:11:0;::::2;;::::0;;::::2;126400:24:::0;::::2;::::0;;;::::2;::::0;::::2;;;;;:29;;::::0;126356:73:::2;:123;;;;-1:-1:-1::0;126463:11:0::2;::::0;-1:-1:-1;;;126463:11:0;::::2;;::::0;;::::2;126450:24:::0;::::2;::::0;;;::::2;::::0;::::2;;;;;:29;;::::0;126356:123:::2;126334:156;;;::::0;::::2;;126537:11;126523:25;;:11;:25;;;:76;;;;-1:-1:-1::0;126583:11:0::2;::::0;-1:-1:-1;;;126583:11:0;::::2;;::::0;;::::2;126569:25:::0;::::2;::::0;;;::::2;::::0;::::2;;;;;:30;;::::0;126523:76:::2;:127;;;;-1:-1:-1::0;126634:11:0::2;::::0;-1:-1:-1;;;126634:11:0;::::2;;::::0;;::::2;126620:25:::0;::::2;::::0;;;::::2;::::0;::::2;;;;;:30;;::::0;126523:127:::2;126501:160;;;::::0;::::2;;126707:10;126692:25;;:11;:25;;;;:65;;;;126747:10;126732:25;;:11;:25;;;;126692:65;126672:96;;;::::0;::::2;;-1:-1:-1::0;;;;;126787:27:0;::::2;126779:36;;;::::0;::::2;;126826:12;:28:::0;;-1:-1:-1;;;;;;126826:28:0::2;-1:-1:-1::0;;;;;126826:28:0;::::2;;::::0;;126892:10:::2;:8;:10::i;:::-;-1:-1:-1::0;;127066:9:0::2;::::0;126991:21:::2;::::0;;;;;127056:31:::2;::::0;-1:-1:-1;;;127066:9:0;::::2;;::::0;;::::2;::::0;-1:-1:-1;;;127077:9:0;::::2;::::0;::::2;127056;:31::i;:::-;127173:10;::::0;126990:97;;-1:-1:-1;;;;;;126990:97:0;;::::2;::::0;-1:-1:-1;126990:97:0::2;::::0;-1:-1:-1;127099:22:0::2;::::0;;;;;127163:33:::2;::::0;127173:10:::2;::::0;;::::2;::::0;127185;;::::2;::::0;::::2;127163:9;:33::i;:::-;127224:9;::::0;127098:98;;-1:-1:-1;;;;;;127098:98:0;;::::2;::::0;-1:-1:-1;127098:98:0::2;::::0;-1:-1:-1;127209:94:0::2;::::0;-1:-1:-1;;;127224:9:0;::::2;;::::0;;::::2;::::0;-1:-1:-1;;;127235:9:0;::::2;::::0;::::2;127246:13:::0;127269:4:::2;127276;127282:6:::0;127289:1:::2;127282:9;;;::::0;127293:6;127300:1:::2;127293:9;;;;;127209:14;:94::i;:::-;-1:-1:-1::0;;127329:10:0::2;::::0;127314:97:::2;::::0;127329:10:::2;::::0;;::::2;::::0;127341;;::::2;::::0;::::2;::::0;127353:14;;127377:4:::2;::::0;127329:10;;127390:6;;:9:::2;;;;::::0;127401:6;127408:1:::2;127401:9;::::0;127314:97:::2;;;127429:248;127453:13;:11;:13::i;:::-;127481:6;::::0;:31:::2;::::0;-1:-1:-1;;;127481:31:0;;-1:-1:-1;;;;;127481:6:0;;::::2;::::0;:16:::2;::::0;:31:::2;::::0;127506:4:::2;::::0;127481:31:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127527:6;::::0;:31:::2;::::0;-1:-1:-1;;;127527:31:0;;-1:-1:-1;;;;;127527:6:0;;::::2;::::0;:16:::2;::::0;:31:::2;::::0;127552:4:::2;::::0;127527:31:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127573:25;:9:::0;127587:10;127573:13:::2;:25::i;:::-;127613;:9:::0;127627:10;127613:13:::2;:25::i;:::-;127653:13;:11;:13::i;:::-;127429:248;;;;;;;;;;;:::i;:::-;;;;;;;;127702:10;127690:9;;:22;;;;;;;;;;;;;;;;;;;;127735:10;127723:9;;:22;;;;;;;;;;;;;;;;;;;;127772:164;127805:9;;;;;;;;;;;127827;;;;;;;;;;;127850:6;;;;;;;;;-1:-1:-1::0;;;;;127850:6:0::2;-1:-1:-1::0;;;;;127850:16:0::2;;127875:4;127850:31;;;;;;;;;;;;;;;:::i;127772:164::-;127962:9;::::0;128014:8;;127756:180;;-1:-1:-1;127947:86:0::2;::::0;-1:-1:-1;;;127962:9:0;::::2;;::::0;;::::2;::::0;-1:-1:-1;;;127973:9:0;::::2;::::0;::::2;::::0;127756:180;;128007:4:::2;::::0;128014:5;128030:1:::2;128024:8;::::0;127947:86:::2;128059:11;128046:10;;:24;;;;;;;;;;;;;;;;;;;;128094:11;128081:10;;:24;;;;;;;;;;;;;;;;;;;;128133:166;128166:10;;;;;;;;;;;128189;;;;;;;;;;;128213:6;;;;;;;;;-1:-1:-1::0;;;;;128213:6:0::2;-1:-1:-1::0;;;;;128213:16:0::2;;128238:4;128213:31;;;;;;;;;;;;;;;:::i;128133:166::-;128325:10;::::0;128380:8;;::::2;::::0;128116:183;;-1:-1:-1;128310:89:0::2;::::0;128325:10:::2;::::0;;::::2;::::0;128337;;::::2;::::0;::::2;::::0;128116:183;;128373:4:::2;::::0;128380:5;128396:1:::2;128390:8;::::0;128310:89:::2;-1:-1:-1::0;;106242:1:0;107204:7;:22;-1:-1:-1;;;;;;;;;;;126053:2354:0:o;117253:33::-;;;-1:-1:-1;;;;;117253:33:0;;:::o;117033:22::-;;;-1:-1:-1;;;117033:22:0;;;;;:::o;117124:20::-;;;-1:-1:-1;;;117124:20:0;;-1:-1:-1;;;;;117124:20:0;;:::o;119373:2178::-;119560:14;106286:1;106892:7;;:19;;106884:63;;;;-1:-1:-1;;;106884:63:0;;;;;;;:::i;:::-;106286:1;107025:7;:18;119595:12;;;;:28:::1;;;119622:1;119611:8;:12;119595:28;119587:37;;;::::0;::::1;;119655:11;;119643:8;:23;;:50;;;;;119682:11;;119670:8;:23;;119643:50;119635:59;;;::::0;::::1;;-1:-1:-1::0;;;;;119713:16:0;::::1;::::0;;::::1;::::0;:39:::1;;-1:-1:-1::0;;;;;;119733:19:0;::::1;119747:4;119733:19;;119713:39;119705:54;;;;-1:-1:-1::0;;;119705:54:0::1;;;;;;;:::i;:::-;119792:18;::::0;-1:-1:-1;;;;;119792:18:0::1;119778:10;:32;119770:48;;;;-1:-1:-1::0;;;119770:48:0::1;;;;;;;:::i;:::-;119856:10;:8;:10::i;:::-;;;119879:17;119899:42;119927:13;:11;:13::i;:::-;119899:27;:42::i;:::-;119879:62:::0;-1:-1:-1;119952:13:0::1;119968:83;119984:42;-1:-1:-1::0;;;;;120007:18:0;::::1;::::0;119984:22:::1;:42::i;:::-;117456:4;-1:-1:-1::0;;;119968:15:0::1;:83::i;:::-;119952:99;;120065:13;120080::::0;120097:17:::1;:15;:17::i;:::-;120064:50:::0;;-1:-1:-1;120064:50:0;-1:-1:-1;120136:48:0::1;120149:34;117456:4;120149:19;:8:::0;120162:5;120149:12:::1;:19::i;:::-;:23:::0;::::1;:34::i;:::-;120136:8:::0;;:12:::1;:48::i;:::-;120127:57:::0;-1:-1:-1;120201:12:0;;120197:97:::1;;120228:6;::::0;:54:::1;::::0;-1:-1:-1;;;;;120228:6:0::1;120252:4:::0;120266::::1;120273:8:::0;120228:23:::1;:54::i;:::-;120308:12:::0;;120304:97:::1;;120335:6;::::0;:54:::1;::::0;-1:-1:-1;;;;;120335:6:0::1;120359:4:::0;120373::::1;120380:8:::0;120335:23:::1;:54::i;:::-;120413:13;120429;:11;:13::i;:::-;120413:29:::0;-1:-1:-1;120457:10:0;;120453:850:::1;;120482:27;120512:31;117456:4;120512:16;:5:::0;120522;120512:9:::1;:16::i;:31::-;120482:61:::0;-1:-1:-1;120565:53:0::1;120587:30;120482:61:::0;120611:5;120587:23:::1;:30::i;:::-;120565:17;:6:::0;120576:5;120565:10:::1;:17::i;:53::-;120635:13;::::0;120556:62;;-1:-1:-1;;;;120635:13:0;::::1;;;120631:661;;;120722:9;::::0;120775:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;120775:31:0;;120665:17:::1;::::0;120685:184:::1;::::0;-1:-1:-1;;;120722:9:0;::::1;;::::0;;::::1;::::0;-1:-1:-1;;;120748:9:0;;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;120775:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;120800:4:::1;::::0;120775:31:::1;;;:::i;120685:184::-;120899:9;::::0;120947:8;;120665:204;;-1:-1:-1;120884:82:0::1;::::0;-1:-1:-1;;;120899:9:0;::::1;;::::0;;::::1;::::0;-1:-1:-1;;;120910:9:0;::::1;::::0;::::1;::::0;120665:204;;120940:4:::1;::::0;120947:5;120963:1:::1;120957:8;::::0;120884:82:::1;121030:10;::::0;121085:6:::1;::::0;:31:::1;::::0;-1:-1:-1;;;121085:31:0;;120993:186:::1;::::0;121030:10:::1;::::0;;::::1;::::0;121057;;;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;121085:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;121110:4:::1;::::0;121085:31:::1;;;:::i;120993:186::-;121209:10;::::0;121259:8;;::::1;::::0;120981:198;;-1:-1:-1;121194:84:0::1;::::0;121209:10:::1;::::0;;::::1;::::0;121221;;::::1;::::0;::::1;::::0;120981:198;;121252:4:::1;::::0;121259:5;121275:1:::1;121269:8;::::0;121194:84:::1;120631:661;;120453:850;;121313:17;121319:2;121323:6;121313:5;:17::i;:::-;121360:2;-1:-1:-1::0;;;;;121346:45:0::1;121354:4;-1:-1:-1::0;;;;;121346:45:0::1;;121364:6;121372:8;121382;121346:45;;;;;;;;:::i;:::-;;;;;;;;121489:14;::::0;:19;;:46:::1;;;121521:14;;121512:5;:23;;121489:46;121481:62;;;;-1:-1:-1::0;;;121481:62:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;106242:1:0;107204:7;:22;-1:-1:-1;119373:2178:0;;;-1:-1:-1;;;;;;;119373:2178:0:o;123033:514::-;139716:5;;123206:15;;;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;123251:31:::1;123261:9;123272;123251;:31::i;:::-;;123314:225;123341:9;123363;123385:49;123405:9;123416;123427:6;-1:-1:-1::0;;;;;123385:49:0::1;:19;:49::i;:::-;123491:12:::0;;123455:4:::1;::::0;123473:5:::1;::::0;123491:9;123526:1:::1;123516:12;::::0;123314:225:::1;123293:246:::0;;;;-1:-1:-1;123033:514:0;-1:-1:-1;;;;;123033:514:0:o;24629:95::-;24709:7;24702:14;;;;;;;;-1:-1:-1;;24702:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24676:13;;24702:14;;24709:7;;24702:14;;24709:7;24702:14;;;;;;;;;;;;;;;;;;;;;;;;136331:588;136622:10;;136421:17;;;;;;;;;;;;136598:70;;136622:10;;;;;136647;;;;;136598:9;:70::i;:::-;136721:10;;136526:142;;-1:-1:-1;136526:142:0;;-1:-1:-1;136526:142:0;-1:-1:-1;136700:63:0;;136721:10;;;;;136733;;;;;136526:142;136700:20;:63::i;:::-;136679:84;;-1:-1:-1;136679:84:0;-1:-1:-1;136784:33:0;136679:84;-1:-1:-1;;;;;136796:20:0;;136784:11;:33::i;:::-;136774:43;-1:-1:-1;136838:33:0;:7;-1:-1:-1;;;;;136850:20:0;;136838:11;:33::i;:::-;136828:43;;136894:17;136882:29;;136331:588;;;;;;:::o;28667:269::-;28760:4;28777:129;28786:12;:10;:12::i;:::-;28800:7;28809:96;28848:15;28809:96;;;;;;;;;;;;;;;;;:11;:25;28821:12;:10;:12::i;:::-;-1:-1:-1;;;;;28809:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;28809:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;124001:1594::-;124165:15;124182;106286:1;106892:7;;:19;;106884:63;;;;-1:-1:-1;;;106884:63:0;;;;;;;:::i;:::-;106286:1;107025:7;:18;124218:10;124210:29:::1;;;;-1:-1:-1::0;;;124210:29:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;124258:16:0;::::1;124250:31;;;;-1:-1:-1::0;;;124250:31:0::1;;;;;;;:::i;:::-;124319:10;:8;:10::i;:::-;-1:-1:-1::0;;124454:9:0::1;::::0;124393:13:::1;::::0;;;124425:230:::1;::::0;-1:-1:-1;;;124454:9:0;::::1;;::::0;;::::1;::::0;-1:-1:-1;;;124478:9:0;::::1;::::0;::::1;124502:49;124454:9:::0;124478;124544:6;124502:19:::1;:49::i;:::-;124603:13:::0;;124566:2;;124583:5:::1;::::0;124603:10;124642:1:::1;124631:13;::::0;124425:230:::1;124730:10;::::0;124392:263;;-1:-1:-1;124392:263:0;-1:-1:-1;124667:14:0::1;::::0;;;124701:234:::1;::::0;124730:10:::1;::::0;;::::1;::::0;124755;;::::1;::::0;::::1;124780:51;124730:10:::0;124755;124824:6;124780:19:::1;:51::i;:::-;124846:2:::0;124863:5:::1;124883:10:::0;124894:1:::1;124883:13;::::0;124701:234:::1;124666:269;;;;125004:21;125028:62;125076:13;:11;:13::i;:::-;125028:6;::::0;:31:::1;::::0;-1:-1:-1;;;125028:31:0;;:43:::1;::::0;125064:6;;-1:-1:-1;;;;;125028:6:0;;::::1;::::0;:16:::1;::::0;:31:::1;::::0;125053:4:::1;::::0;125028:31:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35:::0;::::1;:43::i;:62::-;125004:86;;125101:21;125125:62;125173:13;:11;:13::i;:::-;125125:43;125161:6;125125;;;;;;;;;-1:-1:-1::0;;;;;125125:6:0::1;-1:-1:-1::0;;;;;125125:16:0::1;;125150:4;125125:31;;;;;;;;;;;;;;;:::i;:62::-;125101:86:::0;-1:-1:-1;125202:17:0;;125198:61:::1;;125221:6;::::0;:38:::1;::::0;-1:-1:-1;;;;;125221:6:0::1;125241:2:::0;125245:13;125221:19:::1;:38::i;:::-;125274:17:::0;;125270:61:::1;;125293:6;::::0;:38:::1;::::0;-1:-1:-1;;;;;125293:6:0::1;125313:2:::0;125317:13;125293:19:::1;:38::i;:::-;125354:36;125376:13:::0;125354:17:::1;:5:::0;125364:6;125354:9:::1;:17::i;:::-;:21:::0;::::1;:36::i;:::-;125344:46:::0;-1:-1:-1;125411:36:0::1;125433:13:::0;125411:17:::1;:5:::0;125421:6;125411:9:::1;:17::i;:36::-;125401:46:::0;-1:-1:-1;;;;;;125469:18:0;::::1;125477:10;125469:18;125460:35;;;;-1:-1:-1::0;;;125460:35:0::1;;;;;;;:::i;:::-;125506:19;125512:4;125518:6;125506:5;:19::i;:::-;125558:2;-1:-1:-1::0;;;;;125543:44:0::1;125552:4;-1:-1:-1::0;;;;;125543:44:0::1;;125562:6;125570:7;125579;125543:44;;;;;;;;:::i;:::-;;;;;;;;107056:1;;;;;;106242::::0;107204:7;:22;;;;124001:1594;;;;;;;:::o;26029:175::-;26115:4;26132:42;26142:12;:10;:12::i;:::-;26156:9;26167:6;26132:9;:42::i;117420:40::-;117456:4;117420:40;:::o;139408:99::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;139486:13:::1;::::0;;-1:-1:-1;;;;139469:30:0;::::1;-1:-1:-1::0;;;139486:13:0;;;::::1;;;139485:14;139469:30:::0;;::::1;;::::0;;139408:99::o;134760:365::-;134808:14;134824;134854:13;134869;134886:17;:15;:17::i;:::-;134851:52;;;;;134917:14;134933;134951:18;:16;:18::i;:::-;134989:6;;:31;;-1:-1:-1;;;134989:31:0;;134914:55;;-1:-1:-1;134914:55:0;;-1:-1:-1;134989:54:0;;-1:-1:-1;134914:55:0;;134989:42;;135025:5;;-1:-1:-1;;;;;134989:6:0;;;;:16;;:31;;135014:4;;134989:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:54::-;135063:6;;:31;;-1:-1:-1;;;135063:31:0;;134980:63;;-1:-1:-1;135063:54:0;;135110:6;;135063:42;;135099:5;;-1:-1:-1;;;;;135063:6:0;;:16;;:31;;135088:4;;135063:31;;;:::i;:54::-;135054:63;;134760:365;;;;;;:::o;139122:98::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;139181:18:::1;:31:::0;;-1:-1:-1;;;;;;139181:31:0::1;::::0;;139122:98::o;139254:107::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;139314:3:::1;:12:::0;;-1:-1:-1;;;;139314:12:0::1;-1:-1:-1::0;;;139314:12:0::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;139342:11:::1;::::0;::::1;::::0;::::1;::::0;139349:3;;::::1;::::0;;::::1;::::0;139342:11:::1;:::i;:::-;;;;;;;;139254:107:::0;:::o;116971:24::-;;;-1:-1:-1;;;116971:24:0;;;;;:::o;116917:20::-;;;-1:-1:-1;;;;;116917:20:0;;:::o;135435:583::-;135524:17;135556:15;135586;135630:25;135657:19;135678;135701:68;135725:9;;;;;;;;;;;135749;;;;;;;;;;;135701;:68::i;:::-;135822:9;;135629:140;;-1:-1:-1;135629:140:0;;-1:-1:-1;135629:140:0;-1:-1:-1;135801:61:0;;-1:-1:-1;;;135822:9:0;;;;;;;-1:-1:-1;;;135833:9:0;;;;135629:140;135801:20;:61::i;36162:816::-;36391:8;36372:15;:27;;36364:69;;;;-1:-1:-1;;;36364:69:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;36629:14:0;;36446:18;36629:14;;;:7;:14;;;;;36520:16;;36555:5;;36579:7;;36605:5;;36629:24;;:22;:24::i;:::-;36672:8;36491:204;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;36467:239;;;;;;36446:260;;36719:12;36734:28;36751:10;36734:16;:28::i;:::-;36719:43;;36775:14;36792:28;36806:4;36812:1;36815;36818;36792:13;:28::i;:::-;36775:45;;36849:5;-1:-1:-1;;;;;36839:15:0;:6;-1:-1:-1;;;;;36839:15:0;;36831:58;;;;-1:-1:-1;;;36831:58:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;36902:14:0;;;;;;:7;:14;;;;;:26;;:24;:26::i;:::-;36939:31;36948:5;36955:7;36964:5;36939:8;:31::i;:::-;36162:816;;;;;;;;;;:::o;26267:151::-;-1:-1:-1;;;;;26383:18:0;;;26356:7;26383:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;26267:151::o;116944:20::-;;;-1:-1:-1;;;116944:20:0;;;;;:::o;139515:141::-;139716:5;;-1:-1:-1;;;139716:5:0;;-1:-1:-1;;;;;139716:5:0;139702:10;:19;139694:42;;;;-1:-1:-1;;;139694:42:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;139598:22:0;::::1;139590:31;;;::::0;::::1;;139632:5;:16:::0;;-1:-1:-1;;;;;139632:16:0;;::::1;-1:-1:-1::0;;;139632:16:0::1;-1:-1:-1::0;;;;;;139632:16:0;;::::1;::::0;;;::::1;::::0;;139515:141::o;117004:22::-;;;-1:-1:-1;;;117004:22:0;;;;;:::o;21926:106::-;22014:10;21926:106;:::o;31814:346::-;-1:-1:-1;;;;;31916:19:0;;31908:68;;;;-1:-1:-1;;;31908:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;31995:21:0;;31987:68;;;;-1:-1:-1;;;31987:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;32068:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;;:36;;;32120:32;;;;;32098:6;;32120:32;:::i;:::-;;;;;;;;31814:346;;;:::o;29426:539::-;-1:-1:-1;;;;;29532:20:0;;29524:70;;;;-1:-1:-1;;;29524:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;29613:23:0;;29605:71;;;;-1:-1:-1;;;29605:71:0;;;;;;;:::i;:::-;29689:47;29710:6;29718:9;29729:6;29689:20;:47::i;:::-;29769:71;29791:6;29769:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;29769:17:0;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;-1:-1:-1;;;;;29749:17:0;;;:9;:17;;;;;;;;;;;:91;;;;29874:20;;;;;;;:32;;29899:6;29874:24;:32::i;:::-;-1:-1:-1;;;;;29851:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;29922:35;;;;;;;;;;29950:6;;29922:35;:::i;16693:166::-;16779:7;16815:12;16807:6;;;;16799:29;;;;-1:-1:-1;;;16799:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;16846:5:0;;;16693:166::o;7124:289::-;7185:7;7226:16;7209:13;:11;:13::i;:::-;:33;7205:201;;;-1:-1:-1;7266:24:0;7259:31;;7205:201;7330:64;7352:10;7364:12;7378:15;7330:21;:64::i;:::-;7323:71;;;;13866:179;13924:7;13956:5;;;13980:6;;;;13972:46;;;;-1:-1:-1;;;13972:46:0;;;;;;;:::i;46059:177::-;46142:86;46162:5;46192:23;;;46217:2;46221:5;46169:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;46169:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;46169:58:0;-1:-1:-1;;;;;;46169:58:0;;;;;;;;;;46142:19;:86::i;:::-;46059:177;;;:::o;122417:208::-;122536:9;;122454:21;;;;122526:31;;-1:-1:-1;;;122536:9:0;;;;;;;-1:-1:-1;;;122547:9:0;;;;122526;:31::i;:::-;122593:10;;122510:47;;-1:-1:-1;122583:33:0;;122593:10;;;;;122605;;;;;122583:9;:33::i;:::-;122566:50;;122417:208;;:::o;138047:529::-;138211:7;138232:20;138268:4;;;;;;;;;-1:-1:-1;;;;;138268:4:0;-1:-1:-1;;;;;138268:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;138231:55;;;;;;;;138317:251;138375:12;138406:38;138434:9;138406:27;:38::i;:::-;138463;138491:9;138463:27;:38::i;:::-;138520:7;138546;138317:39;:251::i;:::-;138297:271;138047:529;-1:-1:-1;;;;;;138047:529:0:o;130522:622::-;-1:-1:-1;;;;;130739:13:0;;;130735:402;;130769:10;:17;;-1:-1:-1;;;;130769:17:0;-1:-1:-1;;;130769:17:0;;;130840:4;;131016:17;;130769;;;;-1:-1:-1;;;;;130840:4:0;;;;:9;;130876:4;;;;130932:9;;130960;;130988;;131016:17;;131027:5;;131016:17;;;:::i;:::-;;;;;;;;;;;;;130840:208;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;130801:247;;;;;131082:10;131071:7;:21;;:46;;;;;131107:10;131096:7;:21;;131071:46;131063:62;;;;-1:-1:-1;;;131063:62:0;;;;;;;:::i;:::-;130735:402;;130522:622;;;;;;:::o;121559:698::-;121629:17;121711:31;121721:9;121732;121711;:31::i;:::-;-1:-1:-1;121694:48:0;;-1:-1:-1;;;;;;;121754:13:0;;;121751:493;;121780:4;;:34;;-1:-1:-1;;;121780:34:0;;-1:-1:-1;;;;;121780:4:0;;;;:9;;:34;;121790:9;;121801;;121780:4;;:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;121858:4:0;;:87;;-1:-1:-1;;;121858:87:0;;121826:13;;;;-1:-1:-1;;;;;121858:4:0;;;;:12;;:87;;121879:4;;121886:9;;121897;;-1:-1:-1;;;;;121908:17:0;;;121858:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;121825:120:0;;;-1:-1:-1;;;;;121825:120:0;;;121961:27;121970:3;;;;;;;;;;;121975:5;121982;121961:27;;;;;;;;:::i;:::-;;;;;;;;122013:3;;122020:1;;122003:14;;:5;;-1:-1:-1;;;122013:3:0;;;;122003:9;:14::i;:::-;:18;:57;;;;-1:-1:-1;122025:6:0;;:31;;-1:-1:-1;;;122025:31:0;;122059:1;;-1:-1:-1;;;;;122025:6:0;;:16;;:31;;122050:4;;122025:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;122003:57;121999:112;;;122082:12;;122106:3;;122062:49;;-1:-1:-1;;;;;122082:12:0;;122096:14;;:5;;-1:-1:-1;;;122106:3:0;;;;122096:9;:14::i;:::-;122062:6;;-1:-1:-1;;;;;122062:6:0;;:49;:19;:49::i;:::-;122136:3;;122143:1;;122126:14;;:5;;-1:-1:-1;;;122136:3:0;;;;122126:9;:14::i;:::-;:18;:57;;;;-1:-1:-1;122148:6:0;;:31;;-1:-1:-1;;;122148:31:0;;122182:1;;-1:-1:-1;;;;;122148:6:0;;:16;;:31;;122173:4;;122148:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;122126:57;122122:112;;;122205:12;;122229:3;;122185:49;;-1:-1:-1;;;;;122205:12:0;;122219:14;;:5;;-1:-1:-1;;;122229:3:0;;;;122219:9;:14::i;:::-;122185:6;;-1:-1:-1;;;;;122185:6:0;;:49;:19;:49::i;:::-;121751:493;;121559:698;;;;:::o;34388:114::-;34480:14;;34388:114::o;133601:510::-;134076:4;;:27;;-1:-1:-1;;;134076:27:0;;133718:17;;;;;;133880:4;133947:2;133943:13;;;134001:8;133958:24;;;133940:43;;;;133932:52;;;133986:24;;;133929:82;;133880:4;;-1:-1:-1;;;;;134076:4:0;;:14;;:27;;133929:82;;134076:27;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;134030:73;;;;-1:-1:-1;134030:73:0;;-1:-1:-1;133601:510:0;;-1:-1:-1;;;;;;;;133601:510:0:o;131783:884::-;132017:15;;-1:-1:-1;;;;;132066:13:0;;;132062:598;;132161:4;;:42;;-1:-1:-1;;;132161:42:0;;132129:13;;;;-1:-1:-1;;;;;132161:4:0;;;;:9;;:42;;132171:9;;132182;;132193;;132161:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132128:75;;;;132235:10;132226:5;:19;;:42;;;;;132258:10;132249:5;:19;;132226:42;132218:58;;;;-1:-1:-1;;;132218:58:0;;;;;;;:::i;:::-;132329:16;132348:10;:52;;132381:19;132394:5;132381:12;:19::i;:::-;132348:52;;;-1:-1:-1;;;;;132348:52:0;132329:71;;132415:16;132434:10;:52;;132467:19;132480:5;132467:12;:19::i;:::-;132434:52;;;-1:-1:-1;;;;;132434:52:0;132415:71;;132516:1;132505:8;-1:-1:-1;;;;;132505:12:0;;:28;;;;132532:1;132521:8;-1:-1:-1;;;;;132521:12:0;;132505:28;132501:148;;;132575:4;;;;;;;;;-1:-1:-1;;;;;132575:4:0;-1:-1:-1;;;;;132575:12:0;;132588:2;132592:9;132603;132614:8;132624;132575:58;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;132554:79:0;;;;-1:-1:-1;132554:79:0;;-1:-1:-1;132501:148:0;132062:598;;;;;131783:884;;;;;;;;;;:::o;109796:2517::-;109859:13;109916:16;;;;109925:6;109916:16;;109966:11;;;109965:20;;;109957:29;;109093:9;110001:28;;;109993:42;;;;-1:-1:-1;;;109993:42:0;;;;;;;:::i;:::-;110044:13;110070:3;110060:13;;:93;;-1:-1:-1;;;110060:93:0;;;110081:34;110060:93;110044:109;;;-1:-1:-1;110174:3:0;110164:13;;:18;110160:83;;110201:34;110193:42;110240:3;110192:51;110160:83;110264:3;110254:13;;:18;110250:83;;110291:34;110283:42;110330:3;110282:51;110250:83;110354:3;110344:13;;:18;110340:83;;110381:34;110373:42;110420:3;110372:51;110340:83;110444:4;110434:14;;:19;110430:84;;110472:34;110464:42;110511:3;110463:51;110430:84;110535:4;110525:14;;:19;110521:84;;110563:34;110555:42;110602:3;110554:51;110521:84;110626:4;110616:14;;:19;110612:84;;110654:34;110646:42;110693:3;110645:51;110612:84;110717:4;110707:14;;:19;110703:84;;110745:34;110737:42;110784:3;110736:51;110703:84;110808:5;110798:15;;:20;110794:85;;110837:34;110829:42;110876:3;110828:51;110794:85;110900:5;110890:15;;:20;110886:85;;110929:34;110921:42;110968:3;110920:51;110886:85;110992:5;110982:15;;:20;110978:85;;111021:34;111013:42;111060:3;111012:51;110978:85;111084:5;111074:15;;:20;111070:85;;111113:34;111105:42;111152:3;111104:51;111070:85;111176:6;111166:16;;:21;111162:86;;111206:34;111198:42;111245:3;111197:51;111162:86;111269:6;111259:16;;:21;111255:86;;111299:34;111291:42;111338:3;111290:51;111255:86;111362:6;111352:16;;:21;111348:86;;111392:34;111384:42;111431:3;111383:51;111348:86;111455:6;111445:16;;:21;111441:86;;111485:34;111477:42;111524:3;111476:51;111441:86;111548:7;111538:17;;:22;111534:86;;111579:33;111571:41;111617:3;111570:50;111534:86;111641:7;111631:17;;:22;111627:85;;111672:32;111664:40;111709:3;111663:49;111627:85;111733:7;111723:17;;:22;111719:83;;111764:30;111756:38;111799:3;111755:47;111719:83;111823:7;111813:17;;:22;111809:78;;111854:25;111846:33;111884:3;111845:42;111809:78;111907:1;111900:4;:8;;;111896:47;;;111938:5;-1:-1:-1;;111918:25:0;;;;;;111910:33;;111896:47;112284:7;112275:5;:17;:22;:30;;112304:1;112275:30;;;112300:1;112275:30;112258:48;;112268:2;112259:5;:11;;112258:48;112242:65;;109796:2517;;;;;;:::o;14745:220::-;14803:7;14827:6;14823:20;;-1:-1:-1;14842:1:0;14835:8;;14823:20;14866:5;;;14870:1;14866;:5;:1;14890:5;;;;;:10;14882:56;;;;-1:-1:-1;;;14882:56:0;;;;;;;:::i;50292:3868::-;50408:14;;;-1:-1:-1;;50924:1:0;50921;50914:20;50957:9;;;;-1:-1:-1;51009:13:0;;;50993:14;;;;50989:34;;-1:-1:-1;51109:10:0;51105:185;;51158:1;51144:11;:15;51136:24;;;;;;-1:-1:-1;51213:23:0;;;;-1:-1:-1;51265:13:0;;51105:185;51421:5;51407:11;:19;51399:28;;;;;;51712:17;51790:11;51787:1;51784;51777:25;52153:12;52168;;;:26;;52291:22;;;;;53114:1;53095;:15;;53094:21;;53345:17;;;53341:21;;53334:28;53404:17;;;53400:21;;53393:28;53464:17;;;53460:21;;53453:28;53524:17;;;53520:21;;53513:28;53584:17;;;53580:21;;53573:28;53645:17;;;53641:21;;;53634:28;52674:12;;;;52670:23;;;52695:1;52666:31;51923:20;;;51912:32;;;52727:12;;;;51967:21;;;;52424:16;;;;52718:21;;;;54117:11;;;;;-1:-1:-1;;50292:3868:0;;;;;:::o;15443:153::-;15501:7;15533:1;15529;:5;15521:44;;;;-1:-1:-1;;;15521:44:0;;;;;;;:::i;:::-;15587:1;15583;:5;;;;;;;15443:153;-1:-1:-1;;;15443:153:0:o;46244:205::-;46345:96;46365:5;46395:27;;;46424:4;46430:2;46434:5;46372:68;;;;;;;;;;:::i;30247:378::-;-1:-1:-1;;;;;30331:21:0;;30323:65;;;;-1:-1:-1;;;30323:65:0;;;;;;;:::i;:::-;30401:49;30430:1;30434:7;30443:6;30401:20;:49::i;:::-;30478:12;;:24;;30495:6;30478:16;:24::i;:::-;30463:12;:39;-1:-1:-1;;;;;30534:18:0;;:9;:18;;;;;;;;;;;:30;;30557:6;30534:22;:30::i;:::-;-1:-1:-1;;;;;30513:18:0;;:9;:18;;;;;;;;;;;:51;;;;30580:37;;30513:18;;:9;30580:37;;;;30610:6;;30580:37;:::i;:::-;;;;;;;;30247:378;;:::o;132958:300::-;133094:7;133115:16;133139:31;133149:9;133160;133139;:31::i;:::-;133114:56;;;;133188:62;133201:48;133235:13;:11;:13::i;:::-;133201:29;-1:-1:-1;;;;;133201:17:0;;133223:6;133201:21;:29::i;:48::-;133188:12;:62::i;:::-;133181:69;132958:300;-1:-1:-1;;;;;132958:300:0:o;137217:490::-;137357:7;137366;137387:20;137423:4;;;;;;;;;-1:-1:-1;;;;;137423:4:0;-1:-1:-1;;;;;137423:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137386:55;;;;;;;;137472:227;137530:12;137561:38;137589:9;137561:27;:38::i;:::-;137618;137646:9;137618:27;:38::i;:::-;137675:9;137472:39;:227::i;:::-;137452:247;;;;;137217:490;;;;;;:::o;30958:418::-;-1:-1:-1;;;;;31042:21:0;;31034:67;;;;-1:-1:-1;;;31034:67:0;;;;;;;:::i;:::-;31114:49;31135:7;31152:1;31156:6;31114:20;:49::i;:::-;31197:68;31220:6;31197:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;31197:18:0;;:9;:18;;;;;;;;;;;;:68;:22;:68::i;:::-;-1:-1:-1;;;;;31176:18:0;;:9;:18;;;;;;;;;;:89;31291:12;;:24;;31308:6;31291:16;:24::i;:::-;31276:12;:39;31331:37;;31357:1;;-1:-1:-1;;;;;31331:37:0;;;;;;;31361:6;;31331:37;:::i;8400:185::-;8477:7;8543:20;:18;:20::i;:::-;8565:10;8514:62;;;;;;;;;:::i;:::-;;;;;;;;;;;;;8504:73;;;;;;8497:80;;8400:185;;;:::o;2124:1432::-;2209:7;3134:66;3120:80;;;3112:127;;;;-1:-1:-1;;;3112:127:0;;;;;;;:::i;:::-;3258:1;:7;;3263:2;3258:7;:18;;;;3269:1;:7;;3274:2;3269:7;3258:18;3250:65;;;;-1:-1:-1;;;3250:65:0;;;;;;;:::i;:::-;3413:14;3430:24;3440:4;3446:1;3449;3452;3430:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3430:24:0;;-1:-1:-1;;3430:24:0;;;-1:-1:-1;;;;;;;3473:20:0;;3465:57;;;;-1:-1:-1;;;3465:57:0;;;;;;;:::i;34510:181::-;34664:19;;34682:1;34664:19;;;34510:181::o;8593:326::-;8892:9;;8866:46::o;7421:337::-;7523:7;7603:8;7630:4;7653:7;7679:13;:11;:13::i;:::-;7719:4;7574:165;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;7550:200;;;;;;7543:207;;7421:337;;;;;:::o;48364:761::-;48788:23;48814:69;48842:4;48814:69;;;;;;;;;;;;;;;;;48822:5;-1:-1:-1;;;;;48814:27:0;;;:69;;;;;:::i;:::-;48898:17;;48788:95;;-1:-1:-1;48898:21:0;48894:224;;49040:10;49029:30;;;;;;;;;;;;:::i;:::-;49021:85;;;;-1:-1:-1;;;49021:85:0;;;;;;;:::i;57703:920::-;57912:17;57962:13;-1:-1:-1;;;;;57946:29:0;:13;-1:-1:-1;;;;;57946:29:0;;57942:98;;;58011:13;;58026;57942:98;58073:13;-1:-1:-1;;;;;58057:29:0;:12;-1:-1:-1;;;;;58057:29:0;;58053:563;;58115:61;58138:13;58153;58168:7;58115:22;:61::i;:::-;58103:73;;58053:563;;;58213:13;-1:-1:-1;;;;;58198:28:0;:12;-1:-1:-1;;;;;58198:28:0;;58194:422;;;58243:18;58264:60;58287:12;58301:13;58316:7;58264:22;:60::i;:::-;58243:81;;58339:18;58360:60;58383:13;58398:12;58412:7;58360:22;:60::i;:::-;58339:81;;58462:10;-1:-1:-1;;;;;58449:23:0;:10;-1:-1:-1;;;;;58449:23:0;;:49;;58488:10;58449:49;;;58475:10;58449:49;58437:61;;58194:422;;;;;58543:61;58566:13;58581;58596:7;58543:22;:61::i;138762:142::-;138818:7;-1:-1:-1;;;;;138845:22:0;;;138838:30;;;;-1:-1:-1;138894:1:0;138762:142::o;60798:815::-;60983:15;61000;61048:13;-1:-1:-1;;;;;61032:29:0;:13;-1:-1:-1;;;;;61032:29:0;;61028:98;;;61097:13;;61112;61028:98;61159:13;-1:-1:-1;;;;;61143:29:0;:12;-1:-1:-1;;;;;61143:29:0;;61139:467;;61199:63;61222:13;61237;61252:9;61199:22;:63::i;:::-;61189:73;;61139:467;;;61299:13;-1:-1:-1;;;;;61284:28:0;:12;-1:-1:-1;;;;;61284:28:0;;61280:326;;;61339:62;61362:12;61376:13;61391:9;61339:22;:62::i;:::-;61329:72;;61426:62;61449:13;61464:12;61478:9;61426:22;:62::i;:::-;61416:72;;61280:326;;;61531:63;61554:13;61569;61584:9;61531:22;:63::i;:::-;61521:73;;61280:326;60798:815;;;;;;;:::o;14328:158::-;14386:7;14419:1;14414;:6;;14406:49;;;;-1:-1:-1;;;14406:49:0;;;;;;;:::i;:::-;-1:-1:-1;14473:5:0;;;14328:158::o;41081:195::-;41184:12;41216:52;41238:6;41246:4;41252:1;41255:12;41216:21;:52::i;:::-;41209:59;41081:195;-1:-1:-1;;;;41081:195:0:o;55773:483::-;55925:17;55975:13;-1:-1:-1;;;;;55959:29:0;:13;-1:-1:-1;;;;;55959:29:0;;55955:98;;;56024:13;;56039;55955:98;56064:20;56087:63;56103:13;-1:-1:-1;;;;;56087:63:0;56118:13;-1:-1:-1;;;;;56087:63:0;-1:-1:-1;;;56087:15:0;:63::i;:::-;56064:86;;56168:80;56178:69;56194:7;56203:12;56233:13;56217;:29;-1:-1:-1;;;;;56178:69:0;:15;:69::i;:::-;56168:9;:80::i;56703:390::-;56855:17;56905:13;-1:-1:-1;;;;;56889:29:0;:13;-1:-1:-1;;;;;56889:29:0;;56885:98;;;56954:13;;56969;56885:98;57001:84;57011:73;57027:7;-1:-1:-1;;;57070:13:0;57054;:29;-1:-1:-1;;;;;57011:73:0;:15;:73::i;58988:511::-;59142:15;59190:13;-1:-1:-1;;;;;59174:29:0;:13;-1:-1:-1;;;;;59174:29:0;;59170:98;;;59239:13;;59254;59170:98;59478:13;-1:-1:-1;;;;;59301:190:0;:174;49450:2;59335:45;;59343:9;-1:-1:-1;;;;;59335:18:0;:45;;59415:13;59399;:29;-1:-1:-1;;;;;59301:174:0;59447:13;-1:-1:-1;;;;;59301:174:0;:15;:174::i;:::-;:190;;;;;;;58988:511;-1:-1:-1;;;;58988:511:0:o;59864:383::-;60018:15;60066:13;-1:-1:-1;;;;;60050:29:0;:13;-1:-1:-1;;;;;60050:29:0;;60046:98;;;60115:13;;60130;60046:98;60164:75;60180:9;-1:-1:-1;;;;;60164:75:0;60207:13;60191;:29;-1:-1:-1;;;;;60164:75:0;-1:-1:-1;;;60164:15:0;:75::i;42133:530::-;42260:12;42318:5;42293:21;:30;;42285:81;;;;-1:-1:-1;;;42285:81:0;;;;;;;:::i;:::-;42385:18;42396:6;42385:10;:18::i;:::-;42377:60;;;;-1:-1:-1;;;42377:60:0;;;;;;;:::i;:::-;42511:12;42525:23;42552:6;-1:-1:-1;;;;;42552:11:0;42572:5;42580:4;42552:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42510:75;;;;42603:52;42621:7;42630:10;42642:12;42603:17;:52::i;:::-;42596:59;42133:530;-1:-1:-1;;;;;;;42133:530:0:o;55185:112::-;55287:1;-1:-1:-1;;;;;55267:21:0;;;;55259:30;;;;;38163:422;38530:20;38569:8;;;38163:422::o;44673:742::-;44788:12;44817:7;44813:595;;;-1:-1:-1;44848:10:0;44841:17;;44813:595;44962:17;;:21;44958:439;;45225:10;45219:17;45286:15;45273:10;45269:2;45265:19;45258:44;45173:148;45368:12;45361:20;;-1:-1:-1;;;45361:20:0;;;;;;;;:::i;14:709:1:-;;133:3;126:4;118:6;114:17;110:27;100:2;;155:5;148;141:20;100:2;192;186:9;234:2;226:6;222:15;303:6;291:10;288:22;267:18;255:10;252:34;249:62;246:2;;;314:9;246:2;345:10;341:2;334:22;;376:6;402;440:3;435:2;427:6;423:15;420:24;417:2;;;461:5;454;447:20;417:2;487:5;501:192;515:4;512:1;509:11;501:192;;;574:17;;562:30;;615:4;639:12;;;;671;;;;535:1;528:9;501:192;;;-1:-1:-1;711:6:1;;90:633;-1:-1:-1;;;;;90:633:1:o;728:700::-;;836:3;829:4;821:6;817:17;813:27;803:2;;858:5;851;844:20;803:2;895;889:9;937:3;929:6;925:16;1007:6;995:10;992:22;971:18;959:10;956:34;953:62;950:2;;;1018:9;950:2;1045;1038:22;1080:6;1106;1139:3;1127:16;;1124:25;-1:-1:-1;1121:2:1;;;1166:5;1159;1152:20;1121:2;1192:5;1206:192;1220:4;1217:1;1214:11;1206:192;;;1279:17;;1267:30;;1320:4;1344:12;;;;1376;;;;1240:1;1233:9;1206:192;;1433:166;1511:13;;1560;;1553:21;1543:32;;1533:2;;1589:1;1586;1579:12;1604:165;1684:13;;1737:6;1726:18;;1716:29;;1706:2;;1759:1;1756;1749:12;1774:259;;1886:2;1874:9;1865:7;1861:23;1857:32;1854:2;;;1907:6;1899;1892:22;1854:2;1951:9;1938:23;1970:33;1997:5;1970:33;:::i;2038:402::-;;;2167:2;2155:9;2146:7;2142:23;2138:32;2135:2;;;2188:6;2180;2173:22;2135:2;2232:9;2219:23;2251:33;2278:5;2251:33;:::i;:::-;2303:5;-1:-1:-1;2360:2:1;2345:18;;2332:32;2373:35;2332:32;2373:35;:::i;:::-;2427:7;2417:17;;;2125:315;;;;;:::o;2445:470::-;;;;2591:2;2579:9;2570:7;2566:23;2562:32;2559:2;;;2612:6;2604;2597:22;2559:2;2656:9;2643:23;2675:33;2702:5;2675:33;:::i;:::-;2727:5;-1:-1:-1;2784:2:1;2769:18;;2756:32;2797:35;2756:32;2797:35;:::i;:::-;2549:366;;2851:7;;-1:-1:-1;;;2905:2:1;2890:18;;;;2877:32;;2549:366::o;2920:817::-;;;;;;;;3132:3;3120:9;3111:7;3107:23;3103:33;3100:2;;;3154:6;3146;3139:22;3100:2;3198:9;3185:23;3217:33;3244:5;3217:33;:::i;:::-;3269:5;-1:-1:-1;3326:2:1;3311:18;;3298:32;3339:35;3298:32;3339:35;:::i;:::-;3393:7;-1:-1:-1;3447:2:1;3432:18;;3419:32;;-1:-1:-1;3498:2:1;3483:18;;3470:32;;-1:-1:-1;3554:3:1;3539:19;;3526:33;3568;3526;3568;:::i;:::-;3090:647;;;;-1:-1:-1;3090:647:1;;;;3620:7;3674:3;3659:19;;3646:33;;-1:-1:-1;3726:3:1;3711:19;;;3698:33;;3090:647;-1:-1:-1;;3090:647:1:o;3742:327::-;;;3871:2;3859:9;3850:7;3846:23;3842:32;3839:2;;;3892:6;3884;3877:22;3839:2;3936:9;3923:23;3955:33;3982:5;3955:33;:::i;:::-;4007:5;4059:2;4044:18;;;;4031:32;;-1:-1:-1;;;3829:240:1:o;4074:::-;;4209:3;4197:9;4188:7;4184:23;4180:33;4177:2;;;4231:6;4223;4216:22;4177:2;4259:49;4300:7;4289:9;4259:49;:::i;4319:214::-;;4439:2;4427:9;4418:7;4414:23;4410:32;4407:2;;;4460:6;4452;4445:22;4407:2;4488:39;4517:9;4488:39;:::i;4538:1053::-;;;;;;;;4790:3;4778:9;4769:7;4765:23;4761:33;4758:2;;;4812:6;4804;4797:22;4758:2;4856:9;4843:23;4875:31;4900:5;4875:31;:::i;:::-;4925:5;-1:-1:-1;4982:2:1;4967:18;;4954:32;4995:33;4954:32;4995:33;:::i;:::-;5047:7;-1:-1:-1;5106:2:1;5091:18;;5078:32;5119:33;5078:32;5119:33;:::i;:::-;5171:7;-1:-1:-1;5230:2:1;5215:18;;5202:32;5243:33;5202:32;5243:33;:::i;:::-;5295:7;-1:-1:-1;5354:3:1;5339:19;;5326:33;5368:35;5326:33;5368:35;:::i;:::-;5422:7;-1:-1:-1;5448:59:1;5499:7;5493:3;5478:19;;5448:59;:::i;:::-;5438:69;;5526:59;5577:7;5571:3;5560:9;5556:19;5526:59;:::i;:::-;5516:69;;4748:843;;;;;;;;;;:::o;5596:666::-;;;;;5778:3;5766:9;5757:7;5753:23;5749:33;5746:2;;;5800:6;5792;5785:22;5746:2;5844:9;5831:23;5863:31;5888:5;5863:31;:::i;:::-;5913:5;-1:-1:-1;5970:2:1;5955:18;;5942:32;5983:33;5942:32;5983:33;:::i;:::-;6035:7;-1:-1:-1;6094:2:1;6079:18;;6066:32;6107:35;6066:32;6107:35;:::i;:::-;6161:7;-1:-1:-1;6187:69:1;6248:7;6243:2;6228:18;;6187:69;:::i;:::-;6177:79;;5736:526;;;;;;;:::o;6267:660::-;;;;;;6466:3;6454:9;6445:7;6441:23;6437:33;6434:2;;;6488:6;6480;6473:22;6434:2;6532:9;6519:23;6551:31;6576:5;6551:31;:::i;:::-;6601:5;-1:-1:-1;6658:2:1;6643:18;;6630:32;6671:33;6630:32;6671:33;:::i;:::-;6723:7;-1:-1:-1;6777:2:1;6762:18;;6749:32;;-1:-1:-1;6828:2:1;6813:18;;6800:32;;-1:-1:-1;6851:70:1;6913:7;6907:3;6892:19;;6851:70;:::i;:::-;6841:80;;6424:503;;;;;;;;:::o;6932:399::-;;;7072:2;7060:9;7051:7;7047:23;7043:32;7040:2;;;7093:6;7085;7078:22;7040:2;7130:9;7124:16;7149:33;7176:5;7149:33;:::i;:::-;7251:2;7236:18;;7230:25;7201:5;;-1:-1:-1;7264:35:1;7230:25;7264:35;:::i;7336:835::-;;;;;;;7543:3;7531:9;7522:7;7518:23;7514:33;7511:2;;;7565:6;7557;7550:22;7511:2;7602:9;7596:16;7621:33;7648:5;7621:33;:::i;:::-;7723:2;7708:18;;7702:25;7673:5;;-1:-1:-1;7771:10:1;7758:24;;7746:37;;7736:2;;7802:6;7794;7787:22;7736:2;7830:7;7820:17;;;7877:2;7866:9;7862:18;7856:25;7846:35;;7921:2;7910:9;7906:18;7900:25;7890:35;;7970:3;7959:9;7955:19;7949:26;7984:35;8011:7;7984:35;:::i;:::-;8090:3;8075:19;;8069:26;8038:7;;-1:-1:-1;8104:35:1;8069:26;8104:35;:::i;:::-;8158:7;8148:17;;;7501:670;;;;;;;;:::o;8176:914::-;;;;;;;;8390:3;8378:9;8369:7;8365:23;8361:33;8358:2;;;8412:6;8404;8397:22;8358:2;8449:9;8443:16;8468:33;8495:5;8468:33;:::i;:::-;8570:2;8555:18;;8549:25;8520:5;;-1:-1:-1;8583:33:1;8549:25;8583:33;:::i;:::-;8635:7;-1:-1:-1;8661:50:1;8707:2;8692:18;;8661:50;:::i;:::-;8651:60;;8730:50;8776:2;8765:9;8761:18;8730:50;:::i;:::-;8720:60;;8825:3;8814:9;8810:19;8804:26;8839:33;8864:7;8839:33;:::i;:::-;8943:3;8928:19;;8922:26;8891:7;;-1:-1:-1;8957:33:1;8922:26;8957:33;:::i;:::-;9009:7;-1:-1:-1;9035:49:1;9079:3;9064:19;;9035:49;:::i;9095:194::-;;9218:2;9206:9;9197:7;9193:23;9189:32;9186:2;;;9239:6;9231;9224:22;9186:2;-1:-1:-1;9267:16:1;;9176:113;-1:-1:-1;9176:113:1:o;9294:588::-;;;;;9480:3;9468:9;9459:7;9455:23;9451:33;9448:2;;;9502:6;9494;9487:22;9448:2;9543:9;9530:23;9520:33;;9603:2;9592:9;9588:18;9575:32;9616:33;9643:5;9616:33;:::i;:::-;9668:5;-1:-1:-1;9725:2:1;9710:18;;9697:32;9738:35;9697:32;9738:35;:::i;:::-;9792:7;-1:-1:-1;9818:58:1;9868:7;9863:2;9848:18;;9818:58;:::i;9887:255::-;;;10027:2;10015:9;10006:7;10002:23;9998:32;9995:2;;;10048:6;10040;10033:22;9995:2;-1:-1:-1;;10076:16:1;;10132:2;10117:18;;;10111:25;10076:16;;10111:25;;-1:-1:-1;9985:157:1:o;10147:657::-;;;;;;10350:3;10338:9;10329:7;10325:23;10321:33;10318:2;;;10372:6;10364;10357:22;10318:2;10413:9;10400:23;10390:33;;10470:2;10459:9;10455:18;10442:32;10432:42;;10524:2;10513:9;10509:18;10496:32;10537:33;10564:5;10537:33;:::i;:::-;10589:5;-1:-1:-1;10646:2:1;10631:18;;10618:32;10659:35;10618:32;10659:35;:::i;:::-;10713:7;-1:-1:-1;10739:59:1;10790:7;10784:3;10769:19;;10739:59;:::i;10809:777::-;;;;;10974:2;10962:9;10953:7;10949:23;10945:32;10942:2;;;10995:6;10987;10980:22;10942:2;11036:9;11023:23;11013:33;;11093:2;11082:9;11078:18;11065:32;11055:42;;11148:2;11137:9;11133:18;11120:32;11171:18;11212:2;11204:6;11201:14;11198:2;;;11233:6;11225;11218:22;11198:2;11276:6;11265:9;11261:22;11251:32;;11321:7;11314:4;11310:2;11306:13;11302:27;11292:2;;11348:6;11340;11333:22;11292:2;11393;11380:16;11419:2;11411:6;11408:14;11405:2;;;11440:6;11432;11425:22;11405:2;11490:7;11485:2;11476:6;11472:2;11468:15;11464:24;11461:37;11458:2;;;11516:6;11508;11501:22;11458:2;10932:654;;;;-1:-1:-1;;11552:2:1;11544:11;;-1:-1:-1;;;10932:654:1:o;11591:385::-;;;;11748:2;11736:9;11727:7;11723:23;11719:32;11716:2;;;11769:6;11761;11754:22;11716:2;11803:9;11797:16;11787:26;;11853:2;11842:9;11838:18;11832:25;11822:35;;11900:2;11889:9;11885:18;11879:25;11913:33;11940:5;11913:33;:::i;:::-;11965:5;11955:15;;;11706:270;;;;;:::o;11981:255::-;;12091:2;12079:9;12070:7;12066:23;12062:32;12059:2;;;12112:6;12104;12097:22;12059:2;12156:9;12143:23;12175:31;12200:5;12175:31;:::i;12241:259::-;;12322:5;12316:12;12349:6;12344:3;12337:19;12365:63;12421:6;12414:4;12409:3;12405:14;12398:4;12391:5;12387:16;12365:63;:::i;:::-;12482:2;12461:15;-1:-1:-1;;12457:29:1;12448:39;;;;12489:4;12444:50;;12292:208;-1:-1:-1;;12292:208:1:o;12505:274::-;;12672:6;12666:13;12688:53;12734:6;12729:3;12722:4;12714:6;12710:17;12688:53;:::i;:::-;12757:16;;;;;12642:137;-1:-1:-1;;12642:137:1:o;12784:392::-;-1:-1:-1;;;13042:27:1;;13094:1;13085:11;;13078:27;;;;13130:2;13121:12;;13114:28;13167:2;13158:12;;13032:144::o;13181:203::-;-1:-1:-1;;;;;13345:32:1;;;;13327:51;;13315:2;13300:18;;13282:102::o;13389:697::-;-1:-1:-1;;;;;13706:15:1;;;13688:34;;13758:15;;13753:2;13738:18;;13731:43;13821:1;13810:21;;;13805:2;13790:18;;13783:49;13868:21;;;13863:2;13848:18;;13841:49;-1:-1:-1;;;;;13927:47:1;;13921:3;13906:19;;13899:76;14012:3;13668;13991:19;;13984:32;;;13389:697;;14033:47;;14060:19;;14052:6;14033:47;:::i;:::-;14025:55;13640:446;-1:-1:-1;;;;;;;;13640:446:1:o;14091:375::-;-1:-1:-1;;;;;14349:15:1;;;14331:34;;14401:15;;;;14396:2;14381:18;;14374:43;14448:2;14433:18;;14426:34;;;;14281:2;14266:18;;14248:218::o;14471:582::-;-1:-1:-1;;;;;14740:32:1;;;;14722:51;;14820:1;14809:21;;;14804:2;14789:18;;14782:49;14867:21;;;;14862:2;14847:18;;14840:49;-1:-1:-1;;;;;14978:15:1;;;14973:2;14958:18;;14951:43;15031:15;15025:3;15010:19;;15003:44;14709:3;14694:19;;14676:377::o;15058:274::-;-1:-1:-1;;;;;15250:32:1;;;;15232:51;;15314:2;15299:18;;15292:34;15220:2;15205:18;;15187:145::o;15337:187::-;15502:14;;15495:22;15477:41;;15465:2;15450:18;;15432:92::o;15529:177::-;15675:25;;;15663:2;15648:18;;15630:76::o;15711:591::-;15998:25;;;-1:-1:-1;;;;;16097:15:1;;;16092:2;16077:18;;16070:43;16149:15;;;;16144:2;16129:18;;16122:43;16196:2;16181:18;;16174:34;16239:3;16224:19;;16217:35;;;;16050:3;16268:19;;16261:35;15985:3;15970:19;;15952:350::o;16307:489::-;16566:25;;;16622:2;16607:18;;16600:34;;;;16665:2;16650:18;;16643:34;;;;16708:2;16693:18;;16686:34;-1:-1:-1;;;;;16757:32:1;16751:3;16736:19;;16729:61;16553:3;16538:19;;16520:276::o;16801:398::-;17028:25;;;17101:4;17089:17;;;;17084:2;17069:18;;17062:45;17138:2;17123:18;;17116:34;17181:2;17166:18;;17159:34;17015:3;17000:19;;16982:217::o;17655:188::-;17826:1;17815:21;;;;17797:40;;17785:2;17770:18;;17752:91::o;17848:390::-;18079:1;18068:21;;;18050:40;;18126:21;;;;18121:2;18106:18;;18099:49;-1:-1:-1;;;;;18184:47:1;;;18179:2;18164:18;;18157:75;18038:2;18023:18;;18005:233::o;18630:546::-;18942:1;18931:21;;;;18913:40;;18984:2;18969:18;;18962:34;;;;19027:2;19012:18;;19005:34;;;;19070:2;19055:18;;19048:34;19113:3;19098:19;;19091:35;19157:3;19142:19;;19135:35;18900:3;18885:19;;18867:309::o;19181:221::-;;19330:2;19319:9;19312:21;19350:46;19392:2;19381:9;19377:18;19369:6;19350:46;:::i;19407:348::-;19609:2;19591:21;;;19648:2;19628:18;;;19621:30;19687:26;19682:2;19667:18;;19660:54;19746:2;19731:18;;19581:174::o;19760:399::-;19962:2;19944:21;;;20001:2;19981:18;;;19974:30;20040:34;20035:2;20020:18;;20013:62;-1:-1:-1;;;20106:2:1;20091:18;;20084:33;20149:3;20134:19;;19934:225::o;20164:325::-;20366:2;20348:21;;;20405:1;20385:18;;;20378:29;-1:-1:-1;;;20438:2:1;20423:18;;20416:32;20480:2;20465:18;;20338:151::o;20494:398::-;20696:2;20678:21;;;20735:2;20715:18;;;20708:30;20774:34;20769:2;20754:18;;20747:62;-1:-1:-1;;;20840:2:1;20825:18;;20818:32;20882:3;20867:19;;20668:224::o;20897:351::-;21099:2;21081:21;;;21138:2;21118:18;;;21111:30;21177:29;21172:2;21157:18;;21150:57;21239:2;21224:18;;21071:177::o;21253:326::-;21455:2;21437:21;;;21494:1;21474:18;;;21467:29;-1:-1:-1;;;21527:2:1;21512:18;;21505:33;21570:2;21555:18;;21427:152::o;21584:353::-;21786:2;21768:21;;;21825:2;21805:18;;;21798:30;21864:31;21859:2;21844:18;;21837:59;21928:2;21913:18;;21758:179::o;21942:354::-;22144:2;22126:21;;;22183:2;22163:18;;;22156:30;22222:32;22217:2;22202:18;;22195:60;22287:2;22272:18;;22116:180::o;22301:398::-;22503:2;22485:21;;;22542:2;22522:18;;;22515:30;22581:34;22576:2;22561:18;;22554:62;-1:-1:-1;;;22647:2:1;22632:18;;22625:32;22689:3;22674:19;;22475:224::o;22704:402::-;22906:2;22888:21;;;22945:2;22925:18;;;22918:30;22984:34;22979:2;22964:18;;22957:62;-1:-1:-1;;;23050:2:1;23035:18;;23028:36;23096:3;23081:19;;22878:228::o;23111:350::-;23313:2;23295:21;;;23352:2;23332:18;;;23325:30;23391:28;23386:2;23371:18;;23364:56;23452:2;23437:18;;23285:176::o;23466:324::-;23668:2;23650:21;;;23707:1;23687:18;;;23680:29;-1:-1:-1;;;23740:2:1;23725:18;;23718:31;23781:2;23766:18;;23640:150::o;23795:398::-;23997:2;23979:21;;;24036:2;24016:18;;;24009:30;24075:34;24070:2;24055:18;;24048:62;-1:-1:-1;;;24141:2:1;24126:18;;24119:32;24183:3;24168:19;;23969:224::o;24198:397::-;24400:2;24382:21;;;24439:2;24419:18;;;24412:30;24478:34;24473:2;24458:18;;24451:62;-1:-1:-1;;;24544:2:1;24529:18;;24522:31;24585:3;24570:19;;24372:223::o;24600:354::-;24802:2;24784:21;;;24841:2;24821:18;;;24814:30;24880:32;24875:2;24860:18;;24853:60;24945:2;24930:18;;24774:180::o;24959:326::-;25161:2;25143:21;;;25200:1;25180:18;;;25173:29;-1:-1:-1;;;25233:2:1;25218:18;;25211:33;25276:2;25261:18;;25133:152::o;25290:334::-;25492:2;25474:21;;;25531:2;25511:18;;;25504:30;-1:-1:-1;;;25565:2:1;25550:18;;25543:40;25615:2;25600:18;;25464:160::o;25629:329::-;25831:2;25813:21;;;25870:1;25850:18;;;25843:29;-1:-1:-1;;;25903:2:1;25888:18;;25881:36;25949:2;25934:18;;25803:155::o;25963:397::-;26165:2;26147:21;;;26204:2;26184:18;;;26177:30;26243:34;26238:2;26223:18;;26216:62;-1:-1:-1;;;26309:2:1;26294:18;;26287:31;26350:3;26335:19;;26137:223::o;26365:326::-;26567:2;26549:21;;;26606:1;26586:18;;;26579:29;-1:-1:-1;;;26639:2:1;26624:18;;26617:33;26682:2;26667:18;;26539:152::o;26696:401::-;26898:2;26880:21;;;26937:2;26917:18;;;26910:30;26976:34;26971:2;26956:18;;26949:62;-1:-1:-1;;;27042:2:1;27027:18;;27020:35;27087:3;27072:19;;26870:227::o;27102:326::-;27304:2;27286:21;;;27343:1;27323:18;;;27316:29;-1:-1:-1;;;27376:2:1;27361:18;;27354:33;27419:2;27404:18;;27276:152::o;27433:400::-;27635:2;27617:21;;;27674:2;27654:18;;;27647:30;27713:34;27708:2;27693:18;;27686:62;-1:-1:-1;;;27779:2:1;27764:18;;27757:34;27823:3;27808:19;;27607:226::o;27838:353::-;28040:2;28022:21;;;28079:2;28059:18;;;28052:30;28118:31;28113:2;28098:18;;28091:59;28182:2;28167:18;;28012:179::o;28196:406::-;28398:2;28380:21;;;28437:2;28417:18;;;28410:30;28476:34;28471:2;28456:18;;28449:62;-1:-1:-1;;;28542:2:1;28527:18;;28520:40;28592:3;28577:19;;28370:232::o;28607:355::-;28809:2;28791:21;;;28848:2;28828:18;;;28821:30;28887:33;28882:2;28867:18;;28860:61;28953:2;28938:18;;28781:181::o;28967:355::-;29169:2;29151:21;;;29208:2;29188:18;;;29181:30;29247:33;29242:2;29227:18;;29220:61;29313:2;29298:18;;29141:181::o;29327:480::-;-1:-1:-1;;;;;29629:15:1;;;29611:34;;29681:15;;;29676:2;29661:18;;29654:43;29733:15;;;29728:2;29713:18;;29706:43;29785:15;;;29780:2;29765:18;;29758:43;29545:3;29530:19;;29512:295::o;29812:360::-;-1:-1:-1;;;;;30032:47:1;;;;30014:66;;30111:2;30096:18;;30089:34;;;;30154:2;30139:18;;30132:34;30002:2;29987:18;;29969:203::o;30359:248::-;30533:25;;;30589:2;30574:18;;30567:34;30521:2;30506:18;;30488:119::o;30612:319::-;30814:25;;;30870:2;30855:18;;30848:34;;;;30913:2;30898:18;;30891:34;30802:2;30787:18;;30769:162::o;30936:184::-;31108:4;31096:17;;;;31078:36;;31066:2;31051:18;;31033:87::o;31125:326::-;31353:4;31341:17;;;;31323:36;;31390:2;31375:18;;31368:34;;;;31433:2;31418:18;;31411:34;31311:2;31296:18;;31278:173::o;31456:258::-;31528:1;31538:113;31552:6;31549:1;31546:13;31538:113;;;31628:11;;;31622:18;31609:11;;;31602:39;31574:2;31567:10;31538:113;;;31669:6;31666:1;31663:13;31660:2;;;-1:-1:-1;;31704:1:1;31686:16;;31679:27;31509:205::o;31719:133::-;-1:-1:-1;;;;;31796:31:1;;31786:42;;31776:2;;31842:1;31839;31832:12;31776:2;31766:86;:::o;31857:120::-;31946:5;31943:1;31932:20;31925:5;31922:31;31912:2;;31967:1;31964;31957:12;31982:148;-1:-1:-1;;;;;32063:5:1;32059:46;32052:5;32049:57;32039:2;;32120:1;32117;32110:12;32135:116;32221:4;32214:5;32210:16;32203:5;32200:27;32190:2;;32241:1;32238;32231:12

Swarm Source

ipfs://f940bb264bc082a145ef6482d9ea4b8dfde70bdab78aa145c9422d379a4c17ec
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.