{"sources":{"AgentCosmosNFT.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n/*\n * AGENT COSMOS — 合约 A：只负责铸造 NFT\n * - 只有持有 Binance .ai Agent ID 的钱包能铸造（链上校验）\n * - 总量 100,000，每钱包最多 10 枚\n * - 第 1 枚免费，之后按 USDT 收费，收入全部直接打入合约 B（质押分红合约）\n * - 钱包里第 N 枚 = 第 N 级（tierOf），对应第 N 张图\n * - 二级市场不限制买家\n * 未经审计。\n */\n\ninterface IAgentId { function balanceOf(address) external view returns (uint256); }\ninterface IERC20 { function transferFrom(address, address, uint256) external returns (bool); }\ninterface IVault { function onMintRevenue(uint256 amount) external; }\ninterface IERC721Receiver { function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4); }\n\ncontract AgentCosmosNFT {\n    string public constant name = \"Agent Cosmos\";\n    string public constant symbol = \"ACOS\";\n    uint256 public constant MAX_SUPPLY = 100_000;\n    uint256 public constant WALLET_CAP = 10;\n\n    IAgentId public immutable agentId;\n    IERC20 public immutable usdt;\n    address public owner;\n    address public vault;            // 合约 B，只能设置一次\n    bool public mintOpen;\n    string public baseURI;\n    bool public metadataLocked;\n\n    uint256 public totalSupply;\n    mapping(uint256 => address) private _owners;\n    mapping(address => uint256) private _balances;\n    mapping(uint256 => address) public getApproved;\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\n    mapping(address => uint256[]) private _owned;\n    mapping(uint256 => uint256) private _ownedIndex;\n\n    mapping(address => uint256) public mintedByWallet;\n    mapping(uint256 => uint8) public tierOf;   // 1..10\n\n    uint256 private _lock = 1;\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 Minted(address indexed to, uint256 indexed tokenId, uint8 tier, uint256 price);\n    event OwnershipTransferred(address indexed from, address indexed to);\n    event VaultSet(address vault);\n    event MetadataLocked();\n\n    modifier onlyOwner() { require(msg.sender == owner, \"OWNER\"); _; }\n    modifier nonReentrant() { require(_lock == 1, \"REENTRANT\"); _lock = 2; _; _lock = 1; }\n\n    constructor(address agentId_, address usdt_, address owner_, string memory baseURI_) {\n        require(agentId_ != address(0) && usdt_ != address(0) && owner_ != address(0), \"ZERO\");\n        agentId = IAgentId(agentId_);\n        usdt = IERC20(usdt_);\n        owner = owner_;\n        baseURI = baseURI_;\n        emit OwnershipTransferred(address(0), owner_);\n    }\n\n    // 第 n 枚（1..10）的价格，USDT 18 位\n    function priceForSeq(uint256 n) public pure returns (uint256) {\n        if (n == 1) return 0;\n        if (n <= 4) return 0.25 ether;\n        if (n <= 7) return 0.5 ether;\n        if (n <= 9) return 0.75 ether;\n        return 1 ether;\n    }\n    function nextMintPrice(address a) external view returns (uint256) {\n        uint256 n = mintedByWallet[a] + 1;\n        return n > WALLET_CAP ? 0 : priceForSeq(n);\n    }\n\n    function mint() external nonReentrant returns (uint256 id) {\n        require(mintOpen, \"MINT_CLOSED\");\n        require(vault != address(0), \"NO_VAULT\");\n        require(agentId.balanceOf(msg.sender) > 0, \"NO_AGENT_ID\");\n        uint256 n = mintedByWallet[msg.sender] + 1;\n        require(n <= WALLET_CAP, \"WALLET_CAP\");\n        require(totalSupply < MAX_SUPPLY, \"SOLD_OUT\");\n\n        uint256 price = priceForSeq(n);\n        mintedByWallet[msg.sender] = n;\n        id = ++totalSupply;\n        tierOf[id] = uint8(n);\n        _owners[id] = msg.sender;\n        _balances[msg.sender] += 1;\n        _addOwned(msg.sender, id);\n        emit Transfer(address(0), msg.sender, id);\n        emit Minted(msg.sender, id, uint8(n), price);\n\n        if (price > 0) {\n            require(usdt.transferFrom(msg.sender, vault, price), \"PAY\");\n            IVault(vault).onMintRevenue(price);\n        }\n    }\n\n    // ---------------- ERC721 ----------------\n    function ownerOf(uint256 id) public view returns (address o) { o = _owners[id]; require(o != address(0), \"NO_TOKEN\"); }\n    function balanceOf(address a) external view returns (uint256) { require(a != address(0), \"ZERO\"); return _balances[a]; }\n    function tokensOfOwner(address a) external view returns (uint256[] memory) { return _owned[a]; }\n    function tokenURI(uint256 id) external view returns (string memory) { ownerOf(id); return string(abi.encodePacked(baseURI, _toString(id))); }\n\n    function approve(address to, uint256 id) external {\n        address o = ownerOf(id);\n        require(msg.sender == o || isApprovedForAll[o][msg.sender], \"AUTH\");\n        getApproved[id] = to; emit Approval(o, to, id);\n    }\n    function setApprovalForAll(address op, bool ok) external { isApprovedForAll[msg.sender][op] = ok; emit ApprovalForAll(msg.sender, op, ok); }\n\n    function transferFrom(address from, address to, uint256 id) public {\n        require(ownerOf(id) == from, \"FROM\");\n        require(to != address(0), \"ZERO\");\n        require(msg.sender == from || isApprovedForAll[from][msg.sender] || getApproved[id] == msg.sender, \"AUTH\");\n        delete getApproved[id];\n        _balances[from] -= 1; _balances[to] += 1; _owners[id] = to;\n        _removeOwned(from, id); _addOwned(to, id);\n        emit Transfer(from, to, id);\n    }\n    function safeTransferFrom(address from, address to, uint256 id) external { safeTransferFrom(from, to, id, \"\"); }\n    function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public {\n        transferFrom(from, to, id);\n        if (to.code.length > 0) require(IERC721Receiver(to).onERC721Received(msg.sender, from, id, data) == IERC721Receiver.onERC721Received.selector, \"RECEIVER\");\n    }\n    function supportsInterface(bytes4 x) external pure returns (bool) { return x == 0x80ac58cd || x == 0x5b5e139f || x == 0x01ffc9a7; }\n\n    function _addOwned(address a, uint256 id) internal { _ownedIndex[id] = _owned[a].length; _owned[a].push(id); }\n    function _removeOwned(address a, uint256 id) internal {\n        uint256 i = _ownedIndex[id]; uint256 last = _owned[a].length - 1;\n        if (i != last) { uint256 m = _owned[a][last]; _owned[a][i] = m; _ownedIndex[m] = i; }\n        _owned[a].pop();\n    }\n    function _toString(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\"; uint256 t = v; uint256 d; while (t != 0) { d++; t /= 10; }\n        bytes memory b = new bytes(d); while (v != 0) { d--; b[d] = bytes1(uint8(48 + v % 10)); v /= 10; } return string(b);\n    }\n\n    // ---------------- owner ----------------\n    function setVault(address v) external onlyOwner { require(vault == address(0) && v != address(0), \"SET\"); vault = v; emit VaultSet(v); }\n    function setMintOpen(bool o) external onlyOwner { mintOpen = o; }\n    function setBaseURI(string calldata u) external onlyOwner { require(!metadataLocked, \"LOCKED\"); baseURI = u; }\n    function lockMetadata() external onlyOwner { metadataLocked = true; emit MetadataLocked(); }\n    function transferOwnership(address n) external onlyOwner { require(n != address(0), \"ZERO\"); emit OwnershipTransferred(owner, n); owner = n; }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"agentId_","type":"address","internalType":"address"},{"name":"usdt_","type":"address","internalType":"address"},{"name":"owner_","type":"address","internalType":"address"},{"name":"baseURI_","type":"string","internalType":"string"}],"stateMutability":"nonpayable"},{"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":"MetadataLocked","type":"event","inputs":[],"anonymous":false},{"name":"Minted","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"tier","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"price","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"OwnershipTransferred","type":"event","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","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":"VaultSet","type":"event","inputs":[{"name":"vault","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"WALLET_CAP","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"agentId","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentId"}],"stateMutability":"view"},{"name":"approve","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"balanceOf","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"baseURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"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":"lockMetadata","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"metadataLocked","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[],"outputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mintedByWallet","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":"nextMintPrice","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"o","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"priceForSeq","type":"function","inputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"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":"op","type":"address","internalType":"address"},{"name":"ok","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setBaseURI","type":"function","inputs":[{"name":"u","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintOpen","type":"function","inputs":[{"name":"o","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setVault","type":"function","inputs":[{"name":"v","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"x","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tierOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tokensOfOwner","type":"function","inputs":[{"name":"a","type":"address","internalType":"address"}],"outputs":[{"name":"","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":"id","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"transferOwnership","type":"function","inputs":[{"name":"n","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"usdt","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IERC20"}],"stateMutability":"view"},{"name":"vault","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"}],"matchId":"56874040","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-10-24T20:44:24Z","match":"exact_match","chainId":"56","address":"0x86d4287dbC0696e74AA8383cA25BE8a6B3Ff0Ac6"}