ETH Price: $2,474.02 (+0.79%)
 

Overview

TokenID

1080

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

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

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
StakedQLT

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-02-15
*/

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

// File contracts/libraries/Ownable.sol

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(msg.sender);
    }

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

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

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

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}


// File contracts/interfaces/IERC721.sol

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator)
        external
        view
        returns (bool);
}


// File contracts/libraries/Strings.sol

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length)
        internal
        pure
        returns (string memory)
    {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}


// File contracts/libraries/ERC721.sol

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is IERC721 {
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Base URI
    string private _baseURI;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        string memory baseURI_
    ) {
        _name = name_;
        _symbol = symbol_;
        _baseURI = baseURI_;
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            owner != address(0),
            "ERC721: balance query for the zero address"
        );
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        address owner = _owners[tokenId];
        require(
            owner != address(0),
            "ERC721: owner query for nonexistent token"
        );
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

        string memory baseURI = _baseURI;
        return
            bytes(baseURI).length > 0
                ? string(abi.encodePacked(baseURI, tokenId.toString()))
                : "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        require(
            _exists(tokenId),
            "ERC721: approved query for nonexistent token"
        );

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override
    {
        _setApprovalForAll(msg.sender, operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(
            _isApprovedOrOwner(msg.sender, tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );

        _transfer(from, to, tokenId);
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId)
        internal
        view
        virtual
        returns (bool)
    {
        require(
            _exists(tokenId),
            "ERC721: operator query for nonexistent token"
        );
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner ||
            getApproved(tokenId) == spender ||
            isApprovedForAll(owner, spender));
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(
            ERC721.ownerOf(tokenId) == from,
            "ERC721: transfer from incorrect owner"
        );
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` 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 tokenId
    ) internal virtual {}
}


// File contracts/interfaces/IERC721Enumerable.sol

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        external
        view
        returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}


// File contracts/libraries/ERC721Enumerable.sol

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            index < ERC721.balanceOf(owner),
            "ERC721Enumerable: owner index out of bounds"
        );
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index)
        public
        view
        virtual
        override
        returns (uint256)
    {
        require(
            index < ERC721Enumerable.totalSupply(),
            "ERC721Enumerable: global index out of bounds"
        );
        return _allTokens[index];
    }

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

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId)
        private
    {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}


// File contracts/libraries/Math.sol

library Math {
    function compound(uint256 rewardRateX96, uint256 nCompounds)
        internal
        pure
        returns (uint256 compoundedX96)
    {
        if (nCompounds == 0) {
            compoundedX96 = 2**96;
        } else if (nCompounds == 1) {
            compoundedX96 = rewardRateX96;
        } else {
            compoundedX96 = compound(rewardRateX96, nCompounds / 2);
            compoundedX96 = mulX96(compoundedX96, compoundedX96);

            if (nCompounds % 2 == 1) {
                compoundedX96 = mulX96(compoundedX96, rewardRateX96);
            }
        }
    }

    // ref: https://blogs.sas.com/content/iml/2016/05/16/babylonian-square-roots.html
    function sqrt(uint256 x) internal pure returns (uint256 y) {
        uint256 z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }

    function mulX96(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = (x * y) >> 96;
    }

    function divX96(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = (x << 96) / y;
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
}


// File contracts/libraries/Time.sol

library Time {
    function current_hour_timestamp() internal view returns (uint64) {
        return uint64((block.timestamp / 1 hours) * 1 hours);
    }

    function block_timestamp() internal view returns (uint64) {
        return uint64(block.timestamp);
    }
}


// File contracts/interfaces/IUniswapV3Factory.sol

/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees
interface IUniswapV3Factory {
    /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
    /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @return pool The pool address
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external view returns (address pool);

    /// @notice Creates a pool for the given two tokens and fee
    /// @param tokenA One of the two tokens in the desired pool
    /// @param tokenB The other of the two tokens in the desired pool
    /// @param fee The desired fee for the pool
    /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
    /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
    /// are invalid.
    /// @return pool The address of the newly created pool
    function createPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external returns (address pool);
}


// File contracts/interfaces/IUniswapV3Pool.sol

interface IUniswapV3Pool {
    /// @notice Sets the initial price for the pool
    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value
    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96
    function initialize(uint160 sqrtPriceX96) external;

    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
    /// when accessed externally.
    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.
    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
    /// boundary.
    /// observationIndex The index of the last oracle observation that was written,
    /// observationCardinality The current maximum number of observations stored in the pool,
    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.
    /// feeProtocol The protocol fee for both tokens of the pool.
    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
    /// unlocked Whether the pool is currently locked to reentrancy
    function slot0()
        external
        view
        returns (
            uint160 sqrtPriceX96,
            int24 tick,
            uint16 observationIndex,
            uint16 observationCardinality,
            uint16 observationCardinalityNext,
            uint8 feeProtocol,
            bool unlocked
        );

    /// @notice Increase the maximum number of price and liquidity observations that this pool will store
    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to
    /// the input observationCardinalityNext.
    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store
    function increaseObservationCardinalityNext(
        uint16 observationCardinalityNext
    ) external;

    /// @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 secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block
    /// timestamp
    function observe(uint32[] calldata secondsAgos)
        external
        view
        returns (
            int56[] memory tickCumulatives,
            uint160[] memory secondsPerLiquidityCumulativeX128s
        );
}


// File contracts/interfaces/IERC20.sol

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}


// File contracts/libraries/ERC20.sol

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead 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 IERC20 {
    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}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        uint8 decimals_
    ) {
        _name = name_;
        _symbol = symbol_;
        _decimals = decimals_;
    }

    /**
     * @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 this function is
     * overridden;
     *
     * 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(msg.sender, 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}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount)
        public
        virtual
        override
        returns (bool)
    {
        _approve(msg.sender, 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}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * 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) {
        uint256 currentAllowance = _allowances[sender][msg.sender];
        if (currentAllowance != type(uint256).max) {
            require(
                currentAllowance >= amount,
                "ERC20: transfer amount exceeds allowance"
            );
            unchecked {
                _approve(sender, msg.sender, currentAllowance - amount);
            }
        }

        _transfer(sender, recipient, amount);

        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(
            msg.sender,
            spender,
            _allowances[msg.sender][spender] + 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)
    {
        uint256 currentAllowance = _allowances[msg.sender][spender];
        require(
            currentAllowance >= subtractedValue,
            "ERC20: decreased allowance below zero"
        );
        unchecked {
            _approve(msg.sender, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This 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);

        uint256 senderBalance = _balances[sender];
        require(
            senderBalance >= amount,
            "ERC20: transfer amount exceeds balance"
        );
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(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:
     *
     * - `account` 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 += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(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);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(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 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 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 {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


// File contracts/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
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 sqrtPriceX96 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 sqrtPriceX96)
    {
        uint256 absTick = tick < 0
            ? uint256(-int256(tick))
            : uint256(int256(tick));
        require(absTick <= uint256(int256(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
        sqrtPriceX96 = uint160(
            (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)
        );
    }

    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
    /// ever return.
    /// @param sqrtPriceX96 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 sqrtPriceX96)
        internal
        pure
        returns (int24 tick)
    {
        // second inequality must be < because the price can never reach the price at the max tick
        require(
            sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO,
            "R"
        );
        uint256 ratio = uint256(sqrtPriceX96) << 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) <= sqrtPriceX96
            ? tickHi
            : tickLow;
    }
}


// File contracts/Const.sol

int24 constant INITIAL_QLT_PRICE_TICK = -23000; // QLT_USDC price ~ 100.0

// initial values
uint24 constant UNISWAP_POOL_FEE = 10000;
int24 constant UNISWAP_POOL_TICK_SPACING = 200;
uint16 constant UNISWAP_POOL_OBSERVATION_CADINALITY = 64;

// default values
uint256 constant DEFAULT_MIN_MINT_PRICE_X96 = 100 * Q96;
uint32 constant DEFAULT_TWAP_DURATION = 1 hours;
uint32 constant DEFAULT_UNSTAKE_LOCKUP_PERIOD = 3 days;

// floating point math
uint256 constant Q96 = 2**96;
uint256 constant MX96 = Q96 / 10**6;
uint256 constant TX96 = Q96 / 10**12;

// ERC-20 contract addresses
address constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address constant USDC = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
address constant USDT = address(0xdAC17F958D2ee523a2206206994597C13D831ec7);
address constant DAI = address(0x6B175474E89094C44Da98b954EedeAC495271d0F);
address constant BUSD = address(0x4Fabb145d64652a948d72533023f6E7A623C7C53);
address constant FRAX = address(0x853d955aCEf822Db058eb8505911ED77F175b99e);
address constant WBTC = address(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);

// Uniswap, see `https://docs.uniswap.org/protocol/reference/deployments`
address constant UNISWAP_FACTORY = address(
    0x1F98431c8aD98523631AE4a59f267346ea31F984
);
address constant UNISWAP_ROUTER = address(
    0xE592427A0AEce92De3Edee1F18E0157C05861564
);
address constant UNISWAP_NFP_MGR = address(
    0xC36442b4a4522E871399CD717aBDD847Ab11FE88
);


// File contracts/QLT.sol

contract QLT is ERC20, Ownable {
    event Mint(address indexed account, uint256 amount);
    event Burn(uint256 amount);

    mapping(address => bool) public authorizedMinters;

    constructor() ERC20("Quantland", "QLT", 9) {
        require(
            address(this) < USDC,
            "QLT contract address must be smaller than USDC token contract address"
        );
        authorizedMinters[msg.sender] = true;

        // deploy uniswap pool
        IUniswapV3Pool pool = IUniswapV3Pool(
            IUniswapV3Factory(UNISWAP_FACTORY).createPool(
                address(this),
                USDC,
                UNISWAP_POOL_FEE
            )
        );
        pool.initialize(TickMath.getSqrtRatioAtTick(INITIAL_QLT_PRICE_TICK));
        pool.increaseObservationCardinalityNext(
            UNISWAP_POOL_OBSERVATION_CADINALITY
        );
    }

    function mint(address account, uint256 amount)
        external
        onlyAuthorizedMinter
    {
        _mint(account, amount);

        emit Mint(account, amount);
    }

    function burn(uint256 amount) external onlyOwner {
        _burn(msg.sender, amount);

        emit Burn(amount);
    }

    /* Access Control */
    modifier onlyAuthorizedMinter() {
        require(authorizedMinters[msg.sender], "not authorized minter");
        _;
    }

    function addAuthorizedMinter(address account) external onlyOwner {
        authorizedMinters[account] = true;
    }

    function removeAuthorizedMinter(address account) external onlyOwner {
        authorizedMinters[account] = false;
    }
}


// File contracts/StakedQLT.sol

struct StakingInfo {
    bytes32 stakingPlan;
    uint256 stakedAmount;
    uint64 stakeTime;
    uint64 unstakeTime;
    uint64 redeemTime;
    uint64 lastHarvestTime;
    uint256 accumulatedStakingReward;
}

struct StakingRewardRate {
    uint256 rewardRateX96;
    uint64 startTime;
}

struct StakingPowerMultiplier {
    uint64 multiplier;
    uint64 startTime;
}

struct StakingPlan {
    bytes32 name;
    uint256 stakingAmount;
    uint256 accumulatedStakingReward;
    StakingRewardRate[] rewardRates;
    StakingPowerMultiplier[] multipliers;
    uint64 lockupPeriod;
    uint64 createdAt;
    uint64 deactivatedAt;
}

contract StakedQLT is ERC721Enumerable, Ownable {
    using Math for uint256;

    event Stake(
        uint256 indexed tokenId,
        address staker,
        bytes32 stakingPlan,
        uint256 amount
    );
    event Unstake(uint256 indexed tokenId);
    event Redeem(uint256 indexed tokenId, uint256 amount);
    event Harvest(uint256 indexed tokenId, uint256 rewardAmount);
    event HarvestAll(uint256[] tokenIds, uint256 rewardAmount);
    event StakingPlanCreated(bytes32 name);
    event StakingPlanDeactivated(bytes32 name);
    event StakingRewardRateUpdated(bytes32 name, uint256 rewardRateX96);
    event StakingPowerMultiplierUpdated(bytes32 name, uint256 multiplier);

    QLT private immutable QLTContract;

    uint256 public tokenIdCounter;
    uint64 public harvestStartTime;
    uint64 public unstakeLockupPeriod;

    uint256 public totalStakingAmount;
    address public treasuryAddress;
    mapping(uint256 => StakingInfo) public stakingInfos;
    mapping(bytes32 => StakingPlan) public stakingPlans;

    mapping(address => bool) public authorizedOperators;

    constructor(address _QLTContract)
        ERC721("Staked QLT", "sQLT", "https://staked.quantland.finance/")
    {
        addAuthorizedOperator(msg.sender);
        harvestStartTime = type(uint64).max;
        unstakeLockupPeriod = DEFAULT_UNSTAKE_LOCKUP_PERIOD;

        addStakingPlan("gold", 7 days, (100040 * Q96) / 100000, 1); // APY 3,222 %
        addStakingPlan("platinum", 30 days, (100060 * Q96) / 100000, 3); // APY 19,041 %
        addStakingPlan("diamond", 90 days, (100080 * Q96) / 100000, 5); // APY 110,200 %

        QLTContract = QLT(_QLTContract);
    }

    /* Staking Plan Governance Functions */
    function addStakingPlan(
        bytes32 name,
        uint64 lockupPeriod,
        uint256 rewardRateX96,
        uint64 multiplier
    ) public onlyOwner {
        require(stakingPlans[name].createdAt == 0, "already created");
        StakingPlan storage stakingPlan = stakingPlans[name];
        stakingPlan.name = name;
        stakingPlan.rewardRates.push(
            StakingRewardRate({
                rewardRateX96: rewardRateX96,
                startTime: Time.current_hour_timestamp()
            })
        );
        stakingPlan.multipliers.push(
            StakingPowerMultiplier({
                multiplier: multiplier,
                startTime: Time.block_timestamp()
            })
        );
        stakingPlan.lockupPeriod = lockupPeriod;
        stakingPlan.createdAt = Time.block_timestamp();

        emit StakingPlanCreated(name);
    }

    function deactivateStakingPlan(bytes32 name) public onlyOwner {
        _checkStakingPlanActive(name);

        StakingPlan storage stakingPlan = stakingPlans[name];
        stakingPlan.deactivatedAt = Time.block_timestamp();

        emit StakingPlanDeactivated(name);
    }

    function updateStakingRewardRate(bytes32 name, uint256 rewardRateX96)
        public
        onlyOperator
    {
        _checkStakingPlanActive(name);

        StakingPlan storage stakingPlan = stakingPlans[name];
        stakingPlan.rewardRates.push(
            StakingRewardRate({
                rewardRateX96: rewardRateX96,
                startTime: Time.current_hour_timestamp()
            })
        );

        emit StakingRewardRateUpdated(name, rewardRateX96);
    }

    function updateStakingPowerMultiplier(bytes32 name, uint64 multiplier)
        public
        onlyOperator
    {
        _checkStakingPlanActive(name);

        StakingPlan storage stakingPlan = stakingPlans[name];
        stakingPlan.multipliers.push(
            StakingPowerMultiplier({
                multiplier: multiplier,
                startTime: Time.block_timestamp()
            })
        );

        emit StakingPowerMultiplierUpdated(name, multiplier);
    }

    /* Staking-Related Functions */
    function stake(
        address recipient,
        bytes32 stakingPlan,
        uint256 amount
    ) external returns (uint256 tokenId) {
        require(amount > 0, "amount is 0");
        _checkStakingPlanActive(stakingPlan);

        // transfer QLT
        QLTContract.transferFrom(msg.sender, address(this), amount);

        // mint
        tokenIdCounter += 1;
        tokenId = tokenIdCounter;
        _mint(recipient, tokenId);
        _approve(address(this), tokenId);

        // update staking info
        StakingInfo storage stakingInfo = stakingInfos[tokenId];
        stakingInfo.stakingPlan = stakingPlan;
        stakingInfo.stakedAmount = amount;
        stakingInfo.stakeTime = Time.block_timestamp();
        stakingInfo.lastHarvestTime = Time.current_hour_timestamp();

        // update staking plan info
        stakingPlans[stakingPlan].stakingAmount += amount;
        totalStakingAmount += amount;

        emit Stake(tokenId, recipient, stakingPlan, amount);
    }

    function unstake(uint256 tokenId) external returns (uint256 rewardAmount) {
        _checkOwnershipOfStakingToken(tokenId);

        StakingInfo storage stakingInfo = stakingInfos[tokenId];
        uint64 lockupPeriod = stakingPlans[stakingInfo.stakingPlan]
            .lockupPeriod;
        uint64 stakeTime = stakingInfo.stakeTime;
        uint64 unstakeTime = stakingInfo.unstakeTime;

        if (msg.sender == treasuryAddress) {
            lockupPeriod = 0;
        }

        require(unstakeTime == 0, "already unstaked");
        require(
            Time.block_timestamp() >= (stakeTime + lockupPeriod),
            "still in lockup"
        );

        // harvest first
        rewardAmount = harvestInternal(tokenId);

        // update staking info
        uint256 unstakedAmount = stakingInfo.stakedAmount;
        stakingInfo.unstakeTime = Time.block_timestamp();

        // update staking plan info
        stakingPlans[stakingInfo.stakingPlan].stakingAmount -= unstakedAmount;
        totalStakingAmount -= unstakedAmount;

        emit Unstake(tokenId);
    }

    function redeem(uint256 tokenId) external returns (uint256 redeemedAmount) {
        _checkOwnershipOfStakingToken(tokenId);

        StakingInfo storage stakingInfo = stakingInfos[tokenId];
        uint64 unstakeTime = stakingInfo.unstakeTime;
        uint64 redeemTime = stakingInfo.redeemTime;
        uint64 _unstakeLockupPeriod = unstakeLockupPeriod;

        if (msg.sender == treasuryAddress) {
            _unstakeLockupPeriod = 0;
        }

        // check if can unstake
        require(unstakeTime > 0, "not unstaked");
        require(
            Time.block_timestamp() >= (unstakeTime + _unstakeLockupPeriod),
            "still in lockup"
        );
        require(redeemTime == 0, "already redeemed");

        // recycle and burn staking NFT
        address staker = ownerOf(tokenId);
        transferFrom(msg.sender, address(this), tokenId);
        _burn(tokenId);

        // transfer QLT back to staker
        redeemedAmount = stakingInfo.stakedAmount;
        QLTContract.transfer(staker, redeemedAmount);

        // update staking info
        stakingInfo.redeemTime = Time.block_timestamp();

        emit Redeem(tokenId, redeemedAmount);
    }

    function harvest(uint256 tokenId) external returns (uint256 rewardAmount) {
        return harvestInternal(tokenId);
    }

    function harvestAll(uint256[] calldata tokenIds)
        external
        returns (uint256 rewardAmount)
    {
        for (uint256 i = 0; i < tokenIds.length; i++) {
            rewardAmount += harvestInternal(tokenIds[i]);
        }

        emit HarvestAll(tokenIds, rewardAmount);
    }

    function harvestInternal(uint256 tokenId)
        internal
        returns (uint256 rewardAmount)
    {
        require(Time.block_timestamp() >= harvestStartTime, "come back later");
        _checkOwnershipOfStakingToken(tokenId);

        rewardAmount = getRewardsToHarvest(tokenId);

        if (rewardAmount > 0) {
            // mint QLT to recipient
            QLTContract.mint(ownerOf(tokenId), rewardAmount);

            // update staking info
            StakingInfo storage stakingInfo = stakingInfos[tokenId];
            stakingInfo.lastHarvestTime = Time.current_hour_timestamp();
            stakingInfo.accumulatedStakingReward += rewardAmount;

            // update staking plan info
            StakingPlan storage stakingPlan = stakingPlans[
                stakingInfo.stakingPlan
            ];
            stakingPlan.accumulatedStakingReward += rewardAmount;

            emit Harvest(tokenId, rewardAmount);
        }
    }

    /* Staking State View Functions */
    function getRewardsToHarvest(uint256 tokenId)
        public
        view
        returns (uint256 rewardAmount)
    {
        require(tokenId <= tokenIdCounter, "not existent");

        StakingInfo storage stakingInfo = stakingInfos[tokenId];

        if (stakingInfo.unstakeTime > 0) {
            return 0;
        }

        StakingPlan storage stakingPlan = stakingPlans[stakingInfo.stakingPlan];

        // calculate compounded rewards of QLT
        uint256 stakedAmountX96 = stakingInfo.stakedAmount * Q96;
        uint256 compoundedAmountX96 = stakedAmountX96;
        uint64 rewardEndTime = Time.current_hour_timestamp();
        uint64 lastHarvestTime = stakingInfo.lastHarvestTime;

        StakingRewardRate[] storage rewardRates = stakingPlan.rewardRates;
        uint256 i = rewardRates.length;
        while (i > 0) {
            i--;

            uint64 rewardStartTime = rewardRates[i].startTime;
            uint256 rewardRateX96 = rewardRates[i].rewardRateX96;
            uint256 nCompounds;

            if (rewardEndTime < rewardStartTime) {
                continue;
            }

            if (rewardStartTime >= lastHarvestTime) {
                nCompounds = (rewardEndTime - rewardStartTime) / 1 hours;
                compoundedAmountX96 = compoundedAmountX96.mulX96(
                    Math.compound(rewardRateX96, nCompounds)
                );
                rewardEndTime = rewardStartTime;
            } else {
                nCompounds = (rewardEndTime - lastHarvestTime) / 1 hours;
                compoundedAmountX96 = compoundedAmountX96.mulX96(
                    Math.compound(rewardRateX96, nCompounds)
                );
                break;
            }
        }

        rewardAmount = (compoundedAmountX96 - stakedAmountX96) / Q96;
    }

    function getAllRewardsToHarvest(uint256[] calldata tokenIds)
        public
        view
        returns (uint256 rewardAmount)
    {
        for (uint256 i = 0; i < tokenIds.length; i++) {
            rewardAmount += getRewardsToHarvest(tokenIds[i]);
        }
    }

    function getStakingPower(
        uint256 tokenId,
        uint64 startTime,
        uint64 endTime
    ) public view returns (uint256 stakingPower) {
        require(tokenId <= tokenIdCounter, "not existent");

        StakingInfo storage stakingInfo = stakingInfos[tokenId];
        if (stakingInfo.stakeTime >= endTime || stakingInfo.unstakeTime > 0) {
            return 0;
        }
        if (stakingInfo.stakeTime > startTime) {
            startTime = stakingInfo.stakeTime;
        }

        StakingPlan storage stakingPlan = stakingPlans[stakingInfo.stakingPlan];
        uint256 stakedAmount = stakingInfo.stakedAmount;
        StakingPowerMultiplier[] storage multipliers = stakingPlan.multipliers;
        uint256 i = multipliers.length;
        while (i > 0) {
            i--;

            uint64 rewardStartTime = multipliers[i].startTime;
            uint256 multiplier = multipliers[i].multiplier;

            if (rewardStartTime >= endTime) {
                continue;
            }

            if (rewardStartTime >= startTime) {
                stakingPower +=
                    stakedAmount *
                    (endTime - rewardStartTime) *
                    multiplier;
                endTime = rewardStartTime;
            } else {
                stakingPower +=
                    stakedAmount *
                    (endTime - startTime) *
                    multiplier;
                break;
            }
        }
    }

    function getAllStakingPower(
        uint256[] calldata tokenIds,
        uint64 startTime,
        uint64 endTime
    ) public view returns (uint256 stakingPower) {
        for (uint256 i = 0; i < tokenIds.length; i++) {
            stakingPower += getStakingPower(tokenIds[i], startTime, endTime);
        }
    }

    /* Config Setters */
    function setHarvestStartTime(uint64 _harvestStartTime) external onlyOwner {
        harvestStartTime = _harvestStartTime;
    }

    function setUnstakeLockupPeriod(uint64 _unstakeLockupPeriod)
        external
        onlyOwner
    {
        unstakeLockupPeriod = _unstakeLockupPeriod;
    }

    function setTreasuryAddress(address _treasuryAddress) external onlyOwner {
        treasuryAddress = _treasuryAddress;
    }

    /* Helper Functions */
    function _checkOwnershipOfStakingToken(uint256 tokenId) internal view {
        require(ownerOf(tokenId) == msg.sender, "not owner");
    }

    function _checkStakingPlanActive(bytes32 stakingPlan) internal view {
        require(
            stakingPlans[stakingPlan].deactivatedAt == 0,
            "staking plan not active"
        );
    }

    /* Access Control */
    function addAuthorizedOperator(address account) public onlyOwner {
        authorizedOperators[account] = true;
    }

    function removeAuthorizedOperator(address account) external onlyOwner {
        authorizedOperators[account] = false;
    }

    modifier onlyOperator() {
        require(authorizedOperators[msg.sender], "not authorized");
        _;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_QLTContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"HarvestAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stakingPlan","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"StakingPlanCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"StakingPlanDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"StakingPowerMultiplierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rewardRateX96","type":"uint256"}],"name":"StakingRewardRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAuthorizedOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint64","name":"lockupPeriod","type":"uint64"},{"internalType":"uint256","name":"rewardRateX96","type":"uint256"},{"internalType":"uint64","name":"multiplier","type":"uint64"}],"name":"addStakingPlan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedOperators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"deactivateStakingPlan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getAllRewardsToHarvest","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"}],"name":"getAllStakingPower","outputs":[{"internalType":"uint256","name":"stakingPower","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getRewardsToHarvest","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"}],"name":"getStakingPower","outputs":[{"internalType":"uint256","name":"stakingPower","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"harvest","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"harvestAll","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestStartTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"redeemedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAuthorizedOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_harvestStartTime","type":"uint64"}],"name":"setHarvestStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasuryAddress","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_unstakeLockupPeriod","type":"uint64"}],"name":"setUnstakeLockupPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes32","name":"stakingPlan","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingInfos","outputs":[{"internalType":"bytes32","name":"stakingPlan","type":"bytes32"},{"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"internalType":"uint64","name":"stakeTime","type":"uint64"},{"internalType":"uint64","name":"unstakeTime","type":"uint64"},{"internalType":"uint64","name":"redeemTime","type":"uint64"},{"internalType":"uint64","name":"lastHarvestTime","type":"uint64"},{"internalType":"uint256","name":"accumulatedStakingReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"stakingPlans","outputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"stakingAmount","type":"uint256"},{"internalType":"uint256","name":"accumulatedStakingReward","type":"uint256"},{"internalType":"uint64","name":"lockupPeriod","type":"uint64"},{"internalType":"uint64","name":"createdAt","type":"uint64"},{"internalType":"uint64","name":"deactivatedAt","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenIdCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstake","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeLockupPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint64","name":"multiplier","type":"uint64"}],"name":"updateStakingPowerMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"rewardRateX96","type":"uint256"}],"name":"updateStakingRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b50604051620039fa380380620039fa8339810160408190526200003491620005f3565b6040518060400160405280600a81526020016914dd185ad9590814531560b21b815250604051806040016040528060048152602001631cd4531560e21b815250604051806060016040528060218152602001620039b9602191398251620000a39060009060208601906200054d565b508151620000b99060019060208501906200054d565b508051620000cf9060029060208401906200054d565b50505050620000e433620001ef60201b60201c565b620000ef3362000241565b600d80546001600160801b03191660016203f48160401b031790556200014e6319dbdb1960e21b62093a80620186a06200013a6c01000000000000000000000000620186c862000625565b62000146919062000653565b6001620002c4565b6200019667706c6174696e756d60c01b62278d00620186a0620001826c01000000000000000000000000620186dc62000625565b6200018e919062000653565b6003620002c4565b620001dd66191a585b5bdb9960ca1b6276a700620186a0620001c96c01000000000000000000000000620186f062000625565b620001d5919062000653565b6005620002c4565b6001600160a01b0316608052620006b3565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b3362000255600b546001600160a01b031690565b6001600160a01b031614620002a05760405162461bcd60e51b81526020600482018190526024820152600080516020620039da83398151915260448201526064015b60405180910390fd5b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b33620002d8600b546001600160a01b031690565b6001600160a01b0316146200031f5760405162461bcd60e51b81526020600482018190526024820152600080516020620039da833981519152604482015260640162000297565b6000848152601160205260409020600501546801000000000000000090046001600160401b031615620003875760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818dc99585d1959608a1b604482015260640162000297565b600084815260116020908152604091829020868155825180840190935284835291600383019181810190620003c5906200201e62000526821b17901c565b6001600160401b039081169091528254600180820185556000948552602094859020845160029093020191825592840151920180546001600160401b031916928216929092179091556040805180820190915290841681526004830191818101906200043a9062000549811b6200203d17901c565b6001600160401b0390811690915282546001810184556000938452602093849020835191018054938501519183166001600160801b0319909416939093176801000000000000000091831691909102179091556005830180546001600160401b031916918716919091179055620004ba9062000549811b6200203d17901c565b6005820180546001600160401b03929092166801000000000000000002600160401b600160801b03199092169190911790556040518581527f6b70138d2b1ac6c6c366b880fd69a916ea592a176331c95355ed15efccbd3f369060200160405180910390a15050505050565b600062000536610e104262000653565b6200054490610e1062000625565b905090565b4290565b8280546200055b9062000676565b90600052602060002090601f0160209004810192826200057f5760008555620005ca565b82601f106200059a57805160ff1916838001178555620005ca565b82800160010185558215620005ca579182015b82811115620005ca578251825591602001919060010190620005ad565b50620005d8929150620005dc565b5090565b5b80821115620005d85760008155600101620005dd565b6000602082840312156200060657600080fd5b81516001600160a01b03811681146200061e57600080fd5b9392505050565b60008160001904831182151516156200064e57634e487b7160e01b600052601160045260246000fd5b500290565b6000826200067157634e487b7160e01b600052601260045260246000fd5b500490565b600181811c908216806200068b57607f821691505b60208210811415620006ad57634e487b7160e01b600052602260045260246000fd5b50919050565b6080516132dc620006dd6000396000818161147a01528181611cbd01526123a201526132dc6000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c8063715018a611610146578063c5f956af116100c3578063ddc6326211610087578063ddc63262146105c3578063e3f8a79c146105d6578063e90a95be146105e9578063e985e9c5146105fc578063f2fde38b1461060f578063f996f5c41461062257600080fd5b8063c5f956af1461056e578063c87b56dd14610581578063d201114a14610594578063db006a751461059d578063dc7d35df146105b057600080fd5b806391ddd9871161010a57806391ddd9871461052457806395d89b411461053757806398bdf6f51461053f578063a22cb46514610548578063bc4ff5d31461055b57600080fd5b8063715018a6146104b357806375220bb4146104bb578063863560e5146104ed57806386b4de68146105005780638da5cb5b1461051357600080fd5b8063404d2cf8116101df5780636352211e116101a35780636352211e146103c45780636605bfda146103d757806368626081146103ea5780636f37a2c9146103fd5780636f9b327a1461041057806370a08231146104a057600080fd5b8063404d2cf814610365578063444719f2146103785780634f6ccce71461038b57806359d88c2e1461039e5780635a9241dd146103b157600080fd5b8063181d989b11610226578063181d989b146102e657806323b872dd146103195780632aabff151461032c5780632e17de781461033f5780632f745c591461035257600080fd5b806306fdde0314610263578063081812fc14610281578063095ea7b3146102ac5780630f119377146102c157806318160ddd146102d4575b600080fd5b61026b6106c6565b6040516102789190612cb1565b60405180910390f35b61029461028f366004612ce4565b610758565b6040516001600160a01b039091168152602001610278565b6102bf6102ba366004612d14565b6107f2565b005b6102bf6102cf366004612d55565b610908565b6009545b604051908152602001610278565b6103096102f4366004612d70565b60126020526000908152604090205460ff1681565b6040519015158152602001610278565b6102bf610327366004612d8b565b61096e565b6102d861033a366004612e12565b6109e9565b6102d861034d366004612ce4565b610a76565b6102d8610360366004612d14565b610c30565b6102bf610373366004612d70565b610cc9565b6102d8610386366004612e53565b610d26565b6102d8610399366004612ce4565b610d7c565b6102d86103ac366004612eb7565b610e0f565b6102bf6103bf366004612ef3565b611013565b6102946103d2366004612ce4565b611121565b6102bf6103e5366004612d70565b611198565b6102d86103f8366004612ce4565b6111f3565b6102d861040b366004612f15565b611410565b61046461041e366004612ce4565b6011602052600090815260409020805460018201546002830154600590930154919290916001600160401b0380821691600160401b8104821691600160801b9091041686565b604080519687526020870195909552938501929092526001600160401b03908116606085015290811660808401521660a082015260c001610278565b6102d86104ae366004612d70565b61161b565b6102bf6116a2565b600d546104d590600160401b90046001600160401b031681565b6040516001600160401b039091168152602001610278565b6102bf6104fb366004612ce4565b6116e7565b600d546104d5906001600160401b031681565b600b546001600160a01b0316610294565b6102bf610532366004612d55565b611798565b61026b6117f4565b6102d8600c5481565b6102bf610556366004612f56565b611803565b6102bf610569366004612f8d565b611812565b600f54610294906001600160a01b031681565b61026b61058f366004612ce4565b6119c8565b6102d8600e5481565b6102d86105ab366004612ce4565b611b25565b6102bf6105be366004612fc8565b611d93565b6102d86105d1366004612ce4565b611e8f565b6102bf6105e4366004612d70565b611e9a565b6102d86105f7366004612e12565b611ef4565b61030961060a366004612ff4565b611f46565b6102bf61061d366004612d70565b611f74565b610683610630366004612ce4565b6010602052600090815260409020805460018201546002830154600390930154919290916001600160401b0380831692600160401b8104821692600160801b8204831692600160c01b9092049091169087565b6040805197885260208801969096526001600160401b03948516958701959095529183166060860152821660808501521660a083015260c082015260e001610278565b6060600080546106d59061301e565b80601f01602080910402602001604051908101604052809291908181526020018280546107019061301e565b801561074e5780601f106107235761010080835404028352916020019161074e565b820191906000526020600020905b81548152906001019060200180831161073157829003601f168201915b5050505050905090565b6000818152600360205260408120546001600160a01b03166107d65760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b60006107fd82611121565b9050806001600160a01b0316836001600160a01b0316141561086b5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016107cd565b336001600160a01b038216148061088757506108878133611f46565b6108f95760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016107cd565b6109038383612041565b505050565b3361091b600b546001600160a01b031690565b6001600160a01b0316146109415760405162461bcd60e51b81526004016107cd90613059565b600d80546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b61097833826120af565b6109de5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b60648201526084016107cd565b610903838383612186565b6000805b82811015610a3457610a16848483818110610a0a57610a0a61308e565b9050602002013561232d565b610a2090836130ba565b915080610a2c816130d2565b9150506109ed565b507f31a908ae5661ad1a8af4681296ba891f4f0eb047550f719aac1ff914e4307b67838383604051610a68939291906130ed565b60405180910390a192915050565b6000610a81826124f7565b6000828152601060209081526040808320805484526011909252909120600501546002820154600f546001600160401b039283169280831692600160401b900416906001600160a01b0316331415610ad857600092505b6001600160401b03811615610b225760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481d5b9cdd185ad95960821b60448201526064016107cd565b610b2c8383613133565b6001600160401b0316426001600160401b03161015610b7f5760405162461bcd60e51b815260206004820152600f60248201526e07374696c6c20696e206c6f636b757608c1b60448201526064016107cd565b610b888661232d565b60018581015460028701805467ffffffffffffffff60401b1916600160401b6001600160401b034216021790558654600090815260116020526040812090920180549398509092839290610bdd90849061315e565b9250508190555080600e6000828254610bf6919061315e565b909155505060405187907ff1f1db1ecefb0a90b3cd6a1903d29374b4a935df69fd25c7fc6ed397d3683c2690600090a25050505050919050565b6000610c3b8361161b565b8210610c9d5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016107cd565b506001600160a01b03821660009081526007602090815260408083208484529091529020545b92915050565b33610cdc600b546001600160a01b031690565b6001600160a01b031614610d025760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b6000805b84811015610d7357610d55868683818110610d4757610d4761308e565b905060200201358585610e0f565b610d5f90836130ba565b915080610d6b816130d2565b915050610d2a565b50949350505050565b6000610d8760095490565b8210610dea5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016107cd565b60098281548110610dfd57610dfd61308e565b90600052602060002001549050919050565b6000600c54841115610e525760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08195e1a5cdd195b9d60a21b60448201526064016107cd565b600084815260106020526040902060028101546001600160401b038085169116101580610e9257506002810154600160401b90046001600160401b031615155b15610ea157600091505061100c565b60028101546001600160401b0380861691161115610eca5760028101546001600160401b031693505b8054600090815260116020526040902060018201546004820180545b80156110065780610ef681613175565b9150506000828281548110610f0d57610f0d61308e565b9060005260206000200160000160089054906101000a90046001600160401b031690506000838381548110610f4457610f4461308e565b6000918252602090912001546001600160401b03908116915089811690831610610f6f575050610ee6565b896001600160401b0316826001600160401b031610610fc45780610f93838b61318c565b610fa6906001600160401b0316876131b4565b610fb091906131b4565b610fba90896130ba565b9750819850610fff565b80610fcf8b8b61318c565b610fe2906001600160401b0316876131b4565b610fec91906131b4565b610ff690896130ba565b97505050611006565b5050610ee6565b50505050505b9392505050565b3360009081526012602052604090205460ff166110635760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016107cd565b61106c82612543565b6000828152601160209081526040918290208251808401909352838352916003830191810161109961201e565b6001600160401b0390811690915282546001808201855560009485526020948590208451600290930201918255928401519201805467ffffffffffffffff191692909116919091179055604080518581529182018490527f958740ea6ebf691fabab737173356de81596654a8a7ab76e3bb52f940cf23db291015b60405180910390a1505050565b6000818152600360205260408120546001600160a01b031680610cc35760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016107cd565b336111ab600b546001600160a01b031690565b6001600160a01b0316146111d15760405162461bcd60e51b81526004016107cd90613059565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6000600c548211156112365760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08195e1a5cdd195b9d60a21b60448201526064016107cd565b60008281526010602052604090206002810154600160401b90046001600160401b0316156112675750600092915050565b80546000908152601160205260408120600183015490919061128e90600160601b906131b4565b905080600061129b61201e565b6002860154600386018054929350600160c01b9091046001600160401b0316915b80156113e957806112cc81613175565b91505060008282815481106112e3576112e361308e565b6000918252602082206001600290920201015484546001600160401b0390911692508490849081106113175761131761308e565b90600052602060002090600202016000015490506000826001600160401b0316876001600160401b0316101561134f575050506112bc565b856001600160401b0316836001600160401b0316106113a857610e10611375848961318c565b61137f91906131e9565b6001600160401b0316905061139e61139783836125b2565b899061260f565b97508296506113e1565b610e106113b5878961318c565b6113bf91906131e9565b6001600160401b031690506113d761139783836125b2565b97505050506113e9565b5050506112bc565b600160601b6113f8878761315e565b611402919061320f565b9a9950505050505050505050565b600080821161144f5760405162461bcd60e51b815260206004820152600b60248201526a0616d6f756e7420697320360ac1b60448201526064016107cd565b61145883612543565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef9190613223565b506001600c600082825461150391906130ba565b9091555050600c5490506115178482612626565b6115213082612041565b60008181526010602052604090208381556001810183905560028101805467ffffffffffffffff1916426001600160401b031617905561155f61201e565b6002820180546001600160401b0392909216600160c01b026001600160c01b03909216919091179055600084815260116020526040812060010180548592906115a99084906130ba565b9250508190555082600e60008282546115c291906130ba565b9091555050604080516001600160a01b03871681526020810186905290810184905282907f3f991e971d7c9f35e42f28a2f9f7937a7c31e42a6738bbc54248e6088d5c05959060600160405180910390a2509392505050565b60006001600160a01b0382166116865760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016107cd565b506001600160a01b031660009081526004602052604090205490565b336116b5600b546001600160a01b031690565b6001600160a01b0316146116db5760405162461bcd60e51b81526004016107cd90613059565b6116e56000612774565b565b336116fa600b546001600160a01b031690565b6001600160a01b0316146117205760405162461bcd60e51b81526004016107cd90613059565b61172981612543565b60008181526011602090815260409182902060058101805467ffffffffffffffff60801b1916600160801b6001600160401b034216021790558251848152925190927f76ea635240e43b72b06fc5187986b33eccd576d2bbce1c1513ae09c3d28094f692908290030190a15050565b336117ab600b546001600160a01b031690565b6001600160a01b0316146117d15760405162461bcd60e51b81526004016107cd90613059565b600d805467ffffffffffffffff19166001600160401b0392909216919091179055565b6060600180546106d59061301e565b61180e3383836127c6565b5050565b33611825600b546001600160a01b031690565b6001600160a01b03161461184b5760405162461bcd60e51b81526004016107cd90613059565b600084815260116020526040902060050154600160401b90046001600160401b0316156118ac5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818dc99585d1959608a1b60448201526064016107cd565b600084815260116020908152604091829020868155825180840190935284835291600383019181016118dc61201e565b6001600160401b0390811690915282546001808201855560009485526020808620855160029094020192835593840151918101805492841667ffffffffffffffff199093169290921790915560408051808201825287841681524284168186018181526004890180549586018155885296869020915191909301805496519185166001600160801b031997881617600160401b928616830217905560058701805491909302938a16951694909417919091179055815187815291517f6b70138d2b1ac6c6c366b880fd69a916ea592a176331c95355ed15efccbd3f369281900390910190a15050505050565b6000818152600360205260409020546060906001600160a01b0316611a475760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016107cd565b600060028054611a569061301e565b80601f0160208091040260200160405190810160405280929190818152602001828054611a829061301e565b8015611acf5780601f10611aa457610100808354040283529160200191611acf565b820191906000526020600020905b815481529060010190602001808311611ab257829003601f168201915b505050505090506000815111611af4576040518060200160405280600081525061100c565b80611afe84612895565b604051602001611b0f929190613240565b6040516020818303038152906040529392505050565b6000611b30826124f7565b60008281526010602052604090206002810154600d54600f546001600160401b03600160401b808504821694600160801b9004821693041690336001600160a01b039091161415611b7f575060005b6000836001600160401b031611611bc75760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd081d5b9cdd185ad95960a21b60448201526064016107cd565b611bd18184613133565b6001600160401b0316426001600160401b03161015611c245760405162461bcd60e51b815260206004820152600f60248201526e07374696c6c20696e206c6f636b757608c1b60448201526064016107cd565b6001600160401b03821615611c6e5760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481c995919595b595960821b60448201526064016107cd565b6000611c7987611121565b9050611c8633308961096e565b611c8f87612992565b600185015460405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390529197507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2c9190613223565b5060028501805467ffffffffffffffff60801b1916600160801b426001600160401b03160217905560405186815287907fe3829d5463fae0f748d927f86f762044188c9ce53d91a394eb93e98354cc30929060200160405180910390a25050505050919050565b3360009081526012602052604090205460ff16611de35760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016107cd565b611dec82612543565b6000828152601160209081526040808320815180830183526001600160401b0386811680835242821683870190815260048501805460018101825590895297879020935193909701805497518316600160401b026001600160801b03199098169390921692909217959095179094558151868152928301939093527fbd1e0a597106edf33153c6b88a76e698670f0caf8869b859ca7fbc46e9d929929101611114565b6000610cc38261232d565b33611ead600b546001600160a01b031690565b6001600160a01b031614611ed35760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b03166000908152601260205260409020805460ff19169055565b6000805b82811015611f3f57611f21848483818110611f1557611f1561308e565b905060200201356111f3565b611f2b90836130ba565b915080611f37816130d2565b915050611ef8565b5092915050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b33611f87600b546001600160a01b031690565b6001600160a01b031614611fad5760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b0381166120125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107cd565b61201b81612774565b50565b600061202c610e104261320f565b61203890610e106131b4565b905090565b4290565b600081815260056020526040902080546001600160a01b0319166001600160a01b038416908117909155819061207682611121565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600360205260408120546001600160a01b03166121285760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016107cd565b600061213383611121565b9050806001600160a01b0316846001600160a01b0316148061216e5750836001600160a01b031661216384610758565b6001600160a01b0316145b8061217e575061217e8185611f46565b949350505050565b826001600160a01b031661219982611121565b6001600160a01b0316146121fd5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016107cd565b6001600160a01b03821661225f5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016107cd565b61226a838383612a39565b612275600082612041565b6001600160a01b038316600090815260046020526040812080546001929061229e90849061315e565b90915550506001600160a01b03821660009081526004602052604081208054600192906122cc9084906130ba565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600d546000906001600160401b0316426001600160401b031610156123865760405162461bcd60e51b815260206004820152600f60248201526e31b7b6b2903130b1b5903630ba32b960891b60448201526064016107cd565b61238f826124f7565b612398826111f3565b905080156124f2577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166340c10f196123d884611121565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b15801561242057600080fd5b505af1158015612434573d6000803e3d6000fd5b5050506000838152601060205260409020905061244f61201e565b8160020160186101000a8154816001600160401b0302191690836001600160401b031602179055508181600301600082825461248b91906130ba565b909155505080546000908152601160205260408120600281018054919285926124b59084906130ba565b909155505060405183815284907f6c8433a8e155f0af04dba058d4e4695f7da554578963d876bdf4a6d8d6399d9c9060200160405180910390a250505b919050565b3361250182611121565b6001600160a01b03161461201b5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b60448201526064016107cd565b600081815260116020526040902060050154600160801b90046001600160401b03161561201b5760405162461bcd60e51b815260206004820152601760248201527f7374616b696e6720706c616e206e6f742061637469766500000000000000000060448201526064016107cd565b6000816125c45750600160601b610cc3565b81600114156125d4575081610cc3565b6125e8836125e360028561320f565b6125b2565b90506125f4818261260f565b9050612601600283613266565b60011415610cc35761100c81845b6000606061261d83856131b4565b901c9392505050565b6001600160a01b03821661267c5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016107cd565b6000818152600360205260409020546001600160a01b0316156126e15760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016107cd565b6126ed60008383612a39565b6001600160a01b03821660009081526004602052604081208054600192906127169084906130ba565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b031614156128285760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016107cd565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6060816128b95750506040805180820190915260018152600360fc1b602082015290565b8160005b81156128e357806128cd816130d2565b91506128dc9050600a8361320f565b91506128bd565b6000816001600160401b038111156128fd576128fd61327a565b6040519080825280601f01601f191660200182016040528015612927576020820181803683370190505b5090505b841561217e5761293c60018361315e565b9150612949600a86613266565b6129549060306130ba565b60f81b8183815181106129695761296961308e565b60200101906001600160f81b031916908160001a90535061298b600a8661320f565b945061292b565b600061299d82611121565b90506129ab81600084612a39565b6129b6600083612041565b6001600160a01b03811660009081526004602052604081208054600192906129df90849061315e565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b038316612a9457612a8f81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b612ab7565b816001600160a01b0316836001600160a01b031614612ab757612ab78382612af1565b6001600160a01b038216612ace5761090381612b8e565b826001600160a01b0316826001600160a01b031614610903576109038282612c3d565b60006001612afe8461161b565b612b08919061315e565b600083815260086020526040902054909150808214612b5b576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b600954600090612ba09060019061315e565b6000838152600a602052604081205460098054939450909284908110612bc857612bc861308e565b906000526020600020015490508060098381548110612be957612be961308e565b6000918252602080832090910192909255828152600a90915260408082208490558582528120556009805480612c2157612c21613290565b6001900381819060005260206000200160009055905550505050565b6000612c488361161b565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b60005b83811015612c9c578181015183820152602001612c84565b83811115612cab576000848401525b50505050565b6020815260008251806020840152612cd0816040850160208701612c81565b601f01601f19169190910160400192915050565b600060208284031215612cf657600080fd5b5035919050565b80356001600160a01b03811681146124f257600080fd5b60008060408385031215612d2757600080fd5b612d3083612cfd565b946020939093013593505050565b80356001600160401b03811681146124f257600080fd5b600060208284031215612d6757600080fd5b61100c82612d3e565b600060208284031215612d8257600080fd5b61100c82612cfd565b600080600060608486031215612da057600080fd5b612da984612cfd565b9250612db760208501612cfd565b9150604084013590509250925092565b60008083601f840112612dd957600080fd5b5081356001600160401b03811115612df057600080fd5b6020830191508360208260051b8501011115612e0b57600080fd5b9250929050565b60008060208385031215612e2557600080fd5b82356001600160401b03811115612e3b57600080fd5b612e4785828601612dc7565b90969095509350505050565b60008060008060608587031215612e6957600080fd5b84356001600160401b03811115612e7f57600080fd5b612e8b87828801612dc7565b9095509350612e9e905060208601612d3e565b9150612eac60408601612d3e565b905092959194509250565b600080600060608486031215612ecc57600080fd5b83359250612edc60208501612d3e565b9150612eea60408501612d3e565b90509250925092565b60008060408385031215612f0657600080fd5b50508035926020909101359150565b600080600060608486031215612f2a57600080fd5b612f3384612cfd565b95602085013595506040909401359392505050565b801515811461201b57600080fd5b60008060408385031215612f6957600080fd5b612f7283612cfd565b91506020830135612f8281612f48565b809150509250929050565b60008060008060808587031215612fa357600080fd5b84359350612fb360208601612d3e565b925060408501359150612eac60608601612d3e565b60008060408385031215612fdb57600080fd5b82359150612feb60208401612d3e565b90509250929050565b6000806040838503121561300757600080fd5b61301083612cfd565b9150612feb60208401612cfd565b600181811c9082168061303257607f821691505b6020821081141561305357634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156130cd576130cd6130a4565b500190565b60006000198214156130e6576130e66130a4565b5060010190565b6040808252810183905260006001600160fb1b0384111561310d57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60006001600160401b03808316818516808303821115613155576131556130a4565b01949350505050565b600082821015613170576131706130a4565b500390565b600081613184576131846130a4565b506000190190565b60006001600160401b03838116908316818110156131ac576131ac6130a4565b039392505050565b60008160001904831182151516156131ce576131ce6130a4565b500290565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680613203576132036131d3565b92169190910492915050565b60008261321e5761321e6131d3565b500490565b60006020828403121561323557600080fd5b815161100c81612f48565b60008351613252818460208801612c81565b835190830190613155818360208801612c81565b600082613275576132756131d3565b500690565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d8f1d551ba3775a6fd9e5ef21c2fe7c5d88f0096e85b8b67e0c408e82308f6bc64736f6c634300080b003368747470733a2f2f7374616b65642e7175616e746c616e642e66696e616e63652f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000000173661769325565d4f011b2e5cda688689cc87c

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061025e5760003560e01c8063715018a611610146578063c5f956af116100c3578063ddc6326211610087578063ddc63262146105c3578063e3f8a79c146105d6578063e90a95be146105e9578063e985e9c5146105fc578063f2fde38b1461060f578063f996f5c41461062257600080fd5b8063c5f956af1461056e578063c87b56dd14610581578063d201114a14610594578063db006a751461059d578063dc7d35df146105b057600080fd5b806391ddd9871161010a57806391ddd9871461052457806395d89b411461053757806398bdf6f51461053f578063a22cb46514610548578063bc4ff5d31461055b57600080fd5b8063715018a6146104b357806375220bb4146104bb578063863560e5146104ed57806386b4de68146105005780638da5cb5b1461051357600080fd5b8063404d2cf8116101df5780636352211e116101a35780636352211e146103c45780636605bfda146103d757806368626081146103ea5780636f37a2c9146103fd5780636f9b327a1461041057806370a08231146104a057600080fd5b8063404d2cf814610365578063444719f2146103785780634f6ccce71461038b57806359d88c2e1461039e5780635a9241dd146103b157600080fd5b8063181d989b11610226578063181d989b146102e657806323b872dd146103195780632aabff151461032c5780632e17de781461033f5780632f745c591461035257600080fd5b806306fdde0314610263578063081812fc14610281578063095ea7b3146102ac5780630f119377146102c157806318160ddd146102d4575b600080fd5b61026b6106c6565b6040516102789190612cb1565b60405180910390f35b61029461028f366004612ce4565b610758565b6040516001600160a01b039091168152602001610278565b6102bf6102ba366004612d14565b6107f2565b005b6102bf6102cf366004612d55565b610908565b6009545b604051908152602001610278565b6103096102f4366004612d70565b60126020526000908152604090205460ff1681565b6040519015158152602001610278565b6102bf610327366004612d8b565b61096e565b6102d861033a366004612e12565b6109e9565b6102d861034d366004612ce4565b610a76565b6102d8610360366004612d14565b610c30565b6102bf610373366004612d70565b610cc9565b6102d8610386366004612e53565b610d26565b6102d8610399366004612ce4565b610d7c565b6102d86103ac366004612eb7565b610e0f565b6102bf6103bf366004612ef3565b611013565b6102946103d2366004612ce4565b611121565b6102bf6103e5366004612d70565b611198565b6102d86103f8366004612ce4565b6111f3565b6102d861040b366004612f15565b611410565b61046461041e366004612ce4565b6011602052600090815260409020805460018201546002830154600590930154919290916001600160401b0380821691600160401b8104821691600160801b9091041686565b604080519687526020870195909552938501929092526001600160401b03908116606085015290811660808401521660a082015260c001610278565b6102d86104ae366004612d70565b61161b565b6102bf6116a2565b600d546104d590600160401b90046001600160401b031681565b6040516001600160401b039091168152602001610278565b6102bf6104fb366004612ce4565b6116e7565b600d546104d5906001600160401b031681565b600b546001600160a01b0316610294565b6102bf610532366004612d55565b611798565b61026b6117f4565b6102d8600c5481565b6102bf610556366004612f56565b611803565b6102bf610569366004612f8d565b611812565b600f54610294906001600160a01b031681565b61026b61058f366004612ce4565b6119c8565b6102d8600e5481565b6102d86105ab366004612ce4565b611b25565b6102bf6105be366004612fc8565b611d93565b6102d86105d1366004612ce4565b611e8f565b6102bf6105e4366004612d70565b611e9a565b6102d86105f7366004612e12565b611ef4565b61030961060a366004612ff4565b611f46565b6102bf61061d366004612d70565b611f74565b610683610630366004612ce4565b6010602052600090815260409020805460018201546002830154600390930154919290916001600160401b0380831692600160401b8104821692600160801b8204831692600160c01b9092049091169087565b6040805197885260208801969096526001600160401b03948516958701959095529183166060860152821660808501521660a083015260c082015260e001610278565b6060600080546106d59061301e565b80601f01602080910402602001604051908101604052809291908181526020018280546107019061301e565b801561074e5780601f106107235761010080835404028352916020019161074e565b820191906000526020600020905b81548152906001019060200180831161073157829003601f168201915b5050505050905090565b6000818152600360205260408120546001600160a01b03166107d65760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b60006107fd82611121565b9050806001600160a01b0316836001600160a01b0316141561086b5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016107cd565b336001600160a01b038216148061088757506108878133611f46565b6108f95760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016107cd565b6109038383612041565b505050565b3361091b600b546001600160a01b031690565b6001600160a01b0316146109415760405162461bcd60e51b81526004016107cd90613059565b600d80546001600160401b03909216600160401b0267ffffffffffffffff60401b19909216919091179055565b61097833826120af565b6109de5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b60648201526084016107cd565b610903838383612186565b6000805b82811015610a3457610a16848483818110610a0a57610a0a61308e565b9050602002013561232d565b610a2090836130ba565b915080610a2c816130d2565b9150506109ed565b507f31a908ae5661ad1a8af4681296ba891f4f0eb047550f719aac1ff914e4307b67838383604051610a68939291906130ed565b60405180910390a192915050565b6000610a81826124f7565b6000828152601060209081526040808320805484526011909252909120600501546002820154600f546001600160401b039283169280831692600160401b900416906001600160a01b0316331415610ad857600092505b6001600160401b03811615610b225760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481d5b9cdd185ad95960821b60448201526064016107cd565b610b2c8383613133565b6001600160401b0316426001600160401b03161015610b7f5760405162461bcd60e51b815260206004820152600f60248201526e07374696c6c20696e206c6f636b757608c1b60448201526064016107cd565b610b888661232d565b60018581015460028701805467ffffffffffffffff60401b1916600160401b6001600160401b034216021790558654600090815260116020526040812090920180549398509092839290610bdd90849061315e565b9250508190555080600e6000828254610bf6919061315e565b909155505060405187907ff1f1db1ecefb0a90b3cd6a1903d29374b4a935df69fd25c7fc6ed397d3683c2690600090a25050505050919050565b6000610c3b8361161b565b8210610c9d5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016107cd565b506001600160a01b03821660009081526007602090815260408083208484529091529020545b92915050565b33610cdc600b546001600160a01b031690565b6001600160a01b031614610d025760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b6000805b84811015610d7357610d55868683818110610d4757610d4761308e565b905060200201358585610e0f565b610d5f90836130ba565b915080610d6b816130d2565b915050610d2a565b50949350505050565b6000610d8760095490565b8210610dea5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016107cd565b60098281548110610dfd57610dfd61308e565b90600052602060002001549050919050565b6000600c54841115610e525760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08195e1a5cdd195b9d60a21b60448201526064016107cd565b600084815260106020526040902060028101546001600160401b038085169116101580610e9257506002810154600160401b90046001600160401b031615155b15610ea157600091505061100c565b60028101546001600160401b0380861691161115610eca5760028101546001600160401b031693505b8054600090815260116020526040902060018201546004820180545b80156110065780610ef681613175565b9150506000828281548110610f0d57610f0d61308e565b9060005260206000200160000160089054906101000a90046001600160401b031690506000838381548110610f4457610f4461308e565b6000918252602090912001546001600160401b03908116915089811690831610610f6f575050610ee6565b896001600160401b0316826001600160401b031610610fc45780610f93838b61318c565b610fa6906001600160401b0316876131b4565b610fb091906131b4565b610fba90896130ba565b9750819850610fff565b80610fcf8b8b61318c565b610fe2906001600160401b0316876131b4565b610fec91906131b4565b610ff690896130ba565b97505050611006565b5050610ee6565b50505050505b9392505050565b3360009081526012602052604090205460ff166110635760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016107cd565b61106c82612543565b6000828152601160209081526040918290208251808401909352838352916003830191810161109961201e565b6001600160401b0390811690915282546001808201855560009485526020948590208451600290930201918255928401519201805467ffffffffffffffff191692909116919091179055604080518581529182018490527f958740ea6ebf691fabab737173356de81596654a8a7ab76e3bb52f940cf23db291015b60405180910390a1505050565b6000818152600360205260408120546001600160a01b031680610cc35760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016107cd565b336111ab600b546001600160a01b031690565b6001600160a01b0316146111d15760405162461bcd60e51b81526004016107cd90613059565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6000600c548211156112365760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd08195e1a5cdd195b9d60a21b60448201526064016107cd565b60008281526010602052604090206002810154600160401b90046001600160401b0316156112675750600092915050565b80546000908152601160205260408120600183015490919061128e90600160601b906131b4565b905080600061129b61201e565b6002860154600386018054929350600160c01b9091046001600160401b0316915b80156113e957806112cc81613175565b91505060008282815481106112e3576112e361308e565b6000918252602082206001600290920201015484546001600160401b0390911692508490849081106113175761131761308e565b90600052602060002090600202016000015490506000826001600160401b0316876001600160401b0316101561134f575050506112bc565b856001600160401b0316836001600160401b0316106113a857610e10611375848961318c565b61137f91906131e9565b6001600160401b0316905061139e61139783836125b2565b899061260f565b97508296506113e1565b610e106113b5878961318c565b6113bf91906131e9565b6001600160401b031690506113d761139783836125b2565b97505050506113e9565b5050506112bc565b600160601b6113f8878761315e565b611402919061320f565b9a9950505050505050505050565b600080821161144f5760405162461bcd60e51b815260206004820152600b60248201526a0616d6f756e7420697320360ac1b60448201526064016107cd565b61145883612543565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f0000000000000000000000000173661769325565d4f011b2e5cda688689cc87c6001600160a01b0316906323b872dd906064016020604051808303816000875af11580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef9190613223565b506001600c600082825461150391906130ba565b9091555050600c5490506115178482612626565b6115213082612041565b60008181526010602052604090208381556001810183905560028101805467ffffffffffffffff1916426001600160401b031617905561155f61201e565b6002820180546001600160401b0392909216600160c01b026001600160c01b03909216919091179055600084815260116020526040812060010180548592906115a99084906130ba565b9250508190555082600e60008282546115c291906130ba565b9091555050604080516001600160a01b03871681526020810186905290810184905282907f3f991e971d7c9f35e42f28a2f9f7937a7c31e42a6738bbc54248e6088d5c05959060600160405180910390a2509392505050565b60006001600160a01b0382166116865760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016107cd565b506001600160a01b031660009081526004602052604090205490565b336116b5600b546001600160a01b031690565b6001600160a01b0316146116db5760405162461bcd60e51b81526004016107cd90613059565b6116e56000612774565b565b336116fa600b546001600160a01b031690565b6001600160a01b0316146117205760405162461bcd60e51b81526004016107cd90613059565b61172981612543565b60008181526011602090815260409182902060058101805467ffffffffffffffff60801b1916600160801b6001600160401b034216021790558251848152925190927f76ea635240e43b72b06fc5187986b33eccd576d2bbce1c1513ae09c3d28094f692908290030190a15050565b336117ab600b546001600160a01b031690565b6001600160a01b0316146117d15760405162461bcd60e51b81526004016107cd90613059565b600d805467ffffffffffffffff19166001600160401b0392909216919091179055565b6060600180546106d59061301e565b61180e3383836127c6565b5050565b33611825600b546001600160a01b031690565b6001600160a01b03161461184b5760405162461bcd60e51b81526004016107cd90613059565b600084815260116020526040902060050154600160401b90046001600160401b0316156118ac5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818dc99585d1959608a1b60448201526064016107cd565b600084815260116020908152604091829020868155825180840190935284835291600383019181016118dc61201e565b6001600160401b0390811690915282546001808201855560009485526020808620855160029094020192835593840151918101805492841667ffffffffffffffff199093169290921790915560408051808201825287841681524284168186018181526004890180549586018155885296869020915191909301805496519185166001600160801b031997881617600160401b928616830217905560058701805491909302938a16951694909417919091179055815187815291517f6b70138d2b1ac6c6c366b880fd69a916ea592a176331c95355ed15efccbd3f369281900390910190a15050505050565b6000818152600360205260409020546060906001600160a01b0316611a475760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016107cd565b600060028054611a569061301e565b80601f0160208091040260200160405190810160405280929190818152602001828054611a829061301e565b8015611acf5780601f10611aa457610100808354040283529160200191611acf565b820191906000526020600020905b815481529060010190602001808311611ab257829003601f168201915b505050505090506000815111611af4576040518060200160405280600081525061100c565b80611afe84612895565b604051602001611b0f929190613240565b6040516020818303038152906040529392505050565b6000611b30826124f7565b60008281526010602052604090206002810154600d54600f546001600160401b03600160401b808504821694600160801b9004821693041690336001600160a01b039091161415611b7f575060005b6000836001600160401b031611611bc75760405162461bcd60e51b815260206004820152600c60248201526b1b9bdd081d5b9cdd185ad95960a21b60448201526064016107cd565b611bd18184613133565b6001600160401b0316426001600160401b03161015611c245760405162461bcd60e51b815260206004820152600f60248201526e07374696c6c20696e206c6f636b757608c1b60448201526064016107cd565b6001600160401b03821615611c6e5760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481c995919595b595960821b60448201526064016107cd565b6000611c7987611121565b9050611c8633308961096e565b611c8f87612992565b600185015460405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390529197507f0000000000000000000000000173661769325565d4f011b2e5cda688689cc87c9091169063a9059cbb906044016020604051808303816000875af1158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2c9190613223565b5060028501805467ffffffffffffffff60801b1916600160801b426001600160401b03160217905560405186815287907fe3829d5463fae0f748d927f86f762044188c9ce53d91a394eb93e98354cc30929060200160405180910390a25050505050919050565b3360009081526012602052604090205460ff16611de35760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016107cd565b611dec82612543565b6000828152601160209081526040808320815180830183526001600160401b0386811680835242821683870190815260048501805460018101825590895297879020935193909701805497518316600160401b026001600160801b03199098169390921692909217959095179094558151868152928301939093527fbd1e0a597106edf33153c6b88a76e698670f0caf8869b859ca7fbc46e9d929929101611114565b6000610cc38261232d565b33611ead600b546001600160a01b031690565b6001600160a01b031614611ed35760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b03166000908152601260205260409020805460ff19169055565b6000805b82811015611f3f57611f21848483818110611f1557611f1561308e565b905060200201356111f3565b611f2b90836130ba565b915080611f37816130d2565b915050611ef8565b5092915050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b33611f87600b546001600160a01b031690565b6001600160a01b031614611fad5760405162461bcd60e51b81526004016107cd90613059565b6001600160a01b0381166120125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107cd565b61201b81612774565b50565b600061202c610e104261320f565b61203890610e106131b4565b905090565b4290565b600081815260056020526040902080546001600160a01b0319166001600160a01b038416908117909155819061207682611121565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600360205260408120546001600160a01b03166121285760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016107cd565b600061213383611121565b9050806001600160a01b0316846001600160a01b0316148061216e5750836001600160a01b031661216384610758565b6001600160a01b0316145b8061217e575061217e8185611f46565b949350505050565b826001600160a01b031661219982611121565b6001600160a01b0316146121fd5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016107cd565b6001600160a01b03821661225f5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016107cd565b61226a838383612a39565b612275600082612041565b6001600160a01b038316600090815260046020526040812080546001929061229e90849061315e565b90915550506001600160a01b03821660009081526004602052604081208054600192906122cc9084906130ba565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600d546000906001600160401b0316426001600160401b031610156123865760405162461bcd60e51b815260206004820152600f60248201526e31b7b6b2903130b1b5903630ba32b960891b60448201526064016107cd565b61238f826124f7565b612398826111f3565b905080156124f2577f0000000000000000000000000173661769325565d4f011b2e5cda688689cc87c6001600160a01b03166340c10f196123d884611121565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b15801561242057600080fd5b505af1158015612434573d6000803e3d6000fd5b5050506000838152601060205260409020905061244f61201e565b8160020160186101000a8154816001600160401b0302191690836001600160401b031602179055508181600301600082825461248b91906130ba565b909155505080546000908152601160205260408120600281018054919285926124b59084906130ba565b909155505060405183815284907f6c8433a8e155f0af04dba058d4e4695f7da554578963d876bdf4a6d8d6399d9c9060200160405180910390a250505b919050565b3361250182611121565b6001600160a01b03161461201b5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b60448201526064016107cd565b600081815260116020526040902060050154600160801b90046001600160401b03161561201b5760405162461bcd60e51b815260206004820152601760248201527f7374616b696e6720706c616e206e6f742061637469766500000000000000000060448201526064016107cd565b6000816125c45750600160601b610cc3565b81600114156125d4575081610cc3565b6125e8836125e360028561320f565b6125b2565b90506125f4818261260f565b9050612601600283613266565b60011415610cc35761100c81845b6000606061261d83856131b4565b901c9392505050565b6001600160a01b03821661267c5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016107cd565b6000818152600360205260409020546001600160a01b0316156126e15760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016107cd565b6126ed60008383612a39565b6001600160a01b03821660009081526004602052604081208054600192906127169084906130ba565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b031614156128285760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016107cd565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6060816128b95750506040805180820190915260018152600360fc1b602082015290565b8160005b81156128e357806128cd816130d2565b91506128dc9050600a8361320f565b91506128bd565b6000816001600160401b038111156128fd576128fd61327a565b6040519080825280601f01601f191660200182016040528015612927576020820181803683370190505b5090505b841561217e5761293c60018361315e565b9150612949600a86613266565b6129549060306130ba565b60f81b8183815181106129695761296961308e565b60200101906001600160f81b031916908160001a90535061298b600a8661320f565b945061292b565b600061299d82611121565b90506129ab81600084612a39565b6129b6600083612041565b6001600160a01b03811660009081526004602052604081208054600192906129df90849061315e565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b038316612a9457612a8f81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b612ab7565b816001600160a01b0316836001600160a01b031614612ab757612ab78382612af1565b6001600160a01b038216612ace5761090381612b8e565b826001600160a01b0316826001600160a01b031614610903576109038282612c3d565b60006001612afe8461161b565b612b08919061315e565b600083815260086020526040902054909150808214612b5b576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b600954600090612ba09060019061315e565b6000838152600a602052604081205460098054939450909284908110612bc857612bc861308e565b906000526020600020015490508060098381548110612be957612be961308e565b6000918252602080832090910192909255828152600a90915260408082208490558582528120556009805480612c2157612c21613290565b6001900381819060005260206000200160009055905550505050565b6000612c488361161b565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b60005b83811015612c9c578181015183820152602001612c84565b83811115612cab576000848401525b50505050565b6020815260008251806020840152612cd0816040850160208701612c81565b601f01601f19169190910160400192915050565b600060208284031215612cf657600080fd5b5035919050565b80356001600160a01b03811681146124f257600080fd5b60008060408385031215612d2757600080fd5b612d3083612cfd565b946020939093013593505050565b80356001600160401b03811681146124f257600080fd5b600060208284031215612d6757600080fd5b61100c82612d3e565b600060208284031215612d8257600080fd5b61100c82612cfd565b600080600060608486031215612da057600080fd5b612da984612cfd565b9250612db760208501612cfd565b9150604084013590509250925092565b60008083601f840112612dd957600080fd5b5081356001600160401b03811115612df057600080fd5b6020830191508360208260051b8501011115612e0b57600080fd5b9250929050565b60008060208385031215612e2557600080fd5b82356001600160401b03811115612e3b57600080fd5b612e4785828601612dc7565b90969095509350505050565b60008060008060608587031215612e6957600080fd5b84356001600160401b03811115612e7f57600080fd5b612e8b87828801612dc7565b9095509350612e9e905060208601612d3e565b9150612eac60408601612d3e565b905092959194509250565b600080600060608486031215612ecc57600080fd5b83359250612edc60208501612d3e565b9150612eea60408501612d3e565b90509250925092565b60008060408385031215612f0657600080fd5b50508035926020909101359150565b600080600060608486031215612f2a57600080fd5b612f3384612cfd565b95602085013595506040909401359392505050565b801515811461201b57600080fd5b60008060408385031215612f6957600080fd5b612f7283612cfd565b91506020830135612f8281612f48565b809150509250929050565b60008060008060808587031215612fa357600080fd5b84359350612fb360208601612d3e565b925060408501359150612eac60608601612d3e565b60008060408385031215612fdb57600080fd5b82359150612feb60208401612d3e565b90509250929050565b6000806040838503121561300757600080fd5b61301083612cfd565b9150612feb60208401612cfd565b600181811c9082168061303257607f821691505b6020821081141561305357634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156130cd576130cd6130a4565b500190565b60006000198214156130e6576130e66130a4565b5060010190565b6040808252810183905260006001600160fb1b0384111561310d57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60006001600160401b03808316818516808303821115613155576131556130a4565b01949350505050565b600082821015613170576131706130a4565b500390565b600081613184576131846130a4565b506000190190565b60006001600160401b03838116908316818110156131ac576131ac6130a4565b039392505050565b60008160001904831182151516156131ce576131ce6130a4565b500290565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680613203576132036131d3565b92169190910492915050565b60008261321e5761321e6131d3565b500490565b60006020828403121561323557600080fd5b815161100c81612f48565b60008351613252818460208801612c81565b835190830190613155818360208801612c81565b600082613275576132756131d3565b500690565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d8f1d551ba3775a6fd9e5ef21c2fe7c5d88f0096e85b8b67e0c408e82308f6bc64736f6c634300080b0033

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

0000000000000000000000000173661769325565d4f011b2e5cda688689cc87c

-----Decoded View---------------
Arg [0] : _QLTContract (address): 0x0173661769325565d4f011b2e5Cda688689Cc87c

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000173661769325565d4f011b2e5cda688689cc87c


Deployed Bytecode Sourcemap

59680:14042:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10536:100;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11881:308;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1014:32:1;;;996:51;;984:2;969:18;11881:308:0;850:203:1;11408:407:0;;;;;;:::i;:::-;;:::i;:::-;;72625:164;;;;;;:::i;:::-;;:::i;20198:113::-;20286:10;:17;20198:113;;;2006:25:1;;;1994:2;1979:18;20198:113:0;1860:177:1;60740:51:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2398:14:1;;2391:22;2373:41;;2361:2;2346:18;60740:51:0;2233:187:1;12798:374:0;;;;;;:::i;:::-;;:::i;67152:299::-;;;;;;:::i;:::-;;:::i;64689:1109::-;;;;;;:::i;:::-;;:::i;19779:343::-;;;;;;:::i;:::-;;:::i;73346:119::-;;;;;;:::i;:::-;;:::i;72131:323::-;;;;;;:::i;:::-;;:::i;20388:320::-;;;;;;:::i;:::-;;:::i;70618:1505::-;;;;;;:::i;:::-;;:::i;62624:494::-;;;;;;:::i;:::-;;:::i;10143:326::-;;;;;;:::i;:::-;;:::i;72797:126::-;;;;;;:::i;:::-;;:::i;68482:1845::-;;;;;;:::i;:::-;;:::i;63660:1021::-;;;;;;:::i;:::-;;:::i;60680:51::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60680:51:0;;;;-1:-1:-1;;;60680:51:0;;;;;-1:-1:-1;;;60680:51:0;;;;;;;;;;5533:25:1;;;5589:2;5574:18;;5567:34;;;;5617:18;;;5610:34;;;;-1:-1:-1;;;;;5717:15:1;;;5712:2;5697:18;;5690:43;5770:15;;;5764:3;5749:19;;5742:44;5823:15;5817:3;5802:19;;5795:44;5520:3;5505:19;60680:51:0;5252:593:1;9786:295:0;;;;;;:::i;:::-;;:::i;1752:103::-;;;:::i;60503:33::-;;;;;-1:-1:-1;;;60503:33:0;;-1:-1:-1;;;;;60503:33:0;;;;;;-1:-1:-1;;;;;6012:31:1;;;5994:50;;5982:2;5967:18;60503:33:0;5850:200:1;62334:282:0;;;;;;:::i;:::-;;:::i;60466:30::-;;;;;-1:-1:-1;;;;;60466:30:0;;;1103:87;1176:6;;-1:-1:-1;;;;;1176:6:0;1103:87;;72488:129;;;;;;:::i;:::-;;:::i;10705:104::-;;;:::i;60430:29::-;;;;;;12261:185;;;;;;:::i;:::-;;:::i;61437:889::-;;;;;;:::i;:::-;;:::i;60585:30::-;;;;;-1:-1:-1;;;;;60585:30:0;;;10880:466;;;;;;:::i;:::-;;:::i;60545:33::-;;;;;;65806:1206;;;;;;:::i;:::-;;:::i;63126:489::-;;;;;;:::i;:::-;;:::i;67020:124::-;;;;;;:::i;:::-;;:::i;73473:125::-;;;;;;:::i;:::-;;:::i;70335:275::-;;;;;;:::i;:::-;;:::i;12517:214::-;;;;;;:::i;:::-;;:::i;2010:238::-;;;;;;:::i;:::-;;:::i;60622:51::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60622:51:0;;;;-1:-1:-1;;;60622:51:0;;;;;-1:-1:-1;;;60622:51:0;;;;;-1:-1:-1;;;60622:51:0;;;;;;;;;;;;;7725:25:1;;;7781:2;7766:18;;7759:34;;;;-1:-1:-1;;;;;7866:15:1;;;7846:18;;;7839:43;;;;7918:15;;;7913:2;7898:18;;7891:43;7971:15;;7965:3;7950:19;;7943:44;8024:15;8018:3;8003:19;;7996:44;8071:3;8056:19;;8049:35;7712:3;7697:19;60622:51:0;7418:672:1;10536:100:0;10590:13;10623:5;10616:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10536:100;:::o;11881:308::-;12002:7;13574:16;;;:7;:16;;;;;;-1:-1:-1;;;;;13574:16:0;12027:110;;;;-1:-1:-1;;;12027:110:0;;8682:2:1;12027:110:0;;;8664:21:1;8721:2;8701:18;;;8694:30;8760:34;8740:18;;;8733:62;-1:-1:-1;;;8811:18:1;;;8804:42;8863:19;;12027:110:0;;;;;;;;;-1:-1:-1;12157:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;12157:24:0;;11881:308::o;11408:407::-;11489:13;11505:23;11520:7;11505:14;:23::i;:::-;11489:39;;11553:5;-1:-1:-1;;;;;11547:11:0;:2;-1:-1:-1;;;;;11547:11:0;;;11539:57;;;;-1:-1:-1;;;11539:57:0;;9095:2:1;11539:57:0;;;9077:21:1;9134:2;9114:18;;;9107:30;9173:34;9153:18;;;9146:62;-1:-1:-1;;;9224:18:1;;;9217:31;9265:19;;11539:57:0;8893:397:1;11539:57:0;11631:10;-1:-1:-1;;;;;11631:19:0;;;;:58;;;11654:35;11671:5;11678:10;11654:16;:35::i;:::-;11609:164;;;;-1:-1:-1;;;11609:164:0;;9497:2:1;11609:164:0;;;9479:21:1;9536:2;9516:18;;;9509:30;9575:34;9555:18;;;9548:62;9646:26;9626:18;;;9619:54;9690:19;;11609:164:0;9295:420:1;11609:164:0;11786:21;11795:2;11799:7;11786:8;:21::i;:::-;11478:337;11408:407;;:::o;72625:164::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;72739:19:::1;:42:::0;;-1:-1:-1;;;;;72739:42:0;;::::1;-1:-1:-1::0;;;72739:42:0::1;-1:-1:-1::0;;;;72739:42:0;;::::1;::::0;;;::::1;::::0;;72625:164::o;12798:374::-;13007:39;13026:10;13038:7;13007:18;:39::i;:::-;12985:138;;;;-1:-1:-1;;;12985:138:0;;10283:2:1;12985:138:0;;;10265:21:1;10322:2;10302:18;;;10295:30;10361:34;10341:18;;;10334:62;-1:-1:-1;;;10412:18:1;;;10405:47;10469:19;;12985:138:0;10081:413:1;12985:138:0;13136:28;13146:4;13152:2;13156:7;13136:9;:28::i;67152:299::-;67237:20;;67275:117;67295:19;;;67275:117;;;67352:28;67368:8;;67377:1;67368:11;;;;;;;:::i;:::-;;;;;;;67352:15;:28::i;:::-;67336:44;;;;:::i;:::-;;-1:-1:-1;67316:3:0;;;;:::i;:::-;;;;67275:117;;;;67409:34;67420:8;;67430:12;67409:34;;;;;;;;:::i;:::-;;;;;;;;67152:299;;;;:::o;64689:1109::-;64741:20;64774:38;64804:7;64774:29;:38::i;:::-;64825:31;64859:21;;;:12;:21;;;;;;;;64926:23;;64913:37;;:12;:37;;;;;;:64;;;65007:21;;;;65114:15;;-1:-1:-1;;;;;64913:64:0;;;;65007:21;;;;-1:-1:-1;;;65060:23:0;;;;-1:-1:-1;;;;;65114:15:0;65100:10;:29;65096:78;;;65161:1;65146:16;;65096:78;-1:-1:-1;;;;;65194:16:0;;;65186:45;;;;-1:-1:-1;;;65186:45:0;;11802:2:1;65186:45:0;;;11784:21:1;11841:2;11821:18;;;11814:30;-1:-1:-1;;;11860:18:1;;;11853:46;11916:18;;65186:45:0;11600:340:1;65186:45:0;65291:24;65303:12;65291:9;:24;:::i;:::-;-1:-1:-1;;;;;65264:52:0;27520:15;-1:-1:-1;;;;;65264:52:0;;;65242:117;;;;-1:-1:-1;;;65242:117:0;;12388:2:1;65242:117:0;;;12370:21:1;12427:2;12407:18;;;12400:30;-1:-1:-1;;;12446:18:1;;;12439:45;12501:18;;65242:117:0;12186:339:1;65242:117:0;65413:24;65429:7;65413:15;:24::i;:::-;65507;;;;;65542:23;;;:48;;-1:-1:-1;;;;65542:48:0;-1:-1:-1;;;;;;;;27520:15:0;65542:48;;;;;65653:23;;-1:-1:-1;65640:37:0;;;:12;:37;;;;;:51;;;:69;;65398:39;;-1:-1:-1;65507:24:0;;;;-1:-1:-1;65640:69:0;;65507:24;;65640:69;:::i;:::-;;;;;;;;65742:14;65720:18;;:36;;;;;;;:::i;:::-;;;;-1:-1:-1;;65774:16:0;;65782:7;;65774:16;;;;;64763:1035;;;;;64689:1109;;;:::o;19779:343::-;19921:7;19976:23;19993:5;19976:16;:23::i;:::-;19968:5;:31;19946:124;;;;-1:-1:-1;;;19946:124:0;;12862:2:1;19946:124:0;;;12844:21:1;12901:2;12881:18;;;12874:30;12940:34;12920:18;;;12913:62;-1:-1:-1;;;12991:18:1;;;12984:41;13042:19;;19946:124:0;12660:407:1;19946:124:0;-1:-1:-1;;;;;;20088:19:0;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;19779:343;;;;;:::o;73346:119::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;73422:28:0::1;;::::0;;;:19:::1;:28;::::0;;;;:35;;-1:-1:-1;;73422:35:0::1;73453:4;73422:35;::::0;;73346:119::o;72131:323::-;72277:20;;72310:137;72330:19;;;72310:137;;;72387:48;72403:8;;72412:1;72403:11;;;;;;;:::i;:::-;;;;;;;72416:9;72427:7;72387:15;:48::i;:::-;72371:64;;;;:::i;:::-;;-1:-1:-1;72351:3:0;;;;:::i;:::-;;;;72310:137;;;;72131:323;;;;;;:::o;20388:320::-;20508:7;20563:30;20286:10;:17;;20198:113;20563:30;20555:5;:38;20533:132;;;;-1:-1:-1;;;20533:132:0;;13274:2:1;20533:132:0;;;13256:21:1;13313:2;13293:18;;;13286:30;13352:34;13332:18;;;13325:62;-1:-1:-1;;;13403:18:1;;;13396:42;13455:19;;20533:132:0;13072:408:1;20533:132:0;20683:10;20694:5;20683:17;;;;;;;;:::i;:::-;;;;;;;;;20676:24;;20388:320;;;:::o;70618:1505::-;70749:20;70801:14;;70790:7;:25;;70782:50;;;;-1:-1:-1;;;70782:50:0;;13687:2:1;70782:50:0;;;13669:21:1;13726:2;13706:18;;;13699:30;-1:-1:-1;;;13745:18:1;;;13738:42;13797:18;;70782:50:0;13485:336:1;70782:50:0;70845:31;70879:21;;;:12;:21;;;;;70915;;;;-1:-1:-1;;;;;70915:32:0;;;:21;;:32;;;:63;;-1:-1:-1;70951:23:0;;;;-1:-1:-1;;;70951:23:0;;-1:-1:-1;;;;;70951:23:0;:27;;70915:63;70911:104;;;71002:1;70995:8;;;;;70911:104;71029:21;;;;-1:-1:-1;;;;;71029:33:0;;;:21;;:33;71025:99;;;71091:21;;;;-1:-1:-1;;;;;71091:21:0;;-1:-1:-1;71025:99:0;71183:23;;71136:31;71170:37;;;:12;:37;;;;;71241:24;;;;71323:23;;;71369:18;;71398:718;71405:5;;71398:718;;71427:3;;;;:::i;:::-;;;;71447:22;71472:11;71484:1;71472:14;;;;;;;;:::i;:::-;;;;;;;;:24;;;;;;;;;;-1:-1:-1;;;;;71472:24:0;71447:49;;71511:18;71532:11;71544:1;71532:14;;;;;;;;:::i;:::-;;;;;;;;;;:25;-1:-1:-1;;;;;71532:25:0;;;;-1:-1:-1;71578:26:0;;;;;;;71574:75;;71625:8;;;;71574:75;71688:9;-1:-1:-1;;;;;71669:28:0;:15;-1:-1:-1;;;;;71669:28:0;;71665:440;;71842:10;71792:25;71802:15;71792:7;:25;:::i;:::-;71755:63;;-1:-1:-1;;;;;71755:63:0;:12;:63;:::i;:::-;:97;;;;:::i;:::-;71718:134;;;;:::i;:::-;;;71881:15;71871:25;;71665:440;;;72055:10;72011:19;72021:9;72011:7;:19;:::i;:::-;71974:57;;-1:-1:-1;;;;;71974:57:0;:12;:57;:::i;:::-;:91;;;;:::i;:::-;71937:128;;;;:::i;:::-;;;72084:5;;;;71665:440;71412:704;;71398:718;;;70771:1352;;;;;70618:1505;;;;;;:::o;62624:494::-;73669:10;73649:31;;;;:19;:31;;;;;;;;73641:58;;;;-1:-1:-1;;;73641:58:0;;14576:2:1;73641:58:0;;;14558:21:1;14615:2;14595:18;;;14588:30;-1:-1:-1;;;14634:18:1;;;14627:44;14688:18;;73641:58:0;14374:338:1;73641:58:0;62748:29:::1;62772:4;62748:23;:29::i;:::-;62790:31;62824:18:::0;;;:12:::1;:18;::::0;;;;;;;;62896:140;;;;::::1;::::0;;;;;;62824:18;62853:23:::1;::::0;::::1;::::0;62896:140;::::1;62991:29;:27;:29::i;:::-;-1:-1:-1::0;;;;;62896:140:0;;::::1;::::0;;;62853:194;;::::1;::::0;;::::1;::::0;;-1:-1:-1;62853:194:0;;;::::1;::::0;;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;62853:194:0::1;::::0;;;::::1;::::0;;;::::1;::::0;;63065:45:::1;::::0;;14891:25:1;;;14932:18;;;14925:34;;;63065:45:0::1;::::0;14864:18:1;63065:45:0::1;;;;;;;;62737:381;62624:494:::0;;:::o;10143:326::-;10260:7;10301:16;;;:7;:16;;;;;;-1:-1:-1;;;;;10301:16:0;10350:19;10328:110;;;;-1:-1:-1;;;10328:110:0;;15172:2:1;10328:110:0;;;15154:21:1;15211:2;15191:18;;;15184:30;15250:34;15230:18;;;15223:62;-1:-1:-1;;;15301:18:1;;;15294:39;15350:19;;10328:110:0;14970:405:1;72797:126:0;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;72881:15:::1;:34:::0;;-1:-1:-1;;;;;;72881:34:0::1;-1:-1:-1::0;;;;;72881:34:0;;;::::1;::::0;;;::::1;::::0;;72797:126::o;68482:1845::-;68576:20;68633:14;;68622:7;:25;;68614:50;;;;-1:-1:-1;;;68614:50:0;;13687:2:1;68614:50:0;;;13669:21:1;13726:2;13706:18;;;13699:30;-1:-1:-1;;;13745:18:1;;;13738:42;13797:18;;68614:50:0;13485:336:1;68614:50:0;68677:31;68711:21;;;:12;:21;;;;;68749:23;;;;-1:-1:-1;;;68749:23:0;;-1:-1:-1;;;;;68749:23:0;:27;68745:68;;-1:-1:-1;68800:1:0;;68482:1845;-1:-1:-1;;68482:1845:0:o;68745:68::-;68872:23;;68825:31;68859:37;;;:12;:37;;;;;68983:24;;;;68859:37;;68825:31;68983:30;;-1:-1:-1;;;56298:5:0;68983:30;:::i;:::-;68957:56;-1:-1:-1;68957:56:0;69024:27;69103:29;:27;:29::i;:::-;69168:27;;;;69250:23;;;69296:18;;69080:52;;-1:-1:-1;;;;69168:27:0;;;-1:-1:-1;;;;;69168:27:0;;69325:922;69332:5;;69325:922;;69354:3;;;;:::i;:::-;;;;69374:22;69399:11;69411:1;69399:14;;;;;;;;:::i;:::-;;;;;;;;:24;:14;;;;;:24;;69462:14;;-1:-1:-1;;;;;69399:24:0;;;;-1:-1:-1;69462:11:0;;69474:1;;69462:14;;;;;;:::i;:::-;;;;;;;;;;;:28;;;69438:52;;69505:18;69560:15;-1:-1:-1;;;;;69544:31:0;:13;-1:-1:-1;;;;;69544:31:0;;69540:80;;;69596:8;;;;;69540:80;69659:15;-1:-1:-1;;;;;69640:34:0;:15;-1:-1:-1;;;;;69640:34:0;;69636:600;;69744:7;69709:31;69725:15;69709:13;:31;:::i;:::-;69708:43;;;;:::i;:::-;-1:-1:-1;;;;;69695:56:0;;;69792:108;69841:40;69855:13;69870:10;69841:13;:40::i;:::-;69792:19;;:26;:108::i;:::-;69770:130;;69935:15;69919:31;;69636:600;;;70040:7;70005:31;70021:15;70005:13;:31;:::i;:::-;70004:43;;;;:::i;:::-;-1:-1:-1;;;;;69991:56:0;;;70088:108;70137:40;70151:13;70166:10;70137:13;:40::i;70088:108::-;70066:130;;70215:5;;;;;69636:600;69339:908;;;69325:922;;;-1:-1:-1;;;70275:37:0;70297:15;70275:19;:37;:::i;:::-;70274:45;;;;:::i;:::-;70259:60;68482:1845;-1:-1:-1;;;;;;;;;;68482:1845:0:o;63660:1021::-;63783:15;63828:1;63819:6;:10;63811:34;;;;-1:-1:-1;;;63811:34:0;;16043:2:1;63811:34:0;;;16025:21:1;16082:2;16062:18;;;16055:30;-1:-1:-1;;;16101:18:1;;;16094:41;16152:18;;63811:34:0;15841:335:1;63811:34:0;63856:36;63880:11;63856:23;:36::i;:::-;63930:59;;-1:-1:-1;;;63930:59:0;;63955:10;63930:59;;;16421:34:1;63975:4:0;16471:18:1;;;16464:43;16523:18;;;16516:34;;;63930:11:0;-1:-1:-1;;;;;63930:24:0;;;;16356:18:1;;63930:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;64037:1;64019:14;;:19;;;;;;;:::i;:::-;;;;-1:-1:-1;;64059:14:0;;;-1:-1:-1;64084:25:0;64090:9;64059:14;64084:5;:25::i;:::-;64120:32;64137:4;64144:7;64120:8;:32::i;:::-;64197:31;64231:21;;;:12;:21;;;;;64263:37;;;64311:24;;;:33;;;64355:21;;;:46;;-1:-1:-1;;64355:46:0;27520:15;-1:-1:-1;;;;;64355:46:0;;;;64442:29;:27;:29::i;:::-;64412:27;;;:59;;-1:-1:-1;;;;;64412:59:0;;;;-1:-1:-1;;;64412:59:0;-1:-1:-1;;;;;64412:59:0;;;;;;;;;-1:-1:-1;64521:25:0;;;:12;:25;;;;;-1:-1:-1;64521:39:0;:49;;64564:6;;-1:-1:-1;64521:49:0;;64564:6;;64521:49;:::i;:::-;;;;;;;;64603:6;64581:18;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;;64627:46:0;;;-1:-1:-1;;;;;17031:32:1;;17013:51;;17095:2;17080:18;;17073:34;;;17123:18;;;17116:34;;;64633:7:0;;64627:46;;17001:2:1;16986:18;64627:46:0;;;;;;;63800:881;63660:1021;;;;;:::o;9786:295::-;9903:7;-1:-1:-1;;;;;9950:19:0;;9928:111;;;;-1:-1:-1;;;9928:111:0;;17363:2:1;9928:111:0;;;17345:21:1;17402:2;17382:18;;;17375:30;17441:34;17421:18;;;17414:62;-1:-1:-1;;;17492:18:1;;;17485:40;17542:19;;9928:111:0;17161:406:1;9928:111:0;-1:-1:-1;;;;;;10057:16:0;;;;;:9;:16;;;;;;;9786:295::o;1752:103::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;1817:30:::1;1844:1;1817:18;:30::i;:::-;1752:103::o:0;62334:282::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;62407:29:::1;62431:4;62407:23;:29::i;:::-;62449:31;62483:18:::0;;;:12:::1;:18;::::0;;;;;;;;62512:25:::1;::::0;::::1;:50:::0;;-1:-1:-1;;;;62512:50:0::1;-1:-1:-1::0;;;;;;;;27520:15:0;62512:50:::1;;;::::0;;62580:28;;2006:25:1;;;62580:28:0;;62483:18;;62580:28:::1;::::0;;;;;;;::::1;62396:220;62334:282:::0;:::o;72488:129::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;72573:16:::1;:36:::0;;-1:-1:-1;;72573:36:0::1;-1:-1:-1::0;;;;;72573:36:0;;;::::1;::::0;;;::::1;::::0;;72488:129::o;10705:104::-;10761:13;10794:7;10787:14;;;;;:::i;12261:185::-;12388:50;12407:10;12419:8;12429;12388:18;:50::i;:::-;12261:185;;:::o;61437:889::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;61617:18:::1;::::0;;;:12:::1;:18;::::0;;;;:28:::1;;::::0;-1:-1:-1;;;61617:28:0;::::1;-1:-1:-1::0;;;;;61617:28:0::1;:33:::0;61609:61:::1;;;::::0;-1:-1:-1;;;61609:61:0;;17956:2:1;61609:61:0::1;::::0;::::1;17938:21:1::0;17995:2;17975:18;;;17968:30;-1:-1:-1;;;18014:18:1;;;18007:45;18069:18;;61609:61:0::1;17754:339:1::0;61609:61:0::1;61681:31;61715:18:::0;;;:12:::1;:18;::::0;;;;;;;;61744:23;;;61821:140;;;;::::1;::::0;;;;;;61715:18;61778:23:::1;::::0;::::1;::::0;61821:140;::::1;61916:29;:27;:29::i;:::-;-1:-1:-1::0;;;;;61821:140:0;;::::1;::::0;;;61778:194;;::::1;::::0;;::::1;::::0;;-1:-1:-1;61778:194:0;;;::::1;::::0;;;;;::::1;::::0;;::::1;;::::0;;;;;::::1;::::0;;;::::1;::::0;;;;::::1;-1:-1:-1::0;;61778:194:0;;::::1;::::0;;;::::1;::::0;;;62026:132:::1;::::0;;;;::::1;::::0;;;;::::1;::::0;;27520:15;62026:132;::::1;::::0;;::::1;::::0;;;61983:23:::1;::::0;::::1;:186:::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;::::0;;;;;;::::1;-1:-1:-1::0;;;;;;61983:186:0;;;;-1:-1:-1;;;61983:186:0;;::::1;::::0;::::1;;::::0;;62180:24:::1;::::0;::::1;:39:::0;;62230:46;;;::::1;62180:39:::0;;::::1;62230:46:::0;;;;;;;;;::::1;::::0;;62294:24;;2006:25:1;;;62294:24:0;;::::1;::::0;;;;;;;;::::1;61598:728;61437:889:::0;;;;:::o;10880:466::-;13550:4;13574:16;;;:7;:16;;;;;;10998:13;;-1:-1:-1;;;;;13574:16:0;11029:113;;;;-1:-1:-1;;;11029:113:0;;18300:2:1;11029:113:0;;;18282:21:1;18339:2;18319:18;;;18312:30;18378:34;18358:18;;;18351:62;-1:-1:-1;;;18429:18:1;;;18422:45;18484:19;;11029:113:0;18098:411:1;11029:113:0;11155:21;11179:8;11155:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11242:1;11224:7;11218:21;:25;:120;;;;;;;;;;;;;;;;;11287:7;11296:18;:7;:16;:18::i;:::-;11270:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;11198:140;10880:466;-1:-1:-1;;;10880:466:0:o;65806:1206::-;65857:22;65892:38;65922:7;65892:29;:38::i;:::-;65943:31;65977:21;;;:12;:21;;;;;66030:23;;;;66147:19;;66197:15;;-1:-1:-1;;;;;;;;66030:23:0;;;;;;-1:-1:-1;;;66084:22:0;;;;;66147:19;;;66183:10;-1:-1:-1;;;;;66197:15:0;;;66183:29;66179:86;;;-1:-1:-1;66252:1:0;66179:86;66332:1;66318:11;-1:-1:-1;;;;;66318:15:0;;66310:40;;;;-1:-1:-1;;;66310:40:0;;19191:2:1;66310:40:0;;;19173:21:1;19230:2;19210:18;;;19203:30;-1:-1:-1;;;19249:18:1;;;19242:42;19301:18;;66310:40:0;18989:336:1;66310:40:0;66410:34;66424:20;66410:11;:34;:::i;:::-;-1:-1:-1;;;;;66383:62:0;27520:15;-1:-1:-1;;;;;66383:62:0;;;66361:127;;;;-1:-1:-1;;;66361:127:0;;12388:2:1;66361:127:0;;;12370:21:1;12427:2;12407:18;;;12400:30;-1:-1:-1;;;12446:18:1;;;12439:45;12501:18;;66361:127:0;12186:339:1;66361:127:0;-1:-1:-1;;;;;66507:15:0;;;66499:44;;;;-1:-1:-1;;;66499:44:0;;19532:2:1;66499:44:0;;;19514:21:1;19571:2;19551:18;;;19544:30;-1:-1:-1;;;19590:18:1;;;19583:46;19646:18;;66499:44:0;19330:340:1;66499:44:0;66597:14;66614:16;66622:7;66614;:16::i;:::-;66597:33;;66641:48;66654:10;66674:4;66681:7;66641:12;:48::i;:::-;66700:14;66706:7;66700:5;:14::i;:::-;66784:24;;;;66819:44;;-1:-1:-1;;;66819:44:0;;-1:-1:-1;;;;;19867:32:1;;;66819:44:0;;;19849:51:1;19916:18;;;19909:34;;;66784:24:0;;-1:-1:-1;66819:11:0;:20;;;;;;19822:18:1;;66819:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;66908:22:0;;;:47;;-1:-1:-1;;;;66908:47:0;-1:-1:-1;;;27520:15:0;-1:-1:-1;;;;;66908:47:0;;;;;66973:31;;2006:25:1;;;66980:7:0;;66973:31;;1994:2:1;1979:18;66973:31:0;;;;;;;65881:1131;;;;;65806:1206;;;:::o;63126:489::-;73669:10;73649:31;;;;:19;:31;;;;;;;;73641:58;;;;-1:-1:-1;;;73641:58:0;;14576:2:1;73641:58:0;;;14558:21:1;14615:2;14595:18;;;14588:30;-1:-1:-1;;;14634:18:1;;;14627:44;14688:18;;73641:58:0;14374:338:1;73641:58:0;63251:29:::1;63275:4;63251:23;:29::i;:::-;63293:31;63327:18:::0;;;:12:::1;:18;::::0;;;;;;;63399:132;;;;::::1;::::0;;-1:-1:-1;;;;;63399:132:0;;::::1;::::0;;;27520:15;63399:132;::::1;::::0;;::::1;::::0;;;63356:23:::1;::::0;::::1;:186:::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;::::1;::::0;;;;;::::1;-1:-1:-1::0;;;63356:186:0::1;-1:-1:-1::0;;;;;;63356:186:0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;63560:47;;20127:25:1;;;20168:18;;;20161:59;;;;63560:47:0::1;::::0;20100:18:1;63560:47:0::1;19954:272:1::0;67020:124:0;67072:20;67112:24;67128:7;67112:15;:24::i;73473:125::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;73554:28:0::1;73585:5;73554:28:::0;;;:19:::1;:28;::::0;;;;:36;;-1:-1:-1;;73554:36:0::1;::::0;;73473:125::o;70335:275::-;70444:20;;70482:121;70502:19;;;70482:121;;;70559:32;70579:8;;70588:1;70579:11;;;;;;;:::i;:::-;;;;;;;70559:19;:32::i;:::-;70543:48;;;;:::i;:::-;;-1:-1:-1;70523:3:0;;;;:::i;:::-;;;;70482:121;;;;70335:275;;;;:::o;12517:214::-;-1:-1:-1;;;;;12688:25:0;;;12659:4;12688:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;12517:214::o;2010:238::-;1334:10;1323:7;1176:6;;-1:-1:-1;;;;;1176:6:0;;1103:87;1323:7;-1:-1:-1;;;;;1323:21:0;;1315:66;;;;-1:-1:-1;;;1315:66:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2113:22:0;::::1;2091:110;;;::::0;-1:-1:-1;;;2091:110:0;;20433:2:1;2091:110:0::1;::::0;::::1;20415:21:1::0;20472:2;20452:18;;;20445:30;20511:34;20491:18;;;20484:62;-1:-1:-1;;;20562:18:1;;;20555:36;20608:19;;2091:110:0::1;20231:402:1::0;2091:110:0::1;2212:28;2231:8;2212:18;:28::i;:::-;2010:238:::0;:::o;27293:136::-;27350:6;27384:25;27402:7;27384:15;:25;:::i;:::-;27383:37;;27413:7;27383:37;:::i;:::-;27369:52;;27293:136;:::o;27437:107::-;27520:15;;27437:107::o;16604:174::-;16679:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;16679:29:0;-1:-1:-1;;;;;16679:29:0;;;;;;;;:24;;16733:23;16679:24;16733:14;:23::i;:::-;-1:-1:-1;;;;;16724:46:0;;;;;;;;;;;16604:174;;:::o;13779:452::-;13908:4;13574:16;;;:7;:16;;;;;;-1:-1:-1;;;;;13574:16:0;13930:110;;;;-1:-1:-1;;;13930:110:0;;20840:2:1;13930:110:0;;;20822:21:1;20879:2;20859:18;;;20852:30;20918:34;20898:18;;;20891:62;-1:-1:-1;;;20969:18:1;;;20962:42;21021:19;;13930:110:0;20638:408:1;13930:110:0;14051:13;14067:23;14082:7;14067:14;:23::i;:::-;14051:39;;14120:5;-1:-1:-1;;;;;14109:16:0;:7;-1:-1:-1;;;;;14109:16:0;;:64;;;;14166:7;-1:-1:-1;;;;;14142:31:0;:20;14154:7;14142:11;:20::i;:::-;-1:-1:-1;;;;;14142:31:0;;14109:64;:113;;;;14190:32;14207:5;14214:7;14190:16;:32::i;:::-;14101:122;13779:452;-1:-1:-1;;;;13779:452:0:o;15875:611::-;16048:4;-1:-1:-1;;;;;16021:31:0;:23;16036:7;16021:14;:23::i;:::-;-1:-1:-1;;;;;16021:31:0;;15999:118;;;;-1:-1:-1;;;15999:118:0;;21253:2:1;15999:118:0;;;21235:21:1;21292:2;21272:18;;;21265:30;21331:34;21311:18;;;21304:62;-1:-1:-1;;;21382:18:1;;;21375:35;21427:19;;15999:118:0;21051:401:1;15999:118:0;-1:-1:-1;;;;;16136:16:0;;16128:65;;;;-1:-1:-1;;;16128:65:0;;21659:2:1;16128:65:0;;;21641:21:1;21698:2;21678:18;;;21671:30;21737:34;21717:18;;;21710:62;-1:-1:-1;;;21788:18:1;;;21781:34;21832:19;;16128:65:0;21457:400:1;16128:65:0;16206:39;16227:4;16233:2;16237:7;16206:20;:39::i;:::-;16310:29;16327:1;16331:7;16310:8;:29::i;:::-;-1:-1:-1;;;;;16352:15:0;;;;;;:9;:15;;;;;:20;;16371:1;;16352:15;:20;;16371:1;;16352:20;:::i;:::-;;;;-1:-1:-1;;;;;;;16383:13:0;;;;;;:9;:13;;;;;:18;;16400:1;;16383:13;:18;;16400:1;;16383:18;:::i;:::-;;;;-1:-1:-1;;16412:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;16412:21:0;-1:-1:-1;;;;;16412:21:0;;;;;;;;;16451:27;;16412:16;;16451:27;;;;;;;15875:611;;;:::o;67459:975::-;67609:16;;67537:20;;-1:-1:-1;;;;;67609:16:0;27520:15;-1:-1:-1;;;;;67583:42:0;;;67575:70;;;;-1:-1:-1;;;67575:70:0;;22064:2:1;67575:70:0;;;22046:21:1;22103:2;22083:18;;;22076:30;-1:-1:-1;;;22122:18:1;;;22115:45;22177:18;;67575:70:0;21862:339:1;67575:70:0;67656:38;67686:7;67656:29;:38::i;:::-;67722:28;67742:7;67722:19;:28::i;:::-;67707:43;-1:-1:-1;67767:16:0;;67763:664;;67838:11;-1:-1:-1;;;;;67838:16:0;;67855;67863:7;67855;:16::i;:::-;67838:48;;-1:-1:-1;;;;;;67838:48:0;;;;;;;-1:-1:-1;;;;;19867:32:1;;;67838:48:0;;;19849:51:1;19916:18;;;19909:34;;;19822:18;;67838:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;67939:31:0;67973:21;;;:12;:21;;;;;;-1:-1:-1;68039:29:0;:27;:29::i;:::-;68009:11;:27;;;:59;;;;;-1:-1:-1;;;;;68009:59:0;;;;;-1:-1:-1;;;;;68009:59:0;;;;;;68123:12;68083:11;:36;;;:52;;;;;;;:::i;:::-;;;;-1:-1:-1;;68258:23:0;;68193:31;68227:69;;;:12;:69;;;;;68311:36;;;:52;;68227:69;;68351:12;;68311:52;;68351:12;;68311:52;:::i;:::-;;;;-1:-1:-1;;68385:30:0;;2006:25:1;;;68393:7:0;;68385:30;;1994:2:1;1979:18;68385:30:0;;;;;;;67785:642;;67763:664;67459:975;;;:::o;72959:141::-;73068:10;73048:16;73056:7;73048;:16::i;:::-;-1:-1:-1;;;;;73048:30:0;;73040:52;;;;-1:-1:-1;;;73040:52:0;;22408:2:1;73040:52:0;;;22390:21:1;22447:1;22427:18;;;22420:29;-1:-1:-1;;;22465:18:1;;;22458:39;22514:18;;73040:52:0;22206:332:1;73108:204:0;73209:25;;;;:12;:25;;;;;:39;;;-1:-1:-1;;;73209:39:0;;-1:-1:-1;;;;;73209:39:0;:44;73187:117;;;;-1:-1:-1;;;73187:117:0;;22745:2:1;73187:117:0;;;22727:21:1;22784:2;22764:18;;;22757:30;22823:25;22803:18;;;22796:53;22866:18;;73187:117:0;22543:347:1;25869:592:0;25980:21;26023:15;26019:435;;-1:-1:-1;;;;26019:435:0;;;26098:10;26112:1;26098:15;26094:360;;;-1:-1:-1;26146:13:0;26094:360;;;26208:39;26217:13;26232:14;26245:1;26232:10;:14;:::i;:::-;26208:8;:39::i;:::-;26192:55;;26278:36;26285:13;26300;26278:6;:36::i;:::-;26262:52;-1:-1:-1;26335:14:0;26348:1;26335:10;:14;:::i;:::-;26353:1;26335:19;26331:112;;;26391:36;26398:13;26413;26771:108;26832:9;26869:2;26859:5;26863:1;26859;:5;:::i;:::-;26858:13;;;26771:108;-1:-1:-1;;;26771:108:0:o;14567:382::-;-1:-1:-1;;;;;14647:16:0;;14639:61;;;;-1:-1:-1;;;14639:61:0;;23214:2:1;14639:61:0;;;23196:21:1;;;23233:18;;;23226:30;23292:34;23272:18;;;23265:62;23344:18;;14639:61:0;23012:356:1;14639:61:0;13550:4;13574:16;;;:7;:16;;;;;;-1:-1:-1;;;;;13574:16:0;:30;14711:58;;;;-1:-1:-1;;;14711:58:0;;23575:2:1;14711:58:0;;;23557:21:1;23614:2;23594:18;;;23587:30;23653;23633:18;;;23626:58;23701:18;;14711:58:0;23373:352:1;14711:58:0;14782:45;14811:1;14815:2;14819:7;14782:20;:45::i;:::-;-1:-1:-1;;;;;14840:13:0;;;;;;:9;:13;;;;;:18;;14857:1;;14840:13;:18;;14857:1;;14840:18;:::i;:::-;;;;-1:-1:-1;;14869:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;14869:21:0;-1:-1:-1;;;;;14869:21:0;;;;;;;;14908:33;;14869:16;;;14908:33;;14869:16;;14908:33;14567:382;;:::o;2408:191::-;2501:6;;;-1:-1:-1;;;;;2518:17:0;;;-1:-1:-1;;;;;;2518:17:0;;;;;;;2551:40;;2501:6;;;2518:17;2501:6;;2551:40;;2482:16;;2551:40;2471:128;2408:191;:::o;16920:315::-;17075:8;-1:-1:-1;;;;;17066:17:0;:5;-1:-1:-1;;;;;17066:17:0;;;17058:55;;;;-1:-1:-1;;;17058:55:0;;23932:2:1;17058:55:0;;;23914:21:1;23971:2;23951:18;;;23944:30;24010:27;23990:18;;;23983:55;24055:18;;17058:55:0;23730:349:1;17058:55:0;-1:-1:-1;;;;;17124:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;17124:46:0;;;;;;;;;;17186:41;;2373::1;;;17186::0;;2346:18:1;17186:41:0;;;;;;;16920:315;;;:::o;6661:723::-;6717:13;6938:10;6934:53;;-1:-1:-1;;6965:10:0;;;;;;;;;;;;-1:-1:-1;;;6965:10:0;;;;;6661:723::o;6934:53::-;7012:5;6997:12;7053:78;7060:9;;7053:78;;7086:8;;;;:::i;:::-;;-1:-1:-1;7109:10:0;;-1:-1:-1;7117:2:0;7109:10;;:::i;:::-;;;7053:78;;;7141:19;7173:6;-1:-1:-1;;;;;7163:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7163:17:0;;7141:39;;7191:154;7198:10;;7191:154;;7225:11;7235:1;7225:11;;:::i;:::-;;-1:-1:-1;7294:10:0;7302:2;7294:5;:10;:::i;:::-;7281:24;;:2;:24;:::i;:::-;7268:39;;7251:6;7258;7251:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;7251:56:0;;;;;;;;-1:-1:-1;7322:11:0;7331:2;7322:11;;:::i;:::-;;;7191:154;;15178:360;15238:13;15254:23;15269:7;15254:14;:23::i;:::-;15238:39;;15290:48;15311:5;15326:1;15330:7;15290:20;:48::i;:::-;15379:29;15396:1;15400:7;15379:8;:29::i;:::-;-1:-1:-1;;;;;15421:16:0;;;;;;:9;:16;;;;;:21;;15441:1;;15421:16;:21;;15441:1;;15421:21;:::i;:::-;;;;-1:-1:-1;;15460:16:0;;;;:7;:16;;;;;;15453:23;;-1:-1:-1;;;;;;15453:23:0;;;15494:36;15468:7;;15460:16;-1:-1:-1;;;;;15494:36:0;;;;;15460:16;;15494:36;15227:311;15178:360;:::o;21321:589::-;-1:-1:-1;;;;;21527:18:0;;21523:187;;21562:40;21594:7;22737:10;:17;;22710:24;;;;:15;:24;;;;;:44;;;22765:24;;;;;;;;;;;;22633:164;21562:40;21523:187;;;21632:2;-1:-1:-1;;;;;21624:10:0;:4;-1:-1:-1;;;;;21624:10:0;;21620:90;;21651:47;21684:4;21690:7;21651:32;:47::i;:::-;-1:-1:-1;;;;;21724:16:0;;21720:183;;21757:45;21794:7;21757:36;:45::i;21720:183::-;21830:4;-1:-1:-1;;;;;21824:10:0;:2;-1:-1:-1;;;;;21824:10:0;;21820:83;;21851:40;21879:2;21883:7;21851:27;:40::i;23424:1002::-;23704:22;23754:1;23729:22;23746:4;23729:16;:22::i;:::-;:26;;;;:::i;:::-;23766:18;23787:26;;;:17;:26;;;;;;23704:51;;-1:-1:-1;23920:28:0;;;23916:328;;-1:-1:-1;;;;;23987:18:0;;23965:19;23987:18;;;:12;:18;;;;;;;;:34;;;;;;;;;24038:30;;;;;;:44;;;24155:30;;:17;:30;;;;;:43;;;23916:328;-1:-1:-1;24340:26:0;;;;:17;:26;;;;;;;;24333:33;;;-1:-1:-1;;;;;24384:18:0;;;;;:12;:18;;;;;:34;;;;;;;24377:41;23424:1002::o;24721:1079::-;24999:10;:17;24974:22;;24999:21;;25019:1;;24999:21;:::i;:::-;25031:18;25052:24;;;:15;:24;;;;;;25425:10;:26;;24974:46;;-1:-1:-1;25052:24:0;;24974:46;;25425:26;;;;;;:::i;:::-;;;;;;;;;25403:48;;25489:11;25464:10;25475;25464:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;25569:28;;;:15;:28;;;;;;;:41;;;25741:24;;;;;25734:31;25776:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;24792:1008;;;24721:1079;:::o;22211:221::-;22296:14;22313:20;22330:2;22313:16;:20::i;:::-;-1:-1:-1;;;;;22344:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;22389:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;22211:221:0:o;14:258:1:-;86:1;96:113;110:6;107:1;104:13;96:113;;;186:11;;;180:18;167:11;;;160:39;132:2;125:10;96:113;;;227:6;224:1;221:13;218:48;;;262:1;253:6;248:3;244:16;237:27;218:48;;14:258;;;:::o;277:383::-;426:2;415:9;408:21;389:4;458:6;452:13;501:6;496:2;485:9;481:18;474:34;517:66;576:6;571:2;560:9;556:18;551:2;543:6;539:15;517:66;:::i;:::-;644:2;623:15;-1:-1:-1;;619:29:1;604:45;;;;651:2;600:54;;277:383;-1:-1:-1;;277:383:1:o;665:180::-;724:6;777:2;765:9;756:7;752:23;748:32;745:52;;;793:1;790;783:12;745:52;-1:-1:-1;816:23:1;;665:180;-1:-1:-1;665:180:1:o;1058:173::-;1126:20;;-1:-1:-1;;;;;1175:31:1;;1165:42;;1155:70;;1221:1;1218;1211:12;1236:254;1304:6;1312;1365:2;1353:9;1344:7;1340:23;1336:32;1333:52;;;1381:1;1378;1371:12;1333:52;1404:29;1423:9;1404:29;:::i;:::-;1394:39;1480:2;1465:18;;;;1452:32;;-1:-1:-1;;;1236:254:1:o;1495:171::-;1562:20;;-1:-1:-1;;;;;1611:30:1;;1601:41;;1591:69;;1656:1;1653;1646:12;1671:184;1729:6;1782:2;1770:9;1761:7;1757:23;1753:32;1750:52;;;1798:1;1795;1788:12;1750:52;1821:28;1839:9;1821:28;:::i;2042:186::-;2101:6;2154:2;2142:9;2133:7;2129:23;2125:32;2122:52;;;2170:1;2167;2160:12;2122:52;2193:29;2212:9;2193:29;:::i;2425:328::-;2502:6;2510;2518;2571:2;2559:9;2550:7;2546:23;2542:32;2539:52;;;2587:1;2584;2577:12;2539:52;2610:29;2629:9;2610:29;:::i;:::-;2600:39;;2658:38;2692:2;2681:9;2677:18;2658:38;:::i;:::-;2648:48;;2743:2;2732:9;2728:18;2715:32;2705:42;;2425:328;;;;;:::o;2758:367::-;2821:8;2831:6;2885:3;2878:4;2870:6;2866:17;2862:27;2852:55;;2903:1;2900;2893:12;2852:55;-1:-1:-1;2926:20:1;;-1:-1:-1;;;;;2958:30:1;;2955:50;;;3001:1;2998;2991:12;2955:50;3038:4;3030:6;3026:17;3014:29;;3098:3;3091:4;3081:6;3078:1;3074:14;3066:6;3062:27;3058:38;3055:47;3052:67;;;3115:1;3112;3105:12;3052:67;2758:367;;;;;:::o;3130:437::-;3216:6;3224;3277:2;3265:9;3256:7;3252:23;3248:32;3245:52;;;3293:1;3290;3283:12;3245:52;3333:9;3320:23;-1:-1:-1;;;;;3358:6:1;3355:30;3352:50;;;3398:1;3395;3388:12;3352:50;3437:70;3499:7;3490:6;3479:9;3475:22;3437:70;:::i;:::-;3526:8;;3411:96;;-1:-1:-1;3130:437:1;-1:-1:-1;;;;3130:437:1:o;3572:581::-;3674:6;3682;3690;3698;3751:2;3739:9;3730:7;3726:23;3722:32;3719:52;;;3767:1;3764;3757:12;3719:52;3807:9;3794:23;-1:-1:-1;;;;;3832:6:1;3829:30;3826:50;;;3872:1;3869;3862:12;3826:50;3911:70;3973:7;3964:6;3953:9;3949:22;3911:70;:::i;:::-;4000:8;;-1:-1:-1;3885:96:1;-1:-1:-1;4054:37:1;;-1:-1:-1;4087:2:1;4072:18;;4054:37;:::i;:::-;4044:47;;4110:37;4143:2;4132:9;4128:18;4110:37;:::i;:::-;4100:47;;3572:581;;;;;;;:::o;4158:324::-;4233:6;4241;4249;4302:2;4290:9;4281:7;4277:23;4273:32;4270:52;;;4318:1;4315;4308:12;4270:52;4354:9;4341:23;4331:33;;4383:37;4416:2;4405:9;4401:18;4383:37;:::i;:::-;4373:47;;4439:37;4472:2;4461:9;4457:18;4439:37;:::i;:::-;4429:47;;4158:324;;;;;:::o;4487:248::-;4555:6;4563;4616:2;4604:9;4595:7;4591:23;4587:32;4584:52;;;4632:1;4629;4622:12;4584:52;-1:-1:-1;;4655:23:1;;;4725:2;4710:18;;;4697:32;;-1:-1:-1;4487:248:1:o;4740:322::-;4817:6;4825;4833;4886:2;4874:9;4865:7;4861:23;4857:32;4854:52;;;4902:1;4899;4892:12;4854:52;4925:29;4944:9;4925:29;:::i;:::-;4915:39;5001:2;4986:18;;4973:32;;-1:-1:-1;5052:2:1;5037:18;;;5024:32;;4740:322;-1:-1:-1;;;4740:322:1:o;6055:118::-;6141:5;6134:13;6127:21;6120:5;6117:32;6107:60;;6163:1;6160;6153:12;6178:315;6243:6;6251;6304:2;6292:9;6283:7;6279:23;6275:32;6272:52;;;6320:1;6317;6310:12;6272:52;6343:29;6362:9;6343:29;:::i;:::-;6333:39;;6422:2;6411:9;6407:18;6394:32;6435:28;6457:5;6435:28;:::i;:::-;6482:5;6472:15;;;6178:315;;;;;:::o;6498:393::-;6582:6;6590;6598;6606;6659:3;6647:9;6638:7;6634:23;6630:33;6627:53;;;6676:1;6673;6666:12;6627:53;6712:9;6699:23;6689:33;;6741:37;6774:2;6763:9;6759:18;6741:37;:::i;:::-;6731:47;;6825:2;6814:9;6810:18;6797:32;6787:42;;6848:37;6881:2;6870:9;6866:18;6848:37;:::i;6896:252::-;6963:6;6971;7024:2;7012:9;7003:7;6999:23;6995:32;6992:52;;;7040:1;7037;7030:12;6992:52;7076:9;7063:23;7053:33;;7105:37;7138:2;7127:9;7123:18;7105:37;:::i;:::-;7095:47;;6896:252;;;;;:::o;7153:260::-;7221:6;7229;7282:2;7270:9;7261:7;7257:23;7253:32;7250:52;;;7298:1;7295;7288:12;7250:52;7321:29;7340:9;7321:29;:::i;:::-;7311:39;;7369:38;7403:2;7392:9;7388:18;7369:38;:::i;8095:380::-;8174:1;8170:12;;;;8217;;;8238:61;;8292:4;8284:6;8280:17;8270:27;;8238:61;8345:2;8337:6;8334:14;8314:18;8311:38;8308:161;;;8391:10;8386:3;8382:20;8379:1;8372:31;8426:4;8423:1;8416:15;8454:4;8451:1;8444:15;8308:161;;8095:380;;;:::o;9720:356::-;9922:2;9904:21;;;9941:18;;;9934:30;10000:34;9995:2;9980:18;;9973:62;10067:2;10052:18;;9720:356::o;10499:127::-;10560:10;10555:3;10551:20;10548:1;10541:31;10591:4;10588:1;10581:15;10615:4;10612:1;10605:15;10631:127;10692:10;10687:3;10683:20;10680:1;10673:31;10723:4;10720:1;10713:15;10747:4;10744:1;10737:15;10763:128;10803:3;10834:1;10830:6;10827:1;10824:13;10821:39;;;10840:18;;:::i;:::-;-1:-1:-1;10876:9:1;;10763:128::o;10896:135::-;10935:3;-1:-1:-1;;10956:17:1;;10953:43;;;10976:18;;:::i;:::-;-1:-1:-1;11023:1:1;11012:13;;10896:135::o;11036:559::-;11253:2;11235:21;;;11272:18;;11265:34;;;-1:-1:-1;;;;;;11311:31:1;;11308:51;;;11355:1;11352;11345:12;11308:51;11389:6;11386:1;11382:14;11446:6;11438;11433:2;11422:9;11418:18;11405:48;11523:1;11476:22;;;11500:2;11472:31;11512:13;;;11575:4;11560:20;;;11553:36;;;;11472:31;11036:559;-1:-1:-1;;;11036:559:1:o;11945:236::-;11984:3;-1:-1:-1;;;;;12057:2:1;12054:1;12050:10;12087:2;12084:1;12080:10;12118:3;12114:2;12110:12;12105:3;12102:21;12099:47;;;12126:18;;:::i;:::-;12162:13;;11945:236;-1:-1:-1;;;;11945:236:1:o;12530:125::-;12570:4;12598:1;12595;12592:8;12589:34;;;12603:18;;:::i;:::-;-1:-1:-1;12640:9:1;;12530:125::o;13826:136::-;13865:3;13893:5;13883:39;;13902:18;;:::i;:::-;-1:-1:-1;;;13938:18:1;;13826:136::o;13967:229::-;14006:4;-1:-1:-1;;;;;14103:10:1;;;;14073;;14125:12;;;14122:38;;;14140:18;;:::i;:::-;14177:13;;13967:229;-1:-1:-1;;;13967:229:1:o;14201:168::-;14241:7;14307:1;14303;14299:6;14295:14;14292:1;14289:21;14284:1;14277:9;14270:17;14266:45;14263:71;;;14314:18;;:::i;:::-;-1:-1:-1;14354:9:1;;14201:168::o;15380:127::-;15441:10;15436:3;15432:20;15429:1;15422:31;15472:4;15469:1;15462:15;15496:4;15493:1;15486:15;15512:199;15551:1;-1:-1:-1;;;;;15622:2:1;15619:1;15615:10;15644:3;15634:37;;15651:18;;:::i;:::-;15689:10;;15685:20;;;;;15512:199;-1:-1:-1;;15512:199:1:o;15716:120::-;15756:1;15782;15772:35;;15787:18;;:::i;:::-;-1:-1:-1;15821:9:1;;15716:120::o;16561:245::-;16628:6;16681:2;16669:9;16660:7;16656:23;16652:32;16649:52;;;16697:1;16694;16687:12;16649:52;16729:9;16723:16;16748:28;16770:5;16748:28;:::i;18514:470::-;18693:3;18731:6;18725:13;18747:53;18793:6;18788:3;18781:4;18773:6;18769:17;18747:53;:::i;:::-;18863:13;;18822:16;;;;18885:57;18863:13;18822:16;18919:4;18907:17;;18885:57;:::i;22895:112::-;22927:1;22953;22943:35;;22958:18;;:::i;:::-;-1:-1:-1;22992:9:1;;22895:112::o;24084:127::-;24145:10;24140:3;24136:20;24133:1;24126:31;24176:4;24173:1;24166:15;24200:4;24197:1;24190:15;24216:127;24277:10;24272:3;24268:20;24265:1;24258:31;24308:4;24305:1;24298:15;24332:4;24329:1;24322:15

Swarm Source

ipfs://d8f1d551ba3775a6fd9e5ef21c2fe7c5d88f0096e85b8b67e0c408e82308f6bc
Loading...
Loading
Loading...
Loading
[ 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.