{"sources":{"src/FarmerNFT.sol":{"content":"pragma solidity 0.8.24;\n\ninterface IAgentID { function balanceOf(address owner) external view returns (uint256); }\ninterface IERC721Receiver { function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); }\n\ncontract FarmerNFT {\n    error Owner();\n    error Treasury();\n    error Closed();\n    error Qty();\n    error NotAgent();\n    error WalletLimit();\n    error SoldOut();\n    error Price();\n    error WlClosed();\n    error NotWhitelisted();\n    error WlLimit();\n    error Zero();\n    error MaxRoyalty();\n    error Send();\n    error NoToken();\n    error NotAllowed();\n    error BadTransfer();\n    error Receiver();\n\n    string public constant name = \"Tiny Farm Farmer\";\n    string public constant symbol = \"FARMER\";\n    uint256 public constant MAX_SUPPLY = 1000;\n\n    IAgentID public immutable agentId;\n    address public owner;\n    string public baseURI;\n    uint256 public price;\n    uint256 public maxPerWallet = 5;\n    bool public open;\n    uint256 public minted;\n\n    bytes32 public merkleRoot;\n    bool public whitelistOpen;\n    uint256 public wlPrice;\n    uint256 public wlMaxPerWallet = 1;\n    mapping(address => uint256) public wlMinted;\n\n    address public royaltyReceiver;\n    uint96 public royaltyBps = 500;\n    uint96 public constant MAX_ROYALTY_BPS = 1000;\n\n    mapping(uint256 => address) private _owners;\n    mapping(address => uint256) private _balances;\n    mapping(uint256 => address) private _approvals;\n    mapping(address => mapping(address => bool)) private _operators;\n    mapping(address => uint256) public mintedBy;\n    mapping(uint256 => uint256) private _swap;\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 OwnerChanged(address indexed owner);\n    event RoyaltyReceiverChanged(address indexed receiver);\n    event RoyaltyBpsChanged(uint96 bps);\n    event MerkleRootChanged(bytes32 root);\n\n    modifier onlyOwner() { if (msg.sender != owner) revert Owner(); _; }\n\n    constructor(address agentRegistry, string memory uri, address treasury) {\n        if (treasury == address(0)) revert Treasury();\n        agentId = IAgentID(agentRegistry);\n        owner = msg.sender;\n        baseURI = uri;\n        royaltyReceiver = treasury;\n        emit RoyaltyReceiverChanged(treasury);\n    }\n\n    function mint(uint256 quantity) external payable {\n        if (!open) revert Closed();\n        if (quantity == 0) revert Qty();\n        if (agentId.balanceOf(msg.sender) == 0) revert NotAgent();\n        if (mintedBy[msg.sender] + quantity > maxPerWallet) revert WalletLimit();\n        if (minted + quantity > MAX_SUPPLY) revert SoldOut();\n        if (msg.value != price * quantity) revert Price();\n        mintedBy[msg.sender] += quantity;\n        _mintTo(msg.sender, quantity);\n    }\n\n    function whitelistMint(uint256 quantity, bytes32[] calldata proof) external payable {\n        if (!whitelistOpen) revert WlClosed();\n        if (quantity == 0) revert Qty();\n        if (agentId.balanceOf(msg.sender) == 0) revert NotAgent();\n        if (!_inList(proof, keccak256(abi.encodePacked(msg.sender)))) revert NotWhitelisted();\n        if (wlMinted[msg.sender] + quantity > wlMaxPerWallet) revert WlLimit();\n        if (mintedBy[msg.sender] + quantity > maxPerWallet) revert WalletLimit();\n        if (minted + quantity > MAX_SUPPLY) revert SoldOut();\n        if (msg.value != wlPrice * quantity) revert Price();\n        wlMinted[msg.sender] += quantity;\n        mintedBy[msg.sender] += quantity;\n        _mintTo(msg.sender, quantity);\n    }\n\n    function _inList(bytes32[] calldata proof, bytes32 leaf) private view returns (bool) {\n        bytes32 h = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            bytes32 p = proof[i];\n            h = h <= p ? keccak256(abi.encodePacked(h, p)) : keccak256(abi.encodePacked(p, h));\n        }\n        return h == merkleRoot && merkleRoot != bytes32(0);\n    }\n\n    function _mintTo(address to, uint256 quantity) private {\n        for (uint256 i = 0; i < quantity; i++) {\n            uint256 id = _draw();\n            _owners[id] = to;\n            _balances[to] += 1;\n            emit Transfer(address(0), to, id);\n        }\n    }\n\n    function _draw() private returns (uint256 id) {\n        uint256 left = MAX_SUPPLY - minted;\n        uint256 r = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), msg.sender, minted, block.timestamp))) % left;\n        id = _swap[r] == 0 ? r + 1 : _swap[r];\n        uint256 last = _swap[left - 1] == 0 ? left : _swap[left - 1];\n        _swap[r] = last;\n        minted += 1;\n    }\n\n    function remaining() external view returns (uint256) { return MAX_SUPPLY - minted; }\n    function totalSupply() external view returns (uint256) { return minted; }\n\n    function setOpen(bool v) external onlyOwner { open = v; }\n    function setMerkleRoot(bytes32 v) external onlyOwner { merkleRoot = v; emit MerkleRootChanged(v); }\n    function setWhitelistOpen(bool v) external onlyOwner { whitelistOpen = v; }\n    function setWlPrice(uint256 v) external onlyOwner { wlPrice = v; }\n    function setWlMaxPerWallet(uint256 v) external onlyOwner { wlMaxPerWallet = v; }\n    function setPrice(uint256 v) external onlyOwner { price = v; }\n    function setMaxPerWallet(uint256 v) external onlyOwner { maxPerWallet = v; }\n    function setBaseURI(string calldata v) external onlyOwner { baseURI = v; }\n    function setOwner(address v) external onlyOwner { if (v == address(0)) revert Zero(); owner = v; emit OwnerChanged(v); }\n    function setRoyaltyReceiver(address v) external onlyOwner { if (v == address(0)) revert Zero(); royaltyReceiver = v; emit RoyaltyReceiverChanged(v); }\n    function setRoyaltyBps(uint96 v) external onlyOwner { if (v > MAX_ROYALTY_BPS) revert MaxRoyalty(); royaltyBps = v; emit RoyaltyBpsChanged(v); }\n    function withdraw(address payable to) external onlyOwner { (bool ok,) = to.call{value: address(this).balance}(\"\"); if (!ok) revert Send(); }\n\n    function royaltyInfo(uint256, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount) { return (royaltyReceiver, salePrice * royaltyBps / 10000); }\n    function supportsInterface(bytes4 i) external pure returns (bool) { return i == 0x01ffc9a7 || i == 0x80ac58cd || i == 0x5b5e139f || i == 0x2a55205a; }\n    function balanceOf(address a) external view returns (uint256) { if (a == address(0)) revert Zero(); return _balances[a]; }\n    function ownerOf(uint256 id) public view returns (address o) { o = _owners[id]; if (o == address(0)) revert NoToken(); }\n    function tokenURI(uint256 id) external view returns (string memory) {\n        ownerOf(id);\n        return string(abi.encodePacked(baseURI, _str(id), \".json\"));\n    }\n    function approve(address to, uint256 id) external {\n        address o = ownerOf(id);\n        if (msg.sender != o && !_operators[o][msg.sender]) revert NotAllowed();\n        _approvals[id] = to; emit Approval(o, to, id);\n    }\n    function getApproved(uint256 id) external view returns (address) { ownerOf(id); return _approvals[id]; }\n    function setApprovalForAll(address op, bool ok) external { _operators[msg.sender][op] = ok; emit ApprovalForAll(msg.sender, op, ok); }\n    function isApprovedForAll(address o, address op) external view returns (bool) { return _operators[o][op]; }\n    function transferFrom(address from, address to, uint256 id) public {\n        address o = ownerOf(id);\n        if (o != from || to == address(0)) revert BadTransfer();\n        if (msg.sender != o && _approvals[id] != msg.sender && !_operators[o][msg.sender]) revert NotAllowed();\n        delete _approvals[id];\n        _balances[from] -= 1; _balances[to] += 1; _owners[id] = to;\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 && IERC721Receiver(to).onERC721Received(msg.sender, from, id, data) != IERC721Receiver.onERC721Received.selector) revert Receiver();\n    }\n\n    function _str(uint256 v) private pure returns (string memory) {\n        if (v == 0) return \"0\";\n        uint256 n = v; uint256 d;\n        while (n != 0) { d++; n /= 10; }\n        bytes memory b = new bytes(d);\n        while (v != 0) { d--; b[d] = bytes1(uint8(48 + v % 10)); v /= 10; }\n        return string(b);\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"agentRegistry","type":"address","internalType":"address"},{"name":"uri","type":"string","internalType":"string"},{"name":"treasury","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"BadTransfer","type":"error","inputs":[]},{"name":"Closed","type":"error","inputs":[]},{"name":"MaxRoyalty","type":"error","inputs":[]},{"name":"NoToken","type":"error","inputs":[]},{"name":"NotAgent","type":"error","inputs":[]},{"name":"NotAllowed","type":"error","inputs":[]},{"name":"NotWhitelisted","type":"error","inputs":[]},{"name":"Owner","type":"error","inputs":[]},{"name":"Price","type":"error","inputs":[]},{"name":"Qty","type":"error","inputs":[]},{"name":"Receiver","type":"error","inputs":[]},{"name":"Send","type":"error","inputs":[]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"Treasury","type":"error","inputs":[]},{"name":"WalletLimit","type":"error","inputs":[]},{"name":"WlClosed","type":"error","inputs":[]},{"name":"WlLimit","type":"error","inputs":[]},{"name":"Zero","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":"MerkleRootChanged","type":"event","inputs":[{"name":"root","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"name":"OwnerChanged","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"RoyaltyBpsChanged","type":"event","inputs":[{"name":"bps","type":"uint96","indexed":false,"internalType":"uint96"}],"anonymous":false},{"name":"RoyaltyReceiverChanged","type":"event","inputs":[{"name":"receiver","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":"MAX_ROYALTY_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"name":"MAX_SUPPLY","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":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"o","type":"address","internalType":"address"},{"name":"op","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"maxPerWallet","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"merkleRoot","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"quantity","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"minted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"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":"open","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"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":"price","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"remaining","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"royaltyBps","type":"function","inputs":[],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"name":"royaltyInfo","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"salePrice","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"royaltyAmount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"royaltyReceiver","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"op","type":"address","internalType":"address"},{"name":"ok","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setBaseURI","type":"function","inputs":[{"name":"v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMaxPerWallet","type":"function","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMerkleRoot","type":"function","inputs":[{"name":"v","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setOpen","type":"function","inputs":[{"name":"v","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setOwner","type":"function","inputs":[{"name":"v","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setPrice","type":"function","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRoyaltyBps","type":"function","inputs":[{"name":"v","type":"uint96","internalType":"uint96"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRoyaltyReceiver","type":"function","inputs":[{"name":"v","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setWhitelistOpen","type":"function","inputs":[{"name":"v","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setWlMaxPerWallet","type":"function","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setWlPrice","type":"function","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"i","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"},{"name":"whitelistMint","type":"function","inputs":[{"name":"quantity","type":"uint256","internalType":"uint256"},{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"payable"},{"name":"whitelistOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"withdraw","type":"function","inputs":[{"name":"to","type":"address","internalType":"address payable"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"wlMaxPerWallet","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"wlMinted","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"wlPrice","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"matchId":"57557671","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-10-29T15:40:31Z","match":"exact_match","chainId":"56","address":"0x039aD3cd794b1Af0323EBEACf7404252336bA81f"}