{"sources":{"ZodiacPixel.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\ninterface IAgentId {\n    function balanceOf(address owner) external view returns (uint256);\n}\n\ninterface IERC721Receiver {\n    function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4);\n}\n\n/// PIXEL ZODIAC · 像素十二生肖 (PZDC) - 2,400 original pixel zodiac animals (12 x 200), drawn fully on-chain.\n/// Rules are fixed in code:\n/// - Only addresses holding a SPACE ID .ai Agent ID can mint. Mint window: 5 days from deploy.\n/// - Free tier (2,000): freeMint() gives 2 per wallet, 3 if the wallet holds PIXEL PANDA or PIXEL PONY.\n/// - Puzzle tier (400): puzzleMint(nonce), 1 per wallet, needs keccak256(this, sender, nonce) with 20 leading zero bits.\n/// - Each mint draws an animal pseudo-randomly from the animals still in stock: exactly 200 of each.\n/// - 12 hidden Lucky 1/1s, one per animal, fixed by a hash of a seed taken at deploy.\n/// - craft(): burn one of each of the 12 animals + 0.004 BNB -> 1 numbered GOLDEN DRAGON 金龙 (max 100), forever.\n///   100% of the fee goes to the creator in the same transaction; overpayment is refunded.\n/// - No owner, no admin, no withdraw. 5% EIP-2981 royalty to the creator.\ncontract ZodiacPixel {\n    string public constant name = \"PIXEL ZODIAC\";\n    string public constant symbol = \"PZDC\";\n\n    uint256 public constant ZODIAC_SUPPLY = 2400;\n    uint256 public constant PER_ANIMAL = 200;\n    uint256 public constant FREE_CAP = 2000;\n    uint256 public constant PUZZLE_CAP = 400;\n    uint256 public constant GOLDEN_CAP = 100;\n    uint256 public constant FREE_PER_WALLET = 2;\n    uint256 public constant FREE_PER_HOLDER = 3;\n    uint256 public constant PUZZLE_BITS = 20;\n    uint256 public constant CRAFT_FEE = 0.004 ether;\n    uint256 public constant MINT_DURATION = 5 days;\n    uint96 public constant ROYALTY_BPS = 500; // 5%\n\n    IAgentId public constant AGENT_ID = IAgentId(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    address public constant PIXEL_PANDA = 0x4a3FCc4E49AE9dE55e823F5B1A3A9f1fF462D3f6;\n    address public constant PIXEL_PONY = 0xeff99Ef487F56EF9B2BEF5F3bc04A616625b0eFE;\n\n    address public immutable creator;\n    uint256 public immutable mintStart;\n    uint256 public immutable mintEnd;\n    bytes32 private immutable SEED; // picks the 12 Lucky 1/1s; taken at deploy\n\n    uint256 public freeMinted;\n    uint256 public puzzleMinted;\n    uint256 public goldenMinted;\n    uint256 public burned;\n    uint16[12] private _animalMinted;\n    mapping(address => bool) public freeClaimed;\n    mapping(address => bool) public puzzleClaimed;\n\n    /// animal 0-11 zodiac, 12 Golden Dragon; ordinal = n-th of its animal (1-200); tier 0 free, 1 puzzle, 2 crafted\n    struct Tok {\n        address owner;\n        uint8 animal;\n        uint8 ordinal;\n        uint8 tier;\n    }\n\n    mapping(uint256 => Tok) private _tok;\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    event Crafted(address indexed crafter, uint256 indexed tokenId, uint256 serial);\n\n    error NotAgent();\n    error MintClosed();\n    error NoFreeLeft();\n    error NoPuzzleLeft();\n    error AlreadyClaimed();\n    error BadNonce();\n    error WrongPayment();\n    error GoldenSoldOut();\n    error NotOwner();\n    error WrongSet();\n    error NotOwnerNorApproved();\n    error InvalidToken();\n    error ZeroAddress();\n    error UnsafeRecipient();\n    error TransferFailed();\n\n    constructor(address _creator) {\n        if (_creator == address(0)) revert ZeroAddress();\n        creator = _creator;\n        mintStart = block.timestamp;\n        mintEnd = block.timestamp + MINT_DURATION;\n        SEED = keccak256(abi.encodePacked(block.prevrandao, block.timestamp, address(this), _creator));\n    }\n\n    // ---------------- Mint ----------------\n\n    function _open() private view {\n        if (block.timestamp >= mintEnd) revert MintClosed();\n        if (AGENT_ID.balanceOf(msg.sender) == 0) revert NotAgent();\n    }\n\n    /// balanceOf(a) > 0 on `token`, without reverting if the call fails or returns garbage\n    /// (a low-level staticcall: unlike try/catch it also survives a missing contract or bad return data).\n    function _holds(address token, address a) private view returns (bool) {\n        (bool ok, bytes memory r) = token.staticcall(abi.encodeWithSelector(0x70a08231, a));\n        return ok && r.length >= 32 && abi.decode(r, (uint256)) > 0;\n    }\n\n    /// Free tokens `a` would get from freeMint() right now (0 if claimed / none left).\n    function freeAllowance(address a) public view returns (uint256 n) {\n        if (freeClaimed[a]) return 0;\n        n = _holds(PIXEL_PANDA, a) || _holds(PIXEL_PONY, a) ? FREE_PER_HOLDER : FREE_PER_WALLET;\n        uint256 left = FREE_CAP - freeMinted;\n        if (n > left) n = left;\n    }\n\n    /// 2 free zodiac tokens per wallet (3 for PIXEL PANDA / PIXEL PONY holders), value 0.\n    function freeMint() external {\n        _open();\n        if (freeClaimed[msg.sender]) revert AlreadyClaimed();\n        uint256 n = freeAllowance(msg.sender);\n        if (n == 0) revert NoFreeLeft();\n        freeClaimed[msg.sender] = true;\n        _mintZodiac(msg.sender, n, 0);\n        freeMinted += n;\n    }\n\n    /// True if keccak256(abi.encodePacked(address(this), minter, nonce)) has >= 20 leading zero bits.\n    function checkNonce(address minter, uint256 nonce) public view returns (bool) {\n        return uint256(keccak256(abi.encodePacked(address(this), minter, nonce))) >> (256 - PUZZLE_BITS) == 0;\n    }\n\n    /// 1 zodiac token per wallet from the separate 400-token puzzle supply, value 0.\n    function puzzleMint(uint256 nonce) external {\n        _open();\n        if (puzzleClaimed[msg.sender]) revert AlreadyClaimed();\n        if (puzzleMinted >= PUZZLE_CAP) revert NoPuzzleLeft();\n        if (!checkNonce(msg.sender, nonce)) revert BadNonce();\n        puzzleClaimed[msg.sender] = true;\n        _mintZodiac(msg.sender, 1, 1);\n        ++puzzleMinted;\n    }\n\n    /// Draws each animal from the remaining stock, so every animal ends at exactly 200.\n    /// Called before the tier counter is raised, so zodiacMinted() is the last id minted so far.\n    function _mintZodiac(address to, uint256 n, uint8 tier) private {\n        uint16[12] memory c = _animalMinted;\n        uint256 id = zodiacMinted();\n        uint256 left = ZODIAC_SUPPLY - id;\n        for (uint256 k; k < n; ++k) {\n            ++id;\n            uint256 r = uint256(keccak256(abi.encodePacked(block.prevrandao, to, id))) % left;\n            uint256 a;\n            while (true) {\n                uint256 l = PER_ANIMAL - c[a];\n                if (r < l) break;\n                r -= l;\n                ++a;\n            }\n            uint16 ord = ++c[a];\n            --left;\n            _tok[id] = Tok(to, uint8(a), uint8(ord), tier);\n            emit Transfer(address(0), to, id);\n        }\n        _animalMinted = c;\n        _balances[to] += n;\n    }\n\n    // ---------------- Craft ----------------\n\n    /// Burn 12 tokens you own, one of each animal (any order), plus CRAFT_FEE -> 1 numbered Golden Dragon.\n    function craft(uint256[12] calldata ids) external payable returns (uint256 tokenId) {\n        if (msg.value < CRAFT_FEE) revert WrongPayment();\n        if (goldenMinted >= GOLDEN_CAP) revert GoldenSoldOut();\n        uint256 mask;\n        for (uint256 i; i < 12; ++i) {\n            uint256 id = ids[i];\n            if (id > ZODIAC_SUPPLY) revert WrongSet();\n            Tok storage t = _tok[id];\n            if (t.owner != msg.sender) revert NotOwner();\n            uint256 bit = 1 << t.animal;\n            if (mask & bit != 0) revert WrongSet();\n            mask |= bit;\n            t.owner = address(0);\n            delete _tokenApprovals[id];\n            emit Transfer(msg.sender, address(0), id);\n        }\n        _balances[msg.sender] -= 11; // 12 burned, 1 minted\n        burned += 12;\n        uint256 serial = ++goldenMinted;\n        tokenId = ZODIAC_SUPPLY + serial;\n        _tok[tokenId] = Tok(msg.sender, 12, 0, 2);\n        emit Transfer(address(0), msg.sender, tokenId);\n        emit Crafted(msg.sender, tokenId, serial);\n        _pay(creator, CRAFT_FEE);\n        if (msg.value > CRAFT_FEE) _pay(msg.sender, msg.value - CRAFT_FEE);\n    }\n\n    function _pay(address to, uint256 amount) private {\n        (bool ok, ) = payable(to).call{value: amount}(\"\");\n        if (!ok) revert TransferFailed();\n    }\n\n    // ---------------- Views ----------------\n\n    function zodiacMinted() public view returns (uint256) {\n        return freeMinted + puzzleMinted;\n    }\n\n    /// Every token ever minted (zodiac + Golden Dragons); burned tokens stay counted, see burned().\n    function totalSupply() external view returns (uint256) {\n        return freeMinted + puzzleMinted + goldenMinted;\n    }\n\n    function remaining() external view returns (uint256) {\n        return ZODIAC_SUPPLY - zodiacMinted();\n    }\n\n    function freeLeft() external view returns (uint256) {\n        return FREE_CAP - freeMinted;\n    }\n\n    function puzzleLeft() external view returns (uint256) {\n        return PUZZLE_CAP - puzzleMinted;\n    }\n\n    function goldenLeft() external view returns (uint256) {\n        return GOLDEN_CAP - goldenMinted;\n    }\n\n    function animalLeft(uint8 a) external view returns (uint256) {\n        return PER_ANIMAL - _animalMinted[a];\n    }\n\n    /// 0-11 = Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Goat, Monkey, Rooster, Dog, Pig; 12 = Golden Dragon\n    function animalOf(uint256 tokenId) external view returns (uint8) {\n        ownerOf(tokenId);\n        return _tok[tokenId].animal;\n    }\n\n    function mintOpen() external view returns (bool) {\n        return block.timestamp < mintEnd && zodiacMinted() < ZODIAC_SUPPLY;\n    }\n\n    /// For craft(): the lowest token id `a` owns of each animal (0 where it has none).\n    function craftSet(address a) external view returns (uint256[12] memory ids) {\n        uint256 n = zodiacMinted();\n        for (uint256 id = n; id != 0; --id) {\n            Tok memory t = _tok[id];\n            if (t.owner == a) ids[t.animal] = id;\n        }\n    }\n\n    // ---------------- ERC-721 ----------------\n    function supportsInterface(bytes4 id) external pure returns (bool) {\n        return id == 0x01ffc9a7 || id == 0x80ac58cd || id == 0x5b5e139f || id == 0x2a55205a;\n    }\n\n    function balanceOf(address owner) external view returns (uint256) {\n        if (owner == address(0)) revert ZeroAddress();\n        return _balances[owner];\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address o) {\n        o = _tok[tokenId].owner;\n        if (o == address(0)) revert InvalidToken();\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 NotOwnerNorApproved();\n        _tokenApprovals[tokenId] = to;\n        emit Approval(o, to, tokenId);\n    }\n\n    function getApproved(uint256 tokenId) external view returns (address) {\n        ownerOf(tokenId);\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        address o = ownerOf(tokenId);\n        if (o != from) revert NotOwnerNorApproved();\n        if (to == address(0)) revert ZeroAddress();\n        if (msg.sender != o && _tokenApprovals[tokenId] != msg.sender && !_operatorApprovals[o][msg.sender]) {\n            revert NotOwnerNorApproved();\n        }\n        delete _tokenApprovals[tokenId];\n        unchecked {\n            _balances[from] -= 1;\n            _balances[to] += 1;\n        }\n        _tok[tokenId].owner = 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 r) {\n                if (r != IERC721Receiver.onERC721Received.selector) revert UnsafeRecipient();\n            } catch {\n                revert UnsafeRecipient();\n            }\n        }\n    }\n\n    /// Read-only owner for marketplaces (e.g. Element) that let the owner set royalties. No admin powers.\n    function owner() external view returns (address) {\n        return creator;\n    }\n\n    function royaltyInfo(uint256, uint256 salePrice) external view returns (address, uint256) {\n        return (creator, (salePrice * ROYALTY_BPS) / 10000);\n    }\n\n    // ---------------- On-chain pixel art ----------------\n\n    /// Sprite runs on a 24x24 grid (see _sprite for the encoding), painted in colour-code order.\n    /// Sprites 0-11 the animal heads; 12 scarf 13 red envelope 14 gold coin 15 lantern 16 firecracker (= 11 + accessory).\n    bytes internal constant SPR = hex\"0112086444640486408604a640a604d504f50913152d154d116f118f11af15cd15ed1a0b1a2b032e0844444404601c613c615860008020803c805c8000a020a03ca05ca000c020c75cc000e01ce040e05ce0050019004500590009224d2211404d400d6051600d8051800da051a011c04dc011e04de016004a0016204a201a4b1e692287040625c521e71e091e291e49226705082161396121803d8001e255e202225622060225803980070a0c83448308a444a408c444c40ce248e22a232a4301071cc918eb190b05350d51116f118f020524c134c124e50920552003250420582000425442006350630083508304a31ca94ca304c544c508e054e0010211004d00550201200d214d215d20054155410d6051600d8051800db109d309f30a130a330e51126f168d040711af0dd10df10e110e31124f166d05081d413d411d6041601de13de11e004200060221603d600a032a4036402e610d0e04405840046154610481548108a150a108c24cc20ce248e215004900010c08824c8208b308d30cf1150d0933114f0973118f09b319cb020d24c52ce10d0125054d012d21094125455141098151810a132227032508624c62048014804880588004a018ab58a004c014c048c058c008e054e0090055000520592005405940056059600580598005a059a005c059c005f506005a000a2056200a530e71168d040c0c8050800ca14ca109c349c309f30e110e2442240e51166d0504196141611980458006021d804180070225c529e301191022442210424442106244621082448210a244a210c244c210ef110f0d3109530973099309b311cf09f30e110e31124f1a6b020326003a002a230338100244020c201c20402050200c401c40404050400c601c60406050600c801c80408050800ca01ca040a050a00cc01cc040c050c00ce01ce950e00d001d00410051000920552005405940056059600580598005a059a005c059c005e059e00a0056000a2056200e40524012614a611a8b0504196141611980458006021d804180070e14404840146048601480488014a048a014c048c014e048e029c32de1080209c151c1010718cb14ed110f112f114f116f118f020f08c150c104e250e2010255020521552105415541016255620581558109b303181ca910c148c110e04ce00d001502410251000d2051200d4051400d6051600d8051800db109d30df10e110e31124f166d0406158d11af0dd111ef120f1a4b0506192045201940454025c039c0060216404a400a1a082020203c20542008411c413c4150410c61186140614c611083408314a144a1152049201540494001e255e202005e0002205e20010a18ab10cf0cf10d1109330953097309930db10dd1020b1cc02cc140c018e228e33ce21d002d01410021a03da00318188b10a148a10cc050c008e054e0090055000520592005405940056059600580598009a055a009c055c00df1120f1a2b040311cf11ef1a0b050511414941116149612e0106040d4051400d60516009052a432a6326802e813a80010f0c4050400c614c610c82488208b308d30cf10d110d310d51116f118f15ad020a206138611c8334831ca91cc22cc138c220e03ce0032b0c205020084010404c4054400860146048605460088018804480548004a018a044a058a004c014c048c058c008e054e00900550009205520094055400d6051600d80518011a04da011cf0df10e110e31124f166d1a8b040b10804c8010a04ca019ab15cd11ef120f122f164d1a6b050619214121194045401a01420106021d404140010e20e71d09192b0555116f158d15ad19cb19eb1a0b2247266526852aa3021b0c434443086018614061546004801c813c81588004a010a11ca13ca148a158a004c014c01cc948c058c004e118e140e154e10904450403290c6050600880548008a054a008c024c554c00ce050e0012215204920552201400d414d415d400562516211804d8011a04da015c049c015e049e016004a001a2b1e40424022603e6022803e8026a03aa02ac304050940554021e71e091e2905041d413d411d604160060221603d6007012a030d032ea12ec12ee10210188b10af0cd10cf1110f112f114f116f118f11af11cf11ef120f162d164d1e690322186b108148810ca050a008c054c008e054e001035103012351230143514301635163018351830da051a00dc051c00de051e00e00520012204e2012404e40166146611e89041518c23cc214e438e4190b0521152d55210540154d59400561156d5561158d15ad19cb1de91a0b1a2b1e4905071d413d411d60416025c039c02625060221603d60070209405540010f1ca914cd10ef110f112f114f116f0d910db10dd10df1120f122f164d1a6b0206282328431c691c8920a234a203332800340024202c2138201c4024403840404018602060286034603c6044601880448014a144a110c04cc00ce050e00d0051000d2051200d4051400d6051600980558009a055a009c055c009e055e00e0022003e0052000e202a23522012404e4016604a601a8b05041d213d211d404140060221403d40090325e52a032e210e052d412d61298325a52dc101090ca050a00cd108f30d110d310d510d711d89020c086054600881508108a010a04ca054a008c014c048c054c003260841504104600c6050605860048010804c80588004a014a020a748a058a004c018c140c158c004e058e0090055000920552009405540096055600980558009b309d30df10e11122f164d1a6b040a152145210d8345830db10dd111ef120f162d1a4b0507154145411560496029c32de12625060219604560010e14cd0cf10913093309530973099311af11cf09f30a130a330e51166d02090c814c810ca248a20cc14cc119cb19eb1a0b033408624c62088014804880548008a018a020a744a054a008c018c140c154c008e054e0050059000520592005405940056059600580598005a019ab59a005c015c049c059c005e015e025e039e049e059e0060016004a005a0006201a2b5a200a4056400e614e61168d05041541454115604960060219604560080409a151a109c151c10902168d3ec20a031ea93ee046e00c0516a122a12ea13aa146a109074605462546454665468546a546c50a034e414a634e810b014e600c0345e54a034e210a050a220644066406840aa20b0d0a020620162002401a4002600e601a6002801a8006a016a00ac20d010a40090605e4020602260246026606840a040ac012c00ae012e00b030da009c20aa20c080a0012000a2012200a4012400a6012600d010620090851405960518059a051c059e052005a200a094d405d604d805da04dc05de04e005e2056400b09552055405560558055a055c055e0560056200d0352405a405660\";\n    bytes internal constant IDX = hex\"000000c001760228030a03c4044e050805da068a074407ec08a208bc08e0090c09420984\";\n    /// Fixed colours for codes 5+, 7 chars each\n    bytes internal constant COLS = \"#1b1210#ffffff#f39bb0#ff8a8a#e3262f#f7c948#b8860b#a3121c#fff4c2#ff9a1f\";\n    /// Animal palettes: main, secondary, outline, light (28 chars each)\n    bytes internal constant PALS = \"#a9b0bc#6c7380#262a33#eef1f5#8a5a3c#5a3622#22140c#efc2a6#f58a25#2a1406#2a1406#fff4e2#f7f5f2#f5a3bd#3a3440#ffffff#2fb37a#e3262f#0d3a28#bff2d6#6cc04a#2e7d32#163a12#e8f59a#c8743a#3a1f10#2a140a#f6d3ae#f4ecdc#a8763e#3e3226#ffffff#a0623a#6b3a1e#2a160a#f7caa0#ffffff#e3262f#3a2a1a#ffd23f#e39a4a#b8692a#2e1a0c#fff3e3#ffb3c6#f07a9b#5a2236#ffd6e2\";\n    /// Golden Dragon palettes GOLD / JADE / RUBY\n    bytes internal constant SFURS = \"#ffd447#ff6b3d#4a2e00#fff4cf#6fdcaa#f7c948#032a1a#dcfdeb#ff5a6a#f7c948#4a0610#ffe6e6\";\n    bytes internal constant BGS = \"#ffe3c7#cdf2dc#cfe6ff#e6d8ff#fff2b3#efe3cf#ffcdc4#454a78\";\n    /// Trait weights out of 256, rarest last\n    bytes internal constant W_BG = hex\"302c28241e1a120e\";\n    bytes internal constant W_ACC = hex\"5a322823190e\"; // 90 50 40 35 25 16\n\n    struct Look {\n        uint256 animal;\n        uint256 bg;\n        uint256 acc;\n        uint256 rank; // 0 Common .. 3 Epic, 4 Legendary (Golden Dragon), 5 1/1 (Lucky)\n    }\n\n    function _pick(uint256 r, bytes memory w) internal pure returns (uint256 i) {\n        uint256 acc;\n        for (; i < w.length; ++i) {\n            acc += uint8(w[i]);\n            if (r < acc) return i;\n        }\n        return w.length - 1;\n    }\n\n    /// True for the 12 hidden Lucky 1/1s: the n-th minted of each animal, n fixed by the deploy seed.\n    function _lucky(Tok memory t) internal view returns (bool) {\n        return t.animal < 12 && t.ordinal == uint256(keccak256(abi.encodePacked(SEED, t.animal))) % PER_ANIMAL + 1;\n    }\n\n    function _look(uint256 id, Tok memory t) internal view returns (Look memory l) {\n        l.animal = t.animal;\n        if (t.animal == 12) {\n            l.rank = 4;\n            return l;\n        }\n        if (_lucky(t)) {\n            l.rank = 5;\n            l.acc = 4; // lantern\n            return l;\n        }\n        uint256 h = uint256(keccak256(abi.encodePacked(\"PZDC\", id)));\n        l.bg = _pick(h & 255, W_BG);\n        l.acc = _pick((h >> 8) & 255, W_ACC);\n        uint256 score = l.bg / 2 + l.acc;\n        l.rank = score < 3 ? 0 : score < 5 ? 1 : score < 7 ? 2 : 3;\n    }\n\n    function _slice(bytes memory src, uint256 start, uint256 len) internal pure returns (string memory) {\n        bytes memory o = new bytes(len);\n        for (uint256 i; i < len; ++i) o[i] = src[start + i];\n        return string(o);\n    }\n\n    struct Ctx {\n        bytes spr;\n        bytes idx;\n        bytes cols;\n        bytes pal;\n        bytes buf;\n        uint256 w;\n    }\n\n    /// Writes one sprite into x.buf as stroked paths, one <path> per colour group.\n    /// Sprite data: groups of [colour code, run count, runs]; each run is 2 bytes x<<10 | y<<5 | (width-1).\n    function _sprite(Ctx memory x, uint256 s) internal pure {\n        uint256 i = (uint256(uint8(x.idx[2 * s])) << 8) | uint8(x.idx[2 * s + 1]);\n        uint256 b = (uint256(uint8(x.idx[2 * s + 2])) << 8) | uint8(x.idx[2 * s + 3]);\n        while (i < b) {\n            uint256 c = uint8(x.spr[i]);\n            uint256 n = uint8(x.spr[i + 1]);\n            i += 2;\n            x.w = _put(x.buf, x.w, '<path stroke=\"');\n            bytes memory src = c <= 4 ? x.pal : x.cols;\n            uint256 o = c <= 4 ? (c - 1) * 7 : (c - 5) * 7;\n            for (uint256 k; k < 7; ++k) x.buf[x.w + k] = src[o + k];\n            x.w = _put(x.buf, x.w + 7, '\" d=\"');\n            for (; n != 0; --n) {\n                uint256 v = (uint256(uint8(x.spr[i])) << 8) | uint8(x.spr[i + 1]);\n                i += 2;\n                x.w = _put(x.buf, x.w, bytes(string.concat(\"M\", _u(v >> 10), \" \", _u((v >> 5) & 31), \".5h\", _u((v & 31) + 1))));\n            }\n            x.w = _put(x.buf, x.w, '\"/>');\n        }\n    }\n\n    function _put(bytes memory buf, uint256 w, bytes memory x) internal pure returns (uint256) {\n        uint256 n = x.length;\n        assembly {\n            let dst := add(add(buf, 32), w)\n            let src := add(x, 32)\n            for { let i := 0 } lt(i, n) { i := add(i, 32) } {\n                mstore(add(dst, i), mload(add(src, i)))\n            }\n        }\n        return w + n;\n    }\n\n    uint256 internal constant BUF = 7000;\n\n    /// Paths for sprites `s1` then `s2` (0xff = none) in palette `pal`\n    function _art(bytes memory pal, uint256 s1, uint256 s2) internal pure returns (string memory) {\n        Ctx memory x = Ctx(SPR, IDX, COLS, pal, new bytes(BUF), 0);\n        _sprite(x, s1);\n        if (s2 != 0xff) _sprite(x, s2);\n        bytes memory buf = x.buf;\n        uint256 w = x.w;\n        assembly {\n            mstore(buf, w)\n        }\n        return string(buf);\n    }\n\n    function _pal(uint256 animal) internal pure returns (bytes memory) {\n        return bytes(_slice(PALS, animal * 28, 28));\n    }\n\n    function _pad4(uint256 v) internal pure returns (string memory) {\n        return string.concat(v < 10 ? \"000\" : v < 100 ? \"00\" : v < 1000 ? \"0\" : \"\", _u(v));\n    }\n\n    function _txt(string memory x, string memory y, string memory size, string memory fill, string memory extra, string memory body) internal pure returns (string memory) {\n        return string.concat('<text x=\"', x, '\" y=\"', y, '\" font-size=\"', size, '\" fill=\"', fill, '\"', extra, \">\", body, \"</text>\");\n    }\n\n    function _g(string memory tf, string memory body) internal pure returns (string memory) {\n        return string.concat('<g transform=\"', tf, '\" shape-rendering=\"crispEdges\" stroke-width=\"1\" fill=\"none\">', body, \"</g>\");\n    }\n\n    function _plain(uint256 id, Look memory l, uint8 tier) internal pure returns (string memory s) {\n        string memory ink = l.bg == 7 ? \"#ffffff\" : \"#1b1210\";\n        s = string.concat(\n            '<rect width=\"480\" height=\"480\" fill=\"', _slice(BGS, l.bg * 7, 7), '\"/>',\n            _g(\"translate(24 36) scale(18)\", _art(_pal(l.animal), l.animal, l.acc == 0 ? 0xff : 11 + l.acc)),\n            _txt(\"20\", \"30\", \"16\", ink, ' opacity=\".7\"', string.concat(\"PIXEL ZODIAC #\", _u(id))),\n            _txt(\"460\", \"32\", \"22\", ink, ' text-anchor=\"end\" opacity=\".7\"', _cn(l.animal))\n        );\n        if (tier == 1) {\n            s = string.concat(s, '<rect x=\"5\" y=\"5\" width=\"470\" height=\"470\" rx=\"14\" fill=\"none\" stroke=\"#2f6fe0\" stroke-width=\"10\"/>',\n                '<rect x=\"190\" y=\"446\" width=\"100\" height=\"26\" rx=\"13\" fill=\"#2f6fe0\"/>', _txt(\"240\", \"464\", \"14\", \"#ffffff\", ' text-anchor=\"middle\"', \"PUZZLE\"));\n        }\n    }\n\n    function _luckyCard(uint256 id, Look memory l) internal pure returns (string memory) {\n        string memory lan = _art(bytes(\"\"), 15, 0xff);\n        return string.concat(\n            '<defs><radialGradient id=\"g\" cx=\".5\" cy=\".45\" r=\".75\"><stop offset=\"0\" stop-color=\"#fff6c2\"/><stop offset=\".6\" stop-color=\"#ffd447\"/><stop offset=\"1\" stop-color=\"#d99a0b\"/></radialGradient></defs>',\n            '<rect width=\"480\" height=\"480\" fill=\"url(#g)\"/><path d=\"M44 0v40M436 0v40\" stroke=\"#a3121c\" stroke-width=\"3\"/>',\n            _g(\"translate(16 -64) scale(8)\", lan), _g(\"translate(408 -64) scale(8)\", lan),\n            '<circle cx=\"240\" cy=\"262\" r=\"176\" fill=\"#c8102e\" stroke=\"#fff4c2\" stroke-width=\"4\"/>',\n            _g(\"translate(72 92) scale(14)\", _art(_pal(l.animal), l.animal, 0xff)),\n            '<rect x=\"7\" y=\"7\" width=\"466\" height=\"466\" rx=\"16\" fill=\"none\" stroke=\"#c8102e\" stroke-width=\"14\"/><rect x=\"18\" y=\"18\" width=\"444\" height=\"444\" rx=\"10\" fill=\"none\" stroke=\"#fff4c2\" stroke-width=\"2\"/>',\n            _txt(\"240\", \"56\", \"26\", \"#a3121c\", ' text-anchor=\"middle\" letter-spacing=\"3\"', string.concat(unicode\"LUCKY \", _cn(l.animal), \" 1/1\")),\n            _txt(\"240\", \"452\", \"15\", \"#a3121c\", ' text-anchor=\"middle\"', string.concat(\"PIXEL ZODIAC #\", _u(id)))\n        );\n    }\n\n    function _golden(uint256 id, uint256 serial) internal pure returns (string memory) {\n        uint256 v = (serial - 1) % 3;\n        string memory head = string.concat(\n            '<defs><radialGradient id=\"g\" cx=\".5\" cy=\".45\" r=\".7\"><stop offset=\"0\" stop-color=\"#9e1424\"/><stop offset=\"1\" stop-color=\"#2a0307\"/></radialGradient>',\n            '<linearGradient id=\"f\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\" spreadMethod=\"reflect\"><stop offset=\"0\" stop-color=\"#fff6c2\"/><stop offset=\".25\" stop-color=\"#f7c948\"/><stop offset=\".45\" stop-color=\"#ff9ad5\"/><stop offset=\".6\" stop-color=\"#8cf0ff\"/><stop offset=\".8\" stop-color=\"#f7c948\"/><stop offset=\"1\" stop-color=\"#b8860b\"/>',\n            '<animate attributeName=\"x1\" values=\"0;1;0\" dur=\"5s\" repeatCount=\"indefinite\"/><animate attributeName=\"x2\" values=\"1;2;1\" dur=\"5s\" repeatCount=\"indefinite\"/></linearGradient>',\n            '<linearGradient id=\"s\" x1=\"0\" x2=\"1\"><stop offset=\"0\" stop-color=\"#fff\" stop-opacity=\"0\"/><stop offset=\".5\" stop-color=\"#fff\" stop-opacity=\".45\"/><stop offset=\"1\" stop-color=\"#fff\" stop-opacity=\"0\"/></linearGradient>',\n            '<clipPath id=\"c\"><rect width=\"480\" height=\"480\" rx=\"22\"/></clipPath></defs>'\n        );\n        string memory body = string.concat(\n            '<g clip-path=\"url(#c)\"><rect width=\"480\" height=\"480\" fill=\"url(#g)\"/>',\n            '<g fill=\"#fff6c2\"><circle cx=\"70\" cy=\"110\" r=\"2\"/><circle cx=\"420\" cy=\"90\" r=\"2.5\"/><circle cx=\"400\" cy=\"300\" r=\"2\"/><circle cx=\"60\" cy=\"330\" r=\"2.5\"/><circle cx=\"240\" cy=\"70\" r=\"1.5\"/>',\n            '<animate attributeName=\"opacity\" values=\".3;1;.3\" dur=\"2.4s\" repeatCount=\"indefinite\"/></g>',\n            _g(\"translate(60 72) scale(15)\", _art(bytes(_slice(SFURS, v * 28, 28)), 4, 0xff)),\n            '<rect x=\"-160\" y=\"0\" width=\"120\" height=\"480\" fill=\"url(#s)\" transform=\"skewX(-18)\"><animateTransform attributeName=\"transform\" type=\"translate\" values=\"-100 0;720 0\" dur=\"3.2s\" repeatCount=\"indefinite\" additive=\"sum\"/></rect>',\n            '<rect x=\"8\" y=\"8\" width=\"464\" height=\"464\" rx=\"18\" fill=\"none\" stroke=\"url(#f)\" stroke-width=\"16\"/></g>'\n        );\n        string memory names = string.concat(\n            _txt(\"240\", \"52\", \"22\", \"url(#f)\", ' text-anchor=\"middle\" letter-spacing=\"3\"', unicode\"GOLDEN DRAGON 金龙\"),\n            _txt(\"240\", \"448\", \"17\", \"#fff6c2\", ' text-anchor=\"middle\" letter-spacing=\"1\"', string.concat(_variant(v), unicode\" · No. \", _pad4(serial))),\n            _txt(\"40\", \"420\", \"12\", \"#ffc2b0\", ' opacity=\".8\"', string.concat(\"#\", _u(id)))\n        );\n        return string.concat(head, body, names);\n    }\n\n    function _variant(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"GOLD\";\n        if (v == 1) return \"JADE\";\n        return \"RUBY\";\n    }\n\n    function _svg(uint256 id, Tok memory t, Look memory l) internal pure returns (string memory) {\n        return string.concat(\n            '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 480 480\" font-family=\"monospace\" font-weight=\"bold\">',\n            l.rank == 4 ? _golden(id, id - ZODIAC_SUPPLY) : l.rank == 5 ? _luckyCard(id, l) : _plain(id, l, t.tier),\n            \"</svg>\"\n        );\n    }\n\n    // ---------------- Metadata ----------------\n\n    function _pickStr(string memory list, uint256 i) internal pure returns (string memory) {\n        // `list` is \"|\"-separated\n        bytes memory b = bytes(list);\n        uint256 s;\n        uint256 n;\n        for (uint256 k; k <= b.length; ++k) {\n            if (k == b.length || b[k] == \"|\") {\n                if (n == i) return _slice(b, s, k - s);\n                ++n;\n                s = k + 1;\n            }\n        }\n        return \"\";\n    }\n\n    function _animalName(uint256 a) internal pure returns (string memory) {\n        return _pickStr(\"Rat|Ox|Tiger|Rabbit|Dragon|Snake|Horse|Goat|Monkey|Rooster|Dog|Pig|Golden Dragon\", a);\n    }\n\n    function _cn(uint256 a) internal pure returns (string memory) {\n        return _pickStr(unicode\"鼠|牛|虎|兔|龙|蛇|马|羊|猴|鸡|狗|猪|金龙\", a);\n    }\n\n    function _attr(string memory k, string memory v) internal pure returns (string memory) {\n        return string.concat('{\"trait_type\":\"', k, '\",\"value\":\"', v, '\"},');\n    }\n\n    function _attrs(Look memory l, Tok memory t, uint256 id) internal pure returns (string memory) {\n        string memory a = string.concat(\n            _attr(\"Zodiac\", string.concat(_animalName(l.animal), \" \", _cn(l.animal))),\n            _attr(\"Background\", l.rank == 4 ? \"Holo Red\" : l.rank == 5 ? \"Lucky Gold\" : _pickStr(\"Peach|Mint|Sky|Lilac|Lemon|Sand|Lucky Red|Night\", l.bg)),\n            _attr(\"Accessory\", l.rank == 4 ? \"None\" : l.rank == 5 ? \"Red Lantern\" : _pickStr(\"None|Scarf|Red Envelope|Gold Coin|Lantern|Firecracker\", l.acc)),\n            _attr(\"Rarity\", _pickStr(\"Common|Uncommon|Rare|Epic|Legendary|1/1\", l.rank))\n        );\n        string memory serial = t.tier == 2\n            ? string.concat(',{\"display_type\":\"number\",\"trait_type\":\"Golden Serial\",\"value\":', _u(id - ZODIAC_SUPPLY), \"}\")\n            : \"\";\n        return string.concat('\"attributes\":[', a, '{\"trait_type\":\"Edition\",\"value\":\"', _pickStr(\"Free Mint|Puzzle Mint|Golden Dragon\", t.tier), '\"}', serial, \"],\");\n    }\n\n    function tokenURI(uint256 tokenId) external view returns (string memory) {\n        ownerOf(tokenId);\n        Tok memory t = _tok[tokenId];\n        Look memory l = _look(tokenId, t);\n        string memory nm = l.rank == 4\n            ? string.concat(\"Golden Dragon No. \", _u(tokenId - ZODIAC_SUPPLY), \" (\", _variant((tokenId - ZODIAC_SUPPLY - 1) % 3), \")\")\n            : string.concat(l.rank == 5 ? \"Lucky \" : \"\", _animalName(l.animal), \" #\", _u(tokenId));\n        string memory json = string.concat(\n            '{\"name\":\"', nm, '\",',\n            unicode'\"description\":\"PIXEL ZODIAC 像素十二生肖: 2,400 pixel zodiac animals (200 of each of the 12), drawn fully on-chain on BNB Chain for .ai Agent ID holders. Free and puzzle mints; 12 hidden Lucky 1/1s; burn one of each animal to craft a numbered Golden Dragon 金龙 (max 100). No admin. A collectible, not an investment.\",',\n            _attrs(l, t, tokenId),\n            '\"image\":\"data:image/svg+xml;base64,', _b64(bytes(_svg(tokenId, t, l))), '\"}'\n        );\n        return string.concat(\"data:application/json;base64,\", _b64(bytes(json)));\n    }\n\n    function _u(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\";\n        uint256 t = v;\n        uint256 len;\n        while (t != 0) {\n            len++;\n            t /= 10;\n        }\n        bytes memory b = new bytes(len);\n        while (v != 0) {\n            len--;\n            b[len] = bytes1(uint8(48 + (v % 10)));\n            v /= 10;\n        }\n        return string(b);\n    }\n\n    /// Base64 encoder (adapted from OpenZeppelin Contracts Base64, MIT)\n    function _b64(bytes memory data) internal pure returns (string memory result) {\n        if (data.length == 0) return \"\";\n        string memory table = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n        result = new string(4 * ((data.length + 2) / 3));\n        assembly {\n            let tablePtr := add(table, 1)\n            let resultPtr := add(result, 32)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n            for {} lt(dataPtr, endPtr) {} {\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1)\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1)\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1)\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1)\n            }\n            mstore(afterPtr, afterCache)\n            switch mod(mload(data), 3)\n            case 1 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n                mstore8(sub(resultPtr, 2), 0x3d)\n            }\n            case 2 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n            }\n        }\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"_creator","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"AlreadyClaimed","type":"error","inputs":[]},{"name":"BadNonce","type":"error","inputs":[]},{"name":"GoldenSoldOut","type":"error","inputs":[]},{"name":"InvalidToken","type":"error","inputs":[]},{"name":"MintClosed","type":"error","inputs":[]},{"name":"NoFreeLeft","type":"error","inputs":[]},{"name":"NoPuzzleLeft","type":"error","inputs":[]},{"name":"NotAgent","type":"error","inputs":[]},{"name":"NotOwner","type":"error","inputs":[]},{"name":"NotOwnerNorApproved","type":"error","inputs":[]},{"name":"TransferFailed","type":"error","inputs":[]},{"name":"UnsafeRecipient","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"WrongSet","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":"Crafted","type":"event","inputs":[{"name":"crafter","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"serial","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":"AGENT_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentId"}],"stateMutability":"view"},{"name":"CRAFT_FEE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_CAP","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_PER_HOLDER","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"GOLDEN_CAP","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":"PER_ANIMAL","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PIXEL_PANDA","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"PIXEL_PONY","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"PUZZLE_BITS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PUZZLE_CAP","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"ROYALTY_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"name":"ZODIAC_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"animalLeft","type":"function","inputs":[{"name":"a","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"animalOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"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":"burned","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"checkNonce","type":"function","inputs":[{"name":"minter","type":"address","internalType":"address"},{"name":"nonce","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"craft","type":"function","inputs":[{"name":"ids","type":"uint256[12]","internalType":"uint256[12]"}],"outputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"craftSet","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"ids","type":"uint256[12]","internalType":"uint256[12]"}],"stateMutability":"view"},{"name":"creator","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"freeAllowance","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"freeLeft","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeMint","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"freeMinted","type":"function","inputs":[],"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":"goldenLeft","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"goldenMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"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":"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":"mintStart","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"o","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"puzzleClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"puzzleLeft","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"puzzleMint","type":"function","inputs":[{"name":"nonce","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"puzzleMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"remaining","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"royaltyInfo","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"salePrice","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"id","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":"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":"zodiacMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"matchId":"57385702","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-10-28T12:32:32Z","match":"exact_match","chainId":"56","address":"0x1AE3f37769F465606735Eb52893e1AfD80EE1A52"}