{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"919beca5-cb88-477e-90ba-3e00f91301d1","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"46dedd1a00502b47d117baca5a067a1b5825d403d411e4551d70204bcae34693","dependsOn":["build_contract_project","manifest"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","tools":[]},"key":"adversarial_review","kind":"code","role":"review","skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","state":"accepted"},{"acceptedSubmissionHash":"3874fff04021e9d74a8597797f6672963256fa44de41257b7230113f8cbb165d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"0f3e7566c3ff8e87fc95936b79ba455be33eea683bb01a6834a4a4d43e58e1df","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"0f3e7566c3ff8e87fc95936b79ba455be33eea683bb01a6834a4a4d43e58e1df","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"1ce128dc818f99af04f250ddbe4f6fff2a934eafe02c9b6a80acdaf9ba088ff3","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"}],"objective":"A trustless nft transfer/escrow system for moving nfts between two people securely.\nAlso build and go live with a frontend for using it.\n\nIn which it works as follows-\n\nThe person sending the nft uses the interface to set up a transaction that allows the nft/s to be transfered if an only if and only when, the receiver submits a matching transaction.\n\nThe sender's transaction must include the nft's unique descriptor(the contract address of the nft collection and the nft's token ID) and the specifc assets they expect to receive in return. If crypto that should be a token contract address and an amount, if an nft that should be the unique descriptor.\n\nThe sender signs the transaction and the smart contract listens for the matching transaction from the receiver which must include exactly everything the sender requested and nothing additional, and then it moves the assets.\n\nHave a time limit of 30 minutes for the transactions to both be sent and if they are not, the sending transaction becomes invalid and any matching transaction the receiver tries to send produces an error and fails.\n\nHave security surronding each transaction pair such that it is not possible for any outside party to hijack, alter, piggyback on, cause to fail, re-route, delay, etc either of the transactions.\n\nAdd any other security or ease-of-use features you think are needed, as long as they don't conflict with any of the above.\n\nMake the contract be as gwei-thrifty as reasonably possible without sacrificing quality.","parentJobId":null,"planHash":"916427484b53177d961736468eb5fea37a89cb9ad3abb86fcf6fe9d2b556717d","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"919beca5-cb88-477e-90ba-3e00f91301d1","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-220-trustless-nft-transfer-escrow-system"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50975","feedbackHash":"a459725c988ca277201f6e3654de306e2eb0fa01ecb7d98667db2803bb36bfd9","nodeKey":"adversarial_review","submissionHash":"46dedd1a00502b47d117baca5a067a1b5825d403d411e4551d70204bcae34693","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51300","feedbackHash":"92cac5829be215206c15f9bcfe4792ff593052b5c6c1806247a4a373cf733ded","nodeKey":"build_contract_project","submissionHash":"4a222b61ee57cf72dbd1a9a08baeaf69bf5a54089f0030b5163b3cb68ab2c424","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"50997","feedbackHash":"9b2bffb81e116bb828478923e5e849056e1ea5cec5eb5a3c4507dddab80f06d1","nodeKey":"build_contract_project","submissionHash":"3874fff04021e9d74a8597797f6672963256fa44de41257b7230113f8cbb165d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50959","feedbackHash":"5c1f2f0f36858d40fc095f439f4c9776dd10b0f36614f8351b625330bc0ada20","nodeKey":"manifest","submissionHash":"1ce128dc818f99af04f250ddbe4f6fff2a934eafe02c9b6a80acdaf9ba088ff3","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"7e009007a96b3db1d6645f872c8e3bbba823d79f5300f43ee7142b6373131618","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"55db0c952030e89f56dff4297e16d83ff5b9c1a80849c33240706565070383fb","device":"468e82a89b9bfe18","findings":[],"hash":"1ce128dc818f99af04f250ddbe4f6fff2a934eafe02c9b6a80acdaf9ba088ff3","nodeId":"8e6322c1-ee14-41f2-80b7-83d1de551084","outcome":"completed","summary":"`launch.json` is written and verified. Only that file changed in the tracked tree.\n\n**What the manifest declares**\n\n- **Token**: identifier `Token`, name Pairwise, symbol PAIR, 18 decimals, no constructor arguments. This matches the accepted source, which mints the full fixed supply to the factory caller and has no admin path.\n- **Application contracts**: a single entry, `NFTSwap`, with an empty constructor argument list. The accepted contract has no constructor at all, no owner, and no token dependency, so no `$owner`, `$token` or `$contract` reference applies.\n- **Pool**: paired against native ETH, fee 3000, tick spacing 60, and the 1:1 legacy sqrtPriceX96 default. The notes state that the pinned policy's market cap overrides this price when present.\n- **Notes**: describe the escrow behaviour, the 30-minute expiry, the exact-match fill rule, the compiler settings, and the frontend hookup steps.\n\n**Checks run**\n\n- Schema-level validation of every field, pattern, uniqueness rule and the notes length passed.\n- `forge build --offline` and `forge test --offline` passed with all 40 project tests green.\n- The two protected floor suites were run from a scratch copy against the compiled Token and NFTSwap creation code, using the factory-as-deployer CREATE2 setup and the manifest's declared decimals. All 8 tests passed, including the supply preservation and forbidden-opcode scans.\n\nThe untracked dotfiles shown by git status are sandbox device nodes, not repository changes. The scratch copy of the protected tests lives under test/scratch and is discarded before submission.","treeHash":"43f8e369a81dbd9b10146c5c79d55f5eb6f88786","usage":{"cachedInputTokens":389631,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":6470,"runtime":"claude","turns":13,"wallClockMs":127247}},{"artifacts":[],"attempt":2,"bundleHash":"3210b97e3dba38f5d09b11379682bb35673889eb6f309ecd3b4a015a3809793d","device":"593a9c894818e368","findings":[],"hash":"3874fff04021e9d74a8597797f6672963256fa44de41257b7230113f8cbb165d","nodeId":"1c460a1e-b7d0-48a9-a3b1-f3ae91c9910b","outcome":"completed","summary":"Implemented the escrow contracts, fixed-supply token, wallet frontend, tests, and deployment documentation.\n\nPassed offline: `forge build`, `forge test` (39 tests), `forge fmt --check`, all 8 pinned checks, and 5 frontend tests.\n\n[Local frontend preview](http://127.0.0.1:8080) is running. Public launch remains pending contract deployment and a hosting destination.\n\n[README and deployment instructions](/home/imd2/.identitymd/work/919beca5-cb88-477e-90ba-3e00f91301d1/1c460a1e-b7d0-48a9-a3b1-f3ae91c9910b/README.md)","treeHash":"cb90bb562135ce3e8bc44d50875378feef55fc4c","usage":{"cachedInputTokens":1332480,"inputTokens":79754,"model":"gpt-6-astra","outputTokens":42948,"runtime":"codex","turns":9,"wallClockMs":1347287}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"377843575071cdb1","findings":[{"description":"send() awaits the original ContractTransactionResponse without a timeout or replacement tracking. In the vendored ethers 6.13.5, wrapping the signer's response as a ContractTransactionResponse loses its replacement-scanning start block, so wait() continues watching only the original hash. A successful wallet fee replacement therefore never completes create(), even though the NFT is already escrowed. app.mjs keeps busy=true, disabling creation, loading, settlement and cancellation, and never saves or displays the new offer or replacement hash. Reloading the page and manually retrieving the replacement hash from the wallet permits recovery, so this is a frontend availability/recovery defect rather than permanent asset loss. The integration test uses automining and does not exercise transaction replacement. Track replacements and recover the confirmed receipt, with a way to leave the pending state when a transaction is replaced or cancelled.","line":31,"path":"frontend/client.mjs","reproduction":"Reproduced on local Anvil using the actual SwapClient and contracts compiled with the repository's Solidity settings. Deploy NFTSwap, Mock721 and Mock20; mint Mock721 token ID 0 to maker A and approve NFTSwap. Configure a ready SwapClient for A. Disable automining, then call client.create(B, [{kind:0, token:Mock721, id:'0', amount:'1'}], [{kind:1, token:Mock20, id:'0', amount:'100'}]). After the client reports the pending creation hash, submit from A a replacement with identical nonce, to, data and value, doubling maxFeePerGas and setting maxPriorityFeePerGas to twice its original value plus 1 gwei. Mine the replacement and eight further blocks. Expected: the client returns the confirmed offer using the replacement receipt and releases the UI's busy state. Actual: the replacement receipt has status 1, offers(1).status is Open, and Mock721.ownerOf(0) is NFTSwap, but client.create remains unresolved. The original receipt is null and client.load(originalHash) reports a missing transaction, while client.load(replacementHash) returns offer 1. As a control, waiting on original.replaceableTransaction(startBlock) detects TRANSACTION_REPLACED with reason 'repriced' and the successful replacement receipt; the client's wait remains pending. In the browser this is triggered by the wallet's Speed up action while creation is pending.","severity":"low","title":"Speeding up a transaction leaves the frontend waiting indefinitely"}],"hash":"46dedd1a00502b47d117baca5a067a1b5825d403d411e4551d70204bcae34693","nodeId":"0e6e3211-1634-48eb-bbb9-3290ab91f9d8","outcome":"completed","summary":"Wrote [`.imd-findings.json`](/home/worker/.identitymd/work/919beca5-cb88-477e-90ba-3e00f91301d1/0e6e3211-1634-48eb-bbb9-3290ab91f9d8/.imd-findings.json).\n\nOne verified **low-severity** finding: speeding up a transaction leaves the frontend stuck pending despite successful escrow.\n\nNo substantiated contract vulnerabilities found. Implementation and tests remain unchanged.","treeHash":null,"usage":{"cachedInputTokens":586240,"inputTokens":67722,"model":"gpt-6-astra","outputTokens":8373,"runtime":"codex","turns":5,"wallClockMs":288338}},{"artifacts":[],"attempt":1,"bundleHash":"a066bbb252d1fb655510e24db63ada360cf36d772b045fb6999ce1d9fe1cf638","device":"05778e691c371384","findings":[],"hash":"4a222b61ee57cf72dbd1a9a08baeaf69bf5a54089f0030b5163b3cb68ab2c424","nodeId":"1c460a1e-b7d0-48a9-a3b1-f3ae91c9910b","outcome":"completed","summary":"Implemented the escrow, fixed-supply token, and wallet frontend with exact matching, atomic settlement, 30-minute expiry, and refunds.\n\nOffline checks pass: `forge build`, all 38 Solidity tests, and `forge fmt --check`. Frontend unit and browser tests also pass.\n\nPublic launch remains pending hosting and blockchain deployment details. Setup, assumptions, and operational responsibilities are in [README.md](/root/.identitymd/work/919beca5-cb88-477e-90ba-3e00f91301d1/1c460a1e-b7d0-48a9-a3b1-f3ae91c9910b/README.md).","treeHash":"ee7a6ce58fb15dd2efcbb997c13e81dff68cab9b","usage":{"cachedInputTokens":1589120,"inputTokens":83987,"model":"gpt-6-astra","outputTokens":46016,"runtime":"codex","turns":8,"wallClockMs":1462310}}],"verification":[{"checks":[{"durationMs":1381,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.31s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/NFTSwap.sol:123:13\n    │\n123 │         if (block.timestamp >= offer.expiresAt) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:24:9\n   │\n24 │         token.transfer(address(7), amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:27:9\n   │\n27 │         token.transfer(address(this), 0);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:34:9\n   │\n34 │         token.transferFrom(address(this), address(8), 100);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/NFTSwap.t.sol:38:28\n   │\n38 │             require(!ok && bytes4(reason) == NFTSwap.Reentrancy.selector, \"unguarded callback\");\n   │                            ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes4' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/NFTSwap.sol:106:28\n    │\n106 │         uint64 expiresAt = uint64(block.timestamp + OFFER_LIFETIME);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/mocks/Assets.sol:92:39\n   │\n92 │             callbackRejected = !ok && bytes4(reason) == bytes4(keccak256(\"Reentrancy()\"));\n   │                                       ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes4' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ test/Invariant.t.sol:54:46\n   │\n54 │         if (status != NFTSwap.Status.Open || block.timestamp >= expiry) return;\n   │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/NFTSwap.sol:175:48\n    │\n175 │                 if (ok && data.length >= 32 && bytes32(data) == bytes32(uint256(1))) revert InvalidAsset();\n    │                                                ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:39:9\n   │\n39 │         token.transferFrom(address(this), address(8), 3);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:45:9\n   │\n45 │         token.transfer(address(0), 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:49:9\n   │\n49 │         token.transfer(address(7), 1e27 + 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:51:9\n   │\n51 │         token.transferFrom(address(7), address(8), 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:55:9\n   │\n55 │         token.transfer(address(this), 100);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\n","passed":true},{"durationMs":560,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConserves(uint96) (runs: 256, μ: 49249, ~: 49720)\nLogs:\n  Bound result 228162514264337593543950255\n\n[PASS] test_adminSelectorsCannotMintEvenForDeployer() (gas: 25466)\n[PASS] test_allowanceAndInfiniteApproval() (gas: 75903)\n[PASS] test_factoryConstructionSupplyAndRuntimeFloor() (gas: 5525014)\n[PASS] test_fixedSupplyAndMetadata() (gas: 17317)\n[PASS] test_invalidTransfersAndApprovals() (gas: 20768)\n[PASS] test_selfTransferDoesNotMint() (gas: 14210)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 17.11ms (14.02ms CPU time)\n\nRan 31 tests for test/NFTSwap.t.sol:NFTSwapTest\n[PASS] testFuzz_exactPaymentConservation(uint96,uint16) (runs: 256, μ: 245050, ~: 245158)\nLogs:\n  Bound result 508681\n  Bound result 1255\n\n[PASS] test_canFillOneSecondBeforeExpiry() (gas: 223270)\n[PASS] test_cancelBeforeExpiryAndNoReplay() (gas: 170763)\n[PASS] test_cancelCannotSubstituteCollateral() (gas: 198796)\n[PASS] test_contractMakerCanRefundWithoutReceivingCallback() (gas: 663189)\n[PASS] test_deadlineExclusiveAndRefundAfterExpiry() (gas: 166090)\n[PASS] test_duplicateCollateralCannotBeEscrowedTwice() (gas: 248100)\n[PASS] test_duplicateNFTERC20AndCrossBasketRejected() (gas: 151120)\n[PASS] test_emptyAndOversizeBaskets() (gas: 693129)\n[PASS] test_erc20CallbackCannotReenter() (gas: 569334)\n[PASS] test_escrowsThenSettlesExactERC20() (gas: 247552)\n[PASS] test_failedApprovalAndFakeTransferRollbackCreation() (gas: 264133)\n[PASS] test_falseMalformedFeeBonusTokensRollback() (gas: 453068)\n[PASS] test_fillCannotReplayOrRefund() (gas: 236987)\n[PASS] test_invalidAssetFieldsAndEOA() (gas: 123259)\n[PASS] test_lateMatchingTransactionNeverReactivates() (gas: 174067)\n[PASS] test_lateNFTTransferFailureRollsBackPaymentAndStatus() (gas: 449683)\n[PASS] test_maximumBasketSettles() (gas: 3962961)\n[PASS] test_missingOffer() (gas: 36431)\n[PASS] test_missingPaymentApprovalRollsBackAndCanRetry() (gas: 250709)\n[PASS] test_mixedBasketAndSeveralNFTs() (gas: 444203)\n[PASS] test_nativeCurrencyAndDirectSafeDepositsRejected() (gas: 189726)\n[PASS] test_nftForNFT() (gas: 254438)\n[PASS] test_noReturnERC20Supported() (gas: 246849)\n[PASS] test_outsiderCannotFillCancelOrStealApprovedNFT() (gas: 295517)\n[PASS] test_receiverReentrancyAllEntryPointsBlocked() (gas: 1625027)\n[PASS] test_rejectingReceiverCannotBlockRefundOrOtherOffer() (gas: 895323)\n[PASS] test_rejectsERC721MasqueradingAsCurrency() (gas: 94151)\n[PASS] test_rejectsMissingAdditionalReorderedAndChangedTerms() (gas: 418268)\n[PASS] test_uniqueIdsAndIndependentOffers() (gas: 335112)\n[PASS] test_zeroSelfAndEscrowCounterpartyRejected() (gas: 55259)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 17.16ms (27.91ms CPU time)\n\nRan 2 tests for test/Invariant.t.sol:SwapInvariantTest\n[PASS] invariant_custodyMatchesOfferState() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| SwapHandler | cancel       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | create       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | elapse       | 384   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | fill         | 425   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | unauthorized | 397   | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\n[PASS] invariant_paymentConservationAndNoStrandedCurrency() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| SwapHandler | cancel       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | create       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | elapse       | 384   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | fill         | 425   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | unauthorized | 397   | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 485.76ms (686.11ms CPU time)\n\nRan 3 test suites in 486.50ms (520.03ms CPU time): 40 tests passed, 0 failed, 0 skipped (40 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"1ce128dc818f99af04f250ddbe4f6fff2a934eafe02c9b6a80acdaf9ba088ff3","verifiedTreeHash":"43f8e369a81dbd9b10146c5c79d55f5eb6f88786","verifierVersion":"0.1.0+bb39ded9"},{"checks":[{"durationMs":1307,"exitCode":0,"name":"build","output":"Compiling 25 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.25s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ test/Invariant.t.sol:54:46\n   │\n54 │         if (status != NFTSwap.Status.Open || block.timestamp >= expiry) return;\n   │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:24:9\n   │\n24 │         token.transfer(address(7), amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/mocks/Assets.sol:92:39\n   │\n92 │             callbackRejected = !ok && bytes4(reason) == bytes4(keccak256(\"Reentrancy()\"));\n   │                                       ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes4' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:27:9\n   │\n27 │         token.transfer(address(this), 0);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/NFTSwap.sol:123:13\n    │\n123 │         if (block.timestamp >= offer.expiresAt) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:34:9\n   │\n34 │         token.transferFrom(address(this), address(8), 100);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:39:9\n   │\n39 │         token.transferFrom(address(this), address(8), 3);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/NFTSwap.t.sol:38:28\n   │\n38 │             require(!ok && bytes4(reason) == NFTSwap.Reentrancy.selector, \"unguarded callback\");\n   │                            ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes4' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:45:9\n   │\n45 │         token.transfer(address(0), 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:49:9\n   │\n49 │         token.transfer(address(7), 1e27 + 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:51:9\n   │\n51 │         token.transferFrom(address(7), address(8), 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Token.t.sol:55:9\n   │\n55 │         token.transfer(address(this), 100);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/NFTSwap.sol:106:28\n    │\n106 │         uint64 expiresAt = uint64(block.timestamp + OFFER_LIFETIME);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/NFTSwap.sol:175:48\n    │\n175 │                 if (ok && data.length >= 32 && bytes32(data) == bytes32(uint256(1))) revert InvalidAsset();\n    │                                                ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":557,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConserves(uint96) (runs: 256, μ: 49241, ~: 49720)\nLogs:\n  Bound result 177841003271337192305590317\n\n[PASS] test_adminSelectorsCannotMintEvenForDeployer() (gas: 25466)\n[PASS] test_allowanceAndInfiniteApproval() (gas: 75903)\n[PASS] test_factoryConstructionSupplyAndRuntimeFloor() (gas: 5525014)\n[PASS] test_fixedSupplyAndMetadata() (gas: 17317)\n[PASS] test_invalidTransfersAndApprovals() (gas: 20768)\n[PASS] test_selfTransferDoesNotMint() (gas: 14210)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 10.30ms (18.15ms CPU time)\n\nRan 31 tests for test/NFTSwap.t.sol:NFTSwapTest\n[PASS] testFuzz_exactPaymentConservation(uint96,uint16) (runs: 256, μ: 245113, ~: 245158)\nLogs:\n  Bound result 589212\n  Bound result 413\n\n[PASS] test_canFillOneSecondBeforeExpiry() (gas: 223270)\n[PASS] test_cancelBeforeExpiryAndNoReplay() (gas: 170763)\n[PASS] test_cancelCannotSubstituteCollateral() (gas: 198796)\n[PASS] test_contractMakerCanRefundWithoutReceivingCallback() (gas: 663189)\n[PASS] test_deadlineExclusiveAndRefundAfterExpiry() (gas: 166090)\n[PASS] test_duplicateCollateralCannotBeEscrowedTwice() (gas: 248100)\n[PASS] test_duplicateNFTERC20AndCrossBasketRejected() (gas: 151120)\n[PASS] test_emptyAndOversizeBaskets() (gas: 693129)\n[PASS] test_erc20CallbackCannotReenter() (gas: 569334)\n[PASS] test_escrowsThenSettlesExactERC20() (gas: 247552)\n[PASS] test_failedApprovalAndFakeTransferRollbackCreation() (gas: 264133)\n[PASS] test_falseMalformedFeeBonusTokensRollback() (gas: 453068)\n[PASS] test_fillCannotReplayOrRefund() (gas: 236987)\n[PASS] test_invalidAssetFieldsAndEOA() (gas: 123259)\n[PASS] test_lateMatchingTransactionNeverReactivates() (gas: 174067)\n[PASS] test_lateNFTTransferFailureRollsBackPaymentAndStatus() (gas: 449683)\n[PASS] test_maximumBasketSettles() (gas: 3962961)\n[PASS] test_missingOffer() (gas: 36431)\n[PASS] test_missingPaymentApprovalRollsBackAndCanRetry() (gas: 250709)\n[PASS] test_mixedBasketAndSeveralNFTs() (gas: 444203)\n[PASS] test_nativeCurrencyAndDirectSafeDepositsRejected() (gas: 189726)\n[PASS] test_nftForNFT() (gas: 254438)\n[PASS] test_noReturnERC20Supported() (gas: 246849)\n[PASS] test_outsiderCannotFillCancelOrStealApprovedNFT() (gas: 295517)\n[PASS] test_receiverReentrancyAllEntryPointsBlocked() (gas: 1625027)\n[PASS] test_rejectingReceiverCannotBlockRefundOrOtherOffer() (gas: 895323)\n[PASS] test_rejectsERC721MasqueradingAsCurrency() (gas: 94151)\n[PASS] test_rejectsMissingAdditionalReorderedAndChangedTerms() (gas: 418268)\n[PASS] test_uniqueIdsAndIndependentOffers() (gas: 335112)\n[PASS] test_zeroSelfAndEscrowCounterpartyRejected() (gas: 55259)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 16.38ms (29.81ms CPU time)\n\nRan 2 tests for test/Invariant.t.sol:SwapInvariantTest\n[PASS] invariant_custodyMatchesOfferState() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| SwapHandler | cancel       | 411   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | create       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | elapse       | 396   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | fill         | 416   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | unauthorized | 404   | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\n[PASS] invariant_paymentConservationAndNoStrandedCurrency() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| SwapHandler | cancel       | 411   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | create       | 421   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | elapse       | 396   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | fill         | 416   | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| SwapHandler | unauthorized | 404   | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 477.21ms (703.93ms CPU time)\n\nRan 3 test suites in 478.01ms (503.89ms CPU time): 40 tests passed, 0 failed, 0 skipped (40 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"3874fff04021e9d74a8597797f6672963256fa44de41257b7230113f8cbb165d","verifiedTreeHash":"cb90bb562135ce3e8bc44d50875378feef55fc4c","verifierVersion":"0.1.0+bb39ded9"},{"checks":[],"detail":"start commit produces tree 4b825dc642cb but its accepted dependencies produce cb90bb562135","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"4a222b61ee57cf72dbd1a9a08baeaf69bf5a54089f0030b5163b3cb68ab2c424","verifiedTreeHash":"ee7a6ce58fb15dd2efcbb997c13e81dff68cab9b","verifierVersion":"0.1.0+bb39ded9"}]}