ETH Price: $3,207.05 (-3.45%)

Token

BabySkulls $BONE ($BONE)
 

Overview

Max Total Supply

1,000,000 $BONE

Holders

18

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 4 Decimals)

Balance
100 $BONE

Value
$0.00
0x2c917c710595870e4d8c8559002a25cecc51f7d6
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:
BONE

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-11-16
*/

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


// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

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

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

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

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

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


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @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 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 Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;


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

    /**
     * @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: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @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);
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol)

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

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

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

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

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

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

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// File: @openzeppelin/contracts/governance/utils/IVotes.sol


// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

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

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

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

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

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`.
        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
        // good first aproximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1;
        uint256 x = a;
        if (x >> 128 > 0) {
            x >>= 128;
            result <<= 64;
        }
        if (x >> 64 > 0) {
            x >>= 64;
            result <<= 32;
        }
        if (x >> 32 > 0) {
            x >>= 32;
            result <<= 16;
        }
        if (x >> 16 > 0) {
            x >>= 16;
            result <<= 8;
        }
        if (x >> 8 > 0) {
            x >>= 8;
            result <<= 4;
        }
        if (x >> 4 > 0) {
            x >>= 4;
            result <<= 2;
        }
        if (x >> 2 > 0) {
            result <<= 1;
        }

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        uint256 result = sqrt(a);
        if (rounding == Rounding.Up && result * result < a) {
            result += 1;
        }
        return result;
    }
}

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


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

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

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

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


// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @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: @openzeppelin/contracts/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;


/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

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

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

// File: @openzeppelin/contracts/utils/cryptography/draft-EIP712.sol


// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;


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

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

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

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

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

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

// File: @openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

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


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: @openzeppelin/contracts/token/ERC721/ERC721.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;








/**
 * @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 Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // 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_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @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 Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @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(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "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(_msgSender(), 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(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @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 Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

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

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

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

        _afterTokenTransfer(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 Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

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

    /**
     * @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.
     * - `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 tokenId
    ) internal virtual {}
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;



/**
 * @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 {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @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: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

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 is Context {
    address private _owner;

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

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

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() private 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: @openzeppelin/contracts/security/Pausable.sol


// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;


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

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

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

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

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

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

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

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

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


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

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


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;




/**
 * @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 Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @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_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override 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 override returns (uint8) {
        return 18;
    }

    /**
     * @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:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, 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) {
        address owner = _msgSender();
        _approve(owner, 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:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, 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) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, 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) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * 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:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, 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 Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - 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: @openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

pragma solidity ^0.8.0;






/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

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

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

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

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

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

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

        _approve(owner, spender, value);
    }

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

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

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)

pragma solidity ^0.8.0;






/**
 * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
 * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
 *
 * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
 *
 * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
 * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
 * power can be queried through the public accessors {getVotes} and {getPastVotes}.
 *
 * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
 * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
 *
 * _Available since v4.2._
 */
abstract contract ERC20Votes is IVotes, ERC20Permit {
    struct Checkpoint {
        uint32 fromBlock;
        uint224 votes;
    }

    bytes32 private constant _DELEGATION_TYPEHASH =
        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    mapping(address => address) private _delegates;
    mapping(address => Checkpoint[]) private _checkpoints;
    Checkpoint[] private _totalSupplyCheckpoints;

    /**
     * @dev Get the `pos`-th checkpoint for `account`.
     */
    function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
        return _checkpoints[account][pos];
    }

    /**
     * @dev Get number of checkpoints for `account`.
     */
    function numCheckpoints(address account) public view virtual returns (uint32) {
        return SafeCast.toUint32(_checkpoints[account].length);
    }

    /**
     * @dev Get the address `account` is currently delegating to.
     */
    function delegates(address account) public view virtual override returns (address) {
        return _delegates[account];
    }

    /**
     * @dev Gets the current votes balance for `account`
     */
    function getVotes(address account) public view virtual override returns (uint256) {
        uint256 pos = _checkpoints[account].length;
        return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
    }

    /**
     * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_checkpoints[account], blockNumber);
    }

    /**
     * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.
     * It is but NOT the sum of all the delegated votes!
     *
     * Requirements:
     *
     * - `blockNumber` must have been already mined
     */
    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
    }

    /**
     * @dev Lookup a value in a list of (sorted) checkpoints.
     */
    function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
        // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
        //
        // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
        // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
        // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
        // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)
        // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
        // out of bounds (in which case we're looking too far in the past and the result is 0).
        // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
        // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
        // the same.
        uint256 high = ckpts.length;
        uint256 low = 0;
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (ckpts[mid].fromBlock > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        return high == 0 ? 0 : ckpts[high - 1].votes;
    }

    /**
     * @dev Delegate votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) public virtual override {
        _delegate(_msgSender(), delegatee);
    }

    /**
     * @dev Delegates votes from signer to `delegatee`
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= expiry, "ERC20Votes: signature expired");
        address signer = ECDSA.recover(
            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
            v,
            r,
            s
        );
        require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
        _delegate(signer, delegatee);
    }

    /**
     * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
     */
    function _maxSupply() internal view virtual returns (uint224) {
        return type(uint224).max;
    }

    /**
     * @dev Snapshots the totalSupply after it has been increased.
     */
    function _mint(address account, uint256 amount) internal virtual override {
        super._mint(account, amount);
        require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes");

        _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);
    }

    /**
     * @dev Snapshots the totalSupply after it has been decreased.
     */
    function _burn(address account, uint256 amount) internal virtual override {
        super._burn(account, amount);

        _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);
    }

    /**
     * @dev Move voting power when tokens are transferred.
     *
     * Emits a {DelegateVotesChanged} event.
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._afterTokenTransfer(from, to, amount);

        _moveVotingPower(delegates(from), delegates(to), amount);
    }

    /**
     * @dev Change delegation for `delegator` to `delegatee`.
     *
     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
     */
    function _delegate(address delegator, address delegatee) internal virtual {
        address currentDelegate = delegates(delegator);
        uint256 delegatorBalance = balanceOf(delegator);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        _moveVotingPower(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveVotingPower(
        address src,
        address dst,
        uint256 amount
    ) private {
        if (src != dst && amount > 0) {
            if (src != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);
                emit DelegateVotesChanged(src, oldWeight, newWeight);
            }

            if (dst != address(0)) {
                (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);
                emit DelegateVotesChanged(dst, oldWeight, newWeight);
            }
        }
    }

    function _writeCheckpoint(
        Checkpoint[] storage ckpts,
        function(uint256, uint256) view returns (uint256) op,
        uint256 delta
    ) private returns (uint256 oldWeight, uint256 newWeight) {
        uint256 pos = ckpts.length;
        oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;
        newWeight = op(oldWeight, delta);

        if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
            ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);
        } else {
            ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));
        }
    }

    function _add(uint256 a, uint256 b) private pure returns (uint256) {
        return a + b;
    }

    function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
        return a - b;
    }
}

// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.0;



/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        _spendAllowance(account, _msgSender(), amount);
        _burn(account, amount);
    }
}

// File: contracts/Bone.sol


pragma solidity ^0.8.7;









/// @custom:security-contact [email protected]
contract BONE is ERC20, ERC20Burnable, Pausable, Ownable, ERC20Permit, ERC20Votes {
    
    constructor() ERC20("BabySkulls $BONE", "$BONE") ERC20Permit("$BONE") {
        _mint(address(this), toDecimals(1000000));
    }

    bool private claimTokensPaused = false;
    bool private claimPromosPaused = false;

    uint256 private communityAirdropAmount = toDecimals(1000);

    mapping(uint => mapping(uint => bool)) private claimedToken;
    mapping(uint => mapping(string => uint256)) private claimedPromo;
    
    mapping(string => bool) private promos;
    mapping(string => uint256) private promosPrice;
    mapping(string => address) private promosAddress;
    mapping(string => string) private promosCurrency;

    uint256 priceCreatePromoETH = 0.1 ether;
    uint256 priceCreatePromoBONE = toDecimals(1000);
    uint percentagePromofee = 10;
    uint percentageDonationfee = 10;

    address payable fallbackAddress = payable(address(0x00F39aeb52CCCd1F62F3dc4bE30F00aB85597615));

    address payable BS_address = payable(address(0x30718f4e09873395b912B26eC2FA1bEFA2262c16));
    ERC721Enumerable private BS = ERC721Enumerable(BS_address);

    function changeBSNFTAddress(address newBSNFTAddress) public onlyOwner {
        BS_address = payable(newBSNFTAddress);
        BS = ERC721Enumerable(BS_address);
    }

    function setFallbackAddress(address payable newFallbackAddress) public onlyOwner {
        fallbackAddress = newFallbackAddress;
    }

    function setCommunityAirdropAmount(uint256 _newAirdropAmount) public {
        communityAirdropAmount = _newAirdropAmount;
    }

    function getCommunityAirdropAmount() public view returns (uint256) {
        return communityAirdropAmount;
    }

    function setPriceCreatePromoETH(uint256 _priceCreatePromoETH) public onlyOwner {
        priceCreatePromoETH = _priceCreatePromoETH;
    }

    function setPriceCreatePromoBONE(uint256 _priceCreatePromoBONE) public onlyOwner {
        priceCreatePromoBONE = _priceCreatePromoBONE;
    }

    function setPercentagePromofee(uint _percentagePromofee) public onlyOwner {
        percentagePromofee = _percentagePromofee;
    }

    function setPercentageDonationfee(uint _percentageDonationfee) public onlyOwner {
        percentageDonationfee = _percentageDonationfee;
    }

    function toDecimals(uint256 amount) private pure returns (uint256) {
        return amount * (10 ** decimals());
    }

    function fromDecimals(uint256 amount) private pure returns (uint256) {
        return amount / (10 ** decimals());
    }

    function decimals() public pure override returns (uint8) {
		return 4;
	}

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

    function unpause() public onlyOwner {
        _unpause();
    }

    function getTokenPrice() public view returns (uint256) {
        uint256 tokenPrice = address(this).balance / fromDecimals(totalSupply());
        return tokenPrice;
    }

    function transferContractBalance(uint256 amount, address to) public onlyOwner {
        require(payable(address(this)).balance >= amount, "NOT_ENOUGH_ETH");
        payable(to).transfer(amount);
    }

    function depositContractBalance() public payable onlyOwner returns (string memory) {
        require(msg.value > 0, "NO_ZERO_DEPOSITS");
        return "DEPOSITED";
    }

    function safeTransferFrom(address from, address to, uint256 amount) public onlyOwner {
        _transfer(from, to, amount);
    }

    function safeBurnFrom(address from, uint256 amount) public onlyOwner {
        _burn(from, amount);
    }

    modifier claimTokensNotPaused() {
        require(!claimTokensPaused, "CLAIM_PAUSED");
        _;
    }

    modifier claimPromosNotPaused() {
        require(!claimPromosPaused, "CLAIM_PAUSED");
        _;
    }

    function claimTokens() public claimTokensNotPaused returns (string memory) {
        uint256 bs_supply = BS.totalSupply();
        uint256 user_nft_balance = BS.balanceOf(msg.sender);
        uint256 tokens = 0;

        require(user_nft_balance > 0, "NO_NFTS");

        for(uint nft_index = 0; nft_index < user_nft_balance; nft_index++) {

            uint nft = BS.tokenOfOwnerByIndex(msg.sender, nft_index);

            if(claimedToken[nft][bs_supply] == true) {
                revert("ALREADY_CLAIMED");
            }

            for(uint256 supply_index = (bs_supply); supply_index > 0; supply_index--) {
                if(claimedToken[nft][supply_index] == true) {
                    break;
                }
                else {
                    if(supply_index >= nft) {
                        tokens = tokens + (communityAirdropAmount / supply_index);
                    }
                    else {
                        break;
                    }
                }
            }
            claimedToken[nft][bs_supply] = true;
        }
        _transfer(address(this), msg.sender, tokens);
        return "CLAIMED";
    }

    function tokensForClaim() public view returns (uint256) {
        uint256 user_nft_balance = BS.balanceOf(msg.sender);
        uint256 bs_supply = BS.totalSupply();
        uint256 tokens = 0;
        
        for(uint nft_index = 0; nft_index < user_nft_balance; nft_index++) {

            uint nft = BS.tokenOfOwnerByIndex(msg.sender, nft_index);

            if(claimedToken[nft][bs_supply] == true) {
                return 0;
            }

            for(uint256 supply_index = (bs_supply); supply_index > 0; supply_index--) {
                if(claimedToken[nft][supply_index] == true) {
                    break;
                }
                else {
                    if(supply_index >= nft) {
                        tokens = tokens + (communityAirdropAmount / supply_index);
                    }
                    else {
                        break;
                    }
                }
            }

        }
        return tokens;
    }

    function checkBoneForClaim(uint nft_id) public view returns (uint256) {
        require(BS.ownerOf(nft_id) != address(0), "NFT_NOT_EXISTS");
        uint256 bs_supply = BS.totalSupply();
        
        uint256 tokens = 0;
        uint nft = nft_id;

        if(claimedToken[nft][bs_supply] == true) {
            return 0;
        }

        for(uint256 supply_index = (bs_supply); supply_index > 0; supply_index--) {
            if(claimedToken[nft][supply_index] == true) {
                break;
            }
            else {
                if(supply_index >= nft) {
                    tokens = tokens + (communityAirdropAmount / supply_index);
                }
                else {
                    break;
                }
            }
        }
        return tokens;
    }

    function stringsEquals(string memory s1, string memory s2) private pure returns (bool) {
        bytes memory b1 = bytes(s1);
        bytes memory b2 = bytes(s2);
        uint256 l1 = b1.length;
        if (l1 != b2.length) return false;
        for (uint256 i=0; i<l1; i++) {
            if (b1[i] != b2[i]) return false;
        }
        return true;
    }

    function safeCreatePromo(string memory promo, string memory currency, uint256 price, address receiverAddress) public onlyOwner returns (string memory) {
        require(promos[promo] == false, "PROMO_EXISTS");
        require(stringsEquals(currency, "eth") || stringsEquals(currency, "bone"), "INVALID_CURRENCY");

        promos[promo] = true;
        promosPrice[promo] = price;
        promosCurrency[promo] = currency;
        promosAddress[promo] = receiverAddress;
        return "PROMO_CREATED";
    }

    function createPromo(string memory promo, string memory currency, uint256 price) public payable returns (string memory) {
        require(promos[promo] == false, "PROMO_EXISTS");
        require(stringsEquals(currency, "eth") || stringsEquals(currency, "bone"), "INVALID_CURRENCY");

        if(msg.value > 0) {
            require(msg.value >= priceCreatePromoETH, "NOT_ENOUGH_ETH_PAYMENT");
        }
        else {
            require(balanceOf(msg.sender) >= priceCreatePromoBONE, "NOT_ENOUGH_BONE");
            _transfer(msg.sender, address(this), priceCreatePromoBONE);
        }

        promos[promo] = true;
        promosPrice[promo] = price;
        promosCurrency[promo] = currency;
        promosAddress[promo] = msg.sender;
        return "PROMO_CREATED";
    }

    function safeEditPromo(string memory promo, bool active, uint256 price, string memory currency, address receiverAddress) public onlyOwner returns (string memory) {
        require(stringsEquals(currency, "eth") || stringsEquals(currency, "bone"), "INVALID_CURRENCY");

        promos[promo] = active;
        promosPrice[promo] = price;
        promosCurrency[promo] = currency;
        promosAddress[promo] = receiverAddress;
        return "PROMO_EDITED";
    }

    function editPromo(string memory promo, bool active, uint256 price, string memory currency, address receiverAddress) public returns (string memory) {
        require(promosAddress[promo] == msg.sender, "NOT_OWNER");
        require(stringsEquals(currency, "eth") || stringsEquals(currency, "bone"), "INVALID_CURRENCY");

        promos[promo] = active;
        promosPrice[promo] = price;
        promosCurrency[promo] = currency;
        promosAddress[promo] = receiverAddress;
        return "PROMO_EDITED";
    }

    function safeDeletePromo(string memory promo) public onlyOwner returns (string memory) {
        promos[promo] = false;
        promosPrice[promo] = 0;
        promosCurrency[promo] = "";
        promosAddress[promo] = address(0);
        return "PROMO_DELETED";
    }

    function deletePromo(string memory promo) public returns (string memory) {
        require(promosAddress[promo] == msg.sender, "NOT_OWNER");
        promos[promo] = false;
        promosPrice[promo] = 0;
        promosCurrency[promo] = "";
        promosAddress[promo] = address(0);
        return "PROMO_DELETED";
    }

    function getPromo(string memory promo) public view returns (uint256, string memory, address) {
        require(promos[promo] == true, "PROMO_NOT_EXISTS");
        return (promosPrice[promo], promosCurrency[promo], promosAddress[promo]);
    }

    function isPromoExist(string memory promo) public view returns (bool) {
        return promos[promo];
    }

    function claimPromo(uint nft_id, string memory promo) public payable claimPromosNotPaused returns (string memory) {
        address nft_owner = BS.ownerOf(nft_id);
        require(nft_owner == msg.sender, "NOT_NFT_OWNER");
        require(promos[promo], "PROMO_NOT_EXIST");

        if(claimedPromo[nft_id][promo] != 0) {
            revert("ALREADY_CLAIMED");
        }

        uint256 price = promosPrice[promo];
        string memory currency = promosCurrency[promo];

        if(price > 0) {
            if(stringsEquals(currency, "eth")) {
                require(msg.value >= price, "NOT_ENOUGH_ETH_PAYMENT");
                address receiverAddress = promosAddress[promo];
                uint256 promofee = SafeMath.mul(price, percentagePromofee) / 100;
                payable(receiverAddress).transfer(SafeMath.sub(price, promofee));
            }
            else if(stringsEquals(currency, "bone")) {
                require(balanceOf(msg.sender) >= price, "NOT_ENOUGH_BONE");
                address receiverAddress = promosAddress[promo];
                uint256 promofee = SafeMath.mul(price, percentagePromofee) / 100;
                _transfer(msg.sender, receiverAddress, SafeMath.sub(price, promofee));
            }
        }

        claimedPromo[nft_id][promo] = block.timestamp;
        return "CLAIMED";
    }

    function donate(address donateAddress, uint256 boneTokens) public payable returns (string memory) {
        require(msg.value > 0 || boneTokens > 0, "NO_ZERO_DONATIONS");
        address payable donateAddressPayable = payable(address(donateAddress));

        if(msg.value > 0) {
            uint256 fee = SafeMath.mul(msg.value, percentageDonationfee) / 100;
            uint256 sendFunds = SafeMath.sub(msg.value, fee);
            donateAddressPayable.transfer(sendFunds);
        }

        if(boneTokens > 0) {
            uint256 fee = SafeMath.mul(boneTokens, percentageDonationfee) / 100;
            uint256 sendTokens = SafeMath.sub(boneTokens, fee);
            _transfer(msg.sender, donateAddressPayable, sendTokens);
        }

        return "DONATED";
    }

    function isPromoClaimed(uint256 nft, string memory promo) public view returns (uint256) {
        return claimedPromo[nft][promo];
    }

    function pauseClaimTokens() public onlyOwner {
        require(!claimTokensPaused, "ALREADY_PAUSED");
        claimTokensPaused = true;
    }

    function unpauseClaimTokens() public onlyOwner {
        require(claimTokensPaused, "ALREADY_RUNNING");
        claimTokensPaused = false;
    }

    function pauseClaimPromos() public onlyOwner {
        require(!claimPromosPaused, "ALREADY_PAUSED");
        claimPromosPaused = true;
    }

    function unpauseClaimPromos() public onlyOwner {
        require(claimPromosPaused, "ALREADY_RUNNING");
        claimPromosPaused = false;
    }

    function safeIncreaseClaimAllowance(address to, uint256 amount) public onlyOwner {
        _approve(address(this), to, allowance(address(this), to) + amount);
    }

    function safeDecreaseClaimAllowance(address to, uint256 amount) public onlyOwner {
        _approve(address(this), to, allowance(address(this), to) - amount);
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override
    {
        super._beforeTokenTransfer(from, to, amount);
    }

    // The following functions are overrides required by Solidity.
    function _afterTokenTransfer(address from, address to, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._afterTokenTransfer(from, to, amount);
    }

    function _mint(address to, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._mint(to, amount);
    }

    function _burn(address account, uint256 amount)
        internal
        override(ERC20, ERC20Votes)
    {
        super._burn(account, amount);
    }

    fallback() external payable {
        
    }
    
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBSNFTAddress","type":"address"}],"name":"changeBSNFTAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nft_id","type":"uint256"}],"name":"checkBoneForClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint224","name":"votes","type":"uint224"}],"internalType":"struct ERC20Votes.Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nft_id","type":"uint256"},{"internalType":"string","name":"promo","type":"string"}],"name":"claimPromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimTokens","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"createPromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"}],"name":"deletePromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositContractBalance","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"donateAddress","type":"address"},{"internalType":"uint256","name":"boneTokens","type":"uint256"}],"name":"donate","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"address","name":"receiverAddress","type":"address"}],"name":"editPromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCommunityAirdropAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"}],"name":"getPromo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nft","type":"uint256"},{"internalType":"string","name":"promo","type":"string"}],"name":"isPromoClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"}],"name":"isPromoExist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseClaimPromos","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseClaimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"safeBurnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"receiverAddress","type":"address"}],"name":"safeCreatePromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"safeDecreaseClaimAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"}],"name":"safeDeletePromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"promo","type":"string"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"address","name":"receiverAddress","type":"address"}],"name":"safeEditPromo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"safeIncreaseClaimAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newAirdropAmount","type":"uint256"}],"name":"setCommunityAirdropAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newFallbackAddress","type":"address"}],"name":"setFallbackAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentageDonationfee","type":"uint256"}],"name":"setPercentageDonationfee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentagePromofee","type":"uint256"}],"name":"setPercentagePromofee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceCreatePromoBONE","type":"uint256"}],"name":"setPriceCreatePromoBONE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceCreatePromoETH","type":"uint256"}],"name":"setPriceCreatePromoETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensForClaim","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":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"transferContractBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseClaimPromos","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseClaimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]

610140604052600b805461ffff191690556200001d6103e862000224565b600c5567016345785d8a0000601355620000396103e862000224565b601455600a6015819055601655601780546001600160a01b031990811672f39aeb52cccd1f62f3dc4be30f00ab85597615179091556018805482167330718f4e09873395b912b26ec2fa1befa2262c1690811790915560198054909216179055348015620000a657600080fd5b506040518060400160405280600581526020016424424f4e4560d81b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280601081526020016f42616279536b756c6c732024424f4e4560801b8152506040518060400160405280600581526020016424424f4e4560d81b81525081600390805190602001906200013f9291906200090c565b508051620001559060049060208401906200090c565b50506005805460ff19169055506200016d3362000246565b815160209283012081519183019190912060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830196909652606081810195909552608080820194909452308184018190528251808303909401845260c0918201909252825192909601919091209091529081901b909252610120526200021e915062000218620f424062000224565b620002a0565b62000b70565b6000620002346004600a62000a0c565b62000240908362000acb565b92915050565b600580546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b620002b78282620002bb60201b6200310b1760201c565b5050565b620002d282826200037260201b6200319b1760201c565b6001600160e01b03620002e66200046f8216565b1115620003535760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b60648201526084015b60405180910390fd5b6200036c600a6200328e6200047560201b17836200048a565b50505050565b6001600160a01b038216620003ca5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016200034a565b620003d8600083836200063c565b8060026000828254620003ec9190620009a8565b90915550506001600160a01b038216600090815260208190526040812080548392906200041b908490620009a8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3620002b760008383620006a1565b60025490565b6000620004838284620009a8565b9392505050565b825460009081908015620004dc5785620004a660018362000aed565b81548110620004b957620004b962000b5a565b60009182526020909120015464010000000090046001600160e01b0316620004df565b60005b6001600160e01b03169250620004f683858760201c565b91506000811180156200053a575043866200051360018462000aed565b8154811062000526576200052662000b5a565b60009182526020909120015463ffffffff16145b15620005ae576200055682620006b960201b6200329a1760201c565b866200056460018462000aed565b8154811062000577576200057762000b5a565b9060005260206000200160000160046101000a8154816001600160e01b0302191690836001600160e01b0316021790555062000633565b856040518060400160405280620005d0436200072860201b620033071760201c565b63ffffffff168152602001620005f185620006b960201b6200329a1760201c565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b50935093915050565b60055460ff1615620006845760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016200034a565b6200069c8383836200069c60201b62001d351760201c565b505050565b6200069c8383836200078f60201b6200336c1760201c565b60006001600160e01b03821115620007245760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b60648201526084016200034a565b5090565b600063ffffffff821115620007245760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b60648201526084016200034a565b620007a78383836200069c60201b62001d351760201c565b6001600160a01b038381166000908152600860205260408082205485841683529120546200069c92918216911683818314801590620007e65750600081115b156200069c576001600160a01b0383161562000873576001600160a01b038316600090815260096020908152604082208291620008309190620008fe901b6200339e17856200048a565b91509150846001600160a01b031660008051602062005854833981519152838360405162000868929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156200069c576001600160a01b038216600090815260096020908152604082208291620008b7919062000475901b6200328e17856200048a565b91509150836001600160a01b0316600080516020620058548339815191528383604051620008ef929190918252602082015260400190565b60405180910390a25050505050565b600062000483828462000aed565b8280546200091a9062000b07565b90600052602060002090601f0160209004810192826200093e576000855562000989565b82601f106200095957805160ff191683800117855562000989565b8280016001018555821562000989579182015b82811115620009895782518255916020019190600101906200096c565b50620007249291505b8082111562000724576000815560010162000992565b60008219821115620009be57620009be62000b44565b500190565b600181815b8085111562000a04578160001904821115620009e857620009e862000b44565b80851615620009f657918102915b93841c9390800290620009c8565b509250929050565b60006200048360ff84168360008262000a285750600162000240565b8162000a375750600062000240565b816001811462000a50576002811462000a5b5762000a7b565b600191505062000240565b60ff84111562000a6f5762000a6f62000b44565b50506001821b62000240565b5060208310610133831016604e8410600b841016171562000aa0575081810a62000240565b62000aac8383620009c3565b806000190482111562000ac35762000ac362000b44565b029392505050565b600081600019048311821515161562000ae85762000ae862000b44565b500290565b60008282101562000b025762000b0262000b44565b500390565b600181811c9082168062000b1c57607f821691505b6020821081141562000b3e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160601c60e0516101005161012051614c9162000bc3600039600061384d0152600061389c01526000613877015260006137d0015260006137fa015260006138240152614c916000f3fe60806040526004361061038b5760003560e01c80635fbbae3f116101da578063a46a140011610101578063e69d849d1161009a578063f39459b81161006c578063f39459b814610aea578063f8ffd87b14610b0a578063fad4700614610b1f578063fe61700d14610b3f57005b8063e69d849d14610a4d578063eec74da614610a60578063f1127ed814610a80578063f2fde38b14610aca57005b8063d63565c1116100d3578063d63565c1146109cb578063d7a6a05e146109de578063dba35e38146109fe578063dd62ed3e14610a2d57005b8063a46a140014610956578063a9059cbb1461096b578063c3cda5201461098b578063d505accf146109ab57005b80638e539e8c1161017357806395d89b411161014557806395d89b41146108e157806399aaf21f146108f65780639ab24eb014610916578063a457c2d71461093657005b80638e539e8c146108795780639142376514610899578063928ec28c146108b957806393da92be146108c157005b806379cc6790116101ac57806379cc6790146108015780637ecebe00146108215780638456cb59146108415780638da5cb5b1461085657005b80635fbbae3f146107565780636fcfff451461077657806370a08231146107ab57806372e155c9146107e157005b80633a46b1a8116102be57806348c54b9d116102575780635b68930f116102295780635b68930f146106de5780635c19a95c146106fe5780635c975abb1461071e5780635ef8cd171461073657005b806348c54b9d146106435780634b94f50e146106585780634e190ad41461066d578063587cde1e1461068d57005b806340c10f191161029057806340c10f19146105c3578063419d031d146105e357806342842e0e1461060357806342966c681461062357005b80633a46b1a8146105665780633adc956a146105865780633f4ba83a146105995780634091688f146105ae57005b80631430c11b116103305780632b947531116103025780632b947531146104f5578063313ce567146105155780633644e51514610531578063395093511461054657005b80631430c11b1461048b57806318160ddd146104ab57806323b872dd146104c0578063260c6fdc146104e057005b8063095ea7b311610369578063095ea7b3146103ed5780630aa09dbb1461041d5780630c0148411461043d57806313777c241461045d57005b8063027c131d1461038d57806306fdde03146103a2578063087979ab146103cd575b005b34801561039957600080fd5b5061038b610b54565b3480156103ae57600080fd5b506103b7610be3565b6040516103c4919061495a565b60405180910390f35b3480156103d957600080fd5b506103b76103e83660046146eb565b610c75565b3480156103f957600080fd5b5061040d6104083660046145f1565b610e0f565b60405190151581526020016103c4565b34801561042957600080fd5b5061038b610438366004614874565b600c55565b34801561044957600080fd5b506103b76104583660046147f4565b610e29565b34801561046957600080fd5b5061047d610478366004614874565b611023565b6040519081526020016103c4565b34801561049757600080fd5b5061038b6104a6366004614874565b61121c565b3480156104b757600080fd5b5060025461047d565b3480156104cc57600080fd5b5061040d6104db366004614542565b611251565b3480156104ec57600080fd5b5061047d611275565b34801561050157600080fd5b506103b76105103660046146ae565b6114d4565b34801561052157600080fd5b50604051600481526020016103c4565b34801561053d57600080fd5b5061047d611611565b34801561055257600080fd5b5061040d6105613660046145f1565b611620565b34801561057257600080fd5b5061047d6105813660046145f1565b611642565b6103b76105943660046148cb565b6116bc565b3480156105a557600080fd5b5061038b611bc2565b3480156105ba57600080fd5b5061038b611bfc565b3480156105cf57600080fd5b5061038b6105de3660046145f1565b611c7c565b3480156105ef57600080fd5b5061038b6105fe3660046145f1565b611cba565b34801561060f57600080fd5b5061038b61061e366004614542565b611cfa565b34801561062f57600080fd5b5061038b61063e366004614874565b611d3a565b34801561064f57600080fd5b506103b7611d47565b34801561066457600080fd5b5061047d612095565b34801561067957600080fd5b5061038b6106883660046144cf565b6120b3565b34801561069957600080fd5b506106c66106a83660046144cf565b6001600160a01b039081166000908152600860205260409020541690565b6040516001600160a01b0390911681526020016103c4565b3480156106ea57600080fd5b5061047d6106f93660046148cb565b61210f565b34801561070a57600080fd5b5061038b6107193660046144cf565b612142565b34801561072a57600080fd5b5060055460ff1661040d565b34801561074257600080fd5b5061038b6107513660046145f1565b61214c565b34801561076257600080fd5b506103b76107713660046146ae565b612186565b34801561078257600080fd5b506107966107913660046144cf565b6121f4565b60405163ffffffff90911681526020016103c4565b3480156107b757600080fd5b5061047d6107c63660046144cf565b6001600160a01b031660009081526020819052604090205490565b3480156107ed57600080fd5b5061038b6107fc366004614874565b612216565b34801561080d57600080fd5b5061038b61081c3660046145f1565b61224b565b34801561082d57600080fd5b5061047d61083c3660046144cf565b612256565b34801561084d57600080fd5b5061038b612274565b34801561086257600080fd5b5060055461010090046001600160a01b03166106c6565b34801561088557600080fd5b5061047d610894366004614874565b6122ac565b3480156108a557600080fd5b5061038b6108b43660046144cf565b612308565b6103b761235a565b3480156108cd57600080fd5b5061038b6108dc366004614874565b6123f4565b3480156108ed57600080fd5b506103b7612429565b34801561090257600080fd5b506103b76109113660046146eb565b612438565b34801561092257600080fd5b5061047d6109313660046144cf565b6124a6565b34801561094257600080fd5b5061040d6109513660046145f1565b61252d565b34801561096257600080fd5b50600c5461047d565b34801561097757600080fd5b5061040d6109863660046145f1565b6125a8565b34801561099757600080fd5b5061038b6109a636600461461d565b6125b6565b3480156109b757600080fd5b5061038b6109c6366004614583565b6126ec565b6103b76109d9366004614787565b612850565b3480156109ea57600080fd5b5061038b6109f93660046148a6565b612ace565b348015610a0a57600080fd5b50610a1e610a193660046146ae565b612b76565b6040516103c4939291906149cc565b348015610a3957600080fd5b5061047d610a48366004614509565b612ce6565b6103b7610a5b3660046145f1565b612d11565b348015610a6c57600080fd5b5061038b610a7b366004614874565b612e32565b348015610a8c57600080fd5b50610aa0610a9b366004614677565b612e67565b60408051825163ffffffff1681526020928301516001600160e01b031692810192909252016103c4565b348015610ad657600080fd5b5061038b610ae53660046144cf565b612eeb565b348015610af657600080fd5b5061038b610b053660046145f1565b612f89565b348015610b1657600080fd5b5061038b612fd3565b348015610b2b57600080fd5b5061040d610b3a3660046146ae565b613056565b348015610b4b57600080fd5b5061038b613081565b6005546001600160a01b03610100909104163314610b8d5760405162461bcd60e51b8152600401610b8490614997565b60405180910390fd5b600b54610100900460ff16610bd65760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f52554e4e494e4760881b6044820152606401610b84565b600b805461ff0019169055565b606060038054610bf290614b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1e90614b9e565b8015610c6b5780601f10610c4057610100808354040283529160200191610c6b565b820191906000526020600020905b815481529060010190602001808311610c4e57829003601f168201915b5050505050905090565b6005546060906001600160a01b03610100909104163314610ca85760405162461bcd60e51b8152600401610b8490614997565b610ccd83604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b80610cf95750610cf98360405180604001604052806004815260200163626f6e6560e01b8152506133aa565b610d155760405162461bcd60e51b8152600401610b849061496d565b84600f87604051610d26919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558490601090610d5790899061493e565b90815260200160405180910390208190555082601287604051610d7a919061493e565b90815260200160405180910390209080519060200190610d9b9291906143a1565b5081601187604051610dad919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600c81526020016b141493d353d7d1511255115160a21b815250905095945050505050565b600033610e1d81858561344c565b60019150505b92915050565b6005546060906001600160a01b03610100909104163314610e5c5760405162461bcd60e51b8152600401610b8490614997565b600f85604051610e6c919061493e565b9081526040519081900360200190205460ff1615610ebb5760405162461bcd60e51b815260206004820152600c60248201526b50524f4d4f5f45584953545360a01b6044820152606401610b84565b610ee084604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b80610f0c5750610f0c8460405180604001604052806004815260200163626f6e6560e01b8152506133aa565b610f285760405162461bcd60e51b8152600401610b849061496d565b6001600f86604051610f3a919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558390601090610f6b90889061493e565b90815260200160405180910390208190555083601286604051610f8e919061493e565b90815260200160405180910390209080519060200190610faf9291906143a1565b5081601186604051610fc1919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d0d49150551151609a1b8152509050949350505050565b6019546040516331a9108f60e11b81526004810183905260009182916001600160a01b0390911690636352211e9060240160206040518083038186803b15801561106c57600080fd5b505afa158015611080573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a491906144ec565b6001600160a01b031614156110ec5760405162461bcd60e51b815260206004820152600e60248201526d4e46545f4e4f545f45584953545360901b6044820152606401610b84565b601954604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561113157600080fd5b505afa158015611145573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611169919061488d565b6000848152600d6020908152604080832084845290915281205491925090849060ff161515600114156111a157506000949350505050565b825b8015611212576000828152600d6020908152604080832084845290915290205460ff161515600114156111d557611212565b8181106111fb5780600c546111ea9190614a15565b6111f490846149fd565b9250611200565b611212565b8061120a81614b87565b9150506111a3565b5090949350505050565b6005546001600160a01b0361010090910416331461124c5760405162461bcd60e51b8152600401610b8490614997565b601355565b60003361125f858285613570565b61126a8585856135e4565b506001949350505050565b6019546040516370a0823160e01b815233600482015260009182916001600160a01b03909116906370a082319060240160206040518083038186803b1580156112bd57600080fd5b505afa1580156112d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f5919061488d565b90506000601960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561134757600080fd5b505afa15801561135b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137f919061488d565b90506000805b838110156114cc57601954604051632f745c5960e01b8152336004820152602481018390526000916001600160a01b031690632f745c599060440160206040518083038186803b1580156113d857600080fd5b505afa1580156113ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611410919061488d565b6000818152600d6020908152604080832088845290915290205490915060ff161515600114156114465760009550505050505090565b835b80156114b7576000828152600d6020908152604080832084845290915290205460ff1615156001141561147a576114b7565b8181106114a05780600c5461148f9190614a15565b61149990856149fd565b93506114a5565b6114b7565b806114af81614b87565b915050611448565b505080806114c490614bd3565b915050611385565b509392505050565b6005546060906001600160a01b036101009091041633146115075760405162461bcd60e51b8152600401610b8490614997565b6000600f83604051611519919061493e565b908152604051908190036020018120805492151560ff199093169290921790915560009060109061154b90859061493e565b9081526020016040518091039020819055506040518060200160405280600081525060128360405161157d919061493e565b9081526020016040518091039020908051906020019061159e9291906143a1565b5060006011836040516115b1919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d1115311551151609a1b81525090505b919050565b600061161b6137c3565b905090565b600033610e1d8185856116338383612ce6565b61163d91906149fd565b61344c565b60004382106116935760405162461bcd60e51b815260206004820152601f60248201527f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e6564006044820152606401610b84565b6001600160a01b03831660009081526009602052604090206116b590836138ea565b9392505050565b600b54606090610100900460ff16156117065760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d4105554d15160a21b6044820152606401610b84565b6019546040516331a9108f60e11b8152600481018590526000916001600160a01b031690636352211e9060240160206040518083038186803b15801561174b57600080fd5b505afa15801561175f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178391906144ec565b90506001600160a01b03811633146117cd5760405162461bcd60e51b815260206004820152600d60248201526c2727aa2fa7232a2fa7aba722a960991b6044820152606401610b84565b600f836040516117dd919061493e565b9081526040519081900360200190205460ff1661182e5760405162461bcd60e51b815260206004820152600f60248201526e141493d353d7d393d517d1561254d5608a1b6044820152606401610b84565b6000848152600e602052604090819020905161184b90859061493e565b90815260200160405180910390205460001461189b5760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b6044820152606401610b84565b60006010846040516118ad919061493e565b908152602001604051809103902054905060006012856040516118d0919061493e565b908152602001604051809103902080546118e990614b9e565b80601f016020809104026020016040519081016040528092919081815260200182805461191590614b9e565b80156119625780601f1061193757610100808354040283529160200191611962565b820191906000526020600020905b81548152906001019060200180831161194557829003601f168201915b505050505090506000821115611b635761199781604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b15611a7e57813410156119e55760405162461bcd60e51b81526020600482015260166024820152751393d517d15393d551d217d1551217d410565351539560521b6044820152606401610b84565b60006011866040516119f7919061493e565b908152602001604051809103902060009054906101000a90046001600160a01b0316905060006064611a2b856015546139a7565b611a359190614a15565b9050816001600160a01b03166108fc611a4e868461339e565b6040518115909202916000818181858888f19350505050158015611a76573d6000803e3d6000fd5b505050611b63565b611aa48160405180604001604052806004815260200163626f6e6560e01b8152506133aa565b15611b635733600090815260208190526040902054821115611afa5760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454e4f5547485f424f4e4560881b6044820152606401610b84565b6000601186604051611b0c919061493e565b908152602001604051809103902060009054906101000a90046001600160a01b0316905060006064611b40856015546139a7565b611b4a9190614a15565b9050611b603383611b5b878561339e565b6135e4565b50505b42600e600088815260200190815260200160002086604051611b85919061493e565b9081526020016040518091039020819055506040518060400160405280600781526020016610d3105253515160ca1b815250935050505092915050565b6005546001600160a01b03610100909104163314611bf25760405162461bcd60e51b8152600401610b8490614997565b611bfa6139b3565b565b6005546001600160a01b03610100909104163314611c2c5760405162461bcd60e51b8152600401610b8490614997565b600b5460ff16611c705760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f52554e4e494e4760881b6044820152606401610b84565b600b805460ff19169055565b6005546001600160a01b03610100909104163314611cac5760405162461bcd60e51b8152600401610b8490614997565b611cb68282613a46565b5050565b6005546001600160a01b03610100909104163314611cea5760405162461bcd60e51b8152600401610b8490614997565b611cb63083836116333087612ce6565b6005546001600160a01b03610100909104163314611d2a5760405162461bcd60e51b8152600401610b8490614997565b611d358383836135e4565b505050565b611d443382613a50565b50565b600b5460609060ff1615611d8c5760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d4105554d15160a21b6044820152606401610b84565b601954604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611dd157600080fd5b505afa158015611de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e09919061488d565b6019546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611e5257600080fd5b505afa158015611e66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8a919061488d565b90506000808211611ec75760405162461bcd60e51b81526020600482015260076024820152664e4f5f4e46545360c81b6044820152606401610b84565b60005b8281101561206157601954604051632f745c5960e01b8152336004820152602481018390526000916001600160a01b031690632f745c599060440160206040518083038186803b158015611f1d57600080fd5b505afa158015611f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f55919061488d565b6000818152600d6020908152604080832089845290915290205490915060ff16151560011415611fb95760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b6044820152606401610b84565b845b801561202a576000828152600d6020908152604080832084845290915290205460ff16151560011415611fed5761202a565b8181106120135780600c546120029190614a15565b61200c90856149fd565b9350612018565b61202a565b8061202281614b87565b915050611fbb565b506000908152600d602090815260408083208784529091529020805460ff191660011790558061205981614bd3565b915050611eca565b5061206d3033836135e4565b6040518060400160405280600781526020016610d3105253515160ca1b815250935050505090565b6000806120a96120a460025490565b613a5a565b610e239047614a15565b6005546001600160a01b036101009091041633146120e35760405162461bcd60e51b8152600401610b8490614997565b601880546001600160a01b039092166001600160a01b0319928316811790915560198054909216179055565b6000828152600e6020526040808220905161212b90849061493e565b908152602001604051809103902054905092915050565b611d443382613a72565b6005546001600160a01b0361010090910416331461217c5760405162461bcd60e51b8152600401610b8490614997565b611cb68282613a50565b6060336001600160a01b03166011836040516121a2919061493e565b908152604051908190036020019020546001600160a01b0316146115075760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610b84565b6001600160a01b038116600090815260096020526040812054610e2390613307565b6005546001600160a01b036101009091041633146122465760405162461bcd60e51b8152600401610b8490614997565b601455565b61217c823383613570565b6001600160a01b038116600090815260066020526040812054610e23565b6005546001600160a01b036101009091041633146122a45760405162461bcd60e51b8152600401610b8490614997565b611bfa613aeb565b60004382106122fd5760405162461bcd60e51b815260206004820152601f60248201527f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e6564006044820152606401610b84565b610e23600a836138ea565b6005546001600160a01b036101009091041633146123385760405162461bcd60e51b8152600401610b8490614997565b601780546001600160a01b0319166001600160a01b0392909216919091179055565b6005546060906001600160a01b0361010090910416331461238d5760405162461bcd60e51b8152600401610b8490614997565b600034116123d05760405162461bcd60e51b815260206004820152601060248201526f4e4f5f5a45524f5f4445504f5349545360801b6044820152606401610b84565b5060408051808201909152600981526811115413d4d255115160ba1b602082015290565b6005546001600160a01b036101009091041633146124245760405162461bcd60e51b8152600401610b8490614997565b601655565b606060048054610bf290614b9e565b6060336001600160a01b0316601187604051612454919061493e565b908152604051908190036020019020546001600160a01b031614610ca85760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610b84565b6001600160a01b038116600090815260096020526040812054801561251a576001600160a01b03831660009081526009602052604090206124e8600183614b44565b815481106124f8576124f8614c1a565b60009182526020909120015464010000000090046001600160e01b031661251d565b60005b6001600160e01b03169392505050565b6000338161253b8286612ce6565b90508381101561259b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610b84565b61126a828686840361344c565b600033610e1d8185856135e4565b834211156126065760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e617475726520657870697265640000006044820152606401610b84565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090612680906126789060a00160405160208183030381529060405280519060200120613b66565b858585613bb4565b905061268b81613bdc565b86146126d95760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e6365000000000000006044820152606401610b84565b6126e38188613a72565b50505050505050565b8342111561273c5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610b84565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861276b8c613bdc565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006127c682613b66565b905060006127d682878787613bb4565b9050896001600160a01b0316816001600160a01b0316146128395760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610b84565b6128448a8a8a61344c565b50505050505050505050565b6060600f84604051612862919061493e565b9081526040519081900360200190205460ff16156128b15760405162461bcd60e51b815260206004820152600c60248201526b50524f4d4f5f45584953545360a01b6044820152606401610b84565b6128d683604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b8061290257506129028360405180604001604052806004815260200163626f6e6560e01b8152506133aa565b61291e5760405162461bcd60e51b8152600401610b849061496d565b34156129745760135434101561296f5760405162461bcd60e51b81526020600482015260166024820152751393d517d15393d551d217d1551217d410565351539560521b6044820152606401610b84565b6129d4565b6014543360009081526020819052604090205410156129c75760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454e4f5547485f424f4e4560881b6044820152606401610b84565b6129d433306014546135e4565b6001600f856040516129e6919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558290601090612a1790879061493e565b90815260200160405180910390208190555082601285604051612a3a919061493e565b90815260200160405180910390209080519060200190612a5b9291906143a1565b5033601185604051612a6d919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d0d49150551151609a1b81525090509392505050565b6005546001600160a01b03610100909104163314612afe5760405162461bcd60e51b8152600401610b8490614997565b3031821115612b405760405162461bcd60e51b815260206004820152600e60248201526d09c9ea8be8a9c9eaa8e90be8aa8960931b6044820152606401610b84565b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611d35573d6000803e3d6000fd5b600060606000600f84604051612b8c919061493e565b9081526040519081900360200190205460ff161515600114612be35760405162461bcd60e51b815260206004820152601060248201526f50524f4d4f5f4e4f545f45584953545360801b6044820152606401610b84565b601084604051612bf3919061493e565b908152602001604051809103902054601285604051612c12919061493e565b9081526020016040518091039020601186604051612c30919061493e565b9081526040519081900360200190205481546001600160a01b03909116908290612c5990614b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054612c8590614b9e565b8015612cd25780601f10612ca757610100808354040283529160200191612cd2565b820191906000526020600020905b815481529060010190602001808311612cb557829003601f168201915b505050505091509250925092509193909250565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606000341180612d225750600082115b612d625760405162461bcd60e51b81526020600482015260116024820152704e4f5f5a45524f5f444f4e4154494f4e5360781b6044820152606401610b84565b823415612dce5760006064612d79346016546139a7565b612d839190614a15565b90506000612d91348361339e565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612dca573d6000803e3d6000fd5b5050505b8215612e0c5760006064612de4856016546139a7565b612dee9190614a15565b90506000612dfc858361339e565b9050612e093384836135e4565b50505b50506040805180820190915260078152661113d39055115160ca1b602082015292915050565b6005546001600160a01b03610100909104163314612e625760405162461bcd60e51b8152600401610b8490614997565b601555565b60408051808201909152600080825260208201526001600160a01b0383166000908152600960205260409020805463ffffffff8416908110612eab57612eab614c1a565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6005546001600160a01b03610100909104163314612f1b5760405162461bcd60e51b8152600401610b8490614997565b6001600160a01b038116612f805760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b84565b611d4481613c04565b6005546001600160a01b03610100909104163314612fb95760405162461bcd60e51b8152600401610b8490614997565b611cb6308383612fc93087612ce6565b61163d9190614b44565b6005546001600160a01b036101009091041633146130035760405162461bcd60e51b8152600401610b8490614997565b600b5460ff16156130475760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4105554d15160921b6044820152606401610b84565b600b805460ff19166001179055565b6000600f82604051613068919061493e565b9081526040519081900360200190205460ff1692915050565b6005546001600160a01b036101009091041633146130b15760405162461bcd60e51b8152600401610b8490614997565b600b54610100900460ff16156130fa5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4105554d15160921b6044820152606401610b84565b600b805461ff001916610100179055565b613115828261319b565b6002546001600160e01b0310156131875760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401610b84565b613195600a61328e83613c5e565b50505050565b6001600160a01b0382166131f15760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610b84565b6131fd60008383613dd7565b806002600082825461320f91906149fd565b90915550506001600160a01b0382166000908152602081905260408120805483929061323c9084906149fd565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3611cb660008383613e1d565b60006116b582846149fd565b60006001600160e01b038211156133035760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610b84565b5090565b600063ffffffff8211156133035760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610b84565b6001600160a01b03838116600090815260086020526040808220548584168352912054611d3592918216911683613e28565b60006116b58284614b44565b81518151600091849184919081146133c85760009350505050610e23565b60005b8181101561343f578281815181106133e5576133e5614c1a565b602001015160f81c60f81b6001600160f81b03191684828151811061340c5761340c614c1a565b01602001516001600160f81b0319161461342d576000945050505050610e23565b8061343781614bd3565b9150506133cb565b5060019695505050505050565b6001600160a01b0383166134ae5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610b84565b6001600160a01b03821661350f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610b84565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061357c8484612ce6565b9050600019811461319557818110156135d75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610b84565b613195848484840361344c565b6001600160a01b0383166136485760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610b84565b6001600160a01b0382166136aa5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610b84565b6136b5838383613dd7565b6001600160a01b0383166000908152602081905260409020548181101561372d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610b84565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906137649084906149fd565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516137b091815260200190565b60405180910390a3613195848484613e1d565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561381c57507f000000000000000000000000000000000000000000000000000000000000000046145b1561384657507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b8154600090815b8181101561394e5760006139058284613f65565b90508486828154811061391a5761391a614c1a565b60009182526020909120015463ffffffff16111561393a57809250613948565b6139458160016149fd565b91505b506138f1565b81156139925784613960600184614b44565b8154811061397057613970614c1a565b60009182526020909120015464010000000090046001600160e01b0316613995565b60005b6001600160e01b031695945050505050565b60006116b58284614b25565b60055460ff166139fc5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b84565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b611cb6828261310b565b611cb68282613f80565b6000613a686004600a614a7a565b610e239083614a15565b6001600160a01b038281166000818152600860208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4613195828483613e28565b60055460ff1615613b315760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b84565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613a293390565b6000610e23613b736137c3565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000613bc587878787613f98565b91509150613bd281614085565b5095945050505050565b6001600160a01b03811660009081526006602052604090208054600181018255905b50919050565b600580546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b825460009081908015613ca95785613c77600183614b44565b81548110613c8757613c87614c1a565b60009182526020909120015464010000000090046001600160e01b0316613cac565b60005b6001600160e01b03169250613cc583858763ffffffff16565b9150600081118015613d0357504386613cdf600184614b44565b81548110613cef57613cef614c1a565b60009182526020909120015463ffffffff16145b15613d6357613d118261329a565b86613d1d600184614b44565b81548110613d2d57613d2d614c1a565b9060005260206000200160000160046101000a8154816001600160e01b0302191690836001600160e01b03160217905550613dce565b856040518060400160405280613d7843613307565b63ffffffff168152602001613d8c8561329a565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b50935093915050565b60055460ff1615611d355760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b84565b611d3583838361336c565b816001600160a01b0316836001600160a01b031614158015613e4a5750600081115b15611d35576001600160a01b03831615613ed8576001600160a01b03831660009081526009602052604081208190613e859061339e85613c5e565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051613ecd929190918252602082015260400190565b60405180910390a250505b6001600160a01b03821615611d35576001600160a01b03821660009081526009602052604081208190613f0e9061328e85613c5e565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051613f56929190918252602082015260400190565b60405180910390a25050505050565b6000613f746002848418614a15565b6116b5908484166149fd565b613f8a8282614240565b613195600a61339e83613c5e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613fcf575060009050600361407c565b8460ff16601b14158015613fe757508460ff16601c14155b15613ff8575060009050600461407c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561404c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166140755760006001925092505061407c565b9150600090505b94509492505050565b600081600481111561409957614099614c04565b14156140a25750565b60018160048111156140b6576140b6614c04565b14156141045760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b84565b600281600481111561411857614118614c04565b14156141665760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b84565b600381600481111561417a5761417a614c04565b14156141d35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b84565b60048160048111156141e7576141e7614c04565b1415611d445760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610b84565b6001600160a01b0382166142a05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610b84565b6142ac82600083613dd7565b6001600160a01b038216600090815260208190526040902054818110156143205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610b84565b6001600160a01b038316600090815260208190526040812083830390556002805484929061434f908490614b44565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3611d3583600084613e1d565b8280546143ad90614b9e565b90600052602060002090601f0160209004810192826143cf5760008555614415565b82601f106143e857805160ff1916838001178555614415565b82800160010185558215614415579182015b828111156144155782518255916020019190600101906143fa565b506133039291505b80821115613303576000815560010161441d565b600082601f83011261444257600080fd5b813567ffffffffffffffff8082111561445d5761445d614c30565b604051601f8301601f19908116603f0116810190828211818310171561448557614485614c30565b8160405283815286602085880101111561449e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff8116811461160c57600080fd5b6000602082840312156144e157600080fd5b81356116b581614c46565b6000602082840312156144fe57600080fd5b81516116b581614c46565b6000806040838503121561451c57600080fd5b823561452781614c46565b9150602083013561453781614c46565b809150509250929050565b60008060006060848603121561455757600080fd5b833561456281614c46565b9250602084013561457281614c46565b929592945050506040919091013590565b600080600080600080600060e0888a03121561459e57600080fd5b87356145a981614c46565b965060208801356145b981614c46565b955060408801359450606088013593506145d5608089016144be565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561460457600080fd5b823561460f81614c46565b946020939093013593505050565b60008060008060008060c0878903121561463657600080fd5b863561464181614c46565b9550602087013594506040870135935061465d606088016144be565b92506080870135915060a087013590509295509295509295565b6000806040838503121561468a57600080fd5b823561469581614c46565b9150602083013563ffffffff8116811461453757600080fd5b6000602082840312156146c057600080fd5b813567ffffffffffffffff8111156146d757600080fd5b6146e384828501614431565b949350505050565b600080600080600060a0868803121561470357600080fd5b853567ffffffffffffffff8082111561471b57600080fd5b61472789838a01614431565b965060208801359150811515821461473e57600080fd5b909450604087013593506060870135908082111561475b57600080fd5b5061476888828901614431565b925050608086013561477981614c46565b809150509295509295909350565b60008060006060848603121561479c57600080fd5b833567ffffffffffffffff808211156147b457600080fd5b6147c087838801614431565b945060208601359150808211156147d657600080fd5b506147e386828701614431565b925050604084013590509250925092565b6000806000806080858703121561480a57600080fd5b843567ffffffffffffffff8082111561482257600080fd5b61482e88838901614431565b9550602087013591508082111561484457600080fd5b5061485187828801614431565b93505060408501359150606085013561486981614c46565b939692955090935050565b60006020828403121561488657600080fd5b5035919050565b60006020828403121561489f57600080fd5b5051919050565b600080604083850312156148b957600080fd5b82359150602083013561453781614c46565b600080604083850312156148de57600080fd5b82359150602083013567ffffffffffffffff8111156148fc57600080fd5b61490885828601614431565b9150509250929050565b6000815180845261492a816020860160208601614b5b565b601f01601f19169290920160200192915050565b60008251614950818460208701614b5b565b9190910192915050565b6020815260006116b56020830184614912565b60208082526010908201526f494e56414c49445f43555252454e435960801b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b8381526060602082015260006149e56060830185614912565b905060018060a01b0383166040830152949350505050565b60008219821115614a1057614a10614bee565b500190565b600082614a3257634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115614a72578160001904821115614a5857614a58614bee565b80851615614a6557918102915b93841c9390800290614a3c565b509250929050565b60006116b560ff841683600082614a9357506001610e23565b81614aa057506000610e23565b8160018114614ab65760028114614ac057614adc565b6001915050610e23565b60ff841115614ad157614ad1614bee565b50506001821b610e23565b5060208310610133831016604e8410600b8410161715614aff575081810a610e23565b614b098383614a37565b8060001904821115614b1d57614b1d614bee565b029392505050565b6000816000190483118215151615614b3f57614b3f614bee565b500290565b600082821015614b5657614b56614bee565b500390565b60005b83811015614b76578181015183820152602001614b5e565b838111156131955750506000910152565b600081614b9657614b96614bee565b506000190190565b600181811c90821680614bb257607f821691505b60208210811415613bfe57634e487b7160e01b600052602260045260246000fd5b6000600019821415614be757614be7614bee565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611d4457600080fdfea2646970667358221220e4fea938bbc9229cb7cdcf617e147b2361d02ef2de66896c534bc5054b2da8c164736f6c63430008070033dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724

Deployed Bytecode

0x60806040526004361061038b5760003560e01c80635fbbae3f116101da578063a46a140011610101578063e69d849d1161009a578063f39459b81161006c578063f39459b814610aea578063f8ffd87b14610b0a578063fad4700614610b1f578063fe61700d14610b3f57005b8063e69d849d14610a4d578063eec74da614610a60578063f1127ed814610a80578063f2fde38b14610aca57005b8063d63565c1116100d3578063d63565c1146109cb578063d7a6a05e146109de578063dba35e38146109fe578063dd62ed3e14610a2d57005b8063a46a140014610956578063a9059cbb1461096b578063c3cda5201461098b578063d505accf146109ab57005b80638e539e8c1161017357806395d89b411161014557806395d89b41146108e157806399aaf21f146108f65780639ab24eb014610916578063a457c2d71461093657005b80638e539e8c146108795780639142376514610899578063928ec28c146108b957806393da92be146108c157005b806379cc6790116101ac57806379cc6790146108015780637ecebe00146108215780638456cb59146108415780638da5cb5b1461085657005b80635fbbae3f146107565780636fcfff451461077657806370a08231146107ab57806372e155c9146107e157005b80633a46b1a8116102be57806348c54b9d116102575780635b68930f116102295780635b68930f146106de5780635c19a95c146106fe5780635c975abb1461071e5780635ef8cd171461073657005b806348c54b9d146106435780634b94f50e146106585780634e190ad41461066d578063587cde1e1461068d57005b806340c10f191161029057806340c10f19146105c3578063419d031d146105e357806342842e0e1461060357806342966c681461062357005b80633a46b1a8146105665780633adc956a146105865780633f4ba83a146105995780634091688f146105ae57005b80631430c11b116103305780632b947531116103025780632b947531146104f5578063313ce567146105155780633644e51514610531578063395093511461054657005b80631430c11b1461048b57806318160ddd146104ab57806323b872dd146104c0578063260c6fdc146104e057005b8063095ea7b311610369578063095ea7b3146103ed5780630aa09dbb1461041d5780630c0148411461043d57806313777c241461045d57005b8063027c131d1461038d57806306fdde03146103a2578063087979ab146103cd575b005b34801561039957600080fd5b5061038b610b54565b3480156103ae57600080fd5b506103b7610be3565b6040516103c4919061495a565b60405180910390f35b3480156103d957600080fd5b506103b76103e83660046146eb565b610c75565b3480156103f957600080fd5b5061040d6104083660046145f1565b610e0f565b60405190151581526020016103c4565b34801561042957600080fd5b5061038b610438366004614874565b600c55565b34801561044957600080fd5b506103b76104583660046147f4565b610e29565b34801561046957600080fd5b5061047d610478366004614874565b611023565b6040519081526020016103c4565b34801561049757600080fd5b5061038b6104a6366004614874565b61121c565b3480156104b757600080fd5b5060025461047d565b3480156104cc57600080fd5b5061040d6104db366004614542565b611251565b3480156104ec57600080fd5b5061047d611275565b34801561050157600080fd5b506103b76105103660046146ae565b6114d4565b34801561052157600080fd5b50604051600481526020016103c4565b34801561053d57600080fd5b5061047d611611565b34801561055257600080fd5b5061040d6105613660046145f1565b611620565b34801561057257600080fd5b5061047d6105813660046145f1565b611642565b6103b76105943660046148cb565b6116bc565b3480156105a557600080fd5b5061038b611bc2565b3480156105ba57600080fd5b5061038b611bfc565b3480156105cf57600080fd5b5061038b6105de3660046145f1565b611c7c565b3480156105ef57600080fd5b5061038b6105fe3660046145f1565b611cba565b34801561060f57600080fd5b5061038b61061e366004614542565b611cfa565b34801561062f57600080fd5b5061038b61063e366004614874565b611d3a565b34801561064f57600080fd5b506103b7611d47565b34801561066457600080fd5b5061047d612095565b34801561067957600080fd5b5061038b6106883660046144cf565b6120b3565b34801561069957600080fd5b506106c66106a83660046144cf565b6001600160a01b039081166000908152600860205260409020541690565b6040516001600160a01b0390911681526020016103c4565b3480156106ea57600080fd5b5061047d6106f93660046148cb565b61210f565b34801561070a57600080fd5b5061038b6107193660046144cf565b612142565b34801561072a57600080fd5b5060055460ff1661040d565b34801561074257600080fd5b5061038b6107513660046145f1565b61214c565b34801561076257600080fd5b506103b76107713660046146ae565b612186565b34801561078257600080fd5b506107966107913660046144cf565b6121f4565b60405163ffffffff90911681526020016103c4565b3480156107b757600080fd5b5061047d6107c63660046144cf565b6001600160a01b031660009081526020819052604090205490565b3480156107ed57600080fd5b5061038b6107fc366004614874565b612216565b34801561080d57600080fd5b5061038b61081c3660046145f1565b61224b565b34801561082d57600080fd5b5061047d61083c3660046144cf565b612256565b34801561084d57600080fd5b5061038b612274565b34801561086257600080fd5b5060055461010090046001600160a01b03166106c6565b34801561088557600080fd5b5061047d610894366004614874565b6122ac565b3480156108a557600080fd5b5061038b6108b43660046144cf565b612308565b6103b761235a565b3480156108cd57600080fd5b5061038b6108dc366004614874565b6123f4565b3480156108ed57600080fd5b506103b7612429565b34801561090257600080fd5b506103b76109113660046146eb565b612438565b34801561092257600080fd5b5061047d6109313660046144cf565b6124a6565b34801561094257600080fd5b5061040d6109513660046145f1565b61252d565b34801561096257600080fd5b50600c5461047d565b34801561097757600080fd5b5061040d6109863660046145f1565b6125a8565b34801561099757600080fd5b5061038b6109a636600461461d565b6125b6565b3480156109b757600080fd5b5061038b6109c6366004614583565b6126ec565b6103b76109d9366004614787565b612850565b3480156109ea57600080fd5b5061038b6109f93660046148a6565b612ace565b348015610a0a57600080fd5b50610a1e610a193660046146ae565b612b76565b6040516103c4939291906149cc565b348015610a3957600080fd5b5061047d610a48366004614509565b612ce6565b6103b7610a5b3660046145f1565b612d11565b348015610a6c57600080fd5b5061038b610a7b366004614874565b612e32565b348015610a8c57600080fd5b50610aa0610a9b366004614677565b612e67565b60408051825163ffffffff1681526020928301516001600160e01b031692810192909252016103c4565b348015610ad657600080fd5b5061038b610ae53660046144cf565b612eeb565b348015610af657600080fd5b5061038b610b053660046145f1565b612f89565b348015610b1657600080fd5b5061038b612fd3565b348015610b2b57600080fd5b5061040d610b3a3660046146ae565b613056565b348015610b4b57600080fd5b5061038b613081565b6005546001600160a01b03610100909104163314610b8d5760405162461bcd60e51b8152600401610b8490614997565b60405180910390fd5b600b54610100900460ff16610bd65760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f52554e4e494e4760881b6044820152606401610b84565b600b805461ff0019169055565b606060038054610bf290614b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1e90614b9e565b8015610c6b5780601f10610c4057610100808354040283529160200191610c6b565b820191906000526020600020905b815481529060010190602001808311610c4e57829003601f168201915b5050505050905090565b6005546060906001600160a01b03610100909104163314610ca85760405162461bcd60e51b8152600401610b8490614997565b610ccd83604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b80610cf95750610cf98360405180604001604052806004815260200163626f6e6560e01b8152506133aa565b610d155760405162461bcd60e51b8152600401610b849061496d565b84600f87604051610d26919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558490601090610d5790899061493e565b90815260200160405180910390208190555082601287604051610d7a919061493e565b90815260200160405180910390209080519060200190610d9b9291906143a1565b5081601187604051610dad919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600c81526020016b141493d353d7d1511255115160a21b815250905095945050505050565b600033610e1d81858561344c565b60019150505b92915050565b6005546060906001600160a01b03610100909104163314610e5c5760405162461bcd60e51b8152600401610b8490614997565b600f85604051610e6c919061493e565b9081526040519081900360200190205460ff1615610ebb5760405162461bcd60e51b815260206004820152600c60248201526b50524f4d4f5f45584953545360a01b6044820152606401610b84565b610ee084604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b80610f0c5750610f0c8460405180604001604052806004815260200163626f6e6560e01b8152506133aa565b610f285760405162461bcd60e51b8152600401610b849061496d565b6001600f86604051610f3a919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558390601090610f6b90889061493e565b90815260200160405180910390208190555083601286604051610f8e919061493e565b90815260200160405180910390209080519060200190610faf9291906143a1565b5081601186604051610fc1919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d0d49150551151609a1b8152509050949350505050565b6019546040516331a9108f60e11b81526004810183905260009182916001600160a01b0390911690636352211e9060240160206040518083038186803b15801561106c57600080fd5b505afa158015611080573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a491906144ec565b6001600160a01b031614156110ec5760405162461bcd60e51b815260206004820152600e60248201526d4e46545f4e4f545f45584953545360901b6044820152606401610b84565b601954604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561113157600080fd5b505afa158015611145573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611169919061488d565b6000848152600d6020908152604080832084845290915281205491925090849060ff161515600114156111a157506000949350505050565b825b8015611212576000828152600d6020908152604080832084845290915290205460ff161515600114156111d557611212565b8181106111fb5780600c546111ea9190614a15565b6111f490846149fd565b9250611200565b611212565b8061120a81614b87565b9150506111a3565b5090949350505050565b6005546001600160a01b0361010090910416331461124c5760405162461bcd60e51b8152600401610b8490614997565b601355565b60003361125f858285613570565b61126a8585856135e4565b506001949350505050565b6019546040516370a0823160e01b815233600482015260009182916001600160a01b03909116906370a082319060240160206040518083038186803b1580156112bd57600080fd5b505afa1580156112d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f5919061488d565b90506000601960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561134757600080fd5b505afa15801561135b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137f919061488d565b90506000805b838110156114cc57601954604051632f745c5960e01b8152336004820152602481018390526000916001600160a01b031690632f745c599060440160206040518083038186803b1580156113d857600080fd5b505afa1580156113ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611410919061488d565b6000818152600d6020908152604080832088845290915290205490915060ff161515600114156114465760009550505050505090565b835b80156114b7576000828152600d6020908152604080832084845290915290205460ff1615156001141561147a576114b7565b8181106114a05780600c5461148f9190614a15565b61149990856149fd565b93506114a5565b6114b7565b806114af81614b87565b915050611448565b505080806114c490614bd3565b915050611385565b509392505050565b6005546060906001600160a01b036101009091041633146115075760405162461bcd60e51b8152600401610b8490614997565b6000600f83604051611519919061493e565b908152604051908190036020018120805492151560ff199093169290921790915560009060109061154b90859061493e565b9081526020016040518091039020819055506040518060200160405280600081525060128360405161157d919061493e565b9081526020016040518091039020908051906020019061159e9291906143a1565b5060006011836040516115b1919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d1115311551151609a1b81525090505b919050565b600061161b6137c3565b905090565b600033610e1d8185856116338383612ce6565b61163d91906149fd565b61344c565b60004382106116935760405162461bcd60e51b815260206004820152601f60248201527f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e6564006044820152606401610b84565b6001600160a01b03831660009081526009602052604090206116b590836138ea565b9392505050565b600b54606090610100900460ff16156117065760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d4105554d15160a21b6044820152606401610b84565b6019546040516331a9108f60e11b8152600481018590526000916001600160a01b031690636352211e9060240160206040518083038186803b15801561174b57600080fd5b505afa15801561175f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178391906144ec565b90506001600160a01b03811633146117cd5760405162461bcd60e51b815260206004820152600d60248201526c2727aa2fa7232a2fa7aba722a960991b6044820152606401610b84565b600f836040516117dd919061493e565b9081526040519081900360200190205460ff1661182e5760405162461bcd60e51b815260206004820152600f60248201526e141493d353d7d393d517d1561254d5608a1b6044820152606401610b84565b6000848152600e602052604090819020905161184b90859061493e565b90815260200160405180910390205460001461189b5760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b6044820152606401610b84565b60006010846040516118ad919061493e565b908152602001604051809103902054905060006012856040516118d0919061493e565b908152602001604051809103902080546118e990614b9e565b80601f016020809104026020016040519081016040528092919081815260200182805461191590614b9e565b80156119625780601f1061193757610100808354040283529160200191611962565b820191906000526020600020905b81548152906001019060200180831161194557829003601f168201915b505050505090506000821115611b635761199781604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b15611a7e57813410156119e55760405162461bcd60e51b81526020600482015260166024820152751393d517d15393d551d217d1551217d410565351539560521b6044820152606401610b84565b60006011866040516119f7919061493e565b908152602001604051809103902060009054906101000a90046001600160a01b0316905060006064611a2b856015546139a7565b611a359190614a15565b9050816001600160a01b03166108fc611a4e868461339e565b6040518115909202916000818181858888f19350505050158015611a76573d6000803e3d6000fd5b505050611b63565b611aa48160405180604001604052806004815260200163626f6e6560e01b8152506133aa565b15611b635733600090815260208190526040902054821115611afa5760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454e4f5547485f424f4e4560881b6044820152606401610b84565b6000601186604051611b0c919061493e565b908152602001604051809103902060009054906101000a90046001600160a01b0316905060006064611b40856015546139a7565b611b4a9190614a15565b9050611b603383611b5b878561339e565b6135e4565b50505b42600e600088815260200190815260200160002086604051611b85919061493e565b9081526020016040518091039020819055506040518060400160405280600781526020016610d3105253515160ca1b815250935050505092915050565b6005546001600160a01b03610100909104163314611bf25760405162461bcd60e51b8152600401610b8490614997565b611bfa6139b3565b565b6005546001600160a01b03610100909104163314611c2c5760405162461bcd60e51b8152600401610b8490614997565b600b5460ff16611c705760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f52554e4e494e4760881b6044820152606401610b84565b600b805460ff19169055565b6005546001600160a01b03610100909104163314611cac5760405162461bcd60e51b8152600401610b8490614997565b611cb68282613a46565b5050565b6005546001600160a01b03610100909104163314611cea5760405162461bcd60e51b8152600401610b8490614997565b611cb63083836116333087612ce6565b6005546001600160a01b03610100909104163314611d2a5760405162461bcd60e51b8152600401610b8490614997565b611d358383836135e4565b505050565b611d443382613a50565b50565b600b5460609060ff1615611d8c5760405162461bcd60e51b815260206004820152600c60248201526b10d310525357d4105554d15160a21b6044820152606401610b84565b601954604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611dd157600080fd5b505afa158015611de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e09919061488d565b6019546040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015611e5257600080fd5b505afa158015611e66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8a919061488d565b90506000808211611ec75760405162461bcd60e51b81526020600482015260076024820152664e4f5f4e46545360c81b6044820152606401610b84565b60005b8281101561206157601954604051632f745c5960e01b8152336004820152602481018390526000916001600160a01b031690632f745c599060440160206040518083038186803b158015611f1d57600080fd5b505afa158015611f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f55919061488d565b6000818152600d6020908152604080832089845290915290205490915060ff16151560011415611fb95760405162461bcd60e51b815260206004820152600f60248201526e1053149150511657d0d31052535151608a1b6044820152606401610b84565b845b801561202a576000828152600d6020908152604080832084845290915290205460ff16151560011415611fed5761202a565b8181106120135780600c546120029190614a15565b61200c90856149fd565b9350612018565b61202a565b8061202281614b87565b915050611fbb565b506000908152600d602090815260408083208784529091529020805460ff191660011790558061205981614bd3565b915050611eca565b5061206d3033836135e4565b6040518060400160405280600781526020016610d3105253515160ca1b815250935050505090565b6000806120a96120a460025490565b613a5a565b610e239047614a15565b6005546001600160a01b036101009091041633146120e35760405162461bcd60e51b8152600401610b8490614997565b601880546001600160a01b039092166001600160a01b0319928316811790915560198054909216179055565b6000828152600e6020526040808220905161212b90849061493e565b908152602001604051809103902054905092915050565b611d443382613a72565b6005546001600160a01b0361010090910416331461217c5760405162461bcd60e51b8152600401610b8490614997565b611cb68282613a50565b6060336001600160a01b03166011836040516121a2919061493e565b908152604051908190036020019020546001600160a01b0316146115075760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610b84565b6001600160a01b038116600090815260096020526040812054610e2390613307565b6005546001600160a01b036101009091041633146122465760405162461bcd60e51b8152600401610b8490614997565b601455565b61217c823383613570565b6001600160a01b038116600090815260066020526040812054610e23565b6005546001600160a01b036101009091041633146122a45760405162461bcd60e51b8152600401610b8490614997565b611bfa613aeb565b60004382106122fd5760405162461bcd60e51b815260206004820152601f60248201527f4552433230566f7465733a20626c6f636b206e6f7420796574206d696e6564006044820152606401610b84565b610e23600a836138ea565b6005546001600160a01b036101009091041633146123385760405162461bcd60e51b8152600401610b8490614997565b601780546001600160a01b0319166001600160a01b0392909216919091179055565b6005546060906001600160a01b0361010090910416331461238d5760405162461bcd60e51b8152600401610b8490614997565b600034116123d05760405162461bcd60e51b815260206004820152601060248201526f4e4f5f5a45524f5f4445504f5349545360801b6044820152606401610b84565b5060408051808201909152600981526811115413d4d255115160ba1b602082015290565b6005546001600160a01b036101009091041633146124245760405162461bcd60e51b8152600401610b8490614997565b601655565b606060048054610bf290614b9e565b6060336001600160a01b0316601187604051612454919061493e565b908152604051908190036020019020546001600160a01b031614610ca85760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b6044820152606401610b84565b6001600160a01b038116600090815260096020526040812054801561251a576001600160a01b03831660009081526009602052604090206124e8600183614b44565b815481106124f8576124f8614c1a565b60009182526020909120015464010000000090046001600160e01b031661251d565b60005b6001600160e01b03169392505050565b6000338161253b8286612ce6565b90508381101561259b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610b84565b61126a828686840361344c565b600033610e1d8185856135e4565b834211156126065760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e617475726520657870697265640000006044820152606401610b84565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090612680906126789060a00160405160208183030381529060405280519060200120613b66565b858585613bb4565b905061268b81613bdc565b86146126d95760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e6365000000000000006044820152606401610b84565b6126e38188613a72565b50505050505050565b8342111561273c5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610b84565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861276b8c613bdc565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006127c682613b66565b905060006127d682878787613bb4565b9050896001600160a01b0316816001600160a01b0316146128395760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610b84565b6128448a8a8a61344c565b50505050505050505050565b6060600f84604051612862919061493e565b9081526040519081900360200190205460ff16156128b15760405162461bcd60e51b815260206004820152600c60248201526b50524f4d4f5f45584953545360a01b6044820152606401610b84565b6128d683604051806040016040528060038152602001620cae8d60eb1b8152506133aa565b8061290257506129028360405180604001604052806004815260200163626f6e6560e01b8152506133aa565b61291e5760405162461bcd60e51b8152600401610b849061496d565b34156129745760135434101561296f5760405162461bcd60e51b81526020600482015260166024820152751393d517d15393d551d217d1551217d410565351539560521b6044820152606401610b84565b6129d4565b6014543360009081526020819052604090205410156129c75760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454e4f5547485f424f4e4560881b6044820152606401610b84565b6129d433306014546135e4565b6001600f856040516129e6919061493e565b908152604051908190036020018120805492151560ff19909316929092179091558290601090612a1790879061493e565b90815260200160405180910390208190555082601285604051612a3a919061493e565b90815260200160405180910390209080519060200190612a5b9291906143a1565b5033601185604051612a6d919061493e565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040518060400160405280600d81526020016c141493d353d7d0d49150551151609a1b81525090509392505050565b6005546001600160a01b03610100909104163314612afe5760405162461bcd60e51b8152600401610b8490614997565b3031821115612b405760405162461bcd60e51b815260206004820152600e60248201526d09c9ea8be8a9c9eaa8e90be8aa8960931b6044820152606401610b84565b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611d35573d6000803e3d6000fd5b600060606000600f84604051612b8c919061493e565b9081526040519081900360200190205460ff161515600114612be35760405162461bcd60e51b815260206004820152601060248201526f50524f4d4f5f4e4f545f45584953545360801b6044820152606401610b84565b601084604051612bf3919061493e565b908152602001604051809103902054601285604051612c12919061493e565b9081526020016040518091039020601186604051612c30919061493e565b9081526040519081900360200190205481546001600160a01b03909116908290612c5990614b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054612c8590614b9e565b8015612cd25780601f10612ca757610100808354040283529160200191612cd2565b820191906000526020600020905b815481529060010190602001808311612cb557829003601f168201915b505050505091509250925092509193909250565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60606000341180612d225750600082115b612d625760405162461bcd60e51b81526020600482015260116024820152704e4f5f5a45524f5f444f4e4154494f4e5360781b6044820152606401610b84565b823415612dce5760006064612d79346016546139a7565b612d839190614a15565b90506000612d91348361339e565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612dca573d6000803e3d6000fd5b5050505b8215612e0c5760006064612de4856016546139a7565b612dee9190614a15565b90506000612dfc858361339e565b9050612e093384836135e4565b50505b50506040805180820190915260078152661113d39055115160ca1b602082015292915050565b6005546001600160a01b03610100909104163314612e625760405162461bcd60e51b8152600401610b8490614997565b601555565b60408051808201909152600080825260208201526001600160a01b0383166000908152600960205260409020805463ffffffff8416908110612eab57612eab614c1a565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b6005546001600160a01b03610100909104163314612f1b5760405162461bcd60e51b8152600401610b8490614997565b6001600160a01b038116612f805760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b84565b611d4481613c04565b6005546001600160a01b03610100909104163314612fb95760405162461bcd60e51b8152600401610b8490614997565b611cb6308383612fc93087612ce6565b61163d9190614b44565b6005546001600160a01b036101009091041633146130035760405162461bcd60e51b8152600401610b8490614997565b600b5460ff16156130475760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4105554d15160921b6044820152606401610b84565b600b805460ff19166001179055565b6000600f82604051613068919061493e565b9081526040519081900360200190205460ff1692915050565b6005546001600160a01b036101009091041633146130b15760405162461bcd60e51b8152600401610b8490614997565b600b54610100900460ff16156130fa5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4105554d15160921b6044820152606401610b84565b600b805461ff001916610100179055565b613115828261319b565b6002546001600160e01b0310156131875760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b6064820152608401610b84565b613195600a61328e83613c5e565b50505050565b6001600160a01b0382166131f15760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610b84565b6131fd60008383613dd7565b806002600082825461320f91906149fd565b90915550506001600160a01b0382166000908152602081905260408120805483929061323c9084906149fd565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3611cb660008383613e1d565b60006116b582846149fd565b60006001600160e01b038211156133035760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610b84565b5090565b600063ffffffff8211156133035760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610b84565b6001600160a01b03838116600090815260086020526040808220548584168352912054611d3592918216911683613e28565b60006116b58284614b44565b81518151600091849184919081146133c85760009350505050610e23565b60005b8181101561343f578281815181106133e5576133e5614c1a565b602001015160f81c60f81b6001600160f81b03191684828151811061340c5761340c614c1a565b01602001516001600160f81b0319161461342d576000945050505050610e23565b8061343781614bd3565b9150506133cb565b5060019695505050505050565b6001600160a01b0383166134ae5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610b84565b6001600160a01b03821661350f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610b84565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061357c8484612ce6565b9050600019811461319557818110156135d75760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610b84565b613195848484840361344c565b6001600160a01b0383166136485760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610b84565b6001600160a01b0382166136aa5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610b84565b6136b5838383613dd7565b6001600160a01b0383166000908152602081905260409020548181101561372d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610b84565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906137649084906149fd565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516137b091815260200190565b60405180910390a3613195848484613e1d565b6000306001600160a01b037f000000000000000000000000c5be1810491304be6cd72e642f0cd701312e86081614801561381c57507f000000000000000000000000000000000000000000000000000000000000000146145b1561384657507f51ab41f2177b5e8808ea2b18f1bbac1eeb91cb9e193d91f312a2159b0efc644790565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f2ef5775a41eea7e3b4b9111d971d20a8edb90ec6a0019b059510a85f7d3b7e76828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b8154600090815b8181101561394e5760006139058284613f65565b90508486828154811061391a5761391a614c1a565b60009182526020909120015463ffffffff16111561393a57809250613948565b6139458160016149fd565b91505b506138f1565b81156139925784613960600184614b44565b8154811061397057613970614c1a565b60009182526020909120015464010000000090046001600160e01b0316613995565b60005b6001600160e01b031695945050505050565b60006116b58284614b25565b60055460ff166139fc5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b84565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b611cb6828261310b565b611cb68282613f80565b6000613a686004600a614a7a565b610e239083614a15565b6001600160a01b038281166000818152600860208181526040808420805485845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4613195828483613e28565b60055460ff1615613b315760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b84565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613a293390565b6000610e23613b736137c3565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000613bc587878787613f98565b91509150613bd281614085565b5095945050505050565b6001600160a01b03811660009081526006602052604090208054600181018255905b50919050565b600580546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b825460009081908015613ca95785613c77600183614b44565b81548110613c8757613c87614c1a565b60009182526020909120015464010000000090046001600160e01b0316613cac565b60005b6001600160e01b03169250613cc583858763ffffffff16565b9150600081118015613d0357504386613cdf600184614b44565b81548110613cef57613cef614c1a565b60009182526020909120015463ffffffff16145b15613d6357613d118261329a565b86613d1d600184614b44565b81548110613d2d57613d2d614c1a565b9060005260206000200160000160046101000a8154816001600160e01b0302191690836001600160e01b03160217905550613dce565b856040518060400160405280613d7843613307565b63ffffffff168152602001613d8c8561329a565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b50935093915050565b60055460ff1615611d355760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b84565b611d3583838361336c565b816001600160a01b0316836001600160a01b031614158015613e4a5750600081115b15611d35576001600160a01b03831615613ed8576001600160a01b03831660009081526009602052604081208190613e859061339e85613c5e565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051613ecd929190918252602082015260400190565b60405180910390a250505b6001600160a01b03821615611d35576001600160a01b03821660009081526009602052604081208190613f0e9061328e85613c5e565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051613f56929190918252602082015260400190565b60405180910390a25050505050565b6000613f746002848418614a15565b6116b5908484166149fd565b613f8a8282614240565b613195600a61339e83613c5e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613fcf575060009050600361407c565b8460ff16601b14158015613fe757508460ff16601c14155b15613ff8575060009050600461407c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561404c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166140755760006001925092505061407c565b9150600090505b94509492505050565b600081600481111561409957614099614c04565b14156140a25750565b60018160048111156140b6576140b6614c04565b14156141045760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b84565b600281600481111561411857614118614c04565b14156141665760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b84565b600381600481111561417a5761417a614c04565b14156141d35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610b84565b60048160048111156141e7576141e7614c04565b1415611d445760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610b84565b6001600160a01b0382166142a05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610b84565b6142ac82600083613dd7565b6001600160a01b038216600090815260208190526040902054818110156143205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610b84565b6001600160a01b038316600090815260208190526040812083830390556002805484929061434f908490614b44565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3611d3583600084613e1d565b8280546143ad90614b9e565b90600052602060002090601f0160209004810192826143cf5760008555614415565b82601f106143e857805160ff1916838001178555614415565b82800160010185558215614415579182015b828111156144155782518255916020019190600101906143fa565b506133039291505b80821115613303576000815560010161441d565b600082601f83011261444257600080fd5b813567ffffffffffffffff8082111561445d5761445d614c30565b604051601f8301601f19908116603f0116810190828211818310171561448557614485614c30565b8160405283815286602085880101111561449e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff8116811461160c57600080fd5b6000602082840312156144e157600080fd5b81356116b581614c46565b6000602082840312156144fe57600080fd5b81516116b581614c46565b6000806040838503121561451c57600080fd5b823561452781614c46565b9150602083013561453781614c46565b809150509250929050565b60008060006060848603121561455757600080fd5b833561456281614c46565b9250602084013561457281614c46565b929592945050506040919091013590565b600080600080600080600060e0888a03121561459e57600080fd5b87356145a981614c46565b965060208801356145b981614c46565b955060408801359450606088013593506145d5608089016144be565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561460457600080fd5b823561460f81614c46565b946020939093013593505050565b60008060008060008060c0878903121561463657600080fd5b863561464181614c46565b9550602087013594506040870135935061465d606088016144be565b92506080870135915060a087013590509295509295509295565b6000806040838503121561468a57600080fd5b823561469581614c46565b9150602083013563ffffffff8116811461453757600080fd5b6000602082840312156146c057600080fd5b813567ffffffffffffffff8111156146d757600080fd5b6146e384828501614431565b949350505050565b600080600080600060a0868803121561470357600080fd5b853567ffffffffffffffff8082111561471b57600080fd5b61472789838a01614431565b965060208801359150811515821461473e57600080fd5b909450604087013593506060870135908082111561475b57600080fd5b5061476888828901614431565b925050608086013561477981614c46565b809150509295509295909350565b60008060006060848603121561479c57600080fd5b833567ffffffffffffffff808211156147b457600080fd5b6147c087838801614431565b945060208601359150808211156147d657600080fd5b506147e386828701614431565b925050604084013590509250925092565b6000806000806080858703121561480a57600080fd5b843567ffffffffffffffff8082111561482257600080fd5b61482e88838901614431565b9550602087013591508082111561484457600080fd5b5061485187828801614431565b93505060408501359150606085013561486981614c46565b939692955090935050565b60006020828403121561488657600080fd5b5035919050565b60006020828403121561489f57600080fd5b5051919050565b600080604083850312156148b957600080fd5b82359150602083013561453781614c46565b600080604083850312156148de57600080fd5b82359150602083013567ffffffffffffffff8111156148fc57600080fd5b61490885828601614431565b9150509250929050565b6000815180845261492a816020860160208601614b5b565b601f01601f19169290920160200192915050565b60008251614950818460208701614b5b565b9190910192915050565b6020815260006116b56020830184614912565b60208082526010908201526f494e56414c49445f43555252454e435960801b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b8381526060602082015260006149e56060830185614912565b905060018060a01b0383166040830152949350505050565b60008219821115614a1057614a10614bee565b500190565b600082614a3257634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115614a72578160001904821115614a5857614a58614bee565b80851615614a6557918102915b93841c9390800290614a3c565b509250929050565b60006116b560ff841683600082614a9357506001610e23565b81614aa057506000610e23565b8160018114614ab65760028114614ac057614adc565b6001915050610e23565b60ff841115614ad157614ad1614bee565b50506001821b610e23565b5060208310610133831016604e8410600b8410161715614aff575081810a610e23565b614b098383614a37565b8060001904821115614b1d57614b1d614bee565b029392505050565b6000816000190483118215151615614b3f57614b3f614bee565b500290565b600082821015614b5657614b56614bee565b500390565b60005b83811015614b76578181015183820152602001614b5e565b838111156131955750506000910152565b600081614b9657614b96614bee565b506000190190565b600181811c90821680614bb257607f821691505b60208210811415613bfe57634e487b7160e01b600052602260045260246000fd5b6000600019821415614be757614be7614bee565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611d4457600080fdfea2646970667358221220e4fea938bbc9229cb7cdcf617e147b2361d02ef2de66896c534bc5054b2da8c164736f6c63430008070033

Deployed Bytecode Sourcemap

150650:14848:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;164045:147;;;;;;;;;;;;;:::i;125928:100::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;159274:471;;;;;;;;;;-1:-1:-1;159274:471:0;;;;;:::i;:::-;;:::i;128279:201::-;;;;;;;;;;-1:-1:-1;128279:201:0;;;;;:::i;:::-;;:::i;:::-;;;9898:14:1;;9891:22;9873:41;;9861:2;9846:18;128279:201:0;9733:187:1;152157:130:0;;;;;;;;;;-1:-1:-1;152157:130:0;;;;;:::i;:::-;152237:22;:42;152157:130;157948:517;;;;;;;;;;-1:-1:-1;157948:517:0;;;;;:::i;:::-;;:::i;156746:818::-;;;;;;;;;;-1:-1:-1;156746:818:0;;;;;:::i;:::-;;:::i;:::-;;;10071:25:1;;;10059:2;10044:18;156746:818:0;9925:177:1;152418:140:0;;;;;;;;;;-1:-1:-1;152418:140:0;;;;;:::i;:::-;;:::i;127048:108::-;;;;;;;;;;-1:-1:-1;127136:12:0;;127048:108;;129060:295;;;;;;;;;;-1:-1:-1;129060:295:0;;;;;:::i;:::-;;:::i;155742:996::-;;;;;;;;;;;;;:::i;160285:274::-;;;;;;;;;;-1:-1:-1;160285:274:0;;;;;:::i;:::-;;:::i;153270:75::-;;;;;;;;;;-1:-1:-1;153270:75:0;;153339:1;29554:36:1;;29542:2;29527:18;153270:75:0;29412:184:1;139533:115:0;;;;;;;;;;;;;:::i;129764:238::-;;;;;;;;;;-1:-1:-1;129764:238:0;;;;;:::i;:::-;;:::i;142735:268::-;;;;;;;;;;-1:-1:-1;142735:268:0;;;;;:::i;:::-;;:::i;161272:1363::-;;;;;;:::i;:::-;;:::i;153422:65::-;;;;;;;;;;;;;:::i;163738:147::-;;;;;;;;;;;;;:::i;164548:95::-;;;;;;;;;;-1:-1:-1;164548:95:0;;;;;:::i;:::-;;:::i;164200:166::-;;;;;;;;;;-1:-1:-1;164200:166:0;;;;;:::i;:::-;;:::i;154069:131::-;;;;;;;;;;-1:-1:-1;154069:131:0;;;;;:::i;:::-;;:::i;149944:91::-;;;;;;;;;;-1:-1:-1;149944:91:0;;;;;:::i;:::-;;:::i;154551:1183::-;;;;;;;;;;;;;:::i;153495:174::-;;;;;;;;;;;;;:::i;151835:170::-;;;;;;;;;;-1:-1:-1;151835:170:0;;;;;:::i;:::-;;:::i;142109:128::-;;;;;;;;;;-1:-1:-1;142109:128:0;;;;;:::i;:::-;-1:-1:-1;;;;;142210:19:0;;;142183:7;142210:19;;;:10;:19;;;;;;;;142109:128;;;;-1:-1:-1;;;;;9410:32:1;;;9392:51;;9380:2;9365:18;142109:128:0;9246:203:1;163440:138:0;;;;;;;;;;-1:-1:-1;163440:138:0;;;;;:::i;:::-;;:::i;145208:114::-;;;;;;;;;;-1:-1:-1;145208:114:0;;;;;:::i;:::-;;:::i;118982:86::-;;;;;;;;;;-1:-1:-1;119053:7:0;;;;118982:86;;154208:107;;;;;;;;;;-1:-1:-1;154208:107:0;;;;;:::i;:::-;;:::i;160567:327::-;;;;;;;;;;-1:-1:-1;160567:327:0;;;;;:::i;:::-;;:::i;141865:151::-;;;;;;;;;;-1:-1:-1;141865:151:0;;;;;:::i;:::-;;:::i;:::-;;;29389:10:1;29377:23;;;29359:42;;29347:2;29332:18;141865:151:0;29215:192:1;127219:127:0;;;;;;;;;;-1:-1:-1;127219:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;127320:18:0;127293:7;127320:18;;;;;;;;;;;;127219:127;152566:144;;;;;;;;;;-1:-1:-1;152566:144:0;;;;;:::i;:::-;;:::i;150354:164::-;;;;;;;;;;-1:-1:-1;150354:164:0;;;;;:::i;:::-;;:::i;139275:128::-;;;;;;;;;;-1:-1:-1;139275:128:0;;;;;:::i;:::-;;:::i;153353:61::-;;;;;;;;;;;;;:::i;116389:87::-;;;;;;;;;;-1:-1:-1;116462:6:0;;;;;-1:-1:-1;;;;;116462:6:0;116389:87;;143292:259;;;;;;;;;;-1:-1:-1;143292:259:0;;;;;:::i;:::-;;:::i;152013:136::-;;;;;;;;;;-1:-1:-1;152013:136:0;;;;;:::i;:::-;;:::i;153888:173::-;;;:::i;152859:145::-;;;;;;;;;;-1:-1:-1;152859:145:0;;;;;:::i;:::-;;:::i;126147:104::-;;;;;;;;;;;;;:::i;159753:524::-;;;;;;;;;;-1:-1:-1;159753:524:0;;;;;:::i;:::-;;:::i;142321:212::-;;;;;;;;;;-1:-1:-1;142321:212:0;;;;;:::i;:::-;;:::i;130505:436::-;;;;;;;;;;-1:-1:-1;130505:436:0;;;;;:::i;:::-;;:::i;152295:115::-;;;;;;;;;;-1:-1:-1;152380:22:0;;152295:115;;127552:193;;;;;;;;;;-1:-1:-1;127552:193:0;;;;;:::i;:::-;;:::i;145404:591::-;;;;;;;;;;-1:-1:-1;145404:591:0;;;;;:::i;:::-;;:::i;138564:645::-;;;;;;;;;;-1:-1:-1;138564:645:0;;;;;:::i;:::-;;:::i;158473:793::-;;;;;;:::i;:::-;;:::i;153677:203::-;;;;;;;;;;-1:-1:-1;153677:203:0;;;;;:::i;:::-;;:::i;160902:245::-;;;;;;;;;;-1:-1:-1;160902:245:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;127808:151::-;;;;;;;;;;-1:-1:-1;127808:151:0;;;;;:::i;:::-;;:::i;162643:789::-;;;;;;:::i;:::-;;:::i;152718:133::-;;;;;;;;;;-1:-1:-1;152718:133:0;;;;;:::i;:::-;;:::i;141635:150::-;;;;;;;;;;-1:-1:-1;141635:150:0;;;;;:::i;:::-;;:::i;:::-;;;;28260:13:1;;28275:10;28256:30;28238:49;;28347:4;28335:17;;;28329:24;-1:-1:-1;;;;;28325:50:1;28303:20;;;28296:80;;;;28211:18;141635:150:0;28036:346:1;117291:201:0;;;;;;;;;;-1:-1:-1;117291:201:0;;;;;:::i;:::-;;:::i;164374:166::-;;;;;;;;;;-1:-1:-1;164374:166:0;;;;;:::i;:::-;;:::i;163586:144::-;;;;;;;;;;;;;:::i;161155:109::-;;;;;;;;;;-1:-1:-1;161155:109:0;;;;;:::i;:::-;;:::i;163893:144::-;;;;;;;;;;;;;:::i;164045:147::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;;;;;;;;;164111:17:::1;::::0;::::1;::::0;::::1;;;164103:45;;;::::0;-1:-1:-1;;;164103:45:0;;21160:2:1;164103:45:0::1;::::0;::::1;21142:21:1::0;21199:2;21179:18;;;21172:30;-1:-1:-1;;;21218:18:1;;;21211:45;21273:18;;164103:45:0::1;20958:339:1::0;164103:45:0::1;164159:17;:25:::0;;-1:-1:-1;;164159:25:0::1;::::0;;164045:147::o;125928:100::-;125982:13;126015:5;126008:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125928:100;:::o;159274:471::-;116462:6;;159421:13;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;159455:30:::1;159469:8;159455:30;;;;;;;;;;;;;-1:-1:-1::0;;;159455:30:0::1;;::::0;:13:::1;:30::i;:::-;:65;;;;159489:31;159503:8;159489:31;;;;;;;;;;;;;-1:-1:-1::0;;;159489:31:0::1;;::::0;:13:::1;:31::i;:::-;159447:94;;;;-1:-1:-1::0;;;159447:94:0::1;;;;;;;:::i;:::-;159570:6;159554;159561:5;159554:13;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:22;;;::::1;;-1:-1:-1::0;;159554:22:0;;::::1;::::0;;;::::1;::::0;;;159608:5;;159587:11:::1;::::0;:18:::1;::::0;159599:5;;159587:18:::1;:::i;:::-;;;;;;;;;;;;;:26;;;;159648:8;159624:14;159639:5;159624:21;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;;;;;;;;;;:::i;:::-;;159690:15;159667:13;159681:5;159667:20;;;;;;:::i;:::-;;;;;;;;;;;;;;:38;;;;;-1:-1:-1::0;;;;;159667:38:0::1;;;;;-1:-1:-1::0;;;;;159667:38:0::1;;;;;;159716:21;;;;;;;;;;;;;-1:-1:-1::0;;;159716:21:0::1;;::::0;::::1;;159274:471:::0;;;;;;;:::o;128279:201::-;128362:4;93513:10;128418:32;93513:10;128434:7;128443:6;128418:8;:32::i;:::-;128468:4;128461:11;;;128279:201;;;;;:::o;157948:517::-;116462:6;;158084:13;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;158118:6:::1;158125:5;158118:13;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;;::::1;;:22;158110:47;;;::::0;-1:-1:-1;;;158110:47:0;;21907:2:1;158110:47:0::1;::::0;::::1;21889:21:1::0;21946:2;21926:18;;;21919:30;-1:-1:-1;;;21965:18:1;;;21958:42;22017:18;;158110:47:0::1;21705:336:1::0;158110:47:0::1;158176:30;158190:8;158176:30;;;;;;;;;;;;;-1:-1:-1::0;;;158176:30:0::1;;::::0;:13:::1;:30::i;:::-;:65;;;;158210:31;158224:8;158210:31;;;;;;;;;;;;;-1:-1:-1::0;;;158210:31:0::1;;::::0;:13:::1;:31::i;:::-;158168:94;;;;-1:-1:-1::0;;;158168:94:0::1;;;;;;;:::i;:::-;158291:4;158275:6;158282:5;158275:13;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:20;;;::::1;;-1:-1:-1::0;;158275:20:0;;::::1;::::0;;;::::1;::::0;;;158327:5;;158306:11:::1;::::0;:18:::1;::::0;158318:5;;158306:18:::1;:::i;:::-;;;;;;;;;;;;;:26;;;;158367:8;158343:14;158358:5;158343:21;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;;;;;;;;;;:::i;:::-;;158409:15;158386:13;158400:5;158386:20;;;;;;:::i;:::-;;;;;;;;;;;;;;:38;;;;;-1:-1:-1::0;;;;;158386:38:0::1;;;;;-1:-1:-1::0;;;;;158386:38:0::1;;;;;;158435:22;;;;;;;;;;;;;-1:-1:-1::0;;;158435:22:0::1;;::::0;::::1;;157948:517:::0;;;;;;:::o;156746:818::-;156835:2;;:18;;-1:-1:-1;;;156835:18:0;;;;;10071:25:1;;;156807:7:0;;;;-1:-1:-1;;;;;156835:2:0;;;;:10;;10044:18:1;;156835::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;156835:32:0;;;156827:59;;;;-1:-1:-1;;;156827:59:0;;26785:2:1;156827:59:0;;;26767:21:1;26824:2;26804:18;;;26797:30;-1:-1:-1;;;26843:18:1;;;26836:44;26897:18;;156827:59:0;26583:338:1;156827:59:0;156917:2;;:16;;;-1:-1:-1;;;156917:16:0;;;;156897:17;;-1:-1:-1;;;;;156917:2:0;;:14;;:16;;;;;;;;;;;;;;:2;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156954:14;157016:17;;;:12;:17;;;;;;;;:28;;;;;;;;;156897:36;;-1:-1:-1;156954:14:0;156994:6;;157016:28;;:36;;:28;:36;157013:76;;;-1:-1:-1;157076:1:0;;156746:818;-1:-1:-1;;;;156746:818:0:o;157013:76::-;157129:9;157101:432;157141:16;;157101:432;;157193:17;;;;:12;:17;;;;;;;;:31;;;;;;;;;;;:39;;:31;:39;157190:332;;;157253:5;;157190:332;157331:3;157315:12;:19;157312:195;;157403:12;157378:22;;:37;;;;:::i;:::-;157368:48;;:6;:48;:::i;:::-;157359:57;;157312:195;;;157482:5;;157312:195;157159:14;;;;:::i;:::-;;;;157101:432;;;-1:-1:-1;157550:6:0;;156746:818;-1:-1:-1;;;;156746:818:0:o;152418:140::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;152508:19:::1;:42:::0;152418:140::o;129060:295::-;129191:4;93513:10;129249:38;129265:4;93513:10;129280:6;129249:15;:38::i;:::-;129298:27;129308:4;129314:2;129318:6;129298:9;:27::i;:::-;-1:-1:-1;129343:4:0;;129060:295;-1:-1:-1;;;;129060:295:0:o;155742:996::-;155836:2;;:24;;-1:-1:-1;;;155836:24:0;;155849:10;155836:24;;;9392:51:1;155789:7:0;;;;-1:-1:-1;;;;;155836:2:0;;;;:12;;9365:18:1;;155836:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;155809:51;;155871:17;155891:2;;;;;;;;;-1:-1:-1;;;;;155891:2:0;-1:-1:-1;;;;;155891:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;155871:36;;155918:14;155961;155957:750;155993:16;155981:9;:28;155957:750;;;156052:2;;:45;;-1:-1:-1;;;156052:45:0;;156075:10;156052:45;;;9628:51:1;9695:18;;;9688:34;;;156041:8:0;;-1:-1:-1;;;;;156052:2:0;;:22;;9601:18:1;;156052:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156117:17;;;;:12;:17;;;;;;;;:28;;;;;;;;;156041:56;;-1:-1:-1;156117:28:0;;:36;;:28;:36;156114:84;;;156181:1;156174:8;;;;;;;155742:996;:::o;156114:84::-;156242:9;156214:480;156254:16;;156214:480;;156310:17;;;;:12;:17;;;;;;;;:31;;;;;;;;;;;:39;;:31;:39;156307:372;;;156374:5;;156307:372;156464:3;156448:12;:19;156445:215;;156540:12;156515:22;;:37;;;;:::i;:::-;156505:48;;:6;:48;:::i;:::-;156496:57;;156445:215;;;156631:5;;156445:215;156272:14;;;;:::i;:::-;;;;156214:480;;;;156024:683;156011:11;;;;;:::i;:::-;;;;155957:750;;;-1:-1:-1;156724:6:0;155742:996;-1:-1:-1;;;155742:996:0:o;160285:274::-;116462:6;;160357:13;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;160399:5:::1;160383:6;160390:5;160383:13;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:21;;;::::1;;-1:-1:-1::0;;160383:21:0;;::::1;::::0;;;::::1;::::0;;;:13:::1;::::0;160415:11:::1;::::0;:18:::1;::::0;160427:5;;160415:18:::1;:::i;:::-;;;;;;;;;;;;;:22;;;;160448:26;;;;;;;;;;;::::0;:14:::1;160463:5;160448:21;;;;;;:::i;:::-;;;;;;;;;;;;;:26;;;;;;;;;;;;:::i;:::-;;160516:1;160485:13;160499:5;160485:20;;;;;;:::i;:::-;;;;;;;;;;;;;;:33;;;;;-1:-1:-1::0;;;;;160485:33:0::1;;;;;-1:-1:-1::0;;;;;160485:33:0::1;;;;;;160529:22;;;;;;;;;;;;;-1:-1:-1::0;;;160529:22:0::1;;::::0;::::1;;116680:1;160285:274:::0;;;:::o;139533:115::-;139593:7;139620:20;:18;:20::i;:::-;139613:27;;139533:115;:::o;129764:238::-;129852:4;93513:10;129908:64;93513:10;129924:7;129961:10;129933:25;93513:10;129924:7;129933:9;:25::i;:::-;:38;;;;:::i;:::-;129908:8;:64::i;142735:268::-;142833:7;142875:12;142861:11;:26;142853:70;;;;-1:-1:-1;;;142853:70:0;;13889:2:1;142853:70:0;;;13871:21:1;13928:2;13908:18;;;13901:30;13967:33;13947:18;;;13940:61;14018:18;;142853:70:0;13687:355:1;142853:70:0;-1:-1:-1;;;;;142960:21:0;;;;;;:12;:21;;;;;142941:54;;142983:11;142941:18;:54::i;:::-;142934:61;142735:268;-1:-1:-1;;;142735:268:0:o;161272:1363::-;154489:17;;161371:13;;154489:17;;;;;154488:18;154480:43;;;;-1:-1:-1;;;154480:43:0;;12802:2:1;154480:43:0;;;12784:21:1;12841:2;12821:18;;;12814:30;-1:-1:-1;;;12860:18:1;;;12853:42;12912:18;;154480:43:0;12600:336:1;154480:43:0;161417:2:::1;::::0;:18:::1;::::0;-1:-1:-1;;;161417:18:0;;::::1;::::0;::::1;10071:25:1::0;;;161397:17:0::1;::::0;-1:-1:-1;;;;;161417:2:0::1;::::0;:10:::1;::::0;10044:18:1;;161417::0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;161397:38:::0;-1:-1:-1;;;;;;161454:23:0;::::1;161467:10;161454:23;161446:49;;;::::0;-1:-1:-1;;;161446:49:0;;13143:2:1;161446:49:0::1;::::0;::::1;13125:21:1::0;13182:2;13162:18;;;13155:30;-1:-1:-1;;;13201:18:1;;;13194:43;13254:18;;161446:49:0::1;12941:337:1::0;161446:49:0::1;161514:6;161521:5;161514:13;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;;::::1;;161506:41;;;::::0;-1:-1:-1;;;161506:41:0;;26441:2:1;161506:41:0::1;::::0;::::1;26423:21:1::0;26480:2;26460:18;;;26453:30;-1:-1:-1;;;26499:18:1;;;26492:45;26554:18;;161506:41:0::1;26239:339:1::0;161506:41:0::1;161563:20;::::0;;;:12:::1;:20;::::0;;;;;;:27;;::::1;::::0;161584:5;;161563:27:::1;:::i;:::-;;;;;;;;;;;;;;161594:1;161563:32;161560:89;;161612:25;::::0;-1:-1:-1;;;161612:25:0;;27894:2:1;161612:25:0::1;::::0;::::1;27876:21:1::0;27933:2;27913:18;;;27906:30;-1:-1:-1;;;27952:18:1;;;27945:45;28007:18;;161612:25:0::1;27692:339:1::0;161560:89:0::1;161661:13;161677:11;161689:5;161677:18;;;;;;:::i;:::-;;;;;;;;;;;;;;161661:34;;161706:22;161731:14;161746:5;161731:21;;;;;;:::i;:::-;;;;;;;;;;;;;161706:46;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;161776:1;161768:5;:9;161765:778;;;161797:30;161811:8;161797:30;;;;;;;;;;;;;-1:-1:-1::0;;;161797:30:0::1;;::::0;:13:::1;:30::i;:::-;161794:738;;;161869:5;161856:9;:18;;161848:53;;;::::0;-1:-1:-1;;;161848:53:0;;19027:2:1;161848:53:0::1;::::0;::::1;19009:21:1::0;19066:2;19046:18;;;19039:30;-1:-1:-1;;;19085:18:1;;;19078:52;19147:18;;161848:53:0::1;18825:346:1::0;161848:53:0::1;161920:23;161946:13;161960:5;161946:20;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;161946:20:0::1;161920:46;;161985:16;162046:3;162004:39;162017:5;162024:18;;162004:12;:39::i;:::-;:45;;;;:::i;:::-;161985:64;;162076:15;-1:-1:-1::0;;;;;162068:33:0::1;:64;162102:29;162115:5;162122:8;162102:12;:29::i;:::-;162068:64;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;161829:319;;161794:738;;;162170:31;162184:8;162170:31;;;;;;;;;;;;;-1:-1:-1::0;;;162170:31:0::1;;::::0;:13:::1;:31::i;:::-;162167:365;;;162240:10;127293:7:::0;127320:18;;;;;;;;;;;162255:5;-1:-1:-1;162230:30:0::1;162222:58;;;::::0;-1:-1:-1;;;162222:58:0;;20816:2:1;162222:58:0::1;::::0;::::1;20798:21:1::0;20855:2;20835:18;;;20828:30;-1:-1:-1;;;20874:18:1;;;20867:45;20929:18;;162222:58:0::1;20614:339:1::0;162222:58:0::1;162299:23;162325:13;162339:5;162325:20;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;162325:20:0::1;162299:46;;162364:16;162425:3;162383:39;162396:5;162403:18;;162383:12;:39::i;:::-;:45;;;;:::i;:::-;162364:64;;162447:69;162457:10;162469:15;162486:29;162499:5;162506:8;162486:12;:29::i;:::-;162447:9;:69::i;:::-;162203:329;;162167:365;162585:15;162555:12;:20;162568:6;162555:20;;;;;;;;;;;162576:5;162555:27;;;;;;:::i;:::-;;;;;;;;;;;;;:45;;;;162611:16;;;;;;;;;;;;;-1:-1:-1::0;;;162611:16:0::1;;::::0;::::1;;;;;161272:1363:::0;;;;:::o;153422:65::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;153469:10:::1;:8;:10::i;:::-;153422:65::o:0;163738:147::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;163804:17:::1;::::0;::::1;;163796:45;;;::::0;-1:-1:-1;;;163796:45:0;;21160:2:1;163796:45:0::1;::::0;::::1;21142:21:1::0;21199:2;21179:18;;;21172:30;-1:-1:-1;;;21218:18:1;;;21211:45;21273:18;;163796:45:0::1;20958:339:1::0;163796:45:0::1;163852:17;:25:::0;;-1:-1:-1;;163852:25:0::1;::::0;;163738:147::o;164548:95::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;164618:17:::1;164624:2;164628:6;164618:5;:17::i;:::-;164548:95:::0;;:::o;164200:166::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;164292:66:::1;164309:4;164316:2;164351:6;164320:28;164338:4;164345:2;164320:9;:28::i;154069:131::-:0;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;154165:27:::1;154175:4;154181:2;154185:6;154165:9;:27::i;:::-;154069:131:::0;;;:::o;149944:91::-;150000:27;93513:10;150020:6;150000:5;:27::i;:::-;149944:91;:::o;154551:1183::-;154375:17;;154611:13;;154375:17;;154374:18;154366:43;;;;-1:-1:-1;;;154366:43:0;;12802:2:1;154366:43:0;;;12784:21:1;12841:2;12821:18;;;12814:30;-1:-1:-1;;;12860:18:1;;;12853:42;12912:18;;154366:43:0;12600:336:1;154366:43:0;154657:2:::1;::::0;:16:::1;::::0;;-1:-1:-1;;;154657:16:0;;;;154637:17:::1;::::0;-1:-1:-1;;;;;154657:2:0::1;::::0;:14:::1;::::0;:16:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;:2;:16;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154711:2;::::0;:24:::1;::::0;-1:-1:-1;;;154711:24:0;;154724:10:::1;154711:24;::::0;::::1;9392:51:1::0;154637:36:0;;-1:-1:-1;154684:24:0::1;::::0;-1:-1:-1;;;;;154711:2:0;;::::1;::::0;:12:::1;::::0;9365:18:1;;154711:24:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154684:51;;154746:14;154804:1:::0;154785:16:::1;:20;154777:40;;;::::0;-1:-1:-1;;;154777:40:0;;14598:2:1;154777:40:0::1;::::0;::::1;14580:21:1::0;14637:1;14617:18;;;14610:29;-1:-1:-1;;;14655:18:1;;;14648:37;14702:18;;154777:40:0::1;14396:330:1::0;154777:40:0::1;154834:14;154830:815;154866:16;154854:9;:28;154830:815;;;154925:2;::::0;:45:::1;::::0;-1:-1:-1;;;154925:45:0;;154948:10:::1;154925:45;::::0;::::1;9628:51:1::0;9695:18;;;9688:34;;;154914:8:0::1;::::0;-1:-1:-1;;;;;154925:2:0::1;::::0;:22:::1;::::0;9601:18:1;;154925:45:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154990:17;::::0;;;:12:::1;:17;::::0;;;;;;;:28;;;;;;;;;154914:56;;-1:-1:-1;154990:28:0::1;;:36;;:28:::0;:36:::1;154987:101;;;155047:25;::::0;-1:-1:-1;;;155047:25:0;;27894:2:1;155047:25:0::1;::::0;::::1;27876:21:1::0;27933:2;27913:18;;;27906:30;-1:-1:-1;;;27952:18:1;;;27945:45;28007:18;;155047:25:0::1;27692:339:1::0;154987:101:0::1;155132:9:::0;155104:480:::1;155144:16:::0;;155104:480:::1;;155200:17;::::0;;;:12:::1;:17;::::0;;;;;;;:31;;;;;;;;;::::1;;:39;;:31:::0;:39:::1;155197:372;;;155264:5;;155197:372;155354:3;155338:12;:19;155335:215;;155430:12;155405:22;;:37;;;;:::i;:::-;155395:48;::::0;:6;:48:::1;:::i;:::-;155386:57;;155335:215;;;155521:5;;155335:215;155162:14:::0;::::1;::::0;::::1;:::i;:::-;;;;155104:480;;;-1:-1:-1::0;155598:17:0::1;::::0;;;:12:::1;:17;::::0;;;;;;;:28;;;;;;;;:35;;-1:-1:-1;;155598:35:0::1;155629:4;155598:35;::::0;;154884:11;::::1;::::0;::::1;:::i;:::-;;;;154830:815;;;;155655:44;155673:4;155680:10;155692:6;155655:9;:44::i;:::-;155710:16;;;;;;;;;;;;;-1:-1:-1::0;;;155710:16:0::1;;::::0;::::1;;;;;154551:1183:::0;:::o;153495:174::-;153541:7;153561:18;153606:27;153619:13;127136:12;;;127048:108;153619:13;153606:12;:27::i;:::-;153582:51;;:21;:51;:::i;151835:170::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;151916:10:::1;:37:::0;;-1:-1:-1;;;;;151916:37:0;;::::1;-1:-1:-1::0;;;;;;151916:37:0;;::::1;::::0;::::1;::::0;;;151964:2:::1;:33:::0;;;;::::1;;::::0;;151835:170::o;163440:138::-;163519:7;163546:17;;;:12;:17;;;;;;:24;;;;163564:5;;163546:24;:::i;:::-;;;;;;;;;;;;;;163539:31;;163440:138;;;;:::o;145208:114::-;145280:34;93513:10;145304:9;145280;:34::i;154208:107::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;154288:19:::1;154294:4;154300:6;154288:5;:19::i;160567:327::-:0;160625:13;160683:10;-1:-1:-1;;;;;160659:34:0;:13;160673:5;160659:20;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;160659:20:0;:34;160651:56;;;;-1:-1:-1;;;160651:56:0;;26104:2:1;160651:56:0;;;26086:21:1;26143:1;26123:18;;;26116:29;-1:-1:-1;;;26161:18:1;;;26154:39;26210:18;;160651:56:0;25902:332:1;141865:151:0;-1:-1:-1;;;;;141979:21:0;;141935:6;141979:21;;;:12;:21;;;;;:28;141961:47;;:17;:47::i;152566:144::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;152658:20:::1;:44:::0;152566:144::o;150354:164::-;150431:46;150447:7;93513:10;150470:6;150431:15;:46::i;139275:128::-;-1:-1:-1;;;;;139371:14:0;;139344:7;139371:14;;;:7;:14;;;;;74160;139371:24;74068:114;153353:61;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;153398:8:::1;:6;:8::i;143292:259::-:0;143379:7;143421:12;143407:11;:26;143399:70;;;;-1:-1:-1;;;143399:70:0;;13889:2:1;143399:70:0;;;13871:21:1;13928:2;13908:18;;;13901:30;13967:33;13947:18;;;13940:61;14018:18;;143399:70:0;13687:355:1;143399:70:0;143487:56;143506:23;143531:11;143487:18;:56::i;152013:136::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;152105:15:::1;:36:::0;;-1:-1:-1;;;;;;152105:36:0::1;-1:-1:-1::0;;;;;152105:36:0;;;::::1;::::0;;;::::1;::::0;;152013:136::o;153888:173::-;116462:6;;153956:13;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;154002:1:::1;153990:9;:13;153982:42;;;::::0;-1:-1:-1;;;153982:42:0;;20126:2:1;153982:42:0::1;::::0;::::1;20108:21:1::0;20165:2;20145:18;;;20138:30;-1:-1:-1;;;20184:18:1;;;20177:46;20240:18;;153982:42:0::1;19924:340:1::0;153982:42:0::1;-1:-1:-1::0;154035:18:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;154035:18:0::1;::::0;::::1;::::0;153888:173;:::o;152859:145::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;152950:21:::1;:46:::0;152859:145::o;126147:104::-;126203:13;126236:7;126229:14;;;;;:::i;159753:524::-;159886:13;159944:10;-1:-1:-1;;;;;159920:34:0;:13;159934:5;159920:20;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;;;159920:20:0;:34;159912:56;;;;-1:-1:-1;;;159912:56:0;;26104:2:1;159912:56:0;;;26086:21:1;26143:1;26123:18;;;26116:29;-1:-1:-1;;;26161:18:1;;;26154:39;26210:18;;159912:56:0;25902:332:1;142321:212:0;-1:-1:-1;;;;;142428:21:0;;142394:7;142428:21;;;:12;:21;;;;;:28;142474:8;;:51;;-1:-1:-1;;;;;142489:21:0;;;;;;:12;:21;;;;;142511:7;142517:1;142511:3;:7;:::i;:::-;142489:30;;;;;;;;:::i;:::-;;;;;;;;;;:36;;;;-1:-1:-1;;;;;142489:36:0;142474:51;;;142485:1;142474:51;-1:-1:-1;;;;;142467:58:0;;142321:212;-1:-1:-1;;;142321:212:0:o;130505:436::-;130598:4;93513:10;130598:4;130681:25;93513:10;130698:7;130681:9;:25::i;:::-;130654:52;;130745:15;130725:16;:35;;130717:85;;;;-1:-1:-1;;;130717:85:0;;27128:2:1;130717:85:0;;;27110:21:1;27167:2;27147:18;;;27140:30;27206:34;27186:18;;;27179:62;-1:-1:-1;;;27257:18:1;;;27250:35;27302:19;;130717:85:0;26926:401:1;130717:85:0;130838:60;130847:5;130854:7;130882:15;130863:16;:34;130838:8;:60::i;127552:193::-;127631:4;93513:10;127687:28;93513:10;127704:2;127708:6;127687:9;:28::i;145404:591::-;145631:6;145612:15;:25;;145604:67;;;;-1:-1:-1;;;145604:67:0;;14933:2:1;145604:67:0;;;14915:21:1;14972:2;14952:18;;;14945:30;15011:31;14991:18;;;14984:59;15060:18;;145604:67:0;14731:353:1;145604:67:0;145754:58;;;141315:71;145754:58;;;10934:25:1;-1:-1:-1;;;;;10995:32:1;;10975:18;;;10968:60;;;;11044:18;;;11037:34;;;11087:18;;;11080:34;;;145682:14:0;;145699:174;;145727:87;;10906:19:1;;145754:58:0;;;;;;;;;;;;145744:69;;;;;;145727:16;:87::i;:::-;145829:1;145845;145861;145699:13;:174::i;:::-;145682:191;;145901:17;145911:6;145901:9;:17::i;:::-;145892:5;:26;145884:64;;;;-1:-1:-1;;;145884:64:0;;16054:2:1;145884:64:0;;;16036:21:1;16093:2;16073:18;;;16066:30;16132:27;16112:18;;;16105:55;16177:18;;145884:64:0;15852:349:1;145884:64:0;145959:28;145969:6;145977:9;145959;:28::i;:::-;145593:402;145404:591;;;;;;:::o;138564:645::-;138808:8;138789:15;:27;;138781:69;;;;-1:-1:-1;;;138781:69:0;;18262:2:1;138781:69:0;;;18244:21:1;18301:2;18281:18;;;18274:30;18340:31;18320:18;;;18313:59;18389:18;;138781:69:0;18060:353:1;138781:69:0;138863:18;137739:95;138923:5;138930:7;138939:5;138946:16;138956:5;138946:9;:16::i;:::-;138894:79;;;;;;10394:25:1;;;;-1:-1:-1;;;;;10493:15:1;;;10473:18;;;10466:43;10545:15;;;;10525:18;;;10518:43;10577:18;;;10570:34;10620:19;;;10613:35;10664:19;;;10657:35;;;10366:19;;138894:79:0;;;;;;;;;;;;138884:90;;;;;;138863:111;;138987:12;139002:28;139019:10;139002:16;:28::i;:::-;138987:43;;139043:14;139060:28;139074:4;139080:1;139083;139086;139060:13;:28::i;:::-;139043:45;;139117:5;-1:-1:-1;;;;;139107:15:0;:6;-1:-1:-1;;;;;139107:15:0;;139099:58;;;;-1:-1:-1;;;139099:58:0;;22248:2:1;139099:58:0;;;22230:21:1;22287:2;22267:18;;;22260:30;22326:32;22306:18;;;22299:60;22376:18;;139099:58:0;22046:354:1;139099:58:0;139170:31;139179:5;139186:7;139195:5;139170:8;:31::i;:::-;138770:439;;;138564:645;;;;;;;:::o;158473:793::-;158578:13;158612:6;158619:5;158612:13;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:22;158604:47;;;;-1:-1:-1;;;158604:47:0;;21907:2:1;158604:47:0;;;21889:21:1;21946:2;21926:18;;;21919:30;-1:-1:-1;;;21965:18:1;;;21958:42;22017:18;;158604:47:0;21705:336:1;158604:47:0;158670:30;158684:8;158670:30;;;;;;;;;;;;;-1:-1:-1;;;158670:30:0;;;:13;:30::i;:::-;:65;;;;158704:31;158718:8;158704:31;;;;;;;;;;;;;-1:-1:-1;;;158704:31:0;;;:13;:31::i;:::-;158662:94;;;;-1:-1:-1;;;158662:94:0;;;;;;;:::i;:::-;158772:9;:13;158769:300;;158823:19;;158810:9;:32;;158802:67;;;;-1:-1:-1;;;158802:67:0;;19027:2:1;158802:67:0;;;19009:21:1;19066:2;19046:18;;;19039:30;-1:-1:-1;;;19085:18:1;;;19078:52;19147:18;;158802:67:0;18825:346:1;158802:67:0;158769:300;;;158944:20;;158929:10;127293:7;127320:18;;;;;;;;;;;158919:45;;158911:73;;;;-1:-1:-1;;;158911:73:0;;20816:2:1;158911:73:0;;;20798:21:1;20855:2;20835:18;;;20828:30;-1:-1:-1;;;20874:18:1;;;20867:45;20929:18;;158911:73:0;20614:339:1;158911:73:0;158999:58;159009:10;159029:4;159036:20;;158999:9;:58::i;:::-;159097:4;159081:6;159088:5;159081:13;;;;;;:::i;:::-;;;;;;;;;;;;;;:20;;;;;-1:-1:-1;;159081:20:0;;;;;;;;;;159133:5;;159112:11;;:18;;159124:5;;159112:18;:::i;:::-;;;;;;;;;;;;;:26;;;;159173:8;159149:14;159164:5;159149:21;;;;;;:::i;:::-;;;;;;;;;;;;;:32;;;;;;;;;;;;:::i;:::-;;159215:10;159192:13;159206:5;159192:20;;;;;;:::i;:::-;;;;;;;;;;;;;;:33;;;;;-1:-1:-1;;;;;159192:33:0;;;;;-1:-1:-1;;;;;159192:33:0;;;;;;159236:22;;;;;;;;;;;;;-1:-1:-1;;;159236:22:0;;;;;158473:793;;;;;:::o;153677:203::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;153790:4:::1;153774:30;:40:::0;-1:-1:-1;153774:40:0::1;153766:67;;;::::0;-1:-1:-1;;;153766:67:0;;17561:2:1;153766:67:0::1;::::0;::::1;17543:21:1::0;17600:2;17580:18;;;17573:30;-1:-1:-1;;;17619:18:1;;;17612:44;17673:18;;153766:67:0::1;17359:338:1::0;153766:67:0::1;153844:28;::::0;-1:-1:-1;;;;;153844:20:0;::::1;::::0;:28;::::1;;;::::0;153865:6;;153844:28:::1;::::0;;;153865:6;153844:20;:28;::::1;;;;;;;;;;;;;::::0;::::1;;;;160902:245:::0;160962:7;160971:13;160986:7;161014:6;161021:5;161014:13;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:21;;:13;:21;161006:50;;;;-1:-1:-1;;;161006:50:0;;23793:2:1;161006:50:0;;;23775:21:1;23832:2;23812:18;;;23805:30;-1:-1:-1;;;23851:18:1;;;23844:46;23907:18;;161006:50:0;23591:340:1;161006:50:0;161075:11;161087:5;161075:18;;;;;;:::i;:::-;;;;;;;;;;;;;;161095:14;161110:5;161095:21;;;;;;:::i;:::-;;;;;;;;;;;;;161118:13;161132:5;161118:20;;;;;;:::i;:::-;;;;;;;;;;;;;;;161067:72;;-1:-1:-1;;;;;161118:20:0;;;;161067:72;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160902:245;;;;;:::o;127808:151::-;-1:-1:-1;;;;;127924:18:0;;;127897:7;127924:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;127808:151::o;162643:789::-;162726:13;162772:1;162760:9;:13;:31;;;;162790:1;162777:10;:14;162760:31;162752:61;;;;-1:-1:-1;;;162752:61:0;;24138:2:1;162752:61:0;;;24120:21:1;24177:2;24157:18;;;24150:30;-1:-1:-1;;;24196:18:1;;;24189:47;24253:18;;162752:61:0;23936:341:1;162752:61:0;162879:13;162910:9;:13;162907:229;;162940:11;163003:3;162954:46;162967:9;162978:21;;162954:12;:46::i;:::-;:52;;;;:::i;:::-;162940:66;;163021:17;163041:28;163054:9;163065:3;163041:12;:28::i;:::-;163084:40;;163021:48;;-1:-1:-1;;;;;;163084:29:0;;;:40;;;;;163021:48;;163084:40;;;;163021:48;163084:29;:40;;;;;;;;;;;;;;;;;;;;;162925:211;;162907:229;163151:14;;163148:248;;163182:11;163246:3;163196:47;163209:10;163221:21;;163196:12;:47::i;:::-;:53;;;;:::i;:::-;163182:67;;163264:18;163285:29;163298:10;163310:3;163285:12;:29::i;:::-;163264:50;;163329:55;163339:10;163351:20;163373:10;163329:9;:55::i;:::-;163167:229;;163148:248;-1:-1:-1;;163408:16:0;;;;;;;;;;;;-1:-1:-1;;;163408:16:0;;;;162643:789;;;;:::o;152718:133::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;152803:18:::1;:40:::0;152718:133::o;141635:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;141751:21:0;;;;;;:12;:21;;;;;:26;;;;;;;;;;;;:::i;:::-;;;;;;;;;;141744:33;;;;;;;;;141751:26;;141744:33;;;;;;;;;-1:-1:-1;;;;;141744:33:0;;;;;;;;;141635:150;-1:-1:-1;;;141635:150:0:o;117291:201::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;117380:22:0;::::1;117372:73;;;::::0;-1:-1:-1;;;117372:73:0;;16408:2:1;117372:73:0::1;::::0;::::1;16390:21:1::0;16447:2;16427:18;;;16420:30;16486:34;16466:18;;;16459:62;-1:-1:-1;;;16537:18:1;;;16530:36;16583:19;;117372:73:0::1;16206:402:1::0;117372:73:0::1;117456:28;117475:8;117456:18;:28::i;164374:166::-:0;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;164466:66:::1;164483:4;164490:2;164525:6;164494:28;164512:4;164519:2;164494:9;:28::i;:::-;:37;;;;:::i;163586:144::-:0;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;163651:17:::1;::::0;::::1;;163650:18;163642:45;;;::::0;-1:-1:-1;;;163642:45:0;;17218:2:1;163642:45:0::1;::::0;::::1;17200:21:1::0;17257:2;17237:18;;;17230:30;-1:-1:-1;;;17276:18:1;;;17269:44;17330:18;;163642:45:0::1;17016:338:1::0;163642:45:0::1;163698:17;:24:::0;;-1:-1:-1;;163698:24:0::1;163718:4;163698:24;::::0;;163586:144::o;161155:109::-;161219:4;161243:6;161250:5;161243:13;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;161155:109;-1:-1:-1;;161155:109:0:o;163893:144::-;116462:6;;-1:-1:-1;;;;;116462:6:0;;;;;93513:10;116609:23;116601:68;;;;-1:-1:-1;;;116601:68:0;;;;;;;:::i;:::-;163958:17:::1;::::0;::::1;::::0;::::1;;;163957:18;163949:45;;;::::0;-1:-1:-1;;;163949:45:0;;17218:2:1;163949:45:0::1;::::0;::::1;17200:21:1::0;17257:2;17237:18;;;17230:30;-1:-1:-1;;;17276:18:1;;;17269:44;17330:18;;163949:45:0::1;17016:338:1::0;163949:45:0::1;164005:17;:24:::0;;-1:-1:-1;;164005:24:0::1;;;::::0;;163893:144::o;146301:290::-;146386:28;146398:7;146407:6;146386:11;:28::i;:::-;127136:12;;-1:-1:-1;;;;;;146433:29:0;146425:90;;;;-1:-1:-1;;;146425:90:0;;22607:2:1;146425:90:0;;;22589:21:1;22646:2;22626:18;;;22619:30;22685:34;22665:18;;;22658:62;-1:-1:-1;;;22736:18:1;;;22729:46;22792:19;;146425:90:0;22405:412:1;146425:90:0;146528:55;146545:23;146570:4;146576:6;146528:16;:55::i;:::-;;;146301:290;;:::o;132369:399::-;-1:-1:-1;;;;;132453:21:0;;132445:65;;;;-1:-1:-1;;;132445:65:0;;27534:2:1;132445:65:0;;;27516:21:1;27573:2;27553:18;;;27546:30;27612:33;27592:18;;;27585:61;27663:18;;132445:65:0;27332:355:1;132445:65:0;132523:49;132552:1;132556:7;132565:6;132523:20;:49::i;:::-;132601:6;132585:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;132618:18:0;;:9;:18;;;;;;;;;;:28;;132640:6;;132618:9;:28;;132640:6;;132618:28;:::i;:::-;;;;-1:-1:-1;;132662:37:0;;10071:25:1;;;-1:-1:-1;;;;;132662:37:0;;;132679:1;;132662:37;;10059:2:1;10044:18;132662:37:0;;;;;;;132712:48;132740:1;132744:7;132753:6;132712:19;:48::i;149145:98::-;149203:7;149230:5;149234:1;149230;:5;:::i;28126:195::-;28183:7;-1:-1:-1;;;;;28211:26:0;;;28203:78;;;;-1:-1:-1;;;28203:78:0;;23385:2:1;28203:78:0;;;23367:21:1;23424:2;23404:18;;;23397:30;23463:34;23443:18;;;23436:62;-1:-1:-1;;;23514:18:1;;;23507:37;23561:19;;28203:78:0;23183:403:1;28203:78:0;-1:-1:-1;28307:5:0;28126:195::o;40962:190::-;41018:6;41054:16;41045:25;;;41037:76;;;;-1:-1:-1;;;41037:76:0;;25292:2:1;41037:76:0;;;25274:21:1;25331:2;25311:18;;;25304:30;25370:34;25350:18;;;25343:62;-1:-1:-1;;;25421:18:1;;;25414:36;25467:19;;41037:76:0;25090:402:1;147019:262:0;-1:-1:-1;;;;;142210:19:0;;;142183:7;142210:19;;;:10;:19;;;;;;;;;;;;;;;147217:56;;142210:19;;;;;147266:6;147217:16;:56::i;149251:103::-;149314:7;149341:5;149345:1;149341;:5;:::i;157572:368::-;157759:9;;157789;;157653:4;;157694:2;;157732;;157759:9;157783:15;;157779:33;;157807:5;157800:12;;;;;;;157779:33;157828:9;157823:88;157843:2;157841:1;:4;157823:88;;;157880:2;157883:1;157880:5;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;157871:14:0;;:2;157874:1;157871:5;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;;157871:5:0;:14;157867:32;;157894:5;157887:12;;;;;;;;157867:32;157847:3;;;;:::i;:::-;;;;157823:88;;;-1:-1:-1;157928:4:0;;157572:368;-1:-1:-1;;;;;;157572:368:0:o;134130:380::-;-1:-1:-1;;;;;134266:19:0;;134258:68;;;;-1:-1:-1;;;134258:68:0;;25699:2:1;134258:68:0;;;25681:21:1;25738:2;25718:18;;;25711:30;25777:34;25757:18;;;25750:62;-1:-1:-1;;;25828:18:1;;;25821:34;25872:19;;134258:68:0;25497:400:1;134258:68:0;-1:-1:-1;;;;;134345:21:0;;134337:68;;;;-1:-1:-1;;;134337:68:0;;16815:2:1;134337:68:0;;;16797:21:1;16854:2;16834:18;;;16827:30;16893:34;16873:18;;;16866:62;-1:-1:-1;;;16944:18:1;;;16937:32;16986:19;;134337:68:0;16613:398:1;134337:68:0;-1:-1:-1;;;;;134418:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;134470:32;;10071:25:1;;;134470:32:0;;10044:18:1;134470:32:0;;;;;;;134130:380;;;:::o;134801:453::-;134936:24;134963:25;134973:5;134980:7;134963:9;:25::i;:::-;134936:52;;-1:-1:-1;;135003:16:0;:37;134999:248;;135085:6;135065:16;:26;;135057:68;;;;-1:-1:-1;;;135057:68:0;;17904:2:1;135057:68:0;;;17886:21:1;17943:2;17923:18;;;17916:30;17982:31;17962:18;;;17955:59;18031:18;;135057:68:0;17702:353:1;135057:68:0;135169:51;135178:5;135185:7;135213:6;135194:16;:25;135169:8;:51::i;131411:671::-;-1:-1:-1;;;;;131542:18:0;;131534:68;;;;-1:-1:-1;;;131534:68:0;;24886:2:1;131534:68:0;;;24868:21:1;24925:2;24905:18;;;24898:30;24964:34;24944:18;;;24937:62;-1:-1:-1;;;25015:18:1;;;25008:35;25060:19;;131534:68:0;24684:401:1;131534:68:0;-1:-1:-1;;;;;131621:16:0;;131613:64;;;;-1:-1:-1;;;131613:64:0;;13485:2:1;131613:64:0;;;13467:21:1;13524:2;13504:18;;;13497:30;13563:34;13543:18;;;13536:62;-1:-1:-1;;;13614:18:1;;;13607:33;13657:19;;131613:64:0;13283:399:1;131613:64:0;131690:38;131711:4;131717:2;131721:6;131690:20;:38::i;:::-;-1:-1:-1;;;;;131763:15:0;;131741:19;131763:15;;;;;;;;;;;131797:21;;;;131789:72;;;;-1:-1:-1;;;131789:72:0;;18620:2:1;131789:72:0;;;18602:21:1;18659:2;18639:18;;;18632:30;18698:34;18678:18;;;18671:62;-1:-1:-1;;;18749:18:1;;;18742:36;18795:19;;131789:72:0;18418:402:1;131789:72:0;-1:-1:-1;;;;;131897:15:0;;;:9;:15;;;;;;;;;;;131915:20;;;131897:38;;131957:13;;;;;;;;:23;;131929:6;;131897:9;131957:23;;131929:6;;131957:23;:::i;:::-;;;;;;;;132013:2;-1:-1:-1;;;;;131998:26:0;132007:4;-1:-1:-1;;;;;131998:26:0;;132017:6;131998:26;;;;10071:25:1;;10059:2;10044:18;;9925:177;131998:26:0;;;;;;;;132037:37;132057:4;132063:2;132067:6;132037:19;:37::i;88988:314::-;89041:7;89073:4;-1:-1:-1;;;;;89082:12:0;89065:29;;:66;;;;;89115:16;89098:13;:33;89065:66;89061:234;;;-1:-1:-1;89155:24:0;;88988:314::o;89061:234::-;-1:-1:-1;89491:73:0;;;89241:10;89491:73;;;;11384:25:1;;;;89253:12:0;11425:18:1;;;11418:34;89267:15:0;11468:18:1;;;11461:34;89535:13:0;11511:18:1;;;11504:34;89558:4:0;11554:19:1;;;;11547:61;;;;89491:73:0;;;;;;;;;;11356:19:1;;;;89491:73:0;;;89481:84;;;;;;139533:115::o;143640:1482::-;144773:12;;143739:7;;;144822:236;144835:4;144829:3;:10;144822:236;;;144856:11;144870:23;144883:3;144888:4;144870:12;:23::i;:::-;144856:37;;144935:11;144912:5;144918:3;144912:10;;;;;;;;:::i;:::-;;;;;;;;;;:20;;;:34;144908:139;;;144974:3;144967:10;;144908:139;;;145024:7;:3;145030:1;145024:7;:::i;:::-;145018:13;;144908:139;144841:217;144822:236;;;145077:9;;:37;;145093:5;145099:8;145106:1;145099:4;:8;:::i;:::-;145093:15;;;;;;;;:::i;:::-;;;;;;;;;;:21;;;;-1:-1:-1;;;;;145093:21:0;145077:37;;;145089:1;145077:37;-1:-1:-1;;;;;145070:44:0;;143640:1482;-1:-1:-1;;;;;143640:1482:0:o;3600:98::-;3658:7;3685:5;3689:1;3685;:5;:::i;120041:120::-;119053:7;;;;119577:41;;;;-1:-1:-1;;;119577:41:0;;14249:2:1;119577:41:0;;;14231:21:1;14288:2;14268:18;;;14261:30;-1:-1:-1;;;14307:18:1;;;14300:50;14367:18;;119577:41:0;14047:344:1;119577:41:0;120100:7:::1;:15:::0;;-1:-1:-1;;120100:15:0::1;::::0;;120131:22:::1;93513:10:::0;120140:12:::1;120131:22;::::0;-1:-1:-1;;;;;9410:32:1;;;9392:51;;9380:2;9365:18;120131:22:0::1;;;;;;;120041:120::o:0;165127:145::-;165241:23;165253:2;165257:6;165241:11;:23::i;165280:155::-;165399:28;165411:7;165420:6;165399:11;:28::i;153140:122::-;153200:7;153237:16;153339:1;153237:2;:16;:::i;:::-;153227:27;;:6;:27;:::i;147445:388::-;-1:-1:-1;;;;;142210:19:0;;;147530:23;142210:19;;;:10;:19;;;;;;;;;;127320:18;;;;;;;147645:21;;;;:33;;;-1:-1:-1;;;;;;147645:33:0;;;;;;;147696:54;;142210:19;;;;;127320:18;;147645:33;;142210:19;;;147696:54;;147530:23;147696:54;147763:62;147780:15;147797:9;147808:16;147763;:62::i;119782:118::-;119053:7;;;;119307:9;119299:38;;;;-1:-1:-1;;;119299:38:0;;20471:2:1;119299:38:0;;;20453:21:1;20510:2;20490:18;;;20483:30;-1:-1:-1;;;20529:18:1;;;20522:46;20585:18;;119299:38:0;20269:340:1;119299:38:0;119842:7:::1;:14:::0;;-1:-1:-1;;119842:14:0::1;119852:4;119842:14;::::0;;119872:20:::1;119879:12;93513:10:::0;;93433:98;90215:167;90292:7;90319:55;90341:20;:18;:20::i;:::-;90363:10;85685:57;;-1:-1:-1;;;85685:57:0;;;9107:27:1;9150:11;;;9143:27;;;9186:12;;;9179:28;;;85648:7:0;;9223:12:1;;85685:57:0;;;;;;;;;;;;85675:68;;;;;;85668:75;;85555:196;;;;;83864:279;83992:7;84013:17;84032:18;84054:25;84065:4;84071:1;84074;84077;84054:10;:25::i;:::-;84012:67;;;;84090:18;84102:5;84090:11;:18::i;:::-;-1:-1:-1;84126:9:0;83864:279;-1:-1:-1;;;;;83864:279:0:o;139786:207::-;-1:-1:-1;;;;;139907:14:0;;139846:15;139907:14;;;:7;:14;;;;;74160;;74297:1;74279:19;;;;74160:14;139968:17;139863:130;139786:207;;;:::o;117652:191::-;117745:6;;;-1:-1:-1;;;;;117762:17:0;;;117745:6;117762:17;;;-1:-1:-1;;;;;;117762:17:0;;;;;;117795:40;;117745:6;;;;;;;;117795:40;;117726:16;;117795:40;117715:128;117652:191;:::o;148492:645::-;148729:12;;148666:17;;;;148764:8;;:35;;148779:5;148785:7;148791:1;148785:3;:7;:::i;:::-;148779:14;;;;;;;;:::i;:::-;;;;;;;;;;:20;;;;-1:-1:-1;;;;;148779:20:0;148764:35;;;148775:1;148764:35;-1:-1:-1;;;;;148752:47:0;;;148822:20;148825:9;148836:5;148822:2;:20;;:::i;:::-;148810:32;;148865:1;148859:3;:7;:51;;;;-1:-1:-1;148898:12:0;148870:5;148876:7;148882:1;148876:3;:7;:::i;:::-;148870:14;;;;;;;;:::i;:::-;;;;;;;;;;:24;;;:40;148859:51;148855:275;;;148950:29;148969:9;148950:18;:29::i;:::-;148927:5;148933:7;148939:1;148933:3;:7;:::i;:::-;148927:14;;;;;;;;:::i;:::-;;;;;;;;:20;;;:52;;;;;-1:-1:-1;;;;;148927:52:0;;;;;-1:-1:-1;;;;;148927:52:0;;;;;;148855:275;;;149012:5;149023:94;;;;;;;;149046:31;149064:12;149046:17;:31::i;:::-;149023:94;;;;;;149086:29;149105:9;149086:18;:29::i;:::-;-1:-1:-1;;;;;149023:94:0;;;;;;149012:106;;;;;;;-1:-1:-1;149012:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;148855:275;148704:433;148492:645;;;;;;:::o;164651:199::-;119053:7;;;;119307:9;119299:38;;;;-1:-1:-1;;;119299:38:0;;20471:2:1;119299:38:0;;;20453:21:1;20510:2;20490:18;;;20483:30;-1:-1:-1;;;20529:18:1;;;20522:46;20585:18;;119299:38:0;20269:340:1;164926:193:0;165068:43;165094:4;165100:2;165104:6;165068:25;:43::i;147841:643::-;147973:3;-1:-1:-1;;;;;147966:10:0;:3;-1:-1:-1;;;;;147966:10:0;;;:24;;;;;147989:1;147980:6;:10;147966:24;147962:515;;;-1:-1:-1;;;;;148011:17:0;;;148007:224;;-1:-1:-1;;;;;148107:17:0;;148050;148107;;;:12;:17;;;;;148050;;148090:54;;148126:9;148137:6;148090:16;:54::i;:::-;148049:95;;;;148189:3;-1:-1:-1;;;;;148168:47:0;;148194:9;148205;148168:47;;;;;;29136:25:1;;;29192:2;29177:18;;29170:34;29124:2;29109:18;;28962:248;148168:47:0;;;;;;;;148030:201;;148007:224;-1:-1:-1;;;;;148251:17:0;;;148247:219;;-1:-1:-1;;;;;148347:17:0;;148290;148347;;;:12;:17;;;;;148290;;148330:49;;148366:4;148372:6;148330:16;:49::i;:::-;148289:90;;;;148424:3;-1:-1:-1;;;;;148403:47:0;;148429:9;148440;148403:47;;;;;;29136:25:1;;;29192:2;29177:18;;29170:34;29124:2;29109:18;;28962:248;148403:47:0;;;;;;;;148270:196;;147841:643;;;:::o;64980:156::-;65042:7;65117:11;65127:1;65118:5;;;65117:11;:::i;:::-;65107:21;;65108:5;;;65107:21;:::i;146685:194::-;146770:28;146782:7;146791:6;146770:11;:28::i;:::-;146811:60;146828:23;146853:9;146864:6;146811:16;:60::i;82093:1632::-;82224:7;;83158:66;83145:79;;83141:163;;;-1:-1:-1;83257:1:0;;-1:-1:-1;83261:30:0;83241:51;;83141:163;83318:1;:7;;83323:2;83318:7;;:18;;;;;83329:1;:7;;83334:2;83329:7;;83318:18;83314:102;;;-1:-1:-1;83369:1:0;;-1:-1:-1;83373:30:0;83353:51;;83314:102;83530:24;;;83513:14;83530:24;;;;;;;;;11846:25:1;;;11919:4;11907:17;;11887:18;;;11880:45;;;;11941:18;;;11934:34;;;11984:18;;;11977:34;;;83530:24:0;;11818:19:1;;83530:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83530:24:0;;-1:-1:-1;;83530:24:0;;;-1:-1:-1;;;;;;;83569:20:0;;83565:103;;83622:1;83626:29;83606:50;;;;;;;83565:103;83688:6;-1:-1:-1;83696:20:0;;-1:-1:-1;82093:1632:0;;;;;;;;:::o;77363:643::-;77441:20;77432:5;:29;;;;;;;;:::i;:::-;;77428:571;;;77363:643;:::o;77428:571::-;77539:29;77530:5;:38;;;;;;;;:::i;:::-;;77526:473;;;77585:34;;-1:-1:-1;;;77585:34:0;;12449:2:1;77585:34:0;;;12431:21:1;12488:2;12468:18;;;12461:30;12527:26;12507:18;;;12500:54;12571:18;;77585:34:0;12247:348:1;77526:473:0;77650:35;77641:5;:44;;;;;;;;:::i;:::-;;77637:362;;;77702:41;;-1:-1:-1;;;77702:41:0;;15694:2:1;77702:41:0;;;15676:21:1;15733:2;15713:18;;;15706:30;15772:33;15752:18;;;15745:61;15823:18;;77702:41:0;15492:355:1;77637:362:0;77774:30;77765:5;:39;;;;;;;;:::i;:::-;;77761:238;;;77821:44;;-1:-1:-1;;;77821:44:0;;19378:2:1;77821:44:0;;;19360:21:1;19417:2;19397:18;;;19390:30;19456:34;19436:18;;;19429:62;-1:-1:-1;;;19507:18:1;;;19500:32;19549:19;;77821:44:0;19176:398:1;77761:238:0;77896:30;77887:5;:39;;;;;;;;:::i;:::-;;77883:116;;;77943:44;;-1:-1:-1;;;77943:44:0;;21504:2:1;77943:44:0;;;21486:21:1;21543:2;21523:18;;;21516:30;21582:34;21562:18;;;21555:62;-1:-1:-1;;;21633:18:1;;;21626:32;21675:19;;77943:44:0;21302:398:1;133101:591:0;-1:-1:-1;;;;;133185:21:0;;133177:67;;;;-1:-1:-1;;;133177:67:0;;24484:2:1;133177:67:0;;;24466:21:1;24523:2;24503:18;;;24496:30;24562:34;24542:18;;;24535:62;-1:-1:-1;;;24613:18:1;;;24606:31;24654:19;;133177:67:0;24282:397:1;133177:67:0;133257:49;133278:7;133295:1;133299:6;133257:20;:49::i;:::-;-1:-1:-1;;;;;133344:18:0;;133319:22;133344:18;;;;;;;;;;;133381:24;;;;133373:71;;;;-1:-1:-1;;;133373:71:0;;15291:2:1;133373:71:0;;;15273:21:1;15330:2;15310:18;;;15303:30;15369:34;15349:18;;;15342:62;-1:-1:-1;;;15420:18:1;;;15413:32;15462:19;;133373:71:0;15089:398:1;133373:71:0;-1:-1:-1;;;;;133480:18:0;;:9;:18;;;;;;;;;;133501:23;;;133480:44;;133546:12;:22;;133518:6;;133480:9;133546:22;;133518:6;;133546:22;:::i;:::-;;;;-1:-1:-1;;133586:37:0;;10071:25:1;;;133612:1:0;;-1:-1:-1;;;;;133586:37:0;;;;;10059:2:1;10044:18;133586:37:0;;;;;;;133636:48;133656:7;133673:1;133677:6;133636:19;:48::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:719:1;57:5;110:3;103:4;95:6;91:17;87:27;77:55;;128:1;125;118:12;77:55;164:6;151:20;190:18;227:2;223;220:10;217:36;;;233:18;;:::i;:::-;308:2;302:9;276:2;362:13;;-1:-1:-1;;358:22:1;;;382:2;354:31;350:40;338:53;;;406:18;;;426:22;;;403:46;400:72;;;452:18;;:::i;:::-;492:10;488:2;481:22;527:2;519:6;512:18;573:3;566:4;561:2;553:6;549:15;545:26;542:35;539:55;;;590:1;587;580:12;539:55;654:2;647:4;639:6;635:17;628:4;620:6;616:17;603:54;701:1;694:4;689:2;681:6;677:15;673:26;666:37;721:6;712:15;;;;;;14:719;;;;:::o;738:156::-;804:20;;864:4;853:16;;843:27;;833:55;;884:1;881;874:12;899:247;958:6;1011:2;999:9;990:7;986:23;982:32;979:52;;;1027:1;1024;1017:12;979:52;1066:9;1053:23;1085:31;1110:5;1085:31;:::i;1151:251::-;1221:6;1274:2;1262:9;1253:7;1249:23;1245:32;1242:52;;;1290:1;1287;1280:12;1242:52;1322:9;1316:16;1341:31;1366:5;1341:31;:::i;1667:388::-;1735:6;1743;1796:2;1784:9;1775:7;1771:23;1767:32;1764:52;;;1812:1;1809;1802:12;1764:52;1851:9;1838:23;1870:31;1895:5;1870:31;:::i;:::-;1920:5;-1:-1:-1;1977:2:1;1962:18;;1949:32;1990:33;1949:32;1990:33;:::i;:::-;2042:7;2032:17;;;1667:388;;;;;:::o;2060:456::-;2137:6;2145;2153;2206:2;2194:9;2185:7;2181:23;2177:32;2174:52;;;2222:1;2219;2212:12;2174:52;2261:9;2248:23;2280:31;2305:5;2280:31;:::i;:::-;2330:5;-1:-1:-1;2387:2:1;2372:18;;2359:32;2400:33;2359:32;2400:33;:::i;:::-;2060:456;;2452:7;;-1:-1:-1;;;2506:2:1;2491:18;;;;2478:32;;2060:456::o;2521:734::-;2632:6;2640;2648;2656;2664;2672;2680;2733:3;2721:9;2712:7;2708:23;2704:33;2701:53;;;2750:1;2747;2740:12;2701:53;2789:9;2776:23;2808:31;2833:5;2808:31;:::i;:::-;2858:5;-1:-1:-1;2915:2:1;2900:18;;2887:32;2928:33;2887:32;2928:33;:::i;:::-;2980:7;-1:-1:-1;3034:2:1;3019:18;;3006:32;;-1:-1:-1;3085:2:1;3070:18;;3057:32;;-1:-1:-1;3108:37:1;3140:3;3125:19;;3108:37;:::i;:::-;3098:47;;3192:3;3181:9;3177:19;3164:33;3154:43;;3244:3;3233:9;3229:19;3216:33;3206:43;;2521:734;;;;;;;;;;:::o;3260:315::-;3328:6;3336;3389:2;3377:9;3368:7;3364:23;3360:32;3357:52;;;3405:1;3402;3395:12;3357:52;3444:9;3431:23;3463:31;3488:5;3463:31;:::i;:::-;3513:5;3565:2;3550:18;;;;3537:32;;-1:-1:-1;;;3260:315:1:o;3580:592::-;3682:6;3690;3698;3706;3714;3722;3775:3;3763:9;3754:7;3750:23;3746:33;3743:53;;;3792:1;3789;3782:12;3743:53;3831:9;3818:23;3850:31;3875:5;3850:31;:::i;:::-;3900:5;-1:-1:-1;3952:2:1;3937:18;;3924:32;;-1:-1:-1;4003:2:1;3988:18;;3975:32;;-1:-1:-1;4026:36:1;4058:2;4043:18;;4026:36;:::i;:::-;4016:46;;4109:3;4098:9;4094:19;4081:33;4071:43;;4161:3;4150:9;4146:19;4133:33;4123:43;;3580:592;;;;;;;;:::o;4177:419::-;4244:6;4252;4305:2;4293:9;4284:7;4280:23;4276:32;4273:52;;;4321:1;4318;4311:12;4273:52;4360:9;4347:23;4379:31;4404:5;4379:31;:::i;:::-;4429:5;-1:-1:-1;4486:2:1;4471:18;;4458:32;4534:10;4521:24;;4509:37;;4499:65;;4560:1;4557;4550:12;4601:322;4670:6;4723:2;4711:9;4702:7;4698:23;4694:32;4691:52;;;4739:1;4736;4729:12;4691:52;4779:9;4766:23;4812:18;4804:6;4801:30;4798:50;;;4844:1;4841;4834:12;4798:50;4867;4909:7;4900:6;4889:9;4885:22;4867:50;:::i;:::-;4857:60;4601:322;-1:-1:-1;;;;4601:322:1:o;4928:915::-;5040:6;5048;5056;5064;5072;5125:3;5113:9;5104:7;5100:23;5096:33;5093:53;;;5142:1;5139;5132:12;5093:53;5182:9;5169:23;5211:18;5252:2;5244:6;5241:14;5238:34;;;5268:1;5265;5258:12;5238:34;5291:50;5333:7;5324:6;5313:9;5309:22;5291:50;:::i;:::-;5281:60;;5391:2;5380:9;5376:18;5363:32;5350:45;;5438:5;5431:13;5424:21;5417:5;5414:32;5404:60;;5460:1;5457;5450:12;5404:60;5483:5;;-1:-1:-1;5535:2:1;5520:18;;5507:32;;-1:-1:-1;5592:2:1;5577:18;;5564:32;;5608:16;;;5605:36;;;5637:1;5634;5627:12;5605:36;;5660:52;5704:7;5693:8;5682:9;5678:24;5660:52;:::i;:::-;5650:62;;;5764:3;5753:9;5749:19;5736:33;5778;5803:7;5778:33;:::i;:::-;5830:7;5820:17;;;4928:915;;;;;;;;:::o;5848:611::-;5945:6;5953;5961;6014:2;6002:9;5993:7;5989:23;5985:32;5982:52;;;6030:1;6027;6020:12;5982:52;6070:9;6057:23;6099:18;6140:2;6132:6;6129:14;6126:34;;;6156:1;6153;6146:12;6126:34;6179:50;6221:7;6212:6;6201:9;6197:22;6179:50;:::i;:::-;6169:60;;6282:2;6271:9;6267:18;6254:32;6238:48;;6311:2;6301:8;6298:16;6295:36;;;6327:1;6324;6317:12;6295:36;;6350:52;6394:7;6383:8;6372:9;6368:24;6350:52;:::i;:::-;6340:62;;;6449:2;6438:9;6434:18;6421:32;6411:42;;5848:611;;;;;:::o;6464:747::-;6570:6;6578;6586;6594;6647:3;6635:9;6626:7;6622:23;6618:33;6615:53;;;6664:1;6661;6654:12;6615:53;6704:9;6691:23;6733:18;6774:2;6766:6;6763:14;6760:34;;;6790:1;6787;6780:12;6760:34;6813:50;6855:7;6846:6;6835:9;6831:22;6813:50;:::i;:::-;6803:60;;6916:2;6905:9;6901:18;6888:32;6872:48;;6945:2;6935:8;6932:16;6929:36;;;6961:1;6958;6951:12;6929:36;;6984:52;7028:7;7017:8;7006:9;7002:24;6984:52;:::i;:::-;6974:62;;;7083:2;7072:9;7068:18;7055:32;7045:42;;7137:2;7126:9;7122:18;7109:32;7150:31;7175:5;7150:31;:::i;:::-;6464:747;;;;-1:-1:-1;6464:747:1;;-1:-1:-1;;6464:747:1:o;7216:180::-;7275:6;7328:2;7316:9;7307:7;7303:23;7299:32;7296:52;;;7344:1;7341;7334:12;7296:52;-1:-1:-1;7367:23:1;;7216:180;-1:-1:-1;7216:180:1:o;7401:184::-;7471:6;7524:2;7512:9;7503:7;7499:23;7495:32;7492:52;;;7540:1;7537;7530:12;7492:52;-1:-1:-1;7563:16:1;;7401:184;-1:-1:-1;7401:184:1:o;7590:315::-;7658:6;7666;7719:2;7707:9;7698:7;7694:23;7690:32;7687:52;;;7735:1;7732;7725:12;7687:52;7771:9;7758:23;7748:33;;7831:2;7820:9;7816:18;7803:32;7844:31;7869:5;7844:31;:::i;7910:390::-;7988:6;7996;8049:2;8037:9;8028:7;8024:23;8020:32;8017:52;;;8065:1;8062;8055:12;8017:52;8101:9;8088:23;8078:33;;8162:2;8151:9;8147:18;8134:32;8189:18;8181:6;8178:30;8175:50;;;8221:1;8218;8211:12;8175:50;8244;8286:7;8277:6;8266:9;8262:22;8244:50;:::i;:::-;8234:60;;;7910:390;;;;;:::o;8305:258::-;8347:3;8385:5;8379:12;8412:6;8407:3;8400:19;8428:63;8484:6;8477:4;8472:3;8468:14;8461:4;8454:5;8450:16;8428:63;:::i;:::-;8545:2;8524:15;-1:-1:-1;;8520:29:1;8511:39;;;;8552:4;8507:50;;8305:258;-1:-1:-1;;8305:258:1:o;8568:276::-;8699:3;8737:6;8731:13;8753:53;8799:6;8794:3;8787:4;8779:6;8775:17;8753:53;:::i;:::-;8822:16;;;;;8568:276;-1:-1:-1;;8568:276:1:o;12022:220::-;12171:2;12160:9;12153:21;12134:4;12191:45;12232:2;12221:9;12217:18;12209:6;12191:45;:::i;19579:340::-;19781:2;19763:21;;;19820:2;19800:18;;;19793:30;-1:-1:-1;;;19854:2:1;19839:18;;19832:46;19910:2;19895:18;;19579:340::o;22822:356::-;23024:2;23006:21;;;23043:18;;;23036:30;23102:34;23097:2;23082:18;;23075:62;23169:2;23154:18;;22822:356::o;28569:388::-;28774:6;28763:9;28756:25;28817:2;28812;28801:9;28797:18;28790:30;28737:4;28837:45;28878:2;28867:9;28863:18;28855:6;28837:45;:::i;:::-;28829:53;;28947:1;28943;28938:3;28934:11;28930:19;28922:6;28918:32;28913:2;28902:9;28898:18;28891:60;28569:388;;;;;;:::o;29601:128::-;29641:3;29672:1;29668:6;29665:1;29662:13;29659:39;;;29678:18;;:::i;:::-;-1:-1:-1;29714:9:1;;29601:128::o;29734:217::-;29774:1;29800;29790:132;;29844:10;29839:3;29835:20;29832:1;29825:31;29879:4;29876:1;29869:15;29907:4;29904:1;29897:15;29790:132;-1:-1:-1;29936:9:1;;29734:217::o;29956:422::-;30045:1;30088:5;30045:1;30102:270;30123:7;30113:8;30110:21;30102:270;;;30182:4;30178:1;30174:6;30170:17;30164:4;30161:27;30158:53;;;30191:18;;:::i;:::-;30241:7;30231:8;30227:22;30224:55;;;30261:16;;;;30224:55;30340:22;;;;30300:15;;;;30102:270;;;30106:3;29956:422;;;;;:::o;30383:140::-;30441:5;30470:47;30511:4;30501:8;30497:19;30491:4;30577:5;30607:8;30597:80;;-1:-1:-1;30648:1:1;30662:5;;30597:80;30696:4;30686:76;;-1:-1:-1;30733:1:1;30747:5;;30686:76;30778:4;30796:1;30791:59;;;;30864:1;30859:130;;;;30771:218;;30791:59;30821:1;30812:10;;30835:5;;;30859:130;30896:3;30886:8;30883:17;30880:43;;;30903:18;;:::i;:::-;-1:-1:-1;;30959:1:1;30945:16;;30974:5;;30771:218;;31073:2;31063:8;31060:16;31054:3;31048:4;31045:13;31041:36;31035:2;31025:8;31022:16;31017:2;31011:4;31008:12;31004:35;31001:77;30998:159;;;-1:-1:-1;31110:19:1;;;31142:5;;30998:159;31189:34;31214:8;31208:4;31189:34;:::i;:::-;31259:6;31255:1;31251:6;31247:19;31238:7;31235:32;31232:58;;;31270:18;;:::i;:::-;31308:20;;30528:806;-1:-1:-1;;;30528:806:1:o;31339:168::-;31379:7;31445:1;31441;31437:6;31433:14;31430:1;31427:21;31422:1;31415:9;31408:17;31404:45;31401:71;;;31452:18;;:::i;:::-;-1:-1:-1;31492:9:1;;31339:168::o;31512:125::-;31552:4;31580:1;31577;31574:8;31571:34;;;31585:18;;:::i;:::-;-1:-1:-1;31622:9:1;;31512:125::o;31642:258::-;31714:1;31724:113;31738:6;31735:1;31732:13;31724:113;;;31814:11;;;31808:18;31795:11;;;31788:39;31760:2;31753:10;31724:113;;;31855:6;31852:1;31849:13;31846:48;;;-1:-1:-1;;31890:1:1;31872:16;;31865:27;31642:258::o;31905:136::-;31944:3;31972:5;31962:39;;31981:18;;:::i;:::-;-1:-1:-1;;;32017:18:1;;31905:136::o;32046:380::-;32125:1;32121:12;;;;32168;;;32189:61;;32243:4;32235:6;32231:17;32221:27;;32189:61;32296:2;32288:6;32285:14;32265:18;32262:38;32259:161;;;32342:10;32337:3;32333:20;32330:1;32323:31;32377:4;32374:1;32367:15;32405:4;32402:1;32395:15;32431:135;32470:3;-1:-1:-1;;32491:17:1;;32488:43;;;32511:18;;:::i;:::-;-1:-1:-1;32558:1:1;32547:13;;32431:135::o;32571:127::-;32632:10;32627:3;32623:20;32620:1;32613:31;32663:4;32660:1;32653:15;32687:4;32684:1;32677:15;32703:127;32764:10;32759:3;32755:20;32752:1;32745:31;32795:4;32792:1;32785:15;32819:4;32816:1;32809:15;32835:127;32896:10;32891:3;32887:20;32884:1;32877:31;32927:4;32924:1;32917:15;32951:4;32948:1;32941:15;32967:127;33028:10;33023:3;33019:20;33016:1;33009:31;33059:4;33056:1;33049:15;33083:4;33080:1;33073:15;33099:131;-1:-1:-1;;;;;33174:31:1;;33164:42;;33154:70;;33220:1;33217;33210:12

Swarm Source

ipfs://e4fea938bbc9229cb7cdcf617e147b2361d02ef2de66896c534bc5054b2da8c1
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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