{"sources":{"JinchanNFT.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\n/// @title JinchanNFT — JINCHAN (project v5)\n/// @notice ERC-721 collection of 3,333 money-frog NFTs, gated to holders of\n///         the SPACE ID Agent ID registry NFT. Every mint delivers the NFT\n///         plus a JinchanToken bonus in the SAME transaction; the bonus size\n///         depends on the rarity tier drawn for that token. There are two\n///         separate pools with separate per-tier quotas:\n///           - free pool: 777 mints, 1 per wallet, price 0\n///             quotas Common 620 / Rare 130 / Epic 24 / Legendary 3\n///           - paid pool: 2,556 mints at 0.0006 BNB each, max 10 per wallet\n///             quotas Common 1380 / Rare 670 / Epic 376 / Legendary 130\n///         Tier bonuses: Common 50,000 / Rare 150,000 / Epic 400,000 /\n///         Legendary 1,000,000 JINCHAN, paid from this contract's own token\n///         balance (funded by the owner after deployment). If the bonus\n///         transfer cannot be completed, the whole mint reverts, so a mint\n///         can never deliver an NFT without its bonus.\n///         The mint window opens at an owner-set timestamp and closes\n///         exactly 48 hours later. Unsold quota simply never mints.\n/// @dev    Self-contained, no imports, so the source verifies as a single file.\n///\n///         TIER DRAW METHOD (deliberate design note): each mint draws its\n///         tier pseudo-randomly, weighted by the pool's REMAINING tier\n///         quotas, from\n///           keccak256(abi.encodePacked(block.prevrandao,\n///                                      blockhash(block.number - 1),\n///                                      msg.sender, address(this),\n///                                      drawNonce, block.timestamp))\n///         with an ever-increasing contract nonce. Known limits: this is\n///         NOT a verifiable random function. Block producers can influence\n///         prevrandao/blockhash to a degree, and a sophisticated caller can\n///         simulate a mint off-chain and only submit when the draw is\n///         favourable (revert-if-unfavourable grinding within the same\n///         block is limited only by the changing nonce, which the caller\n///         cannot reset but can observe). The quota weighting bounds the\n///         damage: no strategy can mint more Legendary tokens than the\n///         pool quota holds, and each draw consumes quota of the tier it\n///         lands on. For a fixed-price mint where every tier is a bonus\n///         (never a loss versus the mint price), this trade-off was chosen\n///         for simplicity and zero external dependencies.\n\ninterface IAgentIdRegistry {\n    function balanceOf(address owner) external view returns (uint256);\n}\n\ncontract JinchanNFT {\n    // ---------------------------------------------------------------- ERC-721\n    string public constant name = \"Jinchan\";\n    string public constant symbol = \"JINCHAN\";\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    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\n    // ------------------------------------------------------------------ setup\n    address public immutable owner;\n    IAgentIdRegistry public immutable agentIdRegistry;\n    address public immutable bonusToken;\n\n    // ------------------------------------------------------------------ sale\n    uint256 public constant PRICE = 600000000000000; // 0.0006 BNB\n    uint256 public constant FREE_SUPPLY = 777;\n    uint256 public constant PAID_SUPPLY = 2556;\n    uint256 public constant MAX_PAID_PER_WALLET = 10;\n    uint256 public constant MINT_DURATION = 48 hours;\n\n    uint256 public opensAt; // 0 = not scheduled yet\n    uint256 public freeMintedCount;\n    uint256 public paidMintedCount;\n    mapping(address => bool) private _freeClaimed;\n    mapping(address => uint256) public paidMintedBy;\n    mapping(uint256 => uint8) private _tiers;\n\n    // Remaining per-tier quota, index = tier (0 Common, 1 Rare, 2 Epic, 3 Legendary)\n    uint256[4] private _freeQuota;\n    uint256[4] private _paidQuota;\n    // Bonus per tier in token wei (18 decimals)\n    uint256[4] private _bonus;\n\n    string public baseURI;\n\n    uint256 private _nextTokenId = 1;\n    uint256 private _drawNonce;\n\n    event Minted(address indexed buyer, uint256 tokenId, uint8 tier, bool paid);\n    event OpensAtSet(uint256 opensAt);\n    event BaseURISet(string baseURI);\n    event ProceedsWithdrawn(address indexed to, uint256 amount);\n\n    error NotOwner();\n    error NoAgentId();\n    error MintNotOpen();\n    error MintClosed();\n    error AlreadyFreeClaimed();\n    error FreeSoldOut();\n    error PaidSoldOut();\n    error BadQuantity();\n    error PaidCapExceeded();\n    error WrongPayment();\n    error NonexistentToken();\n    error NotAuthorized();\n    error WrongFrom();\n    error ZeroAddress();\n    error BonusTransferFailed();\n    error TransferFailed();\n\n    bool private _entered;\n    modifier nonReentrant() {\n        require(!_entered, \"REENTRANCY\");\n        _entered = true;\n        _;\n        _entered = false;\n    }\n    modifier onlyOwner() {\n        if (msg.sender != owner) revert NotOwner();\n        _;\n    }\n\n    /// @param _agentIdRegistry  SPACE ID Agent ID registry:\n    ///                          0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F on BSC mainnet.\n    /// @param _bonusToken       JinchanToken address.\n    constructor(address _agentIdRegistry, address _bonusToken) {\n        if (_agentIdRegistry == address(0) || _bonusToken == address(0)) revert ZeroAddress();\n        owner = msg.sender;\n        agentIdRegistry = IAgentIdRegistry(_agentIdRegistry);\n        bonusToken = _bonusToken;\n\n        _freeQuota = [uint256(620), 130, 24, 3];\n        _paidQuota = [uint256(1380), 670, 376, 130];\n        _bonus = [\n            uint256(50000) * 10 ** 18,\n            uint256(150000) * 10 ** 18,\n            uint256(400000) * 10 ** 18,\n            uint256(1000000) * 10 ** 18\n        ];\n    }\n\n    // ------------------------------------------------------------ owner setup\n    /// @notice Schedule the mint window. Can only be changed before the\n    ///         first mint, so the published opening time can never move once\n    ///         minting has started.\n    function setOpensAt(uint256 _opensAt) external onlyOwner {\n        if (totalMinted() > 0) revert MintClosed();\n        opensAt = _opensAt;\n        emit OpensAtSet(_opensAt);\n    }\n\n    function setBaseURI(string calldata _baseURI) external onlyOwner {\n        baseURI = _baseURI;\n        emit BaseURISet(_baseURI);\n    }\n\n    /// @notice Withdraw all BNB collected from paid mints to `to`. The\n    ///         65/35 owner/LP split of the proceeds is an operational step\n    ///         performed by the owner after withdrawal.\n    function withdrawProceeds(address to) external onlyOwner nonReentrant {\n        if (to == address(0)) revert ZeroAddress();\n        uint256 amount = address(this).balance;\n        require(amount > 0, \"NOTHING_TO_WITHDRAW\");\n        (bool ok, ) = to.call{value: amount}(\"\");\n        if (!ok) revert TransferFailed();\n        emit ProceedsWithdrawn(to, amount);\n    }\n\n    // ------------------------------------------------------------------ views\n    function price() public pure returns (uint256) {\n        return PRICE;\n    }\n\n    function mintEnd() public view returns (uint256) {\n        return opensAt == 0 ? 0 : opensAt + MINT_DURATION;\n    }\n\n    function mintOpen() public view returns (bool) {\n        return opensAt != 0 && block.timestamp >= opensAt && block.timestamp < opensAt + MINT_DURATION;\n    }\n\n    function totalMinted() public view returns (uint256) {\n        return freeMintedCount + paidMintedCount;\n    }\n\n    function freeRemaining() public view returns (uint256) {\n        return FREE_SUPPLY - freeMintedCount;\n    }\n\n    function paidRemaining() public view returns (uint256) {\n        return PAID_SUPPLY - paidMintedCount;\n    }\n\n    function freeRemainingByTier(uint8 tier) public view returns (uint256) {\n        return _freeQuota[tier];\n    }\n\n    function paidRemainingByTier(uint8 tier) public view returns (uint256) {\n        return _paidQuota[tier];\n    }\n\n    function hasFreeClaimed(address user) public view returns (bool) {\n        return _freeClaimed[user];\n    }\n\n    function tierOf(uint256 tokenId) public view returns (uint8) {\n        if (_owners[tokenId] == address(0)) revert NonexistentToken();\n        return _tiers[tokenId];\n    }\n\n    function bonusForTier(uint8 tier) public view returns (uint256) {\n        return _bonus[tier];\n    }\n\n    // ------------------------------------------------------------------ mints\n    /// @notice Claim the one free mint for an Agent ID holder. Value must be 0.\n    function freeMint() external nonReentrant {\n        _requireOpen();\n        _requireAgentId();\n        if (_freeClaimed[msg.sender]) revert AlreadyFreeClaimed();\n        if (freeMintedCount >= FREE_SUPPLY) revert FreeSoldOut();\n        _freeClaimed[msg.sender] = true;\n        freeMintedCount += 1;\n        _mintOne(msg.sender, false);\n    }\n\n    /// @notice Paid mint of `qty` NFTs (1–10 per call, 10 per wallet in\n    ///         total). Value must be exactly qty * PRICE.\n    function mint(uint256 qty) external payable nonReentrant {\n        _requireOpen();\n        _requireAgentId();\n        if (qty == 0 || qty > MAX_PAID_PER_WALLET) revert BadQuantity();\n        if (msg.value != qty * PRICE) revert WrongPayment();\n        if (paidMintedBy[msg.sender] + qty > MAX_PAID_PER_WALLET) revert PaidCapExceeded();\n        if (paidMintedCount + qty > PAID_SUPPLY) revert PaidSoldOut();\n        paidMintedBy[msg.sender] += qty;\n        paidMintedCount += qty;\n        for (uint256 i = 0; i < qty; i++) {\n            _mintOne(msg.sender, true);\n        }\n    }\n\n    function _requireOpen() internal view {\n        if (opensAt == 0 || block.timestamp < opensAt) revert MintNotOpen();\n        if (block.timestamp >= opensAt + MINT_DURATION) revert MintClosed();\n    }\n\n    function _requireAgentId() internal view {\n        if (agentIdRegistry.balanceOf(msg.sender) == 0) revert NoAgentId();\n    }\n\n    function _mintOne(address to, bool paid) internal {\n        uint8 tier = _drawTier(paid);\n        uint256 tokenId = _nextTokenId++;\n        _owners[tokenId] = to;\n        _balances[to] += 1;\n        _tiers[tokenId] = tier;\n        emit Transfer(address(0), to, tokenId);\n        _payBonus(to, _bonus[tier]);\n        emit Minted(to, tokenId, tier, paid);\n    }\n\n    /// @dev Draw weighted by the pool's remaining quotas; each draw consumes\n    ///      one unit of the tier it lands on. See the tier-draw design note\n    ///      in the contract header for the method and its known limits.\n    function _drawTier(bool paid) internal returns (uint8) {\n        uint256 total = paid\n            ? _paidQuota[0] + _paidQuota[1] + _paidQuota[2] + _paidQuota[3]\n            : _freeQuota[0] + _freeQuota[1] + _freeQuota[2] + _freeQuota[3];\n        if (total == 0) {\n            if (paid) revert PaidSoldOut();\n            revert FreeSoldOut();\n        }\n        uint256 r = uint256(\n            keccak256(\n                abi.encodePacked(\n                    block.prevrandao,\n                    blockhash(block.number - 1),\n                    msg.sender,\n                    address(this),\n                    _drawNonce++,\n                    block.timestamp\n                )\n            )\n        ) % total;\n        for (uint8 t = 0; t < 4; t++) {\n            uint256 q = paid ? _paidQuota[t] : _freeQuota[t];\n            if (r < q) {\n                if (paid) {\n                    _paidQuota[t] = q - 1;\n                } else {\n                    _freeQuota[t] = q - 1;\n                }\n                return t;\n            }\n            r -= q;\n        }\n        // Unreachable: r < total guarantees a tier is hit above.\n        revert PaidSoldOut();\n    }\n\n    function _payBonus(address to, uint256 amount) internal {\n        (bool ok, bytes memory data) = bonusToken.call(\n            abi.encodeWithSignature(\"transfer(address,uint256)\", to, amount)\n        );\n        if (!ok || (data.length > 0 && !abi.decode(data, (bool)))) revert BonusTransferFailed();\n    }\n\n    // ---------------------------------------------------------------- ERC-721\n    function balanceOf(address account) public view returns (uint256) {\n        if (account == address(0)) revert ZeroAddress();\n        return _balances[account];\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address) {\n        address o = _owners[tokenId];\n        if (o == address(0)) revert NonexistentToken();\n        return o;\n    }\n\n    function tokenURI(uint256 tokenId) public view returns (string memory) {\n        if (_owners[tokenId] == address(0)) revert NonexistentToken();\n        return string(abi.encodePacked(baseURI, _toString(tokenId)));\n    }\n\n    function approve(address to, uint256 tokenId) external {\n        address o = ownerOf(tokenId);\n        if (msg.sender != o && !_operatorApprovals[o][msg.sender]) revert NotAuthorized();\n        _tokenApprovals[tokenId] = to;\n        emit Approval(o, to, tokenId);\n    }\n\n    function getApproved(uint256 tokenId) public view returns (address) {\n        if (_owners[tokenId] == address(0)) revert NonexistentToken();\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 account, address operator) public view returns (bool) {\n        return _operatorApprovals[account][operator];\n    }\n\n    function transferFrom(address from, address to, uint256 tokenId) public {\n        if (!_isAuthorized(msg.sender, tokenId)) revert NotAuthorized();\n        if (ownerOf(tokenId) != from) revert WrongFrom();\n        if (to == address(0)) revert ZeroAddress();\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            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) revert NotAuthorized();\n            } catch {\n                revert NotAuthorized();\n            }\n        }\n    }\n\n    function supportsInterface(bytes4 interfaceId) external pure returns (bool) {\n        return interfaceId == 0x01ffc9a7 // ERC165\n            || interfaceId == 0x80ac58cd // ERC721\n            || interfaceId == 0x5b5e139f; // ERC721Metadata\n    }\n\n    function _isAuthorized(address spender, uint256 tokenId) internal view returns (bool) {\n        address o = _owners[tokenId];\n        return spender == o || _tokenApprovals[tokenId] == spender || _operatorApprovals[o][spender];\n    }\n\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    receive() external payable {}\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":"_agentIdRegistry","type":"address","internalType":"address"},{"name":"_bonusToken","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"AlreadyFreeClaimed","type":"error","inputs":[]},{"name":"BadQuantity","type":"error","inputs":[]},{"name":"BonusTransferFailed","type":"error","inputs":[]},{"name":"FreeSoldOut","type":"error","inputs":[]},{"name":"MintClosed","type":"error","inputs":[]},{"name":"MintNotOpen","type":"error","inputs":[]},{"name":"NoAgentId","type":"error","inputs":[]},{"name":"NonexistentToken","type":"error","inputs":[]},{"name":"NotAuthorized","type":"error","inputs":[]},{"name":"NotOwner","type":"error","inputs":[]},{"name":"PaidCapExceeded","type":"error","inputs":[]},{"name":"PaidSoldOut","type":"error","inputs":[]},{"name":"TransferFailed","type":"error","inputs":[]},{"name":"WrongFrom","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"ZeroAddress","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":"BaseURISet","type":"event","inputs":[{"name":"baseURI","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"name":"Minted","type":"event","inputs":[{"name":"buyer","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"tier","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"paid","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"OpensAtSet","type":"event","inputs":[{"name":"opensAt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"ProceedsWithdrawn","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"amount","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":"MAX_PAID_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MINT_DURATION","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PAID_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":"agentIdRegistry","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentIdRegistry"}],"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":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"baseURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"bonusForTier","type":"function","inputs":[{"name":"tier","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"bonusToken","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"freeMint","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"freeMintedCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeRemaining","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeRemainingByTier","type":"function","inputs":[{"name":"tier","type":"uint8","internalType":"uint8"}],"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":"hasFreeClaimed","type":"function","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"account","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":"mintEnd","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"opensAt","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"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":"paidMintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidMintedCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidRemaining","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidRemainingByTier","type":"function","inputs":[{"name":"tier","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"price","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"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":"setBaseURI","type":"function","inputs":[{"name":"_baseURI","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setOpensAt","type":"function","inputs":[{"name":"_opensAt","type":"uint256","internalType":"uint256"}],"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":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"totalMinted","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":"withdrawProceeds","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"receive","stateMutability":"payable"}],"matchId":"58809089","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-08T09:07:28Z","match":"exact_match","chainId":"56","address":"0xccc127D1A7Ef1e385757784a9878F7279BF3B19D"}