{"sources":{"LuckyMoments.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\n/// @title Lucky Moments (LUMO) — luck cards for AI agents.\n/// @notice Free Genesis claims are gated twice: the caller must hold a Binance\n///         Agent ID (.ai registry) AND present a one-wallet EIP-712 permit from\n///         the project's gate signer. Permits are issued on the project website\n///         only after the claimer's human posts about the project on X and the\n///         post is checked. The gate signer can do nothing else: it cannot move\n///         funds, change prices, or mint. After the free phase, paid mints are\n///         open to everyone at a fixed price, half price for Genesis claimers.\n///         Sale proceeds are forwarded to the treasury in the same transaction.\n///         There are no admin functions.\n\ninterface IAgentRegistry {\n    function balanceOf(address owner) external view returns (uint256);\n}\n\ncontract LuckyMoments {\n    // ------------------------------------------------------------------ ERC-721\n    string public constant name = \"Lucky Moments\";\n    string public constant symbol = \"LUMO\";\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n    event FreeClaimed(address indexed wallet, uint256 indexed tokenId, uint256 luck);\n    event PaidMint(address indexed wallet, uint256 qty, uint256 cost);\n\n    mapping(uint256 => address) private _owners;\n    mapping(address => uint256) private _balances;\n    mapping(uint256 => address) private _tokenApprovals;\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    // ------------------------------------------------------------------ sale rules\n    // The SPACE ID Agent ID registry on BSC mainnet:\n    // 0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F (passed at deployment, immutable).\n    IAgentRegistry public immutable agentRegistry;\n\n    uint256 public constant FREE_SUPPLY = 1500;\n    uint256 public constant MAX_SUPPLY = 5000;\n    uint256 public constant FREE_WINDOW = 7 days;\n    uint256 public constant PRICE = 0.001 ether;\n    uint256 public constant HOLDER_PRICE = 0.0005 ether;\n    uint256 public constant PAID_LIMIT = 10;\n\n    address public immutable gateSigner;\n    address public immutable treasury;\n    uint256 public immutable freeStart;\n    uint256 public immutable freeEnd;\n\n    uint256 public totalSupply;\n    uint256 public freeMinted;\n    mapping(address => bool) public freeClaimed;\n    mapping(address => uint256) public paidMinted;\n    mapping(uint256 => address) public minterOf;\n    mapping(uint256 => uint256) public mintedAt;\n\n    // ------------------------------------------------------------------ EIP-712\n    bytes32 private immutable _domainSeparator;\n    // keccak256(\"Permit(address wallet,uint256 deadline)\")\n    bytes32 private constant _PERMIT_TYPEHASH = keccak256(\"Permit(address wallet,uint256 deadline)\");\n\n    constructor(address gateSigner_, address treasury_, address agentRegistry_) {\n        require(gateSigner_ != address(0), \"signer=0\");\n        require(treasury_ != address(0), \"treasury=0\");\n        require(agentRegistry_ != address(0), \"registry=0\");\n        gateSigner = gateSigner_;\n        treasury = treasury_;\n        agentRegistry = IAgentRegistry(agentRegistry_);\n        freeStart = block.timestamp;\n        freeEnd = block.timestamp + FREE_WINDOW;\n        _domainSeparator = keccak256(\n            abi.encode(\n                keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                keccak256(bytes(\"LuckyMoments\")),\n                keccak256(bytes(\"1\")),\n                block.chainid,\n                address(this)\n            )\n        );\n    }\n\n    // ------------------------------------------------------------------ claims\n    /// @notice Claim the free Genesis card. Needs an Agent ID and a gate permit\n    ///         (EIP-712 signature by gateSigner over (msg.sender, deadline)).\n    function claimFree(uint256 deadline, bytes calldata signature) external {\n        require(block.timestamp <= freeEnd, \"free window closed\");\n        require(freeMinted < FREE_SUPPLY, \"free supply gone\");\n        require(!freeClaimed[msg.sender], \"already claimed\");\n        require(agentRegistry.balanceOf(msg.sender) > 0, \"no Agent ID\");\n        require(block.timestamp <= deadline, \"permit expired\");\n        require(_permitValid(msg.sender, deadline, signature), \"bad permit\");\n\n        freeClaimed[msg.sender] = true;\n        freeMinted += 1;\n        uint256 tokenId = _mint(msg.sender);\n        emit FreeClaimed(msg.sender, tokenId, luckOf(tokenId));\n    }\n\n    function _permitValid(address wallet, uint256 deadline, bytes calldata signature)\n        internal\n        view\n        returns (bool)\n    {\n        if (signature.length != 65) return false;\n        bytes32 r;\n        bytes32 s;\n        uint8 v;\n        assembly {\n            r := calldataload(signature.offset)\n            s := calldataload(add(signature.offset, 32))\n            v := byte(0, calldataload(add(signature.offset, 64)))\n        }\n        // reject malleable signatures\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return false;\n        }\n        if (v != 27 && v != 28) return false;\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, wallet, deadline));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", _domainSeparator, structHash));\n        address recovered = ecrecover(digest, v, r, s);\n        return recovered != address(0) && recovered == gateSigner;\n    }\n\n    // ------------------------------------------------------------------ paid phase\n    function paidOpen() public view returns (bool) {\n        return freeMinted >= FREE_SUPPLY || block.timestamp > freeEnd;\n    }\n\n    /// @notice Current paid price for a wallet (Genesis claimers pay half).\n    function priceFor(address wallet) public view returns (uint256) {\n        return freeClaimed[wallet] ? HOLDER_PRICE : PRICE;\n    }\n\n    function mint(uint256 qty) external payable {\n        require(paidOpen(), \"paid phase not open\");\n        require(qty >= 1 && qty <= PAID_LIMIT, \"qty out of range\");\n        require(paidMinted[msg.sender] + qty <= PAID_LIMIT, \"paid limit reached\");\n        require(totalSupply + qty <= MAX_SUPPLY, \"supply gone\");\n        uint256 cost = priceFor(msg.sender) * qty;\n        require(msg.value >= cost, \"underpaid\");\n\n        paidMinted[msg.sender] += qty;\n        for (uint256 i = 0; i < qty; i++) {\n            _mint(msg.sender);\n        }\n        (bool ok, ) = payable(treasury).call{value: cost}(\"\");\n        require(ok, \"treasury transfer failed\");\n        if (msg.value > cost) {\n            (bool okRefund, ) = payable(msg.sender).call{value: msg.value - cost}(\"\");\n            require(okRefund, \"refund failed\");\n        }\n        emit PaidMint(msg.sender, qty, cost);\n    }\n\n    // ------------------------------------------------------------------ luck\n    function luckOf(uint256 tokenId) public view returns (uint256) {\n        require(_owners[tokenId] != address(0), \"no such token\");\n        return (uint256(keccak256(abi.encode(tokenId, minterOf[tokenId]))) % 100) + 1;\n    }\n\n    function tierOf(uint256 tokenId) public view returns (string memory) {\n        uint256 luck = luckOf(tokenId);\n        if (luck >= 95) return \"Jackpot\";\n        if (luck >= 80) return \"Epic\";\n        if (luck >= 55) return \"Rare\";\n        return \"Common\";\n    }\n\n    // ------------------------------------------------------------------ views for the site\n    function overview()\n        external\n        view\n        returns (\n            uint256 _totalSupply,\n            uint256 _freeMinted,\n            uint256 _freeRemaining,\n            uint256 _freeEnd,\n            bool _paidOpen,\n            uint256 _price,\n            uint256 _holderPrice\n        )\n    {\n        return (\n            totalSupply,\n            freeMinted,\n            FREE_SUPPLY - freeMinted,\n            freeEnd,\n            paidOpen(),\n            PRICE,\n            HOLDER_PRICE\n        );\n    }\n\n    // ------------------------------------------------------------------ metadata (fully on-chain)\n    function tokenURI(uint256 tokenId) external view returns (string memory) {\n        require(_owners[tokenId] != address(0), \"no such token\");\n        uint256 luck = luckOf(tokenId);\n        string memory tier = tierOf(tokenId);\n        string memory json = string.concat(\n            '{\"name\":\"Lucky Moments #',\n            _toString(tokenId),\n            '\",\"description\":\"A luck card sealed at the moment it was minted. Genesis cards were claimed free by Agent ID holders who spread the signal first - the share was the price.\",',\n            '\"image\":\"data:image/svg+xml;base64,',\n            _base64(bytes(_svg(tokenId, luck, tier))),\n            '\",\"attributes\":[',\n            '{\"trait_type\":\"Luck Index\",\"value\":',\n            _toString(luck),\n            '},{\"trait_type\":\"Tier\",\"value\":\"',\n            tier,\n            '\"},{\"trait_type\":\"Mint Type\",\"value\":\"',\n            _isGenesis(tokenId) ? \"Genesis\" : \"Standard\",\n            '\"},{\"trait_type\":\"Minted At\",\"value\":',\n            _toString(mintedAt[tokenId]),\n            \"}]}\"\n        );\n        return string.concat(\"data:application/json;base64,\", _base64(bytes(json)));\n    }\n\n    function _isGenesis(uint256 tokenId) internal view returns (bool) {\n        // Genesis cards are the ones minted through claimFree; they are exactly\n        // the first freeMinted token ids only if no paid mint interleaves, which\n        // cannot happen: paid phase opens only after the free phase ends.\n        return tokenId <= freeMinted;\n    }\n\n    function _svg(uint256 tokenId, uint256 luck, string memory tier) internal pure returns (string memory) {\n        string memory color = \"#37d67a\";\n        if (luck >= 95) color = \"#ffd700\";\n        else if (luck >= 80) color = \"#b388ff\";\n        else if (luck >= 55) color = \"#4fc3f7\";\n        return string.concat(\n            '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"600\" height=\"800\" viewBox=\"0 0 600 800\">',\n            '<defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">',\n            '<stop offset=\"0\" stop-color=\"#0b1020\"/><stop offset=\"1\" stop-color=\"#1d2b1d\"/>',\n            \"</linearGradient></defs>\",\n            '<rect width=\"600\" height=\"800\" fill=\"url(#g)\"/>',\n            '<rect x=\"24\" y=\"24\" width=\"552\" height=\"752\" fill=\"none\" stroke=\"',\n            color,\n            '\" stroke-width=\"3\" rx=\"18\"/>',\n            '<text x=\"300\" y=\"150\" font-family=\"monospace\" font-size=\"34\" fill=\"',\n            color,\n            '\" text-anchor=\"middle\" letter-spacing=\"6\">LUCKY MOMENTS</text>',\n            '<text x=\"300\" y=\"430\" font-family=\"monospace\" font-size=\"220\" font-weight=\"bold\" fill=\"',\n            color,\n            '\" text-anchor=\"middle\">',\n            _toString(luck),\n            \"</text>\",\n            '<text x=\"300\" y=\"520\" font-family=\"monospace\" font-size=\"30\" fill=\"#e8f5e9\" text-anchor=\"middle\">LUCK INDEX</text>',\n            '<text x=\"300\" y=\"640\" font-family=\"monospace\" font-size=\"40\" fill=\"#ffffff\" text-anchor=\"middle\">',\n            tier,\n            \"</text>\",\n            '<text x=\"300\" y=\"720\" font-family=\"monospace\" font-size=\"26\" fill=\"#9e9e9e\" text-anchor=\"middle\">CARD #',\n            _toString(tokenId),\n            \"</text></svg>\"\n        );\n    }\n\n    // ------------------------------------------------------------------ minting core\n    function _mint(address to) internal returns (uint256 tokenId) {\n        totalSupply += 1;\n        tokenId = totalSupply;\n        _owners[tokenId] = to;\n        _balances[to] += 1;\n        minterOf[tokenId] = to;\n        mintedAt[tokenId] = block.timestamp;\n        emit Transfer(address(0), to, tokenId);\n        if (to.code.length > 0) {\n            require(\n                IERC721Receiver(to).onERC721Received(msg.sender, address(0), tokenId, \"\") ==\n                    IERC721Receiver.onERC721Received.selector,\n                \"unsafe recipient\"\n            );\n        }\n    }\n\n    // ------------------------------------------------------------------ ERC-721 surface\n    function balanceOf(address owner) external view returns (uint256) {\n        require(owner != address(0), \"zero address\");\n        return _balances[owner];\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address) {\n        address owner = _owners[tokenId];\n        require(owner != address(0), \"no such token\");\n        return owner;\n    }\n\n    function approve(address to, uint256 tokenId) external {\n        address owner = ownerOf(tokenId);\n        require(msg.sender == owner || _operatorApprovals[owner][msg.sender], \"not authorized\");\n        _tokenApprovals[tokenId] = to;\n        emit Approval(owner, to, tokenId);\n    }\n\n    function getApproved(uint256 tokenId) external view returns (address) {\n        require(_owners[tokenId] != address(0), \"no such token\");\n        return _tokenApprovals[tokenId];\n    }\n\n    function setApprovalForAll(address operator, bool approved) external {\n        _operatorApprovals[msg.sender][operator] = approved;\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function isApprovedForAll(address owner, address operator) external view returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    function transferFrom(address from, address to, uint256 tokenId) public {\n        require(ownerOf(tokenId) == from, \"not owner\");\n        require(to != address(0), \"zero address\");\n        require(\n            msg.sender == from || msg.sender == _tokenApprovals[tokenId] || _operatorApprovals[from][msg.sender],\n            \"not authorized\"\n        );\n        delete _tokenApprovals[tokenId];\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n        emit Transfer(from, to, tokenId);\n    }\n\n    function safeTransferFrom(address from, address to, uint256 tokenId) external {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public {\n        transferFrom(from, to, tokenId);\n        if (to.code.length > 0) {\n            require(\n                IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) ==\n                    IERC721Receiver.onERC721Received.selector,\n                \"unsafe recipient\"\n            );\n        }\n    }\n\n    function supportsInterface(bytes4 interfaceId) external pure returns (bool) {\n        return\n            interfaceId == 0x01ffc9a7 || // ERC165\n            interfaceId == 0x80ac58cd || // ERC721\n            interfaceId == 0x5b5e139f; // ERC721Metadata\n    }\n\n    // ------------------------------------------------------------------ helpers\n    function _toString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) return \"0\";\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(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    function _base64(bytes memory data) internal pure returns (string memory) {\n        bytes memory table = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n        if (data.length == 0) return \"\";\n        uint256 encodedLen = 4 * ((data.length + 2) / 3);\n        bytes memory result = new bytes(encodedLen + 32);\n        uint256 i;\n        uint256 j;\n        assembly {\n            let tablePtr := add(table, 1)\n            let resultPtr := add(result, 32)\n            for {} lt(i, mload(data)) {} {\n                i := add(i, 3)\n                let input := and(mload(add(data, i)), 0xffffff)\n                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))\n                out := shl(8, out)\n                out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))\n                out := shl(8, out)\n                out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))\n                out := shl(8, out)\n                out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))\n                out := shl(224, out)\n                mstore(resultPtr, out)\n                resultPtr := add(resultPtr, 4)\n            }\n            switch mod(mload(data), 3)\n            case 1 {\n                mstore(sub(resultPtr, 2), \"==\")\n            }\n            case 2 {\n                mstore(sub(resultPtr, 1), \"=\")\n            }\n            mstore(result, encodedLen)\n        }\n        return string(result);\n    }\n}\n\ninterface IERC721Receiver {\n    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)\n        external\n        returns (bytes4);\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"gateSigner_","type":"address","internalType":"address"},{"name":"treasury_","type":"address","internalType":"address"},{"name":"agentRegistry_","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"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":"FreeClaimed","type":"event","inputs":[{"name":"wallet","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"luck","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"PaidMint","type":"event","inputs":[{"name":"wallet","type":"address","indexed":true,"internalType":"address"},{"name":"qty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"cost","type":"uint256","indexed":false,"internalType":"uint256"}],"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":"FREE_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_WINDOW","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"HOLDER_PRICE","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":"PAID_LIMIT","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":"agentRegistry","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentRegistry"}],"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":"claimFree","type":"function","inputs":[{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"signature","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"freeClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"freeEnd","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeStart","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"gateSigner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"luckOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"mintedAt","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"minterOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"overview","type":"function","inputs":[],"outputs":[{"name":"_totalSupply","type":"uint256","internalType":"uint256"},{"name":"_freeMinted","type":"uint256","internalType":"uint256"},{"name":"_freeRemaining","type":"uint256","internalType":"uint256"},{"name":"_freeEnd","type":"uint256","internalType":"uint256"},{"name":"_paidOpen","type":"bool","internalType":"bool"},{"name":"_price","type":"uint256","internalType":"uint256"},{"name":"_holderPrice","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"paidMinted","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"priceFor","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"}],"outputs":[{"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":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tierOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"tokenId","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":"treasury","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"}],"matchId":"58971278","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-10T05:02:46Z","match":"exact_match","chainId":"56","address":"0x1E340592665889735C1F871aA13d038fa58bd09e"}