{"sources":{"GlitchCritters.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\n/// @title Glitch Critters - 2,222 fully on-chain pixel agent critters on BNB Chain\n/// @notice 1 free mint per wallet, extra mints 0.0003 BNB each, max 10 per wallet.\n///         Adminless: no owner, no upgrade, mint payments go straight to the immutable payee.\ncontract GlitchCritters {\n    string public constant name = \"Glitch Critters\";\n    string public constant symbol = \"GLITCH\";\n    uint256 public constant MAX_SUPPLY = 2222;\n    uint256 public constant MAX_PER_WALLET = 10;\n    uint256 public constant PRICE = 0.0003 ether;\n\n    address public immutable payee;\n    uint256 public totalSupply;\n\n    mapping(uint256 => address) private _ownerOf;\n    mapping(address => uint256) private _balanceOf;\n    mapping(uint256 => address) public getApproved;\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\n    mapping(address => uint256) public mintedBy;\n    mapping(address => bool) public freeClaimed;\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed id);\n    event Approval(address indexed owner, address indexed spender, uint256 indexed id);\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    error SoldOut();\n    error WalletLimit();\n    error WrongPayment();\n    error ZeroQuantity();\n    error NotAuthorized();\n    error InvalidToken();\n    error UnsafeRecipient();\n    error PayoutFailed();\n\n    constructor(address payee_) {\n        payee = payee_;\n    }\n\n    // ---------------- Mint ----------------\n\n    /// @notice Cost for `account` to mint `qty` right now (first one free if unclaimed).\n    function quote(address account, uint256 qty) public view returns (uint256) {\n        if (qty == 0) return 0;\n        uint256 paid = freeClaimed[account] ? qty : qty - 1;\n        return paid * PRICE;\n    }\n\n    function mint(uint256 qty) external payable {\n        if (qty == 0) revert ZeroQuantity();\n        uint256 supply = totalSupply;\n        if (supply + qty > MAX_SUPPLY) revert SoldOut();\n        if (mintedBy[msg.sender] + qty > MAX_PER_WALLET) revert WalletLimit();\n        if (msg.value != quote(msg.sender, qty)) revert WrongPayment();\n\n        freeClaimed[msg.sender] = true;\n        mintedBy[msg.sender] += qty;\n        _balanceOf[msg.sender] += qty;\n        for (uint256 i = 1; i <= qty; ++i) {\n            uint256 id = supply + i;\n            _ownerOf[id] = msg.sender;\n            emit Transfer(address(0), msg.sender, id);\n        }\n        totalSupply = supply + qty;\n\n        if (msg.value > 0) {\n            (bool ok, ) = payee.call{value: msg.value}(\"\");\n            if (!ok) revert PayoutFailed();\n        }\n    }\n\n    // ---------------- ERC721 ----------------\n\n    function ownerOf(uint256 id) public view returns (address o) {\n        o = _ownerOf[id];\n        if (o == address(0)) revert InvalidToken();\n    }\n\n    function balanceOf(address o) external view returns (uint256) {\n        return _balanceOf[o];\n    }\n\n    function approve(address spender, uint256 id) external {\n        address o = ownerOf(id);\n        if (msg.sender != o && !isApprovedForAll[o][msg.sender]) revert NotAuthorized();\n        getApproved[id] = spender;\n        emit Approval(o, spender, id);\n    }\n\n    function setApprovalForAll(address operator, bool approved) external {\n        isApprovedForAll[msg.sender][operator] = approved;\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function transferFrom(address from, address to, uint256 id) public {\n        if (from != ownerOf(id)) revert NotAuthorized();\n        if (to == address(0)) revert UnsafeRecipient();\n        if (msg.sender != from && !isApprovedForAll[from][msg.sender] && msg.sender != getApproved[id]) {\n            revert NotAuthorized();\n        }\n        unchecked {\n            _balanceOf[from]--;\n            _balanceOf[to]++;\n        }\n        _ownerOf[id] = to;\n        delete getApproved[id];\n        emit Transfer(from, to, id);\n    }\n\n    function safeTransferFrom(address from, address to, uint256 id) external {\n        safeTransferFrom(from, to, id, \"\");\n    }\n\n    function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public {\n        transferFrom(from, to, id);\n        if (to.code.length != 0) {\n            (bool ok, bytes memory ret) = to.call(\n                abi.encodeWithSelector(0x150b7a02, msg.sender, from, id, data)\n            );\n            if (!ok || ret.length < 32 || abi.decode(ret, (bytes4)) != bytes4(0x150b7a02)) {\n                revert UnsafeRecipient();\n            }\n        }\n    }\n\n    function supportsInterface(bytes4 id) external pure returns (bool) {\n        return id == 0x01ffc9a7 || id == 0x80ac58cd || id == 0x5b5e139f || id == 0x2a55205a;\n    }\n\n    /// @notice EIP-2981: 5% royalty on secondary sales to the payee.\n    function royaltyInfo(uint256, uint256 salePrice) external view returns (address, uint256) {\n        return (payee, (salePrice * 500) / 10000);\n    }\n\n    // ---------------- On-chain art ----------------\n\n    function BG_() internal pure returns (string[8] memory) { return [\"#0b1026\", \"#1a0b2e\", \"#062925\", \"#2b0f0f\", \"#0f1f3d\", \"#201a05\", \"#101010\", \"#2a0a2a\"]; }\n    function BG_NAME_() internal pure returns (string[8] memory) { return [\"Midnight\", \"Void\", \"Matrix\", \"Ember\", \"Deep Sea\", \"Gold Dust\", \"Static\", \"Neon Night\"]; }\n    function BODY_() internal pure returns (string[8] memory) { return [\"#7c3aed\", \"#22d3ee\", \"#a3e635\", \"#f472b6\", \"#fb923c\", \"#facc15\", \"#e5e7eb\", \"#ef4444\"]; }\n    function BODY_NAME_() internal pure returns (string[8] memory) { return [\"Ultraviolet\", \"Cyan\", \"Toxic\", \"Bubblegum\", \"Lava\", \"Gold\", \"Chrome\", \"Glitch Red\"]; }\n    function EYES_NAME_() internal pure returns (string[5] memory) { return [\"Round\", \"Visor\", \"Cyclops\", \"Sleepy\", \"Laser\"]; }\n    function HEAD_NAME_() internal pure returns (string[4] memory) { return [\"Antenna\", \"Horns\", \"Ears\", \"None\"]; }\n    function MOUTH_NAME_() internal pure returns (string[4] memory) { return [\"Grin\", \"Fangs\", \"Flat\", \"O\"]; }\n    function AURA_NAME_() internal pure returns (string[4] memory) { return [\"None\", \"Pixel Rain\", \"Halo\", \"Scanlines\"]; }\n\n    function _traits(uint256 id) internal view returns (uint256[6] memory t) {\n        uint256 s = uint256(keccak256(abi.encodePacked(address(this), id, \"GLITCH\")));\n        t[0] = s % 8;\n        t[1] = (s >> 8) % 8;\n        t[2] = (s >> 16) % 5;\n        t[3] = (s >> 24) % 4;\n        t[4] = (s >> 32) % 4;\n        uint256 a = (s >> 40) % 100;\n        t[5] = a < 70 ? 0 : a < 85 ? 1 : a < 95 ? 3 : 2; // Halo rarest\n    }\n\n    function _r(uint256 x, uint256 y, uint256 w, uint256 h, string memory c) internal pure returns (bytes memory) {\n        return abi.encodePacked('<rect x=\"', _s(x), '\" y=\"', _s(y), '\" width=\"', _s(w), '\" height=\"', _s(h), '\" fill=\"', c, '\"/>');\n    }\n\n    function _svg(uint256[6] memory t) internal view returns (bytes memory out) {\n        string memory b = BODY_()[t[1]];\n        out = abi.encodePacked(\n            '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" shape-rendering=\"crispEdges\">',\n            _r(0, 0, 24, 24, BG_()[t[0]])\n        );\n        if (t[5] == 1) out = abi.encodePacked(out, _r(2, 2, 1, 1, \"#ffffff55\"), _r(20, 5, 1, 1, \"#ffffff55\"), _r(5, 19, 1, 1, \"#ffffff55\"), _r(18, 17, 1, 1, \"#ffffff55\"));\n        if (t[5] == 2) out = abi.encodePacked(out, _r(8, 1, 8, 1, \"#fde047\"));\n        // head decoration\n        if (t[3] == 0) out = abi.encodePacked(out, _r(11, 3, 2, 3, b), _r(10, 2, 4, 1, \"#ffffff\"));\n        if (t[3] == 1) out = abi.encodePacked(out, _r(6, 4, 2, 3, \"#f5f5f4\"), _r(16, 4, 2, 3, \"#f5f5f4\"));\n        if (t[3] == 2) out = abi.encodePacked(out, _r(5, 5, 3, 4, b), _r(16, 5, 3, 4, b));\n        // body\n        out = abi.encodePacked(out, _r(6, 6, 12, 12, b), _r(5, 8, 1, 8, b), _r(18, 8, 1, 8, b), _r(8, 18, 8, 3, b), _r(7, 7, 2, 1, \"#ffffff66\"));\n        // eyes\n        if (t[2] == 0) out = abi.encodePacked(out, _r(8, 9, 3, 3, \"#ffffff\"), _r(13, 9, 3, 3, \"#ffffff\"), _r(9, 10, 1, 1, \"#000000\"), _r(14, 10, 1, 1, \"#000000\"));\n        if (t[2] == 1) out = abi.encodePacked(out, _r(7, 9, 10, 2, \"#000000\"), _r(8, 9, 8, 1, \"#22d3ee\"));\n        if (t[2] == 2) out = abi.encodePacked(out, _r(10, 8, 4, 4, \"#ffffff\"), _r(11, 9, 2, 2, \"#000000\"));\n        if (t[2] == 3) out = abi.encodePacked(out, _r(8, 10, 3, 1, \"#000000\"), _r(13, 10, 3, 1, \"#000000\"));\n        if (t[2] == 4) out = abi.encodePacked(out, _r(8, 9, 3, 2, \"#ef4444\"), _r(13, 9, 3, 2, \"#ef4444\"), _r(16, 10, 8, 1, \"#ef444499\"));\n        // mouth\n        if (t[4] == 0) out = abi.encodePacked(out, _r(9, 14, 6, 2, \"#000000\"), _r(10, 14, 1, 1, \"#ffffff\"), _r(12, 14, 1, 1, \"#ffffff\"), _r(14, 14, 1, 1, \"#ffffff\"));\n        if (t[4] == 1) out = abi.encodePacked(out, _r(9, 14, 6, 1, \"#000000\"), _r(10, 15, 1, 1, \"#ffffff\"), _r(13, 15, 1, 1, \"#ffffff\"));\n        if (t[4] == 2) out = abi.encodePacked(out, _r(9, 15, 6, 1, \"#000000\"));\n        if (t[4] == 3) out = abi.encodePacked(out, _r(11, 14, 2, 2, \"#000000\"));\n        if (t[5] == 3) out = abi.encodePacked(out, _r(0, 4, 24, 1, \"#ffffff22\"), _r(0, 12, 24, 1, \"#ffffff22\"), _r(0, 20, 24, 1, \"#ffffff22\"));\n        out = abi.encodePacked(out, \"</svg>\");\n    }\n\n    function tokenURI(uint256 id) external view returns (string memory) {\n        ownerOf(id);\n        uint256[6] memory t = _traits(id);\n        bytes memory attrs = abi.encodePacked(\n            '[{\"trait_type\":\"Background\",\"value\":\"', BG_NAME_()[t[0]],\n            '\"},{\"trait_type\":\"Body\",\"value\":\"', BODY_NAME_()[t[1]],\n            '\"},{\"trait_type\":\"Eyes\",\"value\":\"', EYES_NAME_()[t[2]],\n            '\"},{\"trait_type\":\"Head\",\"value\":\"', HEAD_NAME_()[t[3]],\n            '\"},{\"trait_type\":\"Mouth\",\"value\":\"', MOUTH_NAME_()[t[4]],\n            '\"},{\"trait_type\":\"Aura\",\"value\":\"', AURA_NAME_()[t[5]], '\"}]'\n        );\n        bytes memory json = abi.encodePacked(\n            '{\"name\":\"Glitch Critters #', _s(id),\n            '\",\"description\":\"2,222 fully on-chain pixel agent critters glitching on BNB Chain. 1 free per wallet.\",\"image\":\"data:image/svg+xml;base64,',\n            _b64(_svg(t)), '\",\"attributes\":', attrs, \"}\"\n        );\n        return string(abi.encodePacked(\"data:application/json;base64,\", _b64(json)));\n    }\n\n    // ---------------- Utils ----------------\n\n    function _s(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\";\n        uint256 j = v;\n        uint256 len;\n        while (j != 0) { len++; j /= 10; }\n        bytes memory b = new bytes(len);\n        while (v != 0) { b[--len] = bytes1(uint8(48 + (v % 10))); v /= 10; }\n        return string(b);\n    }\n\n    function _b64(bytes memory data) internal pure returns (string memory) {\n        bytes memory T = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n        uint256 len = data.length;\n        if (len == 0) return \"\";\n        bytes memory out = new bytes(4 * ((len + 2) / 3));\n        uint256 j;\n        for (uint256 i = 0; i < len; i += 3) {\n            uint256 a = uint8(data[i]);\n            uint256 b = i + 1 < len ? uint8(data[i + 1]) : 0;\n            uint256 c = i + 2 < len ? uint8(data[i + 2]) : 0;\n            uint256 n = (a << 16) | (b << 8) | c;\n            out[j++] = T[(n >> 18) & 63];\n            out[j++] = T[(n >> 12) & 63];\n            out[j++] = i + 1 < len ? T[(n >> 6) & 63] : bytes1(\"=\");\n            out[j++] = i + 2 < len ? T[n & 63] : bytes1(\"=\");\n        }\n        return string(out);\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"payee_","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"InvalidToken","type":"error","inputs":[]},{"name":"NotAuthorized","type":"error","inputs":[]},{"name":"PayoutFailed","type":"error","inputs":[]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"UnsafeRecipient","type":"error","inputs":[]},{"name":"WalletLimit","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"ZeroQuantity","type":"error","inputs":[]},{"name":"Approval","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"id","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":"id","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"MAX_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":"PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"approve","type":"function","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"id","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":"freeClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","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":"mintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"o","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"payee","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"quote","type":"function","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"qty","type":"uint256","internalType":"uint256"}],"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":"id","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":"id","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":"id","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":"id","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"57093852","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-10-26T11:48:41Z","match":"exact_match","chainId":"56","address":"0x2bfD003ACCa75A238eeF94119b8B09fDaaCF35Ea"}