{"sources":{"Saturnswarm.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: Saturnswarm.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Saturnswarm - 888 Cute alien swarm creature with a ringed Saturn-style halo and golden rim light in a starry purple-gold space for .ai Agent ID holders on BNB Chain\n/// @notice Each wallet gets its first mint free while the 888 free pool lasts (gas only).\n/// Every other mint costs 0.00007 BNB. Max 50 per wallet, 888 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 Saturnswarm is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 888;\n    uint256 public constant FREE_SUPPLY = 888;\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(\"Saturnswarm\", \"SATURNSWARM\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"52494646204f00005745425056503820144f00001061019d012a900190013f016aab50ab25a3a3ad57ed61602009646818d0d0d9740aaa3a38473967d12ff2695391876fe7aff11ff9f9c9f4fbb8fb9e83cdf77f237acb17a3d53ff13d0ffc8bfa1ffabe2bfa7f187b5ffbe893ae67b008fccbfb4f9a1c54bb4540ffa677c26c27902f0885023c973bf66a2bfd998b5effe93b636b35adf6c0c53319c43bceb41ecf9c81d659bfb8c92f7d5e2419a357e49eeb29667e31a0d87a635672b8ed30e582eda5034a16661a5c01093ad854ffc1ea30df312b345d91c9f8a96bf2066fbbe59881884b0db1ea2b7ab80df0269d1d800461574745d37800d762bba640090c59977fec7639405615f380d725ce92d7fa0b54bb21a475dcfe5f87423d9096c5f011eaf333ff3efe74536165714afe5fcfa7b9e58ee2687a08186c33996705b1fcf05d1995378578e844ec79b8c8af195697da39fbfd2c4254f1d9d1bd3384adabdb2216805fab6890ddb5648efc334fdd0293e5fffc672da5ddd1a42a0a2a55ae780fb2f0a615637deda1c45dbfce47400e20f6934824e2baae9e8a4cb981e11ddf0eb3e9e81a88e63ffbc233a48bd71664351630d871898d5fdb8f48c7db2abe844f8ef3c172b4a1ebda5a542e2c41b83ec4da6d3f74588dba8483fb35cd9322faa37184e2740f9590d809b6297de92a26e7158bda9ed7633d7f4b9e000d1e7f309ffd3ce822bcbc0a3c6c79d2ac8c22827a2e470895db911e2adabc77ff9a34b3647dcf7990abf7a726d301fdd4a420ab5df9a22dff4f34d209a6c2f68a9c078d7fe85ec9cad686389519fe887beaa232fb2f4401c1ac0bae1dde1eca1d7246f91d61282e789570ab3f59cb8410b334d9d8b27333f67139b056d40a0d0b70b84d77388b3f9b3ff13536ca977a7acee0d285ec0e3afd5b73d11c8139b61ae8095cffd0f9fb293f0a6c068f72c8ae828c9899effa24edd7706fcde4009f6d546d605b6443a968ee38bed1be4e5d01318e6cc059f3934856a3bf8c62864e31aa3109564c78ed9df508474788476610f417366e09d4c1892186ebae11d94bbb874eed6ff2880957ae21127bc68b0842fa5022da61936f593f1b8a8ae6c47763a706efd50f4182a69ed66a66b7e4c72cb8d99fecc5ddda848c83df2a6ad3627f9f5e33c4b93a4724bf58fbb4c3edc47784edd6d59af3b5b912433c96543fdf2ad152e575d9ba4352e85900c86537148efd2fe8dc04f008d20e809b4349cd46a87caa6667bf0fd25f97e837403bf0dcc8b0ceb4568d81d315eb9ebc0d0994db4b1caf804a6130670a72700431a25851b4824609b1e98662856792b8f211f38259041876e249230f30ea5c2363f2d245437f4f0ccc5fffb1b2b2b1c5fed95a7bd25aec35951e948fddb3d11b14e8febefce01ce0c666bfde16f9f4532be9574846d0443e8fd97c4ac310cbc507c5ac1560184dc3176071af3aca1146d52b183c01182697e811999db3c25397d461ddbdc1500e3b0b9d6ad4750415236f78eb8a838478cc11953d81c45009392b9326c94ac4be4d9e4f0bced0f58318c5a6824038866634f3a835ef7c9c5ccdc5a28c7bb328730c13640546162e80f5b2b0a12e27a0db0882b9509fb16e2c0c6558401ccaa3b0632ca2332ec5648a2e3e7cfd185d3b5532c0facedf41c974ef1cbfb413e67f9ae8831ba827acc9983fb679d73efc929d57bfa194cb13bfffd57e71ca8f77634b72e4ef79000c5e8bd953e5807cfe1a9928221333088d2740b4719a232a98bb4f14e44c8bc28c55a0e99874b8d0d036ff2ed95d02c06a0e2d4fa7ae8c9999fdb54920db33977d5451c05fd6164bd52ec3d97d032046a5ab8e4adc7f94e5b040a2d46867162d9b20933e9389d8daf1521a05f07c63100d722e669493b2104f48ae2d196b4006174a26c2a75e0728eb72bd86b88a65a617b6acb73efe7c9e9a09328dade3c545d1d1c4a1ba0e1343b88cbd557d31fb973026b223b512655317ce1f25ee52ff5beb564c952f4785ec8e83f17e86ff264e4989bf82b725ca05c67704e166184feb183330751649ef3e55fc76348d6b7d9e4cf8de659febcfffb331ec213ae5529d487d289689c60c658f6bd06e33ee14e58b1f0dd8a12ba008870bebfb234416ba26d736e33df5efc5ad7442b12fdbc1cd398b78fbeadf888c4999747e953ada584f950f46b7128d73b16089468ed9606aa3b19d68c28ffdfd1b2b038411de7675adc96db6dcd1ab3b584f3034b089805ff8643e389620c918e364c94204408deb367f7d9fca085f8a8663fcf9206ad4a6235136a77da0571afa272018e6e129a4184e775bfab4cc99ff6a2d9aa15b4deb3222b0fc90496ac5a7f6ad59ad0db282c42a80e52cf4968dc3f9d4f9d46ef99ef109d4d99542aa6c426c232edff44b27daeeffdf7401b71e7b6fc59368e225007b288b29a7b1e715f71bff1f76a7259630c922a1c8286de5e0245bbf4b187a54a866b3045b0e2955fecc71ab0bb7c5b5a63c177d9c4fb579c6f860282c74bd6522e495aead1c04dbcb615ddea032d56baa2d2ec1a7590542ecdd6d079a35973c3bb73b89761b70cbfa60fea2402fc7d7c5a56f6b629dbb04e612d897379968478e7df1064f75e5ddebbbee7df8da8458a3d20a7561c80a92382e33c428796ea1a2a4e682bde8f5340b9b0b0301bbf924944035a9d1deedaf68e59f82931eea2f5fc94f345d0626200017b91f34b21dd48db0a43af7514d60ccffd1eee64c02c88f5d80fb5031d704597b2e2447a20e16b2b4151397218b145c5bfcc67cec799e82c88950227ca17356784413d10085fe23f5498632d2f13f5ec0af7f7d57745c78f0536272035fad4825c2bb9059fe58635e0a3881053c2824d0c725ee0a2e7be3439b7333065a6a0178d5716cbb29eee5865f9eb30a4852a00f2ba64a7e9a212e715b093c57b83cf663253a9805ce29dfb88c7083e32918afc8f439cb6fe25935e8612b8beb600a54f1e2a51f57ae93ea114c9cc95f2ac54cad8de49b5d2635a46f342464708749ce304ece4389794ed197efc26c110698b9496d9c41f3472afe4345e0c8eb15ac8ccdc7219b92eb0d138a3a454ab12d2aff03c2cceaea1234477711b891ddb19190c80f46bba9ae3537029035c468a56ef178c6966a96cbfc0f89ba68d60c48236fce64c7a3c3cdaf0189f4e5a4b2fe99818e092cb6b0fcb70034da70e7770501816e0c42ef7b31634891de68edfb3988ef8e1b056408dafd7f5d4b9fa8442d3893c0c54deaf27d063c21690364f14f1732b843d0a45bffeebb412cf1eaaaa8b0596b83afd6f91fb9c6d447a5884bd589e891d3aa851f92349c3d02face766fa4562e02d077cde123a08560ea7eb3461974b5ee596796a8620359aa04edf85661019e15617b275d8cae08959dfaff44b4de85fc68cf8a8bfdd3a5c8a03e22bf6102669004556d93791969fb494cd75ca85f9c8a8ec19e76f134b26729de2053711a622af86f78134aa0b261a74284748d54ffb26ac165d634674220bc614062031a9c3149fce3495aeeee2cf1e970d507ff0b7bcb72eb2910d464fd0079fa375fed623109f6480b08b91f9130c582a8539cfc2adca2ad821343eea3396f2adacf0b5ea81e99fcaf01f7dad03470e71bfb608e158e48e355443b870f5d701833b8b51ff5d540293a803b7422e2149e2714e52a66c1424466e8758f88d38e88f9977a76186e3e7eb91f12f63370a1ea7d1f2b0b627a59d0d7650b52eda4c75d6cc67fec2f728a4779b4831ed4578544eda6472256e87e61e7c6cefa36f9c27a9df2226389f8334f89c2cac966e4b045fb0d9f49766eb7e9e111449415a83d8e630c3de066f0e9634e8f452e56e29df81effbc1692345d050579450c8ae820c933d8d6b6198f057c8faa77f800e69f95a353d93572b33b56bb670977c225faf9420164ac841d4e507576c7c6ffb43e70a9e738d90be35eef5e94698987639d6e48c5d85bb05865624e888925152d9fe02046457d6a76410000fee1b0542e0a006be42c433a5be82254901a3e878a10a95d5121c06fb386f33a585f922533a59d95ed73b35c1e3772a5ff51ecfa7ff765cd3b08cd2beaa63eb1814b03198aa8581903138300b1bf9d224cc3087f688da68594cc861d164c4386ab8f5c9d29a0b0674468927e1d4c7f2ca0c67a51c3d2921dbe9dd88e95adebc1334364020f1bb528891424f078bb0c9d05a6bdd04edfda977070011985c84596b4756b0eaaaae56a1adcdea292eab417fb8373807cdf552401d9d5d72c8091e9f09a65b1c4c0a5dbf5e719464bde4397fad832fec79186e11dc8010085cf6e00d95ae7f3f2de741821263d22db545e11de454c8df94b937a04774518a223bdf34f9adfcf6c76ce9486f5b3576b4d78c92707d90cb07b5e1c9b0ac6e27d7950f098a0b5a28a4d2f33e84ff373f0a3a76fe7383555f392bd30d37c033611747a9c56f89120a0ad3fecbe921d477177680757cdb76ea4564a7dd72af310608b9281c9fb62ef937f10cb48e88776993ece7f3704ecc93d5fbb139f3f4bd13cbcc1c9c1661058e98b6fc9786f0e6f45a53eb8b309a5f55923569ca863859cf547bd30fb3e5f6cacaea18c97b0fed2c5c3e53acc25a10129aad48647048160f5ea5ae13f30babdbb505adbaef4bee4f0425e2f31d7db9d021751897747e47870c22238b7d1e0a19078b4fb78214c2d450ee3a086d8c975f0702ba6c7bb71888a0b4e1ade6c7d750e39234c673fb702ed92a3cede5ad07c69afa2fc6bed70fba23cce1421c0fda498231e24e7e67af6242c37fa5336eeebfd666b0bfdcc0aeaef2d1ad722c0a1e4824ca8db0fda50e06cbf1ba8d35c9ee6079781555481deae23ab1930bc9ec8711809c2c5f4a46403a6c3b102f5d00d4436c28d114fb6c43f4dc276eaf1982a854cca1e9ee8e4a4f7134302b3b0fe17334b7dbbf9c9da166ecc53ada619b84465d5e9f1b4a00fb29820885e2231de9f9864d8f1e7f6337b127be773fca8b7e15bf5fa5886f0c436526f9960082623d4a8f30af38dea39b3a84a64d3ccb371a018074e2727c59054030c5e80365cfc009e3cb86cde3096b5a0ead888ad394b85956f22e9bfdaf4e89268bd8ae530d5ee0fd41b70bab458903e7c8551e5cbd17384f97e9d2579a788bec9a771acb810900f527b249c63e328c289240157dfe26fd21382676c79275134a24ea2dac7291ead48595ad43020e82b7f03fcbb17422cc0194b1012bae070236af71760ce14eed161ee4da608072059dae4d497034835d58bf60eb2cc100b59ada6fd3d936df48ee8c6a876f5a99258190b11e9e1cbcd11f8f3638683e3237c7f5e6386b1ae19533770b2d7aaea222eb5db42995533317540dbad636f4b8dc94c3b84d33f4981cd61cf03ec00dbf13ff9159f88dbf44d627f0e5df20fb34a08ca556e0458efbc56add3fcf78ab72ec9e8f43ee3d11de7ff26f9e377a839f8adce42a21645bb67c46b03231d1ff1122e3e5afe478fe107be3bf27df9521144b8715d653ac3512fbec5ce271770bd2dee3f94fd51453af342e099bc763887231f9c74218facac4937ff8171a2b47005fbdd5ec04b3a95b2daa912a377e91c4ff6b12d00424a5adc7a72e544f998e6466c0f41a735c85c6ffeb466159780ab96ac780610acb9f485edecab76e1317be4f4ee5b012eaecf0204b838c8662b8907f12521ccabb37d2ca8e5ff2d7ccd41d3d59c07f7d82f58bb4230ffa78dc80ab6b1ef5ef46c2787b5504c268a208977bf87c56ececf6aa6e59014f4bdae4655d26dd8e925e7928ac3200baec92a5693ea0891c33defb09346dcd36959666cebdbe38811af304a678b4c3e0cec54dbb3f873adb6ffd911e84c88a82b09a66dd110665a517dabb89e4bc731a1604debe33fd147e57010131d5cfdf919c9845d7a400d5948a0439a70cc00ddbddb2e348030b150bab18fda13d432fb4379c0c80d99b7b288c2e30c48bbfc096b15e423c22bf72d9b00c6910190b9926f6c954f98bedca1d5174d75f39a9ecf8e730b16fdb569c6a76de9a51f9fd6a1797281b95c1b767b0608d84f9b4844148e706c4d8bdec8b0cda0a640f493cab8979ee7cef76586e7246a7399d9eb0a9ad768df07e2cdc2b9ff62fba53086dfbfcf6eea95c1bf1c3705b69f24413e4627183ed88eae41b9c965fb08ed17fbe70c8d93a32e70ca16036572f98e900564109f0dc02506db2a1cf2c39842076ea7b75c56a13091c53f99044b9f07d0dba38c77196117b207edc630dfa5dacd3bad580b342baa1bc95630ef0ba5bc76b75efab4ca99bb5957b2e0d082c248f3be7811234a8d38378bb51469d34d6c7574b48becb6ecf7742dc79825fc1fef6218490004827daff5347713ca9a6ce81b20a48f7d5cffabf1f8001901110417dfaae1560fcfe566050acb72aa73edd4651df4d45e0d39885f0c3756efbb6550bbf46fca13b0cc522134b0aeefd8350118ce0cf8eccee05b0c9ff709c032c050db808685f424ab7b356b644e680d97a8a605fc9d20307cb563fcccb194561b944b81d28484f06b2fa825b6076eeb94f077b2605c57570a65e5ebee4224521f4290120062b999202459a088944fb1b32e5e9c0e9a9ba4b6363bc596a24bb3429cda627ece1219e05c4e678381734270cddddbbf3aa68e67a1813d2254aee596ac259e24ae59bcf2af6f6a6466f25131a8892de3054ddedb51d9aa291578c02deeb22d71846eeddd6d29ba63290f453fef8de15f6f44323d09940fdf6c28e3843253141686d9bb07180c632490f7ca755d7cd2bebbe2881c3d5d61e535c8e809d6e06fb32f91989ddde7fc38957320ece16a013a3f4f3334ab6cd38a835eec95b8ebdacbd6888f656dfa2c0964613e8cfbfea80ebd4f5d780989f07a4ec0fe695a6c686d011bbe35e3bd11983b2c6e72593dcbe0513f1746b491c3cfc2461179d144cc2084bb3eec6f62683f1e77274ab607001eb8a713555c839427973753fd3dc6d7c4dc6021952c4995bad686304e47015ef911c805987ad91357836809a78bf4992d3c662f92de3c958dc8ee398933d52971321742fc615b2e26c2da23e60c744f42350ce5395fbd8423a136227bf0764191205de67931a8069824bc45bbc30a6e4cfd127ff810d7493c8c30797edf11b7557d1be013a8ab4ae62ffe0472e8c01a051f4fc5341e4903732b36ba927f14271c85198fffa68426be7a40d0439c602c029a709f2cda832266bb8ef24c5ac53b04244ed2214d627e6a0b392c70f9929489dc61f28da81e503546012edba615b83a1389a16abdddedc032403c38294e65f0dbcb9b9d72bea67723c6ccdfc1c91de005c84b9a7638cd4af4081f4e7275032fe62807381a3c965b048d2c7be961f2b18cced1f951f5943bcc970c1d547a2c4abcf086619124ec5e393b33d53eceb6371478b8ed754ec07a4813f0ee8f1e085fee2532855e9e28e6b5e80a4a5e1f460ccd92f6e522651f9bbe4954008617dfee44de93a31a1d3d834b644dc5fedcfefa3174fa25d81748c749e5789d4893f337e4383ad031da4731ccb33ac53202cc76a1e9148c9f7667ae4d188fb1b003d17680ad78056fdff10732cc0574a3ad6aec99f36e3740b7631d85d4aabd639f5782236bde43cd2902445368b51147379309cb1df5907e2eee2f9050654b35e3e260ca17a3d3a2afb8f90866aa583eadb162c005b38d2205fc0f30231fa312046973bab831815be1fce3c6b34fa76c1d86238648a4b80cf9b5fa33b009ba0f26949115d3539832c2ce5804f9a62771165d4b07548143191e1936368e12972e09d28716f139f1ffe0de355b98577c2300ce0537b3918b6651273e5a53ded1f928c0625df0b8e96a6855ca0e369263be7581da1ee4259481024dca6b6ac4c0f2e566f487c0018d7aa7482f762642671f268e93fea4b906e42072241eb37abde31ad655ac53f098d083fd678b77568cec8adaf49345dceaaaa694cb6e287b74faf4d212efd9badf85cc3c076f950cd3992694cc541d285893e94eb41d0a509817c53e94295e2e2b7dc87631dd97c733048fd04a31e08c1b1858d43388d39b56fbdeb35b30945776d352a3ee2507734cbcc804d0b8ed48d964754a47bd474ef9ae0c5810db0c48969e8ea50a302c76ecb655d42255ab6656e4eb368b393882d8770864137193eef72be360605e1ac1321c566024e07f22941752ecfa31d23c8594f715c811c71be977c39b74c3bba43173239006ad8ea91b159399fe770754c5733fc9cad56cd0e804d0313ae4e9b0395684478547eccc5a6ed7f450bd8ae8331f38dbf680748e85d1f51cf53fa798c3b76ecbfbf280217965c98055a0ed77a633ac16b399da3d4aae27e780deceeba3f5d3f7b2728548e032aad8c9c5fd32bcb6fe2082489e427e41d42420c9c438c4912038bf0ad512398a1fd797e6aa845cb5a81c1b792c48cf1055420385a00a1828fbf288314df09adc30b60a249290c36705bc948fccf9cf7d39a58b4d6aa70236e545025c604f0080653805091d2c8d38a6cc25b516a8093c14035ba7827795c7397e276e63555a76093e85c63d4381d23437134fedb56a4e7e8507bd5d1d32cac423e4f54466582ff6ebf3929c8374e77464745a1c147037f8c377420b414324b0179b3c504d575a095ea8d91534a1a7c5fe0efbaf61add12ec3014188944745b4f9d46f2463eeb7205531628f1602e041f0127a0f2b3e4988dbbb91ff37cdf3d8eb39b8c9bf6f7621de2fda5ace224a30a381bca9a8ef4f45a6e3270e6de3d8085288f3bbeaed8dae48661b6f3a4428043a9f1dbe2e617620d05b1261a474a80e799144dcce15b05280ccf42aaffd77546ee64c78e70647a946581cd29670f3d6277a210d17e126034e0d1b444b3cfd6bffd827b6d740d2d920f046656c6db1f9bcf5358a521e06e5b20f79edb8c274182595c26c9a7adf8e2ff60ddbaff416cbfb2c5b7dbf558c1688695a700819e19c1bc3542d90d7c7534de5c7d8ad05cea4b525500cd1b8265ae70dc1551549ccc8ac1224ac4658d350c73b2b5266fbd7eac6129a75a98e71209e8f48c50be3c54f7d1cc42585b94f1c38656eba3691fbd9557a5659965608f7fc81ad27b227282884902854ea21719ffcb59e43617c9020baffbbd26ca666e0eb0530c68b7afabc723e08770e4515c49002fb7b8ef3907dd96da950f6c6fadb1bb43ad0aeb003fbcb678c85797a14f28135fac0a0cda00aa5e36d56e580fc21273d33ff441ab9eb6f23f7ff8d1feb4a75514e1c6543d3b066ed823f494c56a1a3c66d6206d0af74013906d78de97cb0cdb3291493ec0ac0ced64c583715d25107ef0e6838fe0ef6f78e08d4044fa0628666ed24ffef633706a8b367145088d74d50174b489875c20bc3d2cddd29d392055c42dfee961f232c4de8e69ade19260ba8170030f3728ebbe54aa990b558596688cb4b5679a23664d7414b7d7bdd29c20aef18c5c4b314b7188c938a899b80985b7bda9a82b94a1208098415fdfa89679d001311c244d919e5255481e4a43c27b867b48c2d5cc5c82dcfc0c25d475dcf3c7ea3b4d731be3b465bec63adb55d680cd5f1d26f57b488320e200017ec933a678f7fd831c157e636b0b50d38756861cc1d2cbd6cfd573584845c395cea4a0ab359e7125bdba278d3f208339740c203dee052dbdcfb5120b76c8a6898482cc3f236528a20d13b09d62940e828bd3f44ece4fe9124d50604d8aad1a256608b57f156adeec09105e734fed95a8e61d94fd1412e5d76bad165e021983d4f141e2bd43c71388e40846cbc59cf2c83938259fa557455dbab18b6213b1c9e1ce62fea7a3972559a659d49fc32ac3ae226c63d6ef348c23fbc485ca648cdf2121c32bd480c3096c02ee2552ad05fd23cb211a67ec15c42ca1bc96a90f07538c55690fd848ec222ce376d08a58a840629e694d86e7821c1d6faaf32b2e59af6d5113775c7e692d7d632aed9686df0ea25b6d675a284db3d10573565ddbfd7eef1ebb9f9eb065baa6fb95d53fdf449f660b8595cfbbeeebfb00fc8902dac0a05aae62f910fa5a7de0f04523e35302865495c9b9e5cff75044a532e1df48c6ce318b326c732e79818425ca755caec46a917ec7e91473ab5512a9108e2a2856fcfa24a04ba95703ad8a672b40c617c347bce883f3a19e5300f9f23c997b44a8e715aa3763566dd672f5c0ba83c9657755eb6077ab73b044f0c06ac5c50a2f6049836a4f4934dba9e408fcce6136c4a67873eae3b8f6fd548fb863eae73e4c4342825eb4e7e7be5d47e740a3b2954c9db66111538e63ffcd839203ecccaab3da111b304d6efe5825174c599407e6ce5f03a8ebba6ba3b11929c72e7a3d42e7a08956f685a8462a93d43807b331a0df4c10c27e0ab926772b14201656daef4b7e21c7616db9c3c2e2511619de8314b4f18af7fbeffc8f054bd085e2fe91e8bdfed3c7abe8d475b1a4dff0c389aa861b8d56b04a5a735d20843b58c08b31caea5e2437ad1d6a5b8cdf83a709e7b622e9cc2c47df0f34adcfe9ccf8a1ae3808b58d5676e09156e01d6c5254a2450de3c9a7bd736e84cb6db3a16f10d7cd177cff1be3782da52a64bdebbc4e2b13af96148594df225de61487b6e8d10062460fed3fb56089e89b75e7eb6423d3c55495e7fdbf491633e208617d4d430657ebb4d15b686c415db36f70adbee5a86c83fcc74a2382add0ceffa3d3921f2a2e40611005e04d881ccf8b95ba8f148ef409b8fbb4b09bf6ff85113941a184ddfcf0ed9e1fa931fb8bbf1fa1e7bc599aaba3ae1efed55f6f5cf41dd32f04e527e3d31fc69a6d928211f350534b315b7fc52fe6eae755d7ac3a980bf936cf6998ae09f0428c1f67b910939a9d35fc5c18f31237386fbf9c124c0707605d68274eee6feed85838f68389300933d39050dd63f20a89e146debd41fbea66e809c02e7d8ab07c22b6c9199ca40da0082da06bd9d30e52435020296158670381d22395b282a0932837363118105d229f5db5bd25dd2ad2ab6f5cd5e226b0e38a62d73592afd8a9a6d1c787c8d56faac0950c13547f30af26545d213c0e546ce9df50769f2eb69d2385ed7674639cbf8aded48f81a92a9bb14e9ceb8dcc255ce6ccb5f331318f7f3eed895f5e8bdb1eb7f998896f1965b7db3af2d5a9264536b3091629a757993cf79013b3e8cee72921aa3345350037d1add00d29f07381ac6cc875d09441436a98dab938f27b7e0a2f8da5d806b8a609208cb2b158c3b839b93b7b41e5fe7c28de9a1eee7746427953b42169db90450eae9d3e3c0e29f27486d0d6e91a51e3032ca2fa740462761785a9f524e0dae1b69f3215758d6e24aa686a44b6c67edcbc7999ce94c6afe7a1e2b0c5c2be4298de79a7ce7fca97e6f8167f6f51d1e7684e66138c264f641e9441e5eb3a273855498118dd70471ea26cbb2c46101b66e917ed858c7bb28bf95877db16940e3df1ed6260b4cfeae9b8e33f2018b256afe5a6fafe5cea05a27fa038ce008381ed0b2237723ca0b8aca2917530135e521384ff01a9f88493c72b4804cd541c3e325fe3c18c72d8f019b3c0312e4dfde98b88cf521e634994024060ae9fd814c58b6a6517f9a097319ac15d9cc81cecb1c17860b8e1521262aa54c2309a266ffe9b659eb791bb3fd4f9fe91500a1035cf44438c5d7d42535a122f51c890dddccc4c4cc2ab72d601d14efda94cf08fa2b92f11b67a32bc8590fb4975155a2d41c61ac78764a9ca1bcfa588dd426ffc1bfd115bbda6c8aaeb4df8b06506fb3dd1cc8feb66344b002372ebbd5de65490850deee4d96fde08f1f1cc694f1a5940922af341a0b54beb60175abf5b56a25b903bf5d909d0401e59d44b9d561d1ecdc255004d97dafb68266e942bb9ee9f60b84bf159797c84a5abdd26106e9e7da918476ebe7fab71a2c48923956950fbd3d1dfb53f804ec32be081d5697daeffaa541cffc664bbe21fec04c5935b91be31294c1ecbd39ca7cfe4ca9facb8ba606aea9c3d140d70d4b22cc1f6f041394feabd2eb04da138935e6a6647da4f3946f73034279231daca5dff9982d37e94bc2dd302634759112bee37d2c2a8fa1adb4446a8760c109092325460ba63ce135972657eace99da9513a1052777cd7b39b0ba466ee466941eb3d0ef0b6f4561077b509911c0f02c020ded6da0464bd0c18a43f311173917c15109f5977beaafeaef217518e6ff44d9782416aedc98d01651a05ef05b4168b57a925ca98ba2836208a49ef7d322d6277c1b930f4d41f39662d159b06d92950c80704efe6fdfde5f3827783ae2ea99616668554fecb3de14ca9ad555acbf8f1c81653a4042fe22c577ff936460628dc3e0f69ba81d0545f5198b8fed13716a37a86c77f607093db1796737874f11c0980a5c40e2c3bdea9884cd7c50fabaf49fc62128930396d0e6c5ed6ee614b94e97ffea6feaf5abab8f4b66f21871fc594c5b1350cc35f791ee55dd4e7f46b7419bf584c2b9a5b0c87a534fdc6d462c8aff08c60e7b8553f0a6b35750f6e4779e937198174f3d62468ff68bacf16fb1b9404bbf9a447a6e631e49596523da7c93391670d636663100e8ca183e11ccd0ebc7c1761b4cb3ca58b461b4366353a6d85702eed67ccf8e8591c9b9c5f8086f9cd81c052835381bbd6321602231e45ac53f6da88b26aa3c5b77fc35cfdbc15e55aa88b0080b40bd22f8a287500e3408233f01af7607233a9c6b38a0861700036ebb6fd1e467745ccc5d1d695d55b4e463f8e457dcba2dde912bc024c56160a662f1e1d9a31904c61229385aa362e4f7c8359010ef1b30db0398835448101c7710c69d56d0f20df08c1417d6e8219c42cd6564573e6a25a3eecaff6d635407c63eed013b73f4761aa17af6b0a9c88b361e155010787f22ca7fc74dc815348836159b350f88d1be42142646bb34f1ad579a80a6ecbfe8a4e64d2fe9ee4f05d60d694eed64ae913f462c30ac2a0d762868069cb962e9b8d48e822a7cbee8136fef2c19402751d22811cdb6f6f04bca19d308d5a953401d6f278c6f93648d17d2c8124bf91badca23d516e5bfe72034586b2a3c86da40288322a4519c59419b404a6763c7a9a5968052e1cf0f9642ccea16f952bc9a6b7147c4cb9de233432557cf70a62cc9ae23bad17dcdccfb717d4e975dcdd3ca7919632f730db4ed46cf6e40d36bff5fdc19e398352c73a2f6c73aacab64bd1c49e339c7ea870067867bc94b51813b39ed85b91c9b5faae669facb016e76fa351f8b5c2d1975465c882b6d2de77fef1790c1384c8423976abebf1df541763e873fb69ab99de374b02a3713369d39a8f725f821c87020ebbada3fbcf51ced28695b2c73effc48a9c26546166528fdfce1d0362951c86cb72331b2ab921bdd97a221892a37fb9414856136359870ffd0bcb93b34fab424016753678c52cb4921389e9f7fc2bde4e87f2fadbf17463b3be92912076cd30bf3d3f0514c140df1c3d84a0dce6daa6fd16fa5bd7533e72e2f42c33323653349c4387c981460d130e850bc14682450015071d6a503c04da6ed41f8590a4d5a2e3068b4435de151bfb1225c20f6cf4302ad0d4025180954a14e0228e3a4124ef2056fd5a689a7f7d04663b9b6c7c9b05154954ab01db23fb4a609b38c00a27ab09eb826c1fbbb93279ce466d40ad48a302ae665f6c54af3a3ad3cb4759798fd9a30076ca8efb79447c3514cef71b0ec3e8952c4bc9d3018f648633389a6466a7f62e58d287ef366a5799503d7fd7571d59a9d57e79dd5270971dd856151c1d9be7d599f561d51503d1b12c1a8d683d41c28427f98ef9db918af8baf6a17d5263fe983bdd5cbfe60b4420e5d814c2d7a56f6cc6819579c74f61264cdbf692d70ff624edb2aa05fb820342208b858503f4cd27015eed96ad5108c100a03cd926f916fd35cb4ad41f24ea36e450a2eee34df877ec685a6e19c3815ea37b833d8669e774642cea38ae26b746ea73f6da41f0a47ff133f66e8f0caa460763b9deeae01574fdd2377b3f61e2f2d85cd99a38d01255e5e97e1dbd8886ecc93c725c74700c8afadb98d2b0ccb37427123cd2ffc7afa7c6614b7359d8c7736f1e9a743c11d0f313e108fc055dc7cdb0b1ffae2737a222951ada5a0ff2f92254346f39a41e6534042817041847a79ac2b4508759310dac9144b496e6a8457700ad01021cfd4f203d476ee39e27b4fd5e8e41f8c4b0be089e9143871a9f8bd018caa511176ce9055986f1eb9762bdf2b7d6a9e15be6ae4c2d5068a91ec58207d2af701e17ae357704e75879b5561a2de4b3051ff050152024d025c60ba2920f86cf19c5f792c7dba2f2ddea092bea13a45d25f3810a59882a8804290dad440241b0e981d018b6bef289708c2b867f5706b8e6c9994a0745922452b46b0db05c5c95a5e62860faea3307eba512ff32b05911a3fab31e9b316fe95f35af0d21d4056f6faafbfa0e6757210fe323345ace8383162a448e9d9571647891b12a3b67b4fa100a0daf37fa3ac164344eed5fe352b3e900a0c7c8e72ab2dd2078b4f6e510fc12b0620f292eb63478bb0a61b13d85dcfda00f54f48d88d036c98696f64b9eebc55004b92d42512cb41db76746dc1c2e9ec8152666d70f41b56db20025a90f933acb1b26bbd306665ce5946a54f94ea9a75e98906ab18601a835b77d1dbf66b486062111dbcf995bc8eaee41ded34c9c684f75c26ea3454196aee30ecc6a215ca5a918fc56a6c78447cf6b48342f1351d997caa808c04eddf08d00c8afa92ac30228228fc7a8c464a987506270b5721637065eaef7d8d95381c1a0c781ab391c77f65f887256ae480d7cea1711fcaac05b7cb36001c6e3522416b8d23dbe0bff62e23cba1241bafaeb450eafb4f34799cae55775b0d03c8d04356252f220f3e1bd4b4ab401b2e834e71e68aacbf0ae230c1b3037a57f86863d9031af18a5597436ec3e4dec1c931819779e9bf8d7b68701a2cf2007a128e37601e6fd7d02d2a67015ea92c2835abec3c022c61125d8656abe4f0a3d7c670972db9604df7ecca7c6e06f3fee744cbc2b3c4b8b9075ac282941201acadfd20b10c527b61e1dd9aa07300e3160a446fbc1e1d674eaf03acb2caafedb032ceabfeff0f5289418a8402fde916fba4e658e920080c24de028285a6a495a580bb9ffc242b8582a497e7e4c6a0c0d02a7a2d9c8f30c270276cdb8edb7d84c3460053cc23ea2d85165413e0fcc0f92d5c4adda7d56b5a0847be45e60f50416d3d0ff6fd8e7e19a80bd00f98955e1a28930473375d054caa30a3ae7c96cbb6efcaf5c80f233bc19dce1c56f6528911555c7248dcd59f9eb86c233f658bed7ab2e7762857b9a1360ba57c6c4c0b76474c7888e5255088cd4681c55b0dde4ad1a2b00e2ceb097211ac15941887cb2130fda9f661f6d72d98f54b45cd494424d0c8060f2862fa273364ed8c11839e1e40de97728feee80ca2247c58f5fd6665319d8e2295b0de2cfd70efd5cccd988a925a2102a0525fa8fb07a0f87cb808fb9fc14df8e12072e025ac5d73be2773279315780ac136f36e4c0a1a06834dfe882bbb4685876c29adb74f8cec74d9f2c4073af6b59979d7f28ef1519bd0544055ea519e3262f6efaae099fd354c6e2d8d996838f19536991b7e94d9c6a3549fd2e186c29fd029a02dfc95ebd67044c6c2dca840a6fc2832e2a25d337a96c3cb6ee25b27ed65e294c9ced6ce4690c464fa7696748f9ccb4d2f1eb49d8f515cdce9e673034fcc76517f4d4682090ef78593a48f12b64016538dd8cd674e0d82b3fc31578dc36b46f4015f9740a66c4e2a46ff9c8be9d19372261d80ca0ac2a6746286f693a32aa0ed9aaa8ff8db8b949558f4e23898a0c4ad014fb3be55a7b722650244435a7dc526d23657760a1c22fa5336c1bdeb92d9b1eb034f4db5b3ef4e655ca56b546e930cf6ae1fb29e9e5e8a83cef71cc1ed3077964b3de53c5c22768adf10fa8c48c8f229ee12583dfc1d2497b0c1aa1d1b6a347304f5fad06c90178e279594f3fefa22159aaf65f1f276748e0fb764e18275e0b50c06f54619e3e6e41a196352312e7c537573a6eeb9b6b77f02e0a72654cd2e923717dfe323d54214b77e0b1063e1964a69e306c4b00c70a6ed5db02e232c7f4a983d4a962c6e4b621168457a28bd1e73892d30f243392ffeb9b1b37a9a38f6df6550fd2154284a745807dedc943bac81147f06e680ba8c075f5d2d228959d996dd6e72a0d8fef461fb6fe27f07168a4c3eef99dc5e016724e2b381ad65e5b1efb4368e966aa8c261ee7f6ac7df10911d3982b58fecd263d7d43afa858e58fd26a9de189f4b084e94f38d2842daadc719b94d61260f40839059879f200f8274c8ab9bc3f0b77d6b0d595274eec48a9832e9f2aa699c31b49d449afbf6865b6dd066fa5bd146d9ff9fb0b5113254654f760f4812ba4a90165dca6b1acb24f795adf44305471fdb7e9f378f679acce138bde1248d5601076cb0eb1e5fe66037e5bcafac0ba0f71818303fc6b9176c10aea0f63657486089c47f742c8b0b8a471cd990a84349d8eb9153c12875174b4048a47ffd3ac05be495cc5a0d2800c8815ca8b216e77d184b04998c76241a37cdeaa1ea4c74e915842b21b7f0d82fafb2c2fbb3e4c40331ab4427fa612c461bdfa03044f2675dcf0a60591ae7819d390c95d6d88cb4a39a215527f35b148313e9b136fe3470576cf5cd90b8f38f3c01b32d7deed45cd0965d2a2381d897511492b669a6a850b04ae8e12764b19948c5ec9ee4e07c1a4363b46ae915f26fe8c40d5ba094c63940883f1387e4ce32cf3dfcee79e30c6b3cb1ad42b7d6083b30aec3979cf425920d80747f7ad8125d1044b25aad1e6fbd8ab6044f46874fd4624de2827cda9ec6857b3a6be56ca98bb9797f49de8a13497781046f5bee9cfa5faf87dba4ac88ea3f12a44989ba3fd69de2e7ccce011037e26c1b6c467cfcd35055fff27dca1f6285120d801acbdb9bf310a51d24deb35cfdebd0dc9905950e0c1f19c41d2ed0e0d60440a46016e812ff3fe50616d067c2090ff32f61016331cd90ed001f3b155fd81372d7468bddfa8e542095b5b28a21844438f2958f61f79587009a4df5ad2ae4b694c3749f5a4c1d87e9f0539befa60fe2869347427b2c8eb3f1c3db00791c907d63f2ee79f2d3aece68ec348061859a0531685ddcc31a3beccfbfacd0b82d5fc85710772900dd695a3976c82768963e98b13248392b86127844daafb194fb33991bb3a5e5359115e5fc49e05e30d7d29394015fb25423fe3d8d5875507719a51cb99533abef60427280b9f2650725771452bbb500b48af4192eb26c3b9e3f402b794a79955aa0b324c26ca0c14280cdb16cc1c13e9375eb04340281f2907b9a65e8011b4aaa8579d5fdfd97c3689cc75b9c96c6dead8379ba9818ccb55e2ec8307c682192bc94ee96291d9d1b47e9893ec64f31bedfc55920a3a78a381702229ec573c0d5702c024e54a612252d880cc622b253835b7f4fa45690a9e0f86461ee8b5b975990adacbca3b217f0cb0b2c94153dc7d4b9b2b86cf16a00b448ea29e14464524d85a40856a1d2374b837f1410487d7d3412e05f0931ee8ca2b2cf56426e23333402bc4062366dffd9f140e6d84e54bad29d3dcd32512ccfd25e465165a6d0a6c05a84d857bd6528119c87cd66e59027a348b898f29bf7353aa8944789b0f4c91269e7c21bf95bea790b59b44f583caf3af735fa40ffff9b26f92874d185f74d3ee8a003091904f5659e2198a5a55de3d888eaa541485bea218911028be135f3315e0f2bd2c08c08b0bb563bbec5d7958616eb648005327ff360184a6775065db4b2469cb7f95269f9210f936cd0705efa7006e10836ce14be52e673b8c61dfbfe4d8230ed7be55a7facd10688056d1dd69f888dec0d94bb90c8197b18c8cdcefb5b7dc9d839d0fe95e0a7091cf2db2e9e091a8575718cae72fcf160b140db43499efe2a7c83e3a902f79249bbe1bcb0d791160dae549a9347efc9413001435ac9f7672b500c8e3a12c98cc66566e6996ab38946a7539c94afd735a2e29b18fac8c90f2d81c843e88df9c288dba731b5ad2dcd4310825c700590b66415499b614a582e73bf919935010cebdfee4dc0dc8f2ae68ba3ba949d97a9e6db9c4f31b18e09920d7574e1f41eec0f51f73cee2c4f3a15d3bb84a9678b39d8a31e9390d10ccbf9fbd93bd3dbc2a2ac063fe0ac469566d445da93f6420167ca2559ed59c2a6657229a8ac13d3e4f1a3826ad7dfd73e0e5bfa492b072d5fff1b662304a9c2fb7a087183f8776e0e407d196cbd86a554e65a9a2e85b0a492e5098a4d69d14d1e38d0bffbd7070f039b20bb129c95e2ea9ba49fcf2072a4a8cb889011a9d8dff9155dc46e5e601791c3018dafff83e0cc2c93dee8f7c023c4c11714a0490072f5b001e56089592874342fcbb03224873013601205377aef91b7e69a5149ec9308bee9566fa9c572d20aeea8e2ac7616b0013b8bcfb6357346f9dfb218309a2fce83080e12ac3cde724941226c1ec79f4105ab752625bd140f59f3bf197420ea0e977e0866fae4de951d2a4302a3ff6b7e678df3ad47078e03e5c92eaf2cfc2c28906e8beeb7115152f3acb13b06858838064fcd2554a6ee8260f396af2aa7e51ca4864ddb76e027bbb1df932a973cb8e576aa46e9a88ad3f1c737e1ce6d1fa2f0dbc6a46807593eb5a4d5863a303e2caa0bb25e3251b0a43d9022416d13a6483bb55cd8d1e3a9578e8e9bdc1ff6b08f38c119baa9100b8bae7b42e6ccbc6efefb2d7410f608552ddea218de21e1e2eda7b9340f7387051de5ec9a7cc02ba5358de9eec23bf6fab078ee1278cedbdb74932ffd62a12c24abe9237d44548ec6de0bac65b9636bbaf975fa199850c96628b5ec780fb692dbdbf710394819128fb18368e35ea71c57470864a81c3e350ece838402e30faf02ff5a53c4e34455e15738b5ec72312551d6f3b95a8292c226997426cf023a12ff22c0178938186bad5809b10eaa9e30914738b2c910bffad52003299fdaba30ccf7c14e90acde6dce51bab392ec5328ae2fe37ae6a49aedebe2847898846943da7f46b9a853eb5cd41fd1a584ab521bb9aaf565487066c6f155535d336a088221028d114414d021f1de939e7749388aac480dc4a8388f4368889241189030996ce78567d1c0d65af941f75a4bf959513855c9451d5589df28512a7a646f254d7e536ad46eb10eaa13129f88ca97bd1687f41f0ceb343bef5c94635e5d7fe798a937a284e7ebdec6523bdfce51d66761d48ed62a48dc8844cff8fbafc3b15304cc4163adbcf36951b103f3cf90766868f310c9cba3cf9959544ca0454e3905b6efc4c1c82297cb6847b8aaf15801bc8170e7f7149db65a48dd991d4f8c1655bd110c390c7640e71a293524609debd5825cfe12b349a8b9e364f79c1b0fca36a634087603093ce90ef8a7aecd3314e003b50d05606a4a2e4108fdedd1b72a54cec24e5259d4135c5d7177199773fde1683059abf6f8a79300f0c0527fc351ca8385cd650c14f0b6e8f7bae9c3331446985c34ed9f63b4ecfc01a511cf24822ec91811eb5a855c9d7a2234bd70a88ccc4a1bf4076ffcb32e1ed9f10b4467bec4a3aef06fe48df5310a5607211ed9ba6a5c3c00aab4fdd7567a5c65e68baa077e09509f1c635307afd55cf9d96051aff66375143d15838b9a220c7ffb8b6a47654d4d94598aa1336675719efea87281674673b026dfa57b04b12d15a26bd41a2e3c142eb98b432785cd2386b9b2eea591f9987bccfea6e16105e631450a27a5c603c038c44d09eea660b34f53a868900298b010936d9eb232d3227721464fcb2a8b69e831a66ed4f134107c41fd9f858646abf88cccd73f7ee820afbf8a1b3bfb470874976eff44481910eb4118dcb6ab256b2b7e60280e0e37e53c2bc58eacc7a419d19b5433ea4974bc0aa75aaf62d3043e37b05a28a3e79f9306fec1badad2e677825a43ce7a71dabc05930ce33b1c4093059abe4598162b59f4dc52405923586c7ff1f0e2d516a0f55e9ac58fd679dc1cda9453a6c831ba83ab526b2f09d9a184a182be6e24784a9a74df1f93506cb4f81aa1b74601ccabea4f0178cb7726eb5b3a322b0a19b7737eabbd6292aed349255a08967458c3f57ee157d328a0e335fe2f7aa876447add409b789b35d11cf792490a90d3a70987cb61b8f31a23cc61946a8ff897faee48221062e7a370d5197a99b2efb0a1deee4639eb5e93a5abdf32be610151aa15f8b07556614fd076c1d1d50d9366ab01deae990b7e8c0507f3c7707efde14792d3ff0e8a275da86d099717ee033bca4c62934fe5c898f57f076371648ed4e4778b16a033c472fa026de474af9e6df99aced95d485f34876f19ff4e6e59991c0ff5bc9b9b29001144b6b2da0fe69fa32243197ee10aeaa68b9f80ff3c0d2d558545b6fa317e433f4a4382aef232bc862d4b0f425b112047d742e68ba506b4e18ac8bc708d60a5a8a827927d69e8730a64506d5a90c81fa2766917bb8fce90429a7f6e550085ec1107d8ce48543bf45d7112e76810649a131cbedeefa57a3070e56738f40afd4bef52a67cdb9588dc959a66fb318f837f78345a78a43eb27d4c70e33a224b7de9dd8d9d0e704eae1bea23fb64ba7533724c05223b7a63364b2f9124f79cd90a645e59271bf960a5e0e498294579260deb506294110a8f399b17454006a2d2f586e4d6295d3c5166d583fa6e2613f75c2fb1bf89b9aaf06cd8b9ca38908c0d3651a132ea72b8f2de7ee4e81d5a5f7ae3aa8dcdaaed739b0c184653bb3736f964cdcf7e91b199ffd1ac736bc6ca014769364ab9eb59df32b919d54195243f201e6748660b5a608e5f4a5575d16cafb34bb9533317bce7cc52f229667659a828c181dc299c2df63bae552121ddc8bb07bbf76b77095e3beb4252984309cee29193d550a96e8855928e334b38d290c9b706cc9dd258fe8bd01272b14778b2a7a43a454537553084d7b68b38d407e3bdf7dda377df17aab1f4bd8b915cc6cd1a9113b3d548d67ff1c1017686e13eca8b63d441f5cade9aed30d38308a63c11c7b324c886f505c1f1279ef5990541a9512c67ac7839178e453ffa419cab9e12337bb4d3459a879ea4655139b8454be6242ed5086beaf898e54c0837896df900a4f4fdd8aea435ed04708e89ce9f78695aa9dbf515a72202dfd880bc746896abc04eecb33def8aa858247c4d2cd849a6a3b165c7d415d2c3c210e5428878d786c774fb2702c5eae04335065515c82ce083c18985c1c93c629dbeecee77e58bcfac51aff1d6800ff4ba9fcea581149dae8de2a205cd567806a7a91edd5b90ab5dd42ba7e5d9fcc8ac9487a95fff1fe25f98935f4a61e6dd1a55ec62ce499d17ebd5dc5e55345a303ad532984f74e5de4a77c79de0d63f25a842cb97fb32c1f61291dd3f1565b144d3d98134981aaa6d7b4d20c83fddb6e5a179686e801c072423562840d435a6430bd6638d05eb2c973c52d3cc374285cef94c57049c8cb672d92d70b6250b42c943ce4e4abf1d2781ed04f1f0a5265f09896a63b6c2e1de89bed7f02921044ed0e303f1a58fab639e476dfe232426f43069235883d5d61644ef299ab31e91cc13ad756c3307b56ebc395cf6268b560f7e3aca84868ee8cb87a1816e0ebed4a59982697c3c5250911bc3363dd53a688b3bf3db692bfb3628f6cf26606e82d6d3aab4fe235ccd920ed7729e89eef51cc91f175209df52d35309470c6264284c3244132b50895ac10696dbbed6a2cac464757f596d0946db4551893b8b0ae159467415bd6e57e53c5916a05f8c5acd786f4c73db6ce46c246a8d89460ddbd8ec20eb0082f383897cf5e22a4f0c8aaf8750d7ed06fc836960da153b2d6164909e995cec0daaf702cf54e663e6f8bdcace88ee74bcb2c1e6cecf05a197191065089b5251a7aebc74e361a6aab4f06c7e734bcaa4a139b936bb576b7edead48cbf1f16fe487180957fa622ec4eb2448813376a685738974ca320b5ec9fae3c08c0472e087be31df461bca2e36c6fbace2f8b5396fac25db5589883b1119503820bde1571dff2cc660742f6b3554f9d722a1aeae873f4ef8be98c8f82d49ff50056af12f180f944cf6b05dc211603205036db85668f914c39d45e74c49ec58d10ea4e74b4184e5820fa7370fc92225630b751466a14406d8a6990771a5fbd185250ce666e5ea899429c032784fe868258c7c1b94ffbcb5263902ade8178e360ce4b425abce80fab2b8b8f642bfe3f92c97d79ab67a2ea95394ec24a0a14cf671fcd137b304dbb9fec25962dd54d01996200f95d765e2685c3e54db90817aee197cb9599e771952c3da01bf9f68b027c358c796b5415f8338630297eb42149f720527cecf52449ac50833627904e7c6d3209289968cc531a61e0643b1fb57e9a012019efb62d34377714641b367369fb2f7cfc171f1fa30d4c7bab5c0d64f5efa6f7e973f13aeb93926c06743395aee5ed65ee22429e4e0a89e70c64fddf827730d38c7da338d2d9f63e8e4e8c357b6d59be5076f349ec21a85565385835dc58c3355acd1da23169b35fea482cc3e96be8cfcb1d84e0d4b2124977032330abe57e85716c6b580f89e4887e30b32a2ad31a3235032286f4ea699299623c40011593f13d24b36ba913579b0428acfe6889cd247697b12b5cc2df156725d40a5f687f160506dc38ff06094a4f9dfcc6e350a7f3d6effb1894e78cdc55beabb3ec332c5906ddfa4b7cce5d7e51dc5d146d991e8f6f5ce244b77da19444d2162a2c22fe974e769cd61a18712278f8fc6402e9610e214e563882ddc46215d1ef64630d00e653f3295d9f426fd0f2ba79f0eaf85044480da201dccfe2b1cf6abe583ea19a1b339aa39476a436d034a5364d5809abfa320b5294c0e82f464144164180ee6e84f50ce273932aa74ade0312aaaabe2fe5e3713f1053c7ce35f9244f4c18a1fc99e47a4f8d304d35aa30326898018bcdbe016691358c52c41ad1f0492548ecd0be671362e8c57400e4f830eaa448ae1b86c757e8522c5e299c964e71bf97248ad3245323e735db425d0672b1496b550f30fe09f4eae2e0c3de004cc28067aab745cf2e4d230ed08f643c2becd5466c538f1d4b9e7f9207b3a647d686f324f7c421a28193089954bfbbcf8a234ed04f7f5a6ebc80ab739d70a45d7fda3d256dec8d3cb1ba91de30f2873ec84ecac686dda68a472fb45d4f176d1c72caf9bb0f14f6ae798f474f6dd182e87c313c02c35f9a50721e63a48999f9bbc170e04ac1f79527d7b55aa33776bfb8d82ddea21819a813cdda0449442ca6d869e9806be7b94709d5012b9c781e14ebb21135173f99b45310fa43a99bb809a532f7ede1b682a76a820f4513dd1e38a3d7bea00bfb5a083aaba3f79fd80ddba2d89e42cf2029af677667462c74f992780804239a8907840218f9de92488d6e9f2c45a5a853c9d21a4049749d051416943b2824d851ab398aee74e29e981289a590f17308bb0c5fa09785aed755777841f838b1f07683a0ec640e9b58b5d0e8f52408b5dea91a8e5544786eb7eb3bc7b6870e78b7c6d62e5db41fab8b7a67e2b3374f470b27ab52f7177d2aac45659fadce3197b1bd11b6e719fce4af524f79ebf6c9bde815793ebc8abd184c639cfdbc3ce2f7902c482d4697e753ed9a1e71252b0fb3b80aa6fb7f1a33fd4167021e5d514eb80c48ae98a21ab2eca2e4af466c90ad6daf530518df37e6fc98268512509bcfa2176e0b9eef66eaabfce679b34d2d0831ec43d67eedc02c2bebddcfc71d6b14aa0d21e474da06cca09dc920ca906cd0c633b42f6895143eedf5f3ed8b8dcb922c118d662b4c357c38fc8638dba7c58800ef6e49f6ebcb80a3a4bed8964319dcb94739e77adf755da92eab40c0a839559e3b82a03c39004939dd3e8ec9e4d92305ee7877cf19d022973a05163f274629e004a40bd6f9cef5237b9188a268d4a06344ad4a873317f017a50393c2a44781549661eee0755e1da6b3ed251e0059cdb38694ae63e4b927e1a1f99f08fa6fc9a35938ace6b105391bb5db5a2835dc49bde8ede915584d2a1f998fbc1d7e679c93134e9432e0e7eb788cc4692d3945c414b74ea79face275ba27e83353263f476f8dc9016f5dfd381a18fbe0ad67e4a5571d145d790626a5f53fd65109ffdc8cca60b4de8f753769a90c6af97cbd4c088c5913bcc71ee3deed350c720453f6cb19532e262e513c642ad719bb10c10f41eeb78e943d5a02623f5c8689c38e3013b6caa2ba36c773952aba441f5abe51f6f7197f80a91bc5827eb3f3780dad5ec05f320949ae3b818fc2481467dfd463372a6cb396e6f6b63f80c41591d46d657c716a9401ef2ffc3b9f564f23b8d24f1032d5d92d04d9ffbd35254a3b78124da8d4f09d7f587c93489400180744a782f7778b743b4961b555cb2296b35307ad9d90adf1602bc01ec74caca5014e5886946365bb82f17bf148d29b56b9a3d7f2e85ab8d6362d56793eca3d288ec1ee82a3abc8072a6ebae1ee75d950cf79542282c05ee04ed3e73e5334220c5800ff1c678d5acaeb05a8e3b95b78d57f55a3fd8837b51578bb3973ed3696066563e30d0abbdd4a268ce1434fe5808b51f0d793b3540ca34cb12468f5e5aa7c301cf04f4e825f80bee9814db63a7f0dae4aa84912b9b35c0a24739150c753a0cd7796b365aa1a4c2923383ba52b96770761b2e023b86c27cdad2bbbc1c41126fd5d5e340283caae5b9ba832ed448782d315d5f068939bcbb051a6b9848304b5f9c6d3452c8d9157679d9b8e6815c80eaf9438680125acdb22764a396eebc18f591cab5f7300f2a5d274508af89e90483e89a444d36592b642ef67bf3cdfb2776c13b2d6c03515d08f51d8a95e3b74eef5703038f744d59daf25e7ec2d81d3c2cfab11232881ff3251b9352e6655e7e9d47e3bcc05e3aca0e8f8da0552ddebb2e908e9f86253e49a5665cf311d5a1ab5e5ea896f7b27c39703b384c0a78b4b127aaa56881aff7337d055cec23c264d28dbc13689b2836f51c061b979a73446804c743d5699edceee0341798b751ef0bf30b45dbceb9db654c466919f283ebd3202abeba8590d477b2b166204f220aa0fc039e87c1cfc25b9573ca809229f12f2bc756d13f072ac3e171411b4f89fe922ffe64c152a254dd05081e679bd8d163e9786365406bcef67fe6041740cbd7192581d1e3a943fc7b937219dcb964aeb9b64d89acc857ef37dfbeb49ad72e04ebb071b07e812a1ff1a132f9c2c88717fda75d82937be9fb4c44fb39b283a616d9662512f760523246a68c86d9ee8e76e7966f725f2476631c2b9034bf9ffd817d929fb069626a640c4a7e54f8f48738918f101fd2af100364a8c844b1d2ddbf781a1db5124d99f5251b4dd9afe23fe221391cbd545167561f4d8f3ec8aa5628c6b9815ea4c91f3bafa0a0591adbab12618572a29a969ca7da70eb86ee924b01d785e5b225e836258385345ad65c5760c96d7d503d3179b27f4b97b42ecc1c8368cc4bebda65892a640382ba80884edd2b7ff16ba145a62af1da1b8bd6e4f417e381ed00d6da2cf35f0f35ece6670e234f2c290e2678206f6ce051e8e65e427747d146d70b7a216d3b69eb024d05cf310239afb002add51c85baf9ce0748e9f546852083c50308f6bcbc45ba5fcb59e2738a9b3df5cb272560d5740adc8ce831d059912262de769277a1c48dbafa7734cb6c7f18b460d08a2b44861423446bc894562e014dc0295c820314130b601906246d4284f44379613a1000c598410407ed7ee69dc884962ba51e4318cadc884c3d143cc842314b80785147e4c2579c73f75e6196228465bcc23d27a352ea6020d4a75b1cdcd888d4a6268e9165c9c1ec682a864ff168cb3262edc0a711b732440dcd9dc6d5e60bc0b4bd89d6bf9f63b8e5982ed47a848d62df3a1c068096e9a7904ef7ff70b83abea7e2680bc16398379a41a39de341df44eda94999006ca7f7b00fa64de1b4b1182e2b96164794723eccbc3e82fc6200c25fe6b467ed42d182f88f2391c85930f880420414bb7aa9de2907811a2b413ae0e714e67eb45fae2303c09a28c514b5faa7db1c4c574a2894a8264c13ea4f39cdd0fef28bf8cff98ca5136f3ff0f71ccc3b6c0fa3b7daecc5de00b096fc99b1f67e36bcad7664fde118c7fb3b31666fb342a70ee4d896e532ec06cf61e441498cb379b8176e567b14e5487ca70c85f9961192d411534edcc234dda125b7274c63d5f3d813683b7faee9a08a9de3c3a2fd3a1e0f4a505129971553b0e32ef4ae0deb75cf3932577d0685895ed560dc30bfce25ffa36edea8cc8f96eef7ee2d87d361caf9a795e38a6e37127053f3a5b0f084e65a17e6ac46c8005ebd6ea94219b12cacfe30345974a2065b7e06b7d6b63783c0686c3cdeab91fd94062d729b3fee2017e3550728750f8d7ed9b02411d6901590b0ceb95c572065db339d50bd10cfdd03cda259c8d80d97bb77b134a0d3cb758ac26c8a0b0554418d1c28aa030c1e5d4ac49ec8ed8502f2ea85e4835b43752e2887e0594ba8c2a32cbc69c16412f2b07924b120f4dbae07f048af18ab1ed5d17d2ca0dbf6836b881b8d17dc904b1093d595aa31f6b788cc03f0716c7edc3f114c495b0b4189fb2cbfebbd4a07e368c392b409dbc1cfa6da8c76b02c7d56e1f3773b8749651b4eee9012b2e20e0f3b0d03098fc1f8a27d873f767b822c163b7c21ee4812e2ce7a9ad03307c56ded298eee08012e16197198f3103b2b60b2b6c2337d4d612c1330e6517d0d1376bb8c4091313932a1b80e7f580c3d940c5515f0cefbc86e65e57375965b938730b8d3c42c723166fcc8bb080a4bb29ace0b8706885412e0e7d5555450ac68012816f98708b744590e8bda39c61b11744fc67d4ab4c2cb0f8ef5c89bcd0834744173d59a88492cc585ebe3cc6b9096cd49cc99a8f4461bcf0a20032a3589283124f66c8918a6877b34a58b9b3b2f66da81efabb82ca95b3964573f70cf4c241d8190d17d996a7931cc9705f60f69f690da039f268445a8b6c9fd2b975c36441c9405cd77631183c35b7fa8e00ee7d924864a1c856ab2504c60f0952237effd1c8756a496e2441a318759908535a8877e77c4ed52a1f8ac9cf8adacf0722bb37b5c36b28c205ad331137c18d7e25dd4f12b73068f4eba3afed35b5469149ed9a583d60c9c3e56e29254610685073c32541d82f94d256f819b8eea12fc9d6eed71fc915051cd8f52b7ce1eb5cdb1b43079bafbf7e1cd33b0f2f2eb663b459baac6e252d79a52f94eb4b3c4f5f719499bbea066bf5ff98ce6cf823e44b8d5b2c045ce6da06f6365f8b7f3cf2b0724de9e7d436377905cada6e1a740a2e6f861878246e7c680dea60e3b4c79745e6d04ac5a673a5bb864b1bcdf329b6d80f602a26a8bf10cdd7e508820f50f7ec9432ede0ec23ffb514d66efa6443a0a91a5bdf54425ad2e835920996fbfc3c4b2fe864e6da713a6ccee2b7eec0d2cef6f775375e8db13c4a23334dc21158c3f048a3276ce058c066269e33efa00714bb7fa3678e8a359a5641fa354f38aea862dba8d056afeb84879c93b93cfef30ac1923747035f1f3598e9aba3e2978becd01a21d5f8b174a5bccb131cb829e2cbfc3c1151f1ace9872976dabdfe5f7ad70682fa72a1fb1d58f4b262fcd444a7d5960305fe8cc2e7e5a96ae2e3f60d24948bceb2049a1b11482acf728007dcf20bd304438e3b870f39772c580bbef9b9d168e08aa792de12fbdb1dc3bde39d0e620d59865f61403fcbcc8cafe73bf8d838927f87786f1834ce2e6e6b436af02ca59a4dc9ef0b13fc76321bbb72f0eac4845e06f77dc40c5d02138e9001e73ffeb31daacbb92ccdcad85866a9382108cf3480be78d46a635c8d749126cb3aad786fbb95840ab74430fa6af1feeb900b0d774f98e12112ec72929b29c349e24345889b41fd834c3f97af9152f803ae7747fb06f7ccd8358d046c5523bd6bcb7122de004811a75f1ea8adecaa91a18a0d2d6b6f8a1a4b811bb47527a3e5517869b789a1a083d57c00152e5ba048989608314e64b054c1645c38c5db39e6d7c3f7674de1dcc16645f0c4e032c8ac6832e08ec9cd82c3dbb59df90b91aa4cc658b410b4126e4515a39dfdef372b067afd9bf1b4ecded508ed2b91cc9b961dd8bfca1cb37492a2f23c30d1b331507054a34695f756f736f5696755d4dc472d700a6f2158d3535df914721c9a2ee3f930e0fcdecab6ad0aa9a5f91627605abf554c71a28e2a31d1ca6b100971bec3ea5643b9ca3d4fc85c77855fa317ba8122e6139d04ba546ab29a6746ffc3c0440d29691d14ab4935638d9486608f5055e1e76ca30c52dcb3f6f6583856c45800c9064afe4a2b98d6179a63554a027480af5486a74c6c2be32a7aa31741b87c0b9d53083aae0164d51645b892980f6f6b320a3174185c08e8ca57deb4f1e031c68283a661b6852a4b3606be3184e6b7f46086f8442619977002b3daf7c11dab41a67850dc3907f03025a0b1ef4f6e751b846740000\";\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(\"Saturnswarm\", 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 [\"Alien swarm bee\", \"Alien swarm bee\", \"Alien swarm bee\", \"Alien swarm bee\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Ringed halo\", \"Ringed halo\", \"Ringed halo\", \"Ringed halo\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Golden rim light\", \"Golden rim light\", \"Golden rim light\", \"Golden rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Purple-gold space\", \"Purple-gold space\", \"Purple-gold space\", \"Purple-gold space\"];\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\":\"Saturnswarm #', id.toString(),\n            '\",\"description\":\"Saturnswarm is 888 Cute alien swarm creature with a ringed Saturn-style halo and golden rim light in a starry purple-gold space. 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\":\"Saturnswarm\",\"description\":\"Saturnswarm is 888 Cute alien swarm creature with a ringed Saturn-style halo and golden rim light in a starry purple-gold space. 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":"58361041","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-04T12:01:45Z","match":"exact_match","chainId":"56","address":"0x238C995A1376e08395b970870A546C57aE184434"}