{"sources":{"src/HackedPassV2.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\ninterface IAgentRegistryMine {\n    function balanceOf(address who) external view returns (uint256);\n}\n\ninterface IERC721ReceiverV2 {\n    function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4);\n}\n\n/// @title HackedPassV2 — NFT HACKED, supply 4.444, pembayaran 100% BNB.\n///\n/// Aturan (semua on-chain):\n///   1. $HACKED holder (Merkle proof, snapshot token HACKED) → FREE, maks 4 / wallet\n///   2. .ai holder (Agent ID di registry SPACE ID)        → FREE, maks 2 / wallet\n///   3. non-.ai    → publicPrice / NFT (0,0014 BNB), beli 1 atau 2, total maks 2 / wallet\n///   4. Siapa pun melebihi jatah → extraPrice / NFT (0,002 BNB), total maks 10 / wallet\n///\n/// Dana BNB terkumpul HANYA bisa ditarik FEE_RECIPIENT (immutable, = wallet w1).\n/// Selain itu: tidak ada owner, tidak ada mint tersembunyi, supply keras 4444.\ncontract HackedPassV2 {\n    string public constant name = \"HACKED\";\n    string public constant symbol = \"HACKED\";\n\n    uint256 public immutable maxSupply;      // 4444\n    uint256 public immutable freeAi;         // 2\n    uint256 public immutable freeV2;         // 4\n    uint256 public immutable publicPrice;    // BNB per NFT untuk non-.ai\n    uint256 public immutable extraPrice;     // BNB per NFT ekstra\n    uint256 public constant HARD_MAX = 10;   // total semua jalur per wallet\n\n    address public immutable agentRegistry;  // SPACE ID Agent ID (ERC-721)\n    address public immutable feeRecipient;   // BAW w1\n    bytes32 public immutable v2Root;         // Merkle root 25 alamat V2\n    string public baseURI;\n\n    uint256 public totalSupply;\n    mapping(address => uint256) internal _balanceOf;\n    mapping(uint256 => address) internal _ownerOf;\n    mapping(uint256 => address) public getApproved;\n    mapping(address => mapping(address => bool)) public isApprovedForAll;\n    mapping(address => uint256) public minted;      // total per wallet (semua jalur)\n    mapping(address => bool) public freeDone;       // jatah free sudah dipakai\n    mapping(address => uint256) public paidPublic;  // NFT bayar jalur public (maks 2)\n    uint256 public bnbBalance;\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    event Minted(address indexed who, uint256 indexed id, uint8 path, uint256 mintedTotal);\n    event FeesWithdrawn(address indexed to, uint256 amount);\n\n    error AlreadyClaimed();\n    error SoldOut();\n    error NotMinted();\n    error NotAuthorized();\n    error ZeroAddress();\n    error BadReceiver();\n    error NotFeeRecipient();\n    error CapReached(uint256 current, uint256 limit);\n    error WrongValue(uint256 expected, uint256 got);\n    error BadProof();\n    error BadAmount();\n    error NotEligiblePublic();\n\n    uint8 constant PATH_V2 = 1;\n    uint8 constant PATH_AI = 2;\n    uint8 constant PATH_PUBLIC = 3;\n    uint8 constant PATH_EXTRA = 4;\n\n    constructor(\n        uint256 maxSupply_, uint256 freeAi_, uint256 freeV2_,\n        uint256 publicPrice_, uint256 extraPrice_,\n        address agentRegistry_, address feeRecipient_, bytes32 v2Root_, string memory baseURI_\n    ) {\n        require(maxSupply_ > 0 && freeAi_ > 0 && freeV2_ > freeAi_, \"BAD_PARAMS\");\n        require(publicPrice_ > 0 && extraPrice_ > 0, \"BAD_PRICE\");\n        require(agentRegistry_ != address(0), \"ZERO_REG\");\n        require(feeRecipient_ != address(0), \"ZERO_FEE\");\n        maxSupply = maxSupply_;\n        freeAi = freeAi_;\n        freeV2 = freeV2_;\n        publicPrice = publicPrice_;\n        extraPrice = extraPrice_;\n        agentRegistry = agentRegistry_;\n        feeRecipient = feeRecipient_;\n        v2Root = v2Root_;\n        baseURI = baseURI_;\n    }\n\n    // ---- helper -------------------------------------------------------------\n\n    function _isV2(bytes32[] memory proof) internal view returns (bool) {\n        if (v2Root == bytes32(0) || proof.length == 0) return false;\n        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender))));\n        bytes32 h = leaf;\n        for (uint256 i = 0; i < proof.length; i++) {\n            bytes32 p = proof[i];\n            if (h < p) h = keccak256(bytes.concat(h, p));\n            else h = keccak256(bytes.concat(p, h));\n        }\n        return h == v2Root;\n    }\n\n    function isAiHolder(address who) public view returns (bool) {\n        return IAgentRegistryMine(agentRegistry).balanceOf(who) > 0;\n    }\n\n    function freeAllowance(bytes32[] memory proof) public view returns (uint256) {\n        if (_isV2(proof)) return freeV2;\n        if (isAiHolder(msg.sender)) return freeAi;\n        return 0;\n    }\n\n    function remainingFor(address who) external view returns (uint256) {\n        uint256 m = minted[who];\n        return m >= HARD_MAX ? 0 : HARD_MAX - m;\n    }\n\n    // ---- 1) free: V2 (4) atau .ai (2) ---------------------------------------\n\n    function claimFree(bytes32[] calldata proof) external returns (uint256 lastId) {\n        if (freeDone[msg.sender]) revert AlreadyClaimed();\n        uint256 allow = freeAllowance(proof);\n        if (allow == 0) revert BadProof();\n        if (totalSupply + allow > maxSupply) revert SoldOut();\n\n        freeDone[msg.sender] = true;\n        uint8 path = allow == freeV2 ? PATH_V2 : PATH_AI;\n        for (uint256 i = 0; i < allow; i++) {\n            lastId = ++totalSupply;\n            _ownerOf[lastId] = msg.sender;\n            _balanceOf[msg.sender] += 1;\n            minted[msg.sender] += 1;\n            emit Transfer(address(0), msg.sender, lastId);\n            emit Minted(msg.sender, lastId, path, minted[msg.sender]);\n        }\n    }\n\n    // ---- 2) public non-.ai: publicPrice / NFT, beli 1 atau 2, maks 2 ------\n\n    /// @notice Beli NFT di harga publik. `n` = 1 atau 2 (maks 2 per wallet),\n    ///         biaya tepat n x publicPrice. Beli 1 biji = harga publik juga.\n    function claimPublic(uint256 n) external payable returns (uint256 lastId) {\n        if (freeAllowance(new bytes32[](0)) != 0) revert NotEligiblePublic();\n        uint256 left = 2 - paidPublic[msg.sender];\n        if (left == 0) revert AlreadyClaimed();\n        if (n == 0 || n > left) revert BadAmount();\n        if (minted[msg.sender] + n > HARD_MAX) revert CapReached(minted[msg.sender], HARD_MAX);\n        if (totalSupply + n > maxSupply) revert SoldOut();\n        uint256 cost = publicPrice * n;\n        if (msg.value != cost) revert WrongValue(cost, msg.value);\n\n        bnbBalance += msg.value;\n        for (uint256 i = 0; i < n; i++) {\n            lastId = ++totalSupply;\n            _ownerOf[lastId] = msg.sender;\n            _balanceOf[msg.sender] += 1;\n            minted[msg.sender] += 1;\n            paidPublic[msg.sender] += 1;\n            emit Transfer(address(0), msg.sender, lastId);\n            emit Minted(msg.sender, lastId, PATH_PUBLIC, minted[msg.sender]);\n        }\n    }\n\n    // ---- 3) ekstra: extraPrice / NFT, total semua jalur maks 10 ------------\n\n    function buyExtra(uint256 n) external payable returns (uint256 lastId) {\n        if (n == 0) revert BadAmount();\n        if (minted[msg.sender] + n > HARD_MAX) revert CapReached(minted[msg.sender], HARD_MAX);\n        if (totalSupply + n > maxSupply) revert SoldOut();\n        uint256 cost = extraPrice * n;\n        if (msg.value != cost) revert WrongValue(cost, msg.value);\n\n        bnbBalance += msg.value;\n        for (uint256 i = 0; i < n; i++) {\n            lastId = ++totalSupply;\n            _ownerOf[lastId] = msg.sender;\n            _balanceOf[msg.sender] += 1;\n            minted[msg.sender] += 1;\n            emit Transfer(address(0), msg.sender, lastId);\n            emit Minted(msg.sender, lastId, PATH_EXTRA, minted[msg.sender]);\n        }\n    }\n\n    // ---- 4) tarik dana — hanya FEE_RECIPIENT -------------------------------\n\n    function withdrawBnb() external {\n        if (msg.sender != feeRecipient) revert NotFeeRecipient();\n        uint256 amt = bnbBalance;\n        bnbBalance = 0;\n        (bool ok, ) = feeRecipient.call{value: amt}(\"\");\n        require(ok, \"BNB_SEND\");\n        emit FeesWithdrawn(feeRecipient, amt);\n    }\n\n    // ---- ERC-721 minimal ----------------------------------------------------\n\n    function balanceOf(address owner) external view returns (uint256) {\n        require(owner != address(0), \"ZERO_OWNER\");\n        return _balanceOf[owner];\n    }\n\n    function ownerOf(uint256 id) public view returns (address owner) {\n        owner = _ownerOf[id];\n        if (owner == address(0)) revert NotMinted();\n    }\n\n    function tokenURI(uint256 id) external view returns (string memory) {\n        if (_ownerOf[id] == address(0)) revert NotMinted();\n        return string.concat(baseURI, _toString(id), \".json\");\n    }\n\n    function approve(address spender, uint256 id) external {\n        address owner = _ownerOf[id];\n        if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) revert NotAuthorized();\n        getApproved[id] = spender;\n        emit Approval(owner, spender, id);\n    }\n\n    function setApprovalForAll(address operator, bool ok) external {\n        isApprovedForAll[msg.sender][operator] = ok;\n        emit ApprovalForAll(msg.sender, operator, ok);\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 ZeroAddress();\n        if (msg.sender != from && !isApprovedForAll[from][msg.sender] && msg.sender != getApproved[id]) {\n            revert NotAuthorized();\n        }\n        unchecked { _balanceOf[from] -= 1; }\n        _balanceOf[to] += 1;\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            if (IERC721ReceiverV2(to).onERC721Received(msg.sender, from, id, data)\n                != IERC721ReceiverV2.onERC721Received.selector) {\n                revert BadReceiver();\n            }\n        }\n    }\n\n    function supportsInterface(bytes4 iid) external pure returns (bool) {\n        return iid == 0x01ffc9a7     // ERC-165\n            || iid == 0x80ac58cd     // ERC-721\n            || iid == 0x5b5e139f;    // ERC-721 Metadata (name/symbol/tokenURI)\n    }\n\n    function _toString(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\";\n        bytes memory b = new bytes(32);\n        uint256 len;\n        while (v != 0) {\n            b[len++] = bytes1(uint8(48 + (v % 10)));\n            v /= 10;\n        }\n        bytes memory out = new bytes(len);\n        for (uint256 i = 0; i < len; i++) out[i] = b[len - 1 - i];\n        return string(out);\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"maxSupply_","type":"uint256","internalType":"uint256"},{"name":"freeAi_","type":"uint256","internalType":"uint256"},{"name":"freeV2_","type":"uint256","internalType":"uint256"},{"name":"publicPrice_","type":"uint256","internalType":"uint256"},{"name":"extraPrice_","type":"uint256","internalType":"uint256"},{"name":"agentRegistry_","type":"address","internalType":"address"},{"name":"feeRecipient_","type":"address","internalType":"address"},{"name":"v2Root_","type":"bytes32","internalType":"bytes32"},{"name":"baseURI_","type":"string","internalType":"string"}],"stateMutability":"nonpayable"},{"name":"AlreadyClaimed","type":"error","inputs":[]},{"name":"BadAmount","type":"error","inputs":[]},{"name":"BadProof","type":"error","inputs":[]},{"name":"BadReceiver","type":"error","inputs":[]},{"name":"CapReached","type":"error","inputs":[{"name":"current","type":"uint256","internalType":"uint256"},{"name":"limit","type":"uint256","internalType":"uint256"}]},{"name":"NotAuthorized","type":"error","inputs":[]},{"name":"NotEligiblePublic","type":"error","inputs":[]},{"name":"NotFeeRecipient","type":"error","inputs":[]},{"name":"NotMinted","type":"error","inputs":[]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"WrongValue","type":"error","inputs":[{"name":"expected","type":"uint256","internalType":"uint256"},{"name":"got","type":"uint256","internalType":"uint256"}]},{"name":"ZeroAddress","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":"FeesWithdrawn","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Minted","type":"event","inputs":[{"name":"who","type":"address","indexed":true,"internalType":"address"},{"name":"id","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"path","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"mintedTotal","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":"id","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"HARD_MAX","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"agentRegistry","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"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":"owner","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":"bnbBalance","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"buyExtra","type":"function","inputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"lastId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"claimFree","type":"function","inputs":[{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"lastId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"claimPublic","type":"function","inputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"lastId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"extraPrice","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"feeRecipient","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"freeAi","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeAllowance","type":"function","inputs":[{"name":"proof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeDone","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"freeV2","type":"function","inputs":[],"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":"isAiHolder","type":"function","inputs":[{"name":"who","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":"maxSupply","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"minted","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":"owner","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"paidPublic","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"publicPrice","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"remainingFor","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"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":"ok","type":"bool","internalType":"bool"}],"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":"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":"v2Root","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"withdrawBnb","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"58366985","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-04T13:05:55Z","match":"exact_match","chainId":"56","address":"0xCD355D1191Ce9849B3A935C821A66d9DF37cFE77"}