{"sources":{"PoaNFT.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\ninterface IAgentRegistryNFT {\n    function balanceOf(address account) external view returns (uint256);\n}\n\n/// @title Proof Of Human NFT — 2,500 pieces on BSC.\n/// Token IDs 1..2,500 carry pre-shuffled rarity (assigned at generation).\n/// Mint is Agent-ID-only (SPACE ID Agent ID registry), phased by mint count:\n/// mints #1-1,000 free (max 3 free per wallet), mints #1,001-2,500 cost\n/// 0.002 BNB each (max 8 paid per wallet), proceeds forwarded 100% to owner.\n/// Owner (project wallet) is fixed at construction; the deployer keeps a\n/// setup-only admin role (setBaseURI / setSaleActive) until lockSetup().\ncontract PoaNFT {\n    string public name = \"Proof Of Human\";\n    string public symbol = \"POH\";\n    uint256 public constant MAX_SUPPLY = 2_500;\n    uint256 public constant FREE_LIMIT = 1_000;\n    uint256 public constant PRICE = 0.002 ether;\n    uint256 public constant MAX_FREE_PER_WALLET = 3;\n    uint256 public constant MAX_PAID_PER_WALLET = 8;\n    uint256 public constant MAX_PER_TX = 10;\n\n    address public owner;\n    address public admin; // deployer, setup only; zeroed by lockSetup()\n    bool public setupLocked;\n    bool public saleActive;\n    string private _baseTokenURI;\n    IAgentRegistryNFT public registry;\n\n    uint256 private _nextId = 1;\n    mapping(address => uint256) public freeMintedBy;\n    mapping(address => uint256) public paidMintedBy;\n\n    // ERC721 state\n    mapping(uint256 => address) private _owners;\n    mapping(address => uint256) public balanceOf;\n    mapping(uint256 => address) public getApproved;\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\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 buyer, uint256 firstId, uint256 qty, uint256 paidWei);\n\n    constructor(address initialOwner, address registry_) {\n        require(initialOwner != address(0), \"zero owner\");\n        owner = initialOwner;\n        admin = msg.sender;\n        registry = IAgentRegistryNFT(registry_);\n    }\n\n    // ---------- views ----------\n    function totalSupply() public view returns (uint256) {\n        return _nextId - 1;\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address) {\n        address o = _owners[tokenId];\n        require(o != address(0), \"nonexistent token\");\n        return o;\n    }\n\n    function hasAgentId(address a) public view returns (bool) {\n        try registry.balanceOf(a) returns (uint256 b) {\n            return b > 0;\n        } catch {\n            return false;\n        }\n    }\n\n    function splitFor(uint256 count) public view returns (uint256 freeShares, uint256 paidShares) {\n        uint256 minted = totalSupply();\n        uint256 freeLeft = minted < FREE_LIMIT ? FREE_LIMIT - minted : 0;\n        freeShares = count > freeLeft ? freeLeft : count;\n        paidShares = count - freeShares;\n    }\n\n    function costFor(uint256 count) public view returns (uint256) {\n        (, uint256 paidShares) = splitFor(count);\n        return paidShares * PRICE;\n    }\n\n    function tokenURI(uint256 tokenId) public view returns (string memory) {\n        require(_owners[tokenId] != address(0), \"nonexistent token\");\n        return string(abi.encodePacked(_baseTokenURI, _toString(tokenId), \".json\"));\n    }\n\n    function supportsInterface(bytes4 interfaceId) public pure returns (bool) {\n        return interfaceId == 0x80ac58cd || interfaceId == 0x5b5e139f || interfaceId == 0x01ffc9a7;\n    }\n\n    // ---------- mint ----------\n    function mint(uint256 count) external payable {\n        require(saleActive, \"Sale not active\");\n        require(count >= 1 && count <= MAX_PER_TX, \"count 1-10\");\n        require(hasAgentId(msg.sender), \"Agent ID required\");\n        require(totalSupply() + count <= MAX_SUPPLY, \"Sold out\");\n        (uint256 freeShares, uint256 paidShares) = splitFor(count);\n        require(freeMintedBy[msg.sender] + freeShares <= MAX_FREE_PER_WALLET, \"max 3 free per wallet\");\n        require(paidMintedBy[msg.sender] + paidShares <= MAX_PAID_PER_WALLET, \"max 8 paid per wallet\");\n        uint256 cost = paidShares * PRICE;\n        require(msg.value >= cost, \"insufficient BNB\");\n\n        freeMintedBy[msg.sender] += freeShares;\n        paidMintedBy[msg.sender] += paidShares;\n\n        uint256 firstId = _nextId;\n        for (uint256 i = 0; i < count; i++) {\n            uint256 id = _nextId++;\n            _owners[id] = msg.sender;\n            balanceOf[msg.sender] += 1;\n            emit Transfer(address(0), msg.sender, id);\n            // safe-mint check for contract recipients\n            if (msg.sender.code.length > 0) {\n                require(\n                    _checkOnERC721Received(address(0), msg.sender, id, \"\"),\n                    \"ERC721: transfer to non ERC721Receiver\"\n                );\n            }\n        }\n        emit Minted(msg.sender, firstId, count, cost);\n\n        if (cost > 0) {\n            (bool ok, ) = owner.call{value: cost}(\"\");\n            require(ok, \"proceeds forward failed\");\n        }\n        if (msg.value > cost) {\n            (bool ok2, ) = msg.sender.call{value: msg.value - cost}(\"\");\n            require(ok2, \"refund failed\");\n        }\n    }\n\n    // ---------- setup / owner ----------\n    function setBaseURI(string calldata uri) external {\n        require(!setupLocked && (msg.sender == admin || msg.sender == owner), \"not admin/owner\");\n        _baseTokenURI = uri;\n    }\n\n    function setSaleActive(bool active) external {\n        require(msg.sender == owner || (!setupLocked && msg.sender == admin), \"not owner/admin\");\n        saleActive = active;\n    }\n\n    function lockSetup() external {\n        require(msg.sender == admin || msg.sender == owner, \"not admin/owner\");\n        setupLocked = true;\n        admin = address(0);\n    }\n\n    function transferOwnership(address newOwner) external {\n        require(msg.sender == owner, \"not owner\");\n        require(newOwner != address(0), \"zero\");\n        owner = newOwner;\n    }\n\n    function withdraw() external {\n        require(msg.sender == owner, \"not owner\");\n        (bool ok, ) = owner.call{value: address(this).balance}(\"\");\n        require(ok, \"Withdraw failed\");\n    }\n\n    // ---------- ERC721 transfers ----------\n    function approve(address to, uint256 tokenId) external {\n        address o = ownerOf(tokenId);\n        require(msg.sender == o || isApprovedForAll[o][msg.sender], \"not authorized\");\n        getApproved[tokenId] = to;\n        emit Approval(o, to, tokenId);\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 tokenId) public {\n        require(ownerOf(tokenId) == from, \"not owner\");\n        require(\n            msg.sender == from || msg.sender == getApproved[tokenId] || isApprovedForAll[from][msg.sender],\n            \"not authorized\"\n        );\n        require(to != address(0), \"zero to\");\n        getApproved[tokenId] = address(0);\n        balanceOf[from] -= 1;\n        balanceOf[to] += 1;\n        _owners[tokenId] = 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            require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver\");\n        }\n    }\n\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private returns (bool) {\n        (bool ok, bytes memory ret) = to.call(\n            abi.encodeWithSelector(0x150b7a02, msg.sender, from, tokenId, data)\n        );\n        if (!ok) return false;\n        return ret.length == 4 && abi.decode(ret, (bytes4)) == bytes4(0x150b7a02);\n    }\n\n    function _toString(uint256 value) private pure returns (string memory) {\n        if (value == 0) return \"0\";\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    receive() external payable {}\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"initialOwner","type":"address","internalType":"address"},{"name":"registry_","type":"address","internalType":"address"}],"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":"Minted","type":"event","inputs":[{"name":"buyer","type":"address","indexed":true,"internalType":"address"},{"name":"firstId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"qty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"paidWei","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":"FREE_LIMIT","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_FREE_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_PAID_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_PER_TX","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":"admin","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"costFor","type":"function","inputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeMintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"hasAgentId","type":"function","inputs":[{"name":"a","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":"lockSetup","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"mint","type":"function","inputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"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":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"paidMintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"registry","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentRegistryNFT"}],"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":"saleActive","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setBaseURI","type":"function","inputs":[{"name":"uri","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setSaleActive","type":"function","inputs":[{"name":"active","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setupLocked","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"splitFor","type":"function","inputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"freeShares","type":"uint256","internalType":"uint256"},{"name":"paidShares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","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":"transferOwnership","type":"function","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"withdraw","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"receive","stateMutability":"payable"}],"matchId":"58803578","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-08T05:55:33Z","match":"exact_match","chainId":"56","address":"0x5Ba49f092D83ee86AFa993fD457B6e1Cf53a2458"}