{"sources":{"Horangi.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/// HORANGI (HRNG) - 5,000 fully on-chain pixel Korean minhwa tigers.\n/// Rules are fixed in code and cannot be changed by anyone:\n/// - Total supply 5,000. Mint is open for 7 days after deploy, then closes forever\n/// - Free: the first card per wallet, gas only, for wallets holding a Binance / SPACE ID .ai Agent ID (Hanji frame)\n/// - Paid: open to every wallet, 0.00143 BNB each (about 1 USD at deploy), max 9 paid per wallet (cards 2-10), Obangsaek frame\n/// - 100% of each payment goes to the creator in the same transaction; overpayment is refunded in the same transaction\n/// - No admin, no pool, no withdraw, no pause, no setters. owner() only reports the creator for marketplace collection claims\n/// - Art and metadata are generated on-chain. 1% secondary royalty (EIP-2981)\n/// - A collectible, not an investment. No airdrop or reward is promised\ncontract Horangi {\n    string public constant name = \"HORANGI\";\n    string public constant symbol = \"HRNG\";\n\n    uint256 public constant MAX_SUPPLY = 5000;\n    uint256 public constant MAX_PAID_PER_WALLET = 9;\n    uint256 public constant PRICE = 0.00143 ether; // every paid card (about 1 USD at deploy)\n    uint256 public constant MINT_DURATION = 7 days;\n    uint96 public constant ROYALTY_BPS = 100; // 1%\n\n    IAgentId public constant AGENT_ID = IAgentId(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n\n    address public immutable creator;\n    uint256 public immutable mintStart;\n    uint256 public immutable mintEnd;\n\n    uint256 public totalSupply;\n    /// minted per type: 0 Free, 1 Obangsaek (paid)\n    uint256[2] private _minted;\n\n    mapping(address => bool) public freeClaimed;\n    mapping(address => uint256) public paidMinted;\n\n    /// low 160 bits owner; bits 160-162 type; bits 168-183 serial within a special type\n    mapping(uint256 => uint256) 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\n    error NotAgent();\n    error MintClosed();\n    error SoldOut();\n    error PaidLimit();\n    error Underpaid();\n    error NothingToMint();\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    }\n\n    /// Collection owner for marketplaces (\"claim collection\"). Fixed; there are no owner powers.\n    function owner() external view returns (address) {\n        return creator;\n    }\n\n    // ---------------- Mint ----------------\n\n    /// Price of a wallet's n-th paid card (n starts at 1)\n    function priceOf(uint256) public pure returns (uint256) {\n        return PRICE;\n    }\n\n    /// Cost in wei for a wallet that already bought `already` paid cards to buy `qty` more\n    function costFrom(uint256, uint256 qty) public pure returns (uint256) {\n        return qty * PRICE;\n    }\n\n    /// Preview for a mint page: whether `minter` gets the free card now, and what `paidQty` paid cards cost\n    function quote(address minter, uint256 paidQty) external view returns (bool freeCard, uint256 cost) {\n        freeCard = !freeClaimed[minter] && AGENT_ID.balanceOf(minter) > 0;\n        cost = costFrom(paidMinted[minter], paidQty);\n    }\n\n    /// One call: mints the free tiger automatically on an Agent ID wallet's first mint, plus `paidQty` paid tigers. msg.value must be at least the cost; any extra is refunded in the same transaction.\n    function mint(uint256 paidQty) external payable {\n        if (block.timestamp < mintStart || block.timestamp >= mintEnd) revert MintClosed();\n        bool free = !freeClaimed[msg.sender] && AGENT_ID.balanceOf(msg.sender) > 0;\n        if (paidQty == 0 && !free) {\n            if (freeClaimed[msg.sender]) revert NothingToMint();\n            revert NotAgent();\n        }\n        uint256 a = paidMinted[msg.sender];\n        uint256 b = a + paidQty;\n        if (b > MAX_PAID_PER_WALLET) revert PaidLimit();\n        uint256 id = totalSupply;\n        uint256 base = (free ? 1 : 0) + paidQty;\n        if (id + base > MAX_SUPPLY) revert SoldOut();\n        uint256 price = costFrom(a, paidQty);\n        if (msg.value < price) revert Underpaid();\n\n        if (free) freeClaimed[msg.sender] = true;\n        paidMinted[msg.sender] = b;\n        uint256 owned = uint256(uint160(msg.sender));\n        if (free) id = _mintType(owned, id, 0, 1);\n        id = _mintType(owned, id, 1, paidQty);\n        _balances[msg.sender] += id - totalSupply;\n        totalSupply = id;\n\n        if (price > 0) {\n            (bool ok, ) = payable(creator).call{value: price}(\"\");\n            if (!ok) revert TransferFailed();\n        }\n        if (msg.value > price) {\n            (bool ok2, ) = payable(msg.sender).call{value: msg.value - price}(\"\");\n            if (!ok2) revert TransferFailed();\n        }\n    }\n\n    function _mintType(uint256 owned, uint256 id, uint256 t, uint256 n) private returns (uint256) {\n        if (n == 0) return id;\n        uint256 serial = _minted[t];\n        for (uint256 k; k < n; ++k) {\n            ++id;\n            ++serial;\n            _tok[id] = owned | (t << 160);\n            emit Transfer(address(0), address(uint160(owned)), id);\n        }\n        _minted[t] = serial;\n        return id;\n    }\n\n    // ---------------- Views for the mint page ----------------\n\n    /// freeClaimed, paid so far, Agent ID holder, paid cards left, price of the next paid card\n    function walletInfo(address a)\n        external\n        view\n        returns (bool freeUsed, uint256 paidCount, bool eligible, uint256 paidLeft, uint256 nextPrice)\n    {\n        freeUsed = freeClaimed[a];\n        paidCount = paidMinted[a];\n        eligible = AGENT_ID.balanceOf(a) > 0;\n        paidLeft = MAX_PAID_PER_WALLET - paidCount;\n        nextPrice = paidLeft == 0 ? 0 : priceOf(paidCount + 1);\n    }\n\n    /// Minted per type: Free, Obangsaek (paid)\n    function mintedByType() external view returns (uint256[2] memory) {\n        return _minted;\n    }\n\n    function remaining() external view returns (uint256) {\n        return MAX_SUPPLY - totalSupply;\n    }\n\n    function mintOpen() public view returns (bool) {\n        return block.timestamp >= mintStart && block.timestamp < mintEnd && totalSupply < MAX_SUPPLY;\n    }\n\n    function mintInfo() external view returns (uint256 supply, uint256 maxSupply, uint256 start, uint256 end, bool open) {\n        return (totalSupply, MAX_SUPPLY, mintStart, mintEnd, mintOpen());\n    }\n\n    /// 0 Free, 1 Obangsaek (paid)\n    function typeOf(uint256 tokenId) public view returns (uint8) {\n        ownerOf(tokenId);\n        return uint8((_tok[tokenId] >> 160) & 7);\n    }\n\n    function tokensOfOwner(address o) external view returns (uint256[] memory ids) {\n        uint256 n = _balances[o];\n        ids = new uint256[](n);\n        uint256 j;\n        uint256 ts = totalSupply;\n        for (uint256 i = 1; i <= ts && j < n; ++i) {\n            if (address(uint160(_tok[i])) == o) ids[j++] = i;\n        }\n    }\n\n    // ---------------- ERC-721 ----------------\n\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 o) external view returns (uint256) {\n        if (o == address(0)) revert ZeroAddress();\n        return _balances[o];\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address o) {\n        o = address(uint160(_tok[tokenId]));\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 o, address operator) external view returns (bool) {\n        return _operatorApprovals[o][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] = (_tok[tokenId] & ~uint256(type(uint160).max)) | uint256(uint160(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    function royaltyInfo(uint256, uint256 salePrice) external view returns (address, uint256) {\n        return (creator, (salePrice * ROYALTY_BPS) / 10000);\n    }\n\n    // ---------------- On-chain art ----------------\n\n    // sprite runs: x, y, length, colour (1-4 skin outline/main/belly/dark, 5+ shared COLS)\n    bytes internal constant SPR = hex\"0403030111030301030401010704010110040101140401010205010108050801150501010206010115060101020701011507010103080101140801010309010114090101030a0101140a0101020b0101150b0101020c0101150c0101020d0101150d0101020e0101150e0101020f0101150f010103100101141001010311010114110101041201011312010105130101121301010614020110140201081508010404030211040302030501020705010210050102140501020306010207060a021406010203070202060704020b0702020e07040213070202040806020e08060204090302090902020d09020211090302040a07020d0a0702060b0102090b0602110b0102030c0102060c0102090c0602110c0102140c0102030d1202070e02020f0e0202030f0502100f050206100102111001020512030210120302061303020f130302081408020a0701030d0701030a080403070902030b0902030f0902030b0a0203030b0303120b0303040c0203120c0203030e0403110e040304100203121002030411030311110303040503041105030404060304110603040507010412070104090e0604080f03040d0f0304071004040d100404071102040a1101040d1101040f110204081202040b1202040e12020409130604080b0105100b0105070b01060f0b0106070c02060f0c02060b1102060a1201060d1201060b0f020c0b10020c091101130e11011309000601080101010f010101080201010f020101040305010f03050103040101140401010405100109010606090206060903060604041006110001011400010110010101150101010f0201011602010110030101150301011104010114040101120502011200020c1101010c1401010c1002010c1502010c1103010c1403010c1201020d1102010d1402010d1203020d1204020e120202110a0001010d000101090101010e010101090201010e0201010a0301010d0301010b0402010b0002060a0104060a0204060b0302090a030109100301090703010d0903010d0b03010d0d03010d0f03010d1103010d0c03010f080301110e030111060b0c06070c03060e0c0306060a010b110a010b070b02030f0b0203070c02060f0c0206070b02110f0b0211070c02110f0c02111313020112140101151401011115010116150101121601011516010112170101151701011314021112150111151501111316021113170211131502120c15020f0b16020f0b1402110a15021107150105091501050b1501050d1501050f1501051115010507140111091401110b1401110d1401110f1401111114011106150111081501110a1501110c1501110e150111101501111215011106140112081401120a1401120c1401120e140112101401120515011207150112091501120b1501120d1501120f15011211150112\";\n    bytes internal constant IDX = hex\"00000083009100a900b600c100c400c600ca00ce00dd00e100e70101\";\n    bytes internal constant COLS = \"#ffffff#15141c#ff9fb0#e0435a#ffd23f#e8a417#fff2a8#ff7aa0#ffc2dc#2f9e5a#2b5fd9#8e5bff#e8322e#a51f2a#7a4a2a#f4f6fa#c9d1db#7fe3ff#ff8a3d#1d1f2e\";\n    bytes internal constant SKINS = \"#3a1606#f08a24#1c1410#fff4e2#4a1606#ff6a2a#5a1a08#ffe3cc#2a2a36#f4f4f0#2b2b3a#ffffff#07070c#5b5a6a#15141c#d8d6e2#5a4020#eedcb8#8a5a2a#fffaf0#0f3a34#8fd1bc#2e7a68#e8fff6#4a0f30#e88ab8#6a1a48#fff0f6#0a1a44#4f6fd6#101a3a#dfe7ff#050510#2a2a44#f2c84a#8a8ab0#3a0a04#d23a1a#ffcf3a#ffd8b0\";\n    bytes internal constant BGS = \"#f6ecd6#cdeee0#ffd6b8#f6d2e6#cfe2ff#cfe8c8#ffe0d0#e2dcff\";\n    bytes internal constant W_SKIN = hex\"281a1210100e0c0c0806\";\n    bytes internal constant W_HAT = hex\"501e1c1a16\";\n    bytes internal constant W_EYES = hex\"6e1e161a10\";\n    bytes internal constant W_NECK = hex\"5a1c1a161a\";\n    bytes internal constant HAT_SPR = hex\"0001020304\";\n    bytes internal constant EYE_SPR = hex\"0005060708\";\n    bytes internal constant NECK_SPR = hex\"00090a0b0c\";\n\n    struct Look {\n        uint256 skin;\n        uint256 hat;\n        uint256 eyes;\n        uint256 neck;\n        uint256 bg;\n    }\n\n    function _pick(uint256 r, bytes memory w) internal pure returns (uint256 i) {\n        uint256 total;\n        for (uint256 k; k < w.length; ++k) total += uint8(w[k]);\n        r %= total;\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    /// Traits come only from the token id\n    function _look(uint256 id, uint256 t) internal pure returns (Look memory l) {\n        uint256 h = uint256(keccak256(abi.encodePacked(\"HRNG\", id)));\n        l.skin = _pick(h & 0xffff, W_SKIN);\n        l.hat = _pick((h >> 16) & 0xffff, W_HAT);\n        l.eyes = _pick((h >> 32) & 0xffff, W_EYES);\n        l.neck = _pick((h >> 48) & 0xffff, W_NECK);\n        l.bg = (h >> 64) % 8;\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) } { mstore(add(dst, i), mload(add(src, i))) }\n        }\n        return w + n;\n    }\n\n    function _num(bytes memory b, uint256 p, uint256 v) private pure returns (uint256) {\n        if (v >= 10) b[p++] = bytes1(uint8(48 + v / 10));\n        b[p++] = bytes1(uint8(48 + v % 10));\n        return p;\n    }\n\n    /// Writes one sprite as stroked 1-pixel runs, one <path> per colour (runs are sorted by colour)\n    function _sprite(bytes memory buf, uint256 w, bytes memory spr, bytes memory idx, bytes memory pal, uint256 s) private pure returns (uint256) {\n        uint256 a = (uint256(uint8(idx[2 * s])) << 8) | uint8(idx[2 * s + 1]);\n        uint256 e = (uint256(uint8(idx[2 * s + 2])) << 8) | uint8(idx[2 * s + 3]);\n        uint256 prev;\n        for (uint256 i = a; i < e; ++i) {\n            uint256 q = 4 * i;\n            uint256 c = uint8(spr[q + 3]);\n            if (c != prev) {\n                if (prev != 0) w = _put(buf, w, '\"/>');\n                w = _put(buf, w, '<path stroke=\"');\n                for (uint256 k; k < 7; ++k) buf[w + k] = pal[(c - 1) * 7 + k];\n                w = _put(buf, w + 7, '\" d=\"');\n                prev = c;\n            }\n            buf[w++] = \"M\";\n            w = _num(buf, w, uint8(spr[q]));\n            buf[w++] = \" \";\n            w = _num(buf, w, uint8(spr[q + 1]));\n            w = _put(buf, w, \".5h\");\n            w = _num(buf, w, uint8(spr[q + 2]));\n        }\n        if (prev != 0) w = _put(buf, w, '\"/>');\n        return w;\n    }\n\n    function _slice(bytes memory src, uint256 start, uint256 len) internal pure returns (bytes memory o) {\n        o = new bytes(len);\n        for (uint256 i; i < len; ++i) o[i] = src[start + i];\n    }\n\n    function _tiger(Look memory l) internal pure returns (bytes memory buf) {\n        bytes memory spr = SPR;\n        bytes memory idx = IDX;\n        bytes memory pal = bytes.concat(_slice(SKINS, l.skin * 28, 28), COLS);\n        buf = new bytes(9000);\n        uint256 w = _put(buf, 0, '<g transform=\"translate(72 92) scale(14)\" shape-rendering=\"crispEdges\" fill=\"none\">');\n        w = _sprite(buf, w, spr, idx, pal, 0);\n        if (l.neck != 0) w = _sprite(buf, w, spr, idx, pal, uint8(NECK_SPR[l.neck]));\n        if (l.eyes != 0) w = _sprite(buf, w, spr, idx, pal, uint8(EYE_SPR[l.eyes]));\n        if (l.hat != 0) w = _sprite(buf, w, spr, idx, pal, uint8(HAT_SPR[l.hat]));\n        w = _put(buf, w, \"</g>\");\n        assembly { mstore(buf, w) }\n    }\n\n    function _svg(uint256 id, uint256 t) internal pure returns (string memory) {\n        Look memory l = _look(id, t);\n        string memory art = string(_tiger(l));\n        string memory bg = string(_slice(BGS, l.bg * 7, 7));\n        string memory label = string.concat('<text x=\"36\" y=\"48\" font-size=\"17\" fill=\"#2a1a10\" opacity=\".8\">HORANGI #', _u(id), \"</text>\");\n        string memory body;\n        if (t == 0) {\n            body = string.concat('<rect width=\"480\" height=\"480\" fill=\"', bg, '\"/>', art,\n                '<rect x=\"8\" y=\"8\" width=\"464\" height=\"464\" rx=\"22\" fill=\"none\" stroke=\"#fffaf0\" stroke-opacity=\".85\" stroke-width=\"5\"/>', label);\n        } else {\n            body = string.concat('<rect width=\"480\" height=\"480\" fill=\"', bg, '\"/>', art,\n                '<rect x=\"9\" y=\"9\" width=\"462\" height=\"462\" rx=\"22\" fill=\"none\" stroke=\"#e8322e\" stroke-width=\"18\"/>',\n                '<path d=\"M30 9h84M366 9h84\" stroke=\"#2b5fd9\" stroke-width=\"18\"/><path d=\"M9 120v80M471 120v80\" stroke=\"#ffd23f\" stroke-width=\"18\"/><path d=\"M9 300v80M471 300v80\" stroke=\"#2f9e5a\" stroke-width=\"18\"/><path d=\"M180 471h120\" stroke=\"#1d1f2e\" stroke-width=\"18\"/>',\n                '<rect x=\"300\" y=\"28\" width=\"152\" height=\"28\" rx=\"14\" fill=\"#e8322e\"/><text x=\"376\" y=\"47\" font-size=\"14\" fill=\"#fff\" text-anchor=\"middle\" letter-spacing=\"2\">OBANGSAEK</text>', label);\n        }\n        return string.concat('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 480 480\" font-family=\"monospace\" font-weight=\"bold\">', body, \"</svg>\");\n    }\n\n    /// Raw SVG for any traits id and type (0-1), for previews and the mint page\n    function previewSVG(uint256 traitsId, uint256 t) external pure returns (string memory) {\n        return _svg(traitsId, t % 2);\n    }\n\n    // ---------------- Metadata ----------------\n\n    function _skinName(uint256 i) internal pure returns (string memory) {\n        if (i == 0) return \"Minhwa\";\n        if (i == 1) return \"Persimmon\";\n        if (i == 2) return \"Baekho\";\n        if (i == 3) return \"Ink Wash\";\n        if (i == 4) return \"Hanji\";\n        if (i == 5) return \"Celadon\";\n        if (i == 6) return \"Plum\";\n        if (i == 7) return \"Indigo\";\n        if (i == 8) return \"Night\";\n        return \"Ember\";\n    }\n\n    function _hatName(uint256 i) internal pure returns (string memory) {\n        if (i == 0) return \"None\";\n        if (i == 1) return \"Gat\";\n        if (i == 2) return \"Mugunghwa\";\n        if (i == 3) return \"Topknot\";\n        return \"Flower Crown\";\n    }\n\n    function _eyeName(uint256 i) internal pure returns (string memory) {\n        if (i == 0) return \"Normal\";\n        if (i == 1) return \"Shades\";\n        if (i == 2) return \"Sparkle\";\n        if (i == 3) return \"Sleepy\";\n        return \"Hearts\";\n    }\n\n    function _neckName(uint256 i) internal pure returns (string memory) {\n        if (i == 0) return \"None\";\n        if (i == 1) return \"Norigae\";\n        if (i == 2) return \"Taegeuk\";\n        if (i == 3) return \"Pearls\";\n        return \"Red Scarf\";\n    }\n\n    function _bgName(uint256 i) internal pure returns (string memory) {\n        if (i == 0) return \"Hanji\";\n        if (i == 1) return \"Celadon\";\n        if (i == 2) return \"Persimmon\";\n        if (i == 3) return \"Plum\";\n        if (i == 4) return \"Sky\";\n        if (i == 5) return \"Pine\";\n        if (i == 6) return \"Peach\";\n        return \"Moon\";\n    }\n\n\n    function _typeName(uint256 t) internal pure returns (string memory) {\n        if (t == 0) return \"Free\";\n        return \"Obangsaek\";\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 tokenURI(uint256 tokenId) external view returns (string memory) {\n        ownerOf(tokenId);\n        uint256 t = (_tok[tokenId] >> 160) & 7;\n        Look memory l = _look(tokenId, t);\n        string memory attrs = string.concat(\n            _attr(\"Type\", _typeName(t)),\n            _attr(\"Fur\", _skinName(l.skin)),\n            _attr(\"Head\", _hatName(l.hat)),\n            _attr(\"Eyes\", _eyeName(l.eyes)),\n            _attr(\"Charm\", _neckName(l.neck)),\n            _attr(\"Background\", _bgName(l.bg))\n        );\n        bytes memory json = abi.encodePacked(\n            '{\"name\":\"HORANGI #', _u(tokenId),\n            '\",\"description\":\"HORANGI: 5,000 fully on-chain pixel Korean minhwa tigers on BNB Chain. First card free for .ai Agent ID holders; paid tigers (cards 2-10) wear the Obangsaek frame. No admin. A collectible, not an investment.\",',\n            '\"attributes\":[', attrs, '{\"trait_type\":\"Collection\",\"value\":\"HORANGI\"}],',\n            '\"image\":\"data:image/svg+xml;base64,', _b64(bytes(_svg(tokenId, t))), '\"}'\n        );\n        return string.concat(\"data:application/json;base64,\", _b64(json));\n    }\n\n    /// Collection-level metadata (name, image, royalty) for marketplaces\n    function contractURI() external view returns (string memory) {\n        bytes memory json = abi.encodePacked(\n            '{\"name\":\"HORANGI\",\"description\":\"5,000 fully on-chain pixel Korean minhwa tigers, 7-day mint. First card free per .ai Agent ID wallet; paid 0.00143 BNB each (about 1 USD) for every wallet, max 9 paid (cards 2-10). No admin.\",\"image\":\"data:image/svg+xml;base64,',\n            _b64(bytes(_svg(1, 1))), '\",\"seller_fee_basis_points\":100,\"fee_recipient\":\"', _addr(creator), '\"}'\n        );\n        return string.concat(\"data:application/json;base64,\", _b64(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) { len++; t /= 10; }\n        bytes memory o = new bytes(len);\n        while (v != 0) { len--; o[len] = bytes1(uint8(48 + v % 10)); v /= 10; }\n        return string(o);\n    }\n\n    function _addr(address a) internal pure returns (string memory) {\n        bytes memory o = new bytes(42);\n        bytes memory h = \"0123456789abcdef\";\n        o[0] = \"0\";\n        o[1] = \"x\";\n        uint160 v = uint160(a);\n        for (uint256 i; i < 20; ++i) {\n            uint8 x = uint8(v >> (8 * (19 - i)));\n            o[2 + 2 * i] = h[x >> 4];\n            o[3 + 2 * i] = h[x & 15];\n        }\n        return string(o);\n    }\n\n    /// Base64 (adapted from OpenZeppelin Contracts, 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 afterCache := mload(add(endPtr, 0x20))\n            mstore(add(endPtr, 0x20), 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                mstore8(add(resultPtr, 1), mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                mstore8(add(resultPtr, 2), mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                mstore8(add(resultPtr, 3), mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 4)\n            }\n            mstore(add(endPtr, 0x20), 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":"InvalidToken","type":"error","inputs":[]},{"name":"MintClosed","type":"error","inputs":[]},{"name":"NotAgent","type":"error","inputs":[]},{"name":"NotOwnerNorApproved","type":"error","inputs":[]},{"name":"NothingToMint","type":"error","inputs":[]},{"name":"PaidLimit","type":"error","inputs":[]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"TransferFailed","type":"error","inputs":[]},{"name":"Underpaid","type":"error","inputs":[]},{"name":"UnsafeRecipient","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":"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":"MAX_PAID_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MINT_DURATION","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":"ROYALTY_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"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":"o","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"contractURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"costFrom","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"name":"creator","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"freeClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"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":"o","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"paidQty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"mintEnd","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"mintInfo","type":"function","inputs":[],"outputs":[{"name":"supply","type":"uint256","internalType":"uint256"},{"name":"maxSupply","type":"uint256","internalType":"uint256"},{"name":"start","type":"uint256","internalType":"uint256"},{"name":"end","type":"uint256","internalType":"uint256"},{"name":"open","type":"bool","internalType":"bool"}],"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":"mintedByType","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256[2]","internalType":"uint256[2]"}],"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":"paidMinted","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"previewSVG","type":"function","inputs":[{"name":"traitsId","type":"uint256","internalType":"uint256"},{"name":"t","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"priceOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"name":"quote","type":"function","inputs":[{"name":"minter","type":"address","internalType":"address"},{"name":"paidQty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"freeCard","type":"bool","internalType":"bool"},{"name":"cost","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":"tokensOfOwner","type":"function","inputs":[{"name":"o","type":"address","internalType":"address"}],"outputs":[{"name":"ids","type":"uint256[]","internalType":"uint256[]"}],"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":"typeOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"walletInfo","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"freeUsed","type":"bool","internalType":"bool"},{"name":"paidCount","type":"uint256","internalType":"uint256"},{"name":"eligible","type":"bool","internalType":"bool"},{"name":"paidLeft","type":"uint256","internalType":"uint256"},{"name":"nextPrice","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"matchId":"58333347","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-04T06:57:38Z","match":"exact_match","chainId":"56","address":"0xe6BA3f94EECdd1F0d7A1235fdDE9A34D43d162c7"}