{"sources":{"Plutoko.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.24;\n\n// File: @openzeppelin/contracts/utils/introspection/IERC165.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/IERC721.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)\n\n\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)\n\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n     * reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)\n\n\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n\n// File: @openzeppelin/contracts/utils/Context.sol\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n\n// File: @openzeppelin/contracts/utils/math/Math.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n\n// File: @openzeppelin/contracts/utils/math/SignedMath.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n\n// File: @openzeppelin/contracts/utils/Strings.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\n\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n\n// File: @openzeppelin/contracts/utils/introspection/ERC165.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n\n// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/ERC721.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)\n\n\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    mapping(uint256 tokenId => address) private _owners;\n\n    mapping(address owner => uint256) private _balances;\n\n    mapping(uint256 tokenId => address) private _tokenApprovals;\n\n    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        if (owner == address(0)) {\n            revert ERC721InvalidOwner(address(0));\n        }\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual returns (address) {\n        return _requireOwned(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n        _requireOwned(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual {\n        _approve(to, tokenId, _msgSender());\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual returns (address) {\n        _requireOwned(tokenId);\n\n        return _getApproved(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) public virtual {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n        address previousOwner = _update(to, tokenId, _msgSender());\n        if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) public {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n        transferFrom(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     *\n     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n     */\n    function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n     * particular (ignoring whether it is owned by `owner`).\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n        return\n            spender != address(0) &&\n            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets\n     * the `spender` for the specific `tokenId`.\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n        if (!_isAuthorized(owner, spender, tokenId)) {\n            if (owner == address(0)) {\n                revert ERC721NonexistentToken(tokenId);\n            } else {\n                revert ERC721InsufficientApproval(spender, tokenId);\n            }\n        }\n    }\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n     *\n     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n     * remain consistent with one another.\n     */\n    function _increaseBalance(address account, uint128 value) internal virtual {\n        unchecked {\n            _balances[account] += value;\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n     */\n    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n        address from = _ownerOf(tokenId);\n\n        // Perform (optional) operator check\n        if (auth != address(0)) {\n            _checkAuthorized(from, auth, tokenId);\n        }\n\n        // Execute the update\n        if (from != address(0)) {\n            // Clear approval. No need to re-authorize or emit the Approval event\n            _approve(address(0), tokenId, address(0), false);\n\n            unchecked {\n                _balances[from] -= 1;\n            }\n        }\n\n        if (to != address(0)) {\n            unchecked {\n                _balances[to] += 1;\n            }\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        return from;\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner != address(0)) {\n            revert ERC721InvalidSender(address(0));\n        }\n    }\n\n    /**\n     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        _checkOnERC721Received(address(0), to, tokenId, data);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal {\n        address previousOwner = _update(address(0), tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        } else if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n     * are aware of the ERC721 standard to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is like {safeTransferFrom} in the sense that it invokes\n     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `tokenId` token must exist and be owned by `from`.\n     * - `to` cannot be the zero address.\n     * - `from` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId) internal {\n        _safeTransfer(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is\n     * either the owner of the token, or approved to operate on all tokens held by this owner.\n     *\n     * Emits an {Approval} event.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address to, uint256 tokenId, address auth) internal {\n        _approve(to, tokenId, auth, true);\n    }\n\n    /**\n     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not\n     * emitted in the context of transfers.\n     */\n    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {\n        // Avoid reading the owner unless necessary\n        if (emitEvent || auth != address(0)) {\n            address owner = _requireOwned(tokenId);\n\n            // We do not use _isAuthorized because single-token approvals should not be able to call approve\n            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {\n                revert ERC721InvalidApprover(auth);\n            }\n\n            if (emitEvent) {\n                emit Approval(owner, to, tokenId);\n            }\n        }\n\n        _tokenApprovals[tokenId] = to;\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Requirements:\n     * - operator can't be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        if (operator == address(0)) {\n            revert ERC721InvalidOperator(operator);\n        }\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).\n     * Returns the owner.\n     *\n     * Overrides to ownership logic should be done to {_ownerOf}.\n     */\n    function _requireOwned(uint256 tokenId) internal view returns (address) {\n        address owner = _ownerOf(tokenId);\n        if (owner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n        return owner;\n    }\n\n    /**\n     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the\n     * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param data bytes optional data to send along with the call\n     */\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {\n        if (to.code.length > 0) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) {\n                    revert ERC721InvalidReceiver(to);\n                }\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert ERC721InvalidReceiver(to);\n                } else {\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        }\n    }\n}\n\n// File: @openzeppelin/contracts/interfaces/IERC2981.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)\n\n\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n */\ninterface IERC2981 is IERC165 {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(\n        uint256 tokenId,\n        uint256 salePrice\n    ) external view returns (address receiver, uint256 royaltyAmount);\n}\n\n// File: @openzeppelin/contracts/token/common/ERC2981.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)\n\n\n\n/**\n * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.\n *\n * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for\n * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.\n *\n * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the\n * fee is specified in basis points by default.\n *\n * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See\n * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to\n * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.\n */\nabstract contract ERC2981 is IERC2981, ERC165 {\n    struct RoyaltyInfo {\n        address receiver;\n        uint96 royaltyFraction;\n    }\n\n    RoyaltyInfo private _defaultRoyaltyInfo;\n    mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;\n\n    /**\n     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The default royalty receiver is invalid.\n     */\n    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);\n\n    /**\n     * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The royalty receiver for `tokenId` is invalid.\n     */\n    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @inheritdoc IERC2981\n     */\n    function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256) {\n        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];\n\n        if (royalty.receiver == address(0)) {\n            royalty = _defaultRoyaltyInfo;\n        }\n\n        uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();\n\n        return (royalty.receiver, royaltyAmount);\n    }\n\n    /**\n     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a\n     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an\n     * override.\n     */\n    function _feeDenominator() internal pure virtual returns (uint96) {\n        return 10000;\n    }\n\n    /**\n     * @dev Sets the royalty information that all ids in this contract will default to.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));\n        }\n\n        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Removes default royalty information.\n     */\n    function _deleteDefaultRoyalty() internal virtual {\n        delete _defaultRoyaltyInfo;\n    }\n\n    /**\n     * @dev Sets the royalty information for a specific token id, overriding the global default.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));\n        }\n\n        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Resets royalty information for the token id back to the global default.\n     */\n    function _resetTokenRoyalty(uint256 tokenId) internal virtual {\n        delete _tokenRoyaltyInfo[tokenId];\n    }\n}\n\n// File: @openzeppelin/contracts/access/Ownable.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n\n// File: @openzeppelin/contracts/utils/Base64.sol\n// OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol)\n\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n */\nlibrary Base64 {\n    /**\n     * @dev Base64 Encoding/Decoding Table\n     */\n    string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\n     */\n    function encode(bytes memory data) internal pure returns (string memory) {\n        /**\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n         */\n        if (data.length == 0) return \"\";\n\n        // Loads the table into memory\n        string memory table = _TABLE;\n\n        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n        // and split into 4 numbers of 6 bits.\n        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n        // - `data.length + 2`  -> Round up\n        // - `/ 3`              -> Number of 3-bytes chunks\n        // - `4 *`              -> 4 characters for each chunk\n        string memory result = new string(4 * ((data.length + 2) / 3));\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Prepare the lookup table (skip the first \"length\" byte)\n            let tablePtr := add(table, 1)\n\n            // Prepare result pointer, jump over length\n            let resultPtr := add(result, 0x20)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n\n            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and\n            // set it to zero to make sure no dirty bytes are read in that section.\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n\n            // Run over the input, 3 bytes at a time\n            for {\n\n            } lt(dataPtr, endPtr) {\n\n            } {\n                // Advance 3 bytes\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n\n                // To write each character, shift the 3 byte (24 bits) chunk\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.\n                // Use this as an index into the lookup table, mload an entire word\n                // so the desired character is in the least significant byte, and\n                // mstore8 this least significant byte into the result and continue.\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n            }\n\n            // Reset the value that was cached\n            mstore(afterPtr, afterCache)\n\n            // When data `bytes` is not exactly 3 bytes long\n            // it is padded with `=` characters at the end\n            switch mod(mload(data), 3)\n            case 1 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n                mstore8(sub(resultPtr, 2), 0x3d)\n            }\n            case 2 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n            }\n        }\n\n        return result;\n    }\n}\n\n// File: Plutoko.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Plutoko - 6655 Cheerful Pluto sprite kid with icy glacier skin and astronaut collar in a violet starfield for .ai Agent ID holders on BNB Chain\n/// @notice Each wallet gets its first mint free while the 348 free pool lasts (gas only).\n/// Every other mint costs 0.00005 BNB. Max 50 per wallet, 6655 total. Collectible only, not an investment.\n/// @dev Art and metadata are generated fully on-chain from each token id. No IPFS, no reveal, nothing to set after deploy.\ncontract Plutoko is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 6655;\n    uint256 public constant FREE_SUPPLY = 348;\n    uint256 public constant FREE_PER_WALLET = 1;\n    uint256 public constant MAX_PER_WALLET = 50;\n    uint256 public constant PRICE = 0.00005 ether;\n\n    uint256 public totalSupply;\n    uint256 public freeClaimed;\n    bool public mintOpen = true;\n    mapping(address => uint256) public mintedBy;\n    mapping(address => uint256) public freeUsed;\n\n    error NoAgentId();\n    error OnlyWallets();\n    error MintClosed();\n    error BadQuantity();\n    error SoldOut();\n    error WalletLimit();\n    error WrongPayment();\n    error WithdrawFailed();\n\n    event Launched(address indexed to, uint256 indexed tokenId, string agent);\n\n    /// @notice Contract whose runtime code holds the artwork bytes (WebP), after a leading 0x00 STOP byte.\n    address public immutable IMAGE;\n\n    /// @dev The WebP artwork is embedded in this source and written, in this same deploy transaction,\n    /// into a small storage contract (runtime = 0x00 STOP byte + image bytes) owned by nobody.\n    constructor(address initialOwner) ERC721(\"Plutoko\", \"PLUTOKO\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"52494646cc3400005745425056503820c0340000d02d019d012a900190013ec156a44d27a4abb429f46bca8018094ddb1f0c3d191e8e06c4ce4c4f3fbcd7c5a8d10c2f83ea37fb2fa4b74aee753ddabf5c4f44db16199536f286b6b5203507fb49afbfc5afe076383539a357c7db98a4815d0cb329486cc4c98e5be1c0e6322a145e6d7ccefb894ee3da80369be14ead50fe9282bb1bab0be27a5f3bdfba7e8c9664cb52abf1949a12d75992def8a80e71b705e1f5dfcf44b4b7f4e012631443a7bdd195ba6d63688122f46358dd6b31e1c80f522d90ebfb8a08410d2f9177d920adf0093f994249d6602bf4f7a6ad0bb55c1df163ad7c17921a0b5bf993d34e7992ba0b86e32e981d030ffebd3a69af1d5cab111f3b9e50d01db5777c274bc98aecfcfff3510d2710cacb5582c5905e83efbb6759cc5acb799be1a1965176eb3548c13428bf4b0bfc2f2ec1c40f7695e42356d5c72397dd2b4f4a55b55409b6e436347e332dc9d5ae405a25ff6ea8e7f4b68428849e7b9ccee2431b313ea6b0580af92c71fe2e94bb7eda5b813f420edc88fa67beebdb96a5c02ca5af185e7a722249ae4ed5563438dcfe98c88890ee0df341581adb284bc6bd85fb8eb78aee069d9fa57f5a471cf5930cc6459c4ba10bc7471a1ace692c2505e60484798ed14b495f732c837b8de1a841709244a9f25cd02b203d0eb60058ed5140f1bddb12f391a7968406d91c5bd9c083a8b533e423c0879de953e7012701d590a66956b1fb8d4af8fe1c021bc91b5f68463c1f282b83a50254af2018512de31ff708153347a018ed172823e7a236ecb8417b84cc80ec3aca9f9fa0bcd393d466e4282e27e30e9dcee732bd2c0fa8d4e623a1fec63e25781db560688faf72f99875c4e7fcc05df2bb6cc5c088eef970d65d5c7750500e90e142bd6b8546d5d974eaf7c658d1509cfdc5c99aa9f341215b9b76e1233928f241fe48ef118be89b4b784dfc7c27c2927e04af603270874e94d200803c70ee42046d85855cad71342afb35930fad297336411623d5795178d4bbaaeaa72253acf0f206e148e65b90d467f58fdd06bc8f5640d853ae3ff643bf7c064260524c145396cfd2f867298c92aa1f77558e4f336d2dcf937df3b2ea8327019b9bdc5f682351061448349523856617429ad18cdc851d4f5ceb01a001e0442e7210b628bde3e6a81a7dfb5c9d365100e3647fbba83eb8127c0d803e9d6400d3170423fbc3c12310a2c1cb04cb7ce01f77c1ea7a275500a3a900998b78cf930bf528ec339f2e34ce4cddb4118c4d0b3754d9b1baca6b96bca2790f9ffe23b57fd6d09fe5fe198eddfe2bdee8bc78f380297449ed401d7093d59f2fe9d5eb169f4a7e753f4ef40b49c30519a3725db637acacaefc8cee810a4aa09995fd1d92ed7c7be38c693d31193d423160b5dbef4082ff722b42ccda08b4a104512ad808c6a8c3e7ce53f972bafc353e445ebf43053a0cb674384735872d84cf5ea2b570d76ff8eea428558f78565bd921f736aa50beceedd679a56be8aa06d079fa008cc14a196fe9e2059c127d3e91b5ecece79478b93b84e4b3cc60f8218ac759e64299e593e04bf62d23d0def1a816067c446c191624b68ba1314535172cd869d9df1838ee3429532fe303db3a664fa32b0e60e947996b8d456b605eacb665de37af05b889f3e76119d0da7ba83d7fcc7d4523520abf227887f66777f5e2667f530ee7993bc4c61037ee870b736960aafea4653be98b5ff694c118a09b967cb4fc3f769a559ecfd4fd21080d7ca810e8ed528a602e58b4b5595288e4eebf99384912c2a6e358353eb80d4935e8db6009c677481d204a7f43a330378aba1cdd2218ba5e7d7839f55e77ccc60d539f7bc655080f654c496c8cb26c24a3f13b2774661b4ac20a09f2455f46f0fa5490db113fc836055689392461b9e3d5c64163592aaee8265bb0b7f7af245678c964592bde56c9cfa5c05fecb144b3e95b37393dd7efb95a410848fc4c7d2bef53f2ddd43399147417bfa73efc85678712bf1f752e9cf5b97e12559053d21bd88ebf7f504febf44767f7461901a463c5203b8f45866e765bba56a7cfff933b0ff4c692b4aada40c4a77d499dbf75b21f851477856286211d83bb5f82e6e4baf894e495740143995b57b270d591f539e97e1142285ac909f455e394ff485eaa10c6b0c35f6b3517045612838d0081b9d381e7285f9324a96ef9300d4fb5c26909123e4aec868bf89421bdf96fddc4cc447fe41f6f6d7f89faf65105935ce3871fefe907cf9201b5c1b969d62c58870b95b73048b0555cdd9f89c842be879140734586f9d0ba0e97fda7c2f8da659d6c417ade2d32974998dafd8858b43026bc9a98f2eb33ba3390c395e6efd131ff1c48a936a3f8b6458f43fa974d3249caffca60252f99d2eee2aabab5ebefd1541577ce2d0c7220925e63329870e840d5dfa4a49e765a49fe373c4a6e99b60fc5450915ef5e39e39a95839d0c5a8d395bfcf87f69cefe237f785e2015a25879a5aad684e60af2cd897359c61c36ac6a716707e58282ecf9ad9c3ff4d7ea1f98785a0a40ce799c1d49a0e8f1e8d521d0a36ad5ce5883657502a2559d3d07838dab7e8a67c79e368a0c7f07a6bfe0c7feaf8366aed5106d2c44642c87c37398acf5766e1181b182ab0fb217bd895c3e9284ef340275a49b42c887f2d7d82aabd6a92a828670e60371307cdf425c5bbedf80448d779320c0fc3e2a8aca9d81451b8bfd8ee9fbc2d9c232b343ad259a3aeba35da11887006adc7eac127f5b12483b84661ac51184055de7cc7f2c13ce3bbaa58824a0a28e28302907f2f53634027fd74f1c45f1941f420eea84957d762ce6f36bc018c55f4d7b279d362ac9ead8081e970f7246b26fc9caefb51c775de966c681cddfc7ba1908fc68b375f2b552c73d1df5333a95cc21602dedc293aeb3f91fb7b41118c4abaf6dd1a8020f89ba3dd47a46d38a7e19702d80c549f481b96854a8faa4351c41a21351176f92278e36b0caa80a2f631e165fb9f11134b57690a6c014f6b98b0f9120deee084c693415fea4dbddae7733c9bdc049c3a78425a1c8a1ff5561e1a13f68d3f931b9e8cd5717718bc676cecd60e074b5c7a0a7306b69ffd19819ac9953f851f8c74b701f24605b40d054bc543b146f3281f5f25a7cf2bc5d8e1772c2e003cb1ba790cdcc29067a8ed22bd057e2f338248d7cfaf3c796ed5096c92a4e123f04f6e45f84eda0f095a097114001290b77c0e6ba63e4d1287c1b03c6d01dc4bbcabe380d3ba9522bd68bb05e20ec7516f1dcd344fea4c9d03b566197a50be78833fc1279e76b31f13da572503f01d9f6df97c78cb353b9078024c0f544bc567119689fa1324fbcbb2108ace1d49c08c5ff30d8e7a4cc512e84174b3286f8fa41d38647cada9a4444f0fd7318f88000fef735abbd8440839c04d77b1395859594e5086d4442881bb0c03beede18887000edf554ef5cf5634e3b4314c15bd196b774b003a883984d30ce019a271b6092dbd45347c4a6a8a4f04b4a99ebedcaec1df8843c3f53d2deb4d3add46c05ffa0b17134af8cbe4ff34849bd8d1c7719bbb95b587ff94e8b600c25c5ed9e80df7d288b9a23b242ccf3b8639e04f878955ab522b46359f78594aa32afa7a11ec23744516e445f85769e91b517a950211fbbd3d6609e546d4cfc2ca49fcd2e4e89dc36a2af0b6fe8c3d433f3ec948a760d500ef2df5633053724033d0302b771459c74b9c7537cf037abd702fa9a76c5ee01effafacba1fe18fc4904de96815397ef882eb470c6c1d18d9dc9213814b2daaa00275e3323e1da1947ef9c6e3b73ff3a39702436c6fdfe3ea201b4643e70135a228f704e78269a3531dac6c3fb3fc5f53ec1defd60ad1e44734479c90f4d071c55fc3ee95746db4b5ee32b90af540610962f60774719fa406ccf07ad21cf1ef72bb15b6c6249cee8197af24a806dc518529bb5100226fe8a75c31442a125824e830da4f1e7c01c24e1288710381c75bc2dfe5676eae468ac0aa3afd176d2ece1505dfc9789878593a5266f2b1a3b0027690c5e292b6e0ebe4680ef546909a5f17ddd8ece330e52425bf0ad2e8d4ed55bdf903e7dcc2dcbe677191d83ad4db3adea9f60cb013c02613b6709972557c671d4aa6a120194db48190d2cf33468e323e9855bbc2c286edf4f125a0b563db6890ffeb347b1aaaa98fe93195b93c66f8b44247e3296d0b2bd56f852ef16be342ba6a645ce38ba4792afc7ddca518c36b36af93a316d292154888b7a04112929b4247de3bce4993337a8839dfbb0cbb72143d6de42a809cb9f852ca70f0c50e5a3d62c1df96dce3d4c202f1e048e9abf4111b07a1a579056da07edd5575727ae0c59c8e4d66f658b947c332f2308552a95bc474a4664e1a706800ac992f24d38c687d7c8dcb0efd21e7c5f786d4b2ff83aed8c1c7cd35e101c81d09b8bec15d963ecdec0528830bd42c7effa20f6c467475612e9abc5ccfeedf48faed5574b79ee814d2806bdff3415c12ef1e1d3d7dbf3b4d236ef804d74504da0509399ec0a8b6e1b598505aad436e3678a25bcffb0a9b629582ffb9face8a8bde90580970bb3f13093fbc24866255e6b1db14938321978fe8564f1988eb996ccd73f334391fca949f8fe7f2367f12c4e235a75835de7ba640b7889db0446ec10fbffe5b61e74acecce5188c877104ae582db74eefb49120c0f69c410b0972a58f32884bafe20a695f8ec5f255acb4273f09c640c36a59f0b55b0331368477b9359b6218babf79a265c7c523bf88a89ef4cceed56e3f42ec7ff48848bdeb4dcb4854d0f4d6601a54da6df9170853ecbc5ae0687c8ecbfcf691f6b7e778ba73223e141c318a4036898ccddb23fe4ce7eb94a5354eed61d8531b3a541d0db0d16a241c1d708f22167f7399472f269b6ce1cc6ddeaad2f38daab9f7a6db1f7174a4ff3b3d188e8afa393e43b0bc2bf612db8489632eded9fae58a7f66dd5099f039ab240d881bc3860407ca6f7aa93b3dc6e00b6811e53be422e0fb28c516355a85dd126433511f5a7eab84971a9c81980523897bc5fcf37a600422968d08341e331d16dfd4eff414687404f1de370bad54a563fc2a5e0ccf84210ea1d7ea38f96afefc4d699c3debbd0452a85d53065b8a6804e7f2c0e5d61e580ecf20ac1ab371a6ff3a277be146dd5a3874d50ec4da4264d6e6f07dfe4d8556161be02999710fbcd09bc00b695fa6c581be0dd404d53be624f8666fd5849934933d0d7fb05d4bf608cb5099ade76c2096f4ade98e60639f5ab1d40d1eccde6c56d6f3ba3dbfdf7865be6f5e5d00675bf6bab142a19e613ba4123e8362e8051ed5898ab73d5516f683e14344afbacdb96f9ec6f663e131ca9c8b59bf0b7f192a82f451f19a070c3b27a301f1fa37f7d9db19e02a1c2b6f4001709b4b4e881e60046398f148d7d1747821ce1b73835e3e9020464e6e97e52d79e54c8dff8892cc01af5e89360f8cbbeb72a5d91a7ef003984abbfc8501ff50a69a0d290485e94991f7b067483b098e50b507df7d1ca357c6f9c7e3ce80d9f6526fb6f2035af4ae3b7398ade8f0a6d9bd6180bde606a0cec7adab8a640f142760e871350e54315f96334f35846bc5058d71e37aa6a455e4ad17f0a6b77a7c485363bd0eb3b4f5b8f88f96b611562f3abe2a52362589a45ed78cb911c55902b06685a24608e6a14c406d031a82d2c681ae6bbaba5249b249ccb0a723148b77e20ed07be99c21e3adcab721138c85293d78a6c48c464a290390604eb49d5a81ff5be046f63eb97fcaea0fbc8680bc7e6dd7e23be933a3cc710c5bf8db482a507f6c7ba29ed274d4b4614d478df4782ce74912c015ca9b6b23c25c9eaa0c21ebab8198b1747c8efc92049367721aaa97bc97b029db0d8cdebc7a95bff8750620d86d3bf824f6b27b8a51d8ae4c9fefa69b1ed49bba73bfea295545723d6306730d815370634b45a99cbe693f449de06ef966ca1cf7b59ddc5a5f1fec678906a6ed827a8516f0d46c9399df84a285f7a46854b27e71b1ca17754a7d936b01b5b3568ef72393f95c57bf93bc7baed771526d4b21bf2130e80c12ae781a124470a901eca20fbbe9fe043f189517b64462afacb8221fb7692d39042622a0420f1fecaa2b4620b5448d0903b754144711ee0b52f909c0b04aee3bf2cab4cacb6765b315dd3a8c0fa2e052f1cf6e84fe673bc02c5884009f5c6d8cc266e410146e968cfa83b8de3d8109a4f32aa83392f223a54d3b66c9fa9a20274b2262bb7446b15f47966911a4b31d2787fc612adefbc3c9cf307eb62e15755e8112a017fc32973d606d76930efd2bf09bfd49bba911d43eac070fb7b5feae79ee1ef2dddf99b21fcaded9d1893c19004aba46d211bdc3df4106106814bed6175eb8defc8b5661d06f6313d9cd6f509994d4fecc7bfb07082131f5dc7c19b155d473fc5177a56c05eb787281f1b713dc58a82bf3002c80f6627536bdeb542ea3046bdfede61e1853a49ba954a91d3ddd2618f49411c38f06968683b546ab95b2ebca6277baf55ccfc35c82c35daa0c67702b7fcdc5c74fcc4553a56b4f998a3f4ae2b71d7148d61b69f16c4ba466eb4ce7e745a7819cd12ca75a85d3e031e820db3d570a34e5f1162914df7ecd9ff04a09dbb784b595166ff0bed31de768f89f47ccf1e5505035e205ae149b2a39a73d781bd4227c845a8050e15a6b1adf011e9be33743054c7619cb0f43b17f1ba2dc14503980317f35f1250932c3505f8b0eb200d62f1c8abc8777c7a0ad6bd364b1e2688bb41f53dd07354ec201752e430b678764b01fdb9b4e44e1c2408c992605809e0b8d41997be4c52b14216015b74223a1bdf3f35a1de414161982cf79c0b1f7365d962326c7a063b139fe3ecee63dd1d4d7035a3c8802c0df50acbf5e1d251d1adbad594294d17171e96006cb5237048e6e49f25e478ebe21d68afe51fb4f5ed5ac50667b3d9711dfcc9e910f63187d845129e66bd850ee8f8c509768920b7d1fbe21e846aebe7e5bf573cec11885fe0ef307dfb166301ce71696a99bd7255a11606e9f6eef2d12a1a188328b2b057c658d4c0ffc70502102ab683dc9ccc9709f2e0c9eb198e85d0bf123186b21954972c6a1bdd0f9e9342c5619cc44c33aee2f99eda876e8f99df2490122914274fbbb52cb4f16f051eb9d40475a9cf8b9525e24d183bfccbbae6b1bf3dcd2733a26d5ac07a68f168c4264c571940a299f78e560ebf5bd2ab37e828e959609ed9e85b5dfa51770a40163078ac630567db4c75b22e04d105c3c80421373c971013ef80c0efcbb3d384f6c9d2d359f1beb0857b3338683a24a4f9a9b9febd9debb160f005c8dbd17dc7c21bfe0f04e5db06194cc54d08320b280f73e50d320b0e2b8e3e4ce18686aa86a11d90c9027570cff54f22b41aa986d9365e8635dd8d711e24e2bda93e60eaf0349113c0275f4e3787b44542b0351817df2f3098fccc21de4335a071de02663281e2c2ad07938697189b577e7dcbd20ea52426cbcf7af107acedf9e633056a3d672aabef1f0e30b9e5beb8d9d9f26f5d7311260365414574d317ca169a0cb10e5d9a31b9fe37857d51fe18543434a8b06241a98ef7d88450c6820ca84214b0060fb5bc688264ed69bf2e0d5efd66565aa622b7b9aeabd88a3c6d24e4d01d61c11d17b40a4ed595d3813907c35f7598cb8fe36b310ab86a5d6756545cba534006887558a3aad15f545c74933d33010aa4a9cf19d6a75802eba673d14a8c0283c53f930dfd014580feb47bca5a1c2ac92d423b9bca8330ea2e6909108a70eec899db15cbe89a19ca32ae8ac49fda34722bcc6825211425d7b34da07a19302308c87675d72d42618a44ba39b273771b0d2b40d03a752f63fe8c59417dba7c7abe5665473c37509aa3de96ef3303fa558776d7e4655d06b32b0fa2c5b2bda308cdb9006e6f8d4da6dfd1c9b288f63b65093423a2b56a57a3aad34a82be43dad6d1324051de8af7d92bce9687d6bb33845cbe1bd1d709c846b3b8714530aac2ddd1ce3124082d6631364d23850685db5a0ed51e583e597a9f9fdefdaa14cd0281d03df4f3047e05cc64a8e4a1cfa5e756f2b993a32429f34b01e5becd8f43ae207d820376810086621b2e15e1aee3ec56d7cfd57551b8abad7ce5802c2afcd842e0d816eefa1fd56a3ffd993aa787abc66191840b6e890fa00e68cc05909c5f0c75aa4a7e3d066624e434873eac9e61157d1f77dd7cb7cc1b5f7c96a50d2e590f6d7b94eb9e19c6969a7c0e1dd44732c37f32d4259b19c2366de6af1430557451b3d7a73760d823e96c406d229d7fc86903b296e7b3ba5fc0b27a2428909c835d678a0e81e203477344e92f78665f6fdc7091924ca640ad66f7bf7a0aec3da67c5bdbc1895b943b27abb8b8aec4d0e035b391c3e6576484df205209fd6af712a1609ec97a2b4aa3671b82b4b4dbd0045408fa47b2188b78edb3e078d653a9d7c3e5c8651aa77e4c1f6b7c6464e0207a01368aab16f2a9b1884597ffcabfea86bb7b9cea8558c17d4d8e0889ac7f47fcd71363965f947cd1361db3420bf86d7561a2205b9d5f88c72969b9f9cafa7251b45d52de77a76cc1c1fb9ddb60412b15fc28f93617d13aa9dbbb5a29c9d4dd610f2e003cac1f925a1a6ea1fb1dda6b1cb7b86ad7d261646c7e7bf8fea1e13d6bd8a1bb33ba95b9b088003d5beb6b446731879c1632a9f680c8c42839dc1004d06162ac4202bdbf2ecea147e06cf325e60ec8555e2d46b32737c658a93553e427a2d026ab291467079c0435c0e2162a69706cc9b4a562ebefec09a1bd20af92f96ff17b081d71a4952cb3edd2221f5a48e4b167147f3bcff4a488a628fdc291ce6f232fc47f45a6d55f7c00588aa04b896ce8ef6bb55973713b9e1f16261ed98ba0f0d40d5ae8f8bdddc1ffa6d5436133da9f80878dafa157d16b4c738cdd141918ea672b6c629078e69a5a08585d81365496572bc44cd56977d1ac0e333c6ff7172ae5f91fc0aa557ce8244d4994bd7c01738b2e4975438705f7d9e1fa4c2065d626836dc2e60271ab4b695b6cffb0a5070b87f7ad8c8e8799393aca680394bd9abff4344b823d39ebf3b99f25afa8372532fc7f787528cc82b6a283ca852c203f30cfe434cad0f52096af1e7cff5e46275ff9e313720d6e15f838e4af6d623fbca44ecde514a519913af5e527d560f48f97a6398e790b9ea4a6de2a3c9e453a8ba6d0bdf5d706b85cdb253bfc525eb98c1251546934c5833809b4a19dce79846a76782154d2424a0cdf26d3e9dd4223394e44f37c4c4ea12f8b4baf12afa09a31e0fdeb852cc7771d1f956b668ae38c2c8567c72c8c7ee9b3a40c8a07617789ddfa0a5fb7b5d7f12d8e546d1aa7ed95ed44e1c8551d6e87bf478a68b4e1a3a2c7a3d7bc64adaebf782c897351539d8fe62c5bb641d27a419f7a17cab2bf3559e79a8e9947c0eeea9f65770f73dffef607abeeae2adba3cb07a6ee98946c08e11f8d17d683a66580a1d9e606b67a520a600d774b7b0e59b51e51636c0796cb63cf9c660742e286e95482a657201552627d7a8a83b50a0e6fe2dc3e149fc2b25ef7ddb0fbb9917b2176eddc7bafadd334395d5b216f43983a3a5477fe50172409fc10c4c08ab188a9abcd3336962676dad1b13249249e45fd81e3006f8ff7a7c5066a7e4e067f7cc98d8ef28130e6952037fd6d5d361d2b563a4f2c3cb0f5a05a75fee6cf2c01c54fa88cec6d72ed24b0c7dbb4e253dd97707d80b568bda2c980136f95cabef7f024679e185ac7bc66d67209f9c3eb00b87a4b1569f36565604ef44ed049e55103ff5c3a7e51746259bd570495bd58fdb334ce7f8f47bb821663e90e6e5d39c1a5c02f3d43c7d186b94d6fa69b4ff931c051ed6a12add9a94b36979ee3be993cfd62e6c8773fa79f3c69f7c6ca391bfaa476b0b811d4a58059bd3167c16bb01f12d1eaf9310b35fe749e6de019d21137721c72cfbadad76762a2fe426c8d36d79063ee798a8d6486b04057e17fcc32ab54e935771ff9e903292b2a3bc89d519feb93cb04cf9dfcffd77ebb919fad7462643c78a84a239cc280be759e71830626e26aa0e732826a157c6591aea9c95699982fd95d0e0b93276f4cc867ab5f5f4b814bfe7e84ec87331cc6b5a00fe5d52b60ed7dae25562654068655d5c2a06102cd638489a44f4ae06dea189365aee78a83899559493edea98cdd8325acfe417b57d1e118ecb697b66aba2b5f71b1b29647f61726964ab97714423fe81884643e11e114823644f07c323acf44e67411047e13af38b89e04ca8438d18b5f74727b7b7061082b96544a78f736d077a132d311158b33a5062c62ffe5a16bcfe2ca6599ad092a6ca5f373f0d724c3447867a4824ba913acfe4211edbe6274e81698f131d55adb9958506bf6a94e02f676589daeacfc3a4702331fcbac9ea6ba70c18762aec7b982ee2584a1687b45c228dd18dbca2fb788c6b47bb0a52b424be02b730fce29e20712af316f007fbc2d3724fa88711b5da5f797cc2010555090b67ec60b55ec6e400fc0042029ab2db404219e946eed196c51455668d36aeea47876ac9878eafdcf9e05f905a8e3e974faaecfc6397e88890dfa22668588b043a157f7aacb63d86ce1ced576b4f92162ed1360fd86cccc46fe8fa8b728ad448e14cdf9c97a9977c34ff71682f818a9a59cc490d257c38430b6e2abece8019f34a47781a560d31b125ad454aa8901980c91fb799b3c0fa3d4ef8ae05b7b70095d64840fe19f3f901a3cc22d627503add04ea8b3bf7e3aa7d077457a64e9e6923854bd3407ad16ac889f0d3e05d808612b9d776bf6bf7f98450e3ac8b7160d8c4b26548afe94a5c3d1a25a156f3b8c7eeec834fe522383e1966c30bf32e8318e1bcd48f02910b60399de3f3c8172e5476c894b2d3f92adfd5c2f4432c9d2bc6ed6a0a8f02735d821c18ee73fae7873acdbd5ce5dfedf8229106149adf1f6fa23cdcfa0881a8f83cf62e6d7196f835db002a536439dcf617cf54df6732bef0b255780577a04c9f188e7028d18d9f493027729e625d660b8ea869f85a671636bb882cad13ff35f7b1e18125c10ac76d16282a69716125da7ac58b2ce58005eed87d1d2947fb20f30d6cdfe73d5db1e5d409df0e68404e70d9fcd0d3e67f7aad8df466a5df6918547e593eb399d2a1884c366ff67e5345ec14246c31990826e95c7afa26d182d4bf5720ca9ad78ee885ade385833d37be4a3a5aaf2eb5911726196264bf83b6fec825db5c651c51e8a8f791c27e0c9631c48101bb6e7b31d89a76a6a40eb9340086738685bd82004ba5ccb68a05e53c3281aa4b3282b71006c0fe281561791cf8b8bd317c7bbeffd692d3477310fb18a25ce01e1819bd47e2f685ed2d92329228b6d05c8a0cfede1b5993e9474c65c95556f6df7112f213e3bdff2ca9a7b9cd4b0d1a9379a17e0ecb3011172a0abd8342bbde625cab54baa1846f30ee8f9296c6ddc63658ae1ef66fc1a3225002e0e185a5f7bd4cc0fa2010b74364ccd22b5f0ead08c3da40503c950f23cb6f45954ea68ca769ccd607569fdcf8e9ded83c09ee67584bc01caf0131b9c50722318b1e2d9563007774d70bac2f3a2299390e2800ed5ff203a3d42756848562bff5e7608a7ab89b5aaf110e007b27ce7ecf98369cd4eda1cafe4b7e056864cab42176ea4bc62b01f1720021500264d5880535459537f7fe0d1d01323cdd192bdd97eca82405140e0bc3752eff5fe1dd7d20a2aa57e1722596ff820db982c809bb5d33b4b547ef93208b5a2e79e3f40c4437472e9a290db9d071be8bc8b5c277ab3a023e8c8b66331a850ce5ac5d86f5ae84a6018287f964bee51c106182a01d49dbb6b639f130886fb2ab982d849779983007c41d8803705f6ddbeb1695a0993ff49e6625c2a544c54dba0288c2b691879edccfd4dcb9a17dc10ab05ce38131ea7ee0ca2b50349b1f6bb20a60aef38e4ba3174a6cf070efc40676a3fd5ba45aa5f1f401daa3bd500edac3c927a4ba83274dcedc97eeac0763747682f4d0aad98f3731ec767359ab17158c01bb87a975d5457d8e3049ded064def13384f2c52d44d537d64150c8757cf559fb2c62091832c7c13717cabc8aba1bf6682e1752b51f9bdc1d5080053b1d2a87f2a39a3da0f960fa8b853c50a833c64655c273af0483f9c3b20a5e04f4a56edbcd608a32e2e867bb3bad57b65e3cc17d0f852bf7aeb6d96798c285224e659ff9149ec926cdc0f10f86cd20188122da781ba00a25620ac7f5405d0cda4479f764a83ed29a8cee389643560911c4fdec361e84279c0aae57a062110fd289d20b66b275fa967dcb8e7ec3a95a09d617afe831d48f8039577c15c09365c9f6a9545ff6547cc6e5b7191b3ba0536f827238ccde6f6b74007e39c96ade669d1598a743d847d3cbafb5456b061fb193452e4733b694ad686a011088019c19721bfb6dfd376f43b4ac4e699cd67755a9ec92088cc5acdc0e091c19a7b16c744695c7bb64a3c0b363163ddd20ad422c17656a24e6c1f01c61711dbbac328ad57a562c6495b3e6aa9fd3cd30d511aad93ad3b86314ba432c3a31223c5ab1bd8dc02c297ce4d8a06596b3900b7a79c67b81017998df46e1479c19c470f82109d9001aecc2b10ccd5c2db40c5e3553d2cc851cadd8970d4e8e967cab7d265efaf81d0b51865e2e14511a3a774dd300a8ddca14d2ec0c12030b3c1b99fb06a859a9a2fbac1633808d8b2f3d89cbad39e88836c6b1c234d04a4e3e00da3eb262d47e19b7ddd9472b25b6ce0bf41251b7c400df513b6c08e29b86dbb24973ee19ef3675fbdf4a6d5dd9e502a0e33a4293e3122f02d90748de59f2ad1f4862a6cf0920e44a576afca55a9c76e7178a1f5e6cf8bce17c856d17e5210e8275ebd4e273d598fd25b171fd8225a7c707156ba7f8c8e7498ddc98d4a2c885b716449b35e8532ab2d9e95a4ec54d1d3165d46602cf92a2b4912b6f4f767e35abcfa44f4a5f2e9ec59ec43bc39020d74fbaefd30a245459410932dba3147cc63460f946d994ea244dc077126383eed2af3be9e79dded7b48f808f82267de6f3b839e505158557a7802e767d77350e0153ad8450a9576474a770b8cd95118b30b90e53ce5c80e6147f9a07c49a3838b195d5f8c47d4d528d96f91db6df9f35f54e64e1f151657c35773d726ab861063f0f9c73a4fceef0a77ebdbaa5c9a754f211f7b1fda41e7c5bbd8324930495ddf62acdda3f33b5f21f5a4203b700e1ab836d77a85b24bf26be26d353548516318a3f4971c2e6c2c64e2e404605500e9f9e3899356d10cb8b8977fc7935b9041dcde26941fca8576f84f22be5d7f2b7be67e1af96786aca385f7e2da29229126c434dffb159d0e790b89238152f25832eb0a64ebfad227b9c10de6621fd806581e19540c964c73e50151866f0f004ea9e1671f8b96bdcbc8166a913fbc429a6beec2c39a1fe08616251eedc8af3eaeb9ab9edcfe038c97bb056259e09307cbf94cbfb83b6bb5fdd6950df98e358d940282efcf2088ea746957bd400dec9a0b538a8dd3f0d07c2245c454b4a165e14ee5c9ab7f7ac81ac34101b6f56f7623d269d975be30ddf1e9011322ea21358178c9e5394a1e1dfcb1f704848154bba802c086018286078bdb3c0a9b4b67c4d0ead1455c160aab98734de0919c0059c2a27bb70d103b297192e7aedbb3249c3926fe08eccacab092f18ca85aedee70a4a18c32c6926407709bf6e57b42b5a502184093aed9712ba3c8ae2994f9402e09d0ff9a472250dd2fb87beac41b1eb7121df6451461fcdee02e5e26f7047151f72407157dbcd53b5976cf506b8a7a17f6887d3d3c57f85dc939beca56940d93f699c7d5bf079b21e886c2c447c05d0ee476b21ee26c2585bfacc2f1ba9be9638c9ab60c18b39918ba8a9f959458076947a498f7e69d99079308c1018df7e60c51dbdb89f6a42c4ff0beb3587c41692cc78e662b2b5e0e78e6d2863d3dcd1577ef2adfc56b687613ee4daf7bde23175c85c9515e639f824f80d19a3c3ad3c48d9b6247acaab3f41491f173615af5753d57e6c3f5aacb6d0ce6de06749d7d8844759acccbb7c3a927a466e3229f4b3bc817d24f041d84473a853ddbda368fe588c4d547cbf867c1da11f91469e523703355bb0a3a815845616fc4ef6f9fdf23471e6597048718495aca233108cafefa895ba1acc94c923a3da5f263700bbcaf5aa90e7283c12efcc5d2736295ff33f0defcd0d2109e7fd57cfe2383d552d1cbbfd4888bc6252d331483d0030ff7a46156c4c1c9b1d4da8f81682ae20fc2342e3e8cb8e8b8d33df4c1abf00ea89a217af760eb65e54f947786194bff0c3e9d1a5fa80f6c52a494a2b4b18d5ffaab8adb676e25b8f21c333a757c43340020ed1d2f7c3c40badbea94e603429521722b9d59d7350738ec67e8bd641de6fb740617b02e6b93e577300698ba77d10b97cc92c291c6b6dda8e509c32bf67a630274cf955ababf80faa4ecf47261cdc84577c7619d1c5bb54821dd58023f56d5470030fa866f55639166167a304373c45b76265da774948dbb3318dc7eff0720b4e0038876c09a431a6dab31cc79f16aa3a68f38277308ba75ff7063a8eda5ed35e84095ff6dbb664b8c1012acf8a18857c325648952b1c45eceb3b2e7f43acb97c4e3c3f2e122ef188fbe5997c7aa1f5e7be5246d4c984b069d22f12dd6061a4eb57d940fa594b34eb4299a20ff9ba982bf4b1bde0cdf5be0133eecbe2ee9b1fb2425662a470ae0d6ff25988bbf0e0b5df05f7c09b0152d7e7637db748cef4e014cc470a7ff4f99d464b361b9b763e0b00a16f8d177514ba5a023f7556ff79f7273a39518d2626767d268610bdcfeb262464ee721c6c0e3e08c71842fbe490bef3f35197ab1107ec09881c9a7fa76113ede99d5327bca0159bcfa2a2de5cafcd6e2ea35d7425ba7740beace28ee5b3afc1fac22382b76616f91a4e713e3be19992c7100ce1709619f2271ca4f98b84967808ae09914dc4a61c0704215022b1573a8672079fa5d6c86f740eff1502a9db3a6cfe9d8951df1e3944d8bf2829feeccfbdb80d64e76adbd505537238c68957e5b2bb52a375b60e3e6db93a51d3d149e011c90b6abdb551c11904c4898202b7e5d737ca1c2acb19ec88dae4d9dc5722a6c8218658c26c8acc3276987bc3bc97d405c16824f9350bca25dc4e9275e491dce2859d968d1723f2c3c11ae785a65c6f27d107bc58e5eac9881c804b50452ce3f1d5e885ab94869079e381a27114c74021dde0473b51d2a1aafc4bfd0f226b9c7238422afd9fcd0f6c009c11dd0706d3e9bde3a4eb49d08bb00692b7145fd85c16a3175b2bb8fdd304d100c47761fb0c5ec6f39c70c56b8fad5bd68b7b956343c52a3e77e950aec81df7721d5757841a905033b2794d48bfd50d51406d07c676db8116c18e6b7df61d4bb1ee64ca99e0741cb47cdc3a6ac20be31482b2018267da8b4d350a380d3a80fad99738e8cda3f673f594b06e885fa02d34ba6efc8c8617841e297397a91b230a812bc654b6b02af352965da2a2c358669013abccf00ae7a6869d1699010f573ff26c07c0fc3ef0bccd1ac498b2eb1b37e064e376f9bdde207e4d5959e919cc3864482e517ec2e1a203c874fdef237e1ddc714d330433cd525c47e3ba1ba50fb189f2a92f4423efa2378bbafac4587273af07ceaf50d3bdad027afdeb2c90ca59b3e4e8631467c15e5055332d4fbd4071fa257a09b9e6149f9ded94e032ff432a03a69e6d9536f77024a8864bc29622fdb2c8cf0959ad15af1419f0452c7664cad770d979a6e6bcfe3b10a20472bbe457dc4412afa8652eb24fd45b8529848b0593860d6fe71343acc36e7ac8f0f9ab0a41c4e5fa6afece403dd0951d8d80d6a51787510a6c940b9772ed976972efa40b7446c60b4e9c03489e6e5007129606101151b640c3f7036b178daa542f8a640ba3425f9e3a29a939b59309f5825f11f0c081bace4ea5c6ce22c8e59cde004b2fdf7d3a36f7fcf9f81f79efa7134a9b6d56161701473b40abe700172485d6730306a258a93acbd09c1fa5453986be31940ced89272b665789796ba2fc6d334f7c2657aea7fb73022104e3be264dc8e7f488b30ed2216e355cd8ec45674ba5937414ec89f8bdbd4cb496a75b48393dc053c22aae9d011209197472ca9bb0bc0c3b048d1d372e136b764e892b1044c711b018f05a18da35c2e858f2e7255013f99a944a60368d4549daa93c8aceac3de317239b9a0b2817c9f78092e6c962ad70e8ee64309cd9ef4974334dbe5f2a14dc6333179439fce18c96ef9681c0033b5fc28769c760edb1de20682fd49f44a4e38d3ee15b4acf42339359025f9e487fb6cbf8d1311ec03b8740902a7cdc0c17b6271432b48426719f3366a21d47c0cd52a79e7cecb427c5e550e7b5b3fa2174e1b5e4267ddd41ba9fd027663e0bca68d47cf1c10487cee4eda0e7e0b67a6ad579dc34d808296fb7f97c2911dfe21a004081a84c82086a300429aff2793a658a99218810e3433020456b003193e845f7a9253f8166225858ddfdae57d35c74bf9a55d4cf65cad38350987f85fe4ed1bf9ffb8ddc9480f5231c8542595d0269651b3a3b3c471b17005ba5fa3e8ef1c66324a71bf492df68dbfc732d6b40a81bc5a2c4b337d262a1948c9da08cd0a32ae7618d2fc64b4323869c0e312837cc07908c91312486340d5252ab41ac71d20f39bfbeac14e31c80cffc283845717dd5d423642d3c974d1cfb1f6142d1dd0e1e9a53d8eea41e17862694f75c8cbad63fce5ba3c5b77c50d05049a89623c95c6913e6dcb284c49dbeea9baa35d4e5b20be1e9e104fe885cfe8c5c10e6f2f203cc4b00b07d3b10a7c1c826c52aa04cbbf610c4c7e541ac3e2368c3a04ba77bd7a19999da97f5a8becc2b6c25916a95c7020101f84bba33f65b26fa839b805b41c83e7fe1f67e978a1fb396fc66ef497659388203630167027eeb5e514e0ba2b488a349b50927223c18506c780bef12c0f34618c23a1e9ca128113bbbcebb72abf24217b7eef54bddfbb5caf75370e0c4c39300e8e365f0933646520e1463ff7a67f6d549f5e3ead421e39d81dff7c954f9a2bf49e28356ed889ab03f87805f8b6f7ca66d734c765359c8f60b61b841456cc146b71bd92c7135643afe42a2bd27ba5c3d4b485928c00aca20b8433d4d9fcc50a4c454070482bd539117e39bcbb4b4d9691ad2377eb4cba2cff7300f0e745f32a3fa4b4b800ad62daf34767a436f33d568693e5a4fc91154eeef904c4325a6568a8f99a7123d7f3e6e369a66f339399398e405f7b46bf536b9e0be7dd4f33136a1c276569194aa56098066ce904aa998fd3a35af765bfa6dcf9e30c220dc4d95850c1a6998589dfa96fc3cbe664137c7a60fb9d7b0949e0940efc58ceb5e1548cda7ea105cad0e119277a4bd5081c6681dc0de2da66e4b4f33e10bf90dcf2657927ab3145183ece590ace4f727c172b3dc14d0dc83be08c1faa1ee7e1c8c62f66d00fffc8b42a8f1ec1619603c3ef10b9ee447564179639ce9c922c9513c7f46eade04b229c92a954e61b65fbf037f3a431a08f13ca4b590e0555af2b5e33eccbb41fe0ba1f40f1884421f494e64e198a14847c3dd2f544f2a3bbb3dc2c9128a469e5be8ff7041fcd51c2ceb97c4ca4491b3da046710f88126336ef9fc24eb7d74ca87606dc146eed0715b62f6db704ac11849b83e7e46c590cf9990f72208125dafebf76b444debd66b7f3759e298ef1da873cd63058b65a1bfcd6d3baf398fc657c0bbd2cef53d980f0b631132d89b3f37f223126f9881bd1d1e703e457e8d0d4cc29d76950147371b94d8a8180f40735e88f8ea6ce0d3e24e62be3406bf3cf8416d380ef48810184e9a3dae623fba0b40a6eb629d9ccb8f87ee612f78fed92e3ec9857f04285388a5052892d199613f31f76c6b7cc0613da57aca4bd93395d45d31779fa0f0ac07fab93f5a36b4f2ca5e384ef52f5d611cdb750f202427914fe3a48fcc0fda432868375e2fb3c137e7924a4e6227a6ff584c8b3c59bec4ff26cf8fa7430f696510a1c06e707c84fd5ca68ace96bd4289614e1032def31a18751edc090b370af78179a41e219e5637a5740a686adf3cc9d3f961ae20d573fb6f7bd846eb2ac7d06489c2aed934b6f327f14f9611c930c0c73065cb42cecb93b38bf8a7af7cd541486d31370b0c77303b3cb3904cd27ed34ae6c62c2ec7086a79f188147af2d0ef1362d58f5b233d028947ad936f98ee2c82e9b6bf86c0c779772fe0c720adf6f8e029236b715c769f7bee0f9c8b15b25f93ab5b19bfb41337ea491173324dd489e0f0163eb8b4364bd80e57908cdb2d3b93f7ac652835dc60ea2bcdce8ea5a97fd78b4bdf3359a30cf0d9950ad0a75eaa00ccd53df08cffed439dd00bb4121b253edd28470523b51285e603081b4e7f8b45c590ca3fd671c4a2c312f8900aa31528307931b4d7442ccb04af4a91b7f695b7f7346e2383e1f8e93f94b2e0a7867e4b846e90612cb70e7239d54a08ae9e4613d0dfb380d5a9cc5f5ccae26b59a871fdcea53047429ea4e51b8e44d4669fc5c16fceb17761b0ec2f8774ad323bdff85344de285249f88b986b48ec62f623ec300dd03471bfd7e461e8993a95f1736e8edcd92c85487a57c8fd9d6b7d110e073152db6d1015adeeea3dd3e341afac9bdffc873efeefca59359c143b12661e826e657eb435b713ed45e1404dd56c84473e79808346815afcf3a4c3cd21f6cee682a9bf585af2b8f73faac99eefe9e50d58e5b3a90eabb794bfea011d2aa952f2fcafe15a09b13dc7b4dc0c012655595334df7b168b0f4d4a6b300e3b19f255a47d2407b70dd377e1cc41e42dbbf85d3a84fe4ba8b3c739c5e4ecaf6b50d7fc92a46762d291a13861e07d7b599f40641fb706293473036fc55cb559849922eb75f7c55f11a2dd9de4db1f8bee3ce619cd2137b500255dfd5ca4d5e0fcaae7f66ba068c1de8b303e750409af455c560c515323ff0dc000000\";\n        uint256 len = image_.length + 1;\n        require(len <= 24576, \"image too big\");\n        bytes memory code = abi.encodePacked(hex\"61\", uint16(len), hex\"80600c6000396000f300\", image_);\n        address a;\n        assembly {\n            a := create(0, add(code, 32), mload(code))\n        }\n        require(a != address(0), \"image store failed\");\n        IMAGE = a;\n        _setDefaultRoyalty(initialOwner, 500); // 5%\n    }\n\n    /// @notice How many of `qty` mints would be free for this wallet right now.\n    function freeFor(address wallet, uint256 qty) public view returns (uint256 n) {\n        uint256 w = FREE_PER_WALLET - freeUsed[wallet];\n        uint256 p = FREE_SUPPLY - freeClaimed;\n        n = w < p ? w : p;\n        if (qty < n) n = qty;\n    }\n\n    /// @notice Free mints this wallet still has (limited by the remaining free pool).\n    function freeLeft(address wallet) external view returns (uint256) {\n        return freeFor(wallet, FREE_PER_WALLET);\n    }\n\n    /// @notice Exact BNB (wei) a wallet must send to mint qty.\n    function quote(address wallet, uint256 qty) public view returns (uint256) {\n        return (qty - freeFor(wallet, qty)) * PRICE;\n    }\n\n    function mint(uint256 qty) external payable {\n        if (msg.sender != tx.origin) revert OnlyWallets();\n        if (!mintOpen) revert MintClosed();\n        if (qty == 0) revert BadQuantity();\n        if (totalSupply + qty > MAX_SUPPLY) revert SoldOut();\n        if (mintedBy[msg.sender] + qty > MAX_PER_WALLET) revert WalletLimit();\n        string memory handle;\n        try AGENT_ID.handleOf(msg.sender) returns (string memory h) {\n            handle = h;\n        } catch {\n            revert NoAgentId();\n        }\n        if (bytes(handle).length == 0) revert NoAgentId();\n        uint256 free = freeFor(msg.sender, qty);\n        if (msg.value != (qty - free) * PRICE) revert WrongPayment();\n\n        if (free > 0) {\n            freeUsed[msg.sender] += free;\n            freeClaimed += free;\n        }\n        mintedBy[msg.sender] += qty;\n        for (uint256 i; i < qty; ++i) {\n            uint256 id = ++totalSupply;\n            _mint(msg.sender, id);\n            emit Launched(msg.sender, id, handle);\n        }\n    }\n\n    // ---------------- on-chain art ----------------\n\n    function _seed(uint256 id) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encodePacked(\"Plutoko\", id)));\n    }\n\n    function _r(uint256 s, uint256 i) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encodePacked(s, i)));\n    }\n\n    /// @dev HSL (h 0-359, s and l 0-100) to an rgb() string, which every SVG renderer reads.\n    function _hsl(uint256 h, uint256 s, uint256 l) internal pure returns (string memory) {\n        h %= 360;\n        int256 c = (100 - _abs(int256(2 * l) - 100)) * int256(s) * 255 / 10000;\n        int256 x = c * (60 - _abs(int256(h % 120) - 60)) / 60;\n        int256 m = int256(l) * 255 / 100 - c / 2;\n        int256 r; int256 g; int256 b;\n        if (h < 60) (r, g, b) = (c, x, 0);\n        else if (h < 120) (r, g, b) = (x, c, 0);\n        else if (h < 180) (r, g, b) = (0, c, x);\n        else if (h < 240) (r, g, b) = (0, x, c);\n        else if (h < 300) (r, g, b) = (x, 0, c);\n        else (r, g, b) = (c, 0, x);\n        return string.concat(\"rgb(\", _u(r + m), \",\", _u(g + m), \",\", _u(b + m), \")\");\n    }\n\n    function _abs(int256 v) internal pure returns (int256) {\n        return v < 0 ? -v : v;\n    }\n\n    function _u(int256 v) internal pure returns (string memory) {\n        if (v < 0) v = 0;\n        if (v > 255) v = 255;\n        return uint256(v).toString();\n    }\n\n    function _pick(string[4] memory names, uint256 r) internal pure returns (string memory) {\n        return names[r % 4];\n    }\n\n    function _T1() internal pure returns (string[4] memory) {\n        return [\"Pluto sprite kid\", \"Pluto sprite kid\", \"Pluto sprite kid\", \"Pluto sprite kid\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Astronaut collar\", \"Astronaut collar\", \"Astronaut collar\", \"Astronaut collar\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Golden rim light\", \"Golden rim light\", \"Golden rim light\", \"Golden rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Violet starfield\", \"Violet starfield\", \"Violet starfield\", \"Violet starfield\"];\n    }\n\n\n    /// @notice Raw artwork bytes read from the IMAGE data contract.\n    function _img() internal view returns (bytes memory b) {\n        address a = IMAGE;\n        uint256 n = a.code.length - 1;\n        b = new bytes(n);\n        assembly {\n            extcodecopy(a, add(b, 32), 1, n)\n        }\n    }\n\n    function _svg(uint256) internal view returns (string memory) {\n        return string.concat('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\"><image width=\"400\" height=\"400\" href=\"data:image/webp;base64,', Base64.encode(_img()), '\"/></svg>');\n    }\n\n    function _attributes(uint256 s) internal pure returns (string memory) {\n        return string.concat(\n            '[{\"trait_type\":\"Character\",\"value\":\"', _pick(_T1(), s), '\"},',\n            '{\"trait_type\":\"Outfit\",\"value\":\"', _pick(_T2(), s >> 8), '\"},',\n            '{\"trait_type\":\"Light\",\"value\":\"', _pick(_T3(), s >> 16), '\"},',\n            '{\"trait_type\":\"Background\",\"value\":\"', _pick(_T4(), s >> 80), '\"}]'\n        );\n    }\n\n    /// @notice The token's SVG image.\n    function image(uint256 id) public view returns (string memory) {\n        _requireOwned(id);\n        return _svg(_seed(id));\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        _requireOwned(id);\n        uint256 s = _seed(id);\n        string memory json = string.concat(\n            '{\"name\":\"Plutoko #', id.toString(),\n            '\",\"description\":\"Plutoko is 6655 Cheerful Pluto sprite kid with icy glacier skin and astronaut collar in a violet starfield. Art generated fully on-chain on BNB Chain. Minted by .ai Agent ID holders.\",',\n            '\"image\":\"data:image/svg+xml;base64,', Base64.encode(bytes(_svg(s))),\n            '\",\"attributes\":', _attributes(s), '}'\n        );\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    /// @notice Collection-level metadata for marketplaces.\n    function contractURI() external pure returns (string memory) {\n        string memory json = string.concat(\n            '{\"name\":\"Plutoko\",\"description\":\"Plutoko is 6655 Cheerful Pluto sprite kid with icy glacier skin and astronaut collar in a violet starfield. Art generated fully on-chain on BNB Chain. Mint is gated to .ai Agent ID holders.\",',\n            '\"seller_fee_basis_points\":500}'\n        );\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    // ---------------- owner ----------------\n\n    function setMintOpen(bool open) external onlyOwner {\n        mintOpen = open;\n    }\n\n    function setRoyalty(address receiver, uint96 feeBps) external onlyOwner {\n        _setDefaultRoyalty(receiver, feeBps);\n    }\n\n    function withdraw() external onlyOwner {\n        (bool ok,) = owner().call{value: address(this).balance}(\"\");\n        if (!ok) revert WithdrawFailed();\n    }\n\n    function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC2981) returns (bool) {\n        return super.supportsInterface(interfaceId);\n    }\n}"}},"abi":[{"type":"constructor","inputs":[{"name":"initialOwner","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"BadQuantity","type":"error","inputs":[]},{"name":"ERC2981InvalidDefaultRoyalty","type":"error","inputs":[{"name":"numerator","type":"uint256","internalType":"uint256"},{"name":"denominator","type":"uint256","internalType":"uint256"}]},{"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC2981InvalidTokenRoyalty","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"numerator","type":"uint256","internalType":"uint256"},{"name":"denominator","type":"uint256","internalType":"uint256"}]},{"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC721IncorrectOwner","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InsufficientApproval","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"ERC721InvalidApprover","type":"error","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOperator","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InvalidReceiver","type":"error","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidSender","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"name":"ERC721NonexistentToken","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"MintClosed","type":"error","inputs":[]},{"name":"NoAgentId","type":"error","inputs":[]},{"name":"OnlyWallets","type":"error","inputs":[]},{"name":"OwnableInvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"OwnableUnauthorizedAccount","type":"error","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"WalletLimit","type":"error","inputs":[]},{"name":"WithdrawFailed","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"Approval","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"ApprovalForAll","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"Launched","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"agent","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"name":"OwnershipTransferred","type":"event","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"Transfer","type":"event","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"AGENT_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentIdRegistry"}],"stateMutability":"view"},{"name":"FREE_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"IMAGE","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"MAX_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"approve","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"balanceOf","type":"function","inputs":[{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"contractURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"freeClaimed","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeFor","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"},{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeLeft","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeUsed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"image","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"quote","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"},{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"renounceOwnership","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"royaltyInfo","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"salePrice","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintOpen","type":"function","inputs":[{"name":"open","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRoyalty","type":"function","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"feeBps","type":"uint96","internalType":"uint96"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"totalSupply","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"transferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"transferOwnership","type":"function","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"withdraw","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"58057001","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-02T08:56:51Z","match":"exact_match","chainId":"56","address":"0xF5Cf199D08A7B9bFE5C1Fc44ef5eabdae4314A56"}