{"sources":{"c.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ninterface IAgentRegistry {\n    function balanceOf(address owner) external view returns (uint256);\n}\n\ninterface IERC2981 {\n    function royaltyInfo(uint256 tokenId, uint256 salePrice) external view\n        returns (address receiver, uint256 royaltyAmount);\n}\n\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) { return msg.sender; }\n}\n\ncontract AgentPassNFTv2 is Context {\n    string public constant name = \"AgentPass\";\n    string public constant symbol = \"APASS\";\n\n    uint256 public constant GENESIS_MAX = 4444;\n    uint256 public constant MAX_SUPPLY = 10000;\n    uint256 public constant MAX_PER_WALLET = 10;\n    uint256 public royaltyBps = 750; // 7.5%\n\n    address public owner;\n    uint256 public mintPrice = 0.0014 ether;\n    bool public mintOpen = true;\n    bool public genesisOpen = true;\n    address public registry; // .ai Agent ID registry (ERC721/ERC1155 balanceOf)\n    uint256 public totalSupply;\n    uint256 public genesisMinted;\n\n    mapping(address => uint256) public balanceOf;\n    mapping(uint256 => address) public ownerOf;\n    mapping(uint256 => address) public getApproved;\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\n    mapping(address => bool) public genesisClaimed;\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n    event Approval(address indexed o, address indexed sp, uint256 indexed id);\n    event ApprovalForAll(address indexed o, address indexed op, bool ap);\n    event OwnershipTransferred(address indexed oldO, address indexed newO);\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"not owner\");\n        _;\n    }\n\n    constructor(address _registry) {\n        owner = msg.sender;\n        registry = _registry;\n        emit OwnershipTransferred(address(0), msg.sender);\n    }\n\n    function supportsInterface(bytes4 iid) external pure returns (bool) {\n        return iid == 0x80ac58cd || iid == 0x5b5e139f || iid == 0x01ffc9a7\n            || iid == 0x2a55205a;\n    }\n\n    // ---- minting ----\n    function isAgentHolder(address w) public view returns (bool) {\n        if (registry == address(0)) return false;\n        (bool ok, bytes memory ret) = registry.staticcall(\n            abi.encodeWithSignature(\"balanceOf(address)\", w));\n        return ok && ret.length >= 32 && abi.decode(ret, (uint256)) > 0;\n    }\n\n    function genesisMint() external {\n        require(genesisOpen, \"genesis closed\");\n        require(!genesisClaimed[msg.sender], \"already claimed\");\n        require(isAgentHolder(msg.sender), \"not agent holder\");\n        require(genesisMinted < GENESIS_MAX, \"genesis sold out\");\n        require(totalSupply < MAX_SUPPLY, \"max supply\");\n        genesisClaimed[msg.sender] = true;\n        genesisMinted++;\n        totalSupply++;\n        _mint(msg.sender, totalSupply);\n    }\n\n    function mint(uint256 qty) external payable {\n        require(mintOpen, \"mint closed\");\n        require(qty >= 1 && qty <= MAX_PER_WALLET, \"Invalid quantity\");\n        require(balanceOf[msg.sender] + qty <= MAX_PER_WALLET, \"Exceeds wallet limit\");\n        require(totalSupply + qty <= MAX_SUPPLY, \"Exceeds max supply\");\n        require(msg.value == mintPrice * qty, \"Wrong value\");\n        for (uint256 i = 0; i < qty; i++) {\n            totalSupply++;\n            _mint(msg.sender, totalSupply);\n        }\n    }\n\n    function _mint(address to, uint256 id) internal {\n        require(to != address(0), \"zero addr\");\n        require(ownerOf[id] == address(0), \"exists\");\n        balanceOf[to]++;\n        ownerOf[id] = to;\n        emit Transfer(address(0), to, id);\n    }\n\n    // ---- ERC721 ----\n    function approve(address spender, uint256 id) external {\n        require(ownerOf[id] == msg.sender || isApprovedForAll[ownerOf[id]][msg.sender], \"not owner\");\n        getApproved[id] = spender;\n        emit Approval(ownerOf[id], spender, id);\n    }\n\n    function setApprovalForAll(address op, bool ap) external {\n        isApprovedForAll[msg.sender][op] = ap;\n        emit ApprovalForAll(msg.sender, op, ap);\n    }\n\n    function transferFrom(address from, address to, uint256 id) public {\n        require(ownerOf[id] == from, \"wrong owner\");\n        require(\n            msg.sender == from\n            || getApproved[id] == msg.sender\n            || isApprovedForAll[from][msg.sender],\n            \"not approved\");\n        delete getApproved[id];\n        balanceOf[from]--;\n        balanceOf[to]++;\n        ownerOf[id] = to;\n        emit Transfer(from, to, id);\n    }\n\n    function safeTransferFrom(address from, address to, uint256 id) public {\n        transferFrom(from, to, id);\n        require(\n            to.code.length == 0\n            || IERCReceiver(to).onERC721Received(msg.sender, from, id, \"\") == 0x150b7a02,\n            \"bad receiver\");\n    }\n\n    function safeTransferFrom(address from, address to, uint256 id, bytes calldata) external {\n        safeTransferFrom(from, to, id);\n    }\n\n    function tokenOfOwnerByIndex(address w, uint256 i) external view returns (uint256) {\n        uint256 b = balanceOf[w];\n        require(i < b, \"oob\");\n        uint256 found;\n        for (uint256 id = 1; id <= totalSupply; id++) {\n            if (ownerOf[id] == w) {\n                if (found == i) return id;\n                found++;\n            }\n        }\n        revert(\"not found\");\n    }\n\n    // ---- metadata (on-chain, base64) ----\n    function _b64(bytes memory raw) internal pure returns (string memory) {\n        string memory T = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n        bytes memory t = bytes(T);\n        uint256 len = raw.length;\n        uint256 outLen = 4 * ((len + 2) / 3);\n        bytes memory out = new bytes(outLen);\n        uint256 j;\n        for (uint256 i = 0; i < len; i += 3) {\n            uint256 a = uint256(uint8(raw[i]));\n            uint256 b = i + 1 < len ? uint256(uint8(raw[i + 1])) : 0;\n            uint256 c = i + 2 < len ? uint256(uint8(raw[i + 2])) : 0;\n            uint256 triple = (a << 16) | (b << 8) | c;\n            out[j++] = t[(triple >> 18) & 63];\n            out[j++] = t[(triple >> 12) & 63];\n            out[j++] = i + 1 < len ? t[(triple >> 6) & 63] : bytes1(\"=\");\n            out[j++] = i + 2 < len ? t[triple & 63] : bytes1(\"=\");\n        }\n        return string(out);\n    }\n\n    function _itoa(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\";\n        uint256 t = v;\n        uint256 d;\n        while (t > 0) { d++; t /= 10; }\n        bytes memory buf = new bytes(d);\n        while (v > 0) { buf[--d] = bytes1(uint8(48 + v % 10)); v /= 10; }\n        return string(buf);\n    }\n\n    function tokenURI(uint256 id) external view returns (string memory) {\n        require(ownerOf[id] != address(0), \"no token\");\n        bool genesis = id <= GENESIS_MAX;\n        string memory tier = genesis ? \"Genesis\" : \"Standard\";\n        uint256 weight = genesis ? 2 : 1;\n        string memory color = genesis ? \"#d4a843\" : \"#8b8a94\";\n        string memory svg = string.concat(\n            '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400\" height=\"560\">',\n            '<rect width=\"400\" height=\"560\" fill=\"#0a0a0c\"/>',\n            '<rect x=\"12\" y=\"12\" width=\"376\" height=\"536\" fill=\"none\" stroke=\"', color, '\" stroke-width=\"2\"/>',\n            '<text x=\"200\" y=\"140\" fill=\"', color, '\" font-family=\"Georgia\" font-size=\"34\" text-anchor=\"middle\">AGENTPASS</text>',\n            '<text x=\"200\" y=\"200\" fill=\"#e8e6e1\" font-family=\"monospace\" font-size=\"26\" text-anchor=\"middle\">', tier, '</text>',\n            '<text x=\"200\" y=\"250\" fill=\"#8b8a94\" font-family=\"monospace\" font-size=\"15\" text-anchor=\"middle\">staking weight ', _itoa(weight), 'x</text>',\n            '<text x=\"200\" y=\"470\" fill=\"#8b8a94\" font-family=\"monospace\" font-size=\"14\" text-anchor=\"middle\">#', _itoa(id), ' / 10000</text>',\n            '</svg>');\n        string memory json = string.concat(\n            '{\"name\":\"AgentPass #', _itoa(id), '\",\"description\":\"AgentPass: The Access Layer for On-Chain Agents.\",\"attributes\":[{\"trait_type\":\"Tier\",\"value\":\"', tier, '\"},{\"trait_type\":\"Staking Weight\",\"value\":\"', _itoa(weight), 'x\"}],',\n            '\"image\":\"data:image/svg+xml;base64,', _b64(bytes(svg)), '\"}');\n        return string.concat(\"data:application/json;base64,\", _b64(bytes(json)));\n    }\n\n    // ---- royalty EIP-2981 ----\n    function royaltyInfo(uint256, uint256 salePrice) external view\n        returns (address, uint256) {\n        return (owner, salePrice * royaltyBps / 10000);\n    }\n\n    // ---- admin ----\n    function setRegistry(address r) external onlyOwner { registry = r; }\n    function setMintPrice(uint256 p) external onlyOwner { mintPrice = p; }\n    function setMintOpen(bool o) external onlyOwner { mintOpen = o; }\n    function setGenesisOpen(bool o) external onlyOwner { genesisOpen = o; }\n    function setRoyaltyBps(uint256 b) external onlyOwner { require(b <= 1000, \"max 10%\"); royaltyBps = b; }\n    function withdraw() external onlyOwner {\n        (bool ok, ) = owner.call{value: address(this).balance}(\"\");\n        require(ok, \"withdraw failed\");\n    }\n}\n\ninterface IERCReceiver {\n    function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4);\n}\n\n// TESTNET ONLY: mock .ai agent registry for genesis mint testing\ncontract MockAgentRegistry {\n    mapping(address => uint256) public balanceOf;\n    address public owner;\n    constructor() { owner = msg.sender; }\n    function mintAgent(address to) external { balanceOf[to]++; }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"_registry","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"Approval","type":"event","inputs":[{"name":"o","type":"address","indexed":true,"internalType":"address"},{"name":"sp","type":"address","indexed":true,"internalType":"address"},{"name":"id","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"ApprovalForAll","type":"event","inputs":[{"name":"o","type":"address","indexed":true,"internalType":"address"},{"name":"op","type":"address","indexed":true,"internalType":"address"},{"name":"ap","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"OwnershipTransferred","type":"event","inputs":[{"name":"oldO","type":"address","indexed":true,"internalType":"address"},{"name":"newO","type":"address","indexed":true,"internalType":"address"}],"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":"GENESIS_MAX","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"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":"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":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"genesisClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"genesisMint","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"genesisMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"genesisOpen","type":"function","inputs":[],"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":"isAgentHolder","type":"function","inputs":[{"name":"w","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"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":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mintPrice","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":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"registry","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"royaltyBps","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":"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":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"op","type":"address","internalType":"address"},{"name":"ap","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setGenesisOpen","type":"function","inputs":[{"name":"o","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintOpen","type":"function","inputs":[{"name":"o","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintPrice","type":"function","inputs":[{"name":"p","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRegistry","type":"function","inputs":[{"name":"r","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRoyaltyBps","type":"function","inputs":[{"name":"b","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"iid","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":"tokenOfOwnerByIndex","type":"function","inputs":[{"name":"w","type":"address","internalType":"address"},{"name":"i","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"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"},{"name":"withdraw","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"58071941","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-02T11:53:35Z","match":"exact_match","chainId":"56","address":"0xab089E3e7F995c5eD0A12E854D19C6756903B7e1"}