{"sources":{"Chromemind.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: Chromemind.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Chromemind - 600 Friendly cyberpunk character with a glass dome head showing a glowing magenta-cyan neural brain on a dark teal-magenta neon city for .ai Agent ID holders on BNB Chain\n/// @notice Each wallet gets its first mint free while the 600 free pool lasts (gas only).\n/// Every other mint costs 0.00007 BNB. Max 50 per wallet, 600 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 Chromemind is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 600;\n    uint256 public constant FREE_SUPPLY = 600;\n    uint256 public constant FREE_PER_WALLET = 2;\n    uint256 public constant MAX_PER_WALLET = 50;\n    uint256 public constant PRICE = 0.00007 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(\"Chromemind\", \"CHROMEMIND\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"5249464680470000574542505650382074470000706e019d012a900190013edd5ea64da8a5232c2d770cd1801b89646d3c3069515d2a0265ff7fb95f2bcc37907c7110774f3f0fa77fec5e8dbd23bcd7f9ab7a76fe9de911d56fe8edd343fdd31e0a5bedb89ec73f58a573e7d667747379859f2c8f9b68d8cf93f21b27351b3e3ce05ebe672363102456a4774dc4dc48445e266dae5e6797dd251ddce33679bf9ac230bb3e9da5b67d3f1faee5ef74b07030aa5d6e6afc217c7268d7dd6f3cfaf23f5b7171c219c0d7dc1038fe037605f5d31cc6a4c659f69a082992d5575e6ecc8fd659b44ad37738f6df69fd8e27b1b6c2aaa15470e240bbdb644581a12e742fe3a937a901c8bf7cffbd0f2341fdc42d73aff9c1957d94f072164bdba46ceae6c44fe5dde329ac17d2b50604ab417800f934d9e86c40eeee160c80e9443427439af88870c0984f902a48ab9d6fa427ac8ea2d160271a5e41a44306f6bb4814c1c98a31240c8ad14a76293dbf462b0d71e5bb6d44532e72ce7a52048df870cca2973b0a395ab535768da681e880fdecd58b26b98fc94a4463f9d7c3ded4756429442af32b93cd27f59b6f20ce32496b9b92688ad756b30a8f436a5cad145f8851e91b0259ca97ffea30345306e6db1e27dd36b66a27aab76b71bc6b6a6d77384b5184d87c5c564718fe3c274eb7356aaab40b790aa1caa1329c24d785ff54cbdb7956c2a05b0dd051daf0df2f1b38e7baae1449b3277c121a05b1479b31fe1baa4c8c49dfdf5bf316059054336f0438401b9be2dc6649114a3a68d22e9b17b7ed2f9648bb3177d7fafc4e8af5885b369f18fb927aef0f73d5bf2949a753f45a5d9ceed4d96f38df4c76a01db33202ecd4382284084133b9500d2c7f8e229af7fd6e66245aee458763c6ed228ea01ca619b5aee5de25339fda48bcc2bd4bcc714bd9507725309367c6b6c88ce8a173e83a92e2d293c0a89f6d10351331edbd45b2d57a035717fe34f646e988d8edf24be16882265ed0f0f057b0862761640fd0060726f64fcd54f76882fcde70fbe462aaf7b4d68f0aa9a8bc92d340c7368bcc3a1c54092b8e7b765bc83d5368ddf158937292336dcf215fda628dc705c51a1af31812d86e4a21d0f569154a87e03875dab2f85e82fc8121cd81d7308594cd14368f6ad0bda1765d39b0c1ba407f007a5611502c05573af0c155730968d4d89382548ecd9a7268da20e44ddc99a578daa09ab105d48c4ee2b80f0ff746d17dddb6ecaad479ef4648616e786c98617e043021182f96f8822225c14b20648f6c2e7d106e35f2523dbac7311ccda37352c4c0095c9646015e3004af732624c18fc9841c3cffd698ef25da7e719d003bc8b75afb3b48a1754e08d370b08f77317d13fe9f685dd743d98aabee76ae95bb288dc99a06438eef6f3f5b59a79d9faae56c65d29a23b29f417f31526f6f466963dd283d673f3a360665c441bfbde5434721e4e1795eee4848babd86cd2fdb0972fe58be4380c1f8a22547aca3e73748f9a1e5f28056f1bdbd40c1379788283a745a802f737c5230f9c55b18c20a499fd1940582f67c59188032535e8930135975bec768fb6d13b8c612d151c14ad7b96e3de6741fe2972f009c221b7cc0d17f38074777f4be10c2a6c6177179b51d7f1c397af5685b55e75e54bc8d6801ab01995916a49dd0f2f2bdae9147d7b36476699ad32364f1dd58a11c4b4fefe6a650efdffb47f234fc9aeb18f9bfece4ae6b8f56f0816f8cde51e04e22297cfae5f2eb5e4da6a7131cd7a53f393ddc49d10ee5569f13749cdd967a4103890ae2572868ec936b10e26422d7b6cb33e54a304660a4f35b89585f5f0c9d5d17270296a117d75fee222aa401318bf4aa38fedf3a3ce86ea9874009ceb721889d76cce07bd3a920b56293350dee522d1080684efa6b0917fc1e2683e7196a76fc771f7e36c7a3f703637428f90876bcfcb106d1fd2de2d78dcfd3dc57b621b1171699815935ea74e648b04087926d60e7f54a01b727feb3b006183d8cabc429402333705c668244ec34eb72abb6f4d2c13330369c0fd1387bcaa5325ff7e6633cabd80ce9fd31c218120bab070cf59670f51df5d6a6fc2c2e3f2464d38c6d341736a42e1220eb019ecb8446a6b1fd7508b76ea99d8cdbdbe17f52fef2f3ef3817417bf936c7d234b572a976986950e88b9337ac71ae2b08b4e58985abd92c3c0ac867ac564898ff6398ecc2a776fa9915850efbcc2f0a8072e34104d6269e9ee996c74aeae93fad078b71a42ad5ee955b94550dd1a1a3a889281a8e54b2b2cd455cee588ed8215458706f90e397b3ba9676a63a81d10608edd14a21723703861d7a36954fbab1a3317a9f650652da155da6c58d1025851b77d6539dc9b2640be772497938fecff5d69de32f3d008f2f6b7615e54024e6b4e0bfa44fc2bc8f1201a5dd81fb660c95616cef74a94b061ddda25329a6912697352b1b34dc1ad2f797832d3a0a3f9ab610a5652fd5c9340df0c0f27ef2783126337a42e1f5d4fc9fc947d3238cb15e49116473803267de0ddf4daa872730f3fa9e932093b65e74da99cf90303dfc0a5accd7d6d85eede74d2e5ccc34d99bba7248df3478df5d77452d9ec7668cd90d7fd752c0354814b5cf7f2a0b01312e6b719c753a18fb08939fe15da25311e7daf11def31792a8e4ea60245029b9c257696dc71132af5ee32fdde15996fc1dbe00999c4b5d1ecd127dfb87b6b3df0a49d51f4e81788827deb405b3079b55584c77570047baa83ecbd4d35dbc9413babb50ab773ddb0eabcfec0e92f5aad76833a62b849a3ec757ae83982114ac3c27da1aa82ed76586e60155750a5d369ed667b7247da364596771fd04d32335e074b20adadaf32313603c412f26fcce1d1e6c80a3dc0122005b6d7ef64acecf27dfd49d97567ed2d1b64bfc0d42598cd1cdd95a0ce73c70cc4ca3593ed08db7a466712720b47bf436e8276bb590e4e180ea851917704d545ba394b262caf2fd7188f4372e897923cd56d81e185c1f4b07dcdc9508e6f6d20e3575bb74ada470dc17872fbec6ced3a06d1cd30617e5acf0b50e1ab38c8b784102f0cc6a10338c3a7e362707068f18949b137e6ce5881d531d6f740b04fd8ab89bed53719ae1c3879e97a1df830305bac51b75fabd91075aad2c2afebae37369e3fd57081d963e71bb7272cce6f0c30353c19b2f8e425bd7b99f66424c519984811d1fe3c14646b491da99e8029e41d598d176c37cdd1a461f14b9438b526ef96e52a362a58007f6dd4dee427b371a0e5588cdc075e538d359db0e5ac0001d6c407a831c4e52060b5ebdc184fd96df9a9815cea4ced64b263bece9b75d97979578e59855081b867ae5c4337e8ce2dd72cbcec9c826c933592b4a498060d2dba78a2a4b2c66a0bca56e66e7391325196f994fce267906d4d73f22338a9e072cec75eef474ef89a94aec38066320bb64fb96a28ce034589f3c4e77c9d1c372f7a8030e767448683e4fd65b803a4178bf3f262278ff636a52cf9defe3dbde7f3941fb1653ce8b5fd24c331666df38459c01b643071ac74aae0e67ddaef8ee7518d382331c03a083ced1661a96c98fb0d96d12dbd942a5459ab104078ec476c32255dfcbeea123968d36d03a04a3109a6cc84a6345338523c0bc92c276f04e91009520cf77a6b4a7dbde89680d9b8fa870916fee6ab5ad47853cf0bb92c768dc3a06b2eb798eebc2eb745916cc92a55a6f66513c7a6e935e32356ab13412d7dfffb3f095207b53fb8a45ef0b56a86b6daf3c21e19af68eb50d33ae723de7eb3829dc6c44eb18219c0d97d16fe5ff7b5b62f43a6896c9782c885cf513f8ef8ad07216cd76dac06475f1a69fff2acf5c6eaa054e10b0c9122a69db4b91b48058eec87df852d621584fde8d79025af8b4b126b000a53cd77013e44e035208ce23806ab9d0f430ebb56b7867c21de4276bc631f04d6f04c0597198ff016566df366a315720d708cc741f7bc373081c6b0aac603a2eabaae8ed1f8e1545d64d52f8e34bca0ebb7cd74ad73a2c73870af77ed2123c707d4c5a0c733893a0328c06471cddbb455b804bbae5bc02594808d25dcdfce8657b716950c9a8ef3ecd8e6ebf3c8823d5dff07b074451681a58851da38ab8069fad0808134e08b2cc30000fed9f45288cb8e9780cae10da32a0cf9620ce8408efe5e9f7e8a72ffae871e2613914c9b63f8d62ed66d504c3170c093740689b457e4ce08a933f6e4633103723fbd6ea6dbb7bb0aaab817209d8bc7e96c7c405c93044690d979ed0feb9db4af452024917230250b9391c81870633d7f8265a567e68cf5b242e298161224b94fff9121b827c9668c48415cd73a0e26e5b62650067d64dc4e538495fee8c7308106bd1a77302ec197685f754c5fff8606b416bb50f6d9b22d2584a98800148994d111c3be67f840648635e1f8fc9e2dfdac492bec037879e90f3b20204676805e48d33f3555336a0f2518977af64769ee682f4e45449ac5605eafda947ca44fee75dc4fb2a5aa4ff786133cca216981f730b43107ca662c8f1dd808ab38a944a852413ac0340fd6e4e7815347583ac24d6ce1aa1219ab8c96289ebd7770f07680717202ac21e0b3b9ce7869cb491040e5824f11a38a753be5e3ec72e6e1068dabe666a71072c202a9f20066ff6aeb7dbf4341594ba5b1caa811095860e72e73cb7b1e4a9bbac61829d349ff865c08d0ad646f62b9611ca178ecf2cd9b8acde60e311688a4fff5d7108c64c3e79df2a3c701e37306e0156c7e8e8b651bf4bad98d020a2863c27ca070a161a6b89e6fd2268fefd88289c6f61bc600213028cc4380005af34a1ef96ccd7ddb8544fd5525007f89d4f358935dc2742f19ebecfa63cf82ccbd61ac35b7d92f0afcd81d15b839d33b0fd1f8ba148a869fc8f58a259b1353b7fdf66c8c751804368d28ea80346bbd2b9ecb6c01585548ee6dd51cdafdd620be530936876b72a05a8cebc16e06384cd0a3487a8c3d461301af08e4ef81078525c4345f045e159536b6d7af4ffc742eb4b055020e78da9fd1f05fb41a4466352fde2cd1a343b131e6bce54dc8a4b08cfc5426426559d9c03a05bffa1e8e2a8d10e6963c1b7e92d3f72710d8e2e60fd067ca9655dec9643022d90bc0a9ff81481ef174bebc7eff4cf37db303377909818974898e747a8148a4f50f2a05e17a06248528595d10fed470a7e5ad0dbde74b01b974f03428cc40b829707b5de5ed2a365343c7c48e428c303dbb74e78020e5fbb4f291fcda251aec23ec234614b99bbdd5a223b90a9fd3c4ba07bc01c9a9b7d5120f9ba84141b1cbb56cf2fcb1b4de04755903f412ca53b19f85806cb8eaae2ece3051c8d6015994f30a6c111f3e8c80baafe4f7ebb048ae9c827cf4f1e60815dccede6564c461f0e7a8af42e7f15095fa2607d47045013832a49ac9030c3e8a1a1264aafbd0bb906959b459f645a3bbb6de26df9562722c76e24d9d06de844c1b0f2ca0500e78e70ca28c27116c2c1c89e44b04ab916cb5a17d24840b05c24ea3c95b731125920d49322ca742f00d2f89e04452319f406010e091f7b51f75dec0d7153991528d3538d78f8356bc8924a47b3bd43a650df0cb48fa78da5ecc3a327bf90e72e3be4dcd55f9ee8ffe3511c74d337f8677d800a62a8556d498da61b26ceb61bf97087683e911a1711986d90fc2fe566afcc55099f43bf02c15c6457d8568f888bdb16bac9917f4f92014710a7ee39152c26c3a35bfd307f2af97538cdb1bbaebc3eff2405b836be6308e4100cdae3f15fcfc5d91d5fead689f993ce3790b6317aff7974557b17cef1b01b9ebecf84b9b9d090e5d16fd789faf07c272fe102b6a5b033957297611c35de50920688cb7e4a17711b244024a7d3b6a41b4273d135bbc24a8b2e69e565974d937ab2f5d45cee565a32c4455abea82f12dc99dcd84f47421058bd0ecf14c5638996d7d79aec5cfe75dbd693476f64fdc2baa48fa5e1efaee547c03c37a789ff72e30e56824fcec1d368ea85ab958743304bc3fccb420bc73c0dc484642bc3ecbb15c10abf022b25c0de0af76c062f9c5358ab479eaea678b5f2592ec3098fe3c255e5973434c0c670c66a759ac91ed66c24c12d7bb29869b0d082920b6be038a8fdfae8c0e30794e46d1a0fa4d201acd7c91799b2a904a2461c14cb24324a195958cf4fc02a352f882e4c022bca1e20cab058afe59c35666bfa74b68470a7e717000ebf644f57291d1e551fa2b44872454aad730ad1791da4e55e74bd9009c4d9823ebf48c5eb592413087bbae1184d9cc8df6a036e8cae77292b041ba2d8d00b87a99a926f0ec8f4d31ab5e0438a493ca47a0945b47ec337bc37258f8360752f7cad46c7dfd173320c5b6cf7d8012fa8f9cf928803bf914b9d1a104b97e6427ee69e41e2f7ecb96a55bb83c6ca4b603645cb46baec42c69b95fbb627b04e638f519664a5ed2f5d5c6c46c37e41b6a54b118d450f7ca5fb8ac3e130d829bb403ab728c9e22760d2be88e31dfb562f2ce5b2740c071acf399b28428ed2300c77a81b055cc9e77c92168247a7f3a29e68acd2a5e4b1696b8e830be218c9bd419ec8f56acccdc77b5633d42e43067a8a89b7f3c55da475189d396d869c804c200b0eb6fbc364dd614f307f3ce82fbe510abd3827e319e589a111c751a1e5e1e9311b511421af71b5fb5bc5aee4e0b9f9caad22ea35e56e119efa277dd50f7d5e08e77d011a406666adbba4e544878242cd35f88a8963780ee4b673986c6d76a1560405c5fac90baab7b18f87d06163a6b3144a0c68bad1737b38181aaca602d5098832cd514d23ed8d9430f384c43b590028a9ccc4e32e5399a725b90c316d75aa991ed8c7c35f8b58772da63e8001a8580ab8603457f36367bb8d0dce8499818a8db59d86942388aabbbea5d89ffda93453225e3e37995fbf71b2a51a9da0b5864ed06ded897ce9d4f4f7c89cc55d64ccd191e60cb6f096ee1d75388af53b6ae58192739c9b3320683f3c09d6dface156ca00042cf9ae85fe9b23cd0f3cf7b51fcb587dc07e9ade4d31d9e330a12969f814c31e6bc438b249dac589a1f06bed542eccac12a05d17d73ee99305b2c51e1d3bbbdcf1ce7b22247b62f1e639a1c82f3ccddc90c812586317639883136d00edf2e91aa9d19efd1135ec7f8bd8b0079bb4535c3da35993e924f2773477f0d7a5585fa1f6cc8600bb15fce529579a45edc9f7556ed16b5c25a074b2deda50bf09697ceb6cdc74df9d1777ec77c9b272643d4509dcd18e85ecc840f3cd504a5fd21b20f90423b97a8dabe20dbe72cec1c2f25089f619ef9f479e8bfbf07b57bf28065baa6f0881d40902ba1ef75662e16d7410fef2c4b2bcf080e903b35790a6b14b47a8e1a92c37316ad76fcb6fa832ce5db81f2033041d555aadc6f09ec1103fda91c91dac33292d4e32e05f87b7d50157dea37e27a88703c5880c6aa3fdf64a1c0a1d3876268fc93979c4273974b8a9930daa6f15061a27b35138077bcc1613da4fba61c36831a253be69fef6e01661301405e1f33ffe4f705e8be953fa4b922f6c0b8e4260699c3ea2d3bec3961a9eba1b8af981951dbf06390a464c9530a55e01991be391fa74b525168f5dee9fef414dcb2133c8346653a6321e008cca2163d5399f0a0d3c36e53953e8363b1540c523c55cd58ec37cb314a1847e087936aa142429d0192f399fd393d0070dd9b9c531925ceefab8aa46b00f179c9891c339898fafa37242fb0610e31a77c7a59acf27f16793cda4d206a179b3070d24077a05b9f5677fba6f57bd4f5bcfb513ac85bfebcb6bdb60200b0e3bea82472246e5448cf933a0379b699d6d9bb89748ab670f6bc766ffe1059bbcb1e6b223078f926412768957ed565bddc5945d53a32cd7e4690a75de2863644a9487507ce2f1a14738afe111deb2c00bdd244b74db6c0ca409201e00a4250722792a121fc6d8c3de15827a78e393614c74e4c2e512b1bbcb3dc957fd191efbfeb476edacaafc54fd52c118aeec95f562f2c0b3a059e1f9a7f87ec34cefb95c6791f13e52ccf61971e9504ebaadb31bb3b1a207bb2ce8b5e7fe491c26de38bdb51baf33937961619e99bff31108effa8230aca256e2ecc5a8aaa8fc81dc5432d87d67100608273d57bb240a1c64f6f15e2b5baaa6ae0224cdbf7daf029059a49047ea78ad1175c4bba42294adf78d577fc08a1fe2370e4a5a2bed7cd514179529f24a4f60921622eb8cc1c83313db0511ff67b6ac82d0037564e4097a72938210807fd3c3531022dce5abe96dbb3bfde064e171fa69ba1dbc807a7db6f0ab5d1b95339d2f486234c2bcf0e6b2e775432dc154981ed769b8307ba9512f4a9816ecc2b2bfa5b2099b3cb3f11994f67c511fc751f0384603199be90ac548ea21ce328ab5fd5fc65670d8847432421ba0a03d8106e7980b96a1bc35b025c647b727187cfb7c9d53e4e636e9a3326cc2ee2eab75fca1d9170389ed940ce18a848e6976b08781d8fe49e7233b97737233f55078ecbb54da6778347de0d1fa74d22b3d6d7994091019b452593dfddb84e5f48abd49984608f44c9305883a44c6dc222fb2e53db72d22790e05e25446e603da186a34224d91e471f600a7b2a483a2a71a7c964f073299ab0fc2e1ba2eb11d2807f154fc26824218823caa6fb818af0fa7802e4e5a299ce1516b309a789b7b24d70cc4ba61b1c73e04d5df97ca238e4a9b3e2f71c173e68ca7d222359a40fbd6e57498e3c5cf1d50773b593d9d08aaeff0ca9ed1e334e12438e17c9b2a02a0a63242291ff6661ffeb12d5db3c453f759dc0eb03b067230ea961bd8ae6e60f7fc32f54ac7c1e7c2945129bb591a7f1a9b05b8da79278566631f4419dadedec97411be6badab6f223cdd333b190f0ef3cc6ed6d187d62ea692a83f8f34eb74f2769256a780a9bf79b3fc68f9ae4817b0ff81999cf4feb61825a9ae3c3468bd97afb6e4a7b225a40a8c5713e27f644e5b3b3b52ab45ee2543ef8b21d534ad656854a1decf61ca515dfcb596f94a135ea2c508ff295ce4197101b1cd2b7c6efc2d8f0c36108cd0f79b27c18adb6ddae34087c5042d411bb6594580477cf0628113e7da1fd4947ec94ddf7d437bb935eab8172cb5c60e7a537933f60b19f3981952502c24fe41148b9434ed682f66fffc5c27b6741176eb859e55d182adaa20b966ca3d66e4af0f7c8b751ebf302d17bffa32c9968e5def98494067fa083e3ea0fa1a2c053991cdd513365cc3fcc6370017f572a9f3fee63ac9fa1511e30c668f7d4cba1ab47cafb3af1bc1b173c20f130604ef9ede794032a26b18aa8e52ba3d5aa718136db4741b33aade6c0123c6b153e45940fc25cc89c5f8fb8622471a0e39ad887e2fad9bb606448581d61163ab66bdd42d6b68b92b8e18ed16e45062337cb41c39e85d91eb04c9095068788008713d4641c25a6246abb7031197040a798f485ceb2e076964c5d82f250a93164e3ef77b70237dbf1f462d795c11ae0aad06cda97c52f419c6e061c56146fdd1244cd2b7792837b99bdab7b8bf0979de3ff931e6d7631d5a60d8629be65765ce45a60a68744c301186aa2dc06edc18a79b0ea0d89f8f74d43a4f9608b364e422ae2d0a4c354629e2d681710de4e56ed837952cd49dadf80aceb55133dcd155b59b7f5c5c03ace4a8183addcdfd60f728988b59ffb6aa5e15fea45c323ac28073ea2a64e8aa1e79f678b752ced214b49cdb442a7da24ed9aa9f55ea8bc2dca9fe034a1073a2c8909e802c09369e1dc2dc10fec96ce713bf9e8b6181dd9d798c1ce17bc1eddffb14175d55e14d01bd15ec740c7b3f9686b17e31f12e8d5f01bf0409f33f33f2514213f21ff6fd13a856655ae2feb3a91e764a55202c36cfae1b8083ecb25015fa1fbd0c606c09cf67142e342b9311e93ba4dc1fa9a3aa3e4c11aa45819b4ac7ee343f19aaa64cc1c317a91121cf6f782bd96488ea505e96aed6065350c4c0a5d66eb69f14b03dba78e6e4bf7020d38bda6fdd57243f9d470e9586d9317439bf14eccba021fa151bfac0eabed5e23863537ae09475ec18bde506610d809a2004fe10a54d822b7c3e7b933a1b25a9e82d375aec65ff38d9e1847faf21a5c95d6667520c1662d07f098b68e4db3f9776c7acb352fe1a4b4f6f1dfbc77e8403098aa2d24b6f0167f9c8785d09e3d2ee0615dee32bcb33417befe8899519c935653b232010ea0600a45c39ce036bda295f41aa7da0e5d2302a8fe4a4fd82092570880aaf9e42f4a86084db12c31bb612fd1ee35103e69162f323768529ea9a5b25ab8a714a20bc6fdcf76dbf735c0cbf71b9d7ff5f5e7e966ac4b0767b3b7fb647fd4b64e544f2493e75aecfdceea472f3c26b2f5cd8ccf936203d2225b1875a97c452c619efb2fe10620d9220bc41d45aa70d8a3aaf85d58d6cbac1d60bc1e6df10d86114aa1562631f5e8b8ac77fa0931d26ced925a954a398b67706db48f19c3902e1079d5eec71d3d0fd065e580d24431e8e573f5b6b8fe8d1964f29c27572a83eb78ed32cff0e0253b49e8f5cda80e5a7c6768cd7574aa59d56f3f231137fb8c2ba3917726410f18889c6d4d44f4cbabd7f35b9a78d0e50897086865714924132c8d71fb0ce2c2f5157f6f53c335f354a149bde45635e358e1e202db1cd303b450aaab2b66ef1c1eb235fdcd0a312c0c8b201bf6b337fafa1f05cf0bee66c5513ba9f61e75254582946fdbae0c6fc50dfa2cda53fc2473db286ea8dd659086021e2ab9755f9c109cecba37dc26a0d7fdd5a0f062e3f4d2ab68900f7021f7461516c3e070030123af2284faa34775bbced2ed01a223a33eaf0b7202ab57725c36c4decbf96192dcf70e9f5c1af232d61d83e5a5406b1aedd5fa55036f6bdc7e80e9f814e3637d3b59dffe4054bafa631cac8accf977d7eef8e745e223286699b05790e243bb8f317fb43f781e2e2c6574799c2823c7451a4c33c5ebfaeabec0f5125e858688c06f0ecac94b6b0fbac16cb12dce9bb29bccf7968b04b1d742d1cd0f27c383247efa45ecf8da8d3e77a2844f4f985818bc6ac67d198f433713d7ab7266d091218bc53ac981058f7b79638a9e016347a7a82ab792632e59c8fc81ca48462af190d2f6a3bf646a3bac706ff2dba4682edea0c06ea0a4384336ab271fcf7bb1a9861c82fa301debc1116e6f0b7e28528f18cb681e249cbe12881e072fc322070e44e4e431e7baf8a08a59cf0d969259fca4d5901094cef95c9718f679365edb1ca8fa4d812b42de1d5d368e3b55e53ea99d24901d462f8f3d268c1588a8204fabf0ce23322ada4567f8c4ea59e7c1aef133509656dcfcfe340d1a52b13cf807a3a60db3dabfab76542d33ec47982aa63572d3d6bd93e999b1f28122b1c2da93e01ffcae289aefc067b81021d253b0ee75303edb928c532a01b6fec7138a40c858e7b844a75f32d9c51faeb130904c502154e8d27ebf4a1a0d3e476ebd48a97dc8aeab5dea56481960aaadde99525e7f2713811a3343c172b91adfc4a99038879c3953765f33dcb9afbb6a02a15292eb2a74077960ed3c8879203ee25252ea33c07c23a330ce0ade72d47921b550a601ff6c34a3fc72be19f78175e953b566d66395f9af7bd63796c8809f45fc87544cc3121405447ea7352bff8c3d20d7eaca638fd0cf747bc85f315a4eccce32ee6ec13e3719a77674ec2f885c0783900dd2a353f7b86267097e459ec1348fa00a54afc54653953dc8aaaab0380260767fb46264c78df6ce4e4281f04d24a4787fc24ad63eeb08932fd4f52d3eed0713b086664a3b1d97391e9bd04d9a62c8efa0e05b90bf770726e83a871892034affa29923dfdbe3256ae7652f007ac0ff97252ce9939340d15f0f87e121ced51cfb7ec07e3f0e0e4fbc4e7f90d1272d0d18853b50205444ff8bfd9bec08643bacfc55c16d7614650c99a413e6c355b007158af1d2e085c0bfc071fe7bd014d8e757daccd06387ab24dc199df4a418757044760d09dce497fe987742fdf86df5da32d7d5525c3875adcc6669b4d7c43fa02d2bc7799f5a41dd534261b9759a7cd37db2f4b0cca4b12577ac4f8026eea2529760f46285736a8186e9880f2f68f0d1a354f0fc36c20e0af653081c66746d5be3fc3615796756a8a8e644af1337a50aabafa44ceae0d5e59f924763a0cb3c2a966912f47a2475cbee3894b37ed5567b6a4636bad9b3129535758eeabde96369c701ee3c8310363dac16201fe27861a0b12628142741e7e8b4bd8a8e4d0d2c8d2d92ff2036d9e5d17fd4ed3aacb69c6d6e9a72390d723bacadf6c9412327fa12456d66670c67822d14f3a282f5118a9e003184e76100684c5b346b5cfbb0ed21bd8ae2d434527aaaf31e6371e4fd2b1a15782dba82bd950c01f982686517896f21f2d5dbb4e81073b53b2b75504955143c3dee8a5eec32958040179a65c629d867014744ea490bb819f08a97ad3db96f093f38ff6b91d57aef3ad18824a2f66df3ebefb5afa7c12d60184c25b02d208378a2d683667c6030e2a3dd5194f9159ecde5529eda683024b1ea0fc6f718236af3ccec7e5185572c4af557dff119e208c71cfe9158a37b3ba9c1a483691067ba3cf36c12b26e137885d7a52a318095b976378e611c1fb522f50ffc2a5a20869a4675a0cfbff0e942846b673bc56dbd96f0ed514226615ed18745adc0efd8b0a2d63a07edaf39b88b9b8e09db21f0af23e0f0c9f645aec5b28bc45db861507d9cff12d3f7b9d4d84fe3aeba90f20adbcec9daa77c269cdc9ce034b5bb3145dbe1ca76b8b31fd7beeae80255b5f918d3c5dc9e7748bec70e08ea826b1f3321c1d7ea29e1f6fd9a955d6cf6ab958cfe5d1a97a04cd54410f443d641fe125f06caacab3ff751dc9dcf68fb3857ec4df86fa62d6d12913ad8f8e90381015a8f40557c9273ce6bb8c6949660f44bf2c972f16857cd631466d1904cb5e2d43116a8a82f123643b4e4775555aa4aba827cf19f7d8d5086499ce232493a74321db576fe56e6af4094b438e50d1adab247464d2fd014d88b940efddcd39fb6840fc747699709eb0e59bed41de6b34fb26c5ab8b54327b8b9e3d7d41375087c1b1c6881a663631e96487014842a20da6d1098d6186624e6e890d6cc8a2379fcedc9f7cbfca417962d0fc6d89d1b8961ca58e4de38b56e69bad829cbb0a23c9ddae032dac404056a2b58481fffa63b0e1b66b4497664accae6477c9eea89ae3b38f16168733154db16d9fe32b8203578bf1a0eb58a2fa86c22cae1646ccb69e29a012de6b77f5bbcb3e9f125684f39f67998be30b1b741f6c393afb0b2083f9882d3d266b36a42f60b777b6aaf23c12ecef3cf15d21ee6a71a723bb28044ed413095e9ed1613c0df9f958ad095829ad1de3194f11941188cf2e1aeec4a0c56ac5316a17e3569746fd4647fb24b9beb00e8f5540aee82bbd260196164e50ba1c2f47b00936000db0faa57047af0575159bfc1a6961d85db361dfa66d2acbd5efe2156058761a9e5f5f9736604820906e7ecfd02e6bf509eb2b2f3a9fb2d6358806e2028c13fb9ba7a732d21ab383d589881ab54ab30fb297deaea6828fc24951f7a43698d034157a3d4e3d787b250d13979ae5c9cea919c73cb9cb6bb92a45c8d07438c36afca74bc738681a058fedaa38ab32d2b41b112f09450166463115ef7c65db938c1acc7fa5224397ebe9b21b4d5cd4ec7b6318c9eaf321a6b3d6d7be419a0650510a0f144ed89b2964f57dbb0d0a7fb658e51e5656ae32df5155cc2185a9a7e471b5fe88097ede36669b42d97fdba89502de298d3ea7acdbe33175b6e85fb122e4ec3fa39801d57065fc2e0907a8e0fd32327ab6cdd9e2c39ac99e1d1fdf1f8e201208142d2c1fe1048d0d5537d624d04b60ebe36584ba55be3745915d00c4d553a4838bb98ad015bcb81acfc5eaf6b746fc76385efa8ec4fec232ba4b21aecd2b51a06af6b25a83ae39aeb69d1eca7d171bff296356064226378abec00481a7ed9155f09d1811ec6e1a35dd27f89d181581ca37917a8262017f936f5ed830b38b45f7724169bfdab13af9e15fa95e271567bb9c2a6a2a1a2872a543774e8b9bba9c964919660164f2e678dcb15f15fd376950a22f2f41c8453f2c763db49be67952c632d3a32fef31687de8e37afe3159b747532c9137dc26b891469131a1f0b275f55cba3758897d3bb5f5e24e928c52e618d5c1a8f9ba7d8740b736cd809dd94746732842d898ab4f54586c408eddbc6dd8bc57d958366fd1d58270f49edf870ff00e597c440eac4790d72bd96df9c4ef25337f4f19641d4c142134d39b5be6202ae2dd2672aa230857574523dc6329f6c48ac5f8f7bde42152d64f90360e33fc7856b9966011f9b1686633e0c158c479302bcd0599bd9ec90d2c7b393408c0e5cf538843081499a7ff2277c588126e604b6c91b624da57167603a4ca509d17046f7898ccd64cd5ae3a16c0e033027e35fa1e082ab297977dc7829ef9cab5d45357c48e0486fb6faecf8b04db4c8aa18b2482231a9281ffad6a5748b545dad9acd1c634af20725d0e1d3ea4a78881b8bff58686110f96bcb1b271ab994503b5881ed2e5c5a518da28c38c1982fcd10b0ffd5b33664f85fda641105383480d332b33a5592c5c1499a1e5129f32c18ce94b09e0e1725e8765c776619b7e9634f423453c086d45bd243d7c5ff347b81e70e73f50abdc60da453173c399d10279710f3667d7e194a414413688e50bf1bf94445b1585a9363ddc10f3d83d73de6726e7bc60c2a00ab31b329134d1054b11fc54c85e7730b26f47e2329ccc76879b715612bbc873951105be93d344f886ae0e5239cf5d95109ea9bfcb5500dc35da24048e8f93f4d5ae7e4981b85331dab2cfda668f084befe237f02a1db83dec2ef10ef6726afc605517e2b3e855f5b83494ef3fe63874327deb0911abd48e9fcf66d80566738c7f227b9e51731cfb88ba30647eb137b675a2021f1e432db510731c7df6496e7c0c5af4f961d9b12cb49ccd94d9215109067981f811f35925222226ab0ebab352a9757cacfe5396b2fe10efb718d04daffcfb7a9b256c29ec5718dbe7c6d62300cc1be82edb3975fdd288c5b4ac1d3f3cb4ce0448019fdaaf37f6b6f57dff3630ae01e6b9b8b2ee5ff1eb357963f153e215943f8a6f27d01c95807d2bf6f91a543f6b84679cd34a7338364ef2300523ce47d052b51435b723b544ff6f64b269a22850b0e391cbde8ddd622ee018535accb157742bc3058c6fa64436f3fd25ea1003be28f9c36751aa155d65274370dd29bc719cb2fdeac9c1b5ccadb01183147ff157df77b8222fd31746811d39e0b93a826cf5489af208e50dc07699f43d53f170a294dd17c3823f0697e2670c2f053ee0b8d90ff54e0a231d284e777095cdd9f2a8f11440ea6b7b1ba915bf88dcf12e5519a145f90cc919fd79ed16f12820e58d90a39ee7b7cc7af5cbd357593b48e607ecd517acff45d30410a7f178bbc5c3d47f499fec154d17bc429a3f20ec5d2a5e151421aacab78f90cb61dc3e31136785dff2660874dc6910c9c5c0f3ed277d94b168ae8100b58b2684136344c7614199ddd7629537e309a6a0a9d39f4e12c67973b878a0a67e5eafeb83d9e4e9ae11d05b964e31b2c0654f4bd2671ec437168eec3cc608823e3015fa16c7e876c297edc8fca8101e8663690f191cb5fe793abd4c80d61ed23305344c8f42cad1cef4c56594449c04f65445bbaac50ae40831000051434845fd9ed64617ac26d5f0e238be892535ae1d84f04ce8bd4c5867aafb81dfaccc99ec54e046a5a9e3bdd8e9673d31dac7903e0266f1e6cd94694743b97d79d9e67dc9f646c288834e9331741ab9d1e0a16fd7919952cc198f73edece3b3771a875a89a437882a899bbea31c4ffd0c80f3970bd5ca5c27a551ab2a50e612b4ddf8d1150ca8f6f7849991a25f4ce25cf9e1ef2f29a9f9cd433eb05815ffb8fba8eb550b963438061022d51342f7f164f3cb77b9464627bc09527d53e8abcb5eb79ed0cecd0ad1b475f8c257f8228a436c8e03d797ec0da30af3ef46cd9a3b32e353642d1b3f175fe57458ca77b9a92aad089b0edb6b7b1bedca3654c52d5826ad020dcf8e4f19742309c85975291875d4d662a85d951125714af1720e013c5263c9cc61881b0814370cf4ad41b26103fcf6820294b1dd9ece84ff68a304a5042087e905677df9462b21cef1bd64a837c24a03d9681b50642dfc08e98619fe63f488b3a0b32ea6e688e4f4ee2d06963ec2e0a441561cba14c389b37d839930681a39f7b575e36e53cfcf1f3614cb7ccaf0708c0ac728c666db2d995bc2738d9b678bca0176f2528151f39e3f44917b390c5e2e99035bc5d08abf1d1ac607b25a4e6c97d9a1a5cbbf75bc5bed03702e139ce9e0238f80d6fa9c71582049809603c85eb9d51e3b3d18b0226c50e8d321ff4511f04bc97203648cbe4cc773df74dcf4dd0574ab32ceea4ee63aa12a8723073b9624b1a35a14f0766ecf541f832ab6f4e2de612af2afb900fd1bc5a462af02acbe8de1b5a25922d7d235ebb7c54cfdda13080afbfcfe5a6dfad548be3406917e21989594728e5625bc37785b04db1b4e75429e117dc4430ec65a168b7e8320ba3921f6b18e2eae34242ab4069d8180b73636f88a0e49cafd7caf9e7b3e6f8b528682315a2bc0fd4830911e5a6ea3ae5cc65ded361e7f8d96941eca8a61d47f32d9c84fcf2395ae23d5265c3f5b2002719efd8a1d8470d4f3df0f34717409986b6cea9e9ff87e229856bdd0851cde2e6ae5dbe00b3f56ce603c0b61289f377a1e0e687fc6181eab5d05484674ed4cf57660300bda5ef59695a393dca1e8073a7a4baff1e9e2babe2e6e63899699c7c956b7202feac9dcf9cd4bc5ca0bafbed8889d5f1862dc51848e02c8a8df9930a4dfd3eef859223aa97f357b390799bc0320e5736b8a1efb1756ed16ce033faed2ae967ef774c1d51affd52698aab42a03d33ea4db7fec8e8b0c4f34c51fb21bd99dbfe49c2ac3fb5a4ff7cbe14674a021d4767b7ed6cdb62fff6586a0d7011ee871b060623cf76ec4235c0ac2c216698fb03b3e323c52cebd5b896c998cc63900758618995d1125f30b588cb5b91c3b7579a716b2f4d3344de269ab0d572294ca51ea8c9ca27d3d111a58221953693b88cadc3e01f861f1fbdaae30cd21dab11aae71cd7a1ad343c1f155045c871875e0efe995fa88ea735777dffb8828b7ef3a2eb7b7dbaca5d3f6ae42d832621babb6e4bf01a522d9841de9420fcdc3527be7a7c26407d9ae90fb9b9158095460f1a95b0bf701838a824bd9743969ac6d49730fce35b8834a7206de8d6f414d56e43ebd48d8b00194235101dc77b87b78e17b6d5db15c57e2c21c6dcb735eae5c3ad0bc4c92f7b6202822afb22018df44c4833bfe06f96c3b14b6cdd1ab307d564d554a9da672a2051ffb0a958b4b327ad25e14c96e350475a83b5cf126956133c4a94bad51d4929df6b3b3bd7b5284a87ce0f428365b0693e74ac0752135fb1892a0ae159c327baf6a995908cac9ef6d4f0d0b42523c42f064a93fe9ead97d001b240b0ac0d9505250e8e753b07636622074fd6752a45f902ad1284f9a66eebf2de795d8b57b6c04d934911f39450800a40518f73d80f323e70fa8404a06cc89a6efa6b82814f1c17bc144ca7d3b38896fc522b10642c7c69504239e3e8e0e49213d2a230b40278c0d3ece565b42db47b3eda731affa2e98c81416b40442ed2025af27d07672b87885380b530a4756e12d7c96b443846f7dab926617c6768c9d80b760302217f210739ee4e3b98b3ac31d0a9ad7322bc79db53b1ef9deec81fa0d58c922d7c631cee9d8813686762ddc1171fff598ab55c9c3fc78969f0c2f3f6cdd2e03df822abb34efbb780fdc07de84130863de6ee81ef76ff91060d3f4ddfe4d79422be0ea4daf46bf34b73058e2a97a33d7e2e6f96319d556440b6c8e64c2f1050fd280c4dfd324078216dbc841a7a4d9d36c07e925a7828aea57d0f4db619635302c7963ba6e980e74a85920c41701eed3ee58cbd41e235fade7dd9dabf2daf93c1a41cd0e70d1b7474796d8a94cb5632363e3c12fd68dc8db5cc6641d8621f120259227594dff3bce084fd85e7bfd3e42afdfe1a65e8f8e23fd304d5b730555d6261419f32c86185389a5fdc0542bc3655b5f137d77968cf756d6c684a07e3435f3656142e2a4ea1531a6e210ed4e0dc3737c8e5f7bc1c47149feac8832398288dc08add4d8500c219f34642544439a51bb05d553177e425868654fde6edce9e5f14886556a030da37efade085e61faa88f3dcd5ab71ec13cfef4f441c0e6de12de6112907913238ceab205a0d803aae7b00563ca923d71729dd215135af4dfe7201d6de82d54c2bf2685005e0a4ab31cd7d6ddabc4b39f30a94cc9d0a64e40f56ffec3ece1395dea316351915065ffb2c6b92a5a04a6af09040f2ff574eb58b33d7ab28c8611a425ca8088e665435c9373f91e716f3b2b6a2753c72c3d9faa78ca29a6d188d37796c1a4ad8b68dcd219c8861b7f0587374d88dbfa52cec4a5d668d6dc0b663f2c4debdfb1748f313cc6a6dcab832d36725a0dfdcb3ce13d2b37a0d43a7c7b0266fab7ba710ed689f81d97c9b2c843bf6c1cb35e4cb802452dff1b23ce8f899f690be9fcebd5767ee75e9f108b6943c0b28659cebfac00417bf2d7843a506879a33beffbda66b8b96518935978c26db7bcce60207bb93b7c6ab97b24dbed871f58025936e53a5825fc1d27620de1869809698b72390f1b82c181c8ce7e891e0f9b285b3ededb10b1a936fe676899137efa9b2aad78f532b6d398f847c67b592b79ed8f52952c0aa3f9721b1817b9407422b5f91963262d15f5ea351455affc9c990216e5ed44fd0da83282168f59c0a2416e040eaf4c96d78131650e1c733dba12a7ca0ad76e7bd4213e3a3a852668e257e8aa315336f95dc70d32870945f5927e48ce7ab36837af614f67b2982cb9e65e426bae07cc3c957dccdaf70f4b4e7827d55ec49fa3222e9a758c8258cd4887443d48a2e2bd8e71780b8816b57a31763768fc9c1e812bb9bc27cdb41513cc546c525e2ff604a3595ea8c1cb1dac79d93427f9b3d6d96292379b57b417438d11257cfb5dfc1d80167267de38aa9bca772764245995802c055d538f3d9033014f321cdfc517a50e32b436e37f63e04aa48c1a169aec1469c1bdb3f04c0b711cc521bdf6ed3ecff5e6667c5395770424a8c6a6afd17c7930263024923d5f64b32d2a427fd0440e1707c2fb37a38b84cd78bb9eade313a89fd2ca63e45daeb2d3c060f7b3744c66a8c092ca8e24baba36536a8d747c2c0e6597b72260b34aeb28bcf6e8a00cf3f2f7c0d27315772a115f157aa772a50430e3c0d659f0ecab37fe860a16a6ea3824fbe12fed0666a6dfad5e3744807e3de72428e81b203c2f80d80f05a01c9462668e757459be3e40272985c5955560962d69df7cd707cc2550eb8d16158d245bf65d6465cbd797f4bd9696ce5a905cee622f73517da579d817440dfbd6b7f2cd3be82c42337c831e257d5dbb946a66863068d343a4b0f2919b86a4c1c8f25153cb83e7bfb03f33fb8345358b7fca40008e51e216e3f5cf7568f9bf648c4f9af2a13e805cfbc6b99561563dfe7657af3b51a6d6296200aeb233723f03b47163b76de4e18adf12cd1b89f5df555b44de8ea4a0119e3c7e3c23f182d178e54119656a0b2c2cb34115682928883c9c637c233609042b44e9f46c25178ac9ba4b1592b2500fbb7ec68020bbfc64ef072413b4b05319cd3bab1b0d0da9c9bbf55ff23aa73aff73523e43507b8f6b570cc577b96efb1dee7564d2f448977e98fab787a7fd7d57f4fd1579d4889cdab2eccf9897e35a34e35f8d54fa289736c55f79407ffafc804ebf0fcaad5df4fa7c6b9a774045bbdf2f171b4830e2e831c84249bd3a354ba1bab565ea01782c1a291f88f721458461bd352984410adb344d2318c62ff17f9a873fe088ab1af42d619304e73066013be8b26a540e60cf9b4325e2cac75bbfea3b863e9747908503a8372609841d680c2bc54e9845008c48f6ebc7e36e513a844e9bae35f5ba5eeecdc577aa10e5154950bfe31724e46116aab33bea90ea346ea8754662c4d368c9cc2a14d36bbb122c4d20d261ec6d96cd35c4ca7886cd9b429e0de3746a7c92c1accdb699945814850b89d3a79316d397f8ffa76719ea07715028d21e6ea38a5a7cfb1c768a7c4b5aa5910a34a75221e106b738b9ba21a8cdc97c47dcfdf3133066d2a274d42c6d033574e2de47dc7abf48c770d2b1b19b515230012602619e7dbfb3d39f1fbadca1a87807ef9068307b07f8f6975b33d8bcc0007feed5e064cf082604667801e1ebe80218e5dfd24d224a845e1c31ab14781aa90333ff260c7bf8e01a2f0579995e131ac68abe2ec27f4233473a86a89e2f1e1448e0f53d76bd3c417202d1a56ab69287863f2d96058de352d1eed896ace9368a6eb4cf13c12eff7b250b7977b8b98243df720222d2f72ede7a2cb47f649423f1a9540eda77cf3851424bd20ebae02925a34f2443e45a6f4c7ee507a08fd2cb594d05267a518118c74d8addd13db951e7e688bb0a6af4b0ffa9107b709590c80647212b622860ca60343b93a506311fb0efd454f758082efc2a3d127da5905014903e398e279d2df86257e70031f5a015d4a0733e2cbc07d1fc646355d7769aa250baba5a0dce8ad161d31925042e351fe0294c5edc2dd7eb089650c1a695b37aa6b49f1eb123659491180710709e6b3016b6320486220c3408e7e48abbfece93a2f3a736433be02b3c0a9dde40d01e514df4ae7add49ef36f5f59d51ddffcefa8ea169907767b60d5e309f960b2da17a8edf4537f73e74c31f74f0419d95678d3c58ae4e136a7fe88a29e626fff081459547d09bb69a80fe5e6759852fdfe2abd57c0addcaf39a6018df698d8ff027f9094b77aded3219469bae8b07e81cfdd4fd9e8c33e17f3385ee68a08a6cea1fd5af96ce1dc25046b56a6d3aa5d9e4955f445e068d34f7a463588eb157edff3fa3007008a7ce47b7b49ea419ed0b98fae79354156b89696c8f144701b05779e5f3b06fdefa2ff149cb31e035026bfce1596cccd6bf7ca0369b20d6e71d651b9dbac138f4ad993b86c31e8a10d014e7054d49e54fb99a1ecd0858e9001038f173e51893f55a6740cae5085d009c567f4d01ca5112eb06e21b48200342681eaff33804b860bb65a1b07f095bd33a8cd63da2568b1c27895470f0716d3fab3dd8ad2d52eb6d05f937e1a08ce8a197638174859154b4c06083a5ee7bf9973c5f80b26de20729a879937702bc3f0ff3169b44fbd8da509571ff7a5af42a145ad629078c049119f5d9a4f6164ebfeb8c59c52344c62a02bf4179b13f6b57f20c0eb352f795c1e5652044fa2985b6eeb7e76377caea8423f7dba16e643376ff6cbf0b71d93689059ad5f5a5279b7d22aa873aab85d16a0a29e11a125fec81af467c4a6cb620fb223fa9d3e2504f7f09d01c3a925a15378440a5d30669b63bf08f336d491197c5b9951c289e576c2ccb74d243f61e621a70091b702fce423642807476bb7573111b13054c0184f3128129fe2437b91e395a2a1071b253bad81b0e6abf9a7f18ae23703cb6eba49b4f6b60d1be44abca067781de881df47d5b7da31b9e25198d5b3307c46b7b28dc8f4fa0a04da496ead78d53ad465be38eabc76ffdeddc55c14670551f777428133f7f234a17a9daeeb15f2ce8c5fbc9ab724b3c028e7c42c9755c3b29a67c717af4a1855831e546844a02fd36ebea2ca14cc7ecbc531c9c073b9711ad5af50b7d108d3e9511782d7e18af2a8e557ca8ea836998f07149964d0b981dcc579d7156d62c032a441ecef91ee9fa90c68baa143314d11e000df32245992fac6a5d588465d39afe579656a6849d158a23093ac2c614999b7a2c4fb7aca93498c34baa179dc653a075f2defa434c307e8b600f2495a4ae109c8f2902941ceb005117f21664b3f1924d1b7b7c6124b084a1b13c45ef195e4d0d3f2511d5f69d33f01a78dcf74355c1f6e0328f6c3682310b36f5a109c9489afcc9ecacc72537cea6b50a00c3dbf76ed72fdcfc3c0f7268524264fe441748fc05498b5e333bdba3306339cce3ba7c28402430fb991cdac4298260857bee6ab44b84395352fb707c4a96f160fa2edb6289aed02308a8950b24ac2f2806fdb8331f8ae553e3af049c9ce5c5145bfe0b641c441c1e634864339b6405f1705fb99c7754fa167c5bd81a46f50949832b74cde047ee8057121d7d6478f0742ddd31ec8b806148dea7a33c1e2bb3745fc57f64e884c2a180ac026ade33e19e816f7a7e5d7e3fb28044a090e63d872bb5c45823a9a012de7df2b6e41587ee69aa6c08dd2b46b1bca7b75c1e8147d67a6cf55b0ab1398f308b3af807f71d49ddaf3debf07a4534a901dd1b0d67c5808f84fde3fabb6424a98a249cc575d1e9ede39639f4f82d965c92add1ef622f067be5b4b7754667c0b46c56088a3f76d0c8a9ba0c3b02c26376c361275a90181a65b7fb3489f24b4848ac137420e5d5c75fab7f9aa0ac13f74dcdb724f3f96cd05e2458ba0151f537b3db13aff47f34528920a5730a85e2062a7afbddd461a4c437b1d3950f89ae7f7fa9e2adbe8aaca2d856477d4baea49e220b813abd365bbbe3fd9ef62cc1519736e6cb7650ab61ea887dbe6b29c89c5179129048d545d448b124336c149891edf5084acc4ae3058b65089095d10961aecbfab50c9eb03a322daa99078fa4fc7821e67cab3c8d04269700ec61538aaeed6a3bc18ff4f709f72aceac4cb082ffc105257533d7c372bd077eb2dc219b2fb7ea173e30a26c4d1ac5d709bfc882145906d45ba33ae65ad266ee786bc556c64c341e4670d2ddef6c5a9a9b357c95decab79d776a824f0977e8d471fb9bb563a49464070dca8399f5aa046cb2a07be4c221811ca8f728d5c761e3a3ae9020d55122c16750c89207c2af50b4f5a09ad4714440d5a2a2325878d88256513bb48f8b9e85bc4f319ba0207add9cfb72d6d2c05820460f18503bf5ca9a271488a3e1e00cc3f8db4c42e5cb900a386126be20f61f41aa650fbfb3e28a36fb9bc2c3b66d514f6ee2534c67e4e995e305041c3a4530d54cca465bef14fa7cab14c8594e692cd1d74b4bb57c764488982a47c359c0fc76b0bab98e46020b576f4f2bf128955f0d2658f6427c2e915d1f67c599bf3c7092fdefc1b9231552c36bee48497eac000fa2d9d2e8efe2cc7837576cd4417bd2f40e6a4eec32e2d8f3708eb8523b18c678bcdc6295e0d688bc208259399a0610808caf4498459dcb899991cdbf0d0cbfbacf69fa514369d087bac35f0e3a2eba9f0255be993e616d96ef9166ae75c7a1f17ad5ebe4b89be77414da11eda894ea35a8f887337d9a6b76f669b921901b2d04abf3a141afc936b34632354ef8109dc6c11a9639b2b7012eade54dd537b246aea98295a950a88228884e8013f28573a35167e604cb785beef08f27dfbef05528bf0fa6ab6c3e8914268e2166e446567da949fc77d9470b01729391a518c95e68a9efa85133337f0feee3f2c4445c2ee31e0b82dbb9d195696e2658be84983e6f1e8f8616dc8e2bb2a3fef11aa5afc1d14134deb5337402d7289654c7a7da916c2c592f8d3a195cdb05e1d1aad33731bc1c5e1c8d4985062b52c3eaa7aa98d2b2dd7e19abad1a073077d7a57f20278991f2fe2fdd37f0389ea4fc33825e8e5d95cdc4cfb25e952d7eb69b7430daefdb685c2c7207eb1bb4dc73f49cff741a143c2f7a77da34cd43515eb2699e68112525989194f78f1689f4454102e6c8d4ccf48be8aed90ff5e39d93302d40f5483593c6408eb60dcdbc740ce9313c15065f8ccc5c62b7011b6802b759f722b13dcb291c4278f8f817a1355988dff1695559dfb8b72f373aba3c2f2d35337039e0eb925b39afc842b4850da9ca8a59f3ae9933adae2c9bcdd224750c89b59b596bbdf74762d2f97ad65e67198e0ae10a227a89ab8d3b2d200f1f5bcc67c3f4bb9aa81bca610168b3be0eb1dd5734976f1ad274b097e67358da4b1348f9bc509b5bab7ed98bc79f0f6b135e77a6fdab8d0ac070b34d5e29ee97c7896ca485bc22ceac85918977e4a82f4066b6b564938ca6e7de983a592f6c96e55de02e877a9680505b218d42a388d358856c24f44c55061a175fded001608d910c3693b14acce694ad3e4791d91416db78be37ad20b89ac7ff40076f3d8ef00a8682a3185dfc2b07ba29628631c94e3613d08a7414974422a057dfc4b3a28911310855453948f8c34984889f9a674b16c880f7ee624f5be78a6a9c225c65c665099187896f090f6ccc302b5f1d51a62f43b88b93b38e1df9148cc73d727ca3b9074b560b37b31119270a2eddc6f5ed32980e9f77a1c46d0fc26a36e40061f0a66c70b9fe3ad154fe87256fd4b4031433e46ec44769ef5336e35af1fc5c49f8025955f363f21079e481609a198202d4c8f34f276686bb936660ec8f71ee0ea6afe889b7537b4214d433edea84e2300f4e2435361d95e962136a0e6c1470fc14193d8a61677116b66014940ddee031e94fbfa40fda956ce43291a27d6ef24581f9af8a574fb88a98e317c31de65d1c292ff40ae6266a44dad10479dd40d3465715d5c36803b1d803ab4f4086923cba9f726953ad4129ba8f0a0c9cdacbe5282086d994982e88259fd65ec49d496901c9e6f20429b5a6f224c5611c2974af917513ea2407c273f93a60263d8a2dbbd3eaf55ae70b50eaa9769ddd8cfe6a2f0a5d35901b93757df6f2c8db777751d10b227e4686084f976bf4514ae222ad05c8df477d28fca2125568325464884a875a2a9c7848f9b2ac3334a3618b835baf4dcaaf66bc85f3b7c15085bfb3dc17885b158872f380d5aa8a89fba2120dcc331e4d12f8dfa3fe2750e9c0e8c171da6642d7cdba79ff57348ccae6bdf8065a40323363f3be03d023b251eeb9af83b9bb84c21fdff76bac2d67ef9f882e9a5b6ce77d6ef487867c124ae2edf9c222f38cd95010f39cb063746ecfec30f08299dd169616d45c434ad2fb5cc84b1af9b1feda0efec398bd301a6aee3f88f45ca3ccec12f0aff968780882debe4016ee155ee7241f9319edeec5ea9aa37bcba421daf4008bc469720d48b0e7fc99bceab4c4e8e1f77b15380e2afe3916cab65264cc37e64b082b66dcd815ae9dceaf72a563f440dfc6f64225a84594d6abf72dc713a783317803cd03c960f22627456f6d048a0f72b120bf930f8b671185874f74bcbf4645ba3191cd3246376b7e33bcaa9ba50e4d089a8a45ce400f4c443cb4e32840339a5d363f77bba69265bbba27f7a6cf74dc34a45a71207bfefaf259f543282e203ce5d8ee14f8724eb96691973de3c6a3103691bc774bdcaff70578c5f229bbf687629d9e5c4be6e38103e412686e70332fbd9f6b1fb30ab47b9cd513470d19b57ce2606a3856ac7a6312424da1552142be4bbe3f9129041478f5038d2b6ddeb27c458f7af9370143cb6b03fa317a894a0c43970667f939309234d414e182099cd0f6f465507c8c1db53cdc4bea04fba4a5c8ec7b5c1f7cf1b085e8942a456410198ca53fa1650492d434d1360e50ad052b1d294ee3e28cbe05b683fbe296465adc2fd6bb13c1c09fc67f7873f48b6e803acf972a7d29360521d1ff1fe95197d46ca42bae886c6fd4c9fcd6089834b3daf2346a72ea119ffea7ba7b7bcc03dc49e9d9f616d498ab978000000\";\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(\"Chromemind\", 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 [\"Glass dome thinker\", \"Glass dome thinker\", \"Glass dome thinker\", \"Glass dome thinker\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Chrome collar\", \"Chrome collar\", \"Chrome collar\", \"Chrome collar\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Magenta rim light\", \"Magenta rim light\", \"Magenta rim light\", \"Magenta rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Teal-magenta neon city\", \"Teal-magenta neon city\", \"Teal-magenta neon city\", \"Teal-magenta neon city\"];\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\":\"Chromemind #', id.toString(),\n            '\",\"description\":\"Chromemind is 600 Friendly cyberpunk character with a glass dome head showing a glowing magenta-cyan neural brain on a dark teal-magenta neon city. 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\":\"Chromemind\",\"description\":\"Chromemind is 600 Friendly cyberpunk character with a glass dome head showing a glowing magenta-cyan neural brain on a dark teal-magenta neon city. 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":"58359808","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-04T11:48:13Z","match":"exact_match","chainId":"56","address":"0x688FFC0487162b6Ac7EdE1f10f070Ac717181C2e"}