ETH Price: $3,393.08 (+1.75%)

Token

MusicRacerNFT (MRCR)
 

Overview

Max Total Supply

313 MRCR

Holders

198

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
arnonymous.eth
Balance
1 MRCR
0x47584f11a998c19dda33d8ca4002fbe892ac899b
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:
MusicRacerNFT

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-15
*/

// SPDX-License-Identifier: MIT

// File: @openzeppelin/contracts/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/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/utils/Address.sol



pragma solidity ^0.8.0;

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

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        (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



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



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



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



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



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 tokenId);

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

// File: @openzeppelin/contracts/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/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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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);
    }

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

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

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

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

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);
    }

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

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

// File: @openzeppelin/contracts/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: prb-math/contracts/PRBMath.sol


pragma solidity >=0.8.4;

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);

/// @notice Emitted when one of the inputs is type(int256).min.
error PRBMath__MulDivSignedInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows int256.
error PRBMath__MulDivSignedOverflow(uint256 rAbs);

/// @notice Emitted when the input is MIN_SD59x18.
error PRBMathSD59x18__AbsInputTooSmall();

/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMathSD59x18__CeilOverflow(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__DivInputTooSmall();

/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
error PRBMathSD59x18__DivOverflow(uint256 rAbs);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathSD59x18__ExpInputTooBig(int256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathSD59x18__Exp2InputTooBig(int256 x);

/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMathSD59x18__FloorUnderflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMathSD59x18__FromIntOverflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMathSD59x18__FromIntUnderflow(int256 x);

/// @notice Emitted when the product of the inputs is negative.
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);

/// @notice Emitted when multiplying the inputs overflows SD59x18.
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);

/// @notice Emitted when the input is less than or equal to zero.
error PRBMathSD59x18__LogInputTooSmall(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__MulInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__MulOverflow(uint256 rAbs);

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);

/// @notice Emitted when the input is negative.
error PRBMathSD59x18__SqrtNegativeInput(int256 x);

/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMathSD59x18__SqrtOverflow(int256 x);

/// @notice Emitted when addition overflows UD60x18.
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);

/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMathUD60x18__CeilOverflow(uint256 x);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathUD60x18__ExpInputTooBig(uint256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
error PRBMathUD60x18__FromUintOverflow(uint256 x);

/// @notice Emitted when multiplying the inputs overflows UD60x18.
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);

/// @notice Emitted when the input is less than 1.
error PRBMathUD60x18__LogInputTooSmall(uint256 x);

/// @notice Emitted when the calculating the square root overflows UD60x18.
error PRBMathUD60x18__SqrtOverflow(uint256 x);

/// @notice Emitted when subtraction underflows UD60x18.
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);

/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
library PRBMath {
    /// STRUCTS ///

    struct SD59x18 {
        int256 value;
    }

    struct UD60x18 {
        uint256 value;
    }

    /// STORAGE ///

    /// @dev How many trailing decimals can be represented.
    uint256 internal constant SCALE = 1e18;

    /// @dev Largest power of two divisor of SCALE.
    uint256 internal constant SCALE_LPOTD = 262144;

    /// @dev SCALE inverted mod 2^256.
    uint256 internal constant SCALE_INVERSE = 78156646155174841979727994598816262306175212592076161876661508869554232690281;

    /// FUNCTIONS ///

    /// @notice Calculates the binary exponent of x using the binary fraction method.
    /// @dev Has to use 192.64-bit fixed-point numbers.
    /// See https://ethereum.stackexchange.com/a/96594/24693.
    /// @param x The exponent as an unsigned 192.64-bit fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function exp2(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            // Start from 0.5 in the 192.64-bit fixed-point format.
            result = 0x800000000000000000000000000000000000000000000000;

            // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
            // because the initial result is 2^191 and all magic factors are less than 2^65.
            if (x & 0x8000000000000000 > 0) {
                result = (result * 0x16A09E667F3BCC909) >> 64;
            }
            if (x & 0x4000000000000000 > 0) {
                result = (result * 0x1306FE0A31B7152DF) >> 64;
            }
            if (x & 0x2000000000000000 > 0) {
                result = (result * 0x1172B83C7D517ADCE) >> 64;
            }
            if (x & 0x1000000000000000 > 0) {
                result = (result * 0x10B5586CF9890F62A) >> 64;
            }
            if (x & 0x800000000000000 > 0) {
                result = (result * 0x1059B0D31585743AE) >> 64;
            }
            if (x & 0x400000000000000 > 0) {
                result = (result * 0x102C9A3E778060EE7) >> 64;
            }
            if (x & 0x200000000000000 > 0) {
                result = (result * 0x10163DA9FB33356D8) >> 64;
            }
            if (x & 0x100000000000000 > 0) {
                result = (result * 0x100B1AFA5ABCBED61) >> 64;
            }
            if (x & 0x80000000000000 > 0) {
                result = (result * 0x10058C86DA1C09EA2) >> 64;
            }
            if (x & 0x40000000000000 > 0) {
                result = (result * 0x1002C605E2E8CEC50) >> 64;
            }
            if (x & 0x20000000000000 > 0) {
                result = (result * 0x100162F3904051FA1) >> 64;
            }
            if (x & 0x10000000000000 > 0) {
                result = (result * 0x1000B175EFFDC76BA) >> 64;
            }
            if (x & 0x8000000000000 > 0) {
                result = (result * 0x100058BA01FB9F96D) >> 64;
            }
            if (x & 0x4000000000000 > 0) {
                result = (result * 0x10002C5CC37DA9492) >> 64;
            }
            if (x & 0x2000000000000 > 0) {
                result = (result * 0x1000162E525EE0547) >> 64;
            }
            if (x & 0x1000000000000 > 0) {
                result = (result * 0x10000B17255775C04) >> 64;
            }
            if (x & 0x800000000000 > 0) {
                result = (result * 0x1000058B91B5BC9AE) >> 64;
            }
            if (x & 0x400000000000 > 0) {
                result = (result * 0x100002C5C89D5EC6D) >> 64;
            }
            if (x & 0x200000000000 > 0) {
                result = (result * 0x10000162E43F4F831) >> 64;
            }
            if (x & 0x100000000000 > 0) {
                result = (result * 0x100000B1721BCFC9A) >> 64;
            }
            if (x & 0x80000000000 > 0) {
                result = (result * 0x10000058B90CF1E6E) >> 64;
            }
            if (x & 0x40000000000 > 0) {
                result = (result * 0x1000002C5C863B73F) >> 64;
            }
            if (x & 0x20000000000 > 0) {
                result = (result * 0x100000162E430E5A2) >> 64;
            }
            if (x & 0x10000000000 > 0) {
                result = (result * 0x1000000B172183551) >> 64;
            }
            if (x & 0x8000000000 > 0) {
                result = (result * 0x100000058B90C0B49) >> 64;
            }
            if (x & 0x4000000000 > 0) {
                result = (result * 0x10000002C5C8601CC) >> 64;
            }
            if (x & 0x2000000000 > 0) {
                result = (result * 0x1000000162E42FFF0) >> 64;
            }
            if (x & 0x1000000000 > 0) {
                result = (result * 0x10000000B17217FBB) >> 64;
            }
            if (x & 0x800000000 > 0) {
                result = (result * 0x1000000058B90BFCE) >> 64;
            }
            if (x & 0x400000000 > 0) {
                result = (result * 0x100000002C5C85FE3) >> 64;
            }
            if (x & 0x200000000 > 0) {
                result = (result * 0x10000000162E42FF1) >> 64;
            }
            if (x & 0x100000000 > 0) {
                result = (result * 0x100000000B17217F8) >> 64;
            }
            if (x & 0x80000000 > 0) {
                result = (result * 0x10000000058B90BFC) >> 64;
            }
            if (x & 0x40000000 > 0) {
                result = (result * 0x1000000002C5C85FE) >> 64;
            }
            if (x & 0x20000000 > 0) {
                result = (result * 0x100000000162E42FF) >> 64;
            }
            if (x & 0x10000000 > 0) {
                result = (result * 0x1000000000B17217F) >> 64;
            }
            if (x & 0x8000000 > 0) {
                result = (result * 0x100000000058B90C0) >> 64;
            }
            if (x & 0x4000000 > 0) {
                result = (result * 0x10000000002C5C860) >> 64;
            }
            if (x & 0x2000000 > 0) {
                result = (result * 0x1000000000162E430) >> 64;
            }
            if (x & 0x1000000 > 0) {
                result = (result * 0x10000000000B17218) >> 64;
            }
            if (x & 0x800000 > 0) {
                result = (result * 0x1000000000058B90C) >> 64;
            }
            if (x & 0x400000 > 0) {
                result = (result * 0x100000000002C5C86) >> 64;
            }
            if (x & 0x200000 > 0) {
                result = (result * 0x10000000000162E43) >> 64;
            }
            if (x & 0x100000 > 0) {
                result = (result * 0x100000000000B1721) >> 64;
            }
            if (x & 0x80000 > 0) {
                result = (result * 0x10000000000058B91) >> 64;
            }
            if (x & 0x40000 > 0) {
                result = (result * 0x1000000000002C5C8) >> 64;
            }
            if (x & 0x20000 > 0) {
                result = (result * 0x100000000000162E4) >> 64;
            }
            if (x & 0x10000 > 0) {
                result = (result * 0x1000000000000B172) >> 64;
            }
            if (x & 0x8000 > 0) {
                result = (result * 0x100000000000058B9) >> 64;
            }
            if (x & 0x4000 > 0) {
                result = (result * 0x10000000000002C5D) >> 64;
            }
            if (x & 0x2000 > 0) {
                result = (result * 0x1000000000000162E) >> 64;
            }
            if (x & 0x1000 > 0) {
                result = (result * 0x10000000000000B17) >> 64;
            }
            if (x & 0x800 > 0) {
                result = (result * 0x1000000000000058C) >> 64;
            }
            if (x & 0x400 > 0) {
                result = (result * 0x100000000000002C6) >> 64;
            }
            if (x & 0x200 > 0) {
                result = (result * 0x10000000000000163) >> 64;
            }
            if (x & 0x100 > 0) {
                result = (result * 0x100000000000000B1) >> 64;
            }
            if (x & 0x80 > 0) {
                result = (result * 0x10000000000000059) >> 64;
            }
            if (x & 0x40 > 0) {
                result = (result * 0x1000000000000002C) >> 64;
            }
            if (x & 0x20 > 0) {
                result = (result * 0x10000000000000016) >> 64;
            }
            if (x & 0x10 > 0) {
                result = (result * 0x1000000000000000B) >> 64;
            }
            if (x & 0x8 > 0) {
                result = (result * 0x10000000000000006) >> 64;
            }
            if (x & 0x4 > 0) {
                result = (result * 0x10000000000000003) >> 64;
            }
            if (x & 0x2 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }
            if (x & 0x1 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }

            // We're doing two things at the same time:
            //
            //   1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
            //      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
            //      rather than 192.
            //   2. Convert the result to the unsigned 60.18-decimal fixed-point format.
            //
            // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
            result *= SCALE;
            result >>= (191 - (x >> 64));
        }
    }

    /// @notice Finds the zero-based index of the first one in the binary representation of x.
    /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
    /// @param x The uint256 number for which to find the index of the most significant bit.
    /// @return msb The index of the most significant bit as an uint256.
    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
        if (x >= 2**128) {
            x >>= 128;
            msb += 128;
        }
        if (x >= 2**64) {
            x >>= 64;
            msb += 64;
        }
        if (x >= 2**32) {
            x >>= 32;
            msb += 32;
        }
        if (x >= 2**16) {
            x >>= 16;
            msb += 16;
        }
        if (x >= 2**8) {
            x >>= 8;
            msb += 8;
        }
        if (x >= 2**4) {
            x >>= 4;
            msb += 4;
        }
        if (x >= 2**2) {
            x >>= 2;
            msb += 2;
        }
        if (x >= 2**1) {
            // No need to shift x any more.
            msb += 1;
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
    ///
    /// Requirements:
    /// - The denominator cannot be zero.
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The multiplicand as an uint256.
    /// @param y The multiplier as an uint256.
    /// @param denominator The divisor as an uint256.
    /// @return result The result as an uint256.
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 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) {
            unchecked {
                result = prod0 / denominator;
            }
            return result;
        }

        // Make sure the result is less than 2^256. Also prevents denominator == 0.
        if (prod1 >= denominator) {
            revert PRBMath__MulDivOverflow(prod1, denominator);
        }

        ///////////////////////////////////////////////
        // 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.
        unchecked {
            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 lpotdod = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by lpotdod.
                denominator := div(denominator, lpotdod)

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

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

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

            // 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 floor(x*y÷1e18) with full precision.
    ///
    /// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
    /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
    /// being rounded to 1e-18.  See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
    ///
    /// Requirements:
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
    /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
    ///     1. x * y = type(uint256).max * SCALE
    ///     2. (x * y) % SCALE >= SCALE / 2
    ///
    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
        uint256 prod0;
        uint256 prod1;
        assembly {
            let mm := mulmod(x, y, not(0))
            prod0 := mul(x, y)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        if (prod1 >= SCALE) {
            revert PRBMath__MulDivFixedPointOverflow(prod1);
        }

        uint256 remainder;
        uint256 roundUpUnit;
        assembly {
            remainder := mulmod(x, y, SCALE)
            roundUpUnit := gt(remainder, 499999999999999999)
        }

        if (prod1 == 0) {
            unchecked {
                result = (prod0 / SCALE) + roundUpUnit;
                return result;
            }
        }

        assembly {
            result := add(
                mul(
                    or(
                        div(sub(prod0, remainder), SCALE_LPOTD),
                        mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
                    ),
                    SCALE_INVERSE
                ),
                roundUpUnit
            )
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
    ///
    /// Requirements:
    /// - None of the inputs can be type(int256).min.
    /// - The result must fit within int256.
    ///
    /// @param x The multiplicand as an int256.
    /// @param y The multiplier as an int256.
    /// @param denominator The divisor as an int256.
    /// @return result The result as an int256.
    function mulDivSigned(
        int256 x,
        int256 y,
        int256 denominator
    ) internal pure returns (int256 result) {
        if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
            revert PRBMath__MulDivSignedInputTooSmall();
        }

        // Get hold of the absolute values of x, y and the denominator.
        uint256 ax;
        uint256 ay;
        uint256 ad;
        unchecked {
            ax = x < 0 ? uint256(-x) : uint256(x);
            ay = y < 0 ? uint256(-y) : uint256(y);
            ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
        }

        // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
        uint256 rAbs = mulDiv(ax, ay, ad);
        if (rAbs > uint256(type(int256).max)) {
            revert PRBMath__MulDivSignedOverflow(rAbs);
        }

        // Get the signs of x, y and the denominator.
        uint256 sx;
        uint256 sy;
        uint256 sd;
        assembly {
            sx := sgt(x, sub(0, 1))
            sy := sgt(y, sub(0, 1))
            sd := sgt(denominator, sub(0, 1))
        }

        // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
        // If yes, the result should be negative.
        result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
    }

    /// @notice Calculates the square root of x, rounding down.
    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The uint256 number for which to calculate the square root.
    /// @return result The result as an uint256.
    function sqrt(uint256 x) internal pure returns (uint256 result) {
        if (x == 0) {
            return 0;
        }

        // Set the initial guess to the closest power of two that is higher than x.
        uint256 xAux = uint256(x);
        result = 1;
        if (xAux >= 0x100000000000000000000000000000000) {
            xAux >>= 128;
            result <<= 64;
        }
        if (xAux >= 0x10000000000000000) {
            xAux >>= 64;
            result <<= 32;
        }
        if (xAux >= 0x100000000) {
            xAux >>= 32;
            result <<= 16;
        }
        if (xAux >= 0x10000) {
            xAux >>= 16;
            result <<= 8;
        }
        if (xAux >= 0x100) {
            xAux >>= 8;
            result <<= 4;
        }
        if (xAux >= 0x10) {
            xAux >>= 4;
            result <<= 2;
        }
        if (xAux >= 0x8) {
            result <<= 1;
        }

        // The operations can never overflow because the result is max 2^127 when it enters this block.
        unchecked {
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1; // Seven iterations should be enough
            uint256 roundedDownResult = x / result;
            return result >= roundedDownResult ? roundedDownResult : result;
        }
    }
}

// File: prb-math/contracts/PRBMathUD60x18.sol


pragma solidity >=0.8.4;


/// @title PRBMathUD60x18
/// @author Paul Razvan Berg
/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18
/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60
/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the
/// maximum values permitted by the Solidity type uint256.
library PRBMathUD60x18 {
    /// @dev Half the SCALE number.
    uint256 internal constant HALF_SCALE = 5e17;

    /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.
    uint256 internal constant LOG2_E = 1442695040888963407;

    /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.
    uint256 internal constant MAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;

    /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.
    uint256 internal constant MAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457000000000000000000;

    /// @dev How many trailing decimals can be represented.
    uint256 internal constant SCALE = 1e18;

    /// @notice Calculates arithmetic average of x and y, rounding down.
    /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
    /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.
    function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {
        // The operations can never overflow.
        unchecked {
            // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need
            // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.
            result = (x >> 1) + (y >> 1) + (x & y & 1);
        }
    }

    /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.
    ///
    /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
    /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
    ///
    /// Requirements:
    /// - x must be less than or equal to MAX_WHOLE_UD60x18.
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number to ceil.
    /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.
    function ceil(uint256 x) internal pure returns (uint256 result) {
        if (x > MAX_WHOLE_UD60x18) {
            revert PRBMathUD60x18__CeilOverflow(x);
        }
        assembly {
            // Equivalent to "x % SCALE" but faster.
            let remainder := mod(x, SCALE)

            // Equivalent to "SCALE - remainder" but faster.
            let delta := sub(SCALE, remainder)

            // Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster.
            result := add(x, mul(delta, gt(remainder, 0)))
        }
    }

    /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.
    ///
    /// @dev Uses mulDiv to enable overflow-safe multiplication and division.
    ///
    /// Requirements:
    /// - The denominator cannot be zero.
    ///
    /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.
    /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.
    /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.
    function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
        result = PRBMath.mulDiv(x, SCALE, y);
    }

    /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.
    /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).
    function e() internal pure returns (uint256 result) {
        result = 2718281828459045235;
    }

    /// @notice Calculates the natural exponent of x.
    ///
    /// @dev Based on the insight that e^x = 2^(x * log2(e)).
    ///
    /// Requirements:
    /// - All from "log2".
    /// - x must be less than 133.084258667509499441.
    ///
    /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function exp(uint256 x) internal pure returns (uint256 result) {
        // Without this check, the value passed to "exp2" would be greater than 192.
        if (x >= 133084258667509499441) {
            revert PRBMathUD60x18__ExpInputTooBig(x);
        }

        // Do the fixed-point multiplication inline to save gas.
        unchecked {
            uint256 doubleScaleProduct = x * LOG2_E;
            result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
        }
    }

    /// @notice Calculates the binary exponent of x using the binary fraction method.
    ///
    /// @dev See https://ethereum.stackexchange.com/q/79903/24693.
    ///
    /// Requirements:
    /// - x must be 192 or less.
    /// - The result must fit within MAX_UD60x18.
    ///
    /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function exp2(uint256 x) internal pure returns (uint256 result) {
        // 2^192 doesn't fit within the 192.64-bit format used internally in this function.
        if (x >= 192e18) {
            revert PRBMathUD60x18__Exp2InputTooBig(x);
        }

        unchecked {
            // Convert x to the 192.64-bit fixed-point format.
            uint256 x192x64 = (x << 64) / SCALE;

            // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.
            result = PRBMath.exp2(x192x64);
        }
    }

    /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.
    /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
    /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
    /// @param x The unsigned 60.18-decimal fixed-point number to floor.
    /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.
    function floor(uint256 x) internal pure returns (uint256 result) {
        assembly {
            // Equivalent to "x % SCALE" but faster.
            let remainder := mod(x, SCALE)

            // Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster.
            result := sub(x, mul(remainder, gt(remainder, 0)))
        }
    }

    /// @notice Yields the excess beyond the floor of x.
    /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.
    /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.
    /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.
    function frac(uint256 x) internal pure returns (uint256 result) {
        assembly {
            result := mod(x, SCALE)
        }
    }

    /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.
    ///
    /// @dev Requirements:
    /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.
    ///
    /// @param x The basic integer to convert.
    /// @param result The same number in unsigned 60.18-decimal fixed-point representation.
    function fromUint(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            if (x > MAX_UD60x18 / SCALE) {
                revert PRBMathUD60x18__FromUintOverflow(x);
            }
            result = x * SCALE;
        }
    }

    /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.
    ///
    /// @dev Requirements:
    /// - x * y must fit within MAX_UD60x18, lest it overflows.
    ///
    /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {
        if (x == 0) {
            return 0;
        }

        unchecked {
            // Checking for overflow this way is faster than letting Solidity do it.
            uint256 xy = x * y;
            if (xy / x != y) {
                revert PRBMathUD60x18__GmOverflow(x, y);
            }

            // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE
            // during multiplication. See the comments within the "sqrt" function.
            result = PRBMath.sqrt(xy);
        }
    }

    /// @notice Calculates 1 / x, rounding towards zero.
    ///
    /// @dev Requirements:
    /// - x cannot be zero.
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.
    /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.
    function inv(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            // 1e36 is SCALE * SCALE.
            result = 1e36 / x;
        }
    }

    /// @notice Calculates the natural logarithm of x.
    ///
    /// @dev Based on the insight that ln(x) = log2(x) / log2(e).
    ///
    /// Requirements:
    /// - All from "log2".
    ///
    /// Caveats:
    /// - All from "log2".
    /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.
    /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.
    function ln(uint256 x) internal pure returns (uint256 result) {
        // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)
        // can return is 196205294292027477728.
        unchecked {
            result = (log2(x) * SCALE) / LOG2_E;
        }
    }

    /// @notice Calculates the common logarithm of x.
    ///
    /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
    /// logarithm based on the insight that log10(x) = log2(x) / log2(10).
    ///
    /// Requirements:
    /// - All from "log2".
    ///
    /// Caveats:
    /// - All from "log2".
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.
    /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.
    function log10(uint256 x) internal pure returns (uint256 result) {
        if (x < SCALE) {
            revert PRBMathUD60x18__LogInputTooSmall(x);
        }

        // Note that the "mul" in this block is the assembly multiplication operation, not the "mul" function defined
        // in this contract.
        // prettier-ignore
        assembly {
            switch x
            case 1 { result := mul(SCALE, sub(0, 18)) }
            case 10 { result := mul(SCALE, sub(1, 18)) }
            case 100 { result := mul(SCALE, sub(2, 18)) }
            case 1000 { result := mul(SCALE, sub(3, 18)) }
            case 10000 { result := mul(SCALE, sub(4, 18)) }
            case 100000 { result := mul(SCALE, sub(5, 18)) }
            case 1000000 { result := mul(SCALE, sub(6, 18)) }
            case 10000000 { result := mul(SCALE, sub(7, 18)) }
            case 100000000 { result := mul(SCALE, sub(8, 18)) }
            case 1000000000 { result := mul(SCALE, sub(9, 18)) }
            case 10000000000 { result := mul(SCALE, sub(10, 18)) }
            case 100000000000 { result := mul(SCALE, sub(11, 18)) }
            case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
            case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
            case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
            case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
            case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
            case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
            case 1000000000000000000 { result := 0 }
            case 10000000000000000000 { result := SCALE }
            case 100000000000000000000 { result := mul(SCALE, 2) }
            case 1000000000000000000000 { result := mul(SCALE, 3) }
            case 10000000000000000000000 { result := mul(SCALE, 4) }
            case 100000000000000000000000 { result := mul(SCALE, 5) }
            case 1000000000000000000000000 { result := mul(SCALE, 6) }
            case 10000000000000000000000000 { result := mul(SCALE, 7) }
            case 100000000000000000000000000 { result := mul(SCALE, 8) }
            case 1000000000000000000000000000 { result := mul(SCALE, 9) }
            case 10000000000000000000000000000 { result := mul(SCALE, 10) }
            case 100000000000000000000000000000 { result := mul(SCALE, 11) }
            case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
            case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
            case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
            case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
            case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
            case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
            case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
            case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
            case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
            case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
            case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
            case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
            case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
            case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
            case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
            case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
            case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
            case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
            case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
            case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
            case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
            case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
            case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
            case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
            case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
            case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
            case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
            case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
            case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
            case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
            case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
            case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
            case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
            case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
            case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
            case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
            case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
            case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
            case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
            case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
            case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
            case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
            case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
            case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
            case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
            case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
            case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
            case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }
            default {
                result := MAX_UD60x18
            }
        }

        if (result == MAX_UD60x18) {
            // Do the fixed-point division inline to save gas. The denominator is log2(10).
            unchecked {
                result = (log2(x) * SCALE) / 3321928094887362347;
            }
        }
    }

    /// @notice Calculates the binary logarithm of x.
    ///
    /// @dev Based on the iterative approximation algorithm.
    /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
    ///
    /// Requirements:
    /// - x must be greater than or equal to SCALE, otherwise the result would be negative.
    ///
    /// Caveats:
    /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.
    /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.
    function log2(uint256 x) internal pure returns (uint256 result) {
        if (x < SCALE) {
            revert PRBMathUD60x18__LogInputTooSmall(x);
        }
        unchecked {
            // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).
            uint256 n = PRBMath.mostSignificantBit(x / SCALE);

            // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow
            // because n is maximum 255 and SCALE is 1e18.
            result = n * SCALE;

            // This is y = x * 2^(-n).
            uint256 y = x >> n;

            // If y = 1, the fractional part is zero.
            if (y == SCALE) {
                return result;
            }

            // Calculate the fractional part via the iterative approximation.
            // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
            for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {
                y = (y * y) / SCALE;

                // Is y^2 > 2 and so in the range [2,4)?
                if (y >= 2 * SCALE) {
                    // Add the 2^(-m) factor to the logarithm.
                    result += delta;

                    // Corresponds to z/2 on Wikipedia.
                    y >>= 1;
                }
            }
        }
    }

    /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal
    /// fixed-point number.
    /// @dev See the documentation for the "PRBMath.mulDivFixedPoint" function.
    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
    /// @return result The product as an unsigned 60.18-decimal fixed-point number.
    function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
        result = PRBMath.mulDivFixedPoint(x, y);
    }

    /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.
    function pi() internal pure returns (uint256 result) {
        result = 3141592653589793238;
    }

    /// @notice Raises x to the power of y.
    ///
    /// @dev Based on the insight that x^y = 2^(log2(x) * y).
    ///
    /// Requirements:
    /// - All from "exp2", "log2" and "mul".
    ///
    /// Caveats:
    /// - All from "exp2", "log2" and "mul".
    /// - Assumes 0^0 is 1.
    ///
    /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.
    /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.
    /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.
    function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {
        if (x == 0) {
            result = y == 0 ? SCALE : uint256(0);
        } else {
            result = exp2(mul(log2(x), y));
        }
    }

    /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the
    /// famous algorithm "exponentiation by squaring".
    ///
    /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
    ///
    /// Requirements:
    /// - The result must fit within MAX_UD60x18.
    ///
    /// Caveats:
    /// - All from "mul".
    /// - Assumes 0^0 is 1.
    ///
    /// @param x The base as an unsigned 60.18-decimal fixed-point number.
    /// @param y The exponent as an uint256.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {
        // Calculate the first iteration of the loop in advance.
        result = y & 1 > 0 ? x : SCALE;

        // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
        for (y >>= 1; y > 0; y >>= 1) {
            x = PRBMath.mulDivFixedPoint(x, x);

            // Equivalent to "y % 2 == 1" but faster.
            if (y & 1 > 0) {
                result = PRBMath.mulDivFixedPoint(result, x);
            }
        }
    }

    /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.
    function scale() internal pure returns (uint256 result) {
        result = SCALE;
    }

    /// @notice Calculates the square root of x, rounding down.
    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
    ///
    /// Requirements:
    /// - x must be less than MAX_UD60x18 / SCALE.
    ///
    /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.
    /// @return result The result as an unsigned 60.18-decimal fixed-point .
    function sqrt(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            if (x > MAX_UD60x18 / SCALE) {
                revert PRBMathUD60x18__SqrtOverflow(x);
            }
            // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned
            // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).
            result = PRBMath.sqrt(x * SCALE);
        }
    }

    /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.
    /// @param x The unsigned 60.18-decimal fixed-point number to convert.
    /// @return result The same number in basic integer form.
    function toUint(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            result = x / SCALE;
        }
    }
}

// File: contracts/MultyOwned.sol

pragma solidity >=0.5.0;

//import "hardhat/console.sol";


/// @title у контракта несколько владельцев
contract MultyOwned {
    using PRBMathUD60x18 for uint256;

    uint256 public constant OWNERS_COUNT = 3; // количество владельцев
    uint256 constant OWNER_PART_0 = 425E15;
    uint256 constant OWNER_PART_1 = 425E15;
    uint256 constant OWNER_PART_2 = 150E15;
    address OWNER_0 = address(0x1d3d6671a8A6650E60802613a3838865a4c260ef);
    address OWNER_1 = address(0x79E551d8fF2eB3eC04e2d8B83c0714937cF00ECA);
    address OWNER_2 = address(0xE102c1e0E0DB088ea15f9032b839E9C8cAf92cBC);

    address[OWNERS_COUNT] _OwnerRequest; // кому предложено стать владельцем кошелька

    // раскомментировать, перед выполнением тестов
    /*constructor() {
        OWNER_0 = msg.sender;
    }*/

    /// @dev модификатор метода, только для владельца контракта
    modifier onlyOwner() {
        require(IsOwner(msg.sender), "Only owner can call this function.");
        _;
    }

    /// @dev определяет, является ли указанный адрес владельцем контракта
    function IsOwner(address account) public view returns (bool) {
        return account == OWNER_0 || account == OWNER_1 || account == OWNER_2;
    }

    /// @dev получает индекс владельца или индекс равный OWNERS_COUNT, если указанный адрес не владелец
    function GetContractOwner(uint256 index) public view returns (address) {
        if (index == 0) return OWNER_0;
        if (index == 1) return OWNER_1;
        if (index == 2) return OWNER_2;
        return address(0);
    }

    /// @dev выводит владельца с указанным индексом
    function GetContractOwnerIndex(address account)
        public
        view
        returns (uint8)
    {
        if (account == OWNER_0) return 0;
        if (account == OWNER_1) return 1;
        if (account == OWNER_2) return 2;
        return 4;
    }

    /// @dev предложить акку стать владельцем
    function TransferOwnerRequest(address newOwner) public onlyOwner {
        _OwnerRequest[GetContractOwnerIndex(msg.sender)] = newOwner;
    }

    /// @dev принимает запрос на получение права владения
    function ApplyOwnerRequest() public {
        if (_OwnerRequest[0] == msg.sender) {
            OWNER_0 = msg.sender;
            return;
        }
        if (_OwnerRequest[1] == msg.sender) {
            OWNER_1 = msg.sender;
            return;
        }
        if (_OwnerRequest[2] == msg.sender) {
            OWNER_2 = msg.sender;
            return;
        }
    }

    /// @dev донатит разработчикам
    function Donate() public payable {
        uint256 sum; // сколько всего отправили
        uint256 partSum;

        // передаем 0 разработчику
        partSum = PRBMathUD60x18.mul(OWNER_PART_0, msg.value);
        payable(OWNER_0).transfer(partSum);
        sum += partSum;

        // передаем 1 разработчику
        partSum = PRBMathUD60x18.mul(OWNER_PART_1, msg.value);
        if (sum + partSum > msg.value) {
            partSum = msg.value - sum;
            if (partSum > 0) payable(OWNER_1).transfer(partSum);            
            return;
        }
        payable(OWNER_1).transfer(partSum);
        sum += partSum;

        // передаем 2 разработчику
        partSum = PRBMathUD60x18.mul(OWNER_PART_2, msg.value);
        if (sum + partSum > msg.value) {
            partSum = msg.value - sum;
            if (partSum > 0) payable(OWNER_2).transfer(partSum);            
            return;
        }
        payable(OWNER_2).transfer(partSum);
    }
}

// File: contracts/OpenSeaMeta.sol

pragma solidity >=0.8.3;



/// @title описывает метаданные для Opensea
contract OpenSeaMeta is MultyOwned, ERC721Enumerable {   
    address _owner; // овнер - только для openSea и подобных систем
    string public ContractURI = "https://musicracernft.org/api/globalmeta"; // мета контракта
    string public BaseURI = "https://musicracernft.org/api/carsmeta/"; // базовый адрес для меты токенов

    constructor(string memory name_, string memory symbol_)
        ERC721(name_, symbol_)
    {
        _owner = msg.sender;
    }

    function owner() public view returns (address) {
        return _owner;
    }

    function SetOwner(address newOwner) public onlyOwner {
        _owner = newOwner;
    }

    /// @dev ссылка на метаданные уровня витрины
    //function contractURI() public view returns (string memory) {
    //    return ContractURIInternal;
    //}

    /// @dev задает адрес меты контракта
    function SetContractURI(string calldata newContractURI) public onlyOwner {
        ContractURI = newContractURI;
    }

    /// @dev задает новый BaseURI
    function SetBaseURI(string calldata newBaseURI) public onlyOwner {
        BaseURI = newBaseURI;
    }

    /// @dev используется для вычисления адресов через
    /// унаследованную функцию tokenURI(uint256 tokenId), который дописывает ID токена вконец
    function _baseURI() internal view override returns (string memory) {
        return BaseURI;
    }
}

// File: contracts/Car.sol

pragma solidity >=0.8.3;

/// @title описание формирования начальной цены машины
struct PriceData {
    /// @notice начальная цена 1=0.001 eth
    uint256 StartPrice;
    /// @notice конечная цена (когда все продано) 1=0.001 eth
    uint256 EndPrice;
    /// @notice тип формирования цены
    /// 0 - только стартовая цена
    /// 1 - линейная интерполяция от начальной цены к конечной
    uint256 PriceType;
}

/// @title тип части машины
struct CarPartType {
    /// @notice вероятность генерации не нуливого значения 100000=100%
    uint256 Probability;
    /// @notice сколько всего частей имеется
    uint256 Count;
}

/// @title тип машины
struct CarType {
    /// @notice все типы частей
    CarPartType[] PartTypes;
    /// @notice вероятности окрасок 100% будет окраска=100000
    uint256[] Colors;
    /// @notice сколько машин создано
    uint256 Count;
    /// @notice максимальное количество генерируемых машин
    uint256 MaxCount;
    /// @notice цена минта
    PriceData Price;
    /// @notice сколько машин зарезервировано для фабрики (это количество машин не может минтиться с контракта напрямую)
    uint256 FactoryReserve;
    /// @notice если истина, то минт машин этого типа возможен
    bool Enable;
}

/// @title описание инстанции одной машины
struct Car {
    /// @notice ID типа машины (больше 0, тк 0 это отсуствие типа)
    uint256 TypeId;
    /// @notice установленные части машины 0 - часть не задана
    uint256[] Parts;
    /// @notice какие цвета в машине включены, а какие нет
    bool[] ColorsEnable;
    /// @notice цвета машины
    uint256[] Colors;
}

// File: contracts/CarFactory.sol

pragma solidity >=0.8.4;




/// @title порождает машины
contract CarFactory is OpenSeaMeta {
    using PRBMathUD60x18 for uint256;

    uint256 PriceMul = 1e15; // 1=0.001 эфира

    mapping(uint256 => CarType) public CarsTypes; // все типы машин
    uint256 public CarTypesCount = 0; // общее количество типов машин
    uint256 _RandNonce = 0; // нонс рандома
    event NewType(uint256 indexed carType); // когда создается новый тип машины

    constructor(string memory name_, string memory symbol_)
        OpenSeaMeta(name_, symbol_)
    {
        CarType storage ct = CarsTypes[1];
        ct.PartTypes.push(CarPartType(50e3, 83));
        ct.PartTypes.push(CarPartType(100e3, 28));
        ct.PartTypes.push(CarPartType(50e3, 10));
        ct.PartTypes.push(CarPartType(50e3, 11));
        ct.PartTypes.push(CarPartType(100e3, 11));
        ct.Colors = new uint256[](2);
        ct.Colors[0] = 100e3;
        ct.Colors[1] = 50e3;
        ct.MaxCount = 333;
        ct.Price = PriceData(132, 330, 1);
        ct.FactoryReserve = 47;
        ct.Enable = true;

        CarTypesCount = 1;
        emit NewType(CarTypesCount);
    }

    /// @dev порождает новую машину указанного типа
    /// @param carTypeId ID типа машины
    /// @param carType тип машины
    function CreateCar(uint256 carTypeId, CarType storage carType)
        internal
        returns (Car memory)
    {
        // генерируем части машины из ее типа
        uint256[] memory parts = new uint256[](carType.PartTypes.length);
        for (uint256 i = 0; i < carType.PartTypes.length; ++i) {
            CarPartType memory partType = carType.PartTypes[i];
            if ((_Random() % 100000) < partType.Probability)
                parts[i] = 1 + (_Random() % partType.Count);
            else parts[i] = 0;
        }

        // генерация цветов
        bool[] memory colorsEnable = new bool[](carType.Colors.length);
        uint256[] memory colors = new uint256[](carType.Colors.length);
        for (uint256 i = 0; i < carType.Colors.length; ++i) {
            colorsEnable[i] = (_Random() % 100000) < carType.Colors[i];
            if (colorsEnable[i]) colors[i] = RandomColor();
        }

        // создаем машину
        Car memory newCar = Car(carTypeId, parts, colorsEnable, colors);
        // увеличиваем счетчик созданных машин
        carType.Count++;
        // вывод результата
        return newCar;
    }

    /// @notice
    function RandomColor() internal returns (uint256) {
        uint256 r = _Random() % 256;
        uint256 g = _Random() % 256;
        uint256 b = _Random() % 256;
        //uint256 a = _Random() % 256;

        return b | (g << 8) | (r << 16); // & (a << 24);
    }

    function _Random() internal returns (uint256) {
        uint256 res = uint256(
            keccak256(abi.encodePacked(msg.sender, _RandNonce, block.timestamp))
        );
        _RandNonce++;
        return res;
    }

    /// @dev добавляет новый тип машины
    function AddCarType(CarType calldata newType) public onlyOwner {
        require(
            newType.Price.StartPrice <= newType.Price.EndPrice,
            "car price is incorrect"
        );
        CarTypesCount++;
        CarsTypes[CarTypesCount] = newType;
        emit NewType(CarTypesCount);
    }

    /// @dev возвращает текущую цену машины
    /// @param carTypeId Id типа машины
    function GetPrice(uint256 carTypeId) public view returns (uint256) {
        return GetPriceAlgorithm(carTypeId) * PriceMul;
    }

    /// @dev алгоритм получения ценника
    function GetPriceAlgorithm(uint256 carTypeId)
        private
        view
        returns (uint256)
    {
        CarType memory carType = CarsTypes[carTypeId];
        if (carType.Price.PriceType == 0) return carType.Price.StartPrice;
        if (carType.Price.PriceType == 1) {
            uint256 f = PRBMathUD60x18.div(carType.Count, carType.MaxCount);
            return
                carType.Price.StartPrice +
                PRBMathUD60x18.mul(
                    f,
                    carType.Price.EndPrice - carType.Price.StartPrice
                );
        } else return carType.Price.StartPrice;
    }

    /// @dev возвращает настройки ценообразования минта на определенный тип машин
    function GetPriceData(uint256 carTypeId)
        public
        view
        returns (PriceData memory)
    {
        return CarsTypes[carTypeId].Price;
    }

    /// @dev возвращает количество возможных частей машины указанного типа
    /// @param carTypeId Id типа машины
    function GetPartsCount(uint256 carTypeId) public view returns (uint256) {
        return CarsTypes[carTypeId].PartTypes.length;
    }

    /// @dev возвращает тип части машины
    /// @param carTypeId Id типа машины
    /// @param partIndex индекс части машины
    function GetPart(uint256 carTypeId, uint256 partIndex)
        public
        view
        returns (CarPartType memory)
    {
        return CarsTypes[carTypeId].PartTypes[partIndex];
    }
}

// File: contracts/MusicRacerNFT.sol

pragma solidity >=0.8.3;

//import "hardhat/console.sol";




/// @title определяет владение машинами
contract MusicRacerNFT is CarFactory {
    mapping(uint256 => Car) public IdToCar; // кэш машин по ID
    uint256 _CurMintId = 1; // текщий ID токена для минта
    address public Factory; // фабрика, которая может минтить токены
    mapping(uint256 => bool) public ChangeCarsBlock; // блоки изменений по типам машин (если true то гарантируется, что эту машину овнер изменить не может)

    constructor() CarFactory("MusicRacerNFT", "MRCR") {}

    /// @dev возвращает непосредственно данные машины для конкретного токена
    function GetCar(uint256 tokenId) public view returns (Car memory) {
        return IdToCar[tokenId];
    }

    /// @dev возвращает цвет в формате RGB
    /// @param tokenId id токена
    /// @param colorIndex индекс цвета
    function GetCarColorRGB(uint256 tokenId, uint256 colorIndex)
        public
        view
        returns (
            bool, // имеется ли цвет
            uint8, // r
            uint8, // g
            uint8 // b
        )
    {
        Car memory car = GetCar(tokenId);
        uint256 color = car.Colors[colorIndex];
        uint8 b = (uint8)(color & 0xff);
        color >>= 8;
        uint8 g = (uint8)(color & 0xff);
        color >>= 8;
        uint8 r = (uint8)(color & 0xff);
        return (car.ColorsEnable[colorIndex], r, g, b);
    }

    /// @dev задает адрес фабрики-краудсейла
    function SetFactory(address newFactory) public onlyOwner {
        Factory = newFactory;
    }

    /// @dev проверка возможности заминтить токен вызывающим адресом
    function canMint(uint256 carTypeId) external view returns (bool) {
        return canMintInternal(CarsTypes[carTypeId]);
    }

    function canMintInternal(CarType storage carType)
        internal
        view
        returns (bool)
    {
        if (msg.sender == Factory) {
            if (carType.Count >= carType.MaxCount) return false;
        } else if (carType.Count + carType.FactoryReserve >= carType.MaxCount)
            return false;
        if (
            msg.sender != address(this) &&
            msg.sender != Factory &&
            !IsOwner(msg.sender)
        ) return false;
        return carType.Enable;
    }

    /// @dev минтит машину с указанным ID (метод для фабрики)
    /// @param carTypeId id типа машины
    /// @param _toAddress кому заминтить
    function mint(uint256 carTypeId, address _toAddress) external {
        CarType storage carType = CarsTypes[carTypeId];
        require(canMintInternal(carType), "cannot mint car");
        IdToCar[_CurMintId] = CreateCar(carTypeId, carType);
        _mint(_toAddress, _CurMintId);
        _CurMintId++;
        if (msg.sender == Factory) --carType.FactoryReserve;
    }

    /// @dev производит изначальный минт машин
    /// @param carTypeId ID типа машины, которую нужно заминтить
    function MintCar(uint256 carTypeId) public payable {
        require(msg.value >= GetPrice(carTypeId), "not enough eth");
        Donate();
        this.mint(carTypeId, msg.sender);
    }

    /// @dev изменяет машину
    /// @param tokenId id токена
    /// @param newCar новые данные машины
    function ChangeCar(uint256 tokenId, Car calldata newCar) public onlyOwner {
        uint256 carTypeId = IdToCar[tokenId].TypeId;
        require(!ChangeCarsBlock[carTypeId], "cars changes blocked");
        IdToCar[tokenId] = newCar;
        IdToCar[tokenId].TypeId = carTypeId;
    }

    /// @dev изменяет настройки генерации машин определенного типа
    function ChangeCarType(uint256 carTypeId, CarType calldata newTypeData)
        public
        onlyOwner
    {
        require(!ChangeCarsBlock[carTypeId], "cars changes blocked");
        CarsTypes[carTypeId] = newTypeData;
    }

    /// @dev изменяет стоимость машины
    function SetCarPrice(uint256 carTypeId, PriceData calldata newPrice)
        public
        onlyOwner
    {
        require(!ChangeCarsBlock[carTypeId], "cars changes blocked");
        require(newPrice.StartPrice <= newPrice.EndPrice, "price is incorrect");
        CarsTypes[carTypeId].Price = newPrice;
    }

    /// @dev блокирует изменения определенного типа машин
    /// @param carTypeId тип машин
    function BlockCarChanges(uint256 carTypeId) public onlyOwner {
        ChangeCarsBlock[carTypeId] = true;
    }

    /// @dev задает возможность минтить машину указанного типа
    /// @param carTypeId тип машин
    /// @param mintEnable можно ли минтить машину
    function SetMintEnable(uint256 carTypeId, bool mintEnable)
        public
        onlyOwner
    {
        CarsTypes[carTypeId].Enable = mintEnable;
    }

    /// @dev выводит список всех токенов указанного владельца
    /// @param account на какого владельца выдать список
    function GetTokensList(address account)
        public
        view
        returns (uint256[] memory)
    {
        uint256 count = balanceOf(account);
        uint256[] memory res = new uint256[](count);
        for (uint256 i = 0; i < count; ++i) {
            res[i] = tokenOfOwnerByIndex(account, i);
        }
        return res;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"}],"name":"PRBMath__MulDivFixedPointOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"PRBMath__MulDivOverflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"carType","type":"uint256"}],"name":"NewType","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"Probability","type":"uint256"},{"internalType":"uint256","name":"Count","type":"uint256"}],"internalType":"struct CarPartType[]","name":"PartTypes","type":"tuple[]"},{"internalType":"uint256[]","name":"Colors","type":"uint256[]"},{"internalType":"uint256","name":"Count","type":"uint256"},{"internalType":"uint256","name":"MaxCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"StartPrice","type":"uint256"},{"internalType":"uint256","name":"EndPrice","type":"uint256"},{"internalType":"uint256","name":"PriceType","type":"uint256"}],"internalType":"struct PriceData","name":"Price","type":"tuple"},{"internalType":"uint256","name":"FactoryReserve","type":"uint256"},{"internalType":"bool","name":"Enable","type":"bool"}],"internalType":"struct CarType","name":"newType","type":"tuple"}],"name":"AddCarType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ApplyOwnerRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"BaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"BlockCarChanges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"CarTypesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"CarsTypes","outputs":[{"internalType":"uint256","name":"Count","type":"uint256"},{"internalType":"uint256","name":"MaxCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"StartPrice","type":"uint256"},{"internalType":"uint256","name":"EndPrice","type":"uint256"},{"internalType":"uint256","name":"PriceType","type":"uint256"}],"internalType":"struct PriceData","name":"Price","type":"tuple"},{"internalType":"uint256","name":"FactoryReserve","type":"uint256"},{"internalType":"bool","name":"Enable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"uint256","name":"TypeId","type":"uint256"},{"internalType":"uint256[]","name":"Parts","type":"uint256[]"},{"internalType":"bool[]","name":"ColorsEnable","type":"bool[]"},{"internalType":"uint256[]","name":"Colors","type":"uint256[]"}],"internalType":"struct Car","name":"newCar","type":"tuple"}],"name":"ChangeCar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"},{"components":[{"components":[{"internalType":"uint256","name":"Probability","type":"uint256"},{"internalType":"uint256","name":"Count","type":"uint256"}],"internalType":"struct CarPartType[]","name":"PartTypes","type":"tuple[]"},{"internalType":"uint256[]","name":"Colors","type":"uint256[]"},{"internalType":"uint256","name":"Count","type":"uint256"},{"internalType":"uint256","name":"MaxCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"StartPrice","type":"uint256"},{"internalType":"uint256","name":"EndPrice","type":"uint256"},{"internalType":"uint256","name":"PriceType","type":"uint256"}],"internalType":"struct PriceData","name":"Price","type":"tuple"},{"internalType":"uint256","name":"FactoryReserve","type":"uint256"},{"internalType":"bool","name":"Enable","type":"bool"}],"internalType":"struct CarType","name":"newTypeData","type":"tuple"}],"name":"ChangeCarType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ChangeCarsBlock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ContractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"Factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"GetCar","outputs":[{"components":[{"internalType":"uint256","name":"TypeId","type":"uint256"},{"internalType":"uint256[]","name":"Parts","type":"uint256[]"},{"internalType":"bool[]","name":"ColorsEnable","type":"bool[]"},{"internalType":"uint256[]","name":"Colors","type":"uint256[]"}],"internalType":"struct Car","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"colorIndex","type":"uint256"}],"name":"GetCarColorRGB","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"GetContractOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"GetContractOwnerIndex","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"},{"internalType":"uint256","name":"partIndex","type":"uint256"}],"name":"GetPart","outputs":[{"components":[{"internalType":"uint256","name":"Probability","type":"uint256"},{"internalType":"uint256","name":"Count","type":"uint256"}],"internalType":"struct CarPartType","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"GetPartsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"GetPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"GetPriceData","outputs":[{"components":[{"internalType":"uint256","name":"StartPrice","type":"uint256"},{"internalType":"uint256","name":"EndPrice","type":"uint256"},{"internalType":"uint256","name":"PriceType","type":"uint256"}],"internalType":"struct PriceData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"GetTokensList","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"IdToCar","outputs":[{"internalType":"uint256","name":"TypeId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"IsOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"MintCar","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"OWNERS_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"SetBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"},{"components":[{"internalType":"uint256","name":"StartPrice","type":"uint256"},{"internalType":"uint256","name":"EndPrice","type":"uint256"},{"internalType":"uint256","name":"PriceType","type":"uint256"}],"internalType":"struct PriceData","name":"newPrice","type":"tuple"}],"name":"SetCarPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newContractURI","type":"string"}],"name":"SetContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFactory","type":"address"}],"name":"SetFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"},{"internalType":"bool","name":"mintEnable","type":"bool"}],"name":"SetMintEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"SetOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"TransferOwnerRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"}],"name":"canMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"carTypeId","type":"uint256"},{"internalType":"address","name":"_toAddress","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]

600080546001600160a01b0319908116731d3d6671a8a6650e60802613a3838865a4c260ef179091556001805482167379e551d8ff2eb3ec04e2d8b83c0714937cf00eca1790556002805490911673e102c1e0e0db088ea15f9032b839e9c8caf92cbc17905560e060405260286080818152906200438160a03980516200008f91601191602090910190620003e5565b50604051806060016040528060278152602001620043a9602791398051620000c091601291602090910190620003e5565b5066038d7ea4c68000601355600060155560006016556001601855348015620000e857600080fd5b506040518060400160405280600d81526020016c135d5cda58d49858d95c939195609a1b8152506040518060400160405280600481526020016326a921a960e11b81525081818181816006908051906020019062000148929190620003e5565b5080516200015e906007906020840190620003e5565b505060108054336001600160a01b031990911617905550506014602090815260408051808201825261c35080825260538285019081527fb6c61a840592cc84133e4b25bd509abf4659307c57b160799b38490a5aa48f2c805460018181018355600083815295517f2fdc54bebe143af21bc9f7874666206c3383b1c51a1a7063fa557c077952093e60029384028181019290925594517f2fdc54bebe143af21bc9f7874666206c3383b1c51a1a7063fa557c077952093f9182015587518089018952620186a0808252601c828c0190815286548086018855878b5292519286028089019390935551918301919091558851808a018a52878152600a818c0190815286548086018855878b5291519186028089019290925551908301558851808a018a52968752600b878b0181815286548086018855878b5298519886028089019990995551978301979097558851808a018a52908152808a0196875284549283018555968490529551908202938401559251919093015582518181526060810184529194509092909190830190803683375050815162000308926001850192506020019062000474565b50620186a081600101600081548110620003265762000326620004c8565b906000526020600020018190555061c35081600101600181548110620003505762000350620004c8565b600091825260208083209091019290925561014d600384015560408051606081018252608480825261014a94820185905260019183018290526004860155600585019390935560068401839055602f600785015560088401805460ff1916841790556015839055517f097a2f6c6a41ed0979fb29808bc5ff14ed8e2acb53f623525175eedfdaab1d4e9190a25050506200051b565b828054620003f390620004de565b90600052602060002090601f01602090048101928262000417576000855562000462565b82601f106200043257805160ff191683800117855562000462565b8280016001018555821562000462579182015b828111156200046257825182559160200191906001019062000445565b5062000470929150620004b1565b5090565b8280548282559060005260206000209081019282156200046257916020028201828111156200046257825182559160200191906001019062000445565b5b80821115620004705760008155600101620004b2565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620004f357607f821691505b602082108114156200051557634e487b7160e01b600052602260045260246000fd5b50919050565b613e56806200052b6000396000f3fe6080604052600436106102e45760003560e01c806394bf804d11610190578063ce1f40a1116100dc578063e3bb4dc611610095578063f2b84c4f1161006f578063f2b84c4f146109d7578063fb1c9e6f14610a09578063ff4ccd3514610a1e578063ffcc43c414610a3357600080fd5b8063e3bb4dc614610941578063e985e9c514610961578063eeb36ee4146109aa57600080fd5b8063ce1f40a11461086e578063d89fd2a414610881578063d917deb5146108b1578063db0e0e85146108b9578063dd0860a8146108e6578063e160ddb91461090657600080fd5b8063b8728cb911610149578063c81312c011610123578063c81312c0146107cd578063c83dd23114610818578063c87b56dd14610838578063cb24bc791461085857600080fd5b8063b8728cb914610760578063b88d4fde14610780578063c702c094146107a057600080fd5b806394bf804d1461069e57806395d89b41146106be5780639edc654b146106d3578063a22cb46514610700578063a62141b814610720578063aa6049eb1461074057600080fd5b806332b3c39c1161024f5780635dd871a31161020857806370a08231116101e257806370a082311461061357806375a5316f1461063357806382a0976d146106605780638da5cb5b1461068057600080fd5b80635dd871a3146105be5780636352211e146105de5780636c8db545146105fe57600080fd5b806332b3c39c1461049957806335265716146104b9578063399e28831461053e57806342842e0e1461055e5780634f6ccce71461057e5780635ca9f7501461059e57600080fd5b8063167d3e9c116102a1578063167d3e9c146103da57806318160ddd146103fa5780631c893ef91461041957806323b872dd1461043957806323c8c948146104595780632f745c591461047957600080fd5b80630148541f146102e957806301ffc9a71461030b57806306fdde0314610340578063081812fc14610362578063095ea7b31461039a5780631536ed8b146103ba575b600080fd5b3480156102f557600080fd5b5061030961030436600461315d565b610a48565b005b34801561031757600080fd5b5061032b6103263660046131c4565b610ae6565b60405190151581526020015b60405180910390f35b34801561034c57600080fd5b50610355610b11565b6040516103379190613239565b34801561036e57600080fd5b5061038261037d36600461324c565b610ba3565b6040516001600160a01b039091168152602001610337565b3480156103a657600080fd5b506103096103b5366004613281565b610c38565b3480156103c657600080fd5b506103826103d536600461324c565b610d4e565b3480156103e657600080fd5b506103096103f53660046132ab565b610da2565b34801561040657600080fd5b50600e545b604051908152602001610337565b34801561042557600080fd5b506103096104343660046132ab565b610de9565b34801561044557600080fd5b506103096104543660046132c6565b610e30565b34801561046557600080fd5b50610309610474366004613302565b610e61565b34801561048557600080fd5b5061040b610494366004613281565b610e92565b3480156104a557600080fd5b506103096104b4366004613382565b610f28565b3480156104c557600080fd5b5061052d6104d436600461324c565b601460209081526000918252604091829020600281015460038201548451606081018652600484015481526005840154948101949094526006830154948401949094526007820154600890920154909392919060ff1685565b6040516103379594939291906133a7565b34801561054a57600080fd5b5061030961055936600461324c565b610f70565b34801561056a57600080fd5b506103096105793660046132c6565b610fb0565b34801561058a57600080fd5b5061040b61059936600461324c565b610fcb565b3480156105aa57600080fd5b506103096105b9366004613302565b61105e565b3480156105ca57600080fd5b5061032b6105d936600461324c565b61108f565b3480156105ea57600080fd5b506103826105f936600461324c565b6110a6565b34801561060a57600080fd5b5061030961111d565b34801561061f57600080fd5b5061040b61062e3660046132ab565b611194565b34801561063f57600080fd5b5061040b61064e36600461324c565b60176020526000908152604090205481565b34801561066c57600080fd5b5061030961067b366004613401565b61121b565b34801561068c57600080fd5b506010546001600160a01b0316610382565b3480156106aa57600080fd5b506103096106b9366004613448565b61128f565b3480156106ca57600080fd5b506103556113aa565b3480156106df57600080fd5b5061040b6106ee36600461324c565b60009081526014602052604090205490565b34801561070c57600080fd5b5061030961071b366004613474565b6113b9565b34801561072c57600080fd5b5061030961073b3660046134a0565b61147e565b34801561074c57600080fd5b5061040b61075b36600461324c565b611550565b34801561076c57600080fd5b5061030961077b3660046134d8565b611568565b34801561078c57600080fd5b5061030961079b366004613523565b611641565b3480156107ac57600080fd5b506107c06107bb3660046132ab565b611673565b604051610337919061363a565b3480156107d957600080fd5b506107ed6107e836600461364d565b611713565b60408051941515855260ff938416602086015291831691840191909152166060820152608001610337565b34801561082457600080fd5b50601954610382906001600160a01b031681565b34801561084457600080fd5b5061035561085336600461324c565b611794565b34801561086457600080fd5b5061040b60155481565b61030961087c36600461324c565b61186f565b34801561088d57600080fd5b5061032b61089c36600461324c565b601a6020526000908152604090205460ff1681565b61030961191a565b3480156108c557600080fd5b506108d96108d436600461324c565b611ade565b604051610337919061366f565b3480156108f257600080fd5b5061032b6109013660046132ab565b611b3e565b34801561091257600080fd5b5061092661092136600461364d565b611b83565b60408051825181526020928301519281019290925201610337565b34801561094d57600080fd5b5061030961095c3660046132ab565b611bec565b34801561096d57600080fd5b5061032b61097c366004613690565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205460ff1690565b3480156109b657600080fd5b506109ca6109c536600461324c565b611c52565b60405161033791906136ba565b3480156109e357600080fd5b506109f76109f23660046132ab565b611dc9565b60405160ff9091168152602001610337565b348015610a1557600080fd5b5061040b600381565b348015610a2a57600080fd5b50610355611e2c565b348015610a3f57600080fd5b50610355611eba565b610a5133611b3e565b610a765760405162461bcd60e51b8152600401610a6d9061374f565b60405180910390fd5b600082815260176020908152604080832054808452601a9092529091205460ff1615610ab45760405162461bcd60e51b8152600401610a6d90613791565b60008381526017602052604090208290610ace82826139a5565b50506000928352601760205260409092209190915550565b60006001600160e01b0319821663780e9d6360e01b1480610b0b5750610b0b82611ec7565b92915050565b606060068054610b2090613a59565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4c90613a59565b8015610b995780601f10610b6e57610100808354040283529160200191610b99565b820191906000526020600020905b815481529060010190602001808311610b7c57829003601f168201915b5050505050905090565b6000818152600860205260408120546001600160a01b0316610c1c5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a6d565b506000908152600a60205260409020546001600160a01b031690565b6000610c43826110a6565b9050806001600160a01b0316836001600160a01b03161415610cb15760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a6d565b336001600160a01b0382161480610ccd5750610ccd813361097c565b610d3f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a6d565b610d498383611f17565b505050565b600081610d665750506000546001600160a01b031690565b8160011415610d805750506001546001600160a01b031690565b8160021415610d9a5750506002546001600160a01b031690565b506000919050565b610dab33611b3e565b610dc75760405162461bcd60e51b8152600401610a6d9061374f565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b610df233611b3e565b610e0e5760405162461bcd60e51b8152600401610a6d9061374f565b601980546001600160a01b0319166001600160a01b0392909216919091179055565b610e3a3382611f85565b610e565760405162461bcd60e51b8152600401610a6d90613a8e565b610d4983838361207c565b610e6a33611b3e565b610e865760405162461bcd60e51b8152600401610a6d9061374f565b610d4960128383612fed565b6000610e9d83611194565b8210610eff5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610a6d565b506001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610f3133611b3e565b610f4d5760405162461bcd60e51b8152600401610a6d9061374f565b600091825260146020526040909120600801805460ff1916911515919091179055565b610f7933611b3e565b610f955760405162461bcd60e51b8152600401610a6d9061374f565b6000908152601a60205260409020805460ff19166001179055565b610d4983838360405180602001604052806000815250611641565b6000610fd6600e5490565b82106110395760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610a6d565b600e828154811061104c5761104c613adf565b90600052602060002001549050919050565b61106733611b3e565b6110835760405162461bcd60e51b8152600401610a6d9061374f565b610d4960118383612fed565b6000818152601460205260408120610b0b90612227565b6000818152600860205260408120546001600160a01b031680610b0b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a6d565b6003546001600160a01b031633141561114457600080546001600160a01b03191633179055565b6004546001600160a01b031633141561116b57600180546001600160a01b03191633179055565b6005546001600160a01b031633141561119257600280546001600160a01b03191633179055565b565b60006001600160a01b0382166111ff5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a6d565b506001600160a01b031660009081526009602052604090205490565b61122433611b3e565b6112405760405162461bcd60e51b8152600401610a6d9061374f565b6000828152601a602052604090205460ff161561126f5760405162461bcd60e51b8152600401610a6d90613791565b600082815260146020526040902081906112898282613bbc565b50505050565b60008281526014602052604090206112a681612227565b6112e45760405162461bcd60e51b815260206004820152600f60248201526e31b0b73737ba1036b4b73a1031b0b960891b6044820152606401610a6d565b6112ee83826122c4565b601854600090815260176020908152604090912082518155828201518051919261132092600185019290910190613071565b506040820151805161133c9160028401916020909101906130ac565b5060608201518051611358916003840191602090910190613071565b50905050611368826018546125c0565b6018805490600061137883613c90565b90915550506019546001600160a01b0316331415610d495780600701600081546113a190613cab565b90915550505050565b606060078054610b2090613a59565b6001600160a01b0382163314156114125760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a6d565b336000818152600b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61148733611b3e565b6114a35760405162461bcd60e51b8152600401610a6d9061374f565b6000828152601a602052604090205460ff16156114d25760405162461bcd60e51b8152600401610a6d90613791565b60208101358135111561151c5760405162461bcd60e51b81526020600482015260126024820152711c1c9a58d9481a5cc81a5b98dbdc9c9958dd60721b6044820152606401610a6d565b6000828152601460205260409020819060040161128982828135815560208201356001820155604082013560028201555050565b600060135461155e8361270e565b610b0b9190613826565b61157133611b3e565b61158d5760405162461bcd60e51b8152600401610a6d9061374f565b60a0810135608082013511156115de5760405162461bcd60e51b815260206004820152601660248201527518d85c881c1c9a58d9481a5cc81a5b98dbdc9c9958dd60521b6044820152606401610a6d565b601580549060006115ee83613c90565b9091555050601554600090815260146020526040902081906116108282613bbc565b50506015546040517f097a2f6c6a41ed0979fb29808bc5ff14ed8e2acb53f623525175eedfdaab1d4e90600090a250565b61164b3383611f85565b6116675760405162461bcd60e51b8152600401610a6d90613a8e565b611289848484846128de565b6060600061168083611194565b905060008167ffffffffffffffff81111561169d5761169d61350d565b6040519080825280602002602001820160405280156116c6578160200160208202803683370190505b50905060005b8281101561170b576116de8582610e92565b8282815181106116f0576116f0613adf565b602090810291909101015261170481613c90565b90506116cc565b509392505050565b600080600080600061172487611c52565b905060008160600151878151811061173e5761173e613adf565b602090810291909101015160408301518051601083901c935060ff8084169360081c811692908516918b90811061177757611777613adf565b60209081029190910101519b909a50909850909650945050505050565b6000818152600860205260409020546060906001600160a01b03166118135760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610a6d565b600061181d612911565b9050600081511161183d5760405180602001604052806000815250611868565b8061184784612920565b604051602001611858929190613cc2565b6040516020818303038152906040525b9392505050565b61187881611550565b3410156118b85760405162461bcd60e51b815260206004820152600e60248201526d0dcdee840cadcdeeaced040cae8d60931b6044820152606401610a6d565b6118c061191a565b6040516394bf804d60e01b81526004810182905233602482015230906394bf804d90604401600060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b5050505050565b60008061192f6705e5e73f8d8a800034612a1e565b600080546040519293506001600160a01b03169183156108fc0291849190818181858888f1935050505015801561196a573d6000803e3d6000fd5b506119758183613cf1565b91506119896705e5e73f8d8a800034612a1e565b9050346119968284613cf1565b11156119ec576119a68234613d09565b905080156119e8576001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b5050565b6001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015611a26573d6000803e3d6000fd5b50611a318183613cf1565b9150611a45670214e8348c4f000034612a1e565b905034611a528284613cf1565b1115611aa457611a628234613d09565b905080156119e8576002546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b6002546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b611b0260405180606001604052806000815260200160008152602001600081525090565b50600090815260146020908152604091829020825160608101845260048201548152600582015492810192909252600601549181019190915290565b600080546001600160a01b0383811691161480611b6857506001546001600160a01b038381169116145b80610b0b5750506002546001600160a01b0390811691161490565b60408051808201909152600080825260208201526000838152601460205260409020805483908110611bb757611bb7613adf565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050905092915050565b611bf533611b3e565b611c115760405162461bcd60e51b8152600401610a6d9061374f565b806003611c1d33611dc9565b60ff1660038110611c3057611c30613adf565b0180546001600160a01b0319166001600160a01b039290921691909117905550565b611c7d6040518060800160405280600081526020016060815260200160608152602001606081525090565b60008281526017602090815260409182902082516080810184528154815260018201805485518186028101860190965280865291949293858101939290830182828015611ce957602002820191906000526020600020905b815481526020019060010190808311611cd5575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611d6157602002820191906000526020600020906000905b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411611d305790505b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015611db957602002820191906000526020600020905b815481526020019060010190808311611da5575b5050505050815250509050919050565b600080546001600160a01b0383811691161415611de857506000919050565b6001546001600160a01b0383811691161415611e0657506001919050565b6002546001600160a01b0383811691161415611e2457506002919050565b506004919050565b60118054611e3990613a59565b80601f0160208091040260200160405190810160405280929190818152602001828054611e6590613a59565b8015611eb25780601f10611e8757610100808354040283529160200191611eb2565b820191906000526020600020905b815481529060010190602001808311611e9557829003601f168201915b505050505081565b60128054611e3990613a59565b60006001600160e01b031982166380ac58cd60e01b1480611ef857506001600160e01b03198216635b5e139f60e01b145b80610b0b57506301ffc9a760e01b6001600160e01b0319831614610b0b565b6000818152600a6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611f4c826110a6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600860205260408120546001600160a01b0316611ffe5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a6d565b6000612009836110a6565b9050806001600160a01b0316846001600160a01b031614806120445750836001600160a01b031661203984610ba3565b6001600160a01b0316145b8061207457506001600160a01b038082166000908152600b602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661208f826110a6565b6001600160a01b0316146120f75760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610a6d565b6001600160a01b0382166121595760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a6d565b612164838383612a2a565b61216f600082611f17565b6001600160a01b0383166000908152600960205260408120805460019290612198908490613d09565b90915550506001600160a01b03821660009081526009602052604081208054600192906121c6908490613cf1565b909155505060008181526008602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6019546000906001600160a01b031633141561225957816003015482600201541061225457506000919050565b61227f565b8160030154826007015483600201546122729190613cf1565b1061227f57506000919050565b33301480159061229a57506019546001600160a01b03163314155b80156122ac57506122aa33611b3e565b155b156122b957506000919050565b506008015460ff1690565b6122ef6040518060800160405280600081526020016060815260200160608152602001606081525090565b815460009067ffffffffffffffff81111561230c5761230c61350d565b604051908082528060200260200182016040528015612335578160200160208202803683370190505b50905060005b835481101561242257600084600001828154811061235b5761235b613adf565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090508060000151620186a061239b612ae2565b6123a59190613d36565b10156123f05780602001516123b8612ae2565b6123c29190613d36565b6123cd906001613cf1565b8383815181106123df576123df613adf565b602002602001018181525050612411565b600083838151811061240457612404613adf565b6020026020010181815250505b5061241b81613c90565b905061233b565b50600183015460009067ffffffffffffffff8111156124435761244361350d565b60405190808252806020026020018201604052801561246c578160200160208202803683370190505b50600185015490915060009067ffffffffffffffff8111156124905761249061350d565b6040519080825280602002602001820160405280156124b9578160200160208202803683370190505b50905060005b600186015481101561257c578560010181815481106124e0576124e0613adf565b9060005260206000200154620186a06124f7612ae2565b6125019190613d36565b1083828151811061251457612514613adf565b60200260200101901515908115158152505082818151811061253857612538613adf565b60200260200101511561256c5761254d612b4b565b82828151811061255f5761255f613adf565b6020026020010181815250505b61257581613c90565b90506124bf565b506040805160808101825287815260208101859052908101839052606081018290526002860180549060006125b083613c90565b9091555090979650505050505050565b6001600160a01b0382166126165760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a6d565b6000818152600860205260409020546001600160a01b03161561267b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a6d565b61268760008383612a2a565b6001600160a01b03821660009081526009602052604081208054600192906126b0908490613cf1565b909155505060008181526008602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818152601460209081526040808320815181546101009481028201850190935260e08101838152859491938492849190879085015b8282101561278b57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612745565b505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156127e257602002820191906000526020600020905b8154815260200190600101908083116127ce575b5050505050815260200160028201548152602001600382015481526020016004820160405180606001604052908160008201548152602001600182015481526020016002820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090508060800151604001516000141561287457608001515192915050565b806080015160400151600114156128cd57600061289982604001518360600151612bac565b608083015180516020909101519192506128bd9183916128b891613d09565b612a1e565b6080830151516120749190613cf1565b608001515192915050565b50919050565b6128e984848461207c565b6128f584848484612bc1565b6112895760405162461bcd60e51b8152600401610a6d90613d4a565b606060128054610b2090613a59565b6060816129445750506040805180820190915260018152600360fc1b602082015290565b8160005b811561296e578061295881613c90565b91506129679050600a83613d9c565b9150612948565b60008167ffffffffffffffff8111156129895761298961350d565b6040519080825280601f01601f1916602001820160405280156129b3576020820181803683370190505b5090505b8415612074576129c8600183613d09565b91506129d5600a86613d36565b6129e0906030613cf1565b60f81b8183815181106129f5576129f5613adf565b60200101906001600160f81b031916908160001a905350612a17600a86613d9c565b94506129b7565b60006118688383612cce565b6001600160a01b038316612a8557612a8081600e80546000838152600f60205260408120829055600182018355919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0155565b612aa8565b816001600160a01b0316836001600160a01b031614612aa857612aa88382612d90565b6001600160a01b038216612abf57610d4981612e2d565b826001600160a01b0316826001600160a01b031614610d4957610d498282612edc565b6016546040516bffffffffffffffffffffffff193360601b1660208201526034810191909152426054820152600090819060740160408051601f198184030181529190528051602090910120601680549192506000612b4083613c90565b909155509092915050565b600080610100612b59612ae2565b612b639190613d36565b90506000610100612b72612ae2565b612b7c9190613d36565b90506000610100612b8b612ae2565b612b959190613d36565b9050601083901b600883901b821717935050505090565b600061186883670de0b6b3a764000084612f20565b60006001600160a01b0384163b15612cc357604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612c05903390899088908890600401613db0565b602060405180830381600087803b158015612c1f57600080fd5b505af1925050508015612c4f575060408051601f3d908101601f19168201909252612c4c91810190613ded565b60015b612ca9573d808015612c7d576040519150601f19603f3d011682016040523d82523d6000602084013e612c82565b606091505b508051612ca15760405162461bcd60e51b8152600401610a6d90613d4a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612074565b506001949350505050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110612d125760405163698d9a0160e11b815260048101829052602401610a6d565b600080670de0b6b3a76400008688099150506706f05b59d3b1ffff811182612d4c5780670de0b6b3a7640000850401945050505050610b0b565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b60006001612d9d84611194565b612da79190613d09565b6000838152600d6020526040902054909150808214612dfa576001600160a01b0384166000908152600c602090815260408083208584528252808320548484528184208190558352600d90915290208190555b506000918252600d602090815260408084208490556001600160a01b039094168352600c81528383209183525290812055565b600e54600090612e3f90600190613d09565b6000838152600f6020526040812054600e8054939450909284908110612e6757612e67613adf565b9060005260206000200154905080600e8381548110612e8857612e88613adf565b6000918252602080832090910192909255828152600f9091526040808220849055858252812055600e805480612ec057612ec0613e0a565b6001900381819060005260206000200160009055905550505050565b6000612ee783611194565b6001600160a01b039093166000908152600c602090815260408083208684528252808320859055938252600d9052919091209190915550565b600080806000198587098587029250828110838203039150508060001415612f5b57838281612f5157612f51613d20565b0492505050611868565b838110612f8557604051631dcf306360e21b81526004810182905260248101859052604401610a6d565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b828054612ff990613a59565b90600052602060002090601f01602090048101928261301b5760008555613061565b82601f106130345782800160ff19823516178555613061565b82800160010185558215613061579182015b82811115613061578235825591602001919060010190613046565b5061306d929150613148565b5090565b828054828255906000526020600020908101928215613061579160200282015b82811115613061578251825591602001919060010190613091565b82805482825590600052602060002090601f016020900481019282156130615791602002820160005b8382111561311257835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026130d5565b801561313f5782816101000a81549060ff0219169055600101602081600001049283019260010302613112565b505061306d9291505b5b8082111561306d5760008155600101613149565b6000806040838503121561317057600080fd5b82359150602083013567ffffffffffffffff81111561318e57600080fd5b8301608081860312156131a057600080fd5b809150509250929050565b6001600160e01b0319811681146131c157600080fd5b50565b6000602082840312156131d657600080fd5b8135611868816131ab565b60005b838110156131fc5781810151838201526020016131e4565b838111156112895750506000910152565b600081518084526132258160208601602086016131e1565b601f01601f19169290920160200192915050565b602081526000611868602083018461320d565b60006020828403121561325e57600080fd5b5035919050565b80356001600160a01b038116811461327c57600080fd5b919050565b6000806040838503121561329457600080fd5b61329d83613265565b946020939093013593505050565b6000602082840312156132bd57600080fd5b61186882613265565b6000806000606084860312156132db57600080fd5b6132e484613265565b92506132f260208501613265565b9150604084013590509250925092565b6000806020838503121561331557600080fd5b823567ffffffffffffffff8082111561332d57600080fd5b818501915085601f83011261334157600080fd5b81358181111561335057600080fd5b86602082850101111561336257600080fd5b60209290920196919550909350505050565b80151581146131c157600080fd5b6000806040838503121561339557600080fd5b8235915060208301356131a081613374565b8581526020810185905260e081016133d660408301868051825260208082015190830152604090810151910152565b8360a083015282151560c08301529695505050505050565b600061012082840312156128d857600080fd5b6000806040838503121561341457600080fd5b82359150602083013567ffffffffffffffff81111561343257600080fd5b61343e858286016133ee565b9150509250929050565b6000806040838503121561345b57600080fd5b8235915061346b60208401613265565b90509250929050565b6000806040838503121561348757600080fd5b61349083613265565b915060208301356131a081613374565b60008082840360808112156134b457600080fd5b833592506060601f19820112156134ca57600080fd5b506020830190509250929050565b6000602082840312156134ea57600080fd5b813567ffffffffffffffff81111561350157600080fd5b612074848285016133ee565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561353957600080fd5b61354285613265565b935061355060208601613265565b925060408501359150606085013567ffffffffffffffff8082111561357457600080fd5b818701915087601f83011261358857600080fd5b81358181111561359a5761359a61350d565b604051601f8201601f19908116603f011681019083821181831017156135c2576135c261350d565b816040528281528a60208487010111156135db57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600081518084526020808501945080840160005b8381101561362f57815187529582019590820190600101613613565b509495945050505050565b60208152600061186860208301846135ff565b6000806040838503121561366057600080fd5b50508035926020909101359150565b81518152602080830151908201526040808301519082015260608101610b0b565b600080604083850312156136a357600080fd5b6136ac83613265565b915061346b60208401613265565b6000602080835283518184015280840151608060408501526136df60a08501826135ff565b6040860151601f1986830381016060880152815180845291850193506000929091908501905b8084101561372757845115158252938501936001939093019290850190613705565b50606088015194508187820301608088015261374381866135ff565b98975050505050505050565b60208082526022908201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f604082015261371760f11b606082015260800190565b60208082526014908201527318d85c9cc818da185b99d95cc8189b1bd8dad95960621b604082015260600190565b6000808335601e198436030181126137d657600080fd5b83018035915067ffffffffffffffff8211156137f157600080fd5b6020019150600581901b360382131561380957600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561384057613840613810565b500290565b5b818110156119e85760008155600101613846565b600160401b83111561386e5761386e61350d565b80548382558084101561389457816000526020600020613892828201868301613845565b505b50818160005260208060002060005b868110156138bf578335825592820192600191820191016138a3565b50505050505050565b60008135610b0b81613374565b600160401b8311156138e9576138e961350d565b80548382558084101561393f57816000526020600020601f850160051c8101601f86168015613929576000198083018054828460200360031b1c16815550505b5061393c601f840160051c830182613845565b50505b506000818152602081208391805b868110156138bf5761397d613961856138c8565b845460ff600386901b90811b8019909216921515901b16178455565b60208401935060018083019250601f83111561399c5792830192600092505b5060010161394d565b81358155600180820160206139bc818601866137bf565b600160401b8111156139d0576139d061350d565b8354818555808210156139f55784600052836000206139f3828201848301613845565b505b506000938452828420935b81811015613a1b578235855593850193918301918501613a00565b505050505050613a2e60408301836137bf565b613a3c8183600286016138d5565b5050613a4b60608301836137bf565b61128981836003860161385a565b600181811c90821680613a6d57607f821691505b602082108114156128d857634e487b7160e01b600052602260045260246000fd5b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600160401b831115613b0957613b0961350d565b805483825580841015613b7b576001600160ff1b036001818311811615613b3257613b32613810565b818611811615613b4457613b44613810565b60008481526020812090925086821b81019084831b015b80821015613b76578382558383830155600282019150613b5b565b505050505b5060008181526020812083915b85811015613bb45782358255602083013560018301556040929092019160029190910190600101613b88565b505050505050565b8135601e19833603018112613bd057600080fd5b8201803567ffffffffffffffff811115613be957600080fd5b6020820191508060061b3603821315613c0157600080fd5b613c0c818385613af5565b5050613c1b60208301836137bf565b613c2981836001860161385a565b505060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c0820135600682015560e082013560078201556119e8613c7761010084016138c8565b6008830160ff1981541660ff8315151681178255505050565b6000600019821415613ca457613ca4613810565b5060010190565b600081613cba57613cba613810565b506000190190565b60008351613cd48184602088016131e1565b835190830190613ce88183602088016131e1565b01949350505050565b60008219821115613d0457613d04613810565b500190565b600082821015613d1b57613d1b613810565b500390565b634e487b7160e01b600052601260045260246000fd5b600082613d4557613d45613d20565b500690565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082613dab57613dab613d20565b500490565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613de39083018461320d565b9695505050505050565b600060208284031215613dff57600080fd5b8151611868816131ab565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220a6ec59f0b4532043f867b838fa0a0b7ded9a917f9c5cff484d9f7962d713bb9364736f6c6343000809003368747470733a2f2f6d7573696372616365726e66742e6f72672f6170692f676c6f62616c6d65746168747470733a2f2f6d7573696372616365726e66742e6f72672f6170692f636172736d6574612f

Deployed Bytecode

0x6080604052600436106102e45760003560e01c806394bf804d11610190578063ce1f40a1116100dc578063e3bb4dc611610095578063f2b84c4f1161006f578063f2b84c4f146109d7578063fb1c9e6f14610a09578063ff4ccd3514610a1e578063ffcc43c414610a3357600080fd5b8063e3bb4dc614610941578063e985e9c514610961578063eeb36ee4146109aa57600080fd5b8063ce1f40a11461086e578063d89fd2a414610881578063d917deb5146108b1578063db0e0e85146108b9578063dd0860a8146108e6578063e160ddb91461090657600080fd5b8063b8728cb911610149578063c81312c011610123578063c81312c0146107cd578063c83dd23114610818578063c87b56dd14610838578063cb24bc791461085857600080fd5b8063b8728cb914610760578063b88d4fde14610780578063c702c094146107a057600080fd5b806394bf804d1461069e57806395d89b41146106be5780639edc654b146106d3578063a22cb46514610700578063a62141b814610720578063aa6049eb1461074057600080fd5b806332b3c39c1161024f5780635dd871a31161020857806370a08231116101e257806370a082311461061357806375a5316f1461063357806382a0976d146106605780638da5cb5b1461068057600080fd5b80635dd871a3146105be5780636352211e146105de5780636c8db545146105fe57600080fd5b806332b3c39c1461049957806335265716146104b9578063399e28831461053e57806342842e0e1461055e5780634f6ccce71461057e5780635ca9f7501461059e57600080fd5b8063167d3e9c116102a1578063167d3e9c146103da57806318160ddd146103fa5780631c893ef91461041957806323b872dd1461043957806323c8c948146104595780632f745c591461047957600080fd5b80630148541f146102e957806301ffc9a71461030b57806306fdde0314610340578063081812fc14610362578063095ea7b31461039a5780631536ed8b146103ba575b600080fd5b3480156102f557600080fd5b5061030961030436600461315d565b610a48565b005b34801561031757600080fd5b5061032b6103263660046131c4565b610ae6565b60405190151581526020015b60405180910390f35b34801561034c57600080fd5b50610355610b11565b6040516103379190613239565b34801561036e57600080fd5b5061038261037d36600461324c565b610ba3565b6040516001600160a01b039091168152602001610337565b3480156103a657600080fd5b506103096103b5366004613281565b610c38565b3480156103c657600080fd5b506103826103d536600461324c565b610d4e565b3480156103e657600080fd5b506103096103f53660046132ab565b610da2565b34801561040657600080fd5b50600e545b604051908152602001610337565b34801561042557600080fd5b506103096104343660046132ab565b610de9565b34801561044557600080fd5b506103096104543660046132c6565b610e30565b34801561046557600080fd5b50610309610474366004613302565b610e61565b34801561048557600080fd5b5061040b610494366004613281565b610e92565b3480156104a557600080fd5b506103096104b4366004613382565b610f28565b3480156104c557600080fd5b5061052d6104d436600461324c565b601460209081526000918252604091829020600281015460038201548451606081018652600484015481526005840154948101949094526006830154948401949094526007820154600890920154909392919060ff1685565b6040516103379594939291906133a7565b34801561054a57600080fd5b5061030961055936600461324c565b610f70565b34801561056a57600080fd5b506103096105793660046132c6565b610fb0565b34801561058a57600080fd5b5061040b61059936600461324c565b610fcb565b3480156105aa57600080fd5b506103096105b9366004613302565b61105e565b3480156105ca57600080fd5b5061032b6105d936600461324c565b61108f565b3480156105ea57600080fd5b506103826105f936600461324c565b6110a6565b34801561060a57600080fd5b5061030961111d565b34801561061f57600080fd5b5061040b61062e3660046132ab565b611194565b34801561063f57600080fd5b5061040b61064e36600461324c565b60176020526000908152604090205481565b34801561066c57600080fd5b5061030961067b366004613401565b61121b565b34801561068c57600080fd5b506010546001600160a01b0316610382565b3480156106aa57600080fd5b506103096106b9366004613448565b61128f565b3480156106ca57600080fd5b506103556113aa565b3480156106df57600080fd5b5061040b6106ee36600461324c565b60009081526014602052604090205490565b34801561070c57600080fd5b5061030961071b366004613474565b6113b9565b34801561072c57600080fd5b5061030961073b3660046134a0565b61147e565b34801561074c57600080fd5b5061040b61075b36600461324c565b611550565b34801561076c57600080fd5b5061030961077b3660046134d8565b611568565b34801561078c57600080fd5b5061030961079b366004613523565b611641565b3480156107ac57600080fd5b506107c06107bb3660046132ab565b611673565b604051610337919061363a565b3480156107d957600080fd5b506107ed6107e836600461364d565b611713565b60408051941515855260ff938416602086015291831691840191909152166060820152608001610337565b34801561082457600080fd5b50601954610382906001600160a01b031681565b34801561084457600080fd5b5061035561085336600461324c565b611794565b34801561086457600080fd5b5061040b60155481565b61030961087c36600461324c565b61186f565b34801561088d57600080fd5b5061032b61089c36600461324c565b601a6020526000908152604090205460ff1681565b61030961191a565b3480156108c557600080fd5b506108d96108d436600461324c565b611ade565b604051610337919061366f565b3480156108f257600080fd5b5061032b6109013660046132ab565b611b3e565b34801561091257600080fd5b5061092661092136600461364d565b611b83565b60408051825181526020928301519281019290925201610337565b34801561094d57600080fd5b5061030961095c3660046132ab565b611bec565b34801561096d57600080fd5b5061032b61097c366004613690565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205460ff1690565b3480156109b657600080fd5b506109ca6109c536600461324c565b611c52565b60405161033791906136ba565b3480156109e357600080fd5b506109f76109f23660046132ab565b611dc9565b60405160ff9091168152602001610337565b348015610a1557600080fd5b5061040b600381565b348015610a2a57600080fd5b50610355611e2c565b348015610a3f57600080fd5b50610355611eba565b610a5133611b3e565b610a765760405162461bcd60e51b8152600401610a6d9061374f565b60405180910390fd5b600082815260176020908152604080832054808452601a9092529091205460ff1615610ab45760405162461bcd60e51b8152600401610a6d90613791565b60008381526017602052604090208290610ace82826139a5565b50506000928352601760205260409092209190915550565b60006001600160e01b0319821663780e9d6360e01b1480610b0b5750610b0b82611ec7565b92915050565b606060068054610b2090613a59565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4c90613a59565b8015610b995780601f10610b6e57610100808354040283529160200191610b99565b820191906000526020600020905b815481529060010190602001808311610b7c57829003601f168201915b5050505050905090565b6000818152600860205260408120546001600160a01b0316610c1c5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a6d565b506000908152600a60205260409020546001600160a01b031690565b6000610c43826110a6565b9050806001600160a01b0316836001600160a01b03161415610cb15760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a6d565b336001600160a01b0382161480610ccd5750610ccd813361097c565b610d3f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a6d565b610d498383611f17565b505050565b600081610d665750506000546001600160a01b031690565b8160011415610d805750506001546001600160a01b031690565b8160021415610d9a5750506002546001600160a01b031690565b506000919050565b610dab33611b3e565b610dc75760405162461bcd60e51b8152600401610a6d9061374f565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b610df233611b3e565b610e0e5760405162461bcd60e51b8152600401610a6d9061374f565b601980546001600160a01b0319166001600160a01b0392909216919091179055565b610e3a3382611f85565b610e565760405162461bcd60e51b8152600401610a6d90613a8e565b610d4983838361207c565b610e6a33611b3e565b610e865760405162461bcd60e51b8152600401610a6d9061374f565b610d4960128383612fed565b6000610e9d83611194565b8210610eff5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610a6d565b506001600160a01b03919091166000908152600c60209081526040808320938352929052205490565b610f3133611b3e565b610f4d5760405162461bcd60e51b8152600401610a6d9061374f565b600091825260146020526040909120600801805460ff1916911515919091179055565b610f7933611b3e565b610f955760405162461bcd60e51b8152600401610a6d9061374f565b6000908152601a60205260409020805460ff19166001179055565b610d4983838360405180602001604052806000815250611641565b6000610fd6600e5490565b82106110395760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610a6d565b600e828154811061104c5761104c613adf565b90600052602060002001549050919050565b61106733611b3e565b6110835760405162461bcd60e51b8152600401610a6d9061374f565b610d4960118383612fed565b6000818152601460205260408120610b0b90612227565b6000818152600860205260408120546001600160a01b031680610b0b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a6d565b6003546001600160a01b031633141561114457600080546001600160a01b03191633179055565b6004546001600160a01b031633141561116b57600180546001600160a01b03191633179055565b6005546001600160a01b031633141561119257600280546001600160a01b03191633179055565b565b60006001600160a01b0382166111ff5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a6d565b506001600160a01b031660009081526009602052604090205490565b61122433611b3e565b6112405760405162461bcd60e51b8152600401610a6d9061374f565b6000828152601a602052604090205460ff161561126f5760405162461bcd60e51b8152600401610a6d90613791565b600082815260146020526040902081906112898282613bbc565b50505050565b60008281526014602052604090206112a681612227565b6112e45760405162461bcd60e51b815260206004820152600f60248201526e31b0b73737ba1036b4b73a1031b0b960891b6044820152606401610a6d565b6112ee83826122c4565b601854600090815260176020908152604090912082518155828201518051919261132092600185019290910190613071565b506040820151805161133c9160028401916020909101906130ac565b5060608201518051611358916003840191602090910190613071565b50905050611368826018546125c0565b6018805490600061137883613c90565b90915550506019546001600160a01b0316331415610d495780600701600081546113a190613cab565b90915550505050565b606060078054610b2090613a59565b6001600160a01b0382163314156114125760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a6d565b336000818152600b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61148733611b3e565b6114a35760405162461bcd60e51b8152600401610a6d9061374f565b6000828152601a602052604090205460ff16156114d25760405162461bcd60e51b8152600401610a6d90613791565b60208101358135111561151c5760405162461bcd60e51b81526020600482015260126024820152711c1c9a58d9481a5cc81a5b98dbdc9c9958dd60721b6044820152606401610a6d565b6000828152601460205260409020819060040161128982828135815560208201356001820155604082013560028201555050565b600060135461155e8361270e565b610b0b9190613826565b61157133611b3e565b61158d5760405162461bcd60e51b8152600401610a6d9061374f565b60a0810135608082013511156115de5760405162461bcd60e51b815260206004820152601660248201527518d85c881c1c9a58d9481a5cc81a5b98dbdc9c9958dd60521b6044820152606401610a6d565b601580549060006115ee83613c90565b9091555050601554600090815260146020526040902081906116108282613bbc565b50506015546040517f097a2f6c6a41ed0979fb29808bc5ff14ed8e2acb53f623525175eedfdaab1d4e90600090a250565b61164b3383611f85565b6116675760405162461bcd60e51b8152600401610a6d90613a8e565b611289848484846128de565b6060600061168083611194565b905060008167ffffffffffffffff81111561169d5761169d61350d565b6040519080825280602002602001820160405280156116c6578160200160208202803683370190505b50905060005b8281101561170b576116de8582610e92565b8282815181106116f0576116f0613adf565b602090810291909101015261170481613c90565b90506116cc565b509392505050565b600080600080600061172487611c52565b905060008160600151878151811061173e5761173e613adf565b602090810291909101015160408301518051601083901c935060ff8084169360081c811692908516918b90811061177757611777613adf565b60209081029190910101519b909a50909850909650945050505050565b6000818152600860205260409020546060906001600160a01b03166118135760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610a6d565b600061181d612911565b9050600081511161183d5760405180602001604052806000815250611868565b8061184784612920565b604051602001611858929190613cc2565b6040516020818303038152906040525b9392505050565b61187881611550565b3410156118b85760405162461bcd60e51b815260206004820152600e60248201526d0dcdee840cadcdeeaced040cae8d60931b6044820152606401610a6d565b6118c061191a565b6040516394bf804d60e01b81526004810182905233602482015230906394bf804d90604401600060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b5050505050565b60008061192f6705e5e73f8d8a800034612a1e565b600080546040519293506001600160a01b03169183156108fc0291849190818181858888f1935050505015801561196a573d6000803e3d6000fd5b506119758183613cf1565b91506119896705e5e73f8d8a800034612a1e565b9050346119968284613cf1565b11156119ec576119a68234613d09565b905080156119e8576001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b5050565b6001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015611a26573d6000803e3d6000fd5b50611a318183613cf1565b9150611a45670214e8348c4f000034612a1e565b905034611a528284613cf1565b1115611aa457611a628234613d09565b905080156119e8576002546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b6002546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610d49573d6000803e3d6000fd5b611b0260405180606001604052806000815260200160008152602001600081525090565b50600090815260146020908152604091829020825160608101845260048201548152600582015492810192909252600601549181019190915290565b600080546001600160a01b0383811691161480611b6857506001546001600160a01b038381169116145b80610b0b5750506002546001600160a01b0390811691161490565b60408051808201909152600080825260208201526000838152601460205260409020805483908110611bb757611bb7613adf565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050905092915050565b611bf533611b3e565b611c115760405162461bcd60e51b8152600401610a6d9061374f565b806003611c1d33611dc9565b60ff1660038110611c3057611c30613adf565b0180546001600160a01b0319166001600160a01b039290921691909117905550565b611c7d6040518060800160405280600081526020016060815260200160608152602001606081525090565b60008281526017602090815260409182902082516080810184528154815260018201805485518186028101860190965280865291949293858101939290830182828015611ce957602002820191906000526020600020905b815481526020019060010190808311611cd5575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611d6157602002820191906000526020600020906000905b825461010083900a900460ff161515815260206001928301818104948501949093039092029101808411611d305790505b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015611db957602002820191906000526020600020905b815481526020019060010190808311611da5575b5050505050815250509050919050565b600080546001600160a01b0383811691161415611de857506000919050565b6001546001600160a01b0383811691161415611e0657506001919050565b6002546001600160a01b0383811691161415611e2457506002919050565b506004919050565b60118054611e3990613a59565b80601f0160208091040260200160405190810160405280929190818152602001828054611e6590613a59565b8015611eb25780601f10611e8757610100808354040283529160200191611eb2565b820191906000526020600020905b815481529060010190602001808311611e9557829003601f168201915b505050505081565b60128054611e3990613a59565b60006001600160e01b031982166380ac58cd60e01b1480611ef857506001600160e01b03198216635b5e139f60e01b145b80610b0b57506301ffc9a760e01b6001600160e01b0319831614610b0b565b6000818152600a6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611f4c826110a6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600860205260408120546001600160a01b0316611ffe5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a6d565b6000612009836110a6565b9050806001600160a01b0316846001600160a01b031614806120445750836001600160a01b031661203984610ba3565b6001600160a01b0316145b8061207457506001600160a01b038082166000908152600b602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661208f826110a6565b6001600160a01b0316146120f75760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610a6d565b6001600160a01b0382166121595760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a6d565b612164838383612a2a565b61216f600082611f17565b6001600160a01b0383166000908152600960205260408120805460019290612198908490613d09565b90915550506001600160a01b03821660009081526009602052604081208054600192906121c6908490613cf1565b909155505060008181526008602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6019546000906001600160a01b031633141561225957816003015482600201541061225457506000919050565b61227f565b8160030154826007015483600201546122729190613cf1565b1061227f57506000919050565b33301480159061229a57506019546001600160a01b03163314155b80156122ac57506122aa33611b3e565b155b156122b957506000919050565b506008015460ff1690565b6122ef6040518060800160405280600081526020016060815260200160608152602001606081525090565b815460009067ffffffffffffffff81111561230c5761230c61350d565b604051908082528060200260200182016040528015612335578160200160208202803683370190505b50905060005b835481101561242257600084600001828154811061235b5761235b613adf565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505090508060000151620186a061239b612ae2565b6123a59190613d36565b10156123f05780602001516123b8612ae2565b6123c29190613d36565b6123cd906001613cf1565b8383815181106123df576123df613adf565b602002602001018181525050612411565b600083838151811061240457612404613adf565b6020026020010181815250505b5061241b81613c90565b905061233b565b50600183015460009067ffffffffffffffff8111156124435761244361350d565b60405190808252806020026020018201604052801561246c578160200160208202803683370190505b50600185015490915060009067ffffffffffffffff8111156124905761249061350d565b6040519080825280602002602001820160405280156124b9578160200160208202803683370190505b50905060005b600186015481101561257c578560010181815481106124e0576124e0613adf565b9060005260206000200154620186a06124f7612ae2565b6125019190613d36565b1083828151811061251457612514613adf565b60200260200101901515908115158152505082818151811061253857612538613adf565b60200260200101511561256c5761254d612b4b565b82828151811061255f5761255f613adf565b6020026020010181815250505b61257581613c90565b90506124bf565b506040805160808101825287815260208101859052908101839052606081018290526002860180549060006125b083613c90565b9091555090979650505050505050565b6001600160a01b0382166126165760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a6d565b6000818152600860205260409020546001600160a01b03161561267b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a6d565b61268760008383612a2a565b6001600160a01b03821660009081526009602052604081208054600192906126b0908490613cf1565b909155505060008181526008602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818152601460209081526040808320815181546101009481028201850190935260e08101838152859491938492849190879085015b8282101561278b57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190612745565b505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156127e257602002820191906000526020600020905b8154815260200190600101908083116127ce575b5050505050815260200160028201548152602001600382015481526020016004820160405180606001604052908160008201548152602001600182015481526020016002820154815250508152602001600782015481526020016008820160009054906101000a900460ff16151515158152505090508060800151604001516000141561287457608001515192915050565b806080015160400151600114156128cd57600061289982604001518360600151612bac565b608083015180516020909101519192506128bd9183916128b891613d09565b612a1e565b6080830151516120749190613cf1565b608001515192915050565b50919050565b6128e984848461207c565b6128f584848484612bc1565b6112895760405162461bcd60e51b8152600401610a6d90613d4a565b606060128054610b2090613a59565b6060816129445750506040805180820190915260018152600360fc1b602082015290565b8160005b811561296e578061295881613c90565b91506129679050600a83613d9c565b9150612948565b60008167ffffffffffffffff8111156129895761298961350d565b6040519080825280601f01601f1916602001820160405280156129b3576020820181803683370190505b5090505b8415612074576129c8600183613d09565b91506129d5600a86613d36565b6129e0906030613cf1565b60f81b8183815181106129f5576129f5613adf565b60200101906001600160f81b031916908160001a905350612a17600a86613d9c565b94506129b7565b60006118688383612cce565b6001600160a01b038316612a8557612a8081600e80546000838152600f60205260408120829055600182018355919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0155565b612aa8565b816001600160a01b0316836001600160a01b031614612aa857612aa88382612d90565b6001600160a01b038216612abf57610d4981612e2d565b826001600160a01b0316826001600160a01b031614610d4957610d498282612edc565b6016546040516bffffffffffffffffffffffff193360601b1660208201526034810191909152426054820152600090819060740160408051601f198184030181529190528051602090910120601680549192506000612b4083613c90565b909155509092915050565b600080610100612b59612ae2565b612b639190613d36565b90506000610100612b72612ae2565b612b7c9190613d36565b90506000610100612b8b612ae2565b612b959190613d36565b9050601083901b600883901b821717935050505090565b600061186883670de0b6b3a764000084612f20565b60006001600160a01b0384163b15612cc357604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612c05903390899088908890600401613db0565b602060405180830381600087803b158015612c1f57600080fd5b505af1925050508015612c4f575060408051601f3d908101601f19168201909252612c4c91810190613ded565b60015b612ca9573d808015612c7d576040519150601f19603f3d011682016040523d82523d6000602084013e612c82565b606091505b508051612ca15760405162461bcd60e51b8152600401610a6d90613d4a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612074565b506001949350505050565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110612d125760405163698d9a0160e11b815260048101829052602401610a6d565b600080670de0b6b3a76400008688099150506706f05b59d3b1ffff811182612d4c5780670de0b6b3a7640000850401945050505050610b0b565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b60006001612d9d84611194565b612da79190613d09565b6000838152600d6020526040902054909150808214612dfa576001600160a01b0384166000908152600c602090815260408083208584528252808320548484528184208190558352600d90915290208190555b506000918252600d602090815260408084208490556001600160a01b039094168352600c81528383209183525290812055565b600e54600090612e3f90600190613d09565b6000838152600f6020526040812054600e8054939450909284908110612e6757612e67613adf565b9060005260206000200154905080600e8381548110612e8857612e88613adf565b6000918252602080832090910192909255828152600f9091526040808220849055858252812055600e805480612ec057612ec0613e0a565b6001900381819060005260206000200160009055905550505050565b6000612ee783611194565b6001600160a01b039093166000908152600c602090815260408083208684528252808320859055938252600d9052919091209190915550565b600080806000198587098587029250828110838203039150508060001415612f5b57838281612f5157612f51613d20565b0492505050611868565b838110612f8557604051631dcf306360e21b81526004810182905260248101859052604401610a6d565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b828054612ff990613a59565b90600052602060002090601f01602090048101928261301b5760008555613061565b82601f106130345782800160ff19823516178555613061565b82800160010185558215613061579182015b82811115613061578235825591602001919060010190613046565b5061306d929150613148565b5090565b828054828255906000526020600020908101928215613061579160200282015b82811115613061578251825591602001919060010190613091565b82805482825590600052602060002090601f016020900481019282156130615791602002820160005b8382111561311257835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026130d5565b801561313f5782816101000a81549060ff0219169055600101602081600001049283019260010302613112565b505061306d9291505b5b8082111561306d5760008155600101613149565b6000806040838503121561317057600080fd5b82359150602083013567ffffffffffffffff81111561318e57600080fd5b8301608081860312156131a057600080fd5b809150509250929050565b6001600160e01b0319811681146131c157600080fd5b50565b6000602082840312156131d657600080fd5b8135611868816131ab565b60005b838110156131fc5781810151838201526020016131e4565b838111156112895750506000910152565b600081518084526132258160208601602086016131e1565b601f01601f19169290920160200192915050565b602081526000611868602083018461320d565b60006020828403121561325e57600080fd5b5035919050565b80356001600160a01b038116811461327c57600080fd5b919050565b6000806040838503121561329457600080fd5b61329d83613265565b946020939093013593505050565b6000602082840312156132bd57600080fd5b61186882613265565b6000806000606084860312156132db57600080fd5b6132e484613265565b92506132f260208501613265565b9150604084013590509250925092565b6000806020838503121561331557600080fd5b823567ffffffffffffffff8082111561332d57600080fd5b818501915085601f83011261334157600080fd5b81358181111561335057600080fd5b86602082850101111561336257600080fd5b60209290920196919550909350505050565b80151581146131c157600080fd5b6000806040838503121561339557600080fd5b8235915060208301356131a081613374565b8581526020810185905260e081016133d660408301868051825260208082015190830152604090810151910152565b8360a083015282151560c08301529695505050505050565b600061012082840312156128d857600080fd5b6000806040838503121561341457600080fd5b82359150602083013567ffffffffffffffff81111561343257600080fd5b61343e858286016133ee565b9150509250929050565b6000806040838503121561345b57600080fd5b8235915061346b60208401613265565b90509250929050565b6000806040838503121561348757600080fd5b61349083613265565b915060208301356131a081613374565b60008082840360808112156134b457600080fd5b833592506060601f19820112156134ca57600080fd5b506020830190509250929050565b6000602082840312156134ea57600080fd5b813567ffffffffffffffff81111561350157600080fd5b612074848285016133ee565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561353957600080fd5b61354285613265565b935061355060208601613265565b925060408501359150606085013567ffffffffffffffff8082111561357457600080fd5b818701915087601f83011261358857600080fd5b81358181111561359a5761359a61350d565b604051601f8201601f19908116603f011681019083821181831017156135c2576135c261350d565b816040528281528a60208487010111156135db57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600081518084526020808501945080840160005b8381101561362f57815187529582019590820190600101613613565b509495945050505050565b60208152600061186860208301846135ff565b6000806040838503121561366057600080fd5b50508035926020909101359150565b81518152602080830151908201526040808301519082015260608101610b0b565b600080604083850312156136a357600080fd5b6136ac83613265565b915061346b60208401613265565b6000602080835283518184015280840151608060408501526136df60a08501826135ff565b6040860151601f1986830381016060880152815180845291850193506000929091908501905b8084101561372757845115158252938501936001939093019290850190613705565b50606088015194508187820301608088015261374381866135ff565b98975050505050505050565b60208082526022908201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f604082015261371760f11b606082015260800190565b60208082526014908201527318d85c9cc818da185b99d95cc8189b1bd8dad95960621b604082015260600190565b6000808335601e198436030181126137d657600080fd5b83018035915067ffffffffffffffff8211156137f157600080fd5b6020019150600581901b360382131561380957600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561384057613840613810565b500290565b5b818110156119e85760008155600101613846565b600160401b83111561386e5761386e61350d565b80548382558084101561389457816000526020600020613892828201868301613845565b505b50818160005260208060002060005b868110156138bf578335825592820192600191820191016138a3565b50505050505050565b60008135610b0b81613374565b600160401b8311156138e9576138e961350d565b80548382558084101561393f57816000526020600020601f850160051c8101601f86168015613929576000198083018054828460200360031b1c16815550505b5061393c601f840160051c830182613845565b50505b506000818152602081208391805b868110156138bf5761397d613961856138c8565b845460ff600386901b90811b8019909216921515901b16178455565b60208401935060018083019250601f83111561399c5792830192600092505b5060010161394d565b81358155600180820160206139bc818601866137bf565b600160401b8111156139d0576139d061350d565b8354818555808210156139f55784600052836000206139f3828201848301613845565b505b506000938452828420935b81811015613a1b578235855593850193918301918501613a00565b505050505050613a2e60408301836137bf565b613a3c8183600286016138d5565b5050613a4b60608301836137bf565b61128981836003860161385a565b600181811c90821680613a6d57607f821691505b602082108114156128d857634e487b7160e01b600052602260045260246000fd5b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600160401b831115613b0957613b0961350d565b805483825580841015613b7b576001600160ff1b036001818311811615613b3257613b32613810565b818611811615613b4457613b44613810565b60008481526020812090925086821b81019084831b015b80821015613b76578382558383830155600282019150613b5b565b505050505b5060008181526020812083915b85811015613bb45782358255602083013560018301556040929092019160029190910190600101613b88565b505050505050565b8135601e19833603018112613bd057600080fd5b8201803567ffffffffffffffff811115613be957600080fd5b6020820191508060061b3603821315613c0157600080fd5b613c0c818385613af5565b5050613c1b60208301836137bf565b613c2981836001860161385a565b505060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c0820135600682015560e082013560078201556119e8613c7761010084016138c8565b6008830160ff1981541660ff8315151681178255505050565b6000600019821415613ca457613ca4613810565b5060010190565b600081613cba57613cba613810565b506000190190565b60008351613cd48184602088016131e1565b835190830190613ce88183602088016131e1565b01949350505050565b60008219821115613d0457613d04613810565b500190565b600082821015613d1b57613d1b613810565b500390565b634e487b7160e01b600052601260045260246000fd5b600082613d4557613d45613d20565b500690565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082613dab57613dab613d20565b500490565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613de39083018461320d565b9695505050505050565b600060208284031215613dff57600080fd5b8151611868816131ab565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220a6ec59f0b4532043f867b838fa0a0b7ded9a917f9c5cff484d9f7962d713bb9364736f6c63430008090033

Deployed Bytecode Sourcemap

106344:5904:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110001:289;;;;;;;;;;-1:-1:-1;110001:289:0;;;;;:::i;:::-;;:::i;:::-;;34724:224;;;;;;;;;;-1:-1:-1;34724:224:0;;;;;:::i;:::-;;:::i;:::-;;;1021:14:1;;1014:22;996:41;;984:2;969:18;34724:224:0;;;;;;;;22616:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;24175:221::-;;;;;;;;;;-1:-1:-1;24175:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2148:32:1;;;2130:51;;2118:2;2103:18;24175:221:0;1984:203:1;23698:411:0;;;;;;;;;;-1:-1:-1;23698:411:0;;;;;:::i;:::-;;:::i;93983:230::-;;;;;;;;;;-1:-1:-1;93983:230:0;;;;;:::i;:::-;;:::i;97200:89::-;;;;;;;;;;-1:-1:-1;97200:89:0;;;;;:::i;:::-;;:::i;35364:113::-;;;;;;;;;;-1:-1:-1;35452:10:0;:17;35364:113;;;2966:25:1;;;2954:2;2939:18;35364:113:0;2820:177:1;108007:96:0;;;;;;;;;;-1:-1:-1;108007:96:0;;;;;:::i;:::-;;:::i;25065:339::-;;;;;;;;;;-1:-1:-1;25065:339:0;;;;;:::i;:::-;;:::i;97736:104::-;;;;;;;;;;-1:-1:-1;97736:104:0;;;;;:::i;:::-;;:::i;35032:256::-;;;;;;;;;;-1:-1:-1;35032:256:0;;;;;:::i;:::-;;:::i;111534:158::-;;;;;;;;;;-1:-1:-1;111534:158:0;;;;;:::i;:::-;;:::i;100746:44::-;;;;;;;;;;-1:-1:-1;100746:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;111190:113::-;;;;;;;;;;-1:-1:-1;111190:113:0;;;;;:::i;:::-;;:::i;25475:185::-;;;;;;;;;;-1:-1:-1;25475:185:0;;;;;:::i;:::-;;:::i;35554:233::-;;;;;;;;;;-1:-1:-1;35554:233:0;;;;;:::i;:::-;;:::i;97562:120::-;;;;;;;;;;-1:-1:-1;97562:120:0;;;;;:::i;:::-;;:::i;108231:128::-;;;;;;;;;;-1:-1:-1;108231:128:0;;;;;:::i;:::-;;:::i;22310:239::-;;;;;;;;;;-1:-1:-1;22310:239:0;;;;;:::i;:::-;;:::i;94905:386::-;;;;;;;;;;;;;:::i;22040:208::-;;;;;;;;;;-1:-1:-1;22040:208:0;;;;;:::i;:::-;;:::i;106388:38::-;;;;;;;;;;-1:-1:-1;106388:38:0;;;;;:::i;:::-;;;;;;;;;;;;;;110414:236;;;;;;;;;;-1:-1:-1;110414:236:0;;;;;:::i;:::-;;:::i;97113:79::-;;;;;;;;;;-1:-1:-1;97178:6:0;;-1:-1:-1;;;;;97178:6:0;97113:79;;109098:377;;;;;;;;;;-1:-1:-1;109098:377:0;;;;;:::i;:::-;;:::i;22785:104::-;;;;;;;;;;;;;:::i;105643:135::-;;;;;;;;;;-1:-1:-1;105643:135:0;;;;;:::i;:::-;105706:7;105733:20;;;:9;:20;;;;;:37;;105643:135;24468:295;;;;;;;;;;-1:-1:-1;24468:295:0;;;;;:::i;:::-;;:::i;110721:318::-;;;;;;;;;;-1:-1:-1;110721:318:0;;;;;:::i;:::-;;:::i;104295:132::-;;;;;;;;;;-1:-1:-1;104295:132:0;;;;;:::i;:::-;;:::i;103851:313::-;;;;;;;;;;-1:-1:-1;103851:313:0;;;;;:::i;:::-;;:::i;25731:328::-;;;;;;;;;;-1:-1:-1;25731:328:0;;;;;:::i;:::-;;:::i;111893:352::-;;;;;;;;;;-1:-1:-1;111893:352:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;107347:578::-;;;;;;;;;;-1:-1:-1;107347:578:0;;;;;:::i;:::-;;:::i;:::-;;;;9480:14:1;;9473:22;9455:41;;9544:4;9532:17;;;9527:2;9512:18;;9505:45;9586:17;;;9566:18;;;9559:45;;;;9640:17;9635:2;9620:18;;9613:45;9442:3;9427:19;107347:578:0;9242:422:1;106541:22:0;;;;;;;;;;-1:-1:-1;106541:22:0;;;;-1:-1:-1;;;;;106541:22:0;;;22960:334;;;;;;;;;;-1:-1:-1;22960:334:0;;;;;:::i;:::-;;:::i;100827:32::-;;;;;;;;;;;;;;;;109658:191;;;;;;:::i;:::-;;:::i;106643:47::-;;;;;;;;;;-1:-1:-1;106643:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;95355:1072;;;:::i;105289:164::-;;;;;;;;;;-1:-1:-1;105289:164:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;93655:149::-;;;;;;;;;;-1:-1:-1;93655:149:0;;;;;:::i;:::-;;:::i;105966:195::-;;;;;;;;;;-1:-1:-1;105966:195:0;;;;;:::i;:::-;;:::i;:::-;;;;10148:13:1;;10130:32;;10218:4;10206:17;;;10200:24;10178:20;;;10171:54;;;;10103:18;105966:195:0;9926:305:1;94656:143:0;;;;;;;;;;-1:-1:-1;94656:143:0;;;;;:::i;:::-;;:::i;24834:164::-;;;;;;;;;;-1:-1:-1;24834:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;24955:25:0;;;24931:4;24955:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;24834:164;107074:108;;;;;;;;;;-1:-1:-1;107074:108:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;94308:264::-;;;;;;;;;;-1:-1:-1;94308:264:0;;;;;:::i;:::-;;:::i;:::-;;;11831:4:1;11819:17;;;11801:36;;11789:2;11774:18;94308:264:0;11659:184:1;92553:40:0;;;;;;;;;;;;92592:1;92553:40;;96732:70;;;;;;;;;;;;;:::i;96840:65::-;;;;;;;;;;;;;:::i;110001:289::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;;;;;;;;;110086:17:::1;110106:16:::0;;;:7:::1;:16;::::0;;;;;;;:23;110149:26;;;:15:::1;:26:::0;;;;;;;::::1;;110148:27;110140:60;;;;-1:-1:-1::0;;;110140:60:0::1;;;;;;;:::i;:::-;110211:16;::::0;;;:7:::1;:16;::::0;;;;110230:6;;110211:25:::1;110230:6:::0;110211:16;:25:::1;:::i;:::-;-1:-1:-1::0;;110247:16:0::1;::::0;;;:7:::1;:16;::::0;;;;;:35;;;;-1:-1:-1;110001:289:0:o;34724:224::-;34826:4;-1:-1:-1;;;;;;34850:50:0;;-1:-1:-1;;;34850:50:0;;:90;;;34904:36;34928:11;34904:23;:36::i;:::-;34843:97;34724:224;-1:-1:-1;;34724:224:0:o;22616:100::-;22670:13;22703:5;22696:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22616:100;:::o;24175:221::-;24251:7;27658:16;;;:7;:16;;;;;;-1:-1:-1;;;;;27658:16:0;24271:73;;;;-1:-1:-1;;;24271:73:0;;18483:2:1;24271:73:0;;;18465:21:1;18522:2;18502:18;;;18495:30;18561:34;18541:18;;;18534:62;-1:-1:-1;;;18612:18:1;;;18605:42;18664:19;;24271:73:0;18281:408:1;24271:73:0;-1:-1:-1;24364:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;24364:24:0;;24175:221::o;23698:411::-;23779:13;23795:23;23810:7;23795:14;:23::i;:::-;23779:39;;23843:5;-1:-1:-1;;;;;23837:11:0;:2;-1:-1:-1;;;;;23837:11:0;;;23829:57;;;;-1:-1:-1;;;23829:57:0;;18896:2:1;23829:57:0;;;18878:21:1;18935:2;18915:18;;;18908:30;18974:34;18954:18;;;18947:62;-1:-1:-1;;;19025:18:1;;;19018:31;19066:19;;23829:57:0;18694:397:1;23829:57:0;2810:10;-1:-1:-1;;;;;23921:21:0;;;;:62;;-1:-1:-1;23946:37:0;23963:5;2810:10;24834:164;:::i;23946:37::-;23899:168;;;;-1:-1:-1;;;23899:168:0;;19298:2:1;23899:168:0;;;19280:21:1;19337:2;19317:18;;;19310:30;19376:34;19356:18;;;19349:62;19447:26;19427:18;;;19420:54;19491:19;;23899:168:0;19096:420:1;23899:168:0;24080:21;24089:2;24093:7;24080:8;:21::i;:::-;23768:341;23698:411;;:::o;93983:230::-;94045:7;94069:10;94065:30;;-1:-1:-1;;94088:7:0;;-1:-1:-1;;;;;94088:7:0;;93983:230::o;94065:30::-;94110:5;94119:1;94110:10;94106:30;;;-1:-1:-1;;94129:7:0;;-1:-1:-1;;;;;94129:7:0;;93983:230::o;94106:30::-;94151:5;94160:1;94151:10;94147:30;;;-1:-1:-1;;94170:7:0;;-1:-1:-1;;;;;94170:7:0;;93983:230::o;94147:30::-;-1:-1:-1;94203:1:0;;93983:230;-1:-1:-1;93983:230:0:o;97200:89::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;97264:6:::1;:17:::0;;-1:-1:-1;;;;;;97264:17:0::1;-1:-1:-1::0;;;;;97264:17:0;;;::::1;::::0;;;::::1;::::0;;97200:89::o;108007:96::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;108075:7:::1;:20:::0;;-1:-1:-1;;;;;;108075:20:0::1;-1:-1:-1::0;;;;;108075:20:0;;;::::1;::::0;;;::::1;::::0;;108007:96::o;25065:339::-;25260:41;2810:10;25293:7;25260:18;:41::i;:::-;25252:103;;;;-1:-1:-1;;;25252:103:0;;;;;;;:::i;:::-;25368:28;25378:4;25384:2;25388:7;25368:9;:28::i;97736:104::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;97812:20:::1;:7;97822:10:::0;;97812:20:::1;:::i;35032:256::-:0;35129:7;35165:23;35182:5;35165:16;:23::i;:::-;35157:5;:31;35149:87;;;;-1:-1:-1;;;35149:87:0;;20141:2:1;35149:87:0;;;20123:21:1;20180:2;20160:18;;;20153:30;20219:34;20199:18;;;20192:62;-1:-1:-1;;;20270:18:1;;;20263:41;20321:19;;35149:87:0;19939:407:1;35149:87:0;-1:-1:-1;;;;;;35254:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;35032:256::o;111534:158::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;111644:20:::1;::::0;;;:9:::1;:20;::::0;;;;;:27:::1;;:40:::0;;-1:-1:-1;;111644:40:0::1;::::0;::::1;;::::0;;;::::1;::::0;;111534:158::o;111190:113::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;111262:26:::1;::::0;;;:15:::1;:26;::::0;;;;:33;;-1:-1:-1;;111262:33:0::1;111291:4;111262:33;::::0;;111190:113::o;25475:185::-;25613:39;25630:4;25636:2;25640:7;25613:39;;;;;;;;;;;;:16;:39::i;35554:233::-;35629:7;35665:30;35452:10;:17;;35364:113;35665:30;35657:5;:38;35649:95;;;;-1:-1:-1;;;35649:95:0;;20553:2:1;35649:95:0;;;20535:21:1;20592:2;20572:18;;;20565:30;20631:34;20611:18;;;20604:62;-1:-1:-1;;;20682:18:1;;;20675:42;20734:19;;35649:95:0;20351:408:1;35649:95:0;35762:10;35773:5;35762:17;;;;;;;;:::i;:::-;;;;;;;;;35755:24;;35554:233;;;:::o;97562:120::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;97646:28:::1;:11;97660:14:::0;;97646:28:::1;:::i;108231:128::-:0;108290:4;108330:20;;;:9;:20;;;;;108314:37;;:15;:37::i;22310:239::-;22382:7;22418:16;;;:7;:16;;;;;;-1:-1:-1;;;;;22418:16:0;22453:19;22445:73;;;;-1:-1:-1;;;22445:73:0;;21098:2:1;22445:73:0;;;21080:21:1;21137:2;21117:18;;;21110:30;21176:34;21156:18;;;21149:62;-1:-1:-1;;;21227:18:1;;;21220:39;21276:19;;22445:73:0;20896:405:1;94905:386:0;94956:13;:16;-1:-1:-1;;;;;94956:16:0;94976:10;94956:30;94952:104;;;95003:7;:20;;-1:-1:-1;;;;;;95003:20:0;95013:10;95003:20;;;94905:386::o;94952:104::-;95070:16;;-1:-1:-1;;;;;95070:16:0;95090:10;95070:30;95066:104;;;95117:7;:20;;-1:-1:-1;;;;;;95117:20:0;95127:10;95117:20;;;94905:386::o;95066:104::-;95184:16;;-1:-1:-1;;;;;95184:16:0;95204:10;95184:30;95180:104;;;95231:7;:20;;-1:-1:-1;;;;;;95231:20:0;95241:10;95231:20;;;94905:386::o;95180:104::-;94905:386::o;22040:208::-;22112:7;-1:-1:-1;;;;;22140:19:0;;22132:74;;;;-1:-1:-1;;;22132:74:0;;21508:2:1;22132:74:0;;;21490:21:1;21547:2;21527:18;;;21520:30;21586:34;21566:18;;;21559:62;-1:-1:-1;;;21637:18:1;;;21630:40;21687:19;;22132:74:0;21306:406:1;22132:74:0;-1:-1:-1;;;;;;22224:16:0;;;;;:9;:16;;;;;;;22040:208::o;110414:236::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;110546:26:::1;::::0;;;:15:::1;:26;::::0;;;;;::::1;;110545:27;110537:60;;;;-1:-1:-1::0;;;110537:60:0::1;;;;;;;:::i;:::-;110608:20;::::0;;;:9:::1;:20;::::0;;;;110631:11;;110608:34:::1;110631:11:::0;110608:20;:34:::1;:::i;:::-;-1:-1:-1::0;;;;110414:236:0:o;109098:377::-;109171:23;109197:20;;;:9;:20;;;;;109236:24;109197:20;109236:15;:24::i;:::-;109228:52;;;;-1:-1:-1;;;109228:52:0;;25482:2:1;109228:52:0;;;25464:21:1;25521:2;25501:18;;;25494:30;-1:-1:-1;;;25540:18:1;;;25533:45;25595:18;;109228:52:0;25280:339:1;109228:52:0;109313:29;109323:9;109334:7;109313:9;:29::i;:::-;109299:10;;109291:19;;;;:7;:19;;;;;;;;:51;;;;;;;;;;:19;;:51;;;;;;;;;;;:::i;:::-;-1:-1:-1;109291:51:0;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;109291:51:0;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;109353:29;109359:10;109371;;109353:5;:29::i;:::-;109393:10;:12;;;:10;:12;;;:::i;:::-;;;;-1:-1:-1;;109434:7:0;;-1:-1:-1;;;;;109434:7:0;109420:10;:21;109416:51;;;109445:7;:22;;;109443:24;;;;;:::i;:::-;;;;-1:-1:-1;109160:315:0;109098:377;;:::o;22785:104::-;22841:13;22874:7;22867:14;;;;;:::i;24468:295::-;-1:-1:-1;;;;;24571:24:0;;2810:10;24571:24;;24563:62;;;;-1:-1:-1;;;24563:62:0;;26107:2:1;24563:62:0;;;26089:21:1;26146:2;26126:18;;;26119:30;26185:27;26165:18;;;26158:55;26230:18;;24563:62:0;25905:349:1;24563:62:0;2810:10;24638:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;24638:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;24638:53:0;;;;;;;;;;24707:48;;996:41:1;;;24638:42:0;;2810:10;24707:48;;969:18:1;24707:48:0;;;;;;;24468:295;;:::o;110721:318::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;110850:26:::1;::::0;;;:15:::1;:26;::::0;;;;;::::1;;110849:27;110841:60;;;;-1:-1:-1::0;;;110841:60:0::1;;;;;;;:::i;:::-;110943:17;::::0;::::1;;110920:19:::0;::::1;:40;;110912:71;;;::::0;-1:-1:-1;;;110912:71:0;;26461:2:1;110912:71:0::1;::::0;::::1;26443:21:1::0;26500:2;26480:18;;;26473:30;-1:-1:-1;;;26519:18:1;;;26512:48;26577:18;;110912:71:0::1;26259:342:1::0;110912:71:0::1;110994:20;::::0;;;:9:::1;:20;::::0;;;;111023:8;;110994:26:::1;;:37;111023:8:::0;110994:26;23308:5:1;23295:19;23289:4;23282:33;23369:2;23362:5;23358:14;23345:28;23341:1;23335:4;23331:12;23324:50;23428:2;23421:5;23417:14;23404:28;23400:1;23394:4;23390:12;23383:50;;;23172:267;104295:132:0;104353:7;104411:8;;104380:28;104398:9;104380:17;:28::i;:::-;:39;;;;:::i;103851:313::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;103975:22;;;::::1;:13;::::0;::::1;103947:24;:50;;103925:122;;;::::0;-1:-1:-1;;;103925:122:0;;26808:2:1;103925:122:0::1;::::0;::::1;26790:21:1::0;26847:2;26827:18;;;26820:30;-1:-1:-1;;;26866:18:1;;;26859:52;26928:18;;103925:122:0::1;26606:346:1::0;103925:122:0::1;104058:13;:15:::0;;;:13:::1;:15;::::0;::::1;:::i;:::-;::::0;;;-1:-1:-1;;104094:13:0::1;::::0;104084:24:::1;::::0;;;:9:::1;:24;::::0;;;;104111:7;;104084:34:::1;104111:7:::0;104084:24;:34:::1;:::i;:::-;-1:-1:-1::0;;104142:13:0::1;::::0;104134:22:::1;::::0;::::1;::::0;;;::::1;103851:313:::0;:::o;25731:328::-;25906:41;2810:10;25939:7;25906:18;:41::i;:::-;25898:103;;;;-1:-1:-1;;;25898:103:0;;;;;;;:::i;:::-;26012:39;26026:4;26032:2;26036:7;26045:5;26012:13;:39::i;111893:352::-;111981:16;112015:13;112031:18;112041:7;112031:9;:18::i;:::-;112015:34;;112060:20;112097:5;112083:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;112083:20:0;;112060:43;;112119:9;112114:103;112138:5;112134:1;:9;112114:103;;;112174:31;112194:7;112203:1;112174:19;:31::i;:::-;112165:3;112169:1;112165:6;;;;;;;;:::i;:::-;;;;;;;;;;:40;112145:3;;;:::i;:::-;;;112114:103;;;-1:-1:-1;112234:3:0;111893:352;-1:-1:-1;;;111893:352:0:o;107347:578::-;107470:4;107521:5;107546;107571;107609:14;107626:15;107633:7;107626:6;:15::i;:::-;107609:32;;107652:13;107668:3;:10;;;107679;107668:22;;;;;;;;:::i;:::-;;;;;;;;;;;107879:16;;;;:28;;107807:11;;;;;-1:-1:-1;107727:4:0;107719:12;;;;107753:1;107743:11;107783:12;;;107847;;;;107896:10;;107879:28;;;;;;:::i;:::-;;;;;;;;;;;;107909:1;;-1:-1:-1;107912:1:0;;-1:-1:-1;107915:1:0;;-1:-1:-1;107347:578:0;-1:-1:-1;;;;;107347:578:0:o;22960:334::-;27634:4;27658:16;;;:7;:16;;;;;;23033:13;;-1:-1:-1;;;;;27658:16:0;23059:76;;;;-1:-1:-1;;;23059:76:0;;27159:2:1;23059:76:0;;;27141:21:1;27198:2;27178:18;;;27171:30;27237:34;27217:18;;;27210:62;-1:-1:-1;;;27288:18:1;;;27281:45;27343:19;;23059:76:0;26957:411:1;23059:76:0;23148:21;23172:10;:8;:10::i;:::-;23148:34;;23224:1;23206:7;23200:21;:25;:86;;;;;;;;;;;;;;;;;23252:7;23261:18;:7;:16;:18::i;:::-;23235:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;23200:86;23193:93;22960:334;-1:-1:-1;;;22960:334:0:o;109658:191::-;109741:19;109750:9;109741:8;:19::i;:::-;109728:9;:32;;109720:59;;;;-1:-1:-1;;;109720:59:0;;28050:2:1;109720:59:0;;;28032:21:1;28089:2;28069:18;;;28062:30;-1:-1:-1;;;28108:18:1;;;28101:44;28162:18;;109720:59:0;27848:338:1;109720:59:0;109790:8;:6;:8::i;:::-;109809:32;;-1:-1:-1;;;109809:32:0;;;;;28365:25:1;;;109830:10:0;28406:18:1;;;28399:60;109809:4:0;;:9;;28338:18:1;;109809:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109658:191;:::o;95355:1072::-;95399:11;95469:15;95563:43;92677:6;95596:9;95563:18;:43::i;:::-;95625:7;;;95617:34;;95553:53;;-1:-1:-1;;;;;;95625:7:0;;95617:34;;;;;95553:53;;95617:34;;95625:7;95617:34;95553:53;95625:7;95617:34;;;;;;;;;;;;;;;;;;;;-1:-1:-1;95662:14:0;95669:7;95662:14;;:::i;:::-;;;95755:43;92722:6;95788:9;95755:18;:43::i;:::-;95745:53;-1:-1:-1;95829:9:0;95813:13;95745:53;95813:3;:13;:::i;:::-;:25;95809:182;;;95865:15;95877:3;95865:9;:15;:::i;:::-;95855:25;-1:-1:-1;95899:11:0;;95895:51;;95920:7;;95912:34;;-1:-1:-1;;;;;95920:7:0;;;;95912:34;;;;;95938:7;;95920;95912:34;95920:7;95912:34;95938:7;95920;95912:34;;;;;;;;;;;;;;;;;;;95895:51;95973:7;;95355:1072::o;95809:182::-;96009:7;;96001:34;;-1:-1:-1;;;;;96009:7:0;;;;96001:34;;;;;96027:7;;96009;96001:34;96009:7;96001:34;96027:7;96009;96001:34;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96046:14:0;96053:7;96046:14;;:::i;:::-;;;96139:43;92767:6;96172:9;96139:18;:43::i;:::-;96129:53;-1:-1:-1;96213:9:0;96197:13;96129:53;96197:3;:13;:::i;:::-;:25;96193:182;;;96249:15;96261:3;96249:9;:15;:::i;:::-;96239:25;-1:-1:-1;96283:11:0;;96279:51;;96304:7;;96296:34;;-1:-1:-1;;;;;96304:7:0;;;;96296:34;;;;;96322:7;;96304;96296:34;96304:7;96296:34;96322:7;96304;96296:34;;;;;;;;;;;;;;;;;;;96193:182;96393:7;;96385:34;;-1:-1:-1;;;;;96393:7:0;;;;96385:34;;;;;96411:7;;96393;96385:34;96393:7;96385:34;96411:7;96393;96385:34;;;;;;;;;;;;;;;;;;;105289:164;105378:16;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;105378:16:0;-1:-1:-1;105419:20:0;;;;:9;:20;;;;;;;;;105412:33;;;;;;;105419:26;;;105412:33;;;;;;;;;;;;;;;;;;;;;;;;;105289:164::o;93655:149::-;93710:4;93745:7;;-1:-1:-1;;;;;93734:18:0;;;93745:7;;93734:18;;:40;;-1:-1:-1;93767:7:0;;-1:-1:-1;;;;;93756:18:0;;;93767:7;;93756:18;93734:40;:62;;;-1:-1:-1;;93789:7:0;;-1:-1:-1;;;;;93789:7:0;;;93778:18;;;;93655:149::o;105966:195::-;-1:-1:-1;;;;;;;;;;;;;;;;;106112:20:0;;;;:9;:20;;;;;:41;;106143:9;;106112:41;;;;;;:::i;:::-;;;;;;;;;;;106105:48;;;;;;;;;;;;;;;;;;;;;;;;;;;105966:195;;;;:::o;94656:143::-;93441:19;93449:10;93441:7;:19::i;:::-;93433:66;;;;-1:-1:-1;;;93433:66:0;;;;;;;:::i;:::-;94783:8:::1;94732:13;94746:33;94768:10;94746:21;:33::i;:::-;94732:48;;;;;;;;;:::i;:::-;;:59:::0;;-1:-1:-1;;;;;;94732:59:0::1;-1:-1:-1::0;;;;;94732:59:0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;94656:143:0:o;107074:108::-;107128:10;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107128:10:0;107158:16;;;;:7;:16;;;;;;;;;107151:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107158:16;;107151:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107074:108;;;:::o;94308:264::-;94404:5;94442:7;;-1:-1:-1;;;;;94431:18:0;;;94442:7;;94431:18;94427:32;;;-1:-1:-1;94458:1:0;;94308:264;-1:-1:-1;94308:264:0:o;94427:32::-;94485:7;;-1:-1:-1;;;;;94474:18:0;;;94485:7;;94474:18;94470:32;;;-1:-1:-1;94501:1:0;;94308:264;-1:-1:-1;94308:264:0:o;94470:32::-;94528:7;;-1:-1:-1;;;;;94517:18:0;;;94528:7;;94517:18;94513:32;;;-1:-1:-1;94544:1:0;;94308:264;-1:-1:-1;94308:264:0:o;94513:32::-;-1:-1:-1;94563:1:0;;94308:264;-1:-1:-1;94308:264:0:o;96732:70::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;96840:65::-;;;;;;;:::i;21671:305::-;21773:4;-1:-1:-1;;;;;;21810:40:0;;-1:-1:-1;;;21810:40:0;;:105;;-1:-1:-1;;;;;;;21867:48:0;;-1:-1:-1;;;21867:48:0;21810:105;:158;;;-1:-1:-1;;;;;;;;;;13759:40:0;;;21932:36;13650:157;31551:174;31626:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;31626:29:0;-1:-1:-1;;;;;31626:29:0;;;;;;;;:24;;31680:23;31626:24;31680:14;:23::i;:::-;-1:-1:-1;;;;;31671:46:0;;;;;;;;;;;31551:174;;:::o;27863:348::-;27956:4;27658:16;;;:7;:16;;;;;;-1:-1:-1;;;;;27658:16:0;27973:73;;;;-1:-1:-1;;;27973:73:0;;28935:2:1;27973:73:0;;;28917:21:1;28974:2;28954:18;;;28947:30;29013:34;28993:18;;;28986:62;-1:-1:-1;;;29064:18:1;;;29057:42;29116:19;;27973:73:0;28733:408:1;27973:73:0;28057:13;28073:23;28088:7;28073:14;:23::i;:::-;28057:39;;28126:5;-1:-1:-1;;;;;28115:16:0;:7;-1:-1:-1;;;;;28115:16:0;;:51;;;;28159:7;-1:-1:-1;;;;;28135:31:0;:20;28147:7;28135:11;:20::i;:::-;-1:-1:-1;;;;;28135:31:0;;28115:51;:87;;;-1:-1:-1;;;;;;24955:25:0;;;24931:4;24955:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;28170:32;28107:96;27863:348;-1:-1:-1;;;;27863:348:0:o;30855:578::-;31014:4;-1:-1:-1;;;;;30987:31:0;:23;31002:7;30987:14;:23::i;:::-;-1:-1:-1;;;;;30987:31:0;;30979:85;;;;-1:-1:-1;;;30979:85:0;;29348:2:1;30979:85:0;;;29330:21:1;29387:2;29367:18;;;29360:30;29426:34;29406:18;;;29399:62;-1:-1:-1;;;29477:18:1;;;29470:39;29526:19;;30979:85:0;29146:405:1;30979:85:0;-1:-1:-1;;;;;31083:16:0;;31075:65;;;;-1:-1:-1;;;31075:65:0;;29758:2:1;31075:65:0;;;29740:21:1;29797:2;29777:18;;;29770:30;29836:34;29816:18;;;29809:62;-1:-1:-1;;;29887:18:1;;;29880:34;29931:19;;31075:65:0;29556:400:1;31075:65:0;31153:39;31174:4;31180:2;31184:7;31153:20;:39::i;:::-;31257:29;31274:1;31278:7;31257:8;:29::i;:::-;-1:-1:-1;;;;;31299:15:0;;;;;;:9;:15;;;;;:20;;31318:1;;31299:15;:20;;31318:1;;31299:20;:::i;:::-;;;;-1:-1:-1;;;;;;;31330:13:0;;;;;;:9;:13;;;;;:18;;31347:1;;31330:13;:18;;31347:1;;31330:18;:::i;:::-;;;;-1:-1:-1;;31359:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;31359:21:0;-1:-1:-1;;;;;31359:21:0;;;;;;;;;31398:27;;31359:16;;31398:27;;;;;;;30855:578;;;:::o;108367:517::-;108507:7;;108467:4;;-1:-1:-1;;;;;108507:7:0;108493:10;:21;108489:200;;;108552:7;:16;;;108535:7;:13;;;:33;108531:51;;-1:-1:-1;108577:5:0;;108367:517;-1:-1:-1;108367:517:0:o;108531:51::-;108489:200;;;108646:7;:16;;;108620:7;:22;;;108604:7;:13;;;:38;;;;:::i;:::-;:58;108600:89;;-1:-1:-1;108684:5:0;;108367:517;-1:-1:-1;108367:517:0:o;108600:89::-;108718:10;108740:4;108718:27;;;;:65;;-1:-1:-1;108776:7:0;;-1:-1:-1;;;;;108776:7:0;108762:10;:21;;108718:65;:102;;;;;108801:19;108809:10;108801:7;:19::i;:::-;108800:20;108718:102;108700:144;;;-1:-1:-1;108839:5:0;;108367:517;-1:-1:-1;108367:517:0:o;108700:144::-;-1:-1:-1;108862:14:0;;;;;;108367:517::o;101987:1263::-;102086:10;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102086:10:0;102229:24;;102190:22;;102215:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;102215:39:0;;102190:64;;102270:9;102265:288;102289:24;;102285:28;;102265:288;;;102335:27;102365:7;:17;;102383:1;102365:20;;;;;;;;:::i;:::-;;;;;;;;;;;102335:50;;;;;;;;;;;;;;;;;;;;;;;;;;;102427:8;:20;;;102417:6;102405:9;:7;:9::i;:::-;:18;;;;:::i;:::-;102404:43;102400:141;;;102494:8;:14;;;102482:9;:7;:9::i;:::-;:26;;;;:::i;:::-;102477:32;;:1;:32;:::i;:::-;102466:5;102472:1;102466:8;;;;;;;;:::i;:::-;;;;;;:43;;;;;102400:141;;;102540:1;102529:5;102535:1;102529:8;;;;;;;;:::i;:::-;;;;;;:12;;;;;102400:141;-1:-1:-1;102315:3:0;;;:::i;:::-;;;102265:288;;;-1:-1:-1;102649:14:0;;;:21;102609:26;;102638:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;102638:33:0;-1:-1:-1;102722:14:0;;;:21;102609:62;;-1:-1:-1;102682:23:0;;102708:36;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;102708:36:0;;102682:62;;102760:9;102755:198;102779:14;;;:21;102775:25;;102755:198;;;102863:7;:14;;102878:1;102863:17;;;;;;;;:::i;:::-;;;;;;;;;102853:6;102841:9;:7;:9::i;:::-;:18;;;;:::i;:::-;102840:40;102822:12;102835:1;102822:15;;;;;;;;:::i;:::-;;;;;;:58;;;;;;;;;;;102899:12;102912:1;102899:15;;;;;;;;:::i;:::-;;;;;;;102895:46;;;102928:13;:11;:13::i;:::-;102916:6;102923:1;102916:9;;;;;;;;:::i;:::-;;;;;;:25;;;;;102895:46;102802:3;;;:::i;:::-;;;102755:198;;;-1:-1:-1;103025:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103159:13;;;:15;;;103005:17;103159:15;;;:::i;:::-;;;;-1:-1:-1;103236:6:0;;101987:1263;-1:-1:-1;;;;;;;101987:1263:0:o;29547:382::-;-1:-1:-1;;;;;29627:16:0;;29619:61;;;;-1:-1:-1;;;29619:61:0;;30412:2:1;29619:61:0;;;30394:21:1;;;30431:18;;;30424:30;30490:34;30470:18;;;30463:62;30542:18;;29619:61:0;30210:356:1;29619:61:0;27634:4;27658:16;;;:7;:16;;;;;;-1:-1:-1;;;;;27658:16:0;:30;29691:58;;;;-1:-1:-1;;;29691:58:0;;30773:2:1;29691:58:0;;;30755:21:1;30812:2;30792:18;;;30785:30;30851;30831:18;;;30824:58;30899:18;;29691:58:0;30571:352:1;29691:58:0;29762:45;29791:1;29795:2;29799:7;29762:20;:45::i;:::-;-1:-1:-1;;;;;29820:13:0;;;;;;:9;:13;;;;;:18;;29837:1;;29820:13;:18;;29837:1;;29820:18;:::i;:::-;;;;-1:-1:-1;;29849:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;29849:21:0;-1:-1:-1;;;;;29849:21:0;;;;;;;;29888:33;;29849:16;;;29888:33;;29849:16;;29888:33;29547:382;;:::o;104500:637::-;104595:7;104645:20;;;:9;:20;;;;;;;;104620:45;;;;;;;;;;;;;;;;;;;;;104595:7;;104620:45;;;;104645:20;;104620:45;104595:7;;104620:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104680:7;:13;;;:23;;;104707:1;104680:28;104676:65;;;104717:13;;;:24;;104500:637;-1:-1:-1;;104500:637:0:o;104676:65::-;104756:7;:13;;;:23;;;104783:1;104756:28;104752:377;;;104801:9;104813:51;104832:7;:13;;;104847:7;:16;;;104813:18;:51::i;:::-;105037:13;;;;:24;;105012:22;;;;;104801:63;;-1:-1:-1;104947:133:0;;104801:63;;105012:49;;;:::i;:::-;104947:18;:133::i;:::-;104903:13;;;;:24;:177;;;;:::i;104752:377::-;105105:13;;;:24;;104500:637;-1:-1:-1;;104500:637:0:o;104752:377::-;104609:528;104500:637;;;:::o;26941:315::-;27098:28;27108:4;27114:2;27118:7;27098:9;:28::i;:::-;27145:48;27168:4;27174:2;27178:7;27187:5;27145:22;:48::i;:::-;27137:111;;;;-1:-1:-1;;;27137:111:0;;;;;;;:::i;98086:100::-;98138:13;98171:7;98164:14;;;;;:::i;346:723::-;402:13;623:10;619:53;;-1:-1:-1;;650:10:0;;;;;;;;;;;;-1:-1:-1;;;650:10:0;;;;;346:723::o;619:53::-;697:5;682:12;738:78;745:9;;738:78;;771:8;;;;:::i;:::-;;-1:-1:-1;794:10:0;;-1:-1:-1;802:2:0;794:10;;:::i;:::-;;;738:78;;;826:19;858:6;848:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;848:17:0;;826:39;;876:154;883:10;;876:154;;910:11;920:1;910:11;;:::i;:::-;;-1:-1:-1;979:10:0;987:2;979:5;:10;:::i;:::-;966:24;;:2;:24;:::i;:::-;953:39;;936:6;943;936:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;936:56:0;;;;;;;;-1:-1:-1;1007:11:0;1016:2;1007:11;;:::i;:::-;;;876:154;;88415:132;88473:14;88509:30;88534:1;88537;88509:24;:30::i;36400:589::-;-1:-1:-1;;;;;36606:18:0;;36602:187;;36641:40;36673:7;37816:10;:17;;37789:24;;;;:15;:24;;;;;:44;;;37844:24;;;;;;;;;;;;37712:164;36641:40;36602:187;;;36711:2;-1:-1:-1;;;;;36703:10:0;:4;-1:-1:-1;;;;;36703:10:0;;36699:90;;36730:47;36763:4;36769:7;36730:32;:47::i;:::-;-1:-1:-1;;;;;36803:16:0;;36799:183;;36836:45;36873:7;36836:36;:45::i;36799:183::-;36909:4;-1:-1:-1;;;;;36903:10:0;:2;-1:-1:-1;;;;;36903:10:0;;36899:83;;36930:40;36958:2;36962:7;36930:27;:40::i;103555:224::-;103687:10;;103658:57;;-1:-1:-1;;103675:10:0;31677:2:1;31673:15;31669:53;103658:57:0;;;31657:66:1;31739:12;;;31732:28;;;;103699:15:0;31776:12:1;;;31769:28;103592:7:0;;;;31813:12:1;;103658:57:0;;;-1:-1:-1;;103658:57:0;;;;;;;;;103648:68;;103658:57;103648:68;;;;103738:10;:12;;103648:68;;-1:-1:-1;103626:101:0;103738:12;;;:::i;:::-;;;;-1:-1:-1;103768:3:0;;103555:224;-1:-1:-1;;103555:224:0:o;103275:272::-;103316:7;103336:9;103360:3;103348:9;:7;:9::i;:::-;:15;;;;:::i;:::-;103336:27;;103374:9;103398:3;103386:9;:7;:9::i;:::-;:15;;;;:::i;:::-;103374:27;;103412:9;103436:3;103424:9;:7;:9::i;:::-;:15;;;;:::i;:::-;103412:27;;103520:2;103515:1;:7;;103509:1;103504;:6;;103499:1;:12;:24;103492:31;;;;;103275:272;:::o;70656:129::-;70714:14;70750:27;70765:1;68129:4;70775:1;70750:14;:27::i;32290:799::-;32445:4;-1:-1:-1;;;;;32466:13:0;;4033:20;4081:8;32462:620;;32502:72;;-1:-1:-1;;;32502:72:0;;-1:-1:-1;;;;;32502:36:0;;;;;:72;;2810:10;;32553:4;;32559:7;;32568:5;;32502:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32502:72:0;;;;;;;;-1:-1:-1;;32502:72:0;;;;;;;;;;;;:::i;:::-;;;32498:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32744:13:0;;32740:272;;32787:60;;-1:-1:-1;;;32787:60:0;;;;;;;:::i;32740:272::-;32962:6;32956:13;32947:6;32943:2;32939:15;32932:38;32498:529;-1:-1:-1;;;;;;32625:51:0;-1:-1:-1;;;32625:51:0;;-1:-1:-1;32618:58:0;;32462:620;-1:-1:-1;33066:4:0;32290:799;;;;;;:::o;61556:1188::-;61627:14;;;-1:-1:-1;;61746:1:0;61743;61736:20;61786:1;61783;61779:9;61770:18;;61838:5;61834:2;61831:13;61823:5;61819:2;61815:14;61811:34;61802:43;;;45198:4;61872:5;:14;61868:94;;61910:40;;-1:-1:-1;;;61910:40:0;;;;;2966:25:1;;;2939:18;;61910:40:0;2820:177:1;61868:94:0;61974:17;62002:19;62082:5;62079:1;62076;62069:19;62056:32;-1:-1:-1;;62131:18:0;62117:33;;62177:10;62173:157;;62260:11;45198:4;62243:5;:13;62242:29;62233:38;;62290:13;;;;;;62173:157;62586:11;62457:21;;;62453:39;62534:20;;;;62523:32;;;-1:-1:-1;;;62519:84:0;62424:202;;;;62649:13;62398:283;62376:350;;-1:-1:-1;61556:1188:0;;;;:::o;38503:988::-;38769:22;38819:1;38794:22;38811:4;38794:16;:22::i;:::-;:26;;;;:::i;:::-;38831:18;38852:26;;;:17;:26;;;;;;38769:51;;-1:-1:-1;38985:28:0;;;38981:328;;-1:-1:-1;;;;;39052:18:0;;39030:19;39052:18;;;:12;:18;;;;;;;;:34;;;;;;;;;39103:30;;;;;;:44;;;39220:30;;:17;:30;;;;;:43;;;38981:328;-1:-1:-1;39405:26:0;;;;:17;:26;;;;;;;;39398:33;;;-1:-1:-1;;;;;39449:18:0;;;;;:12;:18;;;;;:34;;;;;;;39442:41;38503:988::o;39786:1079::-;40064:10;:17;40039:22;;40064:21;;40084:1;;40064:21;:::i;:::-;40096:18;40117:24;;;:15;:24;;;;;;40490:10;:26;;40039:46;;-1:-1:-1;40117:24:0;;40039:46;;40490:26;;;;;;:::i;:::-;;;;;;;;;40468:48;;40554:11;40529:10;40540;40529:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;40634:28;;;:15;:28;;;;;;;:41;;;40806:24;;;;;40799:31;40841:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;39857:1008;;;39786:1079;:::o;37290:221::-;37375:14;37392:20;37409:2;37392:16;:20::i;:::-;-1:-1:-1;;;;;37423:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;37468:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;37290:221:0:o;56340:4067::-;56456:14;;;-1:-1:-1;;56952:1:0;56949;56942:20;56992:1;56989;56985:9;56976:18;;57044:5;57040:2;57037:13;57029:5;57025:2;57021:14;57017:34;57008:43;;;57138:5;57147:1;57138:10;57134:143;;;57211:11;57203:5;:19;;;;;:::i;:::-;;57194:28;;57252:13;;;;57134:143;57387:11;57378:5;:20;57374:103;;57422:43;;-1:-1:-1;;;57422:43:0;;;;;32890:25:1;;;32931:18;;;32924:34;;;32863:18;;57422:43:0;32716:248:1;57374:103:0;57719:17;57845:11;57842:1;57839;57832:25;59283:1;59264;58402;58387:12;;:16;;58372:32;;58513:25;;;;59264:15;;;59263:21;;59520;;;59516:25;;59505:36;59590:21;;;59586:25;;59575:36;59661:21;;;59657:25;;59646:36;59732:21;;;59728:25;;59717:36;59803:21;;;59799:25;;59788:36;59875:21;;;59871:25;;;59860:36;58354:15;58785;;;58781:29;;;58777:37;;;57954:20;;;57943:32;;;58907:15;;;;57998:21;;58620:19;;;;58898:24;;;;60345:15;;56340:4067;-1:-1:-1;;;;56340:4067:0:o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:451:1;105:6;113;166:2;154:9;145:7;141:23;137:32;134:52;;;182:1;179;172:12;134:52;218:9;205:23;195:33;;279:2;268:9;264:18;251:32;306:18;298:6;295:30;292:50;;;338:1;335;328:12;292:50;361:22;;417:3;399:16;;;395:26;392:46;;;434:1;431;424:12;392:46;457:2;447:12;;;14:451;;;;;:::o;470:131::-;-1:-1:-1;;;;;;544:32:1;;534:43;;524:71;;591:1;588;581:12;524:71;470:131;:::o;606:245::-;664:6;717:2;705:9;696:7;692:23;688:32;685:52;;;733:1;730;723:12;685:52;772:9;759:23;791:30;815:5;791:30;:::i;1048:258::-;1120:1;1130:113;1144:6;1141:1;1138:13;1130:113;;;1220:11;;;1214:18;1201:11;;;1194:39;1166:2;1159:10;1130:113;;;1261:6;1258:1;1255:13;1252:48;;;-1:-1:-1;;1296:1:1;1278:16;;1271:27;1048:258::o;1311:::-;1353:3;1391:5;1385:12;1418:6;1413:3;1406:19;1434:63;1490:6;1483:4;1478:3;1474:14;1467:4;1460:5;1456:16;1434:63;:::i;:::-;1551:2;1530:15;-1:-1:-1;;1526:29:1;1517:39;;;;1558:4;1513:50;;1311:258;-1:-1:-1;;1311:258:1:o;1574:220::-;1723:2;1712:9;1705:21;1686:4;1743:45;1784:2;1773:9;1769:18;1761:6;1743:45;:::i;1799:180::-;1858:6;1911:2;1899:9;1890:7;1886:23;1882:32;1879:52;;;1927:1;1924;1917:12;1879:52;-1:-1:-1;1950:23:1;;1799:180;-1:-1:-1;1799:180:1:o;2192:173::-;2260:20;;-1:-1:-1;;;;;2309:31:1;;2299:42;;2289:70;;2355:1;2352;2345:12;2289:70;2192:173;;;:::o;2370:254::-;2438:6;2446;2499:2;2487:9;2478:7;2474:23;2470:32;2467:52;;;2515:1;2512;2505:12;2467:52;2538:29;2557:9;2538:29;:::i;:::-;2528:39;2614:2;2599:18;;;;2586:32;;-1:-1:-1;;;2370:254:1:o;2629:186::-;2688:6;2741:2;2729:9;2720:7;2716:23;2712:32;2709:52;;;2757:1;2754;2747:12;2709:52;2780:29;2799:9;2780:29;:::i;3002:328::-;3079:6;3087;3095;3148:2;3136:9;3127:7;3123:23;3119:32;3116:52;;;3164:1;3161;3154:12;3116:52;3187:29;3206:9;3187:29;:::i;:::-;3177:39;;3235:38;3269:2;3258:9;3254:18;3235:38;:::i;:::-;3225:48;;3320:2;3309:9;3305:18;3292:32;3282:42;;3002:328;;;;;:::o;3335:592::-;3406:6;3414;3467:2;3455:9;3446:7;3442:23;3438:32;3435:52;;;3483:1;3480;3473:12;3435:52;3523:9;3510:23;3552:18;3593:2;3585:6;3582:14;3579:34;;;3609:1;3606;3599:12;3579:34;3647:6;3636:9;3632:22;3622:32;;3692:7;3685:4;3681:2;3677:13;3673:27;3663:55;;3714:1;3711;3704:12;3663:55;3754:2;3741:16;3780:2;3772:6;3769:14;3766:34;;;3796:1;3793;3786:12;3766:34;3841:7;3836:2;3827:6;3823:2;3819:15;3815:24;3812:37;3809:57;;;3862:1;3859;3852:12;3809:57;3893:2;3885:11;;;;;3915:6;;-1:-1:-1;3335:592:1;;-1:-1:-1;;;;3335:592:1:o;3932:118::-;4018:5;4011:13;4004:21;3997:5;3994:32;3984:60;;4040:1;4037;4030:12;4055:309;4120:6;4128;4181:2;4169:9;4160:7;4156:23;4152:32;4149:52;;;4197:1;4194;4187:12;4149:52;4233:9;4220:23;4210:33;;4293:2;4282:9;4278:18;4265:32;4306:28;4328:5;4306:28;:::i;4580:549::-;4887:25;;;4943:2;4928:18;;4921:34;;;4874:3;4859:19;;4964:55;5015:2;5000:18;;4992:6;4444:12;;4432:25;;4506:4;4495:16;;;4489:23;4473:14;;;4466:47;4562:4;4551:16;;;4545:23;4529:14;;4522:47;4369:206;4964:55;5056:6;5050:3;5039:9;5035:19;5028:35;5114:6;5107:14;5100:22;5094:3;5083:9;5079:19;5072:51;4580:549;;;;;;;;:::o;5134:156::-;5194:5;5239:3;5230:6;5225:3;5221:16;5217:26;5214:46;;;5256:1;5253;5246:12;5295:424;5390:6;5398;5451:2;5439:9;5430:7;5426:23;5422:32;5419:52;;;5467:1;5464;5457:12;5419:52;5503:9;5490:23;5480:33;;5564:2;5553:9;5549:18;5536:32;5591:18;5583:6;5580:30;5577:50;;;5623:1;5620;5613:12;5577:50;5646:67;5705:7;5696:6;5685:9;5681:22;5646:67;:::i;:::-;5636:77;;;5295:424;;;;;:::o;5724:254::-;5792:6;5800;5853:2;5841:9;5832:7;5828:23;5824:32;5821:52;;;5869:1;5866;5859:12;5821:52;5905:9;5892:23;5882:33;;5934:38;5968:2;5957:9;5953:18;5934:38;:::i;:::-;5924:48;;5724:254;;;;;:::o;5983:315::-;6048:6;6056;6109:2;6097:9;6088:7;6084:23;6080:32;6077:52;;;6125:1;6122;6115:12;6077:52;6148:29;6167:9;6148:29;:::i;:::-;6138:39;;6227:2;6216:9;6212:18;6199:32;6240:28;6262:5;6240:28;:::i;6303:339::-;6400:6;6408;6452:9;6443:7;6439:23;6482:3;6478:2;6474:12;6471:32;;;6499:1;6496;6489:12;6471:32;6522:23;;;-1:-1:-1;6579:2:1;-1:-1:-1;;6561:16:1;;6557:25;6554:45;;;6595:1;6592;6585:12;6554:45;;6633:2;6622:9;6618:18;6608:28;;6303:339;;;;;:::o;6647:356::-;6733:6;6786:2;6774:9;6765:7;6761:23;6757:32;6754:52;;;6802:1;6799;6792:12;6754:52;6842:9;6829:23;6875:18;6867:6;6864:30;6861:50;;;6907:1;6904;6897:12;6861:50;6930:67;6989:7;6980:6;6969:9;6965:22;6930:67;:::i;7008:127::-;7069:10;7064:3;7060:20;7057:1;7050:31;7100:4;7097:1;7090:15;7124:4;7121:1;7114:15;7140:1138;7235:6;7243;7251;7259;7312:3;7300:9;7291:7;7287:23;7283:33;7280:53;;;7329:1;7326;7319:12;7280:53;7352:29;7371:9;7352:29;:::i;:::-;7342:39;;7400:38;7434:2;7423:9;7419:18;7400:38;:::i;:::-;7390:48;;7485:2;7474:9;7470:18;7457:32;7447:42;;7540:2;7529:9;7525:18;7512:32;7563:18;7604:2;7596:6;7593:14;7590:34;;;7620:1;7617;7610:12;7590:34;7658:6;7647:9;7643:22;7633:32;;7703:7;7696:4;7692:2;7688:13;7684:27;7674:55;;7725:1;7722;7715:12;7674:55;7761:2;7748:16;7783:2;7779;7776:10;7773:36;;;7789:18;;:::i;:::-;7864:2;7858:9;7832:2;7918:13;;-1:-1:-1;;7914:22:1;;;7938:2;7910:31;7906:40;7894:53;;;7962:18;;;7982:22;;;7959:46;7956:72;;;8008:18;;:::i;:::-;8048:10;8044:2;8037:22;8083:2;8075:6;8068:18;8123:7;8118:2;8113;8109;8105:11;8101:20;8098:33;8095:53;;;8144:1;8141;8134:12;8095:53;8200:2;8195;8191;8187:11;8182:2;8174:6;8170:15;8157:46;8245:1;8240:2;8235;8227:6;8223:15;8219:24;8212:35;8266:6;8256:16;;;;;;;7140:1138;;;;;;;:::o;8283:435::-;8336:3;8374:5;8368:12;8401:6;8396:3;8389:19;8427:4;8456:2;8451:3;8447:12;8440:19;;8493:2;8486:5;8482:14;8514:1;8524:169;8538:6;8535:1;8532:13;8524:169;;;8599:13;;8587:26;;8633:12;;;;8668:15;;;;8560:1;8553:9;8524:169;;;-1:-1:-1;8709:3:1;;8283:435;-1:-1:-1;;;;;8283:435:1:o;8723:261::-;8902:2;8891:9;8884:21;8865:4;8922:56;8974:2;8963:9;8959:18;8951:6;8922:56;:::i;8989:248::-;9057:6;9065;9118:2;9106:9;9097:7;9093:23;9089:32;9086:52;;;9134:1;9131;9124:12;9086:52;-1:-1:-1;;9157:23:1;;;9227:2;9212:18;;;9199:32;;-1:-1:-1;8989:248:1:o;9669:252::-;4444:12;;4432:25;;4506:4;4495:16;;;4489:23;4473:14;;;4466:47;4562:4;4551:16;;;4545:23;4529:14;;;4522:47;9857:2;9842:18;;9869:46;4369:206;10236:260;10304:6;10312;10365:2;10353:9;10344:7;10340:23;10336:32;10333:52;;;10381:1;10378;10371:12;10333:52;10404:29;10423:9;10404:29;:::i;:::-;10394:39;;10452:38;10486:2;10475:9;10471:18;10452:38;:::i;10501:1153::-;10635:4;10664:2;10693;10682:9;10675:21;10738:6;10732:13;10727:2;10716:9;10712:18;10705:41;10793:2;10785:6;10781:15;10775:22;10833:4;10828:2;10817:9;10813:18;10806:32;10861:63;10919:3;10908:9;10904:19;10890:12;10861:63;:::i;:::-;10973:2;10961:15;;10955:22;-1:-1:-1;;11043:22:1;;;11039:31;;11034:2;11019:18;;11012:59;11120:21;;11150:22;;;11226:23;;;;-1:-1:-1;11267:1:1;;10996:7;;11188:15;;;;11277:185;11291:6;11288:1;11285:13;11277:185;;;11366:13;;11359:21;11352:29;11340:42;;11437:15;;;;11313:1;11306:9;;;;;11402:12;;;;11277:185;;;11281:3;11511:2;11503:6;11499:15;11493:22;11471:44;;11578:2;11566:9;11561:3;11557:19;11553:28;11546:4;11535:9;11531:20;11524:58;11599:49;11644:3;11628:14;11599:49;:::i;:::-;11591:57;10501:1153;-1:-1:-1;;;;;;;;10501:1153:1:o;11848:398::-;12050:2;12032:21;;;12089:2;12069:18;;;12062:30;12128:34;12123:2;12108:18;;12101:62;-1:-1:-1;;;12194:2:1;12179:18;;12172:32;12236:3;12221:19;;11848:398::o;12251:344::-;12453:2;12435:21;;;12492:2;12472:18;;;12465:30;-1:-1:-1;;;12526:2:1;12511:18;;12504:50;12586:2;12571:18;;12251:344::o;12600:535::-;12683:4;12689:6;12749:11;12736:25;12843:2;12839:7;12828:8;12812:14;12808:29;12804:43;12784:18;12780:68;12770:96;;12862:1;12859;12852:12;12770:96;12889:33;;12941:20;;;-1:-1:-1;12984:18:1;12973:30;;12970:50;;;13016:1;13013;13006:12;12970:50;13049:4;13037:17;;-1:-1:-1;13100:1:1;13096:14;;;13080;13076:35;13066:46;;13063:66;;;13125:1;13122;13115:12;13063:66;12600:535;;;;;:::o;13140:127::-;13201:10;13196:3;13192:20;13189:1;13182:31;13232:4;13229:1;13222:15;13256:4;13253:1;13246:15;13272:168;13312:7;13378:1;13374;13370:6;13366:14;13363:1;13360:21;13355:1;13348:9;13341:17;13337:45;13334:71;;;13385:18;;:::i;:::-;-1:-1:-1;13425:9:1;;13272:168::o;13582:147::-;13645:78;13663:3;13656:5;13653:14;13645:78;;;13719:1;13705:16;;13690:1;13679:13;13645:78;;13734:773;-1:-1:-1;;;13856:3:1;13853:29;13850:55;;;13885:18;;:::i;:::-;13934:4;13928:11;13961:3;13955:4;13948:17;13985:6;13980:3;13977:15;13974:184;;;14025:4;14022:1;14015:15;14068:4;14065:1;14055:18;14086:62;14140:6;14134:4;14130:17;14124:3;14118:4;14114:14;14086:62;:::i;:::-;;13974:184;;14181:5;14205:4;14202:1;14195:15;14229:4;14274:2;14271:1;14261:16;14295:1;14305:196;14319:3;14316:1;14313:10;14305:196;;;14385:20;;14365:41;;14429:15;;;;14489:1;14472:19;;;;14331:9;14305:196;;;14309:3;;;;13734:773;;;:::o;14512:170::-;14554:11;14606:3;14593:17;14619:28;14641:5;14619:28;:::i;14972:1357::-;-1:-1:-1;;;15088:3:1;15085:29;15082:55;;;15117:18;;:::i;:::-;15166:4;15160:11;15193:3;15187:4;15180:17;15217:6;15212:3;15209:15;15206:513;;;15257:4;15254:1;15247:15;15300:4;15297:1;15287:18;15363:2;15358:3;15354:12;15351:1;15347:20;15341:4;15337:31;15400:2;15395:3;15391:12;15433:2;15426:10;15416:204;;15482:1;15478:6;15528:2;15515:11;15511:20;15601:2;15595:9;15590:2;15584;15578:4;15574:13;15571:1;15567:21;15563:30;15559:46;15555:2;15548:58;;;15416:204;;15633:76;15703:2;15695:6;15691:15;15688:1;15684:23;15678:4;15674:34;15661:11;15633:76;:::i;:::-;;;15206:513;-1:-1:-1;13529:1:1;13522:14;;;13566:4;13553:18;;15742:5;;13529:1;15892:431;15906:3;15903:1;15900:10;15892:431;;;15952:95;16014:32;16039:6;16014:32;:::i;:::-;14775:11;;14862:3;14816:1;14812:14;;;14847:19;;;14899:9;;14891:18;;;14937:13;;14930:21;14915:37;;14911:48;14888:72;14875:86;;14687:280;15952:95;16082:2;16074:6;16070:15;16060:25;;16108:1;16158:2;16143:13;16139:22;16122:39;;16195:2;16180:13;16177:21;16174:139;;;16279:20;;;;16246:1;;-1:-1:-1;16174:139:1;-1:-1:-1;15925:1:1;15918:9;15892:431;;16334:1557;16489:5;16476:19;16470:4;16463:33;16515:1;16553:2;16547:4;16543:13;16575:2;16620:70;16686:2;16679:5;16675:14;16668:5;16620:70;:::i;:::-;-1:-1:-1;;;16705:13:1;16702:39;16699:65;;;16744:18;;:::i;:::-;16793:10;16787:17;16832:13;16820:10;16813:33;16876:6;16861:13;16858:25;16855:208;;;16916:10;16913:1;16906:21;16965:2;16962:1;16952:16;16981:72;17045:6;17039:4;17035:17;17019:13;17013:4;17009:24;16981:72;:::i;:::-;;16855:208;-1:-1:-1;17113:1:1;17106:21;;;17155:16;;;;17199:208;17213:13;17210:1;17207:20;17199:208;;;17290:20;;17270:41;;17377:20;;;;17334:15;;;;17235:10;;17199:208;;;17203:3;;;;;;17452:70;17518:2;17511:5;17507:14;17500:5;17452:70;:::i;:::-;17531:112;17629:13;17614;17610:1;17604:4;17600:12;17531:112;:::i;:::-;;;17688:70;17754:2;17747:5;17743:14;17736:5;17688:70;:::i;:::-;17767:118;17871:13;17856;17852:1;17846:4;17842:12;17767:118;:::i;17896:380::-;17975:1;17971:12;;;;18018;;;18039:61;;18093:4;18085:6;18081:17;18071:27;;18039:61;18146:2;18138:6;18135:14;18115:18;18112:38;18109:161;;;18192:10;18187:3;18183:20;18180:1;18173:31;18227:4;18224:1;18217:15;18255:4;18252:1;18245:15;19521:413;19723:2;19705:21;;;19762:2;19742:18;;;19735:30;19801:34;19796:2;19781:18;;19774:62;-1:-1:-1;;;19867:2:1;19852:18;;19845:47;19924:3;19909:19;;19521:413::o;20764:127::-;20825:10;20820:3;20816:20;20813:1;20806:31;20856:4;20853:1;20846:15;20880:4;20877:1;20870:15;21927:1240;-1:-1:-1;;;22081:3:1;22078:29;22075:55;;;22110:18;;:::i;:::-;22159:4;22153:11;22186:3;22180:4;22173:17;22210:6;22205:3;22202:15;22199:586;;;-1:-1:-1;;;;;22267:1:1;22317:14;;;22309:23;;22306:49;;;22335:18;;:::i;:::-;22387:2;22382:3;22379:11;22375:2;22371:20;22368:46;;;22394:18;;:::i;:::-;22437:1;22451:16;;;22506:4;22492:19;;22437:1;;-1:-1:-1;22596:12:1;;;22586:23;;;22544:15;;;22534:26;22622:153;22640:2;22633:5;22630:13;22622:153;;;22715:2;22708:5;22701:17;22758:2;22753;22746:5;22742:14;22735:26;22666:1;22659:5;22655:13;22646:22;;22622:153;;;22626:3;;;;22199:586;-1:-1:-1;13529:1:1;13522:14;;;13566:4;13553:18;;22808:5;;22915:246;22929:3;22926:1;22923:10;22915:246;;;21837:19;;21824:33;;21911:2;21900:14;;21887:28;21883:1;21873:12;;21866:50;23101:2;23089:15;;;;;23149:1;23132:19;;;;;22948:1;22941:9;22915:246;;;22919:3;;;21927:1240;;;:::o;23944:1331::-;24120:5;24107:19;24205:2;24201:7;24193:5;24177:14;24173:26;24169:40;24149:18;24145:65;24135:93;;24224:1;24221;24214:12;24135:93;24249:30;;24302:18;;24343;24332:30;;24329:50;;;24375:1;24372;24365:12;24329:50;24412:4;24406;24402:15;24388:29;;24468:6;24465:1;24461:14;24445;24441:35;24433:6;24429:48;24426:68;;;24490:1;24487;24480:12;24426:68;24503:128;24624:6;24616;24610:4;24503:128;:::i;:::-;;;24674:72;24740:4;24733:5;24729:16;24722:5;24674:72;:::i;:::-;24755:116;24857:13;24844:11;24840:1;24834:4;24830:12;24755:116;:::i;:::-;-1:-1:-1;;24925:2:1;24914:14;;24901:28;24897:1;24887:12;;24880:50;24984:2;24973:14;;24960:28;24956:1;24946:12;;24939:50;25097:3;25086:15;;23295:19;25082:1;25072:12;;23282:33;23358:14;;;23345:28;23331:12;;;23324:50;23417:14;;;23404:28;23390:12;;;23383:50;25156:3;25149:5;25145:15;25132:29;25128:1;25122:4;25118:12;25111:51;25171:98;25227:41;25263:3;25256:5;25252:15;25227:41;:::i;:::-;25223:1;25217:4;25213:12;23861:3;23857:8;23850:4;23844:11;23840:26;23927:3;23918:5;23911:13;23904:21;23900:31;23891:7;23888:44;23882:4;23875:58;;23747:192;;;25624:135;25663:3;-1:-1:-1;;25684:17:1;;25681:43;;;25704:18;;:::i;:::-;-1:-1:-1;25751:1:1;25740:13;;25624:135::o;25764:136::-;25803:3;25831:5;25821:39;;25840:18;;:::i;:::-;-1:-1:-1;;;25876:18:1;;25764:136::o;27373:470::-;27552:3;27590:6;27584:13;27606:53;27652:6;27647:3;27640:4;27632:6;27628:17;27606:53;:::i;:::-;27722:13;;27681:16;;;;27744:57;27722:13;27681:16;27778:4;27766:17;;27744:57;:::i;:::-;27817:20;;27373:470;-1:-1:-1;;;;27373:470:1:o;28470:128::-;28510:3;28541:1;28537:6;28534:1;28531:13;28528:39;;;28547:18;;:::i;:::-;-1:-1:-1;28583:9:1;;28470:128::o;28603:125::-;28643:4;28671:1;28668;28665:8;28662:34;;;28676:18;;:::i;:::-;-1:-1:-1;28713:9:1;;28603:125::o;29961:127::-;30022:10;30017:3;30013:20;30010:1;30003:31;30053:4;30050:1;30043:15;30077:4;30074:1;30067:15;30093:112;30125:1;30151;30141:35;;30156:18;;:::i;:::-;-1:-1:-1;30190:9:1;;30093:112::o;30928:414::-;31130:2;31112:21;;;31169:2;31149:18;;;31142:30;31208:34;31203:2;31188:18;;31181:62;-1:-1:-1;;;31274:2:1;31259:18;;31252:48;31332:3;31317:19;;30928:414::o;31347:120::-;31387:1;31413;31403:35;;31418:18;;:::i;:::-;-1:-1:-1;31452:9:1;;31347:120::o;31836:489::-;-1:-1:-1;;;;;32105:15:1;;;32087:34;;32157:15;;32152:2;32137:18;;32130:43;32204:2;32189:18;;32182:34;;;32252:3;32247:2;32232:18;;32225:31;;;32030:4;;32273:46;;32299:19;;32291:6;32273:46;:::i;:::-;32265:54;31836:489;-1:-1:-1;;;;;;31836:489:1:o;32330:249::-;32399:6;32452:2;32440:9;32431:7;32427:23;32423:32;32420:52;;;32468:1;32465;32458:12;32420:52;32500:9;32494:16;32519:30;32543:5;32519:30;:::i;32584:127::-;32645:10;32640:3;32636:20;32633:1;32626:31;32676:4;32673:1;32666:15;32700:4;32697:1;32690:15

Swarm Source

ipfs://a6ec59f0b4532043f867b838fa0a0b7ded9a917f9c5cff484d9f7962d713bb93
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.