{"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":"dec04d23-9b4c-454c-9593-cc0a6df6eac7","kind":"skill:build-contract-project","nodes":[{"acceptedSubmissionHash":"a1aed6b687302ea90826b660a1194c1208680628b20656b2206f8d0853bd94b4","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","state":"accepted"}],"objective":"Pawn update: FloorRelay plus site and keeper fixes. Goal: oracle answers bought on the explorer (signed with no consumer) are accepted, and nothing on the site needs to buy requests from the browser.\n\n1. FloorRelay (immutable, no owner). Constants: IMD_ATTESTER = the attester address api.imd.fun currently publishes; CHAIN = 1. isValidSignature(hash, sig): decode sig as (attestation struct per OracleAttestation v2, imdSignature). Compute the zero-consumer EIP-712 digest of the struct (domain \"IdentityMD Oracle\", \"2\", chainId 1, verifyingContract 0x0) and require ECDSA recovers to IMD_ATTESTER. Compute the digest of the same struct for the caller's domain (verifyingContract = msg.sender) and require it equals hash. Return the magic value only if both hold; otherwise a failure value, never revert. No other functions.\nPawnShop and MilestoneBurn are unchanged. Confirm their checks accept an ERC-1271 contract attester and that newest-wins on issuedAt still rejects older answers.\n\n2. Site.\n- Remove the in-page oracle purchase flow everywhere (it fails: purchase routes are not CORS-enabled). Replace with a request-id field: fetch the attestation from api.imd.fun, verify attester and question hash client-side, pack (attestation, signature) in the relay format, submit.\n- Post floor (Setup and the public Refresh floor on Borrow) and the Burn section use that flow. Borrow page copy: \"Floor older than 26 hours? Buy the floor question on explorer.imd.fun (0.5 IMD), paste the request id here, post it, and collect the 0.001 ETH bounty.\" Show the exact question text with a copy button.\n- Setup: a \"Switch attester to FloorRelay\" button that queues the change on PawnShop (and on MilestoneBurn if it has its own attester), showing the 48-hour countdown and the current attester. Until the switch lands, show a notice that only answers signed for the contract are accepted.\n- Keep owner controls gated to the owner wallet; read-only owner state for everyone.\n\n3. Keeper. Post floors using the relay format from configured request ids; drop any purchase logic. Keep startAuction and alerts.\n\n4. Tests: genuine zero-consumer attestation passes for PawnShop and MilestoneBurn; another signer fails; struct/hash mismatch fails; older issuedAt rejected; relay never reverts; site packing matches the relay decoding. Update README, docs/SETUP-AND-KEEPER.md and keeper/README.md.\n\n5. Build web/ to dist/ and publish the site under the same name.","parentJobId":"c0f35007-65d3-45b3-8e39-4ea31424729e","planHash":"b0250f615d7aa2b030830c4405af6380ff792689276faf8de5944be2025e6308","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"699b8539-76a2-4c37-b11e-ba4d269487ad","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1031-workflow-frontend-stage-context"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51380","feedbackHash":"f2867883314086317768592917f8a284181db6ff8f809911256008573b5d5a46","nodeKey":"build_contract_project","submissionHash":"a1aed6b687302ea90826b660a1194c1208680628b20656b2206f8d0853bd94b4","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"c38995ceb427c66efe1deb5ae8365c05e3f583abeaaddcd65978f5f1f2ba17a3","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"81ab2552dcaa561ccba0cd736d1800619567b9e68dcdfddee71c518a148c67e9","device":"f7cb61cceaa27e78","findings":[],"hash":"a1aed6b687302ea90826b660a1194c1208680628b20656b2206f8d0853bd94b4","nodeId":"eb85af6d-58b3-4c54-940b-b14f0a66609c","outcome":"completed","summary":"Implemented FloorRelay, request-id site/keeper flows, owner-gated switching, tests, documentation, and rebuilt `dist/`. PawnShop and MilestoneBurn remain unchanged.\n\nChecks passed: `forge build`, 105 Foundry tests, `forge fmt --check`, plus web, keeper, and browser tests.\n\nPublication was attempted under the existing name but refused: **503 `member_sites_closed`**.\n\nRelay deployment and the 48-hour switch remain operational steps. Floor answers still require at least 26-hour validity.","treeHash":"907311ea6e10a24cb5737d519a9f69d66541d067","usage":{"cachedInputTokens":4607232,"inputTokens":154985,"model":"gpt-6-astra","outputTokens":34040,"runtime":"codex","turns":9,"wallClockMs":1042380}}],"verification":[{"checks":[{"durationMs":89923,"exitCode":0,"name":"build","output":"Compiling 89 files with Solc 0.8.26\nSolc 0.8.26 finished in 89.72s\nCompiler run successful with warnings:\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/FloorRelay.t.sol:225:5:\n    |\n225 |     function _packSigned(OracleAttestation.Attestation memory a) internal view returns (bytes memory) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/MilestoneBurn.sol:32:67\n   │\n32 │     constructor(address token_, address setter_, address signer_, address shop_) OracleAttestationConsumer(signer_) {\n   │                                                                   ━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/MilestoneBurn.sol:53:46\n   │\n53 │                 || a.agreed > a.panelSize || a.issuedAt > block.timestamp || block.timestamp - a.issuedAt > 26 hours\n   │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/MilestoneBurn.sol:53:78\n   │\n53 │                 || a.agreed > a.panelSize || a.issuedAt > block.timestamp || block.timestamp - a.issuedAt > 26 hours\n   │                                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MilestoneBurn.sol:67:9\n   │\n67 │         emit Burned(amount, cap, a.requestId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/PawnShop.sol:132:17\n    │\n132 │     constructor(address owner_, address token_, address weth_, address attester_)\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[arbitrary-send-eth]: ETH is sent to a user-controlled destination; restrict the destination or the caller\n   ╭▸ src/PullPayments.sol:31:22\n   │\n31 │         (bool ok,) = receiver.call{value: amount}(\"\");\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/CollateralVault.sol:105:45\n    │\n105 │                 || m.nonce == bytes32(0) || m.expiresAt <= block.timestamp || bytes(m.relayOrigin).length == 0\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/CollateralVault.sol:110:9\n    │\n110 │         emit WorkerAuthorized(workerDigest, m.expiresAt);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/PullPayments.sol:33:9\n   │\n33 │         emit Claimed(msg.sender, receiver, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/CollateralVault.sol:122:20\n    │\n122 │                 || block.timestamp > workerExpiresAt || !IPawnShop(pawnShop).loanActive(loanId)\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/CollateralVault.sol:131:9\n    │\n131 │         nonReentrant\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/CollateralVault.sol:128:22\n    │\n128 │     function callFor(address target, bytes calldata data)\n    │                      ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/CollateralVault.sol:143:9\n    │\n143 │         emit Called(target, bytes4(data));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/CollateralVault.sol:143:29\n    │\n143 │         emit Called(target, bytes4(data));\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://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/CollateralVault.sol:147:64\n    │\n147 │     function withdrawETH(uint256 amount) external onlyBorrower nonReentrant {\n    │                                                                ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/CollateralVault.sol:152:81\n    │\n152 │     function withdrawToken(address token, uint256 amount) external onlyBorrower nonReentrant {\n    │                                                                                 ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/CollateralVault.sol:168:9\n    │\n168 │         emit Released(receiver);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:175:34\n    │\n175 │         if (queuedAt[op] == 0 || block.timestamp < queuedAt[op] || block.timestamp > queuedAt[op] + EXECUTION_WINDOW) {\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:175:68\n    │\n175 │         if (queuedAt[op] == 0 || block.timestamp < queuedAt[op] || block.timestamp > queuedAt[op] + EXECUTION_WINDOW) {\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/PawnShop.sol:259:34\n    │\n259 │     function executeFeeRecipient(address recipient) external {\n    │                                  ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/PawnShop.sol:270:36\n    │\n270 │     function executeDiscountModule(address module) external {\n    │                                    ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:292:46\n    │\n292 │                 || a.agreed > a.panelSize || a.issuedAt > block.timestamp\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:293:20\n    │\n293 │                 || block.timestamp - a.issuedAt > FLOOR_MAX_AGE || a.issuedAt <= floors[collection].issuedAt\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:306:36\n    │\n306 │         if (f.lastBountyAt == 0 || block.timestamp >= uint256(f.lastBountyAt) + FLOOR_BOUNTY_INTERVAL) {\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/PullPayments.sol:21:9\n   │\n21 │         emit Credited(account, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:310:9\n    │\n310 │         emit FloorSubmitted(collection, price, a.issuedAt, a.expiresAt);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/PawnShop.sol:307:30\n    │\n307 │             f.lastBountyAt = uint64(block.timestamp);\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://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:315:32\n    │\n315 │         return f.price != 0 && f.issuedAt <= block.timestamp && block.timestamp - f.issuedAt <= FLOOR_MAX_AGE\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:315:65\n    │\n315 │         return f.price != 0 && f.issuedAt <= block.timestamp && block.timestamp - f.issuedAt <= FLOOR_MAX_AGE\n    │                                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:316:16\n    │\n316 │             && block.timestamp <= f.expiresAt;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:354:9\n    │\n354 │         emit Pawned(id, msg.sender, collection, tokenId, address(vault), principal, fee, loan.due);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:365:9\n    │\n365 │         emit Repaid(id);\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:378:9\n    │\n378 │         emit Extended(id, termId, fee, loan.due);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:393:13\n    │\n393 │         if (block.timestamp <= loan.due + GRACE) revert GracePeriod();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:399:9\n    │\n399 │         emit AuctionStarted(id, loan.auctionFloor, block.timestamp);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:409:13\n    │\n409 │         if (elapsed <= 3 days) {\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:412:13\n    │\n412 │         if (elapsed < 10 days) {\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PawnShop.sol:431:13\n    │\n431 │             block.timestamp < loan.auctionStarted + WRITE_OFF_DELAY\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:438:9\n    │\n438 │         emit AuctionWrittenOff(id, loan.principal);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PawnShop.sol:459:9\n    │\n459 │         emit AuctionBought(id, msg.sender, receiver, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LendingPool.sol:92:17\n   │\n92 │             if (uint256(donationCheckpoints[mid].start) + VESTING <= block.timestamp) low = mid + 1;\n   │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:168:9\n    │\n168 │         emit Deposit(msg.sender, receiver, msg.value, shares);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `shortfallReserve` is updated\n    ╭▸ src/LendingPool.sol:196:9\n    │\n196 │         IWETH(asset()).withdraw(assets);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:319:26\n    │\n319 │         if (amount != 0) emit EmptyPoolReserve(amount);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:199:9\n    │\n199 │         emit Withdraw(msg.sender, receiver, account, assets, shares);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:202:55\n    │\n202 │     function borrow(uint256 amount) external onlyShop nonReentrant {\n    │                                                       ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:208:9\n    │\n208 │         emit Borrowed(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:212:66\n    │\n212 │     function settle(uint256 principal) external payable onlyShop nonReentrant {\n    │                                                                  ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:223:9\n    │\n223 │         emit AuctionLossMarked(id, loss);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:226:85\n    │\n226 │     function settleAuction(uint256 id, uint256 principal) external payable onlyShop nonReentrant {\n    │                                                                                     ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:241:9\n    │\n241 │         emit Settled(principal, msg.value, covered, gap - covered);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:244:53\n    │\n244 │     function receiveFee() external payable onlyShop nonReentrant {\n    │                                                     ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:247:9\n    │\n247 │         emit FeeReceived(msg.value);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:251:58\n    │\n251 │     function receiveRecovery() external payable onlyShop nonReentrant {\n    │                                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:254:9\n    │\n254 │         emit RecoveryReceived(msg.value);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:262:13\n    │\n262 │             emit ReserveAdded(msg.value);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/LendingPool.sol:268:53\n    │\n268 │     function addReserve() external payable onlyShop nonReentrant {\n    │                                                     ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:271:9\n    │\n271 │         emit ReserveAdded(msg.value);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LendingPool.sol:279:9\n    │\n279 │         emit Donated(msg.sender, msg.value, donationCheckpoints.length - 1);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LendingPool.sol:283:42\n    │\n283 │         if (value > type(uint128).max || block.timestamp > type(uint64).max) {\n    │                                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LendingPool.sol:293:17\n    │\n293 │             if (last.start == block.timestamp && count > vestingStartIndex) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LendingPool.sol:297:61\n    │\n297 │                 donationCheckpoints.push(DonationCheckpoint(uint64(block.timestamp), amount, weight));\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://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LendingPool.sol:300:57\n    │\n300 │             donationCheckpoints.push(DonationCheckpoint(uint64(block.timestamp), amount, weight));\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://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LendingPool.sol:330:34\n    │\n330 │         if (pendingCapAt == 0 || block.timestamp < pendingCapAt) revert TimelockPending();\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":21809,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/OracleConsumerConformance.t.sol:OracleConsumerConformanceTest\n[PASS] test_acceptsFreshUintSignatureFromVectorKey() (gas: 202125)\n[PASS] test_acceptsTheProtocolSignature() (gas: 19508)\n[PASS] test_burnConsumerDigestMatchesTheProtocol() (gas: 9407531)\n[PASS] test_digestMatchesTheProtocol() (gas: 13167)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.56ms (4.69ms CPU time)\n\nRan 2 tests for test/SetupFlows.t.sol:SetupFlowsTest\n[PASS] test_burnSetupRejectsLowCapAndForeignConsumerThenBurnsOnce() (gas: 478014)\n[PASS] test_ownerPinsFloorThenPublicWalletPostsAndClaimsBounty() (gas: 502970)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.71ms (1.64ms CPU time)\n\nRan 6 tests for test/Governance.t.sol:GovernanceTest\n[PASS] test_allChangesWait48HoursAndCancel() (gas: 637434)\n[PASS] test_collectionLimitsDisableAndHashInitialization() (gas: 1496859)\n[PASS] test_explicitOwnershipTwoStepAndNoRenounce() (gas: 173359)\n[PASS] test_hardBoundsAndNonzeroAddresses() (gas: 221481)\n[PASS] test_hashRotationInvalidatesFloorButKeepsAuctionPrice() (gas: 2511696)\n[PASS] test_nonSeatLoanAndInsufficientIdleRollBackCustody() (gas: 7739554)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 5.61ms (2.55ms CPU time)\n\nRan 4 tests for test/MilestoneBurn.t.sol:MilestoneBurnTest\n[PASS] test_deploymentRejectsUnrelatedSignerSource() (gas: 12999)\n[PASS] test_rejectsStaleExpiredWrongDomainAndInsufficientPanel() (gas: 354292)\n[PASS] test_rotationFollowsShopTimelockWithoutOwnerOrWithdrawalPower() (gas: 638093)\n[PASS] test_unsetOneTimeSetupAndThreshold() (gas: 650004)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.62ms (2.39ms CPU time)\n\nRan 6 tests for test/CollateralVault.t.sol:CollateralVaultTest\n[PASS] test_auctionStopsCallsButBorrowerRetainsRewardWithdrawals() (gas: 2701441)\n[PASS] test_authorizationCannotNameBorrowerOtherTokenOrNonSeat() (gas: 2487376)\n[PASS] test_callForRewardsWithdrawalsAndBlockedTargets() (gas: 3044310)\n[PASS] test_indirectCollateralRemovalRollsBackAndNFTOnlyLeavesViaShop() (gas: 3554660)\n[PASS] test_onlyRegisteredTypedWorkerDigestValidAndExpires() (gas: 2371429)\n[PASS] test_revokeAndCloseDisableAuthorization() (gas: 2628247)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 5.92ms (2.84ms CPU time)\n\nRan 5 tests for test/ReviewScope.t.sol:ReviewScopeTest\n[PASS] test_bountyCopied() (gas: 271647)\n[PASS] test_fixedMaximumPrincipal() (gas: 200110)\n[PASS] test_newWindowHashRejected() (gas: 75954)\n[PASS] test_ownerValuationCanBorrowAllIdle() (gas: 2455658)\n[PASS] test_underwaterExtensions() (gas: 20676906)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 16.15ms (13.04ms CPU time)\n\nRan 2 tests for test/LaunchToken.t.sol:LaunchTokenTest\n[PASS] testFuzz_exactTransfers(uint256) (runs: 256, μ: 89182, ~: 89614)\nLogs:\n  Bound result 925669307339\n\n[PASS] test_supplyMetadataAndTransfer() (gas: 171792)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 72.31ms (72.63ms CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_allRuntimeTypesMeetSizeAndForbiddenOpcodeFloor() (gas: 33277867)\n[PASS] test_factoryDeploymentPreservesSupplyAndExplicitOwner() (gas: 342104)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 75.71ms (73.33ms CPU time)\n\nRan 11 tests for test/PawnShop.t.sol:PawnShopTest\n[PASS] testFuzz_principalFeeAndFundConservation(uint256,uint8) (runs: 256, μ: 2541168, ~: 2541296)\nLogs:\n  Bound result 5206727181242267503\n  Bound result 1\n\n[PASS] test_auctionCurveSurplusOverpaymentAndDuplicate() (gas: 2894781)\n[PASS] test_auctionUsesStoredStaleFloorAndSocializesGap() (gas: 2735068)\n[PASS] test_claimFailureAndReentrancyPreserveLiabilities() (gas: 2665047)\n[PASS] test_discountAndModuleChangeKeepOldCommitment() (gas: 5274220)\n[PASS] test_failedNFTSettlementIsAtomic() (gas: 2950218)\n[PASS] test_feeWaterfallFillsBountyReserveThenShortfallThenRecipient() (gas: 44819048)\n[PASS] test_limitsIdleLiquidityAndDuplicateNFT() (gas: 4358596)\n[PASS] test_pauseStalenessAndInvalidActions() (gas: 2725121)\n[PASS] test_pawnRepayAndConservation() (gas: 2626833)\n[PASS] test_termSnapshotAndLateExtension() (gas: 5119362)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 84.20ms (110.60ms CPU time)\n\nRan 19 tests for test/ReviewRegression.t.sol:ReviewRegressionTest\n[PASS] testFuzz_maxRedeemNeverExceedsIdle(uint256,uint256) (runs: 256, μ: 662925, ~: 663731)\nLogs:\n  Bound result 256943843482716701\n  Bound result 139080881530111267\n\n[PASS] test_certainLossBeforeExitAndLaterSettlement() (gas: 3104777)\n[PASS] test_disablingCollectionCancelsQueuedReenable() (gas: 156029)\n[PASS] test_emptyPoolDonationRejectedAndFeeGoesToReserve() (gas: 479971)\n[PASS] test_feeSandwichHasNoImmediateGainAndFeeVests() (gas: 2577333)\n[PASS] test_lastShareExitRetiresVestingAndNewStreamStillWorks() (gas: 700856)\n[PASS] test_longSignedExpiryCannotVetoDailyUpdates() (gas: 238947)\n[PASS] test_lossMarksNetReserveAndReconcileMultipleAuctions() (gas: 5325281)\n[PASS] test_missingCollateralCanBeWrittenOffImmediately() (gas: 2573149)\n[PASS] test_missingNFTRepaysAndClearsCommitment() (gas: 2589496)\n[PASS] test_newQueueSupersedesAndExpires() (gas: 381532)\n[PASS] test_oneWeiEntitlementAfterPartialRedemptionRemainsWithdrawable() (gas: 669493)\n[PASS] test_onlyShopCanMarkOrSettleDebt() (gas: 119881)\n[PASS] test_roundingAllowsAllBackedAssetsToExit() (gas: 576860)\n[PASS] test_seizedNFTZeroPriceBooksGapWithoutPayingIssuer() (gas: 2862325)\n[PASS] test_shortExpiryCannotReplaceValidFloor() (gas: 2474975)\n[PASS] test_stuckAuctionLossSharedAfterWriteOff() (gas: 2721070)\n[PASS] test_transferRestrictionDoesNotBlockFinancialWriteOff() (gas: 3258199)\n[PASS] test_writeOffUnsoldAuctionUnlocksAndLateRecoveryVests() (gas: 3307600)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 120.86ms (103.50ms CPU time)\n\nRan 8 tests for test/LendingPool.t.sol:LendingPoolTest\n[PASS] testFuzz_roundTripNeverCreatesAssets(uint256) (runs: 256, μ: 285897, ~: 285814)\nLogs:\n  Bound result 925669307339\n\n[PASS] test_accessCapAndFailedClaim() (gas: 564585)\n[PASS] test_directDonationInflationCannotStealVictimDeposit() (gas: 475055)\n[PASS] test_donationVestsExactlyAndDoesNotResetOnNewDonation() (gas: 743015)\n[PASS] test_dustDonationsCannotBlockDonationsOrWithdrawals() (gas: 9730308)\n[PASS] test_erc4626DepositMintWithdrawRedeemAndNativeClaim() (gas: 773407)\n[PASS] test_nativeWithdrawRequiresShareAllowance() (gas: 406240)\n[PASS] test_shortfallReserveExcludedAndConsumedBeforeShares() (gas: 959512)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 122.43ms (126.41ms CPU time)\n\nRan 11 tests for test/FloorRelay.t.sol:FloorRelayTest\n[PASS] testFuzz_malformedOffsetsLengthsAndNarrowFields(uint256,uint8) (runs: 256, μ: 19727, ~: 19394)\n[PASS] testFuzz_neverRevertsForArbitraryPayload(bytes32,bytes) (runs: 256, μ: 9810, ~: 9759)\n[PASS] test_anotherSignerAndStructMismatchFailBothConsumers() (gas: 102898)\n[PASS] test_everyTruncationAndBadSignatureReturnsFailure() (gas: 74358153)\n[PASS] test_fullFloorSubmissionAndOlderIssuedAtRejection() (gas: 11121200)\n[PASS] test_governedSwitchAndAutomaticBurnSync() (gas: 10925871)\n[PASS] test_hashMustBelongToCallerAndChainOne() (gas: 56476)\n[PASS] test_realFloorStillNeeds26HourLifetime() (gas: 132111)\n[PASS] test_realSignatureCompletesBurnWithExplicitTestQuestion() (gas: 293582)\n[PASS] test_realZeroConsumerSignatureAcceptedByBothConsumerVerifiers() (gas: 78463)\n[PASS] test_sitePackingMatchesSolidityAndVerifies() (gas: 53653)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 127.15ms (331.01ms CPU time)\n\nRan 5 tests for test/Oracle.t.sol:OracleTest\n[PASS] test_floorCannotShortenStoredExpiry() (gas: 155528)\n[PASS] test_freshUpdatesAndOneBountyPer24Hours() (gas: 462892)\n[PASS] test_rejectsWrongQuestionChainPanelTypeAndTime() (gas: 616599)\n[PASS] test_replayTamperingWrongSignerAndWrongDomain() (gas: 343515)\n[PASS] test_signedRequestCannotBeReusedWithNewTimestamp() (gas: 178838)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 139.45ms (3.55ms CPU time)\n\nRan 4 tests for test/LockDiscount.t.sol:LockDiscountTest\n[PASS] testFuzz_discountRoundsUpAndNeverExceedsBase(uint256,uint8) (runs: 256, μ: 145558, ~: 182787)\nLogs:\n  Bound result 782205487404687307781069530324\n  Bound result 0\n\n[PASS] test_manySameTierLoansDoNotMultiplyCommitment() (gas: 4430904)\n[PASS] test_tiersLargestCommitmentAndRelease() (gas: 717951)\n[PASS] test_unauthorizedAndInsufficientLockedActions() (gas: 122483)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 141.38ms (143.76ms CPU time)\n\nRan 9 tests for test/AdversarialBoundaries.t.sol:AdversarialBoundariesTest\n[PASS] testFuzz_auctionPriceIsMonotoneAndUnderbidRollsBack(uint256,uint256) (runs: 1000, μ: 3150221, ~: 3150406)\nLogs:\n  Bound result 218\n  Bound result 433302\n\n[PASS] testFuzz_inexactRepaymentLeavesDebtCollateralAndCommitmentIntact(uint256) (runs: 1000, μ: 2892805, ~: 2892959)\nLogs:\n  Bound result 5811\n\n[PASS] testFuzz_malformedSignedAnswersNeverConsumeRequests(uint256) (runs: 1000, μ: 301254, ~: 301442)\nLogs:\n  Bound result 75\n\n[PASS] test_claimZeroRecipientAndSecondClaimCannotSpendOtherCredits() (gas: 2285606)\n[PASS] test_discountThresholdOneWeiAndMaximumFeeDoNotOverflow() (gas: 775914)\n[PASS] test_failedExtensionRollsBackTheNewDiscountTier() (gas: 3374582)\n[PASS] test_floorChangesDoNotRepriceAnAuctionAlreadyStarted() (gas: 2626640)\n[PASS] test_minimumPrincipalAndOneWeiBelowIt() (gas: 2454387)\n[PASS] test_nativeZeroOperationsAndInvalidSettlementAreAtomic() (gas: 2470206)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 146.85ms (409.45ms CPU time)\n\nRan 1 test for test/PawnInvariant.t.sol:PawnInvariantTest\n[PASS]\nPawnInvariantTest invariants:\n[PASS] invariant_ETHCreditsAreFullyBacked\n[PASS] invariant_debtAndCollateralFollowLoanState\n[PASS] invariant_poolBookMatchesCashAndDebt\n PawnInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+-------------------+-------+---------+----------╮\n| Contract    | Selector          | Calls | Reverts | Discards |\n+==============================================================+\n| PawnHandler | advanceAndPublish | 1017  | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | claim             | 1042  | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | deposit           | 975   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | donate            | 1071  | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | lockOrUnlock      | 999   | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | pawn              | 1047  | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | repayOrAuction    | 1032  | 0       | 0        |\n|-------------+-------------------+-------+---------+----------|\n| PawnHandler | withdraw          | 1009  | 0       | 0        |\n╰-------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 500\n  Bound result 4975000000000013531\n  Bound result 242\n  Bound result 499210479212827\n  Bound result 60\n  Bound result 21\n  Bound result 6\n  Bound result 4186\n  Bound result 1000000000000000000\n  Bound result 4\n  Bound result 300000000000000000\n  Bound result 15895\n  Bound result 1000499210479232899\n  Bound result 55222565436617553482068407\n  Bound result 1000000000000000\n  Bound result 100000000000000000\n  Bound result 4233600000\n  Bound result 2517837089\n  Bound result 14423200\n  Bound result 6\n  Bound result 90000000000000000\n  Bound result 100000000000000000\n  Bound result 97200\n  Bound result 167568\n  Bound result 4975000000000010900\n  Bound result 11118\n  Bound result 2999994\n  Bound result 1962\n  Bound result 81714272112120207\n  Bound result 49\n  Bound result 128\n  Bound result 60\n  Bound result 164802500743714\n  Bound result 91142027303451149\n  Bound result 640000\n  Bound result 4975000000000004026\n  Bound result 5260\n  Bound result 1010315\n  Bound result 4975000000000008823\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.75s (3.75s CPU time)\n\nRan 1 test for test/VaultCustodyInvariant.t.sol:VaultCustodyInvariantTest\n[PASS]\nVaultCustodyInvariantTest invariants:\n[PASS] invariant_custodyAndWorkerAuthorizationFollowTerminalState\n[PASS] invariant_vaultRewardsAndCreditsRemainBorrowerProperty\n VaultCustodyInvariantTest invariants (runs: 256, calls: 20480, reverts: 0)\n\n╭---------------------+-------------+-------+---------+----------╮\n| Contract            | Selector    | Calls | Reverts | Discards |\n+================================================================+\n| VaultCustodyHandler | advance     | 2612  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | authorize   | 2588  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | claim       | 2569  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | close       | 2580  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | fund        | 2530  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | rejectTheft | 2573  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | revoke      | 2491  | 0       | 0        |\n|---------------------+-------------+-------+---------+----------|\n| VaultCustodyHandler | withdraw    | 2537  | 0       | 0        |\n╰---------------------+-------------+-------+---------+----------╯\n\nLogs:\n  Bound result 3763\n  Bound result 4448\n  Bound result 1355011\n  Bound result 0\n  Bound result 0\n  Bound result 1523458\n  Bound result 0\n  Bound result 314\n  Bound result 0\n  Bound result 0\n  Bound result 1589\n  Bound result 13222\n  Bound result 423012\n  Bound result 1932116\n  Bound result 192\n  Bound result 376\n  Bound result 7000\n  Bound result 5000000000000000000\n  Bound result 344838894539167347\n  Bound result 0\n  Bound result 4312\n  Bound result 1959987\n  Bound result 2827\n  Bound result 2500\n  Bound result 7389\n  Bound result 9487\n  Bound result 0\n  Bound result 325\n  Bound result 2980925\n  Bound result 236193343038044654\n  Bound result 98554\n  Bound result 2262778\n  Bound result 852612\n  Bound result 85645870019816329\n  Bound result 1015\n  Bound result 0\n  Bound result 6667\n  Bound result 13910\n  Bound result 402549\n  Bound result 7\n  Bound result 16\n  Bound result 1072355\n  Bound result 26148432\n  Bound result 26678596008409879686852094\n  Bound result 26678601008409879686863795\n  Bound result 9000000000000000000\n  Bound result 15071\n  Bound result 2560106\n  Bound result 26148432\n  Bound result 26678601008409879686877406\n  Bound result 22999681481306357\n  Bound result 26678605008409879686852564\n  Bound result 0\n  Bound result 5000000000000003763\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.69s (7.68s CPU time)\n\nRan 4 tests for test/PoolAccountingInvariant.t.sol:PoolAccountingInvariantTest\n[PASS]\nPoolAccountingInvariantTest invariants:\n[PASS] invariant_allShareBalancesAndPullCreditsAreAccountedFor\n[PASS] invariant_cashDebtReservesAndVestingMatchIndependentLedger\n PoolAccountingInvariantTest invariants (runs: 256, calls: 20480, reverts: 0)\n\n╭-----------------------+-----------------------+-------+---------+----------╮\n| Contract              | Selector              | Calls | Reverts | Discards |\n+============================================================================+\n| PoolAccountingHandler | advance               | 1915  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | borrow                | 1905  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | claim                 | 1825  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | deposit               | 1893  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | donate                | 1866  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | feeOrReserve          | 1874  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | redeem                | 1957  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | settle                | 1761  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | transferShares        | 1820  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | unauthorizedShopCalls | 1807  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| PoolAccountingHandler | withdraw              | 1857  | 0       | 0        |\n╰-----------------------+-----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1800000000\n  Bound result 8186\n  Bound result 432000\n  Bound result 1721321966\n  Bound result 10379\n  Bound result 11315\n  Bound result 3320572652\n  Bound result 255\n  Bound result 15782\n  Bound result 81\n  Bound result 79\n  Bound result 31\n  Bound result 83\n  Bound result 13\n  Bound result 685076\n  Bound result 18\n  Bound result 17\n  Bound result 150692865055459987\n  Bound result 112073483374816811\n  Bound result 223495\n  Bound result 5448525848231276887\n  Bound result 2313\n  Bound result 999999999999999991\n  Bound result 12345\n  Bound result 605862\n  Bound result 3784\n  Bound result 1217\n  Bound result 4420\n  Bound result 75\n  Bound result 20\n  Bound result 10418\n  Bound result 3390\n  Bound result 185\n  Bound result 2659260247507229508370400\n  Bound result 2592000000\n  Bound result 709511289769358636096162\n  Bound result 9573\n  Bound result 737749336177274464\n  Bound result 10000\n  Bound result 5890\n  Bound result 7465\n  Bound result 4670\n  Bound result 2241\n  Bound result 136627350109\n  Bound result 922872240286847338\n  Bound result 4241\n  Bound result 5183\n  Bound result 2\n  Bound result 1108\n  Bound result 92240510829748331\n  Bound result 40000000000000000\n  Bound result 300\n  Bound result 29335933505250810\n  Bound result 540143798861292000375\n  Bound result 1928028034\n  Bound result 3665\n  Bound result 5102000000000000000\n  Bound result 61\n  Bound result 1250571159459155378\n  Bound result 7110\n  Bound result 9996\n  Bound result 7772\n  Bound result 73242\n  Bound result 11788\n  Bound result 3627\n  Bound result 884\n  Bound result 259200\n  Bound result 1102639\n  Bound result 700000000000000000\n  Bound result 93600\n  Bound result 15616\n  Bound result 1418\n  Bound result 5246\n  Bound result 432000\n  Bound result 6048000000\n  Bound result 7016\n  Bound result 24\n  Bound result 1247\n  Bound result 2204\n  Bound result 9556\n  Bound result 2900000000000000000\n  Bound result 953495054\n  Bound result 1791495012\n  Bound result 16034\n  Bound result 1209\n  Bound result 13494\n  Bound result 13494\n  Bound result 691200\n  Bound result 999999434341769069464613\n  Bound result 3156480618411229475118249\n  Bound result 3788320652286115209481014\n\n[PASS] test_feesAndDonationsVestAsIndependentTranches() (gas: 2938276)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 200000000000000000\n  Bound result 302400\n  Bound result 700000000000000000\n  Bound result 302400\n  Bound result 691200\n  Bound result 1000000000000000000000000\n  Bound result 1000000000000000000000000\n  Bound result 1000000000000000000000000\n\n[PASS] test_lastShareExitRetiresIncomeAndSameTimestampReentryStartsNewVesting() (gas: 3489337)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 200000000000000000\n  Bound result 500000000000000000\n  Bound result 1000000000000000000000000\n  Bound result 1000000000000000000000000\n  Bound result 3000000000000000000000000\n  Bound result 1000000000000000000\n  Bound result 100000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 691200\n  Bound result 1000000000000000000000000\n\n[PASS] test_partialLossAndFinalSettlementReconcileLedger() (gas: 1911521)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 3000000000000000000\n  Bound result 1000000000000000000\n  Bound result 900000000000000000\n  Bound result 2000000000000000000\n  Bound result 2000000000000000000\n  Bound result 691200\n  Bound result 1000000000000000000000000\n  Bound result 1000000000000000000000000\n  Bound result 1000000000000000000000000\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 10.08s (10.08s CPU time)\n\nRan 1 test for test/TokenCustodyInvariant.t.sol:TokenCustodyInvariantTest\n[PASS]\nTokenCustodyInvariantTest invariants:\n[PASS] invariant_fixedSupplyAndAllCustodyMatchTheLedger\n[PASS] invariant_largestCommitmentAndEveryTierCountMatchOpenLoans\n TokenCustodyInvariantTest invariants (runs: 256, calls: 20480, reverts: 0)\n\n╭---------------------+--------------------+-------+---------+----------╮\n| Contract            | Selector           | Calls | Reverts | Discards |\n+=======================================================================+\n| TokenCustodyHandler | advance            | 2079  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | commit             | 2047  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | donate             | 2027  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | lock               | 2070  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | rejectOverUnlock   | 2075  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | rejectUnauthorized | 2052  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | release            | 2025  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | transfer           | 2022  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | tryBurn            | 1975  | 0       | 0        |\n|---------------------+--------------------+-------+---------+----------|\n| TokenCustodyHandler | unlock             | 2108  | 0       | 0        |\n╰---------------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5000000000000000000000000\n  Bound result 300\n  Bound result 20000000000000000000000000\n  Bound result 300\n  Bound result 1299\n  Bound result 300000000000000000000000000\n  Bound result 5000000000000000000\n  Bound result 276\n  Bound result 955\n  Bound result 2353797\n  Bound result 576\n  Bound result 93600\n  Bound result 294999994999999999999999999\n  Bound result 3854863046\n  Bound result 2723\n  Bound result 5807\n  Bound result 227875\n  Bound result 1928028033\n  Bound result 10000000000000000000\n  Bound result 90000\n  Bound result 151630618350059329276608512\n  Bound result 900000000000000000\n  Bound result 51\n  Bound result 9462\n  Bound result 460192\n  Bound result 36492436467852573441310443\n  Bound result 2223922\n  Bound result 518400\n  Bound result 18\n  Bound result 1067922364\n  Bound result 15776\n  Bound result 8660\n  Bound result 7200\n  Bound result 4153\n  Bound result 1836046\n  Bound result 46842038911504560070\n  Bound result 169\n  Bound result 4348\n  Bound result 184257797988157689060713089\n  Bound result 3041169675973448491958970\n  Bound result 2670\n  Bound result 2827\n  Bound result 1803401830\n  Bound result 17\n  Bound result 4714\n  Bound result 739225856536157148635584832409\n  Bound result 5244\n  Bound result 189257802988157692915576082\n  Bound result 20000000000000000000007200\n  Bound result 1803409422\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 21.70s (21.70s CPU time)\n\nRan 19 test suites in 21.70s (44.29s CPU time): 105 tests passed, 0 failed, 0 skipped (105 total tests)\n","passed":true},{"durationMs":171,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"CollateralVault.authorizeWorker((bytes32,address,uint256,bytes32,uint64,string))\",\"CollateralVault.callFor(address,bytes)\",\"CollateralVault.claim(address)\",\"CollateralVault.initialize(address,address,uint256,uint256,address,bool)\",\"CollateralVault.receive()\",\"CollateralVault.release(address)\",\"CollateralVault.revokeWorker()\",\"CollateralVault.withdrawETH(uint256)\",\"CollateralVault.withdrawToken(address,uint256)\",\"LaunchToken.approve(address,uint256)\",\"LaunchToken.transfer(address,uint256)\",\"LaunchToken.transferFrom(address,address,uint256)\",\"LendingPool.acceptOwnership()\",\"LendingPool.addReserve()\",\"LendingPool.approve(address,uint256)\",\"LendingPool.borrow(uint256)\",\"LendingPool.claim(address)\",\"LendingPool.deposit(uint256,address)\",\"LendingPool.depositETH(address)\",\"LendingPool.donate()\",\"LendingPool.executeDepositCap()\",\"LendingPool.markAuctionLoss(uint256,uint256,uint256)\",\"LendingPool.mint(uint256,address)\",\"LendingPool.queueDepositCap(uint256)\",\"LendingPool.receive()\",\"LendingPool.receiveFee()\",\"LendingPool.receiveRecovery()\",\"LendingPool.redeem(uint256,address,address)\",\"LendingPool.redeemETH(uint256,address,address)\",\"LendingPool.settle(uint256)\",\"LendingPool.settleAuction(uint256,uint256)\",\"LendingPool.transfer(address,uint256)\",\"LendingPool.transferFrom(address,address,uint256)\",\"LendingPool.transferOwnership(address)\",\"LendingPool.withdraw(uint256,address,address)\",\"LendingPool.withdrawETH(uint256,address,address)\",\"LockDiscount.commit(uint256,address,uint256)\",\"LockDiscount.lock(uint256)\",\"LockDiscount.release(uint256)\",\"LockDiscount.unlock(uint256)\",\"MilestoneBurn.burn((bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MilestoneBurn.setQuestionHashOnce(bytes32)\",\"MilestoneBurn.syncSigner()\",\"PawnShop.acceptOwnership()\",\"PawnShop.buyAuction(uint256,address)\",\"PawnShop.cancelChange(bytes32)\",\"PawnShop.claim(address)\",\"PawnShop.disableCollection(address)\",\"PawnShop.executeAttester(address)\",\"PawnShop.executeCollection(address,(uint16,uint16,uint16,bool,bool,bytes32))\",\"PawnShop.executeDiscountModule(address)\",\"PawnShop.executeFeeRecipient(address)\",\"PawnShop.executeTerm(uint8,uint32,uint16)\",\"PawnShop.extend(uint256,uint8)\",\"PawnShop.fundBounties()\",\"PawnShop.markAuctionLoss(uint256)\",\"PawnShop.pawn(address,uint256,uint8)\",\"PawnShop.queueAttester(address)\",\"PawnShop.queueCollection(address,(uint16,uint16,uint16,bool,bool,bytes32))\",\"PawnShop.queueDiscountModule(address)\",\"PawnShop.queueFeeRecipient(address)\",\"PawnShop.queueTerm(uint8,uint32,uint16)\",\"PawnShop.receive()\",\"PawnShop.repay(uint256)\",\"PawnShop.setNewLoansPaused(bool)\",\"PawnShop.setQuestionHashOnce(address,bytes32)\",\"PawnShop.startAuction(uint256)\",\"PawnShop.submitFloor(address,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"PawnShop.transferOwnership(address)\",\"PawnShop.writeOffAuction(uint256)\"],\"files\":{\".gitignore\":4,\"DESIGN.md\":71,\"README.md\":183,\"dist/abi/CollateralVault.json\":739,\"dist/abi/LaunchToken.json\":315,\"dist/abi/LendingPool.json\":1716,\"dist/abi/LockDiscount.json\":367,\"dist/abi/MilestoneBurn.json\":609,\"dist/abi/PawnShop.json\":2083,\"dist/assets/VT323-Regular-DICElq-Y.ttf\":1068,\"dist/assets/ccip-DAHrphgT.js\":1,\"dist/assets/index-BE5mvMs3.css\":1,\"dist/assets/index-Dwd2G1uw.js\":93,\"dist/fonts/OFL.txt\":93,\"dist/fonts/VT323-Regular.ttf\":1068,\"dist/imd-deployment.json\":147,\"dist/index.html\":3,\"dist/pawn.svg\":13,\"docs/DESIGN.md\":3,\"docs/SETUP-AND-KEEPER.md\":132,\"docs/abi/CollateralVault.json\":739,\"docs/abi/FloorRelay.json\":26,\"docs/abi/LaunchToken.json\":315,\"docs/abi/LendingPool.json\":1716,\"docs/abi/LockDiscount.json\":367,\"docs/abi/MilestoneBurn.json\":609,\"docs/abi/PawnShop.json\":2083,\"docs/abi/README.md\":15,\"docs/floor-relay-validation.md\":63,\"docs/frontend/browser-results.json\":239,\"docs/frontend/browser-targeted-results.json\":19,\"docs/frontend/build.txt\":21,\"docs/frontend/delivery-check.json\":18,\"docs/frontend/desktop.png\":839,\"docs/frontend/export-check.txt\":5,\"docs/frontend/floor-relay/export-check.txt\":4,\"docs/frontend/floor-relay/forge-build.txt\":545,\"docs/frontend/floor-relay/forge-fmt.txt\":0,\"docs/frontend/floor-relay/forge-test.txt\":276,\"docs/frontend/floor-relay/keeper-tests.txt\":17,\"docs/frontend/floor-relay/owner-browser-results.json\":45,\"docs/frontend/floor-relay/owner-browser.txt\":7,\"docs/frontend/floor-relay/publication.json\":28,\"docs/frontend/floor-relay/publication.txt\":2,\"docs/frontend/floor-relay/setup-browser-results.json\":11,\"docs/frontend/floor-relay/setup-browser.txt\":11,\"docs/frontend/floor-relay/typecheck.txt\":9,\"docs/frontend/floor-relay/web-tests.txt\":34,\"docs/frontend/keeper-dry-run.txt\":4,\"docs/frontend/keeper-tests.txt\":76,\"docs/frontend/keyboard-focus.png\":890,\"docs/frontend/live-browser.json\":99,\"docs/frontend/live-desktop.png\":804,\"docs/frontend/live-read.json\":83,\"docs/frontend/mobile.png\":728,\"docs/frontend/night-desktop.png\":836,\"docs/frontend/night-mobile.png\":703,\"docs/frontend/owner-controls/build.txt\":27,\"docs/frontend/owner-controls/delivery-check.json\":13,\"docs/frontend/owner-controls/design-guidance-LICENSE.txt\":220,\"docs/frontend/owner-controls/export-check.txt\":5,\"docs/frontend/owner-controls/keyboard-focus.png\":1089,\"docs/frontend/owner-controls/live-browser.json\":106,\"docs/frontend/owner-controls/live-read.json\":83,\"docs/frontend/owner-controls/owner-browser-results.json\":45,\"docs/frontend/owner-controls/owner-browser.txt\":7,\"docs/frontend/owner-controls/owner-state-desktop.png\":905,\"docs/frontend/owner-controls/owner-state-mobile.png\":643,\"docs/frontend/owner-controls/publication.json\":38,\"docs/frontend/owner-controls/regression-browser-results.json\":244,\"docs/frontend/owner-controls/setup-browser-results.json\":11,\"docs/frontend/owner-controls/typecheck.txt\":4,\"docs/frontend/owner-controls/unit-tests.txt\":24,\"docs/frontend/owner-controls/validation.md\":68,\"docs/frontend/publish.json\":8,\"docs/frontend/setup-browser-results.json\":11,\"docs/frontend/setup-mobile.png\":777,\"docs/frontend/transaction-review.png\":650,\"docs/frontend/typecheck.txt\":4,\"docs/frontend/unit-tests.txt\":22,\"docs/frontend/update-build.txt\":27,\"docs/frontend/update-foundry-tests.txt\":262,\"docs/frontend/update-unit-tests.txt\":86,\"docs/frontend/update-validation.md\":28,\"docs/frontend/validation.md\":90,\"docs/review-notes.md\":34,\"docs/validation.md\":34,\"foundry.toml\":21,\"keeper/LICENSE\":21,\"keeper/README.md\":97,\"keeper/THIRD_PARTY_LICENSES.md\":254,\"keeper/config.json\":13,\"keeper/core.mjs\":65,\"keeper/cron.example\":3,\"keeper/hourly-workflow.yml\":35,\"keeper/run.mjs\":280,\"keeper/runtime-entry.ts\":16,\"keeper/runtime.mjs\":58,\"keeper/tests/core.test.mjs\":139,\"keeper/tests/oracle.test.mjs\":181,\"launch.json\":36,\"src/CollateralVault.sol\":193,\"src/FloorRelay.sol\":62,\"src/LaunchToken.sol\":11,\"src/LendingPool.sol\":340,\"src/LockDiscount.sol\":105,\"src/MilestoneBurn.sol\":75,\"src/OracleAttestation.sol\":221,\"src/PawnShop.sol\":490,\"src/PullPayments.sol\":35,\"src/interfaces/IPawn.sol\":21,\"test/AdversarialBoundaries.t.sol\":240,\"test/CONTRIBUTOR_TESTS.md\":20,\"test/CollateralVault.t.sol\":149,\"test/Deployment.t.sol\":64,\"test/FloorRelay.t.sol\":250,\"test/Governance.t.sol\":181,\"test/LaunchToken.t.sol\":35,\"test/LendingPool.t.sol\":162,\"test/LockDiscount.t.sol\":93,\"test/MilestoneBurn.t.sol\":112,\"test/Oracle.t.sol\":116,\"test/OracleConsumerConformance.t.sol\":105,\"test/PawnInvariant.t.sol\":227,\"test/PawnShop.t.sol\":244,\"test/PoolAccountingInvariant.t.sol\":365,\"test/ReviewRegression.t.sol\":349,\"test/ReviewScope.t.sol\":66,\"test/SetupFlows.t.sol\":58,\"test/TokenCustodyInvariant.t.sol\":278,\"test/VaultCustodyInvariant.t.sol\":266,\"test/fixtures/README.md\":31,\"test/fixtures/floor-zero-consumer.json\":94,\"test/fixtures/large-uint-zero-consumer.json\":94,\"test/fixtures/site-packed-floor.json\":3,\"test/helpers/LiveRelayVectors.sol\":50,\"test/helpers/Mocks.sol\":104,\"test/helpers/PawnTestBase.sol\":99,\"tools/export-relay.mjs\":13,\"tools/export_abis.py\":16,\"web/.gitignore\":8,\"web/README.md\":75,\"web/deployment.json\":78,\"web/index.html\":1,\"web/network.json\":57,\"web/package-lock.json\":2266,\"web/package.json\":33,\"web/public/abi/CollateralVault.json\":739,\"web/public/abi/LaunchToken.json\":315,\"web/public/abi/LendingPool.json\":1716,\"web/public/abi/LockDiscount.json\":367,\"web/public/abi/MilestoneBurn.json\":609,\"web/public/abi/PawnShop.json\":2083,\"web/public/fonts/OFL.txt\":93,\"web/public/fonts/VT323-Regular.ttf\":1068,\"web/public/imd-deployment.json\":127,\"web/public/pawn.svg\":13,\"web/scripts/check-live.mjs\":123,\"web/scripts/common.mjs\":51,\"web/scripts/manifest.mjs\":11,\"web/scripts/prepare.mjs\":49,\"web/scripts/validate-export.mjs\":32,\"web/src/App.tsx\":363,\"web/src/components.tsx\":330,\"web/src/config.ts\":197,\"web/src/engine.tsx\":522,\"web/src/finance.tsx\":591,\"web/src/floor-relay.json\":7,\"web/src/forms.tsx\":85,\"web/src/governance-state.tsx\":125,\"web/src/loans.tsx\":571,\"web/src/logic.ts\":195,\"web/src/main.tsx\":10,\"web/src/mascot.tsx\":37,\"web/src/operations.tsx\":454,\"web/src/oracle-flow.tsx\":248,\"web/src/oracle.ts\":214,\"web/src/relay-setup.tsx\":77,\"web/src/setup.tsx\":252,\"web/src/style.css\":1161,\"web/src/trade.tsx\":408,\"web/src/trading-fees.ts\":97,\"web/tests/browser.ts\":621,\"web/tests/logic.test.ts\":147,\"web/tests/mock-rpc.ts\":354,\"web/tests/oracle.test.ts\":62,\"web/tests/owner-browser.ts\":421,\"web/tests/render-live.mjs\":140,\"web/tests/setup-browser.ts\":325,\"web/tests/trading-fees.test.ts\":77,\"web/tsconfig.json\":1,\"web/vite.config.ts\":8},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":10981,"exitCode":0,"name":"slither","output":"[high/medium] reentrancy-eth at src/LendingPool.sol:232: Reentrancy in LendingPool._settle(uint256) (src/LendingPool.sol#232-242):\n[medium/high] incorrect-equality at src/LendingPool.sol:329: LendingPool.executeDepositCap() (src/LendingPool.sol#329-335) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:274: LendingPool.donate() (src/LendingPool.sol#274-280) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:282: LendingPool._vest(uint256) (src/LendingPool.sol#282-302) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PawnShop.sol:174: PawnShop._execute(bytes32) (src/PawnShop.sol#174-179) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PawnShop.sol:154: PawnShop.loanActive(uint256) (src/PawnShop.sol#154-156) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MilestoneBurn.sol:48: MilestoneBurn.burn(OracleAttestation.Attestation,bytes) (src/MilestoneBurn.sol#48-68) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:85: LendingPool.unvestedDonations() (src/LendingPool.sol#85-105) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:161: LendingPool.depositETH(address) (src/LendingPool.sol#161-169) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:85: LendingPool.unvestedDonations() (src/LendingPool.sol#85-105) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:191: LendingPool._withdrawNative(uint256,uint256,address,address) (src/LendingPool.sol#191-200) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:257: LendingPool._receiveIncome() (src/LendingPool.sol#257-266) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PullPayments.sol:17: PullPayments._credit(address,uint256) (src/PullPayments.sol#17-22) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LendingPool.sol:138: LendingPool.deposit(uint256,address) (src/LendingPool.sol#138-141) uses a dangerous strict equality:\n[medium/medium] unused-return at src/FloorRelay.sol:20: FloorRelay.isValidSignature(bytes32,bytes) (src/FloorRelay.sol#20-61) ignores return value by (recovered,err,None) = ECDSA.tryRecover(digest,sig) (src/FloorRelay.sol#58-59)\n[low/medium] missing-zero-check at src/PawnShop.sol:270: PawnShop.executeDiscountModule(address).module (src/PawnShop.sol#270) lacks a zero-check on :\n[low/medium] missing-zero-check at src/PawnShop.sol:132: PawnShop.constructor(address,address,address,address).owner_ (src/PawnShop.sol#132) lacks a zero-check on :\n[low/medium] missing-zero-check at src/PawnShop.sol:259: PawnShop.executeFeeRecipient(address).recipient (src/PawnShop.sol#259) lacks a zero-check on :\n[low/medium] reentrancy-benign at src/PawnShop.sol:442: Reentrancy in PawnShop.buyAuction(uint256,address) (src/PawnShop.sol#442-460):\n[low/medium] reentrancy-benign at src/PawnShop.sol:462: Reentrancy in PawnShop._distributeFee(uint256) (src/PawnShop.sol#462-473):\n[low/medium] reentrancy-benign at src/LendingPool.sol:191: Reentrancy in LendingPool._withdrawNative(uint256,uint256,address,address) (src/LendingPool.sol#191-200):\n[low/medium] reentrancy-benign at src/PawnShop.sol:462: Reentrancy in PawnShop._distributeFee(uint256) (src/PawnShop.sol#462-473):\n[low/medium] reentrancy-benign at src/LendingPool.sol:257: Reentrancy in LendingPool._receiveIncome() (src/LendingPool.sol#257-266):\n[low/medium] reentrancy-benign at src/PawnShop.sol:391: Reentrancy in PawnShop.startAuction(uint256) (src/PawnShop.sol#391-400):\n[low/medium] reentrancy-benign at src/LendingPool.sol:232: Reentrancy in LendingPool._settle(uint256) (src/LendingPool.sol#232-242):\n[low/medium] reentrancy-benign at src/PawnShop.sol:319: Reentrancy in PawnShop.pawn(address,uint256,uint8) (src/PawnShop.sol#319-355):\n[low/medium] timestamp at src/PawnShop.sol:442: PawnShop.buyAuction(uint256,address) (src/PawnShop.sol#442-460) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:174: PawnShop._execute(bytes32) (src/PawnShop.sol#174-179) uses timestamp for comparisons\n[low/medium] timestamp at src/CollateralVault.sol:101: CollateralVault.authorizeWorker(CollateralVault.WorkerAuthorization) (src/CollateralVault.sol#101-111) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:313: LendingPool._reserveEmptyPool() (src/LendingPool.sol#313-320) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:274: LendingPool.donate() (src/LendingPool.sol#274-280) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:130: LendingPool.maxRedeem(address) (src/LendingPool.sol#130-136) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:138: LendingPool.deposit(uint256,address) (src/LendingPool.sol#138-141) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:154: PawnShop.loanActive(uint256) (src/PawnShop.sol#154-156) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:284: PawnShop.submitFloor(address,OracleAttestation.Attestation,bytes) (src/PawnShop.sol#284-311) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:163: PawnShop._queue(bytes32,bytes32) (src/PawnShop.sol#163-172) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:171: LendingPool.withdrawETH(uint256,address,address) (src/LendingPool.sol#171-179) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:191: LendingPool._withdrawNative(uint256,uint256,address,address) (src/LendingPool.sol#191-200) uses timestamp for comparisons\n[low/medium] timestamp at src/CollateralVault.sol:119: CollateralVault.isValidSignature(bytes32,bytes) (src/CollateralVault.sol#119-126) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:257: LendingPool._receiveIncome() (src/LendingPool.sol#257-266) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:161: LendingPool.depositETH(address) (src/LendingPool.sol#161-169) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:85: LendingPool.unvestedDonations() (src/LendingPool.sol#85-105) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:329: LendingPool.executeDepositCap() (src/LendingPool.sol#329-335) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:117: LendingPool.maxDeposit(address) (src/LendingPool.sol#117-120) uses timestamp for comparisons\n[low/medium] timestamp at src/MilestoneBurn.sol:48: MilestoneBurn.burn(OracleAttestation.Attestation,bytes) (src/MilestoneBurn.sol#48-68) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:202: LendingPool.borrow(uint256) (src/LendingPool.sol#202-209) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:427: PawnShop.writeOffAuction(uint256) (src/PawnShop.sol#427-439) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:391: PawnShop.startAuction(uint256) (src/PawnShop.sol#391-400) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:181: LendingPool.redeemETH(uint256,address,address) (src/LendingPool.sol#181-189) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:313: PawnShop.floorFresh(address) (src/PawnShop.sol#313-317) uses timestamp for comparisons\n[low/medium] timestamp at src/PawnShop.sol:402: PawnShop.auctionPrice(uint256) (src/PawnShop.sol#402-416) uses timestamp for comparisons\n[low/medium] timestamp at src/LendingPool.sol:282: LendingPool._vest(uint256) (src/LendingPool.sol#282-302) uses timestamp for comparisons\n[low/medium] timestamp at src/OracleAttestation.sol:157: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/OracleAttestation.sol#157-165) uses timestamp for comparisons","passed":true},{"durationMs":857,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/MilestoneBurn.sol:34: Reentrancy: State change after external call (4 places)\n[low] centralization-risk at src/LendingPool.sol:14: Centralization Risk (14 places)\n[low] large-numeric-literal at src/LaunchToken.sol:9: Large Numeric Literal (18 places)\n[low] literal-instead-of-constant at src/FloorRelay.sol:22: Literal Instead of Constant (43 places)\n[low] local-variable-shadowing at src/CollateralVault.sol:45: Local Variable Shadows State Variable\n[low] missing-inheritance at src/FloorRelay.sol:10: Missing Inheritance\n[low] non-reentrant-not-first at src/CollateralVault.sol:131: `nonReentrant` is Not the First Modifier (9 places)\n[low] state-no-address-check at src/PawnShop.sol:138: Address State Variable Set Without Checks (3 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"a1aed6b687302ea90826b660a1194c1208680628b20656b2206f8d0853bd94b4","verifiedTreeHash":"907311ea6e10a24cb5737d519a9f69d66541d067","verifierVersion":"0.1.0+ad90ce4c"}]}