{"sources":{"Kraknito.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: Kraknito.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Kraknito - 2332 Baby kraken with teal tentacles and pearl necklace in the deep ocean for .ai Agent ID holders on BNB Chain\n/// @notice Each wallet gets its first mint free while the 336 free pool lasts (gas only).\n/// Every other mint costs 0.00005 BNB. Max 50 per wallet, 2332 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 Kraknito is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 2332;\n    uint256 public constant FREE_SUPPLY = 336;\n    uint256 public constant FREE_PER_WALLET = 1;\n    uint256 public constant MAX_PER_WALLET = 50;\n    uint256 public constant PRICE = 0.00005 ether;\n\n    uint256 public totalSupply;\n    uint256 public freeClaimed;\n    bool public mintOpen = true;\n    mapping(address => uint256) public mintedBy;\n    mapping(address => uint256) public freeUsed;\n\n    error NoAgentId();\n    error OnlyWallets();\n    error MintClosed();\n    error BadQuantity();\n    error SoldOut();\n    error WalletLimit();\n    error WrongPayment();\n    error WithdrawFailed();\n\n    event Launched(address indexed to, uint256 indexed tokenId, string agent);\n\n    /// @notice Contract whose runtime code holds the artwork bytes (WebP), after a leading 0x00 STOP byte.\n    address public immutable IMAGE;\n\n    /// @dev The WebP artwork is embedded in this source and written, in this same deploy transaction,\n    /// into a small storage contract (runtime = 0x00 STOP byte + image bytes) owned by nobody.\n    constructor(address initialOwner) ERC721(\"Kraknito\", \"KRAKNITO\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"52494646c42e00005745425056503820b82e0000f013019d012a900190013ec15aa64ea7a5383326926b0b00180941ba4b2118ad614c8e493fe9228fdb3b864acf7b4c201ef64cf515fd67799f3ae79c16fdaef5ae39c4cfbc7398b897c7fe80a414cc534e8ced9e04351329f25cd2d20832b71f419a9fc66515ba14431a2e5eb68f9c970d9a03536c583c1374ca1d3b39251e5a218dfdbf96fc12eaf49b0e049d5b43d6748940cc7081370d4f56099d92fee19d125e99dc24a181464bfe6659e743c146919fc23c7986ba5f48f9fcf0131f87b6b049892b1d183f84ad1cfee3ddbecb913710f6cf6e0e6e997f279e198ddb611f679628c1dca7819d60f84ffff1358fd683b51db40dbcffe24b835dc4820e5f885c6d3e0db335804dc70f75ff8d6177d86596c313059df5ebadcab48c2bc5d2189e92ab5aeaee78c4270f639c810971485b2174c1bda6de891ff3c26e2e75770beba012fec804cd4d51daaf5edb66f8bb4f991ca5251045f54d87a1a132480f99145196f9b36c3004b649d826d9ee58628a9bd45159ebd24ae300c343d4bca7b8098043f84524b0d6d1558e7a40f7a6f9ca3f9f153989e5325274371278b0ed6a48ea900e11a313d60584b1161a020c3871d68b5211c4c6581ddd9bee3a2a3d46d6cca65f10da7258838323d7ebbb9033b9ec6cdae3251d7959965e47ffb9abf5d6118ac63e2dfeb030c31eea056615d0197f1e1ca1b508a1d98abbb5d6bcc18ff01ed9a77cba092e491643877f717b6d9ec7ccc42b06b2dc694142500f8e5e2a7a6b13d5e13c36e1b59a8a86a3d60165560ad8635207d7faf7257b7e10cf4a9f6e18c181ca63de3fd045d11eea64dd3e37e218cba20afe6639b8da6f31afca456c263e5564e5bc6371fafa6af72a359277611fde4444048ed792b538fee13e24abe8ab8c66d6c13b7789e373e8e26fd671583db41064b0244588715f5757dd1e14315e44a994e2a3f646baa090d1586003304124bb4c5ae293a8ace0fddfab4178c0e7783a8cbc98da473ce4b71df44d34d55e7cfd55149a01d269ab686cca963e523f40fe06f1d4610a1768ef169dc53cba2848b02e0dbaf918a60105adcb13a1647ed55ff5c7214bb5a3b5399cbae238f17e44ae198920721165468eb38ebfb384d36f7f83e57ffbce787620a666b3eb5bb546b85244429a0f19f0698da7cf6e94173e4d465501c36394f72bd9d8d1ab1ef8dbdcf8f98964a0c1ffb59eff1744a479eeb5b97b89bfd31c553696eba4966136d4c21e50e55509f08e25c5e644c6a03b691ac5806aef464310bc17e23615f1d63d183929d5ac36cb8bca51a7214148282bd0625bca47b724c83a229a29275d3d26be4fe573511ac5ee22cda8fed6d11dfc6f00b2faf390c27bd723dac5e3adb9bf728384853114b5d7e222d7568920eeee2c68067f8b56e97e042c8b6aaba98af30245d59784a32422261f58433e1ef278f3d93292a2e4cfb9e7180a1f67f3a856507a60e18067104ca2af1a4c05255abd781fcef295562d8738c2773cb8d7e9ee717c14c2a290c565dce79d35f581ca89f4cdee2ace909a5b5e7c15ad6cdedefa0e51bb2f231a92f20300922df7ae47567586afe0b7c7a17f26e418b18aaf56b8c8fc0da7d6bbb166c9e64f09c2cfb2c5dabb41d322de2c4107a2450aee9524dac11a272094d695002142d650bae55a030ca926641e6ce49d1a2bce480b686042b894d6c7b21d1c7f4c6ac230cd7a3e3fe6a94afc7ec8c0300c8eb3f005b96d96728493a90c8db760ccbad992e1eb86f864cbd4eded2e054e01d45981948da9368db1213d309ef5823f6eabd0055e6ca7aec702a4f3b1e57286448479982c09a800f92534717ff8beae8494072077e9a0e7f6f12246932932e46b278277c17360fbf82161dee6ebc59a5ab25b5d463d97ce179fafc245cfd4314d14e36a5331a7ac449c8f58fc4f03b374567d9dda376aadba36a6568a8965aafb64633aa92e049ed7275d10509cc9775ca8c822d52bfd6508ea320ab05b2955cb0788c5823b1b55fc82f09a345b9e0b121d5ccb25097aefc980635b11b6070aa5dd243b73a41fe73dd82ece001ba7d9dabbd04ad63a587a1425f5e723586e2546c35d27f992854c4ac09c6a093e72d71ed5c5cc54ec27d8e2fd8641c10065e55d46c9491bdf831c093e497ec51fd464ad2c4712dd759f0c0153aab398bff6fb9d1afaccd2665c2b249f03f0147b343a2ce96e6d2ccbd74f780ef59389d0d0a18d34a2bbf96ce1adfb485a0a4f0d89f53f290fc3327aa22c01aee968189a9f367fd18bcc3b3618c3a6a45efc425ca11d8dd1c331260595d24ae0f9480ae4b503b50d929505b81dd25a709bf012abd79ca1471918fd8a42748f95ce286eff12b4ff4a7885e61a00a203d5f50ad00d5798bb6471a43e2ed07da883f66c1349a80dbb3a7435199c308aa684549f53a37d4f04be1675758c0b9a5afda6061ed0483ea47e6429d3af858d28b83076f239c48c39fe733912378a54e36546a2d8352ef6576b98e1f11357a30dd5c60e5d3efd18b14200540d975e0d060400ca321c2691616627871f13ea898b907f4d97a0116f3af01d727065fc13e7e2432e57a75e654fbaa201af2290221a3bb7ac7bdd33d484daa9de1cd99370cc11f2903c3cc9b326463427896a6142f27bf546844c0f6c301474d811330a8a47cff913825c66385eea2760be6e52becb5d22490a394cd8bafacac72bb95572eb9aaec8ae47d139d6e510dddd1c603570bdaebf6273b7d3545fbe4e9ce51e169321d66297999efbf7150b371a46b892eb86cbff677038331ee940b721fd93367f9f633c3d7c917dd4f5c95ecc098f32658b689fc3e74c549e44d53985d6b65fb59dc7ce4e6896b0f43de6624bfe870acc0be23f7e6c2e734a8266729194ee7b3f3256f0426e78ca866a3c206cda2c0a3d5e9ee166ffb7176952de2e1cbb79526224f81dd138e23be66b85f95221890897bf320fc82c3ba166d57430c064d5f8ce00500917396ac77057383810318309ba17db0d092ead795a53269e9e8b2442da3f2a0014bc89a55a5c0a59869b2d084a1ccb833b4a22684c0e90416b35346b72d244f6267a3583391cbcf755f5f8f85ea62860894522c67b74f7f0d0d0f50f38700000fed39e9d648ebc9fef3cb7d5e68bb3171a93da5220956be4dfee0892abff6f4e45abdf8bc7434c34fe303bc947e2dbbefdb52430bdfe94df922ef9c09fb80b64ade9281992827785bf938e9e2b23be68b97bde33d72fe863f6a6c3a5c6329f66952494bd5e0a5b9c3f153ce3bc2d5063212b5c463214d92ea316395335303d1f6c33a07178e06f60c4a70da90009a66a0280fe8f6c3973b339191386eb48169e7ca552ad35a01474fc84a82326a34eff2ccff8e2dc2ebecb9c4a9ee913818f4659262fd5444835f70181d7eb57f128714d963c4f8606041bd603fe8ae4feb2ae8800a1de00dcfdbbca8a0e121b6aad1e7bea606563c402515fb225a0010c19b05dbf2c18801ea7cbb7f6f4c00a7d637a95f8303713754e736888b895a6287684596d022f22db4e3e64b18140cf3cfd6114cdda05c15eed89a6b6eabaaef084ac96b8b932ebd235875a3aae1dcf9c59e2f8c099cc41f7339229158fa7c149d71f8ed9c5b689111961c0a4c63aad6a91ad4fcb6292ff0c077afe7aea211b66ce87c0b1f93e08608bf5f16443bb4064afb0999dd07b095b5445ff7a739156e015235b9415f6c2d1428e8d657d2de479dac469a8c091c49a2dacbedde0e91cd439b412af192cb03c576fe5973d2899885d4088367cebac203d822903114adb2377778fb63c8f67f9c6f963b3c611b94952d27840bd709025d2c07cedf48c6275201dc393e64d51629939db0dc9217c25f19a09c371135e0122255b7a7875e0c538c3f4489cabb589ae30aa73fd78ea6b561c9062f814e2ce635bb2354f338450fb1aa8df792b7afd09a34ca8f4ceec88a4d357f66e8cede27f209bee78b00100a7f33be871bbfb49bb84a30bccce17c0aa1ac8215cf2b541e3f55c8193c0f2da9ff42300f71e1537e2feaaea94489565ba68eff66176228f6c0d27e11f1c6b1e6e58ae6cc628a6abd03224ca1dd6d0cfdd64bfac0d946eb27a741aff50aea67f42ac002c26731a6facffef8328cd3640d80f3d400ef979cee8517d1ec0ec051fc5321ce4762877ce6528f24a519dae4f272ced4c6752a100bf4550336d78ff18bb9467040981c313e99edae8d4f79ccc70310500d15824dd456a0b8039c1995527da42467ba1b85c3e79f0695a8a7e4a6faffb31bacdf060cfbfadfe8f17677a9730d557b2d8f298fc8250988993272df6b3f52f5ae3c1380fc04efad5d8b90a823d165e156049cba397c258323468bcaba40a84cd2cf6fa6289d4df90fa20bb49f45d12bf694d14319a5418f00565c61c2aafb3685433d933332d84f32d7d0104979eaad2129af7743f543acab13c9efeea3774a70bad05aad6d508af8af545fcafb12500a318d80a06cb837e4327a026a08477b06cbf7b8a709daf0e8d344f26d9abc4811ec53de75daf48192afa59445be5848dbf1a4d095bf879b92144c3b15d493be19ebf80791f8c384ea3d28fd5a95df44d2c7110bac7f4ca0ae00678ad6ff068efb350bd5c7ce6f833a18dba8dde6727cf93a862424bef73f1331e665289b6a41a1f5af56994601402186d03ed7c7d5ab4b3f0c0353ffe601e762681fcc9c34646fd91ed56c3ea01e8354374e8d82c07955d16e8ae9d08ec8032306179cd8784e6f719ab952fa80da0a22cd86b69602a3a2d07e599a06be0b017b513aa40dca6c8848441c53bfc144451dbcbe5ff9e79af86aab8876a519f28c7179f459160a597836165922fc6ed6c77e3f1901ab6f4270b7f38d72a3cede2eec65b4aa419d0d39723d1bad6f3872b23d92d288d4a0b9c183ebadc18a256150555e6b261a7170d8c7e346dd793a035a191214dec331c6ce907ba07c02966aeeb79053791db41173c0826e45ba5a206dab6333349d7f1eb98d4be00fc1cbacd21239844f62f8096e0c856cae82947e8cfe41f36f6014d54b4b336152cc31ffe5ab4513a4b9723a38880887036d15e590ee758b775e43f96df335c20a92d785878c3a8373aaad5f62ed7fa99ae11a8b7fc282565851df5b6cf70011e1268b619856f479b244b2d2a4ba749f4fc2a0d0f1f5b51a50bacf5b4c0f330325ae7ca15bda26fe40d70adba6b4bad222b129fb9f0efb875bad2fa80640adc0b3f1c39edb052e53f7913511d7689f065b9f460f459ddade6172f4f1502bb96ad3aa5f40be80e454df2278464c1ceeff1d710d01fb81e3e8bbc9556dcf245fe89ecc94b0eedddf377be673c6e328490bbc243c686d08c2ec74bf83d6555ff946d5a55cd56a4a68188691dfce68cfcf9b8a06c54ddb5f22f3027abbc143ba15bb8a69ad30fae2a8086718d2f5f23377ddae25d9e78e2a04230e469350d15fff5971e8cbe5d8bb57073fa7163ef2bc68ea4c39041a8944d3d9a82d30da7b2ed72a2fa348dffc34be714ff7ba32bbb8efc8ed3590cc2ac1e31cd710d29953857f663c75ca838aba39d389088f457195a052a96bfdb588890820b5a56c7172bb707b59c2af2b6bf020e8d757ac5dfbc4021589e9792732f67c117fd9c94ee5392250131492136fcdf826f58878ea53810a0d0be3c776a2b10331ad8785ab1bd9ed21e1ffa4c10382574347b9945f209d379aeb965753854069313060728ae11d88730b5378f903ccfbb36430fa11ae9b9c9c61a3b9183204c7325571873988b86cfbe9f9520e1b3ece16e9b347805aba3d6b53a13f3ec7a9835dff6666b809cceff6323194039f851c12564e51de13f4f22fe010cb08a30dba636b6450481fc7c0aca53f2a1a43a955e06f1dd64156ab53ca7452610cc8d476a61d92d41f94e30e0bab56741677aa10c5f8b39590af997f7b5e2e66d856a769085c1a23fc5f45bcdd1a3ef129ffc5b98664aceb4a1de40d57b8a689b0497df635106400c92116b55d7bc1f0c81d2c2253249345accfdb59db5c317d2b19579e10f96b837a359e9ef117b07b258e6c95a2b336b7cbc1a08e540c15897f7bd26d489776d62123f4649b31eb02664d0cb52726b1cd71f476b4866194c5d16d7e603be39da81a87685d8725b635e3ea3924d432218a0fa4a421813468b8cbb069cb6c96ccc09ac8ac23c7eadd1405851b735fc3358e3f0c4f11ea523d3e9b49b44fc164cb541b0978bc2f1177efcb56551ca311db40b742aa9f31931fcd95feec62862d69dca053abba9ca066a7ba2addb8c0be52b85d6c57c08b7834824d987f7023d441e26be20b7f2d45db6b82761f4c17029b4d8488b01f134131982cb354b31763883569a945cbdc21aefad847ad1172c5634689ecf41e014f0578c9528c46105e637bef68dd390a634267af94ee0ae03f020aec77334278bc47fdd139ccc1ea43e2339f77abbf2265b3ac436bf2d4b5af2d6b744ff4de924b382e9c62ab47a6819fa888158908b5dcacd4ed9679e9003ee8058a16531d16e77c564f56ec3153a51e31ab6af112df61a3e65bc77c39faaab9acc1da6fbb5b0255a32df95f13688dc6cf4851de35b92ed2c010605cfb8119a80b5a181ba1f509eed21cbb280d076468b5f8881ac97e68be75138fc525dd14f9fc15ee71b5ec3558a2308a0817e403ee67dc7c9965cc214a444971477818bf2dff651ce2000ba718e605700350a0e063a9a5d915172aabf9ea6d6fbe813b847b2bdfc07aa09be0552051454f1eb3e637ca4fe9bd45c0d5bcbc05add26a07ceb5c2aa342d74d6510edb8ae7a27d352eeba43567960e0035c3cab7c8bc650460bf07e5a5f3d47591beb126cea19bb2aa903bf52b582a589e0f0cce69e7bbc73a943aa335cc7d6c4e6cdfc66bbdf929fe6c6d40f18617525355bd30bbe4a7ea1140b94e20a88ef0d234f0124014bd7884c393435b9baa3c92d07426447b407f991b8e29476335d417435787af451553252dd8d7b9d7b8003f8efe6e59ced0b3d99f42be9cf34c2368223189545310f8c3463d73576baae6212d5a4de89a0dc964a7dc726f760cf9214cca0920382b6e7ea013ebaa5a4a204108a3f3a4528eef305d04fea6c6052cb5042e50d06cf489cd483de5945a8edd8c661a5bc070c1c2d206a3b4dcedf96df990c7b884c8edf27193f15dca72f1135fead8ccf3ad7b6527e119437c9d13b764b893d09999d144cbed072cf3bf6d947f625d07b1efd5112f7237706f53b01c58f69db9d5468b36820801237f0bebaa3a6a77c406f6e2f95987d85ab44e497f4a989b682422276b6453e63cff983bb28bd35b921980757d48f55d31c08999bac9b8bc587e1572386bdecebf379e9effa6259dac9243db9e5201ce3e7df571f50e98a01a59e6f15370a3c7860339af6859796fb94285979708fcc53c5a0b105afbf74792f1878003ed859df1f59022a7e8ad65d839171a3365ed2e71f4a7f5f851a0c2bbbd95922b3793246d26135d00c9e0d44accce0a7f0d49cfa112e2708aa2a4a46baaff00e330951517d15e603b2535c59af4554aef766291764f09069a82d59d0274164604733f26012dcfdd1aa8359cf273cc2f9e805fb5d977c4b6f3180f55a370c68117b6770470b13c7c252093a27b0284e0b48b73520d43916a74714756bb97f3fd1b4b58f67847238757931e5e7c6baeddb5ccd3e20be99b49e3ca9b170b6a179baeb28b02d21ae4c62fb957bdc6b5461d83cc3a6c38adcd0cc4bee401855a176baa04e38f76c63229c16e46165cd7468b8a979038afd2e286187d6ce2b933695a6748cae885e1330185266b2cb517fff8708fbb4324900d64bc8588a74ec398205fec79f8065e1ea304bea3e141937f9e4aa66a5ecd1af7c3384847d8f1761b9ebfd616898da0941f996e7c34fead1d08a46bcb2cb7726123a44573480c4a311736239b994d24ea102fc8e707a11907329f20d81fcbf974db6e71adf0f3f3cfd84f50d328122a69b89b6a7f5a925cc26fa87c5196180528c683a5d792453f0c0182b5d3a8d296418f37fdad5e35596ecb0aeb243b996bfeab4c85e38143c532e9629b47cc3a08d70dfb7ef58c073e43cd247851759d17a16186e9324f26b2b118acb139431db11dee2a551968bf6d153376fdc880afe89ec6ceeaaa19c88e21b3bdf74aebb04b9ccb5f460159631c6ee47dc743f3ee3cff2373529274b9c360608873e47b5da945aeedc914f646a833d963b910a377732dee391523fcba5391fa50715b2efdb116ae532af0aefdd02b398b051dc8b55028d3226c202fa45749cec36ee825fda33681d9bf5087eb99ae2fca2e2ff6ed0685ab2f6091eb8907782b4ce66d2ea64c2c94b1e28d27bf2060d12da8d4e3dc7bc5fb531f9c99ad199edf74df6f05e61d7fd1b9508fdd4344325a3a3df0d535934c19b2e6df0939663f242d8c0c421aadcb8841eb536f17745b6852b07a6666a95d1341d80f29443705765f32b86193398a65f5c0a0215a96d6c1482dce9a1602c6632f04bb175fffcc6087fb4a090c2f54824f58b55d8deb62ee7ee7c1b83a7fdad45bd21e750e86db77ff5f75330dcd6707a7db0139e9f1556f6c16381a9b64d2993b2d9f96a267822e066147d775769304a1c2d0c3f7a3b3ecf7ced26243b36f2841a8670f78e4580eed11396ce96d348894c9eb72235fb73d70fa23385392e093b9aa21a7dd93f91f60d722d7baf7f5d7db7bb4e5ceee437d594718ab40b362d368b4b36edf9dd87b411823d00014d754d72c5ebb4c894f1c31bb32506f47d5cf636265e198610c57c31d960ea97e9be6b611e5e0781469b4a409b6c3c066ec0199dd7878c51327999d433f3e15b28e006fa2e7ef81006edbf585f0c3f72e991931d81517f06c7d82320ce799328cccdd3825b955921f4690f4096ee97351b8a9e840a1d889e211f78c72180f98fcdf1d72a26f4c0f392fea5e39fbd3f4c6202c0297f18936c280301b6293752479e99f6d6ad0771e7557379bf2e7991051dc5488e2c435652bea311ab8a469c9b250b7e73609385a9cf95ae06aaadd15b03f34f854753a16e281d2cfc5d485a692f515d9afb6583a981081d113160417980fa7c4be715ab7165ac21dcdfffffc9a2c5b8f6d04e0fb453708e225ab4d713b9910c7f6c80b11ed7f37cb71df0a13ae519d861fba93eec5952603c221309ff37aaa025cd6890fdebc57fe32d1c1a2dc03fb558f8d1c250d5abef091e91a224935ee85f76490a6feb634c23c11533f3bed778ef9cbc28a972db9019b4e2f0eed90eaae75e8d13371af42f170e4dd319bfd0471fd6e103cbfc2e2e30953cf2ecd5b9a5e2aa3163102f3e84b8ce7bf3b56742b9c03aecf2d006e25da1d8af831fa1258c65afc63988d16bc6c8e9d2e690318d1699920aa27f82a2edc6076e5d6dda31a74e9461016765f413d2894904b0dc4a4e62ee57eb64bd796cb5f49459366ffba30ee4bda7c900770a912c6b29d34b5ef7f1e0623c04be5d3e85c906192550e1cd5bceba2e01ffaeae284146bd2d99a49267666b59b9f847e296e143fe775ecf9d8a081fd3fc274e6baf512900169ca7ec8c8a73b3cfaa9fdf37ba4162ff4f36e99bbbfe3a6ad66de2cc933a3b7893edca5e5037ad2a1c4d409d8f76dddbd8fcadbf27d80e2c89be885c6986005cdaff751944556009524f3d0706a062c9945beb26b16dedfd1af02ace9fd63d4203315afce5300049b71a6c8c447ebe6243148ac2ab5ea0f2be9a3fa215e200239ce996111e55b9ec63d2688cfdf0d7e0b65225c001874a69fe9c898f40ce456c05f39802c085801637bb98409dafbfe3d145624a3a03a0c2803d87b1a91f2df52c9162d8c7ccf791ce71fcbe1213ff8c7b203583a1f132b86e5bcedc2bb94920fd79d0af310a3c1cdbbfbb3f3fae0bbe3ae39ad9f54fda5c796167c682bbb45ec68fcdffdc6d729c6b41087d3c311fe794ce1931b8cc316e1fbdbf1705a3dcb261db1c1ee2082d97e2d7e4d1604ec8a0b6fac1538f84b2acf15633be6fac4aa7e25da2b01e6c2cbc4c489980c2dbcd276f9b8350e935278d518a484442db57c0c2bdffae90f0d07624bc1043082ee65c25b70b9820eb6fd64d61ec1d98214ab96fc78160c150145469c9f735ac72aece2a08b5f191870c6f5afe6abb49d1a9cce9d3b5aacfd04d3722c04261c198356a20cfb54cefa1560df6240726272de23a29abe58a1b65c35d8e889f83906f6f38ea43f97c18f8a97d86e92ebb211f27a02230d9c3a9985f818504d7eb210fd987ce41aa60fe715206ab8e7d1dbe5c8f9efe8331747054eee0df33ffb8ebb1851606d3254fa0b21ac955e0ec77f1fb23f1d4188293877f880f33d2deead7f75082e925ff5f0e5005a142ef16bd83dab3c8c9d90d37320dd4151e5a443305642941cd3aca074f0639e20f8469daeb02c204d0cf9c3d7659b555910848471d80011e0e9c86d73bae0043000a343137a2fb5e495a9b0f7d4e1976cb0629a0fe58baaa5898cb00315bd7f53270829d63ba469c6274d73deb47f28bf272a87fb1135b5d5f4efdd6e057e06c7d95bb687fe14adab41f3a11b9b16217acdff1a5e77dd4f48bca60a0ffd285791ae611dd6ca5cde4e07019dea548f1a317962fb5c1a889cc8afd159d432ec7125aae01a745f330af5a3eb68ce7f4a5e3ce412729f5d97a61668389f761ff3287e26e46e41609ae9c38e05b8d874ffeedb8925bdd6551b6ed9a06f3cb34ef42267cec6af0add96fc434c86ae1d72b70eebb4fbbbe0e56426b272f00099fa0824c87db7d82667b59d120d3d84712d80d0016e227678eb64dbb8daf90c8169aa81b6f5e24a8cc95f3573c984ed1ea2a87a103445cf126acabc3905757778ceacd68d51555c5e20480fd18df6074728aed85a58478752cfb5e9b3d42dc61de32abc3db21b467f577f18cc4a54cd75524b820f0d3f755e35edbf8d62bd0702aa2358e7dab29f337bc64dfd64be42865088c3edb8f7cb542862f7b8c31d72fc45925f66c54dc40edc3eeebcd4792b2b336eff8c6515adb072baaaf7d9cc1714b340f7413b8e0ce59a9405eaa997d586d296f7c3d36c08bfc5b499e758926930209f99affc5bd19a02772c63b5b1eda24f37a219e68ae1caa197b38b563ff7e8d4b9a77b8fffacb4d25ca759bf61eed9d3e02957340ff17701d5e88eb2b561895e12a39e9cfef34fc003ad9ff57a60c1cc620b82769c7fdc4ba01b271bb1525c51459aca6d4f918156b02829aa645cd013a0a9ecd75cc29a485ebc0efd51dc1fdf54483cae0e064f6a97ab00cb8f399b32098913dce72a2918f1dd3f2ce6857b8002ddf7040c52ba7e50bbff12cde6b86a465e0cfea7aa0f7015484caa89ed656d83d7da4ccecb6a0e3595ac903b889687a25650411bc5f190dbbff7e414308cc2d765fa8b4c45448b58569636a8fc4e5e3ac1d43197f72b987ce3f9034107b63155a7b7ab75a0f81124c68e87a5d453c232ba5db52922b4f9bbc230d294820bb6047ae976ec6e4aef3a739d5a1fcd1a253de8a814787482ce1fa4cb0c15ed3767c0da70a52fe7428e527c983a7c0a8ecb11c50d8d5d01ef634ac99cda532cbb6dad6c6636074be43208ca3b850c73468ef836b57324ca73486a23555ea4dbcba0fd5100378c9641c674a3acbf156139745226defedf47a1963085b2c8e4ad100542271fc9234f18aea86ca41f16207f5abb3f25bfd9b64933daedea7ed6a53584b1c1726d7142d23da61cd94aff727507a93c89f05d72fc0c6d51953a9f68418825823487191cc48c995b66ef1aa74c1b9f33551aab5e534fbd9dea8b2f770f0d553686eac70f72b43fc1eb728cfd0249d4b91b384e8ef68965bb6edd28aa3299bc915598d94eead251d34e32a6c3f2a37b3e3975e2c303a1056b564462cc28e533568dda33c8fb5a2b5849f70a4b567af6685e80a0027eee9c53d5017bf25316887ddfd0d01aede14d0ec16ef6522653ea3d5ca82d1afe09ddb4dd41e35c165e29af7b4bff0ddf760a9827a983f67366c06a1cb7ce8ef8521e35271dd544b15c31e8a7865bb29486489b0d7392cf4a049c15308bb2dd581d9ddc04172c83878869878113b1c346cce8deae0bc970e00c51c22423da93bd10aa1e29e2b815076e741a4af8790f079d97c918ab849a6605d236a859b65483819809bebdd3b72135c29f603545cffada3d6e1917e2ec51fdf2bb7bde08529fe138d44563027e64419c42a05b0294a4181a54e98b256aca2c01ee083103204638966bd232aab380add4956ce2dfa7fdb7eb87592127f4b092f305286f83303dc52f1c876182aac9f193a319c1cc6a938e09b263564818a97e6af1ce84e89333ef68a4e1659db6e544264232a13b4aae30396d0dee9df8efceacf5dc6371a1c528998632caf517bf812a0fbd2c9b1f6ebbfb2e43fcb97b8e9df686b0e33799786f457896de02b7aafa495e14d08bb29ea68541ea9be35f6332c6803bf704f1933e6d3b3667ac654c90c556895dc45efb6d602898b600167bc223da830db98ab221380eedcdb5ef7283ac1da1bb54a19e58eaf58b044504a1a920fe17b1bf102eefceef93cfdb06f51c8caa40c46c164c5827e42c853f4c8e14c5224bc873921c7deab654a8a699e37c5a95f54dca3cad939614367dc8eac58b316ef2dd1ce062baec064c6c541af4ff663a1175c2e057becec9c9b4673d46a0c8eb2814d7d826566f05c7fd572d0fbb275fe9ef08b53a8d28e994674f3731e687d541efcaec37912971ec0b2875cefd9fadc850d43ebfbe884ecddb4336f5bd05b97d1a135e3fd316c43b7c1e75b6763e30e9a7ad98f99754e28ee7dcddd83193d84fe9fedcadfd5bd166f4dddb3f25db050f976217703d99081a9f3d1756b4042297c96702a209a93961cd0bd843a7dd1c49ade8459a708e7c725bef29d7916fb20aede52126f7f418e5e4a79610954afbc79e147914fb25e7fde9ea413fd6192e1471de1d2c35327432dccd13279746c05c6f0dfd33d7496ae797639a6d138da8e13a4f9776297765de2b8e5deca8d2e95725cec3360abd709beb0974c9821b4ba6252c9a7621d04bbe41726bda2cc3a6cbc8c2ad0b69ddf8fe9f1d74290fb0137ff622e6bd8ffa97a314212ef26acbe7e287bb1f9bb1e0a72fecf689faa12275decbf044bbcefc964ce244e6cb14434603a6c234ef1cf15b0821fceda647b450e8082336f6eb8e8cbf62762926d568cb92f3680bfdfcd92e9626a58577ad420e3bed9d05656c86138336bc3c4b26e27336c80a06d676aa63af42c04b2606a3c243446ece446be16ff1b062ce0c65b0f631598b5898eaf29b5170fb1789cdfb0316d8a4695b0c75cc73fd570d0fa5ea1ab29aa84dd83175431b62667dc50df215cbbc5edbb1a066da49597aaa36d835e1d0e89ab6f23b597d86fe8a09f9e5e757d2592b09aa08114a893f230bcd9762b5872745e47b8dc8424638eca7e9cbddb08d1433d4d069edfc30816b3a2063015c6d6f58f39c07d0b9afe9cbae6c7ffb32e616c7bd248de295087dd0824783c2a85aba4740c86ad38ba1438b98d2fabd82913368845c9b80b18bdf1c5235b878ea3d6d11ee3054361074d246211e7cf309e6ea046cba3219eb814e118bc3e5802260ebf1222e4e8b75e451e61e423a76f96d4931b7e58efcb6e34da675e08222f55f98da7b13a44927acd8f6bbfc0a0ab123bb5120cd1f5afc2e2c020abc2718f175a7f6e03849bc154c9cf1a43e83c7209d66902ca47c55aa77217266218b3e198bd79b34747d0ec96a14965cf8767d5aa8a9c169c52d39d0776d18c6e30e90333bb8a4c9950a021ca899c550a1a2504c011991cd330f9e1cb73a6b9d416011674132827c9531bbe8db3f910860562ad71d1e41e7f83d0b8ef1ca5a882b1975d959120a6621eab5fa60f823338d3d75ec9f9f400a3482621808f0e51abfc2b38f8529ae741489c9d31c7ce5201f30f6dff1dc2963636982235b1c9f6a0bcecf72650c70af5887a31b73fc263358e48246a4cb51b686de82473cde518d10aa8fa1206d6dc5b4fe63667e9ed8b25aac9923790be1cf965b078de170fa0115cf87fbda0acf434d2b8c4d82661893f1cbb334b7e72f2da06b987308f902e20a8532fb66986ffe0887e717d7daec26199307583e3eecd3ee2873446f84d3401127fe8206168f6ef6c9b4c0576a2a70bdbf9a1834ef26fb404008ecd4d3da850096208ea086ba6b8a9a00baf59249eb84b46725084b873d2a99b459ce4f6e7b2dd8d0a1374257e35a8dd3c5e2da4367551e3f64e37b869db49d9db14d5703c7f6c4c712bd94a0827b324d436dc5a7a98e2209236a8bd58f64cd4faa5d0fd95a9cd11108c3c85cab07082c50218ee7c6f7949e05d919c38561b858e280b637c0104883a136c53caaeb839e2281668dda12c4ae6242aeb0f76c81dbd102d78fa1a349998b4e77e19d5a08d61fee1ff48b6cc8ef2887b631c1c33c01bdc91c6196fd0148b2a0938df2c1628d3745756de2e637c1a6323212d4b797fd9b042340c44323622d420a8507de2e73a72d1eb1090687fb2161adffa2ac7dabd83db90853419c65f130c4792d6a1b0215d3966d5a9011aa86ec21159a4521b9213b98446520ba7213bf3f3e05d6f8d607e8e0a33e7dacffa4a9bde467f92dc285287084cb9a573250e9016e89e53560e90a204e4856f594e60e314e5a8e6b3fe647e995abd74d071fb09836ab2c0d4a2d90562768925ab49b587f32388e49814b51960238853dfb754241fc7bb55d69c4128cde580378e21ed1c368eb43000d0f566166f91fb994acfc11c28286d19654c3979dad4dc56c308c51b696e9c67d341e9c1c08ec1d5762e0d449d820e54acaac7af369f549a347a8ec3358598ae17c18e24d950cacbfd8243c4447d142d1ee00d2bd41c9792c66e260cc69943fc8c85a4bfdde04318f13ea8f5bb38438c5cfde2d646332d996ae6490492bbcbaca0b44a31571237a6c1018f4cb02e29e6ada7dd58d79c43247b7005528dab3495d7fe2bf9b8ed73f5ebbed8b25b595131fd2c2128a1580fc7bf0460d7c684ef7cee135a2f9a101987ee1b1ba35944d3dad71f67d4b06753858b4928811262e5176bfa97cd0976f86d9efd7875579143d9e34d94981ab1373eb6c9d1cebc3f0c0f828bdd5ed5e1b4b6b39b1b03685d007bc6539bf1643cefc6c021a7a7033671c66911f0d12c00ef62c6fa6b23c36301c04ffa2911655c21f5be1de360604acc8065bdb86cec27ac6e4faa6de821964c243c0f231bf3d72e442003b29c4d46c1c469c5f03af3448def29bd64ebabc21fb413405c801f497f30b9f5499f962858e2522eed94be55da46e04048794e42aa8cfe0e607debd8a93b16b67f79fe76a58e0012bd5e31bd291db59fa6a465c41eb596b6db23f884242c33a8874df1a0f0b09361c17ba99b9a54dbd66fde4499e3dee27d93ed4abdf23c124dd9473bba8046d68803bd19bc87c95d372b19c2366cbc11ade4d1caea75039d43b56961dfe9a4facdb014b83412edfc83b855b7d362b685a352e601bb437ed0f7c33632742fe4b4f51a8fddd57ac65ba43c631d3a8b729bfa427cd9b4018f6c0b381617d20764875c981b1b53016d4d9cc5f28e8d8d6d0116836890443d16e3306d134849c2e752f1e8e1c4a7dcc03c8fc525c61cf966620c39d95da897f7502e3dd97914a25d8a94cd362895b5669d5afb987c3e265ba3ed28e24a0aa5970ee7480e823ae803af10a8601b0dc4e9407f692a6abbd230e6b9b9220bd5d83efd75e8454e0e042780f66311d73acd76920560611568ecdf535305b56564dcbffa95426915aaf9041293606c91cba04eeced78b6dbb4c79cef6ad3515a33f8e12ca97e63b34f7f7a30b0d5b570f8e9e97b055c3db963bc42a25e2cd804b5f6de5ed0868ed8602be2527369478cbc5e9b83803a4ca8d388fdc3fd0743c6acb4c51698c674ed76e66748aecfec134d771c2fbf176d2808cc5fe294c89efff0f888e0147e240336ea0764856fc3a2a3acf0ba8d0b9d957f835242cc03d2db9e485e1cf72aa4f18310c655b25805e67c7c51c09290c7d0682d0b0cad166dec8648255ccce079d7270ca3053873476e6fb0004d4be10f1a03182f70fe833201fe02c5817143aca03937e5e3b34c9d269285234d207753bd762e428d4fa9bbb0047ff0a20bd04fbfe0e3ea0c7338ad2495d7ef7a40c2a1d8d666318f838573adc7929c5b79155766cebfd19b6c4e53da51c5e5b2667dad0c6fb3f349776e6762823f7191d395a1ca59538622da201bc54d6cc6654f41376fb2d181f76dc26d9f20d210c687c842a3084d4ee62a05c95a2df9ca2b70d17c7e0b45c0153c6ffee446bf6dec98af0337723c83e47ea5a650f24507ec4dfb230a6348e38a682dc5bff6cafd963c4c935c69ec94336166fd723d4a350b0987eb4af587c9ed6511e773e59d61c115af4a3c9797d7f04c670d555f04017a6169d27862fb79f036bb2fa2604334dc4bc46fe21f5e93e59ddbd660cf20511e616872cbef8128076fe4ce342a7ed16d33b61d4446098321e764b7a64c3ff352447c10d3a42e18982b0cf642016f43ea7d16c533a75919f84e10f8874e4a589f45367fc62bcd002975b3bf2f8d461646449237fc323e005228ecafae610463d68786ce16b398cc5e999d6300a2c3387577ca9fc75ff93d424d3ba114d2b8f2da480c8afc0949e1cbaacfc5851c775bcb69ea56d2b865019ed4555eace9e0abda51f4c445703200070e46f6ea3a104e401641b7ad2010d2efcad6343a79e14f1c5643b6c08fbaf0f43346d3f9c40baeb428bd8097e1c56bb75055c62f2b4ec66cafef50ac9d64e62a1d720b6291d30623ed5f6f7c04f71acc308a9adb66c5c4029da2e50000\";\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(\"Kraknito\", 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 [\"Baby kraken\", \"Baby kraken\", \"Baby kraken\", \"Baby kraken\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Pearl necklace\", \"Pearl necklace\", \"Pearl necklace\", \"Pearl necklace\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Aqua rim light\", \"Aqua rim light\", \"Aqua rim light\", \"Aqua rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Deep ocean\", \"Deep ocean\", \"Deep ocean\", \"Deep ocean\"];\n    }\n\n\n    /// @notice Raw artwork bytes read from the IMAGE data contract.\n    function _img() internal view returns (bytes memory b) {\n        address a = IMAGE;\n        uint256 n = a.code.length - 1;\n        b = new bytes(n);\n        assembly {\n            extcodecopy(a, add(b, 32), 1, n)\n        }\n    }\n\n    function _svg(uint256) internal view returns (string memory) {\n        return string.concat('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\"><image width=\"400\" height=\"400\" href=\"data:image/webp;base64,', Base64.encode(_img()), '\"/></svg>');\n    }\n\n    function _attributes(uint256 s) internal pure returns (string memory) {\n        return string.concat(\n            '[{\"trait_type\":\"Character\",\"value\":\"', _pick(_T1(), s), '\"},',\n            '{\"trait_type\":\"Outfit\",\"value\":\"', _pick(_T2(), s >> 8), '\"},',\n            '{\"trait_type\":\"Light\",\"value\":\"', _pick(_T3(), s >> 16), '\"},',\n            '{\"trait_type\":\"Background\",\"value\":\"', _pick(_T4(), s >> 80), '\"}]'\n        );\n    }\n\n    /// @notice The token's SVG image.\n    function image(uint256 id) public view returns (string memory) {\n        _requireOwned(id);\n        return _svg(_seed(id));\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        _requireOwned(id);\n        uint256 s = _seed(id);\n        string memory json = string.concat(\n            '{\"name\":\"Kraknito #', id.toString(),\n            '\",\"description\":\"Kraknito is 2332 Baby kraken with teal tentacles and pearl necklace in the deep ocean. 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\":\"Kraknito\",\"description\":\"Kraknito is 2332 Baby kraken with teal tentacles and pearl necklace in the deep ocean. 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":"58039502","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-02T04:56:39Z","match":"exact_match","chainId":"56","address":"0x3134f8d194951d8f87fAb8B1cCc0571c68733de9"}