{"sources":{"Botphoenix.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: Botphoenix.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Botphoenix - 600 Friendly little mechanical phoenix with glowing red-gold feathers and warm rim light on a red-violet ember gradient 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 Botphoenix 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(\"Botphoenix\", \"BOTPHOENIX\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"524946466a45000057454250565038205e450000102f019d012a900190013ec154a14c27a4a32aac594b19501809666ed9323d18b7962d7199a335bb7e4bac8e35f93e727d74ea6c71f82d20af91b0bde94ffae6f06f375e701ea2bfc27a5575486f49ff71c0b4dbc7cd3455f43fdb7ea4d62be59700bfcc3769c037726fe3f9ddfbafa8470ea5027c6c749ea8e1c78b99ebd250aa2c493c1180b8972aa2d90aa2ea8efba961e40121ac31eee42fe5599f43d918a1bdd6e08c281b7d24b98091368a3a0098065d10ddd84a9d4cb55e69f7f5d828626120507ab7a199a18a0e27c214fee307589dc2eacda09552a0a4f1f300f2e4ed658e543630019d82e19acc4e84885cb948f4bdb630e66751db249b261f8ca111dac7155d18475c3b941b6c651928461d7f47e82545e9acc60d0f3a575ff67dd40448f96b189fec707067c530ce2ff7d8c67933eb4b36aaead6ab25473ddba25500b38b11dbe8969394c89158deef3757a1a0bf82f00f0b7a70e610177796629717013a0ca58d145f30e1bfe38aa223cf111f4fcfc6cb5f488005a7fa91687735bc042ef89628afc1874b6a6ef6051ece5b637bd164a18f1f9e59f496ede5546956bf7390b4e132e7fd9ce062fb64694f791a64bcf56b85992273bf73331ea81a04c9f94233c91fa1fe9075c70ce7f6e948e6b4116b7763639bd9356a7f42ecd31e51375a0c5f88b7e2f8f7ecf6430d91396ad008753cb20b6534e8f05eea70b9ebe59cbc5a42ec20371b777eabb24ae129ca7b9d8fea514b0192a4c515ef481e34da4f151104aed4a2d7dcd9fc4167f4c03cb3e134692ef93b7b304ea1859413060cf0161d3e5fc6ce3ab7035b043c36796e9f4f6525fe1b674206b9bdba7084f1bdc5de1520e02f39fc526126c1bc17cf6677b0e89f04bd0db2973c7a5b1aca11a44a522b3f003db501051f019b51ef3b701e1c30159731e5f7817c8f8c6f2cbde8ddfac208f898ffb3394bf143a6b54f62e1e3b5f72bc1a4e88ce81b1e1e631f453afcdb659b5c7b80ed6ee1248b522e9eab4c415dc7409e37a9a0effe5622ba6b61855011726888f11a589e0346811771b7c69591220723dfb5be88af9790eaed83d6daff6c90b9a46d2a4aaa437bbea408593e2581f8603758cd177ac969e9ec3201c03f73a5bff7ebc0bd1bc0f12bdff3a6f1e915d6f520db4d5d18d6f04453906974300faeb0b606534f369b7b1caab2a541e8f5da6855634f89b050961d98575bf839b209ffaeb373ac30d8c993542a5b1ceb5391d5063e32fc6958cea2f0d5b22185e4a6bba18ae8deef3a1c28f17ae4594729d3bb306409cb6606ec19ae86bb7d1a5121ceeceb4227fe8be1999e3e15a1dd025835d2273fba16951ce97ec788627c33cf5cc806006fbed9e2b81852289d35a2fd4b538f5f93f0d0ecb11baed00fd1c1bf8267e627958a3f476f1001743cc7a7fbbf944eee69f919f8625ce1448cc461d681cad2fc64cecbd07352bdcc6bda78e6d36e123e6ec58d38dc6ed89e2017d8ff904305ccfc387ffffccb5574d5eb63f3af28c21b77eb81808dbcdcf7d1966dce54c1c4f8cc9cea87dff542ae45f542323be7bacd906d7f0837be49abd4f04362d2b8205a719c053c4407a4d2586378bce98082f6344ea64fbb6983791f09075cbb6bf66c75bd0aa3291065a36a829183cd9ea6a28f64546888eb128749464a8169bed06c7620b000e28491a2977f77a37bddebdaa54190f689c6d88e9050f96f3438c00c7f1aa3db41366df455911ca59a257f2ded2c49c603fb5aa859ca77cc3b4e5411dd39d1bf2ba0d69431e653298acc8862ab48468dd00dd9ddfb1858c6252f2d0870e51b6365cdab64645a207c14e183e5391e89d934cbd53b8ac61875b604ef1d5dad6d09f3c9164fc300f139c1697330b3efd1cc2991d92a0a3eccb53985870cf09b2d926a25adf3efbab833eed85db8ce830fd143fb9686d04a5b5046327a4d6a4f74123b2a660de21c8349f5f7a31a7e56782b7f3d76076cebb6f3886910e718b99eab006b9b3f9ec92320ad2d6c9d66a161ef8c700494d415ee8ccc32ab9ed5a44dd464b1b59a37bdadcaac231466f024d317854240359443b2b7e4ec0c726d985c949ae1a98afb9cf828a44ac52b6369629fcb4bbbcd30263aae99bc50761f65998c7eb995d4f0783c5e44d1fb843cfb875269bd065a3ee2b733047ee1f9e504e405184b50364f0f336a04d4537e7f9f8b7a28cb1edc9daadb238bb3d5f0d737ba060960abb2cffdfb31d1ccde616d7c11e52a679c9b5f61f1197ecfa77a697889eb1f68323d0a91ac55bb8a379cf96c0f103a7250c2235f6f0f0f16a655f3e446346ca74e580200e2d1df570dbd8a9636202743ed1d75d9f307a7c6dca84fe9092868424e51d1715a07b1f5b0ce62fe436b1577c5f9b6ffea47a7848bce9966fcf064c143f870ad097edb81f893a2562e0cf61579928be1d87c182a2fe9e3a84ebf808fc20e72a1dd001c1a9f2480ca25aefdb301b7f8d07c361563bc1dd8a54c7767058fab8a4268f5041ccb1d59ca0c8d83e915d2a848862fec155a73d7e5c56240ad5d84f1b66ad6054842bbbaaf81997899ddcbc15811b5782948b44f8aa72d9fffe910b41afaa0c65be92ec8d76ec12c592c8ab57719e0b388595d558f86f927ccb3e6a76e369b7c9406b137b29c1005abf1753defd9073f14dad701fb7ae48c63e4eb9c5bf5b69028f7901671578557feb27d7e15ffffccc7580b5ebf0456bc628fc17c1b8385b587af7d78785756356b6f363b20fc3f0c261e4da7644fd583aaad77f53270a2c2db07ecaa69d9022e37d67b5a48d3d79d0b9fc8268c769411708e87c20b1798b06c89fd98ab2cdb692f5293470b3054235f2901373a729c6b21efd2458d0eaaea2a8052e1a6d9bf4a577f264a820c8b1e362c7a6b7d986d0ec9bc6006724051b32d9e13afa8c7f5de015e324bc965ee8376bcb6cfda6dface447a0d3f0b84d355b1ca09c459b368831bc61ef8ec0e692e8cbfaa40d40736b7eb5b242c4d87eadbae173b266aad2c94a04331c3f24385ebaba0bfd12a9490d64ca276fdedebe39ac8f58c7c93657f129fc2a7723d8448973be9692b917e04663396ffd1dfb6802a5d01f66ed55bc573161be3d2e16323bc6005759a57f9a7b8abca4340b6c22b7af9e2f6f24369140492fee98ccd00ff3ba444f8dfd364734af9671384d050581b274be3f47f8bcbd1d562a4e33ec105b7ef08aa6caa2b9c6f2944b41a908d83015c5df3b15ba53188d2b0df34553314015b5634d7527d9b384e54c7958ae0dcc0144c1dad14fee7124402cc4412d2ed659d2bd6ed1893b3f473fd878ae2f0c5969fc40ffd47abb435f66a58fafb94287eb37802122fff72b1efd1a19df8045b71843e209799eac1ec3348acc0ba92993b3244bc2f1ec9d70ebb32771c1423b9c24a8e4baf5afa0000fedb6029a7931deba31683d70faf80e66f44b702899734b0325e9349bc721826c05ba6e383ebac3ad819b2add8a15786828b65dbcd3e775c738c524914c703d601c161b2818ca6ce8614dc4d08e17c8569574b00bd01f55a9f2a568d403cc028c39ac9f9c1f1468f2c2724cf6106111892c43af7c9ab8b3ebafc7a1e223162d9b535e378c0bb2c151949ea8494888c04607901a1f9b7468a48022b507fb43f6d20041d7cbebefb752f6dba0805f2001d63a47ec307d0be65734a6793267614dbbe0fcb71bf238b5df2c7c244a111feb60387f6ca71d7e4c74562fa1ee09728dcb9c4c69697cb060aeee7fc6ced9e422e9f373c629c839dc08e2e698847ab6600144950042f77200012c9698b34c29a8f870f1db55239fe30c3b5272ab3cd1adcd5dff5341118800dbf7d4a7c6df15ee3f77e8bf9a65230e6f830f94c84124f42df88356000298c37d35292a882062b498a31f6404bf3bc22138d760c05824a63e5198061d6b0c84ecac1e3895fafddac1d7c5c68fb52495351914512248985c9c84342f42ca89206c68f10fd24eca3e37be891612347e192e0dd13a9f298c903eb95cd801ccee0ea86bf60dc9f0a26dcad22cca5ea41d6f168d080254151bdef7d68b1d2fba2f5b9672bc35b31f0753a35132e4acc3f1323938c023942df015ef1d0fca8648de6d33f73cbd4f867b8f926e2f6cd52730682c3f00f9123c46589ebf543591800a9543174d35860d87e6d0435e218503445adcc7ecc0b1f29c70186d042f3c9201ff5a9201e74e0d03e8f813a972e615563c3a1192f2916d65a0c45a65adf3dd2277094f5a3fcc4e4c4d62815f42b857985a9baf7a91569a15e52c8a53302184855f49cdd0ed9788ccf02b93ea6ff000cc49a77586c93c556d24964e67ecf902abab530d15a0401c708e42be7cb8cc37f2649f59bdef8879dc08466a8af9ce82c0a7fd12ae4da69f85906041b82f9275327bd5f7cb8c00c2f1b2b6b6adcc65cc600864f240023329b0c6871ec644cd256250efda601481c75df005ca3dbdb61ba5251543dcd6f03ea6d9983ac981503a7e9387a841614a558f8b0403f9a61540a11e808c9e149bff71c7513eb452636cf16ea464df548bc33872d6fd212b840827953dd72113d6e9b728993e936b263f49aca88e0691f7126ac93f4e93d1559ff7a96f8eba732d407054bab68b16335ba7c698d392bd59f458a6c61dab9a880839cdba7c56ddb2914beef733cba4c00623cac807c1ce75f5c9a70a0ce8dea72200d82031d23b33bd20512545e1f6283b9dc131211ae2afd91972288233ec70f05d3b6f75fdbdc8f75653b895476e94b5173c9e70a9f1b263d259c841c1a501c4442f7ab2c3be5aa7ac8b2e93069a79a37b48bde0f1b5285ddd90461586e0f48a137e03135351292e7f4acfb33410ac7b00ff921a43db55d049f2110e293890b1d02be055a183f59c5d9be2759b2d6d2fd23ac1a36fb8f9427600f96cf14d495c117238ddccb9b391e7200b348b74e99ce4d9486850615262b0bbe6db2f2dcdc2f09b5d8f496c38b2109105d0f176768d9389134abdd7e3d300b17312aef606a91904bc40620567c26befb0f093415d89df8d7fb48bd268a33794672bb7f461c612ddbcba9c210baabb6926b5d7718986b8207ba8c866b54650da866b1ccd3d1e2c3802c3d9a4e911e4702b9afcefaea03adbd9b6eff09939d99223a34cf70f47bac1e4bd1dbaf56bddd0b5b2f09f09ec6ffb6a0c8d185c3528c1f2b96fac4fdfcdc9489ebc9e1b9531558a0c8d1931266533b3183ae44f6d6bd4704cb86f394a7b6b026faf4fce96a34f5d80ba287dfbcadb470c0c944ba83f99749b9eef62f7feeae5026e2823948ce179b8835707b2ddd654cdbe776c54e3c003ae46103cec3d891ed3d49adf496ce9319118708e0e14848b4af9b2a5871e3d8059db26b7bf9babcb01b2e7e2281f08a939a4625b3e9926e309e9f3ec887f2fc5a17e653c989e596abdfaa331a8bdac1800a5fdc53e3252b3beddad88cd0e3a4e9be12b7fc26823ddb34a4b432a730a7122833bf3c880de047c3130757c5cc28011e9cf1aaf8c7c3d3dd387a50bd9811ebd3f7e8c8728b869f73e1450f782791e8eff97260c31dbe37b0e571a46c71669a26d0073f24c1a907e39ad635e41bcf4d1d35be33e8fe617408d6f1ef48391fe351fb321461c2046b4df77ddde77ef404d859b9c8b498320a12499dbebe1c2b47532e0912f26696c76bd28d83fe96829a2e9ec2acebefdb7c7607bc8ee9e947e0426f0c66d4c1607c1e998dda2eadc77e4b969b74d40b1d30c34a5a71e5dde68f1695d0e8efac96e1010b8defbc31005a2dd07221230ea922b47002a365b2d10a91103ba8765fb19ab864bf087c4893563d226d5750abcc409062ffad14cf035f61d29df6241e2f58f6b26846a7c02fa2b97f35d0c15938d3f835ad307b45a2afd41f4b7d29d93dff3c8b70105cdd5536fc91526b86fabd8e97e518ecffd19bcfd81e02f1e005bec4a67ed381e7dd3ec831fd35e290d4d6ac6b095079ed0a327951341e311949392c0e49b32cff95c65e761a350f775c965d1300147f15d9a29bdc9582c3a4e51aa5a92fdf084bf44aace93ea8609162f2a528a551cab3cebc2b80c4538d1cd31e1a19427f9edc6c6a3a7d6ac263bce0e012facd20ea38f687d1606407009dcd364d81d67bf39831af58c1eb634b252db13aab008fe738c7b55a08141f9070a8f93d6a8127a18845b44fda26b31ddf1410e2ad95e8ca643650ac511027a300877f2c18f59027f198b0f577c9098ee6b4f41347e1b4a5776595eb530456cbffb82c9063c21ffb27c512127ccae8e6c0ed9f89c31b04e8d8414a75b76e5435d03b514d35a283462301fdc38fd11e79237c4794c623d42dd066fc1c4442201287adf5f00a71e1c5d9c28e55c3906c4417b86ca3730ca7ac9d82acf7444f5a138ea3a88d34ccb2e87720bd0da53ed7b5c796060f12f6a6f984dd151b6dc54089cea5c57c111d263b0951c1a2595f7e16c59fd8db55bfabecd01ab165e330d62781a39a0ea4e7dc184b16b60b9b370c4bc1a64a2f5ffe63cc4988654a84ce93aa33773bfc772b9d7e1186593cc4474a86f0ed8ec3e41700313d8cb45d45e5476b728a98e44782384a5882a12a566052cf26a881fea6cdb48f66a5b2733d5f78107f2c5fc098a0068a3d73d68261c46edc0689f91c34901eae4c8c8405c9b32190b167ef3ffbd08a0d91a1132cb508e2f0c375b8911e7c8a35c7e1ef645b26925d2fe9eaa99dc44a47709d0a9458dd5a50bf283e74e32d008c15c280ce5c16f70c2d4c50e3bb87cc25e98fd2e5469a355d88c3e280b1dfd36a5783ad92173ecd01ab58f2160e12a04b0be98037a94afd407857d540c45e5611ac8fca61ceeba5396b8a80f23bd0e7790e830db823629ad2d1bb96dc48d3d7eada421f74d542213fdeefe6b4ff74f56a2de9718d45d4a525b00dd256eaf092e834232abab19dd99fecb409fef9a1a4c155c7ff0b58a3707cd44d28acd78bfb73d4a78386894aafe8e651110b7ee14e68e62782d604085d27b6a5a57921e1a8be2056d24e9525fda9123cc9a96917fe4e1aed18c201079d642ba39f051d29062fe205420572696bd48c5f132d85b28a0e867c33e8e64b64c5b72da83e611ec1c57b164074f52698f9e63bbf305b94a530cecbb31571ee07aaae0b13816fd818f975b2476d53ed518ee74987e8191f6ef3a305db39e09fcd3836147d176bb633e932a98f81f68e42672d9b5a23961397e54b1f711e75bad12da58761bd3c5682d79a65e411238968dd74459b953454da902482f6b1e73a0bb42cf2c52cc9030bfee03b24e82e637bc5740911f9e7d09bbfdf8e79e2af12f818e98683971b4aa52c20f3673edefe1e52235b598dc5b9f1a56a214b8d0d9112d1de2f695f056b474b1d2e00f6c46a3fd4d980e755377ddc4ff272fe07e188f7d2c80bd4de0f9b3a375ffa359843d6ad75407b670165899a7310b242fb08d5606ddd6283dd44f9ac3f452a107c0d6aebf8d9ef93e158ec39079920261d244dc26c301bff595492bc7348d7e0383822a2ca31f34c3dc5ac05e1c3d82c71ca84442398ea2b128f5c2a8e3eb6604efc2e817e87c2bc5e01c79ade68b89488e40b5c9ad14bff5ad7b18d1a5f7cd662988492e20905ad139f12c1868f3cefebdd533715a1bab65e59f3bdc2689f6fbba2831bdae1a52c08c4775783c1554a4ab30425eeddf6cca937104940427c3092df2fd26aab679c25084b4ddcb8a0657f804ac929eb68c8f384bb5a9480b08d5fd1d611d65cfc4a37ed2c271ec6eb162aa65fb19d9a7f67adf26aa4f1338f5aecd3003cbb3d8c0e9091cc325eda0edd827e1986c87def07aa2be67e40dd92be1495eefead64101ce2b8cf5710f8d4056ec8785c89469083a4f452da8f2dab96eac6e0aa9d008afbd1e70d86371fa50b85ddb1ef28b50225d98374e637b32137eb44ac0236414da6dbbc8be244acbd3381912d0d31190ddb31c88f53c030a26847d8a56c3979574b68247186b649943237a4e97d158eddf71719b249677efe1c0f266d3610fd3c14dc91dfb816071ec28a9a18d38085977a721b4780a803f2e1a55a10ac8c72e3771b8d9d02d96ec00bfa5974ecfbd5fb021c72d927bbc30a90909f5e56a34c9f0308347743952b4a68ef08be10bf1a97d0af37b32265efb3c1c7d1370fefc716fccfdfa859e9fe30afc17776c62dd42149b43f47c11fec102d305c6b3528fb5a30ac7e63869dd54ba1de25d6b427a3fcc609749d852f32eb277cf7ec2e9baff47f4d4ac21a26f7695a23fee7aed45d233ce6972e1b6d1ddec0804fbd1fe1825ec909fea1dbd8820781b98f850c97613b2aba921e33abc1b2a92a4482576cf17acd3a22863e6c846bcbec9b5275991a9994934b78dad6f33439e27ce7a94e41f1d767a5ab55bec3cd919a0a87a1e1a1c5285d595f0ce2d1aaf2ba005756d66ed8d46e124cbb9d04bf6ab25ef72f77e8d2f97dfa5084dbbb0381ff6aa42259c9cf0db173b42b3ca92dd13f48f63c6240b72479cb7ed1893bdb5a470dfbb2c2cbd898672b259c22ca077004f795f2c720e344c78e534e8727acd7224a607fd95a295ba1b2cb844cfc3093bdd49d17f175376563a7acd533737e46a6c51cdcab250f953e5d01f85d61e8c6a124a4aebdb01070e0fe4c9c54fe100e14d3ffb454521aceb9741060406e9d52ea07bdd19007be21ecfaea4534c6ee2b31308dc904bce5fd71d6dd02b11ef26b1d130bf32ab59635e878e56589a4d59eeef84e7cfebfbab0a56d16294826b3d4f4c7f82ede23eb1219855b61a6c2b2a250d273feb0835d9e0a014d57435bd7fb345e309c551596fef09e010e5194d376196c57ee9ab949834776de248bb2886a966f37fbed7310761f3fd28494e3cba496fa738685f540547c39c050f0807f9f1a7e49873d35ac0b99a0ddc22b6eeea65344feb4a96ba90a6d5e0129185605491be9d3e2f13b2f3ec50e31c4a5e2db3dce610dcbb2a2ff58a6be0b2d2c4274740bd02ec42187b5c5fc6378fe2d6bfd8483cc87af6770da0d71de0db07496a99e2ce851587e9a148f543309305031c88bb4a8b686b49f960dfa83a60ff42dead1597a5ac98f900a97e339194f1e05fe4827a6f19c8a10da1e5856ce81eb5cf5a70c39bbcdd5bf8c4ec56545d7a435490bc4a9059183de8286929a6ef7c8372fa67beeec6955738936574b7b2745820df52395239e22e26ed6e02578219bb0010b5aae8b566853bf6429bcfb4f9f4d75083e668959d3c2f4b04e646b53a5d51f23722e3a9fff97c9972323587c70fabc4e48fd17a357639df924c7f5214f60c209dab220531e72d8b7337f653eb51efcffb51590e6423322ccf01e6dff833b1d00e482a1e7101e3735e3bb5eacf780fbdffa92e471e8a0e5aefe5d2df02a5da8ce3b4b28158901d2aa660527eb1b707f640609f001f9496576bd2c4def48b7156a7f2a97ff9465644e688463ba8030db86d160900acaf5ac23107c2e52ef5f9df3da829f91b56f011799f5214e51b7bd4defca7ee38329582ec1d1cf1f5769109f5c86ce02a17c85bbf441b00139dbf3ffc9b4746161d64945b241a50d94e937f56ba534e171a379ab31fc179b1849f1726a5af8d958f080b0961b30d6380fe599f11e43be83237250a9dd166fc53a3b1bac4ae470b073eddcc0981af17959fad30782bf6cb7fa8eed9f34f3599bf58c5cef7c2af7cd05cd6096c8cba59308b522cec4b638028de823a42aa2a3c032352ecce78bdaa35dc2f8fe39631accb115cf50f927d375b966a312cbff6e03d81df567b1b6d9eb3b3050ed2793fffff7d8b4de9133ec1c1ac9cc0680b3c1be130681a79211483cff1e8bab5eff973322632abecf3eccf75fa6dccdc29b2fa4047df125ae1095e4a877f495e2c833cf4b02fdb41a30384e3acce42ae59da9bc2765d1410541346368c8c1c7efee1942ef1b699f2ac01e3529cab3b8ebb2295b5c14ec522b925bbd3fd23fea843f2e08f65f8da3190c69e6fe4cdbacb3bea1e35fe194a4a1577f1f8d0fafb3b2063d12d2704f928390257c38749e1f32a1e0800dbe5dce3c46904afc4639131667c71a0ea9908e152a7b704365801a63a5a718bbd66909b19e12e2db215a8810c52c28bdc6fcb083ac9d137fc65d9a2dbc50d584e4d254724b1f31afe41fdbd0d0ad0b92056c532f050507a04f15933c772739cd9d5a86fa846fdf958ae88d1a25ff703fb243daf18946563fd32499ab3db082891a0068de42dd436e6538505a1ad855b17f5b77bdef6df2b9fc1015ecc1df1ca910ba4f772756e3771a6a4a9dda34df16a268ba78e7a10101bb582e8acb05c2e0fea90677a2f385fd77ae3d723c3d4a13bcec288373cb282184729c7d65cb4522c22ce43a42b2b838a017315c5e3a042911d67843625c073b962f0fe8d7cec4b9905b43d3f47e1a032c7004975cf6a018d65f7a7aeb7aeddc1f1704a17fb88e519671aeaad3f0e29431cfe27ea22eae5fd6bf38160a42702f128ff98c4ccb8b4b8dfcbb76886c9e3aa5a60924406b907496b052501ce66ea45873781b56ad1728cba1fe25e47cba8153554186a698eb5f53c1ddd89a9df085d18043ec15091a9a8e13bc9b60a8999aa6177ab230f7afe80ce98d43827fca6a0d83aa648748257ff8321c4b27c31bf1f48ab2ee2c28e309d0a040655918a804d32c7ffebfda51b2e33465b837cfa9b9d915a5ff306fa848af26427cf5f68f232ce04395b7295e6a78116a4b2956be69b7396941075d41a85ce3eff0337c886c5b5b4ea9c0a4d70b16f0a520fa4e54a1530cd2f7699009b78623b38f88286cb845d117483e839e9c1cdd84da167ea4511d3151748179e50fffe183e472284908b50ec4c584106d36aad65814b24a2b9755c51f934417c667d2916097f34d879b5259b8d38cc2cd562996258422ae75d2b77d38fd42b14b5f9b0bddd85b7c602e96f992ab2a693f9355143194223b420584a665ea56b6295ad23652e3eaead8c15064d6ba97d5312221f789d29e129fb886b982fbba75f1dc642ee6a267549cdb0a6b600dae4d7aa9b44860a86a7488c37463661dc56c22ba1d6b853fa4e380c78da53b20ab320ec499916a890dc9c8785b46de3c969098ab955af30c5926e19ed57a4bc21778308a4f626e2dd923d8aff04a5a8f7573ee52a07f8f090f622dbe3b52148ca8fa91836055f8052018621d93062bb9976aae3652a90517900e5716f1300beb465ca74dcbf4d1b7bb9efbf18c4e79f401dbd1bcb0ca386975755f123db0c96a183eed6a21ffb296382e657723259620e2d026ec661f23bb95eec13d7c4efa21d74d48733f69e81af1367f5502bf8af2110bc608d87fecc556c687c64255c8d1938ec3c5376a93d85a3c1e4ce800dacaebc10f434af6283e462fadff9db6bd22ad8f2b14b0830d544c189eacca5da49bb2a182ad8b2fc0a944b08b170d7e08547b4fcbc8e838f7920292ca9b047912165653933f501c10d8f79956a34b690a2de9833dec67443743f82399d326814fa6f2a1f69455300d9ade2ae4bf4b196760584e57d2c1bdf170d87ba6a8ac59549ae4437292aa0270b91862dc956cb3abdbab261e750a741e97c186d23550019c9945205d35b9d4e33c41ec6f240479c32214c85dbd4f49e365b1a7ceb2f27c3598c428f49c684071339552e613f6aee2892c6973988005c0bded8a3099bdc5438169c9432646f2d32fad825a6dec6831d2cfba51f394ace6fa506aa2f84c77bfe4a5a9b8dd07783d76aff080bba0d58b12262839787b6bf896cf4c742ca9b2555cd35c7864c0483b121c648936762982f812bbdbaf735602c68d032b50c523ba8fb82e7674086db0c5d6595a22dde1f67743274b6075efb728a12e30c5fbf937486eb1b9357e1c6f99cd91433c25c617a69593795fea00e7abdb4387885d37573d3e680be80f8f5ff7833aa9f49d39672a5d33828f53e5fe606a232febfaf2eb0cdf0995bb51376c6347d88cb5a7d426f2c5b1edeb9dc86fd35889a9f36163a285c47d9853a96bf425c61c483b050796ca4fff159b7016e07e59ea5fe8d5b382ca8fb3ad80b600916acb9f2c5648b01a70ac4a3bc63282f428571e95b9a1fd5e9ad08b0652527fb5b39f8485f6b41c0edc0da50c1613375f09284e1f33ba41b1cca26e7a4465220a9d3f0d9236d774cfeee8250913ea61ebfcd1c363bc6cc87ba86dac1666329b1abd65ec0d7e2ef1c2504f4e5a13429cbe942cd61def949f6eda5ae8d0f8a93b815a2b02e92a965690d017ee27c8b6fc0ee0b7ff4adeeeae81e3b731d3ad8efe0935a6d9936d8d08acdb9b4df69a06cc2038814d6c01adc14353165d4b411d5e5c137072240340d050ad29093c4a9ba251baebc45592ba780a6bc04a8c202e1e9d3fffcfb29ec4056416ef77c0a2944945ac702eac0ddad6688ba8cc254b2bcf744700fa90006881f9dfdb6def4845ba2c9c3b256ecc7d0e1797be9bfdb6c7567753ba09c0289b1e9edda6eb4ee18ad9370dd6a25783a9906a221fbf375f77739207cc4e6c457e2d00d864c7551a96eb7e73403351727750a1b487b1e26d30907bdc0b4c2c660786fe592c24e63f9860d8ad504676b0871492c7f6336ab594572407e6a762394de2caf5575882829553aa720f0b70e17fa7b3d84684388a7105ad13225d73c263170cc5763a2b02acce32212565c80dc3a763dff815bc0ba6850d179b79642c0d866838b46323cab91cdf5fe3fd90b60a82668cb4905a79319fe2359bf63e16c797a10673ad5510ebf75319b80da614f715f301b4a8cefa1caab1c6bac83c4855b71ce50870a0e16e5f5b71fb2090faab76c662e62927d933e886f20e45d08f578f9aa722621f068af7c4aa7bb6d84827e7dfca38a6554099bab5942aff2897d1093fbace3ffd46ff1348f1483cfc86733d57fc26cf9f93126b69a6f43ecda2df9854daf81aeb8636832613c8cd2c064cd9ac4b7f226000b7e1698b3d1a2aa59733ce0bea7259e7655634049888b789afc6b651fb8f3062008e4f3be7c8afefbb68061efec9840797fc1a61b22eb20627fcd6d4a1a679a29f233494e84d4698828530350f282ba91cbd07f77e9cd0e72f1d713187db825552eaced7d812cd153bbb45d366f48734b1305206545ee5b895da05bd17ffbc90bc79ebcf22e14d8a2c17c956eeaf252ba63f20f00f9211db080e16f59af71a169ad4bd2830f49dd7fde0959a1dde1f6cb6c69a2a3e74c61341bf86ef407942ab7d5e645a7c252d16f8b9f1d4a6d32a9555d13d53e6ec36fe70209783b92d14dd7d1aeedde61e78111dcac2f77bd3a14ef9b9a5a4b6942131fece44aae2deb1ed756f7dc2e955f7cae0802260002ce61c5b5423f9cbfc172923b8f4dd393c2678d3728bd7d4cb2305bc18d4426751dd8a217cc2f3b4aad61317a0396a6bcad5c11815e9aac7009b4731d9c8d6d0fce4ff0349f512547f69864902894a5b778228414112d06602f7254f6151ff1155e01434a8d96f41f8b13c945ecf0620b84cb5fc718d75aff97de7c4c8fd3af4c4559daab03204d5268e141b541174cc6b3a9aad269b9f678e66c1f77ecd67f5511833a7b46fcccc91604c599d88aadbb8e41b3b5472fcc09ee2135c634f869a879e2c1d41c3105ccfb4e8f0130af3e221fe3dcd923709462af43ec86490d0cd7a10f53597b779d1b33c88120e3b262ff3701d4e7ab3b9e83bbe8ae8d72f97f974208a154e414cffb561d27ab5d4b778dc2a9a7d96e77f1f4f0237c2e31121ef6476dda662232ec34c670a692a61dc76be3d276a3b7ae7c54938554f41f7bb1980d9662e13b8a1916e9a77db8c9b3d31b270ce54fd61fbd031649a06b5988b4fc3ca4160472bab290c916ee8d362db17fd6d3cc661f66d03c49f6fb273e5d8394239d8b39b6f89997dd7965d309ea9db7a1c7d65b3356ebc277c6348b15f43069d78c7910006b4a19938ab4790d5179a7b4ae6dc6623cd2dc1b36ef7ace35aad1848f721bf54710fb2ab5da881b1ca61aaa32161652ab0a53605af9b1ce61c5dc899148e0b8ba6494a7508bf1ad1058e8e69c17e8ce931da0d89c32bae81372d4a2b567114c8d464af5750e82ad2405ee0b1a173373aac8cd1818e256306c7458ed9c1ee08a3c32c3ea5babfdcd086346979bed24fd61fde9d96d33cb0caa6289849f00cb051f9a7510f9c57fedf4f64487651de36926f9f16058e32f80b1c8340fa8d68625fdc1db0658194d83e40967d9915f31e395295f8413c8ad0ed7f3cfb32343e39f450b2b26fd717831dfdc5355e5eabe0b864c6ea0844698f2eb2b1a4273a464437d6d78fe38babdef8d942b2b83f3ed3795b206343bf87bb381757393a68a9415d740e914f6fdaeffa7588ac95fba82dcc7788f5a8e18f7fe8d5a0071438285cfdd0523a1edd96cc50a52d815f5411873737246638c8b2193e23ceb6a809c9f6eca632464161a7b54cf57838d27391b1c236173307bef1efbee780567e8951a18246391e5f2936e953fd7186e17b975a4448bd9acd8698c70d90555732a7b057116f72e9c335660fd53176066b44f024730f8a548703dba2be3358e1c6fffa5ea3ab195e364f3036b9d10a0f8969b919cf569420d9fc7dc5190f1a6bfd4fa6b497f4e37053f506389425cd81b44f6d3da72b615b3cf1b70b8de9295297ae60bdfe55fca03f5e216eb68cc02ef6ca7401a4d7149dead885484f5c49fe22de8ffded7ae19c50c06233f1f98d53826206e0c273031ef3b779e9eda36c394e5f0860a060baa33dabd9dfa56f9ae4c85d44f6f9c2263609c36fd165ed05666f1e2ce73b5283feaac510187f1cd5640c9637ab0fe8e5f92796bfe57d34777e7a6e82cd39512aaf6d71c6350799d6c7440707f89174d7d8e505cfd1bb369a5a1420206f655e607ea8ae766b02a68d041fa115722b9cb06c7e8a2ad4210d622cd113ffe94653caaaab07b93f20bada0ffefeb446c44fcbfcbc2aa97c39f68264d3ee214fa31e43e4a56e1250cdb6a1b7f35bd6bd013ab53576496b4c43d70f9b4299e57f497d2425a01c8b09ad78d17dc3c7065878d7e9610c81118fe56b301071e4e6bb92ef6aaaed51e45af59228d3a3ed3f6144eb6cbf057dc75c7d078b9f3b7b487bfba38f1b41e6d7a23b97b96e95e4010ac0e9c9741ccdcaddc2f02a4a9a203a1998a104692e6fe05f383ec23c02c2976e5df97860d0049ff8caac2a09b65b103986dc5c76e4b1f50c850587228bc4f01ec9bd9d09198047c9d1d03d290166919a7aa43354880319a04fa3abbedde92ac818ac5cb50fe7b6139c4099ec03945226667ffd034a44ca3c99c9d40cb699fce29faec079d670a5d52e6b2241895bcee08fed7a64d1118edf80df74f6d5267160657efb42bc34ed8e2bf7243b80ca23fe70e7342127eac3cb895bf9f88349de911e1910a432c79780a8c6fdc4b1c256f056bd06a071149ad70067b1c87475fe3ebba776e57cf4838995fbad08a0e3edf29d83dcedf5a601706ebf84a1304e65d7abdaec36a45c7d75321ae78bb41ec381c74574dc01341f88188b82ee07a361ce93fc3b275ad83450c6d5a3d151936f8506c537d4ddd9903251ac7ae44a649f8a1b0f709eaac6943a295d3db6dda2016ad101013a0a1d3fbc8687c6b4b82e1b9440af41ee6171364bd1d46d00df98a56fbf8100d4b765b692a7ab640424ea4837b0db9f0352ccdc884ea8475b7a4bec9c41f4d3ccbc2150d9676d1c916066f6a9d7391e05cf889e13fccb845fc0d83b6c23efc5fcae16b15d380ba3b10391fb70b0c269c919c332eadef186cc2ca72defcabe718a0da9c544fe497968609694b7d924808ce833f752c9220c1f5da15ec45fa2f845527498d077b6ac533c22de3c6aba3d8f598c1ba90f29125e551c668adf18418ce7e37eecd1cad95a48b9a407c7a25d55a216a6e96024048df7df8f896a8458e6b14b932bf34f21751aa7e57a98920f6a600583f5284fb47ad57aef7f021f2e6361b59802ece606c37988eb1adb4ef4b798d6f2f7d591b82636a7063354e1ac90a18e05e9df5826408c84409a9de1ed618f74838d0f97de78d111425bac5b0a8552642daa51aebf5e9663a3b73fb919167b46e6ca8ba23648b9cc9b8b0363a6d87489c2109d67a5ac26b18d21425726d0d259d876cbac3ebd0b1b986ba9e708624d87aae83414863ec9919a50bb876b17abaf0396520fb87144a7c34fb47afb35b26675ae6fe17c9e2c99ea482b0b95f09f09ebc2d45ca5007af26916000ea08b397fa9b4b1cfec8945ff26a0fa84dcb437f63f17ef73fb8f400ad2121b7f66a35e1fc325ad8d7051fd4662a4318c45fd33f88c542f2548093f86f92d500fa9919f35dbe499113afd5d6b6d1ac8dd9e755c8c9397d6ad588bd239e7127e735a33fff5f9113d99fa9c75dc0200fe9e954298a3e9a16944335821f3653cfc9b11f7370626f5f62ca69a3639b398a411922f62c852806adc36869b2de92c83b38ad517099989ab295bdcf5eefc44d049618afbecd0e21dfd7137723edac891c87b861df4028ce99ccd49ba36aeff3a70a60a36faf42932745abe9e824f29808598131294dca763a42bbaf986f701e2b37bfa4dca395a372f9cf8e62635d66a88ad8a276444b5903be6620d5b6c96d8c15460745d28d659d2fa04d3fc4d19148dc921c16bffab48a2ac07830b4e5e1e449f6673d37e64f61b8cb4d99282c7e63107428ec611c4f1dde87c26bd7f285566d265d47fc53837c7d77c9487007d83b2ca4d6f6bb97ad892de6fdbfba8d77e4a9e0c49a111301425f458eef8b9dc5ca0e7cd1f6f7da6228d9200b2a6e132dc28943f7b696001773e9ea656b1febb8655d5034107626e250222c6d08135176fb65c6eb3e6163231c10003217e56386a3c63a43c03f9bc8dbee16ea3d6d9e08bd8ef1f458858a6ef6ec482a9658c6973ee9e3c300df8fee7a2d8b0ff1dd1e8ae322978b9992b056ba3c28041dd08311e5a09156544ee851882ffc127785d96ccd3c545316f374412959118aa6b9914773282e76b5cd2ef7b1e7c14f37781c285b9c1143e3f6fb6680cc7532eacdfa3bc3aaa6231139e0fa40d65f32fefd49e36d22a6ccd978471830e7270d0cfc1923daa98a54de69e07ee53f280839e8e8ee82684bcb2dcbd84edf5565994c4356f27234e32e2cbd7dbd819cdf181490e5b4274b2868d694f2f9700f616c9ee67f978a2d6ea89477c450cbcac30a71ae0c6ac472111fe17e55b1a1cc479fb2e002ca77c45fe8870c02d857f093953e341ddb54c273ada46835cccf216d3243be788e04a8a27158aaf6b3c38bd3aa11a3af79d2e8ea2674c30072ef4e82e48217e51bcd01f12eb4d6a91ca00c5cf92e494ec743756fc6e22473ff65c749ef86e6fdd707144af8feef555c48a0406be002407a0270980470b86c9caca92ed27cb6a4cc753799a2c9835b1236bf6e8a457006ba6a13517824b630089bba2320d17c907a4b0e0f800ad2321fa7a68f68424ed983e552702931eff8f8a64239f52a7fe18637077fe625a524c6f374a2b7c5331ba7c9cb7465ede1ca5f5ccb0110e4d0a4377a2c313eae93c441276cb79155dd1590b933393e50af3e0d719bdb69e6704598fc8ff7730798ae3dc9785159ff28e01cfd44244bb3eae321136f16d5567a18ee1cf732e1812e6ae4d142f678a822a1a0f3f2b6a67748a874aeaee5330fc6fab240c44f880f24f839763ee5dec69f3264bfb8cff8b2e61be35ae802fdce2c3cd6cee647a9c130282da9cb1c0f8266898766c9742e52a887342a66ab5ad224ce2248544ca6e115902c3c5581eff8dffed383fa8586a190b5c14267c950b339a7687c1c1fc2c9887a87303309e4822e3ceccebfac6eef6e4c241ca4a5c8b2b0db27a9b4ffc5f70f278388acd1879c437f015ca87ca78bc2bb65ee6995baa30c5658fd866450a90ec9cd6ac25ba45c1f52022f7798478db9bde00a659b00bff7ff0342d864ac6f243d3aa703918802c69d323439d37fbdce5f4be8c3269b7167732869d7d00137d235e2e3253834801dbb0a2b29a2b7cbb9bf1c2847a2f2701a3e06b698ac37cc183ba30612388ffe76e607984112473b9e243f5b0b89cf6357242766c0e4ce633aa87bc772cba0869288419b48ebc0c492fe6411cd9673571864f5bda17f08a8a4cbd52c0e1af84b5e9b9a37598d639f0134f6b2c3febe73d731aa3e0af659f5f89920a8ae4c79b091e3ebe63aebd4ccafc7de5cd23861c35256615baa8f52f50c1861ec44ac162a561cbef1929a3ec92e73a68e355c63c02c0aa45d1dc0090e00748c3193a53bb122da0f6f7cc2b41f2d204252d884e76c88b7cb8ea00a89df2444b0b92af1043233658672b49f3b63ce472d9373cee17f3ecbcd4dda2400554b0ae14898ca7ec858fb5f303a10fc938ba1244117cc184f0a9a1afb4cf21c07a37f83bfc041f0644f19982df10ec714ee4b73952042b454ae0b87265430e1566bffc0458905e1546e264341b5fa90faeba467a1d24a5155f8ee4e486bfe6c609d1df06175fd4e8148b2be32313e80220c8843f2393f91ee1c6e5812eeee020ebf9a51c90efc828c68fdd6041e6c57c7f8823751916fdce6d03dff60f6af8a0af6ae676cd905d70443ba9151bb6721e92750261c0a5980fa20834bf6b67a2887c41d398c9dc9910d68bcbf278b36b143bccebae2611f70d291782d6381e157f10f9f8f0b048eb7ee5c65992c91be4d20716cc7186f89f790f432b8614f68b0b5f29d3a34b7f7d79763b94b165991245bf967243a5f871d4071fec4e84b347c31b62823ea174b1aef48ef04560e0ce695b0ed803cda13b887909aa5d60228fec847621931f959a58d488b6b6d4e79ac67a2395e80d54c0e5540c0d06c558962f10eeecf0383a1fcb988ca57cf51db284949d2be5477e395b3db70aba0a92b1fb26e69d434ad8e83867b3ad2f427978834af66b148dd5798e6ec5fdb0341d2969c288e2a821b9678914b9c515771217f1db5bbd0078cc78e10b71805a56a36850de8be259b4289e5a08cdec7de80d8e84c9a79f15cc79ca8a1f91b553d0304673a99bb7b66019099f6dcac842ee1ed838a59f28f620fc39a1dde2b752efd9f99845c1d051a55e142d4a6b804e866cba59f3564c5b9100db3cb9e17d465f6995857bd7859f8e722cb39fcda89fe0275c2c6974c72eb66e07e1257d779203531ca3947fe76f9ba9a5173a9e92acaeacd33c4ec143ca2627d0c52ec74c3d8c08e167cefecfdc9c59a4c8d534600cfc869318313b39228b228f78ca733e823dc72aec21995fb7a8ce224232ecea2444188f0a9d8d4d9659dcc707e9c2922f4a1cd54f0af1588d77c4cfa0d658c39b864426dbc3594dcb1d25f1ebb1637d4f4aa38d59ab51aba86c561f3faf0126b8ad5929231191b9c9d04b20402f0f26d738cb72f9517b0a4de439d313f078da368e2f8f880a7245d117d972f73c2c6ffcfcf1a603da737b6b316463e94f37da409f0919f2fe74e6aad93c30a7bdf971f9ad8b80d579b3e64c62c33a20d79cf8197b407e8ad6df4b5d8b2449df7be523a770ea7ec7e1489f7f9b3345e671de1db634258d9c770533dc2d991f277e0c529f4b60cf1046cddf343df656b9fb8bab672c79b1d246226c96368c8d6e9a6a2acfbe6dbcdc973182a10362a7ab2a5583c83c3001b36a07ad451488e521c864af4d4fe125d4d8aded7c95f9b2b2535dd9923e29e0dc34b3b37f2a3d3a1908d1b00d0ac714979557adc347707abc5656571cc79712163822949cbb5a6f48f7ddda29da74b099f98df24338282f7aa79b55a07b551854288044c07571ab2dde3afa1157c13f4f28e6b01b8ceaeb9f61449a130c59c15c7a8f86966e6e84ce45815a71b4cdb0f4b21f52aa693c9c600b24d1788d0a4b1930b77ba9495c3754df8daa2a5f74c2273262cca4a96dda293ec6251c386dd16d68656e65757b5d0e1bcca8507af7bb59d4376568b140129b1715712672e4d03df8db08d7fb198a8730a900bfc03b569f17f0793baf86d3cb4c5c6f8afe5e17abd2936e59932bc0aa522ca33847c1abe52edfb95a0a5414ebec048189434fc781a5d3e0308601a731699c17c633d6cf726af97bfd25024a2327b1d3273fa1476fae36fa3239fc7cba23b566155c9474a3e5a106e8b9a57c24b93882dd80f0a0ca3fb5b7255f8ab522921cda1397d060bda5fb8222b38c615b9ec39a847fb138db0d439b11c895335059fd279efbcd421567809c2014ed335254c74fa25675b001283eecf83df6c16383954e05a3059b5413f10de8230ced5eb3a40ba16eb34e961d8a93e24d88c39e167a20b74d7cc7592a555fe4d921b97770e0a95d143aab158d5db8ade882aaaf8b9171a26d0f99f4319cf8eaa661e72440e1943e66897f9f60ff65126e4eb8b97c8745b7d5ad98965ad694da986117bec4affbb61df60a169a1cc7242fc469c8d5cafb1e1b2ed20a9e97f01fc3465b6b840f33b0dd1d0348e14c9656f770c9373c0900a92a28e46fb8afc640d8eeb0c16ecc634d51018e35888e6ea1dda9645acee18dd77388b6c569bbd1b78c9ccbf122eadf3940093a08f58607398e9a7d28b1b8bd84e9bc9f8ac9ec47e8dbf6a96d7d97530f2b42537871d9712c3136de1a5f0697e1b2aa9ef667859514f80952eef23881be54db782585dc16fa26edb8f26f59d3c87655d0fc1e2f0495703c2e64a458ac7e7157e8fd99db2fe7f6a7cbf03a43ad7aebf7649be223e1a61a3d650c1951a376ac1c4055562cd9626d6921c97e550c3578f108ac76a842acf825db0d1743f1e8c50f177e289736bafc61549f28c700c05d746d87dee745c64635b57ae7bb5208984b8450bae0f1ecd204a5fc82bbc642aacb398bdd7300cb134a52fea12656e57d0b2ae7d6f164e1cd39aaa2449f222fa2c7ddbf72c2065e5cdcbb61c06b3db0b9a9efe59b8cf9cc40ba5cc4c91defd018d2289f2df0974780d9c2e6c1e574630dfaff1eb0bbbcdc558cfbda8720d499427f6535f602f197b2a285c53574eafeb13532a3cdbf3fbef0e94cb8c1f6b5d35b8e08b9cd11604bb58b665d23e32c33aaaf6f7d947751cc1ff2cc8464b535c2eecce80adf89f01dd0eb4759a977b3ee3507bb38191e53737568a54ec603f0da4d87d1b564309bbb95a0b25d24fe710b6c238419bf71b0ce391b39f5139967aea414cc6691077759ee3644e6d4ba564cbe13d62ab5bb4127d5b097d57c36f4fde90658dc9eea9fd9ce5c99d8976c040906301aaeaa98810a6ef3d9b47a0d6065a49fa98270516a5dd910bfc589c246bb7fd40df3f6cac7642a47715b9daf5f2bc93fe5ee19c8696572197f37c5c2ba631e45646ab2d9f6b156f984ece03e05f71ca0c1d2a6e692ddb9894e2febd055194e272df3206a5c296ffb8da0a1017b9ec765196776c91943fa3904bafcc5f676c57e57e63d603c108e70c954aa23aa6dbb1d7641433b9eb611e45be11c447a72d18e23190b8efefc9b2a3ecc01dfaa53d58ea7e91aec0c965c7beb3723c91b0fbb342dcd3a00c9279e49a4cad4378fa13f8110f55bb06667c0919efc2a438193b12220a2fe036fbb1b8c2d928f40cc693bf786fadfc9f05181e6e8b98cb7127c3f073b93841be9cc0c889dcf47750163ecff1980e2ed47e9699822e192a455859c22d3dafffdff6d897a8c56b52cf44735f2fac27d1e5e9ebea8b1adcfb5e4c0b861cfb8916ccb452facf61922e241f18141b9bcdcf04530cf91f78d058c734ff80888066c10a93c4213e62f8ea38f97088692c5fa12fee4b6bf24c8fd4a884faa953b444bfe9ed3ca17b3f8f2bd9546d2756bd7d5ed243ede8c8fd2c37a493e5d531e2eb65d24af41413134e862aba930faca79a9b593a8a9d44f0bdc0a1ed5091d59ae3b890d5e3b47b8c98c6ed672b60ca3d6ecdcc42426d0ec1dbdb399f03c750d3d1eb26012077bff1297a742b838ce085db28444cc81571f68e5a3cd1528f8caaa821e80a53547acc1191df163cc2b88e482b9ca1c319ca84905f54610dd2f4c21f62505faf123cb0f559402ac25260275f69f23543907d1dc24d9c076c009f711b9de5cf5733e63b4b993af7eb7bdf1ee178945e7fa4f6304dfc8187c11a59cfac61156d84b60099fc1c3265b83d084a43507561e85eabf56551626006ec7308d55f6657a0fc3b70a37af77ae305d57ad56d0cc08272ba046577777098fa398931806fc9ba3210337757daa1011c703f0997196ae6d92d8dd4fe9b0ccd246cf909ca6ce761aaa8f7e91b74a61f111b573699cf21de6641c2c84d26e7f2d623354c42f5c0bcc753ac313b44cea258a63e210b3fa7c22df105b1949cb63fa8e64cef9d84c39acf5a8eb039d615f82cc77fe7d672af2e891622f49facd8d72a5b52dc4274ca0c370ae97d744ee5d22c37bc2fb4ab10a7f6b724d8d2a1fe5e426108598bae9dcae293ee696579f87cece9a53b6f70962f8c4885bf122540896c444315a6980d20f8d7ec5204b598dc510afdd1c12c6ace269006993414569297674d894bef1de16cbb2a0697a355db252b4061b2bbc0d1f02ff4dd0d6acf35223fe89aec4cbd184f8c44efa91b0aeef4f59540ce3e392ffdcbe540f604e0551fb09eebe9f5e040abeb1606cb4c66ecee05975e4bbbb2dc7dbd4c84b1850eba7ce3086ef60cf2c20df80f869bdca21d1f43fd0abc17af96a6330ff40185f202b937819f1cb998de4682935f48f102d0f4a4fbb7ef319acad073c98dd782dfc14efb80c263cda1687b13ac297362b87acd99fcad06b402b95ccbc7705aa6891c9886ef756e9ceeb9c8ad4406c5aafca8789611dc9f3aa013fd149bffd4fae0c8a31846c467b1cc812b0a97dd991e424958fe43372a7fdd4a594a91d6ae6d97be60214e1e356a9311fdf3ea83b60a46d02dd23965883e157881eec9cbb662988e99511c07f468cb142db6c3f126a00fde6c2331a013b6f4f9b7644aa26015510f4a2a1d5543ae30cb406bfce39ba240857d2f75f0d67128e6483b867d80ff5448b8cd9f804a07bccee49895cd338e4cb29a5e550535785915c075069108c4eafb802333288be427dc8af4a7192a5bc91e6d7f35aa02eeb6f12dcf45f7c38e63db0b9f4137ffb23adc4b61a2b341ce387b36727ef6581c8b4e5500e01c5d3bf4642b6197167db325de21fe08371d1906b2c87795634076b8ff913c6cef67cdaa8580cfeede46cdf2e39285ec635d48008146d742ef9faafc8e72b0dcde20dc593b9621fc25fec9569a8634a12172743a027a5d3981f75e828b4bbc777fc1ab0a8828f70f18efd3880ad868c4337842030b8e43b996178e3fe341f8c6aec37266ade44d36a356dcd7a61e88aad91ad3fafe32a7b0953c2184648a22b5cc96b2309a1022f2a62b9d4771b3cb2af3ac2127886ac2e923c2f8479b4e28254f6442637ea162cedd03e5e4c15a0167cd24f70b0a966dd63dc485b9b1352b8f1c4104ef04cd5f8ce37345c4e243988d9acd2e6a923919b8a1648b1292fe9358423e9d31b49e092332ad5c0dccda4d73ee0c1ad6a0d63e75f23157084a9da1e7c6770d9ce44eaa2dfe96408a35183b66ac21f7f880a2c8661e5948b20b5c6b41fe8dc25ca15d07408887e9985c1a3d56da07fcb6eb291b584821549cceb1a420a9a838fecb6c18ef681935839464d97aaf7c76135a12699c4f7081f124ed59a573c29b329b5894f4ed8feff534404ee90604e94fc9753be4486bf2643a94cc532a02cf151adb27add0309b754206a625413dc02a058147524b3fd2d02dc271d7f9471dd7384f88076ea57ebbd84d1ab80619e9aace2a977607851044516460a03e38a99539f9ae2c2ffb1217728160259f28364458025296119a69cebc1f198eed45fcab8a483064c854cc696f4fe03d2c6fa672f4851494925d4ac9a2196b4f09c4e23a5fcbb4529f4e86b78f2ef2fcbc0af1ab2b48a15daa302d9f523bf502da64328ec5fcb66d3136f13d837e166281689c872a0009f389bead45d5b64420b355a428f71703b809c46e30e0f114f9c5ea566a6d4fbd43b9eef4b175f8eb3a18d867c1c88fc31673d1f33ef16aa9671f0652ccc90adc3f39c4b50c9b2b9d3bee2014deb2218f6c1c9259d2cd1ee85aac03dec4bef241474832a7c1e825e2b109666b4e18485237232788f6fae7ee88f65bfaa8839ba7bd5546509273b10d0e61184dfe69f9350245c9f6565e776f1b17608686cc32d1bef7febfbacc6a362a2c5e51075ccc49974f6f4c3b0509f5bfc024eefba2581970fe42c398060f626b7e93a9bdd5d4fa0746319444b92b3bf666f0b697c4b8addf5a686f9937b357abb8b35d579bb5c567ce6ef96e026e0373ed6749b0cd99b77f99ff5d579e2a3d5109a52692122c0300e2de4f080577829c1fd62a4a4bd52b31f034cee086f133dda16ed7e5b9bb0629d6cf93576ec7814e66dca694081f563d74f92d9fb5528d52ccf6f1e42975c6bc0bd6c85f35b756106ba28e07ea4f966faeaa37251797e4d15026bb24e40388ffb85aea545937be67b6d4c9f2f7a1fd51aa9edcd26dbc2e20524ff9aeb88165570e764c0eea5a59c33488a4525201754194a5c0d42ccd88e4a679ebb03f1a69229c029a723deff20105a9d478255d7bac57cc7906c07bf68e13d730b5d288932d492d4ed3df9b4413c63e4a8413b0216d115b9724d441a4fc1f910e347861f21b3f47e15c167e192da4cbff3f7710551e64deeb99452657ccf061c38207121fa0b4049f6a5b32a534d7a666d5bfd8918f54ed19a0abf8bdb7a037604c9814b0c8e0caadbd8cbf74f97e2b83f637e5fb325432b892b0fca175e58e61a51927c08761331bca28b8f57a73d0e366d09dd389baeddc5cd8a6d05e914c8ad432fe911a857097c9939114e8851981eb0c030383fb755cc695184ae1008023536dc38c1073e0003fc7a98a94ce9a8a4bdd5d97035593fa72768b6829c54ad6683e32b5e80a38a14b96cdeb41327cc6e7a3d3fa2516813d4f088719d6afab0f544772e386206f9a94535582bc979f028e0d37c039a58493cf54fe496803b200652f42a8a11dfc1e492471cd6a8f8a7dfbcc5b8dee1810338e4000000\";\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(\"Botphoenix\", 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 [\"Mechanical phoenix\", \"Mechanical phoenix\", \"Mechanical phoenix\", \"Mechanical phoenix\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Glowing feathers\", \"Glowing feathers\", \"Glowing feathers\", \"Glowing feathers\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Warm rim light\", \"Warm rim light\", \"Warm rim light\", \"Warm rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Red-violet embers\", \"Red-violet embers\", \"Red-violet embers\", \"Red-violet embers\"];\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\":\"Accent\",\"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\":\"Botphoenix #', id.toString(),\n            '\",\"description\":\"Botphoenix is 600 Friendly little mechanical phoenix with glowing red-gold feathers and warm rim light on a red-violet ember gradient. 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\":\"Botphoenix\",\"description\":\"Botphoenix is 600 Friendly little mechanical phoenix with glowing red-gold feathers and warm rim light on a red-violet ember gradient. 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":"58368627","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-04T13:22:21Z","match":"exact_match","chainId":"56","address":"0x221F42a2516Dd4462C572F84b777a6f4e94135a4"}