creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/GnomeSJ471.sol": {
        "content": "/*\n\n░██████╗░███╗░░██╗░█████╗░███╗░░░███╗███████╗██╗░░░░░░█████╗░███╗░░██╗██████╗░\n██╔════╝░████╗░██║██╔══██╗████╗░████║██╔════╝██║░░░░░██╔══██╗████╗░██║██╔══██╗\n██║░░██╗░██╔██╗██║██║░░██║██╔████╔██║█████╗░░██║░░░░░███████║██╔██╗██║██║░░██║\n██║░░╚██╗██║╚████║██║░░██║██║╚██╔╝██║██╔══╝░░██║░░░░░██╔══██║██║╚████║██║░░██║\n╚██████╔╝██║░╚███║╚█████╔╝██║░╚═╝░██║███████╗███████╗██║░░██║██║░╚███║██████╔╝\n░╚═════╝░╚═╝░░╚══╝░╚════╝░╚═╝░░░░░╚═╝╚══════╝╚══════╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░\n\n                                   ╓╓╓▄▄▄▓▓█▓▓▓▓▀▀▀▀▀▀▓█\n                             ╓▄██▀╙╙░░░░░░░░░░░░░░░░╠╬║█\n                        ╓▄▓▀╙░░░░░░░░░░░░░░░░░░░░░░╠╠╠║▌\n                     ╓█╩░░░░░░░░░░░░░░░░░░░░░░░░░░╠╠╠╠║▌\n                   ▄█▒░░░░░░░░░░░░░▒▄██████▄▄░░░░░╠╠╠╠║▌\n                 ╓██▀▀▀╙╙╚▀░░░░░▄██╩░░░░░░░░╙▀█▄▒░╠╠╠╠╬█\n              ╓▓▀╙░░░░░░░░░░░░░╚╩░░░░░░░░░░░░░░╙▀█╠╠╠╠╬▓\n             ▄╩░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╠╠╠╠╠║▌\n            ║██▓▓▓▓▓▄▄▒░░░░░░░░░░░▄▄██▓█▄▄▒░░░░░░░╠╠╠╠╠╬█\n           ╔▀         ╙▀▀█▓▄▄▄██▀╙       └╙▀█▄▒░░░╠╠╠╠╠╠║▌\n          ║█▀▀╙╙╙▀▀▓▄╖       ▄▄▓▓▓▓╗▄▄╓      ╙╙█▄▒░╠╠╠╠╠╬█\n        ╓▀   ╓╓╓╓╓╓   ╙█▄ ▄▀╙          ╙▀▓▄      ╙▀▓▒▒╠╠╠║▌\n        ▐██████████╙╙▀█▄ ╙█▄▓████████▀▀╗▄           █▀███╬█\n        █║██████▌ ██    ╙██╓███████╙▀█   └▀╗╓       ║▒   ╙╙▓\n       ╒▌╫███████╦╫█     ║ ╫███████╓▄█▌     └█╕     ║▌    ▀█▀▀\n        █╚██████████    ╓╣ ║██████████▒    ╔▀╙      ║▒     └█\n       ┌╣█╣████████╓╓▄▓▓▒▄█▄║████████▌╓╗╗▀╙        ╓█        ╚▄\n       │█▄╗▀▀╙      ╙▀╙         ╙▀▀██▒            ▄█          ╙▄\n     █▒                               ╙▀▀▀▀╠█▌╓▄▓▀             ║\n      ╙█╓           ╓╓                   ╓██╩║▌                ║\n       ╓╣███▄▄▄▄▓██╬╬╠╬███▄▄▄▄╓╓╓╓╓▄▄▄▓█╬╬▒░░╠█             ╔ ┌█\n      ╓▌  ▀█╬╬▒╠╠╠╠░▒░░░╠╠╠╚╚╚╩╠╠╠╠╬███▀╩░░░▄█        ▓      █▀\n     ╒▌   ╘█░╚╚╚╚╚▀▀▀▀▀▀▀▀▀▀▀▀▀▀╚╚╚░░░░░░▄█▀╙         ║      ▐▌\n     ╟     └▀█▄▒▒▒░░░░░░░░░░░▒▒▒▒▒▄▄█▓╝▀╙                    ▐▌\n     ║░        ╙╙▀▀▀▀▀▀▀▀▀▀▀▀▀▀╙╙                        ╓   █\n      █                                                  ▓ ╓█\n      ║▌   ╔                                            ╔█▀\n       █   ╚▄                              ╓╩          ╔▀\n       ╚▌   ╙                             ▓▀         ╓█╙\n        ╙▌          ▐                  ╓═    ▄    ╓▄▀╙\n          ▀▄        ╙▒                      ▄██▄█▀\n            ╙▀▄╓║▄   └                    ▄╩\n                ╙▀█                   ╓▄▀▀\n                   ▀▓        ▄▄▓▀▀▀▀╙\n                     └▀╗▄╓▄▀╙\n    \n    \nhttps://www.gnomeland.money/\nhttps://twitter.com/Gnome0xLand\n\n$GNOMES\n\nEverywhere...\n\n// SPDX-License-Identifier: MIT\n\n */\npragma solidity ^0.8.0;\n// File: @openzeppelin/contracts/utils/ReentrancyGuard.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n\n// File: @openzeppelin/contracts/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\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/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\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/Strings.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\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/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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/Pausable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n// File: @openzeppelin/contracts/access/Ownable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\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\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    bool private _paused;\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n\ninterface IGnomeURI {\n    function _tokenURI(uint256 id) external view returns (string memory);\n}\n\ninterface IMinimalNonfungiblePositionManager {\n    function createAndInitializePoolIfNecessary(\n        address token0,\n        address token1,\n        uint24 fee,\n        uint160 sqrtPriceX96\n    ) external payable returns (address pool);\n}\n\n// libraries to separate ERC20 and ERC721 events, and certain signature-specific functions\n// ERC20 events\nlibrary libSJ20 {\n    event Transfer(address indexed from, address indexed to, uint amount);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    function emitTransfer(address _from, address _to, uint _amount) internal {\n        emit Transfer(_from, _to, _amount);\n    }\n\n    function emitApproval(address _owner, address _spender, uint _value) internal {\n        emit Approval(_owner, _spender, _value);\n    }\n}\n\n// ERC721 events\nlibrary libSJ721 {\n    event Transfer(address indexed _from, address indexed _to, uint indexed _tokenId);\n    event Approval(address indexed _owner, address indexed _approved, uint indexed _tokenId);\n    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n    function emitTransfer(address _from, address _to, uint _tokenId) internal {\n        emit Transfer(_from, _to, _tokenId);\n    }\n\n    function emitApproval(address _owner, address _approve, uint _tokenId) internal {\n        emit Approval(_owner, _approve, _tokenId);\n    }\n\n    function emitApprovalForAll(address _owner, address _operator, bool _approved) internal {\n        emit ApprovalForAll(_owner, _operator, _approved);\n    }\n}\n\n// ERC165 https://eips.ethereum.org/EIPS/eip-721\ninterface IERC165 {\n    function supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n\n// ERC20 https://eips.ethereum.org/EIPS/eip-20\ninterface IERC20 {\n    function balanceOf(address account) external view returns (uint256);\n    function totalSupply() external view returns (uint256);\n    function transfer(address to, uint256 value) external returns (bool);\n    function allowance(address owner, address spender) external view returns (uint256);\n    function approve(address spender, uint256 value) external returns (bool);\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// ERC721 https://eips.ethereum.org/EIPS/eip-721\ninterface IERC721 is IERC165 {\n    function balanceOf(address account) external view returns (uint256);\n    function ownerOf(uint256 _tokenId) external view returns (address);\n    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) external payable;\n    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;\n    function setApprovalForAll(address _operator, bool _approved) external;\n    function getApproved(uint256 _tokenId) external view returns (address);\n    function isApprovedForAll(address _owner, address _operator) external view returns (bool);\n\n    // payable removed for erc20 etherscan compatibility\n    function approve(address spender, uint256 value) external returns (bool);\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\ninterface ISJ741 is IERC20, IERC721 {\n    // library transfers can not be included in the interface\n    // incorporate them directly with library\n    // libSJ20.Transfer\n    // libSJ20.Approval\n    // libSJ721.Transfer\n    // libSJ721.Approval\n    // libSJ721.ApprovalForAll\n    function balanceOf(address account) external view override(IERC20, IERC721) returns (uint256);\n    function approve(address spender, uint256 value) external override(IERC20, IERC721) returns (bool);\n    function transferFrom(address from, address to, uint256 value) external override(IERC20, IERC721) returns (bool);\n}\n\n// ERC721 Token Receiver https://eips.ethereum.org/EIPS/eip-721\ninterface IERC721TokenReceiver {\n    function onERC721Received(\n        address _operator,\n        address _from,\n        uint256 _tokenId,\n        bytes memory _data\n    ) external returns (bytes4);\n}\n\ninterface IGnomeGamePlay {\n    function isGnomeSignedUp(uint256 tokenId) external view returns (bool);\n    function getMeditateTimeStamp(uint256 gnomeID) external view returns (uint256);\n    function getSleepTimeStamp(uint256 gnomeID) external view returns (uint256);\n    function getGnomeStats(\n        uint256 tokenId\n    )\n        external\n        view\n        returns (\n            string memory _gnomeX,\n            uint256 _xp,\n            uint256 _hp,\n            uint256 _shieldTimeStamp,\n            uint256 _meditationTimeStamp,\n            bool[] memory _items,\n            uint256 _activityAmount,\n            uint256 _boopAmount,\n            uint256 _WethSpent,\n            uint256 _GnomeSpent,\n            uint256 _lastHPUpdateTime,\n            uint256 _gnomeEmotion\n        );\n    function setGnomeStats(\n        uint256 tokenId,\n        string memory _gnomeX,\n        uint256 _xp,\n        uint256 _hp,\n        uint256 _shieldTimeStamp,\n        uint256 _meditateTimeStamp,\n        bool[] memory _items,\n        uint256 _activityAmount,\n        uint256 _boopAmount,\n        uint256 _lastHPUpdateTime,\n        uint256 _gnomeEmotion,\n        uint256 _GnomeSpent,\n        uint256 _WethSpent\n    ) external returns (bool);\n    function deleteGameStats(uint256 tokenId) external;\n    function setGnomeX(uint256 tokenId, string memory gnomeX) external;\n    function setGnomeXP(uint256 tokenId, uint256 xp) external;\n    function setGnomeHP(uint256 tokenId, uint256 hp) external;\n    function setisSignedUp(uint256 tokenId, bool _isSignedUp) external;\n    function setBoopTimeStamp(uint256 tokenId, uint256 lastAtackTimeStamp) external;\n    function setGnomeItems(uint256 tokenId, bool[] memory items) external;\n    function setGnomeFeedAmount(string memory food, uint256 tokenId, uint256 _feedAmount) external;\n    function setGnomeBoopAmount(uint256 tokenId, uint256 boopAmount) external;\n    function getIsSleeping(uint256 tokenId) external view returns (bool);\n    function setMeditateTimeStamp(uint256 tokenId, uint256 _meditateTimeStamp) external;\n    function setGnomeHPUpdate(uint256 tokenId, uint256 lastHPUpdateTime) external;\n    function setGnomeEmotion(uint256 tokenId, uint256 gnomeEmotion) external;\n}\n\ncontract GnomesNFT is ISJ741, Ownable {\n    /// @dev Token name\n    string internal constant _name = \"GnomeLand\";\n    /// @dev Token symbol\n    string internal constant _symbol = \"GNOMES\";\n\n    uint internal constant _decimals = 8;\n    uint internal constant _totalIds = 555;\n    uint internal _totalSupply = _totalIds * 10 ** _decimals;\n    uint internal constant _maxSupply = 3333 * 10 ** _decimals;\n\n    uint internal constant ONE = 10 ** _decimals; // 1.0 token(s)\n    uint internal constant MAXID = ONE + _totalIds; // 1.00000001 : 1.00003333 is the range for NFT IDs\n\n    uint32 public minted; // number of unique ID mints\n    uint32[] private broken; // broken NFTs stored in limbo list\n    string public baseTokenURI =\n        \"https://nftstorage.link/ipfs/bafkreie37v2cvci7sy3pnk53w4ju7k3pdtdipdq5hgon2zbkitmbmjnpiy\";\n    address public dev;\n    bool public supportsNFTinterface;\n    IGnomeURI public gnomeURI;\n    IGnomeGamePlay public gnomeGamePlay;\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n    mapping(address => mapping(address => uint)) internal _allowance;\n    mapping(uint256 tokenId => address) public ownerOf;\n    mapping(uint256 => address) private _nftApprovals;\n    mapping(address => uint) internal _balanceOf;\n    mapping(address => uint32[]) public ownedNFTs;\n    mapping(uint32 => uint256) private idToIndex;\n    mapping(string => uint16) public destChainId;\n    mapping(address => uint256) public treasuryMintTimeStamp;\n    mapping(address => bool) public isAuth;\n    bool gameActive = false;\n\n    uint256 public factoryMints = 0;\n    uint256 public maxfactoryMints = 690;\n    error UnsupportedReceiver();\n\n    modifier onlyDev() {\n        require(msg.sender == dev, \"Not the developer\");\n        _;\n    }\n\n    constructor(address _owner) Ownable(_owner) {\n        minted = uint32(ONE);\n\n        _balanceOf[msg.sender] = _totalSupply;\n        dev = msg.sender;\n        isAuth[msg.sender] = true;\n    }\n\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    function decimals() public view virtual returns (uint) {\n        return _decimals;\n    }\n\n    function totalSupply() public view override returns (uint) {\n        return _totalSupply;\n    }\n\n    function balanceOf(address account) public view override returns (uint) {\n        return _balanceOf[account];\n    }\n\n    function allowance(address owner, address spender) public view override returns (uint) {\n        return _allowance[owner][spender];\n    }\n\n    function setBaseURI(string memory newBaseURI) public onlyDev {\n        baseTokenURI = newBaseURI;\n    }\n\n    function changeDev(address newDev) public onlyDev {\n        dev = newDev;\n    } //simple function to change developer address, or revoke ownership (with address(0))\n\n    // @DEV toggleNFTinterface is for the small possibility of frontend system changes leading the contract to favor enabling the disabled supportsNFTinterface flag\n    // don't waste it, as frontends don't typically change classification of contracts\n    // probably never to be used.\n    function toggelNFTinterface() public onlyDev {\n        supportsNFTinterface = !supportsNFTinterface;\n    }\n\n    function approve(address spender, uint amount) public override returns (bool) {\n        // if the amount is greater than one token, and within range of IDs for NFTs\n        // then set NFT approval for the given ID\n        if (amount > ONE && amount <= MAXID) {\n            address owner = ownerOf[amount]; // getting the owner of token ID via the `amount` input\n            if (msg.sender != owner && !isApprovedForAll(owner, msg.sender)) revert(\"SJ741: You are not approved\");\n            _nftApprovals[amount] = spender; // calling nft approval for the token and spender\n            libSJ721.emitApproval(owner, spender, amount);\n            return true;\n        }\n\n        // else set the ERC20 allowance\n        // the NFT ID range being set within a limited subset of ONE token(s)\n        // allows for non-clashing interactions\n        _allowance[msg.sender][spender] = amount;\n        libSJ20.emitApproval(msg.sender, spender, amount);\n        return true;\n    }\n\n    function _transfer741(address from, address to, uint amount) internal virtual {\n        require(_balanceOf[from] >= amount, \"SJ741: transfer amount exceeds balance\");\n\n        // checking the decimal amount of tokens owned before transaction for both participants\n        uint256 fromDecimalsPre = _balanceOf[from] % ONE;\n        uint256 toDecimalsPre = _balanceOf[to] % ONE;\n\n        // simple erc20 balance operations\n        _transfer20(from, to, amount);\n\n        // checking the decimal amount of tokens after transaction for both partcipants\n        uint256 fromDecimalsPost = _balanceOf[from] % ONE;\n        uint256 toDecimalsPost = _balanceOf[to] % ONE;\n\n        // stores the NFT IDs owned by `from`, enabling NFT management for that address.\n        uint32[] storage ownedNFTsArray = ownedNFTs[from];\n\n        // references NFTs marked as \"broken\", tracking these special state NFTs.\n        uint32[] storage brokenIDsArray = broken;\n\n        // if sender has higher decimal count after transaction, then they \"roll under\" and break an NFT\n        if (fromDecimalsPre < fromDecimalsPost) {\n            if (ownedNFTsArray.length > 0) {\n                // if the sender has an nft to send\n\n                uint32 tokenId = ownedNFTsArray[0]; //selects the user's first NFT from the list\n\n                brokenIDsArray.push(tokenId); //pushes the nft into the \"broken list\" for limbo NFTs\n                _transfer721(from, address(0), tokenId); //transfers the NFT ID ownership to (0) address for stewardship\n            }\n        }\n\n        // if receiver has lower decimal count after transaction then they \"roll over\" and will \"remake\" an nft\n        if (toDecimalsPre > toDecimalsPost) {\n            if (brokenIDsArray.length > 0) {\n                // recover an id from broken list\n\n                _transfer721(address(0), to, brokenIDsArray[brokenIDsArray.length - 1]);\n                brokenIDsArray.pop();\n            } else {\n                // mint new id\n                _mint(to);\n            }\n        }\n\n        // amount of tokens - amount of whole tokens being processed in int\n        uint amountInTokens = amount / ONE;\n\n        // ignore minting nfts from dev when they call -- this allows for gas-efficient team operations\n        // @DEV if dev gathers NFTs, use the ERC721 transferFrom method to extract\n        // @DEV be careful, don't let the wallet fall to some convoluted transferFrom scam to do something unexpected\n        if (from == dev) return;\n\n        if (amountInTokens > 0) {\n            uint len = ownedNFTsArray.length; //len is the length, or number of NFTs in the addresses's owned array\n            len = amountInTokens < len ? amountInTokens : len;\n            // transfers owned NFTs from `from` to `to` until either all are transferred or the desired amount is reached\n            // Subtracts transferred NFT count from `amountInTokens` to update remaining transfers\n            for (uint i = 0; i < len; i++) {\n                _transfer721(from, to, ownedNFTsArray[0]);\n            }\n            amountInTokens -= len;\n            len = brokenIDsArray.length;\n            len = amountInTokens < len ? amountInTokens : len;\n\n            // recovers NFTs from the broken state to `to`, or mints new ones if not enough broken NFTs are available\n            // if any tokens remain to be allocated, it mints new NFTs to `to` for the remaining balance\n            for (uint i = 0; i < len; i++) {\n                _transfer721(address(0), to, brokenIDsArray[brokenIDsArray.length - 1]);\n                brokenIDsArray.pop();\n            }\n\n            _mintBatch(to, amountInTokens - len);\n        }\n    }\n\n    function _mintBatch(address to, uint256 amount) internal {\n        if (amount == 0) return; // Exit if no NFTs to mint\n\n        if (amount == 1) {\n            // Optimize single mint process\n            _mint(to);\n            return;\n        }\n        uint32 id = minted; // Start ID from last minted value\n        uint256 ownedLen = ownedNFTs[to].length; // Current number of NFTs owned by 'to'\n        for (uint i = 0; i < amount; ) {\n            unchecked {\n                id++; // Increment ID for each new NFT\n            }\n            ownerOf[id] = to; // Assign new NFT to owner.\n            idToIndex[id] = ownedLen; // Map NFT ID to its index in owner's array\n            ownedNFTs[to].push(id); // Add new NFT ID to owner's list\n\n            libSJ721.emitTransfer(address(0), to, id); // Emit NFT transfer event\n\n            unchecked {\n                ownedLen++; // Increment count of owned NFTs\n                i++; // Move to next NFT\n            }\n        }\n        unchecked {\n            minted += uint32(amount); // Update total minted count\n        }\n    }\n\n    function _mint(address to) internal virtual returns (uint32 tokenId) {\n        unchecked {\n            minted++; // Increment the total number of minted tokens\n        }\n        tokenId = minted; // Assign the newly minted token ID\n\n        ownerOf[tokenId] = to; // Set ownership of the new token to 'to'\n        idToIndex[tokenId] = ownedNFTs[to].length; // Map the new token ID to its index in the owner's list\n        ownedNFTs[to].push(tokenId); // Add the new token ID to the owner's list of owned tokens\n\n        libSJ721.emitTransfer(address(0), to, tokenId); // Emit an event for the token transfer\n    }\n\n    function _mintGnomes(address to, bool burnGnomes) internal virtual returns (uint32 tokenId) {\n        unchecked {\n            minted++; // Increment the total number of minted tokens\n        }\n        tokenId = minted; // Assign the newly minted token ID\n\n        ownerOf[tokenId] = to; // Set ownership of the new token to 'to'\n        idToIndex[tokenId] = ownedNFTs[to].length; // Map the new token ID to its index in the owner's list\n        ownedNFTs[to].push(tokenId); // Add the new token ID to the owner's list of owned tokens\n\n        libSJ721.emitTransfer(address(0), to, tokenId); // Emit an event for the token transfer\n\n        libSJ20.emitTransfer(address(0), to, ONE);\n        _totalSupply += ONE;\n        _balanceOf[to] += ONE;\n    }\n\n    function _burn(address from, uint32 tokenId) internal {\n        require(from == ownerOf[tokenId], \"SJ741: Incorrect owner\"); // Ensure 'from' is the current owner\n\n        delete _nftApprovals[tokenId]; // Clear any approvals for this token\n        delete ownerOf[tokenId];\n        uint256 index = idToIndex[tokenId]; // Get current index of the token in the owner's list\n        uint32[] storage nftArray = ownedNFTs[from]; // Reference to the list of NFTs owned by 'from'\n        uint256 len = nftArray.length; // Current number of NFTs owned by 'from'\n        uint32 lastTokenId = nftArray[len - 1]; // Last token in the 'from' array to swap with transferred token\n\n        nftArray[index] = lastTokenId; // Replace the transferred token with the last token in the array\n        nftArray.pop(); // Remove the last element, effectively deleting the transferred token from 'from'\n\n        if (len - 1 != 0) {\n            idToIndex[lastTokenId] = index; // Update the index of the swapped token\n        }\n        libSJ721.emitTransfer(from, address(0), tokenId); // Emit an ERC721 transfer event\n\n        _balanceOf[from] -= ONE; // Deduct the amount from the sender's balance\n\n        libSJ20.emitTransfer(from, address(0), ONE); // Emit an ERC20 transfer event\n        _totalSupply -= ONE;\n    }\n\n    // Updates the mappings and arrays managing ownership and index of NFTs after a transfer\n    function _updateOwnedNFTs(address from, address to, uint32 tokenId) internal {\n        uint256 index = idToIndex[tokenId]; // Get current index of the token in the owner's list\n        uint32[] storage nftArray = ownedNFTs[from]; // Reference to the list of NFTs owned by 'from'\n        uint256 len = nftArray.length; // Current number of NFTs owned by 'from'\n        uint32 lastTokenId = nftArray[len - 1]; // Last token in the 'from' array to swap with transferred token\n\n        nftArray[index] = lastTokenId; // Replace the transferred token with the last token in the array\n        nftArray.pop(); // Remove the last element, effectively deleting the transferred token from 'from'\n\n        if (len - 1 != 0) {\n            idToIndex[lastTokenId] = index; // Update the index of the swapped token\n        }\n\n        ownedNFTs[to].push(tokenId); // Add the transferred token to the 'to' array\n        idToIndex[tokenId] = ownedNFTs[to].length - 1; // Update the index mapping for the transferred token\n    }\n\n    // Executes a simple ERC20 token transfer.\n    function _transfer20(address from, address to, uint256 amount) internal {\n        _balanceOf[from] -= amount; // Deduct the amount from the sender's balance\n        unchecked {\n            _balanceOf[to] += amount; // Add the amount to the recipient's balance\n        }\n        libSJ20.emitTransfer(from, to, amount); // Emit an ERC20 transfer event\n    }\n\n    // Handles the transfer of an ERC721 token, ensuring proper ownership and event emission\n    function _transfer721(address from, address to, uint32 tokenId) internal virtual {\n        require(from == ownerOf[tokenId], \"SJ741: Incorrect owner\"); // Ensure 'from' is the current owner\n\n        delete _nftApprovals[tokenId]; // Clear any approvals for this token\n        ownerOf[tokenId] = to; // Transfer ownership of the token to 'to'\n        _updateOwnedNFTs(from, to, tokenId); // Update ownership tracking structures\n        libSJ721.emitTransfer(from, to, tokenId); // Emit an ERC721 transfer event\n    }\n\n    // only erc20 calls this\n    // if amount is a token id owned my the caller send as an NFT\n    // else transfer741\n    function transfer(address to, uint amount) public override returns (bool) {\n        if (ownerOf[amount] == msg.sender) {\n            _transfer721(msg.sender, to, uint32(amount));\n            _transfer20(msg.sender, to, ONE);\n            return true;\n        }\n        _transfer741(msg.sender, to, amount);\n        return true;\n    }\n\n    // erc20 and erc721 call this\n    function transferFrom(address from, address to, uint amount) public virtual returns (bool) {\n        //if amount is within the NFT id range, then a simple NFT transfer + token amount (ONE)\n        if (treasuryMintTimeStamp[from] > block.timestamp) {\n            uint finalBalance = _balanceOf[from] - amount;\n            require(finalBalance >= ONE, \"Can't transfer all your Gnome yet\");\n        }\n\n        if (amount > ONE && amount <= MAXID) {\n            require(\n                //require from is the msg caller, or that caller is approved for that specific NFT, or all NFTs\n                msg.sender == from || msg.sender == getApproved(amount) || isApprovedForAll(from, msg.sender),\n                \"SJ741: You don't have the right\"\n            );\n\n            _transfer721(from, to, uint32(amount));\n            _transfer20(from, to, ONE);\n            return true;\n        }\n\n        _spendAllowance(from, msg.sender, amount);\n        _transfer741(from, to, amount);\n        return true;\n    }\n\n    // erc721\n    function safeTransferFrom(address from, address to, uint256 tokenId) public payable override {\n        require(\n            msg.sender == from || msg.sender == getApproved(tokenId) || isApprovedForAll(from, msg.sender),\n            \"SJ741: You don't have the right\"\n        );\n        if (treasuryMintTimeStamp[from] > block.timestamp) {\n            uint finalBalance = _balanceOf[from] - ONE;\n            require(finalBalance >= ONE, \"Can't transfer all your Gnome yet\");\n        }\n        _transfer721(from, to, uint32(tokenId));\n        _transfer20(from, to, ONE);\n\n        if (\n            to.code.length != 0 &&\n            IERC721TokenReceiver(to).onERC721Received(msg.sender, from, tokenId, \"\") !=\n            IERC721TokenReceiver.onERC721Received.selector\n        ) {\n            revert UnsupportedReceiver();\n        }\n    }\n\n    // erc721\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public payable override {\n        require(\n            msg.sender == from || msg.sender == getApproved(tokenId) || isApprovedForAll(from, msg.sender),\n            \"SJ741: You don't have the right\"\n        );\n        if (treasuryMintTimeStamp[from] > block.timestamp) {\n            uint finalBalance = _balanceOf[from] - ONE;\n            require(finalBalance >= ONE, \"Can't transfer all your Gnome yet\");\n        }\n        _transfer721(from, to, uint32(tokenId));\n        _transfer20(from, to, ONE);\n\n        if (\n            to.code.length != 0 &&\n            IERC721TokenReceiver(to).onERC721Received(msg.sender, from, tokenId, data) !=\n            IERC721TokenReceiver.onERC721Received.selector\n        ) {\n            revert UnsupportedReceiver();\n        }\n    }\n\n    function _spendAllowance(address owner, address spender, uint amount) internal virtual {\n        require(_allowance[owner][spender] >= amount, \"SJ741: insufficient allowance\");\n        _allowance[owner][spender] -= amount;\n    }\n\n    function getApproved(uint256 tokenId) public view override returns (address) {\n        if (ownerOf[tokenId] == address(0)) revert();\n        return _nftApprovals[tokenId];\n    }\n\n    function setApprovalForAll(address operator, bool approved) public override {\n        _operatorApprovals[msg.sender][operator] = approved;\n        libSJ721.emitApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function isApprovedForAll(address owner, address operator) public view override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    function toString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(value % 10) + 48);\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    function withdraw() external onlyDev {\n        payable(dev).transfer(address(this).balance);\n    }\n\n    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n        return\n            // Even though we support ERC721 and should return true, etherscan wants to treat us as ERC721 instead of ERC20\n            // @DEV ERC165 for ERC721 can be toggled on for reasons of frontend/dapp/script implementations, but is very specific\n            (supportsNFTinterface && interfaceId == 0x80ac58cd) || // ERC165 interface ID for ERC721\n            interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165\n            interfaceId == 0x36372b07; // ERC165 interface ID for ERC20\n    }\n\n    // Modifier to restrict access to owner only\n    function getGnomeIds(address _gnome) public view returns (uint32[] memory) {\n        return ownedNFTs[_gnome];\n    }\n\n    function getIdGnome(uint256 _id) public view returns (address) {\n        return ownerOf[_id];\n    }\n\n    function factoryMint(address to) external onlyAuth returns (uint32) {\n        require(factoryMints < maxfactoryMints, \"No more Gnomies to Mint!\");\n        factoryMints++;\n\n        return _mintGnomes(to, false);\n    }\n\n    function authMint(address to) external onlyAuth returns (uint32) {\n        return _mintGnomes(to, false);\n    }\n\n    function fatalizeGnomeAuth(uint32 tokenId) public onlyAuth {\n        _burn(ownerOf[tokenId], tokenId);\n    }\n\n    modifier onlyAuth() {\n        require(msg.sender == owner() || isAuth[msg.sender], \"Caller is not the authorized\");\n        _;\n    }\n\n    function setChainId(string memory _chain, uint16 _ID) external onlyAuth {\n        destChainId[_chain] = _ID;\n    }\n\n    function setTokenURI(string memory _tokenURI) public onlyAuth {\n        baseTokenURI = _tokenURI;\n    }\n\n    function tokenURI(uint256 id) public view returns (string memory) {\n        if (!gameActive) {\n            return baseTokenURI;\n        }\n\n        // Check if gnomeGamePlay is set to a valid address\n        require(address(gnomeGamePlay) != address(0), \"gnomeGamePlay address is not set\");\n\n        if (gnomeGamePlay.isGnomeSignedUp(id)) {\n            return gnomeURI._tokenURI(id);\n        }\n\n        return baseTokenURI;\n    }\n\n    function setGnomeUri(IGnomeURI _renderer) external onlyAuth {\n        gnomeURI = _renderer;\n    }\n\n    function setGnomeGamePlay(IGnomeGamePlay _gnomeGamePlay, bool _gameActive) external onlyAuth {\n        gnomeGamePlay = _gnomeGamePlay;\n        gameActive = _gameActive;\n    }\n\n    function setIsAuth(address fren, bool isAuthorized) external onlyAuth {\n        isAuth[fren] = isAuthorized;\n    }\n\n    function setTreasuryMintTimeStamp(address gnome, uint256 timeStamp) external onlyAuth {\n        treasuryMintTimeStamp[gnome] = timeStamp;\n    }\n\n    function getTreasuryMintTimeStamp(address gnome) external view returns (uint256) {\n        return treasuryMintTimeStamp[gnome];\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200,
        "details": {
          "yul": true
        }
      },
      "viaIR": true,
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}