{"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":"792f6f16-ef1b-43bf-84bd-8703e8375735","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"1a847880daf74236172578aeca6ca775f46d903a847414d2497d6f062c6c0e74","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"398b536cd73ce3e4d0026074a655ed8282e606861261bbdfb2e607e6bf1434f8","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"1c6828849dc73d3ed1f6d3dfbb898a765800b50e79e2db0c489734de5930b4fb","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"bdfe59a5a93c990b62fb013c75e5be5485c06e1bcd01ba3573b25526d2b0142d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"c1e4bd6449fca6cb473d259b00c9a2bcf3b601eeb019a8b0d261eb08a4a64302","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"8e1df04c1b7d412d22df75817fc1458c539693d6521ed8e37264aed9056c23b0","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"a70756327da0d408ffe772a64fba60f20167f98e9ad8b613c35955f17b216bfd","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"9e04d0c51f9ec62bc93bdc1bbbc0d9c343b24c453eabfeed9dc9a387607383ae","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"3c7b8702d105744891f98a67dd434acc18648b10f3969517f19742753b43845d","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Deploy only src/KeptVault.sol from this repository on Robinhood Chain (chain id 4663), with no changes to the production source unless an audit finding requires one. KEPT lets any project lock tokens behind milestones that the IMD oracle checks; kept milestones release to the team, unproven ones are burned. Constructor arguments in order: owner_ = $owner; intake_ = 0x1397434cd35e8a9c8ac312a61d3a285eb31dea56 (IMD Intake on Robinhood); imd_ = 0x5f7bb59365ce557c26dbcaa4ee9d39a4b95b7127 (IMD on Robinhood); action_ = 0x6f7261636c652e72657175657374406f7261636c652d31000000000000000000 (bytes32 \"oracle.request@oracle-1\"); signer_ = 0x5598aa9146215bc13eb26f2c692ad1461fd32982 (IMD oracle signer); panelSize_ = 9; quorum_ = 7. No token, pool, hook, ETH or initialization calls. Tests: forge test (offline); docs/VERIFICATION.md records a Robinhood fork rehearsal against the live Intake, IMD and PoolManager.","parentJobId":null,"planHash":"155c88c2fb6b94df33e28e24992b13e68008f012761756e51a218292951e499d","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"792f6f16-ef1b-43bf-84bd-8703e8375735","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2172-deploy-only-src-keptvault-sol-repository"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52221","feedbackHash":"79d84cfee74f35d65a0b534504407f279437431632e48e6864844b8675c59b2b","nodeKey":"adapt_contract_project","submissionHash":"1a847880daf74236172578aeca6ca775f46d903a847414d2497d6f062c6c0e74","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51352","feedbackHash":"7256dae1b4e47761210f375bcf91c8a26438ef894a1e7c49da7ee127a3350846","nodeKey":"audit_economics","submissionHash":"398b536cd73ce3e4d0026074a655ed8282e606861261bbdfb2e607e6bf1434f8","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52420","feedbackHash":"091a3b7374c468029c26efaf86a02d25f4aec4d64e420cb3c8683313adf0f2a0","nodeKey":"audit_flow","submissionHash":"1c6828849dc73d3ed1f6d3dfbb898a765800b50e79e2db0c489734de5930b4fb","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51476","feedbackHash":"155d5e0189f654ab13a739a72eb73df81acd58620c8d5e46fb9abfebb255b7d8","nodeKey":"audit_imported_code","submissionHash":"bdfe59a5a93c990b62fb013c75e5be5485c06e1bcd01ba3573b25526d2b0142d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"53910","feedbackHash":"9facbb5790695f81874535bca581b03fa93e2657c803cc9faa786ba182aa0f48","nodeKey":"audit_judge","submissionHash":"c1e4bd6449fca6cb473d259b00c9a2bcf3b601eeb019a8b0d261eb08a4a64302","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52686","feedbackHash":"5d7e4984fdb0dcc71408ae5be321127bfcebc682d2c8d9b0e174b5408120f303","nodeKey":"audit_math","submissionHash":"8e1df04c1b7d412d22df75817fc1458c539693d6521ed8e37264aed9056c23b0","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52179","feedbackHash":"7e2f0e2b0301fc33d89f89e2114a57f715204c8aa0996570349dc5e1582cd3f1","nodeKey":"audit_permissions","submissionHash":"a70756327da0d408ffe772a64fba60f20167f98e9ad8b613c35955f17b216bfd","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51426","feedbackHash":"ff248ecf7cb2b29ab6976b75abf750387bfc8d200c22a358d58b96b70705a2a9","nodeKey":"manifest","submissionHash":"9e04d0c51f9ec62bc93bdc1bbbc0d9c343b24c453eabfeed9dc9a387607383ae","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52272","feedbackHash":"8f59d8ca1d50b5ffd8a60178f9f7d26887c68807146aa4cb09cbda2288e397a0","nodeKey":"write_foundry_tests","submissionHash":"3c7b8702d105744891f98a67dd434acc18648b10f3969517f19742753b43845d","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"2fb4972cd00a2517cc8ada2ed0093f3109a9d62a3ec782d2f49112c206507543","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"f0ecf1a8be410ce52b493066c88581e8c8f8b22f859c19a00b70ba8088099e24","device":"2ca00c67242c649b","findings":[],"hash":"1a847880daf74236172578aeca6ca775f46d903a847414d2497d6f062c6c0e74","nodeId":"e03b72f1-b906-4b09-b2ed-f1c70bb4c7ea","outcome":"completed","summary":"Prepared the KeptVault-only launch with fixes for deadline enforcement, beneficiary-controlled attempts, and price caps.\n\n- Offline build passed; 98 tests passed.\n- Robinhood fork: 2 tests passed.\n- Shrinking tokens remain explicitly unsupported; owner trust is documented.\n\nDetails: [ADAPTATION.md](/home/identitymd/.identitymd/work/792f6f16-ef1b-43bf-84bd-8703e8375735/e03b72f1-b906-4b09-b2ed-f1c70bb4c7ea/ADAPTATION.md) and [verification record](/home/identitymd/.identitymd/work/792f6f16-ef1b-43bf-84bd-8703e8375735/e03b72f1-b906-4b09-b2ed-f1c70bb4c7ea/docs/VERIFICATION.md).\n\nNo transactions were broadcast.","treeHash":"e3f5b07cc28ed5a85fe5db5953e6cd14d04b1d85","usage":{"cachedInputTokens":5619840,"inputTokens":179961,"model":"gpt-6-astra","outputTokens":36191,"runtime":"codex","turns":9,"wallClockMs":932001}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"1559912e747bbcd4","findings":[{"citation":"resolved","description":"For PageContains, ContractDeployed and ValueAtLeast, `_check` (line 304, `if (block.timestamp > _checkDeadline(m)) revert CheckWindowClosed();`) sells a check at any time up to and including `deadline`, and `checkOpen` reports `open == true` for the same range. But `onOracleResult` refuses any attestation with `a.issuedAt > m.deadline` (line 364) and also requires `a.issuedAt >= m.askedAt` (line 360). The oracle signs minutes after the request, so a check bought at `deadline - latency` or later can only be honoured by an attestation issued in the sub-minute interval `[askedAt, deadline]`, which the panel cannot meet. The contract therefore takes the budget, counts the attempt, hands the Intake 0.5 IMD, and then reverts the only answer the request can ever receive. Because the callback reverts instead of recording the verdict, the request stays `inFlight` for `ANSWER_TIMEOUT` (1 day), and because `block.timestamp > deadline` afterwards, no further check can be bought on that milestone. If it was the beneficiary's last chance (last attempt, or the deadline), the tranche burns at `deadline + GRACE` even though the oracle attested it kept. The documentation (README, SPEC) tells users to ask early enough, but the contract's own seller (`_check`), its own advisory view (`checkOpen`) and its own acceptor (`onOracleResult`) disagree about the window: the acceptor's effective window is strictly narrower than what the seller and view promise. The execution path is: seller accepts -> budget debited -> attempt incremented -> external request paid -> answer arrives -> acceptor refuses -> state parked for a day -> burn. Suggested minimal fix that preserves the design: close snapshot checks (and `checkOpen`) a fixed margin before the deadline, e.g. refuse a snapshot `_check` when `block.timestamp + SNAPSHOT_LEAD > m.deadline` with `SNAPSHOT_LEAD` of some tens of minutes, so the contract never sells a request that its acceptor cannot honour; alternatively record a refused-but-valid verdict without reverting so the request is at least cleared immediately rather than parked for a day.","line":364,"path":"src/KeptVault.sol","reproduction":"State: a pledge with one PageContains milestone, deadline D = T0 + 7 days, amount 100 TEAM, budget 10 IMD; vault with the mock Intake quoting 0.5 IMD. Steps: (1) warp to D - 60; `vault.checkOpen(id, 0)` returns (true, true); beneficiary calls `vault.check(id, 0)`: succeeds, budget drops to 9.5 IMD, attempts = 1, 0.5 IMD leaves the vault. (2) The oracle signs a correct `true` verdict with panelSize 9, quorum 7, agreed 9, issuedAt = D + 120, expiresAt = issuedAt + 1 day, chainId 4663, delivered by the Intake at D + 180 under 200k gas. Expected: the verdict is recorded (or at least the request cleared). Actual: `onOracleResult` reverts `InvalidAttestation()` (line 364); the Intake records the delivery as failed and never retries. (3) beneficiary calls `vault.check(id, 0)` again: reverts `CheckInFlight()`; after D + 1 day: reverts `CheckWindowClosed()`. (4) At D + 3 days + 1, anyone calls `vault.settle(id, 0)`: 100 TEAM go to 0x...dEaD, attempts remain 1, the 0.5 IMD is gone. Reproduced with a scratch Foundry test (test/scratch/DeadWindow.t.sol, passes against the current code as a demonstration of the behaviour) using the project's own MockIntake and FeeToken.","severity":"low","snippet":"        if (m.spec.kind != Questions.Kind.GithubRelease && a.issuedAt > m.deadline) {\n            revert InvalidAttestation();\n        }","title":"Snapshot templates sell a check inside the oracle's latency window that no answer can satisfy: attempt and 0.5 IMD are spent, the milestone can burn despite a true verdict"}],"hash":"1c6828849dc73d3ed1f6d3dfbb898a765800b50e79e2db0c489734de5930b4fb","nodeId":"7b4714e6-8628-4a73-95de-09672aa10b43","outcome":"completed","summary":"The findings file validates, the quoted snippet matches the tree, and the working tree shows no tracked changes.\n\n## Recap\n\n**Scope covered.** I audited `src/KeptVault.sol` and its periphery (`OracleAttestation.sol`, `Questions.sol`, `IIntake.sol`) against the Execution Trace, Periphery and First Principles guides, tracing every vault entry point through its guards, state writes and failure paths. The baseline suite passes (98 tests). The vendored attestation library is identical to the canonical one in the oracle-consumer reference apart from formatting.\n\n**What holds.** The control flow is in good shape:\n- Request and callback binding is keyed by intake, with a signer snapshot per check, so a protocol swap mid-flight can neither strand nor hijack a pending answer.\n- Stale-clear inside `check` rolls back when a later guard reverts. Settle never burns over an un-timed-out check, and a rebate can never land after a budget refund.\n- Worst-case callback gas (max-length PageContains, kept verdict, rebate from a zero budget, cold storage) measured 165,812, under the 200k stipend. The existing tests only measured a short GitHub pledge, so this closes a gap rather than finding one.\n- Every string that reaches the JSON body is character-restricted; the slither divide-before-multiply lead in `isoDate` is the standard civil-date algorithm, not a defect.\n\n**One finding, low severity.** For the three snapshot templates, `check` and `checkOpen` sell a check right up to the deadline, but `onOracleResult` refuses any answer issued after the deadline. A check bought inside the oracle's latency can never be honoured. The attempt and 0.5 IMD are spent, the request is parked for a day, no retry is possible, and the tranche can burn despite a true verdict. The docs tell users to ask early. The contract's own seller and acceptor still disagree about the window. The reproduction is in the findings file and demonstrated in `test/scratch/DeadWindow.t.sol`.\n\n**Not reached.** The hook's swap and initialize callbacks and the token are outside this contracts-only launch. I traced `sweep` and `unlockCallback` for the static-analysis reentrancy lead (guarded) and marked the rest `unreached`. One lead I could not substantiate offline: whether the live oracle serves chain evidence for every chain the `Questions` allowlist admits (56, 8453, 42161). A refused chain would spend attempts without a callback.","treeHash":null,"usage":{"cachedInputTokens":1732694,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":44752,"runtime":"claude","turns":41,"wallClockMs":907346}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"8f08088e7a7f557f","findings":[{"citation":"resolved","description":"Flow gap (execution x periphery x first principles). A check is bound to its milestone only through m.inFlight. Anyone may call clearStale(pledgeId, index) exactly ANSWER_TIMEOUT (1 day) after the check was asked (line 393-394), which zeroes m.inFlight while _known/_tickets keep the id. If the oracle's delivery then arrives with an attestation that is signed, unexpired, issued inside the snapshot deadline and says kept, onOracleResult refuses it at line 350 with UnknownRequest and the Intake records the request as not delivered and never retries. The beneficiary has paid 0.5 IMD and spent one of three attempts for a true answer that the contract threw away; for PageContains/ContractDeployed/ValueAtLeast milestones whose deadline has meanwhile passed, no new check can be bought (line 304) and the tranche is burned although the milestone was kept. The caller of clearStale needs no stake: any holder of the locked token benefits from a burn. Preconditions: oracle delivery later than 24h after the request while the attestation (issuedAt + validity) is still inside its own window, which with the request's validForSeconds = 86400 is a narrow but real race; the same discard happens through _check's own stale-clear path (line 302) and settle's (line 412). Minimal fix preserving the design: keep accepting a verdict for a request this contract made while the milestone is still Open and no newer check has been bought (e.g. do not zero the binding in clearStale, only allow a new request to supersede it), or make clearStale callable only by the beneficiary.","line":350,"path":"src/KeptVault.sol","reproduction":"Mock Intake, signer key 0xA11CE, T0 = 1791000000. creator: createPledge(team, beneficiary, 'p', [PageContains, deadline T0+36h, amount 100e18, a='https://example.org/', b='hello'], budget 1e18). beneficiary: check(id,0) at T0 -> 0.5 IMD paid, attempts=1. Oracle signs Attestation{answer=true, chainId=4663, panelSize 9, quorum 7, agreed 8, issuedAt T0+10min, expiresAt T0+1d+10min}. At T0+1d a third party calls clearStale(id,0) -> succeeds. At T0+1d+1s the Intake delivers (rid, a, sig): expected the Kept verdict to be recorded; actual callback reverts UnknownRequest, milestone stays Open with attempts=1. At T0+36h+3d+1s settle(id,0) burns 100e18 team tokens. Scratch test test/scratch/Economics.t.sol::test_clearStaleDiscardsValidLateKeptVerdict reproduces every step.","severity":"low","snippet":"        if (m.inFlight != requestId || m.inFlightIntake != msg.sender) revert UnknownRequest();","title":"Permissionless clearStale discards a still-valid, in-window Kept verdict; the paid check is lost and a snapshot milestone can burn"},{"citation":"resolved","description":"Economic Security / Invariant (cross-asset coupling). withdrawBudget returns the pledge's IMD only when every milestone is settled (p.open == 0). settle pays a Kept tranche with p.token.safeTransfer(p.beneficiary, amount) (line 422). If that transfer reverts for a reason outside the vault, e.g. the beneficiary is blacklisted by a USDC-style token after pledge creation, or the token is paused, the milestone can never settle: outcome is already Kept so no check can be bought (line 299), and there is no alternative payout path. The IMD budget, a different and healthy asset, is then unreachable by anyone, although nothing can ever spend it again. The README documents the token restriction, but the comment at line 426-427 states the opposite intent ('a refund can never block a payout') while a blocked payout does block the refund. Minimal fix: let withdrawBudget run once no milestone can still buy a check (every milestone is settled, or has outcome != Open, or is past _checkDeadline with no fresh in-flight check), which keeps the budget available exactly as long as it can be spent; optionally let the beneficiary pull a Kept tranche to an address of their choice.","line":430,"path":"src/KeptVault.sol","reproduction":"Blacklistable ERC-20 B (reverts if from/to blocked). creator: createPledge(B, beneficiary, 'p', [PageContains, deadline T0+7d, amount 100e18], budget 10e18). beneficiary: check(id,0); mock Intake delivers a signed true attestation -> outcome Kept, budget 9.5e18. Token admin blocks beneficiary. settle(id,0) reverts 'blacklisted' now and at T0+100d. withdrawBudget(id) reverts NotOpen; beneficiary check(id,0) reverts NotOpen. Expected: 9.5 IMD returnable to creator since no path can spend it; actual: locked forever. Scratch test test/scratch/Economics.t.sol::test_unpayableKeptTrancheStrandsImdBudget.","severity":"low","snippet":"        if (p.open != 0) revert NotOpen();","title":"A Kept tranche that cannot be transferred (recipient blacklisted/paused token) permanently strands the creator's IMD budget"},{"citation":"resolved","description":"Invariant (view/write divergence) and economics. For PageContains/ContractDeployed/ValueAtLeast the check window closes at the deadline inclusive (line 304 with _checkDeadline = deadline), while onOracleResult requires a.issuedAt >= m.askedAt (line 360) and a.issuedAt <= m.deadline (line 364). A check bought at block.timestamp == deadline therefore admits only issuedAt == deadline, and one bought within the panel's latency (minutes) of the deadline admits no real answer either. The contract still quotes it as open and funded in checkOpen (lines 549-552) and takes the price and the attempt. Since no retry is possible after the deadline, a team that checks 'at the deadline' as the UI suggests loses 0.5 IMD and the tranche. Minimal fix: close snapshot checks a margin before the deadline (or express the margin in checkOpen and check), or let the oracle's toBlock/issuedAt window be the reference instead of the request time.","line":304,"path":"src/KeptVault.sol","reproduction":"createPledge with one PageContains milestone, deadline D = T0+2h, budget 1e18. warp(D). checkOpen(id,0) returns (true,true). beneficiary check(id,0) succeeds, budget 0.5e18, attempts 1. Oracle signs true at issuedAt = D+1 and the Intake delivers at D+1: expected a usable verdict or a refused purchase; actual callback reverts InvalidAttestation. At D+1d+1 check(id,0) reverts CheckWindowClosed; at D+3d+1 settle burns the tranche. Scratch test test/scratch/Economics.t.sol::test_checkAtDeadlineCanNeverBeAnswered.","severity":"low","snippet":"        if (block.timestamp > _checkDeadline(m)) revert CheckWindowClosed();","title":"Snapshot checks bought at or near the deadline are a guaranteed loss: checkOpen reports open, 0.5 IMD and an attempt are spent, and no attestation can satisfy askedAt <= issuedAt <= deadline"},{"citation":"resolved","description":"Economic Security (legitimate feature turned against the protocol). The rebate at lines 380-385 pays the last check's price from refereeFund into the pledge's budget for any Kept milestone, with no condition on the pledge's token, amount, question or who the beneficiary is. An attacker creates a pledge locking 1 wei of a token they minted, names themselves beneficiary, picks a question that is certainly true (ContractDeployed for the live Intake address, or ValueAtLeast totalSupply() >= 1), funds the budget with exactly 0.5 IMD, checks, receives Kept, settles the 1 wei back to themselves and withdraws the budget including the rebate. Net IMD for the attacker: 0; net for the Referee Fund: -0.5 IMD per milestone (up to 8 per pledge, 4 IMD per transaction batch), paid to the Intake. The fund is filled by the hook's 1% of IMD swap volume and by donations, so the honest teams it was meant to rebate lose the subsidy; the attacker's only cost is gas and one oracle round trip per 0.5 IMD. Not a direct theft, so low; a minimal mitigation is to rebate only pledges above a minimum locked value in a whitelisted token, or to cap rebates per creator/pledge.","line":380,"path":"src/KeptVault.sol","reproduction":"fundReferee(1e18) by anyone. Attacker mints 8 wei of Junk, approves. Loop twice: createPledge(Junk, attacker, 'x', [ContractDeployed chain 4663 target 0x1397434cd35e8a9C8aC312A61D3A285EB31dea56, deadline T0+2h, amount 1], budget 0.5e18); check(id,0); Intake delivers signed true; settle(id,0); withdrawBudget(id). Expected the fund to subsidise real teams; actual refereeFund == 0, attacker's IMD balance unchanged, Junk balance back to 8. Scratch test test/scratch/Economics.t.sol::test_refereeFundDrainedByTrivialSelfPledges.","severity":"low","snippet":"        if (price != 0 && refereeFund >= price) {","title":"Referee Fund can be drained at zero IMD cost with trivially true self-pledges of a worthless token"},{"citation":"resolved","description":"Documented owner power, recorded here as the economics guide requires, not as a bypass. proposeProtocol + executeProtocol (lines 558-580) replace intake and oracleSigner after PROTOCOL_DELAY. New checks then verify against the owner's signer and accept request ids from the owner's intake, so the owner, colluding with a beneficiary, can release any still-open tranche to that beneficiary; conversely a renounced owner (setOwner(0)) leaves pledges bound to Intake v1 forever, and if that intake stops selling oracle.request every open milestone burns at deadline+GRACE. Locked tokens have no creator exit during the notice. The in-flight signer/intake snapshot (lines 330-331) correctly protects pending checks. No code change is required; the brief names the owner. The judge should weigh it alongside the oracle liveness note in the README (burn on missing or late answers).","line":579,"path":"src/KeptVault.sol","reproduction":"owner: proposeProtocol(attackerIntake, action, attackerSigner); warp +7d; anyone: executeProtocol(). beneficiary: check(id,0) -> attackerIntake returns any id; attackerIntake calls onOracleResult with an attestation signed by attackerSigner for this vault -> Kept; settle pays the beneficiary. Existing test test_ownerHasNoPathToLockedTokens shows the owner cannot pay itself directly.","severity":"info","snippet":"        _setProtocol(c.intake, c.action, c.signer);","title":"Trust assumption: after a 7-day notice the owner can point every future verdict at a signer and Intake of its choice, and creators cannot exit"}],"hash":"398b536cd73ce3e4d0026074a655ed8282e606861261bbdfb2e607e6bf1434f8","nodeId":"82587fc2-3418-4405-a03d-704ae0d38016","outcome":"completed","summary":"Review complete. The findings file is written at `.imd-findings.json` with five findings and a 24-row coverage record; no production file was changed.\n\n**Outcome.** The vault's core economics hold. IMD balance equals budgets plus Referee Fund on every path, locked tokens equal unsettled amounts, pulls are exact, replay and sender checks are sound, and in-flight checks keep their signer and Intake across a protocol rotation. The baseline suite passes with 97 tests. I found no critical or high defect, so no proof file was required.\n\n**Findings, all reproduced in `test/scratch/Economics.t.sol`:**\n\n1. **Low, flow gap.** Anyone can call `clearStale` one day after a check, and a still-valid Kept verdict delivered after that is refused with `UnknownRequest`. The team loses the paid check and, for snapshot milestones past their deadline, the tranche burns.\n2. **Low, cross-asset coupling.** If a Kept tranche cannot be transferred, for example because the beneficiary is blacklisted by a USDC-style token, `withdrawBudget` is blocked forever and the creator's healthy IMD budget is stranded. The README documents the token restriction, but the code comment claims a refund can never block a payout while the reverse coupling exists.\n3. **Low, view/write divergence.** A snapshot check bought at the deadline is reported open and funded, spends 0.5 IMD and an attempt, yet no attestation can satisfy both `issuedAt >= askedAt` and `issuedAt <= deadline`. No retry is possible.\n4. **Low, incentive gap.** The Referee Fund rebates any Kept milestone, so self-pledges of 1 wei of a junk token with a trivially true question drain it at zero IMD cost to the attacker.\n5. **Info, trust assumption.** After the 7-day notice the owner can redirect signer and Intake, and creators cannot exit during the notice. Recorded as a documented power, not a bypass.\n\n**Coverage.** Every KeptVault entry point is traced. The hook's `beforeInitialize`, `sweep` and `unlockCallback` and the token functions hold; `beforeSwap` and `afterSwap` fee math is marked unreached since the hook is outside this launch and I prioritised the vault.","treeHash":null,"usage":{"cachedInputTokens":1848194,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":38678,"runtime":"claude","turns":35,"wallClockMs":719200}},{"artifacts":[],"attempt":1,"bundleHash":"25b1cefd63ffcbf73f94b8fb756c7a149ea420f85044d502d5f1b1aac3b0e793","device":"ef31844bb462de78","findings":[{"description":"settle() sends the tranche with safeTransfer to the beneficiary (Kept) or to BURN = 0x…dEaD (Broken) and has no other way to finish the milestone. withdrawBudget() requires p.open == 0 (line 430). If the pledge token refuses that transfer (a blocklisting/pausable token that blocks the beneficiary or the dead address, or a token that rejects 0x…dEaD), settle reverts on every call, p.open never reaches 0, and the creator's unused IMD budget is locked in the vault for good. The NatSpec on withdrawBudget says it is kept apart from settle so a refund can never block a payout; the reverse case, a payout blocking the refund, is not handled. Only that pledge's own token and budget are affected; other pledges and the Referee Fund are unaffected (covered by the new invariant suite). Possible fixes: let withdrawBudget return the budget once every milestone has an outcome rather than once every transfer succeeded, or let a Broken tranche settle as recorded-burned when the transfer to BURN fails; or document such tokens as unsupported, as ADAPTATION.md already does for balance-shrinking tokens.","line":422,"path":"src/KeptVault.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {KeptVault} from \"src/KeptVault.sol\";\nimport {Questions} from \"src/libraries/Questions.sol\";\nimport {IIntake} from \"src/interfaces/IIntake.sol\";\n\ncontract BlockToken is ERC20 {\n    mapping(address => bool) public blocked;\n    constructor() ERC20(\"B\", \"B\") {}\n    function mint(address to, uint256 a) external { _mint(to, a); }\n    function setBlocked(address a, bool b) external { blocked[a] = b; }\n    function _update(address f, address t, uint256 v) internal override {\n        require(!blocked[t], \"blocked\");\n        super._update(f, t, v);\n    }\n}\n\ncontract NoIntake {\n    function priceOf(bytes32, address) external pure returns (uint256) { return 0.5 ether; }\n}\n\ncontract BlocklistTest is Test {\n    function test_blockedBurnAddressStrandsBudget() public {\n        vm.warp(1_791_000_000);\n        BlockToken team = new BlockToken();\n        BlockToken imd = new BlockToken();\n        NoIntake intake = new NoIntake();\n        address owner = makeAddr(\"owner\");\n        address creator = makeAddr(\"creator\");\n        KeptVault vault = new KeptVault(owner, address(intake), address(imd),\n            bytes32(\"oracle.request@oracle-1\"), makeAddr(\"signer\"), 9, 7);\n        team.mint(creator, 100 ether);\n        imd.mint(creator, 10 ether);\n        vm.startPrank(creator);\n        team.approve(address(vault), type(uint256).max);\n        imd.approve(address(vault), type(uint256).max);\n        KeptVault.MilestoneInput[] memory ms = new KeptVault.MilestoneInput[](1);\n        ms[0].kind = Questions.Kind.GithubRelease;\n        ms[0].deadline = uint64(block.timestamp + 7 days);\n        ms[0].amount = 100 ether;\n        ms[0].title = \"ship\";\n        ms[0].a = \"kept/app\";\n        ms[0].b = \"v1\";\n        uint256 id = vault.createPledge(IERC20(address(team)), makeAddr(\"ben\"), \"p\", ms, 10 ether);\n        vm.stopPrank();\n        team.setBlocked(vault.BURN(), true);\n        vm.warp(block.timestamp + 11 days);\n        // Expected: the unproven tranche can be finished (burned or otherwise retired) and the\n        // creator's 10 IMD budget returned. Actual: settle reverts forever, so withdrawBudget does too.\n        try vault.settle(id, 0) {} catch {}\n        vault.withdrawBudget(id);\n        assertEq(imd.balanceOf(creator), 10 ether);\n    }\n}","reproduction":"Team token with a blocklist that blocks 0x000000000000000000000000000000000000dEaD. createPledge one GithubRelease milestone (100 tokens, deadline now+7d) with budget 10 IMD. Warp 11 days. settle(id,0) reverts ('blocked'), every time. withdrawBudget(id): expected the 10 IMD back to the creator; actual reverts NotOpen() forever. Same result when the beneficiary is blocklisted after a Kept verdict.","severity":"low","title":"A tranche whose recipient refuses the token can never settle, which also strands the pledge's IMD budget"},{"description":"For PageContains, ContractDeployed and ValueAtLeast, check() is open until block.timestamp == deadline and checkOpen() reports open=true, but onOracleResult requires askedAt <= a.issuedAt <= deadline. An oracle answer takes minutes, so a check bought within that latency of the deadline spends the price and one of the three attempts and is always refused with InvalidAttestation in the one-shot callback. The rule itself (no snapshot signed after the deadline) is intended and is tested; the issue is that the vault keeps selling a check it will refuse. Suggest closing snapshot checks some minutes before the deadline, or surfacing that in checkOpen.","line":364,"path":"src/KeptVault.sol","reproduction":"PageContains milestone, deadline D. Beneficiary calls check at D - 60s. Oracle answers 'true' with issuedAt = D + 4min (normal latency). Expected: either the check is refused up front or the answer is usable. Actual: check succeeds and spends 0.5 IMD and one attempt, the callback reverts InvalidAttestation, and the attempt is lost (KeptVaultAudit.t.sol testFuzz_snapshotRejectsVerdictIssuedAfterDeadline shows the refusal).","severity":"info","title":"Snapshot templates sell checks in the last minutes before the deadline that cannot be answered in time"},{"description":"For ContractDeployed and ValueAtLeast the `a.agreed < a.quorum` check is skipped by design (the deployer's recipe rerun settles split panels), so a signed attestation with agreed = 0 releases the tranche. Value release on those templates then rests only on the oracle signer key and the Intake writer's pairing of answer to request (questionHash is not checked because the window is relative). This is the documented protocol behaviour; recorded so reviewers weigh it for large tranches.","line":359,"path":"src/KeptVault.sol","reproduction":null,"severity":"info","title":"Chain-evidence verdicts accept any panel agreement, down to zero"}],"hash":"3c7b8702d105744891f98a67dd434acc18648b10f3969517f19742753b43845d","nodeId":"9190af3d-b0c8-4920-88d7-a13a12994fe4","outcome":"completed","summary":"I added two test files and found one real defect. `forge build` passes, and `forge test --offline` with the verifier's seed passes: 133 tests pass, 0 fail, and 1 is skipped (the Robinhood fork suite, which only runs on a fork). The source code is unchanged.\n\n**`test/KeptVaultFailurePaths.t.sol`** (33 tests) covers failure paths the existing suite didn't pin down:\n- **Constructor:** each missing address or action is rejected, and panel sizes are checked at the edges (5–100, quorum a strict majority). A fuzz test (1000 runs) checks the same rule on `setPanel`.\n- **Admin:** only the owner can call admin functions; after the owner renounces, nobody can; handing over ownership moves the role. Protocol changes reject zero fields, cancel and execute fail with nothing pending, and re-proposing restarts the 7-day wait.\n- **Funding and checks:** wrong pledge or milestone ids, zero amounts, funding a finished pledge, a zero price quote, and checks after a milestone is kept or settled. Three \"no\" answers use up all attempts, and a \"no\" earns no rebate.\n- **Stale checks:** the timeout boundary is exact, and an answer that arrives after its check was cleared, or after the tranche was burned, is refused. Burning happens only strictly after the deadline plus the 3-day grace period.\n- **Callback guards:** refused cases include a duplicate delivery, a retired Intake answering the new one's request, an attacker's own Intake, an attestation issued too far ahead, an expiry before issue, an empty signature, a high-s variant of the oracle's own valid signature, a flipped answer, and a signature made for a different vault.\n- **Gas:** the worst-case callback (8 milestones, longest strings, rebate path) fits the 200,000 gas the Intake gives it.\n- **Custody:** IMD locked as a pledge token can't be spent on checks, pledges don't affect each other, and a token that re-enters the vault can't reenter `settle` or `withdrawBudget`. A fuzz test checks that payouts and burns split exactly.\n\n**`test/KeptVaultActorsInvariant.t.sol`** is an invariant suite over random call sequences (64 runs × 100 calls). It uses two creators, two beneficiaries, an outsider, three pledge tokens (one is IMD itself), three milestone types, price changes, signer rotation, and forged or weak verdicts. Rule breaks are counted rather than asserted inside the handler, so they can't be hidden as ordinary reverts. The invariants are:\n- Each team token is held by the vault, paid out or burned, and nothing else.\n- The vault's IMD equals pledge budgets plus the Referee Fund plus IMD locked as a pledge token, and every IMD that came in is accounted for going out.\n- Only the beneficiary spends attempts, no forged verdict is accepted, and payouts go to the right place in the right amount.\n- No burn happens before the grace period ends, outcomes never reopen, and refunds go to the creator in full.\n\nA separate test proves the handler actually reaches payouts, burns, refunds and rotations, so the invariants aren't vacuous.\n\n**Reported in `.imd-findings.json`** rather than tested as correct:\n- **Low (with a proof test that fails today):** if the pledge token refuses the transfer to the beneficiary or to the burn address `0x…dEaD` (for example a token with a blocklist), `settle` reverts every time. The milestone then never closes, so `withdrawBudget` reverts `NotOpen` forever and the creator's unused IMD budget is locked in the vault.\n- **Info:** for the page, contract-deployed and value templates, the vault still sells checks right up to the deadline. An answer takes minutes and must be issued by the deadline, so a check bought in those last minutes costs 0.5 IMD and an attempt, and its answer is always refused.\n- **Info:** for the two on-chain-evidence templates, a verdict is accepted even when no panel members agreed. This is documented protocol behaviour, recorded so reviewers can weigh it for large tranches.\n\nI couldn't touch `docs/VERIFICATION.md` because only `test/**` is in scope. It already ","treeHash":"15b27abff51c3e3b934ee29d2932a7a7206bece9","usage":{"cachedInputTokens":1723168,"inputTokens":38,"model":"claude-opus-5-5","outputTokens":47498,"runtime":"claude","turns":26,"wallClockMs":687703}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"8a05ec1ea94411ea","findings":[{"citation":"resolved","description":"Boundary x invariant seam. For PageContains, ContractDeployed and ValueAtLeast the check window closes at `deadline` inclusive (`_checkDeadline`, src/KeptVault.sol:596) while the callback refuses any attestation whose `issuedAt` is later than `deadline`. The oracle answers minutes after the request, so a check bought in the last minutes before the deadline (or at the deadline itself) is paid for, counts as an attempt, and is then refused regardless of the answer. Because the refusal is a revert, the Intake records the delivery as failed and does not retry, and the milestone stays in flight for ANSWER_TIMEOUT (1 day). `checkOpen` reports (true, true) at that moment, so a front end following the view will spend the budget on a check that cannot be answered in time. The window should close early enough for an answer to be issued before the deadline (deadline minus an oracle-latency allowance), or `checkOpen` should report false in that band; alternatively the snapshot-time rule could key on `askedAt` (when the relative window was resolved) instead of the signing time. Note: the existing fuzz test testFuzz_snapshotRejectsVerdictIssuedAfterDeadline asserts the revert itself as intended, so this is about the boundary left open for the purchase, not the revert.","line":364,"path":"src/KeptVault.sol","reproduction":"PageContains milestone, deadline D = T0 + 7 days, budget 10 IMD. At D - 60 s: checkOpen(id,0) returns (true,true); beneficiary calls check(id,0): budget drops by 0.5 IMD, attempts = 1. The panel answers true and signs at D + 60 s (issuedAt = D + 60). Intake delivers: onOracleResult reverts InvalidAttestation (issuedAt > deadline). Expected by the buyer: a kept verdict for a check the contract sold as open. Actual: 0.5 IMD spent, check stuck in flight (check again reverts CheckInFlight for a day, then CheckWindowClosed), settle at D + 3 days + 1 s burns the 100-token tranche. Verified in test/scratch/LowRepro.t.sol::test_snapshotCheckNearDeadlineIsDoomed.","severity":"low","snippet":"        if (m.spec.kind != Questions.Kind.GithubRelease && a.issuedAt > m.deadline) {","title":"Snapshot checks bought within the oracle's latency of the deadline can never succeed, yet checkOpen and check accept them"},{"citation":"resolved","description":"Boundary. `askedAt` is the sequencer's block timestamp at the request; `issuedAt` is the oracle's wall clock. The consumer base already tolerates `issuedAt` up to ISSUED_AT_TOLERANCE (5 min) ahead of block time because the two clocks differ, but the reverse comparison here is strict: an answer stamped even one second before the request block's timestamp is refused. On an Arbitrum-family chain such as Robinhood Chain the sequencer's block timestamp may run ahead of wall-clock time, so an honest answer issued promptly can carry issuedAt < askedAt. The refusal is a revert inside the 200k callback, so the paid check is lost and the milestone stays in flight for a day. Suggested fix: compare against `askedAt - ISSUED_AT_TOLERANCE` (or the askedAt block's timestamp minus a small allowance), keeping the intent of rejecting pre-signed answers.","line":360,"path":"src/KeptVault.sol","reproduction":"Standard pledge, check at block time T (askedAt = T). Attestation with issuedAt = T - 1, expiresAt = issuedAt + 1 day, correct signer, agreed 8/7/9, chainId 4663, delivered at T + 10 min. Expected: a verdict that is at most one second 'early' is accepted like the 5-minute-late case is. Actual: onOracleResult reverts InvalidAttestation; the same attestation with issuedAt = T is accepted. Verified in test/scratch/LowRepro.t.sol::test_issuedAtOneSecondBeforeAskedAtIsRefused.","severity":"low","snippet":"                || a.issuedAt < m.askedAt || a.expiresAt < a.issuedAt || a.answer.length != 32","title":"Attestation issuedAt earlier than the request block's timestamp is refused with no skew tolerance, unlike the forward tolerance"},{"citation":"resolved","description":"Boundary x precision (all-or-nothing threshold). The rebate pays the whole check price or nothing. Any Referee Fund balance below the current price (donations that do not divide evenly by 0.5 IMD, or a remainder left after a series of rebates) can never be used: there is no partial rebate and no function that moves `refereeFund` anywhere else, and the hook sweeps arbitrary fee amounts into it, so the fund will almost always hold such a remainder. If the price is ever raised by the Intake, a larger balance becomes dead the same way. Minimal fix: rebate `min(price, refereeFund)` so the fund is always drained to zero, or let the owner top the remainder up to a whole price.","line":380,"path":"src/KeptVault.sol","reproduction":"fundReferee(0.4 ether) with price 0.5 ether; create a standard pledge with budget 10 IMD; check; deliver a kept verdict. Expected: the fund contributes what it has toward the kept milestone's check. Actual: refereeFund stays 0.4 ether, the pledge budget stays 9.5 ether, and no call can ever move the 0.4 IMD. Verified in test/scratch/LowRepro.t.sol::test_refereeFundRemainderBelowPriceIsDead.","severity":"low","snippet":"        if (price != 0 && refereeFund >= price) {","title":"Referee Fund remainder smaller than one check price is never rebated and has no exit"}],"hash":"8e1df04c1b7d412d22df75817fc1458c539693d6521ed8e37264aed9056c23b0","nodeId":"49ea3bec-0867-4490-b4ae-16ed3bbe9b19","outcome":"completed","summary":"Review complete. The findings file is written and validated, and the existing offline unit suites pass (95 tests, invariant and fork suites excluded for time).\n\n**Area covered:** Math Precision, Boundary and Numerical Gap guides against `src/KeptVault.sol` and `src/libraries/Questions.sol`, with the hook and token given lighter rows since this launch deploys only the vault.\n\n**What holds**\n\n- The callback fits the Intake's 200,000 gas stipend even at maximum-length strings with the kept-plus-rebate path. Foundry's in-test numbers are warm-biased, so I rehearsed it on a local anvil chain and measured through anvil's own `eth_call` in a fresh transaction. Worst case is 165,812 gas, ordinary strings 148,240.\n- The calendar math in `isoDate` matches Python's UTC formatting on twelve vectors including both leap-day cases and the 2100 non-leap boundary. The slither divide-before-multiply leads are the algorithm, not a defect.\n- Sum-to-uint128 downcast, deadline bounds, panel bounds, the settle versus check window edges, and the budget and totalBudgets accounting all trace clean. The slither reentrancy and strict-equality leads on the vault are sentinel checks or guarded paths, not findings.\n\n**Findings, all low, each with a passing reproduction in test/scratch/LowRepro.t.sol**\n\n1. Snapshot-kind checks may be bought up to the deadline, but the callback refuses any verdict signed after it, so a check bought inside the oracle's latency is paid for and then reverted, with the tranche burned later. The view reports it as open and funded at that moment.\n2. The callback refuses an `issuedAt` even one second before the request block's timestamp, with no skew tolerance, while the forward direction tolerates five minutes. On a sequencer chain this can discard an honest prompt answer.\n3. The Referee Fund rebates all or nothing, so any remainder below one check price is permanently unusable and has no exit.\n\nNo critical or high defects were found in the assigned area, so no proof test files were attached. Scratch files live only under test/scratch and the anvil process was stopped.","treeHash":null,"usage":{"cachedInputTokens":2187347,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":53183,"runtime":"claude","turns":37,"wallClockMs":914814}},{"artifacts":[],"attempt":1,"bundleHash":"bfd5e8f731dec674971a696250086c16fb3367626f455320937821b7453ded2e","device":"6d41a24119881b34","findings":[],"hash":"9e04d0c51f9ec62bc93bdc1bbbc0d9c343b24c453eabfeed9dc9a387607383ae","nodeId":"dc7ba853-7cec-467f-ac09-bb006e486a65","outcome":"completed","summary":"Created [launch.json](/home/imd-worker/.identitymd/work/792f6f16-ef1b-43bf-84bd-8703e8375735/dc7ba853-7cec-467f-ac09-bb006e486a65/launch.json) for only `KeptVault`, using `$owner` and all seven approved constructor arguments.\n\nValidation passed:\n\n- Manifest structure and compiled ABI checks.\n- `forge build --offline`.\n- Seeded `forge test --offline`: 98 passed, 0 failed; fork suite skipped.\n\nOnly `launch.json` changed.","treeHash":"8186f98a9cec4ac07b59723c6ab021073a6b2ddd","usage":{"cachedInputTokens":461056,"inputTokens":39745,"model":"gpt-6-astra","outputTokens":3365,"runtime":"codex","turns":5,"wallClockMs":232789}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"02f22d6f13810ca8","findings":[{"citation":"resolved","description":"Access x asymmetry seam. `clearStale` has no caller restriction, while the only party who pays for the check and who is harmed by clearing it is the beneficiary (`_check` is beneficiary-only). `onOracleResult` itself never checks ANSWER_TIMEOUT: a verdict that arrives one second after `askedAt + 1 day` is still accepted as long as `m.inFlight == requestId` (line 350). So the request is not dead at the timeout; it is only killable. Any third party can watch the mempool for the Intake's delivery transaction and front-run it with `clearStale`, after which the delivery reverts with UnknownRequest and the attempt (0.5 IMD) is spent. The beneficiary is never consulted. For a GithubRelease milestone checked near `deadline + GRACE`, or for a milestone on its third attempt, the window cannot be reopened and `settle` burns the tranche. Preconditions: the oracle is more than ANSWER_TIMEOUT late, which the protocol reference says can happen (an answer 'can be withheld or lost'). Minimal fix: restrict `clearStale` to the beneficiary (or the creator) while the milestone's check window is still open, or make `onOracleResult` refuse answers after the timeout so the timeout is symmetric for both sides and clearing has no racing effect.","line":389,"path":"src/KeptVault.sol","reproduction":"Verified in test/scratch (passes on current code, showing the behaviour): creator locks 100 TEAM behind one GithubRelease milestone, beneficiary calls check(id,0) at T0 (requestId R, attempts=1). warp to T0 + 1 days. stranger calls clearStale(id,0): succeeds, m.inFlight = 0. The Intake then delivers a signer-valid kept=true attestation for R: the callback reverts UnknownRequest at line 350, attempts stays 1, the IMD paid for the check is gone. Expected: a valid verdict for the beneficiary's own request should not be refusable by an unrelated caller; actual: an unrelated caller decides whether the paid verdict counts. If the check was the third attempt, or the window is closed, settle(id,0) after deadline+GRACE burns the 100 TEAM.","severity":"low","snippet":"    function clearStale(uint256 pledgeId, uint8 index) external nonReentrant {\n        Pledge storage p = _pledge(pledgeId);\n        Milestone storage m = _milestone(p, pledgeId, index);\n        if (m.inFlight == bytes32(0)) revert NoCheckInFlight();\n        if (block.timestamp < uint256(m.askedAt) + ANSWER_TIMEOUT) revert TooEarly();\n        _clear(pledgeId, index, m);","title":"Permissionless clearStale lets a stranger turn a late but valid kept verdict into a wasted attempt or a burn"},{"citation":"resolved","description":"Economics x asymmetry seam. The rebate at lines 380-385 pays `inFlightPrice` into the pledge's budget for every kept milestone, regardless of what was locked (any ERC-20, amount >= 1 wei), who the beneficiary is (creator may name themselves) or whether the question had any stake. `createPledge`, `check`, `settle` and `withdrawBudget` are all open, and the question templates include ones that are already true at creation (ContractDeployed on an address that already has code, ValueAtLeast with threshold 1 on totalSupply()). A caller therefore cycles: fund budget P, check, verdict kept, rebate P from refereeFund into budget, settle, withdrawBudget returns P to the creator. The caller's IMD balance is unchanged, the refereeFund falls by P per milestone, and the IMD ends in the Intake's treasury. With 8 milestones per pledge and MAX_ATTEMPTS irrelevant (one check each), 4 IMD of donations go per pledge; repeated pledges empty the fund entirely. Only gas is spent. Hook sweeps (`KeptHook.sweep` -> `fundReferee`) and donors therefore subsidise whoever runs the cycle, not genuine teams. Minimal fix: tie the rebate to stake, e.g. require a minimum locked amount per rebated milestone, rebate only once per pledge, or only rebate milestones whose creator != beneficiary, or let the owner gate rebates per pledge.","line":380,"path":"src/KeptVault.sol","reproduction":"Verified in test/scratch (passes on current code, showing the behaviour): donor calls fundReferee(4 ether). stranger holds 4 IMD and 8 wei of any ERC-20, calls createPledge(token, beneficiary=stranger, name, 8 x {kind: ContractDeployed, chainId: 4663, target: <IMD token address, already has code>, amount: 1, deadline: now+2h}, budget: 4 ether). For i in 0..7: stranger check(id,i) (budget -0.5), Intake delivers signed kept=true -> rebate: refereeFund -0.5, budget +0.5; settle(id,i) pays 1 wei to stranger. withdrawBudget(id) returns 4 ether to stranger. Result: refereeFund == 0, stranger IMD unchanged (4 ether), Intake treasury +4 ether. Expected: the fund rebates teams that kept real milestones; actual: anyone can convert the whole fund into oracle fees for their own trivial questions.","severity":"low","snippet":"        if (price != 0 && refereeFund >= price) {","title":"Referee Fund rebates any kept milestone, so a self-dealing dust pledge drains donations to the Intake treasury at zero net cost"},{"citation":"resolved","description":"Access control. Ownership moves in one call with no acceptance by the new owner and no validation (zero is documented as renounce, but any other wrong address is equally final). The owner's only material power is `proposeProtocol`, which is the sole way the vault can follow IMD rotating the oracle signer (a single hot EOA, 0x5598...) or retiring Intake v1. If the owner is lost, every future `onOracleResult` fails `BadSignature` at line 629 once the key rotates, every open milestone burns at `deadline + GRACE`, and budgets of pledges with deadlines up to MAX_LEAD (3 years) stay locked until then. The in-flight bindings (`inFlightSigner`) do not help new checks. Also note `executeProtocol` is permissionless, so a proposal left pending by an owner who then renounces or loses the key is applied by anyone and cannot be cancelled. Minimal fix: two-step transfer (`pendingOwner` + `acceptOwner`), keeping explicit renounce as a separate call.","line":588,"path":"src/KeptVault.sol","reproduction":"State: vault deployed with owner = $owner. Owner calls setOwner(0x1234...typo). Call proposeProtocol(...) from $owner -> revert OnlyOwner; from the typo address nobody holds the key. IMD later rotates the oracle signer. Beneficiary check(id,0) succeeds and pays 0.5 IMD; the Intake delivers an attestation signed by the new key; onOracleResult reverts BadSignature; after ANSWER_TIMEOUT the check is cleared; the same happens for every attempt; settle after deadline+GRACE burns the tranche. Expected: a transfer to a wrong address is recoverable until accepted; actual: it is final in one call.","severity":"low","snippet":"    function setOwner(address next) external onlyOwner {\n        owner = next;\n        emit OwnerChanged(next);","title":"setOwner is single-step: a mistyped address irrevocably loses the only power that can follow an oracle signer or Intake rotation"},{"citation":"resolved","description":"Documented privileged power, recorded as the Trust Gap guide requires (access x asymmetry, seam 3), not a permission bypass. The timelock cannot be bypassed (`_setProtocol` is reachable only from the constructor and `executeProtocol`), in-flight checks keep their old intake and signer, and `check` remains beneficiary-only, so the owner alone cannot move tokens. But after executeProtocol the owner's intake and signer decide every subsequent verdict: with a colluding beneficiary (or on any pledge where the owner is the beneficiary) locked tokens are released without any oracle answer; by answering 'no' or never answering, every open milestone burns. Creators have no exit during the 7-day notice; their tokens and IMD budgets stay locked. The README and ADAPTATION.md already state this. Recorded so the judge has the concrete trace; no code change is required by the brief.","line":558,"path":"src/KeptVault.sol","reproduction":"Verified in test/scratch: creator locks 100 TEAM behind a GithubRelease milestone with beneficiary B. Owner deploys an Intake-shaped contract E and holds key K, calls proposeProtocol(E, action, addr(K)); warp 7 days; anyone calls executeProtocol(). B calls check(id,0): E takes 0.5 IMD and returns id R. E calls onOracleResult(R, attestation{kept=true, panelSize 9, quorum 7, agreed 8, chainId 4663}, sig by K): accepted. settle(id,0) transfers 100 TEAM to B. No real oracle verdict was involved.","severity":"info","snippet":"    function proposeProtocol(address intake_, bytes32 action_, address signer_) external onlyOwner {","title":"Trust assumption: owner can, after the 7-day notice, replace Intake and signer and so release or burn every open pledge; locked pledges cannot exit during notice"}],"hash":"a70756327da0d408ffe772a64fba60f20167f98e9ad8b613c35955f17b216bfd","nodeId":"0e6eb198-7a52-49b1-80e1-6acf9d10847c","outcome":"completed","summary":"The review is complete and the findings file is written and validated against the tree.\n\n**What I covered**\n\nI audited `src/KeptVault.sol` against the Access Control, Trust Gap and Asymmetry guides. I mapped every role and guard, diffed the paired surfaces (check/onOracleResult, settle Kept/Broken, fund/withdrawBudget, propose/execute/cancel, check/clearStale), and checked the owner's powers for timelock bypasses and in-flight value redirection. The existing offline suite passes (97 tests, invariant and fork suites excluded for time). Each lead below was reproduced with a scratch Foundry test before being reported.\n\n**Findings in `.imd-findings.json`**\n\n- **Low, `clearStale` is permissionless but `onOracleResult` has no timeout check.** A stranger can front-run a late delivery at the one-day mark and turn a valid kept verdict into a wasted attempt, or a burn when the window or attempts are exhausted.\n- **Low, the Referee Fund rebates any kept milestone.** A dust pledge with trivially true questions and a self-beneficiary cycles budget through check, rebate, settle and withdraw at zero net cost, emptying donations into the Intake treasury.\n- **Low, `setOwner` is single-step.** A mistyped address permanently loses the only power that can follow an oracle signer or Intake rotation, after which every open milestone burns.\n- **Info, documented trust assumption.** After the 7-day notice the owner's chosen Intake and signer decide every verdict, and creators cannot exit during the notice. Recorded with a concrete trace, not as a bypass.\n\n**What held**\n\nThe callback binding is sound: only the intake that took a request may answer, only for the live in-flight id, verified against the signer at ask time and consumed once. The timelock cannot be bypassed, no owner or rescue path touches locked tokens, and the launch constructor arguments match the oracle-consumer reference. All 22 entry points plus four invariant rows are in the coverage record. No critical or high findings, so no proof files were attached.","treeHash":null,"usage":{"cachedInputTokens":778205,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":31346,"runtime":"claude","turns":23,"wallClockMs":622885}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e9049e5b12ba53ba","findings":[{"citation":"resolved","description":"check() is open from creation until deadline + GRACE (3 days), and Questions.body always sends a relative window {\"hours\":1} that ends when the check is asked. Only the GithubRelease question mentions the deadline ('published at or before <deadline>'). The PageContains ('Fetch ... now'), ContractDeployed and ValueAtLeast ('at the window's closing block') questions do not mention the deadline. onOracleResult only requires a.issuedAt >= askedAt and never compares a.issuedAt or a.toBlock with m.deadline. So for three of the four templates the promise is really 'true at some instant the team picks between creation and deadline + 3 days', not 'done by the deadline'. A tranche that should burn is paid to the beneficiary when delivery comes up to 3 days late. And because Kept is final, a value or page condition that holds for only a moment, at a block the team times (a page edited for one minute; a balance or totalSupply() raised just before check() and lowered right after), releases the tranche for good.","line":288,"path":"src/KeptVault.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {KeptVault} from \"src/KeptVault.sol\";\nimport {OracleAttestation} from \"src/OracleAttestation.sol\";\nimport {Questions} from \"src/libraries/Questions.sol\";\nimport {IIntake} from \"src/interfaces/IIntake.sol\";\n\ncontract Tok is ERC20(\"T\", \"T\") {\n    function mint(address to, uint256 v) external { _mint(to, v); }\n}\n\ncontract Intake is IIntake {\n    uint256 n;\n    function priceOf(bytes32, address) external pure returns (uint256) { return 0.5 ether; }\n    function request(bytes32, bytes calldata, Callback calldata, address asset, uint256 amount)\n        external payable returns (bytes32)\n    {\n        IERC20(asset).transferFrom(msg.sender, address(1), amount);\n        return keccak256(abi.encode(++n));\n    }\n    function deliver(address t, bytes32 id, OracleAttestation.Attestation calldata a, bytes calldata s) external {\n        KeptVault(t).onOracleResult{gas: 200_000}(id, a, s);\n    }\n}\n\ncontract LateTest is Test {\n    bytes32 constant ACTION = 0x6f7261636c652e72657175657374406f7261636c652d31000000000000000000;\n    uint256 key = 0xA11CE;\n    KeptVault vault;\n    Intake intake;\n    Tok imd;\n    Tok team;\n    address creator = makeAddr(\"creator\");\n    address beneficiary = makeAddr(\"beneficiary\");\n\n    function setUp() public {\n        vm.warp(1_791_000_000);\n        imd = new Tok();\n        team = new Tok();\n        intake = new Intake();\n        vault = new KeptVault(makeAddr(\"owner\"), address(intake), address(imd), ACTION, vm.addr(key), 9, 7);\n        team.mint(creator, 100 ether);\n        imd.mint(creator, 10 ether);\n        vm.startPrank(creator);\n        team.approve(address(vault), type(uint256).max);\n        imd.approve(address(vault), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function digestOf(OracleAttestation.Attestation calldata a) external view returns (bytes32) {\n        return vault.attestationDigest(a);\n    }\n\n    function _kept(uint64 chainId) internal returns (OracleAttestation.Attestation memory a, bytes memory sig) {\n        a.requestId = keccak256(\"uuid\");\n        a.chainId = chainId;\n        a.answerType = 0;\n        a.answer = abi.encode(true);\n        a.panelSize = 9;\n        a.quorum = 7;\n        a.agreed = 9;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = a.issuedAt + 1 days;\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, this.digestOf(a));\n        sig = abi.encodePacked(r, s, v);\n    }\n\n    /// A ContractDeployed milestone with deadline D, delivered (deployed) at D + 2 days, is\n    /// released to the beneficiary: the question never mentions D, and `check` is open until D + 3 days.\n    function test_contractDeployedAfterDeadlineIsKept() public {\n        uint64 deadline = uint64(block.timestamp + 7 days);\n        KeptVault.MilestoneInput[] memory ms = new KeptVault.MilestoneInput[](1);\n        ms[0].kind = Questions.Kind.ContractDeployed;\n        ms[0].deadline = deadline;\n        ms[0].amount = 100 ether;\n        ms[0].chainId = 4663;\n        ms[0].target = address(0xC0FFEE);\n        ms[0].title = \"V2 deployed\";\n        vm.prank(creator);\n        uint256 id = vault.createPledge(IERC20(address(team)), beneficiary, \"p\", ms, 1 ether);\n\n        // The team misses the deadline and deploys two days late.\n        vm.warp(deadline + 2 days);\n        vm.prank(creator);\n        bytes32 rid = vault.check(id, 0);\n        (OracleAttestation.Attestation memory a, bytes memory sig) = _kept(4663);\n        // An attestation issued after the deadline says nothing about the state at the deadline.\n        try intake.deliver(address(vault), rid, a, sig) {} catch {}\n        vm.warp(deadline + 3 days + 2 days);\n        vault.settle(id, 0);\n        assertEq(team.balanceOf(beneficiary), 0, \"late delivery was paid out instead of burned\");\n    }\n}","reproduction":"Milestone kind=ContractDeployed, chainId=4663, target=0xC0FFEE, deadline D=now+7d, amount 100e18. Nothing is deployed by D. At D+2d the team deploys at the target and calls check(id,0). The oracle truthfully answers true (the code exists at the closing block of the last hour), signed with issuedAt = D+2d. At D+5d settle(id,0) sends 100e18 to the beneficiary. Expected: Broken, tokens to 0x..dEaD, because the deadline was missed. Fix: for the panel/chain templates refuse check() after the deadline (or before it, if a point-in-time reading is not acceptable), and/or reject attestations with issuedAt > deadline for templates whose question does not pin the deadline; better, ask with an absolute window ending at the deadline block where the template allows it. The proof below fails now and passes once a late verdict is refused.","severity":"medium","snippet":"        if (block.timestamp > uint256(m.deadline) + GRACE) revert CheckWindowClosed();","title":"Deadline is not enforced for PageContains, ContractDeployed and ValueAtLeast: a milestone delivered up to 3 days late is released, and the team picks the instant a point-in-time condition is judged"},{"citation":"resolved","description":"createPledge takes a beneficiary separate from msg.sender, and check() lets either one spend the milestone's MAX_ATTEMPTS = 3 attempts at any time from creation on. The design note says 'a check can only ever help the team', which holds only when the creator and the beneficiary are the same party. A creator who locks tokens for a separate beneficiary (a grant or contractor escrow) and later wants out can call check() three times early, while the milestone truthfully reads false or the check simply times out. The attempts are then used up, the beneficiary's later valid proof is refused with AttemptsExhausted, and settle burns the tranche.","line":289,"path":"src/KeptVault.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {KeptVault} from \"src/KeptVault.sol\";\nimport {OracleAttestation} from \"src/OracleAttestation.sol\";\nimport {Questions} from \"src/libraries/Questions.sol\";\nimport {IIntake} from \"src/interfaces/IIntake.sol\";\n\ncontract Tok is ERC20(\"T\", \"T\") {\n    function mint(address to, uint256 v) external { _mint(to, v); }\n}\n\ncontract Intake is IIntake {\n    uint256 n;\n    function priceOf(bytes32, address) external pure returns (uint256) { return 0.5 ether; }\n    function request(bytes32, bytes calldata, Callback calldata, address asset, uint256 amount)\n        external payable returns (bytes32)\n    {\n        IERC20(asset).transferFrom(msg.sender, address(1), amount);\n        return keccak256(abi.encode(++n));\n    }\n    function deliver(address t, bytes32 id, OracleAttestation.Attestation calldata a, bytes calldata s) external {\n        KeptVault(t).onOracleResult{gas: 200_000}(id, a, s);\n    }\n}\n\ncontract LateTest is Test {\n    bytes32 constant ACTION = 0x6f7261636c652e72657175657374406f7261636c652d31000000000000000000;\n    uint256 key = 0xA11CE;\n    KeptVault vault;\n    Intake intake;\n    Tok imd;\n    Tok team;\n    address creator = makeAddr(\"creator\");\n    address beneficiary = makeAddr(\"beneficiary\");\n\n    function setUp() public {\n        vm.warp(1_791_000_000);\n        imd = new Tok();\n        team = new Tok();\n        intake = new Intake();\n        vault = new KeptVault(makeAddr(\"owner\"), address(intake), address(imd), ACTION, vm.addr(key), 9, 7);\n        team.mint(creator, 100 ether);\n        imd.mint(creator, 10 ether);\n        vm.startPrank(creator);\n        team.approve(address(vault), type(uint256).max);\n        imd.approve(address(vault), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function digestOf(OracleAttestation.Attestation calldata a) external view returns (bytes32) {\n        return vault.attestationDigest(a);\n    }\n\n    function _kept(uint64 chainId) internal returns (OracleAttestation.Attestation memory a, bytes memory sig) {\n        a.requestId = keccak256(\"uuid\");\n        a.chainId = chainId;\n        a.answerType = 0;\n        a.answer = abi.encode(true);\n        a.panelSize = 9;\n        a.quorum = 7;\n        a.agreed = 9;\n        a.issuedAt = uint64(block.timestamp);\n        a.expiresAt = a.issuedAt + 1 days;\n        (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, this.digestOf(a));\n        sig = abi.encodePacked(r, s, v);\n    }\n\n    /// When creator and beneficiary differ, the creator can spend all attempts before the\n    /// deadline, so the beneficiary can never prove the milestone and it is burned.\n    function test_creatorExhaustsAttemptsBeforeBeneficiaryDelivers() public {\n        imd.mint(creator, 10 ether);\n        uint64 deadline = uint64(block.timestamp + 30 days);\n        KeptVault.MilestoneInput[] memory ms = new KeptVault.MilestoneInput[](1);\n        ms[0].kind = Questions.Kind.GithubRelease;\n        ms[0].deadline = deadline;\n        ms[0].amount = 100 ether;\n        ms[0].title = \"Ship\";\n        ms[0].a = \"kept-labs/app\";\n        ms[0].b = \"v1.0.0\";\n        vm.prank(creator);\n        uint256 id = vault.createPledge(IERC20(address(team)), beneficiary, \"p\", ms, 5 ether);\n        for (uint256 i; i < 3; ++i) {\n            vm.prank(creator);\n            vault.check(id, 0);\n            vm.warp(1_791_000_000 + (i + 1) * 1 days);\n            vault.clearStale(id, 0);\n        }\n        vm.warp(deadline - 1 hours); // beneficiary has shipped and asks for its verdict\n        vm.prank(beneficiary);\n        vault.check(id, 0);\n    }\n}","reproduction":"Pledge: creator C, beneficiary B (B != C), GithubRelease, deadline now+30d, budget 5 IMD. On days 0, 1 and 2, C calls check(id,0) and, after each 1-day timeout, clearStale(id,0) (or the oracle answers false because nothing has shipped yet). At deadline-1h B ships the release and calls check(id,0), which reverts AttemptsExhausted(). After deadline+3d settle burns 100e18. Expected: the beneficiary keeps a way to prove a milestone it delivered. Fix: reserve at least one attempt inside a window near the deadline, or let only the beneficiary spend attempts.","severity":"low","snippet":"        if (msg.sender != p.creator && msg.sender != p.beneficiary) revert NotAllowed();","title":"When creator != beneficiary, the creator can use up all 3 attempts before the deadline and force the tranche to burn"},{"citation":"resolved","description":"The price is read from intake.priceOf at call time and only bounded by p.budget. After a protocol change (owner-proposed, 7-day delay, anyone executes), or if the Intake reprices, the team's next routine check() pays any amount up to the full budget, and the TransferMismatch check accepts the pull because it equals the reported price. The caller has no maxPrice parameter.","line":293,"path":"src/KeptVault.sol","reproduction":"Pledge with a 100 IMD budget. The owner proposes intake = X, and after 7 days it is executed. X.priceOf returns 100e18. The beneficiary calls check(id,0) expecting 0.5 IMD. The vault approves 100e18, X pulls it, and the budget is 0. Expected: check() refuses a price above what the caller accepted (add a maxPrice argument or a per-pledge price cap).","severity":"low","snippet":"        uint256 price = target.priceOf(action, address(imd));","title":"check() pays whatever price the current Intake reports, with no cap, so an Intake changed through proposeProtocol can take a pledge's whole budget"},{"citation":"resolved","description":"_pullExact refuses fee-on-transfer deposits, but nothing tracks the vault's balance of each token after that. With a negative-rebase, balance-decaying or owner-confiscatable token, the vault's balance falls below the sum of p.locked across pledges. Earlier settles then pay in full out of other pledges' tokens, and the last settle of that token reverts. Its milestone can never be settled, and withdrawBudget for that pledge is blocked forever because p.open never reaches 0.","line":400,"path":"src/KeptVault.sol","reproduction":"Two pledges each lock 100 units of rebasing token R (vault balance 200). R rebases by -10% (vault balance 180). settle(pledge1) sends 100. settle(pledge2) tries to send 100 with a balance of 80 and reverts. Pledge2's open stays 1, so withdrawBudget(pledge2) reverts NotOpen, and its IMD budget is stuck. Expected: either pro-rata accounting per token or documented refusal of such tokens.","severity":"low","snippet":"        p.token.safeTransfer(to, amount);","title":"Pledges that share a token share one balance: a token whose balances shrink after deposit leaves the last settle of that token unpayable"},{"citation":"resolved","description":"The contract is fully configured in its constructor, which makes no external calls, so it deploys on an empty chain. The owner ($owner) can still replace the signer, Intake and action after a public 7-day delay, change the panel for future pledges, and transfer or renounce ownership. The oracle-consumer reference requires these to stay owner-settable, so this is not removed. Note what it allows: tokens already locked cannot leave during the 7-day notice, and an owner-chosen signer can sign Kept for any check the team asks after executeProtocol. The adapter should keep the delay and decide whether the policy accepts it. The brief's intake_ 0x1397434cd35e8a9c8ac312a61d3a285eb31dea56 is Intake version 1, which is still served. The reference recommends version 2 (0xa43e6f75ee006411f79ac1c84120606c2330de82) for new contracts, but KeptVault only calls request(), which both versions support, so the brief's address works. The other constructor arguments (IMD 0x5f7b...7127, action bytes32 'oracle.request@oracle-1', signer 0x5598...2982, panel 9 / quorum 7) match the reference and pass _setPanel.","line":519,"path":"src/KeptVault.sol","reproduction":"State: the vault is deployed with owner O. O calls proposeProtocol(intake, action, S') with S' a key O holds. After 7 days anyone calls executeProtocol(). The team calls check() on an unproven milestone, O signs answer=true with S', and settle releases the tranche, which should have burned. Expected per the brief: only an IMD oracle verdict releases tokens. Today this rests on O's honesty plus the 7-day public notice.","severity":"info","snippet":"    function proposeProtocol(address intake_, bytes32 action_, address signer_) external onlyOwner {","title":"Owner-settable oracle signer, Intake and action after deployment (timelocked), and the brief's Intake is version 1"},{"citation":"resolved","description":"Read in full: src/KeptVault.sol, src/OracleAttestation.sol (struct, type string and domain match the protocol: 15 fields, 'IdentityMD Oracle' v2), src/libraries/Questions.sol, src/interfaces/IIntake.sol. I also read the test fixtures and mock intake, and the offline suite passes (79 tests). KeptVault runtime is 20,337 B, and the source uses no DELEGATECALL, CALLCODE or SELFDESTRUCT. src/KeptHook.sol, src/KeptToken.sol, src/libraries/HookFlags.sol and SpecifiedAmount.sol are not part of this deployment and were not audited. Not reached: the live Robinhood Intake 0x1397...ea56, IMD 0x5f7b...7127 and the PoolManager. No fork was run, so the docs/VERIFICATION.md fork rehearsal was not re-checked, and the question bodies were not re-sent to POST /requests/check.","line":18,"path":"src/KeptVault.sol","reproduction":"n/a: scope statement. Checked: the 200k-gas callback path passes in the existing suite (MockIntake gas 200_000). A wrong sender, an unknown or settled request, an expired or tampered attestation, a reused oracle requestId (consumed) and a signer rotation in flight are all refused in KeptVault.onOracleResult.","severity":"info","snippet":"contract KeptVault is OracleAttestationConsumer, ReentrancyGuard {","title":"Scope: contracts read and not reached"}],"hash":"bdfe59a5a93c990b62fb013c75e5be5485c06e1bcd01ba3573b25526d2b0142d","nodeId":"aca9c941-305c-42f2-a187-f56d4d776c38","outcome":"completed","summary":"I audited KeptVault and found no critical or high issues. There is one medium, three lows and two info notes, all in `.imd-findings.json`. No repository files were changed: I deleted my scratch tests, and the tree is clean. The two findings that come with tests both fail on the current code for the reason stated.\n\n**Medium: `src/KeptVault.sol:288`.** For three of the four milestone templates, the deadline is not actually enforced. `check()` stays open until three days after the deadline, and every question asks about \"the last hour\" before the check. Only the GitHub-release question mentions the deadline; the page-text, contract-deployed and value-threshold questions don't. The vault also never compares the answer's timestamp with the deadline.\n- **Late delivery is paid:** in my test, a contract deployed 2 days after its deadline was checked, judged true, and its 100e18 tranche went to the beneficiary instead of being burned.\n- **The team picks the moment:** a condition that holds only briefly (a page edited for a minute, a value pumped just before the check) also counts, because a \"kept\" result is final.\n\n**Lows:**\n- **`:289`, attempts can be used up deliberately:** if the creator and the beneficiary are different people, the creator can spend all 3 check attempts early. The beneficiary's later, valid proof is then refused (`AttemptsExhausted`) and the tranche burns. My test reproduces this.\n- **`:293`, no price cap on a check:** `check()` pays whatever price the current Intake reports. If the owner switches the Intake (after the 7-day wait), the team's next routine check can be charged that pledge's whole IMD budget.\n- **`:400`, tokens whose balances shrink:** with a rebasing or decaying token, pledges using the same token draw on one shared balance. The last pledge to settle then can't be paid, and its unused IMD budget is stuck for good.\n\n**Info:**\n- **`:519`, owner controls the protocol settings:** after a 7-day public wait, the owner can replace the oracle signer, Intake and action. The oracle reference requires these to stay changeable, so I didn't flag them as forbidden. But an owner who installs their own signer could approve milestones that should have burned.\n- **Intake version:** the brief's Intake address is version 1. It still works because the vault only calls `request()`, though version 2 is recommended for new contracts. The other constructor arguments match the reference, and the constructor makes no outside calls.\n\n**What I read:** `KeptVault.sol`, `OracleAttestation.sol`, `Questions.sol`, `IIntake.sol`, plus the test fixtures and mocks. The offline suite passes (79 tests), and the vault's deployed code is 20,337 bytes with no forbidden opcodes in the source.\n\n**What I didn't reach:**\n- **Live contracts:** I didn't run a fork, so the live Robinhood Intake, IMD and PoolManager weren't checked, and neither was the fork rehearsal in `docs/VERIFICATION.md`.\n- **Question bodies:** I didn't re-send them to `POST /requests/check`.\n- **Out of scope:** `KeptHook`, `KeptToken` and the other libraries aren't part of this deployment, so I didn't audit them.","treeHash":null,"usage":{"cachedInputTokens":875846,"inputTokens":28,"model":"claude-opus-5-5","outputTokens":19655,"runtime":"claude","turns":15,"wallClockMs":516642}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"be306690d4a9deec","findings":[{"citation":"resolved","description":"Merged from audit_flow, audit_economics, audit_math and write_foundry_tests (same root cause). For PageContains, ContractDeployed and ValueAtLeast, _check (line 304, `if (block.timestamp > _checkDeadline(m)) revert CheckWindowClosed();`) and _checkOpen (line 549) treat the window as open up to and including `deadline`, while onOracleResult refuses any attestation with `a.issuedAt > m.deadline` (line 364) and `a.issuedAt < m.askedAt` (line 360). The panel signs minutes after the request, so a check bought within that latency of the deadline can only be honoured by an attestation issued in a sub-minute slot the oracle cannot hit. The seller debits the budget, counts an attempt, pays the Intake 0.5 IMD, and the acceptor then reverts the only answer the request will ever get. Because the refusal is a revert, the Intake records the delivery as failed and never retries; the request stays in flight for ANSWER_TIMEOUT and afterwards `block.timestamp > deadline` so no new check can be bought. If this was the last attempt or the only check, the tranche burns at deadline + GRACE although the oracle attested it kept. The README tells users to ask early, but the contract's own view and seller contradict its acceptor. Minimal fix preserving the design: for snapshot kinds, close _check and _checkOpen a fixed lead (e.g. 30 minutes) before the deadline so the vault never sells a request it cannot accept; or record the refused-but-signed verdict without reverting so the check is at least cleared immediately.","line":364,"path":"src/KeptVault.sol","reproduction":"VaultFixture (mock Intake, price 0.5 IMD, signer 0xA11CE). creator: createPledge(TEAM, beneficiary, one PageContains milestone, deadline D = T0+2h, amount 100e18, budget 1e18). warp(D-60): checkOpen(id,0) == (true,true); beneficiary check(id,0) succeeds, budget 0.5e18, attempts 1, 0.5 IMD leaves the vault. warp(D+120): Intake delivers a correctly signed true attestation (panelSize 9, quorum 7, agreed 8, chainId 4663, issuedAt D+120, expiresAt +1d). Expected: verdict recorded or the purchase refused up front. Actual: callback reverts InvalidAttestation(); check(id,0) reverts CheckInFlight() until D+1d, then CheckWindowClosed(); settle(id,0) at D+3d+1 transfers 100e18 TEAM to 0x...dEaD. Reproduced in test/scratch/Review.t.sol::test_snapshotCheckAtDeadlineIsDoomed (passes on the current code, demonstrating the behaviour).","severity":"low","snippet":"        if (m.spec.kind != Questions.Kind.GithubRelease && a.issuedAt > m.deadline) {\n            revert InvalidAttestation();\n        }","title":"Snapshot templates sell checks inside the oracle's latency window that no attestation can satisfy: price and attempt spent, tranche can burn despite a true answer"},{"citation":"resolved","description":"Merged from audit_permissions and audit_economics. onOracleResult never checks ANSWER_TIMEOUT itself: a verdict delivered at askedAt + 1 day + 1 s is accepted as long as `m.inFlight == requestId` (line 350). So the request is not dead at the timeout, only killable, and anyone may kill it: clearStale has no caller restriction and zeroes m.inFlight exactly one day after the check. The attestation the oracle signs is valid for VALID_FOR = 1 day from issuedAt, which is later than askedAt, so there is a real window in which the attestation is still valid but a third party (any holder of the locked token benefits from a burn) can front-run the Intake's delivery with clearStale. The delivery then reverts UnknownRequest, the Intake does not retry, the 0.5 IMD and the attempt are gone, and for a snapshot milestone whose deadline has passed no new check can be bought, so settle burns the tranche. Minimal fix preserving the design: restrict clearStale to the beneficiary (the party who paid for the check), or make onOracleResult refuse answers after askedAt + ANSWER_TIMEOUT so the timeout is symmetric and clearing cannot race a valid delivery.","line":389,"path":"src/KeptVault.sol","reproduction":"VaultFixture. createPledge(TEAM, beneficiary, one PageContains milestone, deadline T0+36h, amount 100e18, budget 1e18). beneficiary check(id,0) at T0 -> rid, attempts 1. Oracle signs true for rid with issuedAt T0+10min, expiresAt T0+1d+10min, panel 9/7/8, chainId 4663. warp(T0+1d): stranger clearStale(id,0) succeeds, m.inFlight = 0. warp(T0+1d+1): Intake delivers (rid, a, sig). Expected: a valid verdict for the beneficiary's own request is recorded. Actual: callback reverts UnknownRequest(), outcome stays Open with attempts 1. warp(T0+36h+3d+1): settle(id,0) burns 100e18 TEAM. Reproduced in test/scratch/Review.t.sol::test_clearStaleRaceDiscardsValidVerdict (passes on current code).","severity":"low","snippet":"    function clearStale(uint256 pledgeId, uint8 index) external nonReentrant {\n        Pledge storage p = _pledge(pledgeId);\n        Milestone storage m = _milestone(p, pledgeId, index);\n        if (m.inFlight == bytes32(0)) revert NoCheckInFlight();\n        if (block.timestamp < uint256(m.askedAt) + ANSWER_TIMEOUT) revert TooEarly();\n        _clear(pledgeId, index, m);\n    }","title":"Permissionless clearStale (and the settle/_check clear paths) discard a still-valid kept verdict that arrives after ANSWER_TIMEOUT; the paid check is lost and the milestone can burn"},{"citation":"resolved","description":"Merged from audit_permissions and audit_economics. The rebate pays inFlightPrice from refereeFund into the pledge's budget for every Kept milestone, with no condition on the locked token, the locked amount (1 wei suffices), the beneficiary (the creator may name themselves) or the question. ContractDeployed on an address that already has code, or ValueAtLeast with threshold 1 on totalSupply(), is true at creation. A caller cycles createPledge(budget P) -> check -> kept -> rebate P -> settle -> withdrawBudget(P): their IMD is unchanged, refereeFund falls by P per milestone (up to 8 per pledge), and the IMD ends in the Intake treasury. Hook sweeps and donations therefore subsidise whoever runs the cycle rather than genuine teams. No direct theft, so low. Minimal mitigation: rebate only when creator != beneficiary and the locked amount is above a minimum, or let the owner gate rebates per pledge or cap them per creator.","line":380,"path":"src/KeptVault.sol","reproduction":"VaultFixture. creator fundReferee(1e18). stranger holds 1000 IMD and 8 wei of a fresh ERC-20 Junk. Twice: stranger createPledge(Junk, beneficiary = stranger, 'x', [ContractDeployed chainId 4663 target = <address with code>, deadline T0+2h, amount 1], budget 0.5e18); stranger check(id,0); Intake delivers signed true; settle(id,0); withdrawBudget(id). Expected: the fund rebates teams that kept real milestones. Actual: refereeFund == 0, stranger's IMD balance unchanged, Junk balance back to 8. Reproduced in test/scratch/Review.t.sol::test_refereeFundDrain (passes on current code).","severity":"low","snippet":"        if (price != 0 && refereeFund >= price) {\n            refereeFund -= price;\n            p.budget += price;\n            totalBudgets += price;\n            emit Rebated(t.pledgeId, t.index, price);\n        }","title":"Referee Fund rebates any kept milestone, so trivially true self-pledges of a worthless token drain donations into the Intake treasury at zero net cost"},{"citation":"resolved","description":"Merged from audit_economics and write_foundry_tests. settle (line 422, `p.token.safeTransfer(to, amount)`) is the only way to finish a milestone and withdrawBudget requires p.open == 0. If the pledge token refuses the transfer (a blocklisting or pausable token that blocks the beneficiary after a Kept verdict, or blocks 0x...dEaD), settle reverts on every call, p.open never reaches 0, and the creator's unused IMD budget, a healthy asset nothing can ever spend again (check reverts NotOpen or CheckWindowClosed), is locked for good. The README documents transfer-restricted tokens as unsupported and the budget lock as a consequence, but the NatSpec at lines 426-427 states the opposite intent ('a refund can never block a payout') while a blocked payout blocks the refund. Only that pledge is affected. Minimal fix: let withdrawBudget run once no milestone can still buy a check (every milestone settled or outcome != Open or past _checkDeadline with nothing in flight), which keeps the budget available exactly as long as it can be spent.","line":430,"path":"src/KeptVault.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {KeptVault} from \"src/KeptVault.sol\";\nimport {Questions} from \"src/libraries/Questions.sol\";\nimport {IIntake} from \"src/interfaces/IIntake.sol\";\n\ncontract BlockToken is ERC20 {\n    mapping(address => bool) public blocked;\n    constructor() ERC20(\"B\", \"B\") {}\n    function mint(address to, uint256 a) external { _mint(to, a); }\n    function setBlocked(address a, bool b) external { blocked[a] = b; }\n    function _update(address f, address t, uint256 v) internal override {\n        require(!blocked[t], \"blocked\");\n        super._update(f, t, v);\n    }\n}\n\ncontract NoIntake {\n    function priceOf(bytes32, address) external pure returns (uint256) { return 0.5 ether; }\n}\n\ncontract BlocklistTest is Test {\n    function test_blockedBurnAddressStrandsBudget() public {\n        vm.warp(1_791_000_000);\n        BlockToken team = new BlockToken();\n        BlockToken imd = new BlockToken();\n        NoIntake intake = new NoIntake();\n        address owner = makeAddr(\"owner\");\n        address creator = makeAddr(\"creator\");\n        KeptVault vault = new KeptVault(owner, address(intake), address(imd),\n            bytes32(\"oracle.request@oracle-1\"), makeAddr(\"signer\"), 9, 7);\n        team.mint(creator, 100 ether);\n        imd.mint(creator, 10 ether);\n        vm.startPrank(creator);\n        team.approve(address(vault), type(uint256).max);\n        imd.approve(address(vault), type(uint256).max);\n        KeptVault.MilestoneInput[] memory ms = new KeptVault.MilestoneInput[](1);\n        ms[0].kind = Questions.Kind.GithubRelease;\n        ms[0].deadline = uint64(block.timestamp + 7 days);\n        ms[0].amount = 100 ether;\n        ms[0].title = \"ship\";\n        ms[0].a = \"kept/app\";\n        ms[0].b = \"v1\";\n        uint256 id = vault.createPledge(IERC20(address(team)), makeAddr(\"ben\"), \"p\", ms, 10 ether);\n        vm.stopPrank();\n        team.setBlocked(vault.BURN(), true);\n        vm.warp(block.timestamp + 11 days);\n        // Expected: the unproven tranche can be finished (burned or otherwise retired) and the\n        // creator's 10 IMD budget returned. Actual: settle reverts forever, so withdrawBudget does too.\n        try vault.settle(id, 0) {} catch {}\n        vault.withdrawBudget(id);\n        assertEq(imd.balanceOf(creator), 10 ether);\n    }\n}","reproduction":"Team token with a blocklist that blocks 0x000000000000000000000000000000000000dEaD. createPledge(one GithubRelease milestone, 100 tokens, deadline now+7d, budget 10 IMD). warp +11 days. settle(id,0) reverts 'blocked' every time. withdrawBudget(id): expected 10 IMD back to the creator, actual reverts NotOpen() forever. The same holds when the beneficiary is blocklisted after a Kept verdict. The attached proof (the write_foundry_tests proof, run here) fails on the current code with NotOpen().","severity":"low","snippet":"        if (p.open != 0) revert NotOpen();","title":"A tranche whose recipient refuses the token can never settle, which strands the pledge's unrelated IMD budget forever"},{"citation":"resolved","description":"From audit_permissions. Ownership moves in one call with no acceptance by the new owner. The owner's only material power is proposeProtocol, the sole way the vault can follow IMD rotating the oracle signer (a single hot EOA) or retiring Intake v1. With the owner lost, every future onOracleResult fails BadSignature once the key rotates, every open milestone burns at deadline + GRACE, and budgets of pledges with deadlines up to MAX_LEAD (3 years) stay locked until then. executeProtocol is permissionless, so a proposal left pending by an owner who then loses the key is applied by anyone and cannot be cancelled. Intentional ownership is a trust assumption, not a defect; the defect is the irrecoverable transfer path. Minimal fix: two-step transfer (pendingOwner + acceptOwner), keeping explicit renounce as a separate call.","line":588,"path":"src/KeptVault.sol","reproduction":"Vault deployed with owner = $owner. $owner calls setOwner(0x1234...typo) -> owner = typo address, OwnerChanged emitted. proposeProtocol(...) from $owner -> revert OnlyOwner(); nobody holds the typo key. IMD later rotates the signer: beneficiary check(id,0) pays 0.5 IMD, the Intake delivers an attestation signed by the new key, onOracleResult reverts BadSignature(); after ANSWER_TIMEOUT the check is cleared; the same for every attempt; settle after deadline+GRACE burns the tranche. Expected: a transfer to a wrong address is recoverable until accepted. Actual: final in one call.","severity":"low","snippet":"    function setOwner(address next) external onlyOwner {\n        owner = next;\n        emit OwnerChanged(next);\n    }","title":"setOwner is single-step with no acceptance: a mistyped address irrevocably loses the only power that can follow an oracle signer or Intake rotation"},{"citation":"resolved","description":"From audit_math. askedAt is the sequencer's block timestamp at the request; issuedAt is the oracle's wall clock. _verifyWith tolerates issuedAt up to ISSUED_AT_TOLERANCE (5 min) ahead of block time because the two clocks differ, but the reverse comparison at line 360 is strict: an answer stamped one second before the request block's timestamp is refused. On an Arbitrum-family chain such as Robinhood Chain the sequencer's block timestamp can run ahead of wall-clock time, so an honest answer issued promptly can carry issuedAt < askedAt. The refusal is a revert inside the 200k callback, so the paid check is lost and the milestone stays in flight for a day. Fix: compare against askedAt - ISSUED_AT_TOLERANCE (or a small allowance), keeping the intent of rejecting pre-signed answers.","line":360,"path":"src/KeptVault.sol","reproduction":"VaultFixture. Standard GithubRelease pledge, beneficiary check(id,0) at block time T0 (askedAt = T0). warp(T0+10min). Intake delivers an attestation with issuedAt = T0-1, expiresAt = issuedAt + 1 day, correct signer, panel 9/7/8, chainId 4663. Expected: a verdict one second 'early' accepted like the 5-minute-late case. Actual: onOracleResult reverts InvalidAttestation(); the same attestation with issuedAt = T0 is accepted. Reproduced in test/scratch/Review.t.sol::test_issuedAtBeforeAskedAtRefused (passes on current code).","severity":"low","snippet":"                || a.issuedAt < m.askedAt || a.expiresAt < a.issuedAt || a.answer.length != 32","title":"Attestation issuedAt earlier than the request block's timestamp is refused with no skew tolerance, unlike the 5-minute forward tolerance"},{"citation":"resolved","description":"From audit_math. The rebate is all-or-nothing (`refereeFund >= price`). Any balance below the current price, which the hook's arbitrary fee sweeps and odd donations make the normal state, can never be used: there is no partial rebate and no function moves refereeFund anywhere else. If the Intake raises its price, a larger balance becomes dead the same way. Minimal fix: rebate min(price, refereeFund), or let the owner top the remainder up to a whole price.","line":381,"path":"src/KeptVault.sol","reproduction":"VaultFixture. fundReferee(0.4e18) with price 0.5e18; standard pledge with budget 10 IMD; beneficiary check(id,0); Intake delivers a kept verdict. Expected: the fund contributes what it has. Actual: refereeFund stays 0.4e18, budget stays 9.5e18, and no call can ever move the 0.4 IMD. Reproduced in test/scratch/Review.t.sol::test_refereeRemainderDead (passes on current code).","severity":"low","snippet":"            refereeFund -= price;","title":"Referee Fund remainder smaller than one check price is never rebated and has no exit"},{"citation":"resolved","description":"Merged from audit_permissions and audit_economics; recorded as a documented privileged power, not a bypass. The timelock cannot be skipped (_setProtocol is reachable only from the constructor and executeProtocol), in-flight checks keep their old intake and signer (lines 330-331), and check stays beneficiary-only, so the owner alone cannot move tokens. After executeProtocol the owner's intake and signer decide every subsequent verdict: with a colluding beneficiary any open tranche is released without a real oracle answer; by answering 'no' or never answering, every open milestone burns at deadline + GRACE. A renounced owner leaves pledges bound to Intake v1 forever. The README and ADAPTATION.md state this. No code change is required by the brief.","line":574,"path":"src/KeptVault.sol","reproduction":"owner: proposeProtocol(E, action, addr(K)) where E is an Intake-shaped contract and K a key the owner holds; warp +7d; anyone executeProtocol(). beneficiary check(id,0): E takes 0.5 IMD and returns id R. E calls onOracleResult(R, {kept=true, panelSize 9, quorum 7, agreed 8, chainId 4663}, sig by K): accepted. settle(id,0) transfers the tranche to the beneficiary with no real oracle verdict.","severity":"info","snippet":"    function executeProtocol() external {\n        ProtocolChange memory c = pendingProtocol;\n        if (c.readyAt == 0) revert NothingPending();\n        if (block.timestamp < c.readyAt) revert TooEarly();\n        delete pendingProtocol;\n        _setProtocol(c.intake, c.action, c.signer);\n    }","title":"Trust assumption: after the 7-day notice the owner can point every future verdict at an Intake and signer of its choice and so release or burn every open pledge; creators cannot exit during notice"},{"citation":"resolved","description":"From write_foundry_tests. For chain-evidence kinds the `a.agreed < a.quorum` check is skipped by design (the deployer's recipe rerun settles split panels, as the protocol documents), so a signed attestation with agreed = 0 releases the tranche. Value release on those templates then rests only on the oracle signer key and the Intake writer's pairing of answer to request (questionHash is not pinned because the window is relative). Recorded so the author weighs it for large tranches; the oracle reference itself says to treat the answer as a strong signal for moderate value.","line":359,"path":"src/KeptVault.sol","reproduction":"VaultFixture. ValueAtLeast milestone; beneficiary check(id,0); Intake delivers a correctly signed attestation with panelSize 9, quorum 7, agreed 0, answer true. Expected by a reader of the oracle reference: refused for agreed < quorum. Actual: accepted, outcome Kept, settle pays the beneficiary. (For PageContains/GithubRelease the same attestation is refused with InvalidAttestation.)","severity":"info","snippet":"                || a.quorum > a.panelSize || (!chainEvidence && a.agreed < a.quorum) || a.agreed > a.panelSize","title":"Chain-evidence verdicts (ContractDeployed, ValueAtLeast) accept any signed panel agreement, down to zero"}],"hash":"c1e4bd6449fca6cb473d259b00c9a2bcf3b601eeb019a8b0d261eb08a4a64302","nodeId":"910b8d37-3b91-4b21-ad9d-ebfe51072b56","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds nine substantiated findings plus a 24-row coverage record covering all 22 entry points.\n\n**What I verified**\n\n- The project builds and all 133 offline tests pass. The vault's runtime is 21,509 bytes and its initcode with the seven constructor words is 23,549 bytes, both under the limits. The manifest's seven arguments match the brief in declaration order, and the constructor makes no external call.\n- The Robinhood fork rehearsal passes against the live Intake, IMD and PoolManager at block 91,883,318 through the local endpoint.\n- Every specialist claim I kept was re-run in a scratch Foundry test I wrote against the project fixture, or by running the specialists' attached proof. That proof fails on the current code with NotOpen exactly as its finding states, so it stays attached.\n\n**Findings kept, after merging duplicates**\n\n1. Low. Snapshot templates sell checks inside the oracle's latency window that the callback then refuses, so the price and attempt are lost and the tranche can burn. Four specialists reported this; merged into one.\n2. Low. Permissionless clearStale races a still-valid late delivery, since the callback itself never enforces the timeout. Two reports merged.\n3. Low. The Referee Fund rebates any kept milestone, so trivially true self-pledges of a worthless token drain donations at zero net cost. Two reports merged.\n4. Low. A token that refuses the payout or burn transfer blocks settle forever and strands the unrelated IMD budget. Two reports merged, proof attached. The README documents this restriction, which is why it stays low.\n5. Low. Single-step setOwner with no acceptance.\n6. Low. issuedAt earlier than askedAt is refused with no skew tolerance, unlike the forward tolerance.\n7. Low. Fund remainders below one check price are permanently unusable.\n8. Info. Owner's timelocked power to replace Intake and signer, recorded as a trust assumption. Two reports merged.\n9. Info. Chain-evidence verdicts accept agreed equal to zero, by documented design.\n\nNothing was dropped as unreproducible; every specialist finding traced correctly against the code. My own pass over the entry points, including the hook and token functions the specialists could not verify, found nothing at medium or above beyond these. Scratch files under test/scratch are mine and are not part of the submission.","treeHash":null,"usage":{"cachedInputTokens":1138165,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":32092,"runtime":"claude","turns":24,"wallClockMs":498819}}],"verification":[{"checks":[{"durationMs":55712,"exitCode":0,"name":"build","output":"Compiling 116 files with Solc 0.8.26\nSolc 0.8.26 finished in 55.61s\nCompiler run successful!\n","passed":true},{"durationMs":12810,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RealAttestation.t.sol:RealAttestationTest\n[PASS] test_liveSignatureRecoversTheLiveSigner() (gas: 12095)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 304.44µs (201.56µs CPU time)\n\nRan 2 tests for test/KeptVaultTokenCompatibility.t.sol:KeptVaultTokenCompatibilityTest\n[PASS] test_standardTokenSharedPledgesSettleAndRefundIndependently() (gas: 1956008)\n[PASS] test_unsupportedBalanceShrinkCanStrandLastTrancheAndBudget() (gas: 1167841)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.01ms (1.67ms CPU time)\n\nRan 1 test for test/fork/Robinhood.t.sol:RobinhoodForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 3.91ms (0.00ns CPU time)\n\nRan 4 tests for test/OracleConformance.t.sol:OracleConformanceTest\n[PASS] test_acceptsTheProtocolSignature() (gas: 20019)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3543)\n[PASS] test_digestMatchesTheProtocol() (gas: 13531)\n[PASS] test_keptVerdictFromTheVectorKey() (gas: 1339588)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 29.74ms (998.79µs CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 853251, ~: 847340)\nLogs:\n  Bound result 465\n  Bound result 899000000000000206610767428\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 357621, ~: 357785)\nLogs:\n  Bound result 3166\n  Bound result 268498866\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5883840)\n[PASS] test_callbacksOnlyManager() (gas: 119114)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 218315)\n[PASS] test_onlyFactoryInitializes() (gas: 221037)\n[PASS] test_onlyOnePoolEver() (gas: 45463)\n[PASS] test_partialFillsAllModes() (gas: 2474138)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 574156)\n[PASS] test_sweepFundsTheReferee() (gas: 879784)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 64.18ms (139.39ms CPU time)\n\nRan 14 tests for test/KeptVaultAudit.t.sol:KeptVaultAuditTest\n[PASS] testFuzz_explicitPriceLimit(uint96,uint96) (runs: 256, μ: 916039, ~: 589714)\nLogs:\n  Bound result 14264337593543950333\n  Bound result 1261917568799\n\n[PASS] testFuzz_snapshotCheckClosesAtDeadline(uint8,uint32) (runs: 256, μ: 721577, ~: 704773)\nLogs:\n  Bound result 1\n  Bound result 240258\n\n[PASS] testFuzz_snapshotRejectsVerdictIssuedAfterDeadline(uint8,uint32) (runs: 256, μ: 1562148, ~: 1563659)\nLogs:\n  Bound result 1\n  Bound result 240258\n\n[PASS] testFuzz_snapshotSignedAtDeadlineCanArriveLater(uint8,uint32) (runs: 256, μ: 1585203, ~: 1586952)\nLogs:\n  Bound result 1\n  Bound result 67458\n\n[PASS] test_checkOpenDistinguishesDefaultAndExplicitPriceCaps() (gas: 505594)\n[PASS] test_creatorCanCheckWhenAlsoBeneficiary() (gas: 1404603)\n[PASS] test_creatorCannotExhaustBeneficiaryAttempts() (gas: 1591611)\n[PASS] test_creatorCannotUseExplicitPriceCheckOrClearStaleAsSideEffect() (gas: 1243379)\n[PASS] test_defaultPriceCapRejectsRepricedIntake() (gas: 588079)\n[PASS] test_defaultPriceCapSurvivesTimelockedIntakeReplacement() (gas: 1376226)\n[PASS] test_explicitCapCanAcceptNewPriceAndRebateActualPrice() (gas: 1507048)\n[PASS] test_githubPublicationDeadlineStillAllowsGraceCheck() (gas: 1443934)\n[PASS] test_priceCapFailureDoesNotClearStaleCheck() (gas: 1282371)\n[PASS] test_zeroQuoteRemainsInvalidEvenWithExplicitCap() (gas: 497017)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 64.75ms (205.86ms CPU time)\n\nRan 43 tests for test/KeptVault.t.sol:KeptVaultTest\n[PASS] test_attestationCannotBeReplayedOnAnotherCheck() (gas: 1726979)\n[PASS] test_callbackOnlyFromIntake() (gas: 1254102)\n[PASS] test_callbackRejectsExpiredAttestation() (gas: 1264729)\n[PASS] test_callbackRejectsUnknownRequest() (gas: 1254900)\n[PASS] test_callbackRejectsWeakOrMismatchedAttestations() (gas: 1991894)\n[PASS] test_callbackRejectsWrongAnswerType() (gas: 1289194)\n[PASS] test_callbackRejectsWrongSigner() (gas: 1270836)\n[PASS] test_chainEvidenceAcceptsDeployerSettledVerdict() (gas: 1240396)\n[PASS] test_checkNeedsBudget() (gas: 1237961)\n[PASS] test_checkOpenReportsBudget() (gas: 543071)\n[PASS] test_checkPaysIntakeFromBudget() (gas: 1267661)\n[PASS] test_checkRejectsIntakeThatDoesNotPull() (gas: 1014807)\n[PASS] test_checkRejectsRepeatedRequestId() (gas: 1697655)\n[PASS] test_createPullsTokensAndBudget() (gas: 477341)\n[PASS] test_createRejectsBadQuestionStrings() (gas: 2756885)\n[PASS] test_createRejectsTaxedToken() (gas: 1114020)\n[PASS] test_createValidatesMilestones() (gas: 704836)\n[PASS] test_createValidatesPledge() (gas: 192120)\n[PASS] test_falseVerdictKeepsMilestoneOpen() (gas: 1861435)\n[PASS] test_inFlightCheckStaysBoundToItsIntake() (gas: 1486471)\n[PASS] test_isoDate() (gas: 41366)\n[PASS] test_keptPaysBeneficiaryAndReturnsBudget() (gas: 1528583)\n[PASS] test_keptRebatesFromRefereeFund() (gas: 1579314)\n[PASS] test_multiMilestoneMixedOutcomes() (gas: 3152001)\n[PASS] test_newChecksUseTheRotatedSigner() (gas: 1529920)\n[PASS] test_noRebateWhenFundIsShort() (gas: 1424042)\n[PASS] test_oneCheckInFlight() (gas: 1172688)\n[PASS] test_onlyBeneficiaryChecksBeforeDeadline() (gas: 1177243)\n[PASS] test_onlyBeneficiaryChecksEvenAfterDeadline() (gas: 1264896)\n[PASS] test_ownerHasNoPathToLockedTokens() (gas: 540546)\n[PASS] test_panelChangeOnlyAffectsNewPledges() (gas: 871407)\n[PASS] test_panelEvidenceNeedsQuorumAgreement() (gas: 1286460)\n[PASS] test_protocolChangeWaitsSevenDays() (gas: 224290)\n[PASS] test_questionBodies() (gas: 68804)\n[PASS] test_questionOfMatchesPreview() (gas: 496487)\n[PASS] test_settleBurnsAfterStaleLastCheck() (gas: 1368568)\n[PASS] test_settleTwiceReverts() (gas: 528241)\n[PASS] test_settleWaitsForCheckInFlight() (gas: 1450907)\n[PASS] test_signerRotationDoesNotStrandChecksInFlight() (gas: 1496054)\n[PASS] test_staleCheckRetriesAndAttemptsCap() (gas: 1744575)\n[PASS] test_unprovenMilestoneBurns() (gas: 644737)\n[PASS] test_valueTemplateRejectsZeroThreshold() (gas: 195184)\n[PASS] test_withdrawBudgetOnlyWhenFinished() (gas: 844312)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 64.84ms (42.91ms CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTokenFirstTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 854561, ~: 849434)\nLogs:\n  Bound result 734\n  Bound result 899000000000081868060051027\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 356834, ~: 362910)\nLogs:\n  Bound result 3553\n  Bound result 9668\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5887215)\n[PASS] test_callbacksOnlyManager() (gas: 119829)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 209541)\n[PASS] test_onlyFactoryInitializes() (gas: 221547)\n[PASS] test_onlyOnePoolEver() (gas: 45691)\n[PASS] test_partialFillsAllModes() (gas: 2468116)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 563352)\n[PASS] test_sweepFundsTheReferee() (gas: 875763)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 66.86ms (117.63ms CPU time)\n\nRan 3 tests for test/KeptVaultLaunch.t.sol:KeptVaultLaunchTest\n[PASS] test_constructorRejectsNativeValue() (gas: 2066681)\n[PASS] test_exactLaunchArgumentsDeployOnEmptyChainWithoutInitialization() (gas: 6852797)\n[PASS] test_runtimeFitsAndHasNoForbiddenOpcodes() (gas: 31002565)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 68.16ms (69.29ms CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS]\nVaultInvariantTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultInvariantTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19445\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 2861\n  Bound result 1\n  Bound result 3455\n  Bound result 1\n  Bound result 4\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 2211\n  Bound result 1\n  Bound result 860591\n  Bound result 16282\n  Bound result 17510\n  Bound result 2\n  Bound result 1\n  Bound result 2451791247615983616\n  Bound result 2\n  Bound result 4\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 1242826416\n  Bound result 16959\n  Bound result 2115\n  Bound result 4\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 16217\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 195956085\n  Bound result 3\n  Bound result 1723020866\n  Bound result 1710\n  Bound result 127340\n  Bound result 2\n  Bound result 860419\n  Bound result 647555205861763807992079\n  Bound result 860419\n  Bound result 647555205861763807992079\n  Bound result 205065511\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 1\n  Bound result 13841\n  Bound result 3298891303\n  Bound result 1521356376\n  Bound result 4\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 408414\n  Bound result 10809\n  Bound result 411723527615725136\n  Bound result 7\n  Bound result 5\n  Bound result 5\n  Bound result 56\n  Bound result 2705626677\n  Bound result 4\n  Bound result 3\n  Bound result 5696\n  Bound result 148\n  Bound result 5696\n  Bound result 148\n  Bound result 5696\n  Bound result 148\n  Bound result 3302\n  Bound result 1\n  Bound result 593\n  Bound result 5\n  Bound result 708378881\n  Bound result 2\n  Bound result 17091\n  Bound result 1820\n  Bound result 17091\n  Bound result 1820\n  Bound result 2547112994207557362\n  Bound result 10\n  Bound result 4\n  Bound result 10\n  Bound result 4938\n  Bound result 10\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 6571\n  Bound result 10000\n  Bound result 2\n  Bound result 2\n  Bound result 567184\n  Bound result 16273\n  Bound result 567184\n  Bound result 16273\n  Bound result 10465\n  Bound result 5\n  Bound result 4\n  Bound result 11916\n  Bound result 8\n  Bound result 12\n  Bound result 4\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 6739\n  Bound result 3154\n  Bound result 23295\n  Bound result 2539\n  Bound result 1878\n  Bound result 4\n  Bound result 1212\n  Bound result 3384\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 1535\n  Bound result 3\n  Bound result 7664\n  Bound result 9\n  Bound result 13835821\n  Bound result 7\n  Bound result 4\n  Bound result 4\n  Bound result 860527\n  Bound result 16652\n  Bound result 860527\n  Bound result 16652\n  Bound result 860527\n  Bound result 16652\n  Bound result 860527\n  Bound result 16652\n  Bound result 1179\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 3\n  Bound result 150000\n  Bound result 29516360790239361883594\n  Bound result 150000\n  Bound result 29516360790239361883594\n  Bound result 150000\n  Bound result 29516360790239361883594\n  Bound result 4934191420466944596\n  Bound result 1\n  Bound result 860405\n  Bound result 10018\n  Bound result 1242827628\n  Bound result 13\n  Bound result 2\n  Bound result 1171089380634855316\n  Bound result 4\n  Bound result 17687\n  Bound result 4176\n  Bound result 17687\n  Bound result 4176\n  Bound result 17687\n  Bound result 4176\n  Bound result 17687\n  Bound result 4176\n  Bound result 4763\n  Bound result 14\n  Bound result 1\n  Bound result 8\n  Bound result 18\n  Bound result 18\n  Bound result 9994\n  Bound result 18\n  Bound result 9\n  Bound result 11\n  Bound result 4\n  Bound result 3600\n  Bound result 1\n  Bound result 3600\n  Bound result 1\n  Bound result 3600\n  Bound result 1\n  Bound result 3600\n  Bound result 1\n  Bound result 7117\n  Bound result 4\n  Bound result 860643\n  Bound result 1434\n  Bound result 860643\n  Bound result 1434\n  Bound result 860643\n  Bound result 1434\n  Bound result 860643\n  Bound result 1434\n  Bound result 11950\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 2\n  Bound result 20\n  Bound result 659\n  Bound result 12839\n  Bound result 14\n  Bound result 2866112149639490298\n  Bound result 5\n  Bound result 98977\n  Bound result 3600\n  Bound result 172800\n  Bound result 4\n  Bound result 859658\n  Bound result 1737\n  Bound result 859658\n  Bound result 1737\n  Bound result 859658\n  Bound result 1737\n  Bound result 859658\n  Bound result 1737\n  Bound result 283\n  Bound result 1\n  Bound result 3344\n  Bound result 1\n  Bound result 13\n  Bound result 11\n  Bound result 10\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 12.45s (12.45s CPU time)\n\nRan 2 tests for test/VaultInvariant.t.sol:VaultHandlerSmokeTest\n[PASS]\nVaultHandlerSmokeTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultHandlerSmokeTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19327\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 5472\n  Bound result 1\n  Bound result 15026\n  Bound result 1\n  Bound result 4\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 2810\n  Bound result 4\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 1313867396929476720\n  Bound result 3\n  Bound result 1\n  Bound result 20894\n  Bound result 2\n  Bound result 4\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 1181\n  Bound result 16665\n  Bound result 2354\n  Bound result 4\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 16717\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 14519\n  Bound result 3\n  Bound result 2438\n  Bound result 1710\n  Bound result 127340\n  Bound result 2\n  Bound result 860419\n  Bound result 42161\n  Bound result 860419\n  Bound result 42161\n  Bound result 1368\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 1\n  Bound result 16105\n  Bound result 49828827948877472595967\n  Bound result 1904875907\n  Bound result 7\n  Bound result 3\n  Bound result 5\n  Bound result 3\n  Bound result 408414\n  Bound result 385\n  Bound result 408414\n  Bound result 385\n  Bound result 408414\n  Bound result 385\n  Bound result 370723312740531176\n  Bound result 8\n  Bound result 5\n  Bound result 5\n  Bound result 56\n  Bound result 2475\n  Bound result 4\n  Bound result 1\n  Bound result 6107\n  Bound result 230\n  Bound result 5167\n  Bound result 1\n  Bound result 947\n  Bound result 8\n  Bound result 2522754948866715240\n  Bound result 2\n  Bound result 17743\n  Bound result 49825994352230070160209\n  Bound result 17743\n  Bound result 49825994352230070160209\n  Bound result 15678\n  Bound result 10\n  Bound result 4\n  Bound result 10\n  Bound result 4938\n  Bound result 10\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 6969\n  Bound result 10000\n  Bound result 2\n  Bound result 2\n  Bound result 6181\n  Bound result 16769\n  Bound result 6181\n  Bound result 16769\n  Bound result 10904\n  Bound result 6\n  Bound result 4\n  Bound result 10969\n  Bound result 7\n  Bound result 12\n  Bound result 4\n  Bound result 644917\n  Bound result 4722366482869645213441\n  Bound result 644917\n  Bound result 4722366482869645213441\n  Bound result 644917\n  Bound result 4722366482869645213441\n  Bound result 644917\n  Bound result 4722366482869645213441\n  Bound result 6206\n  Bound result 3588\n  Bound result 23295\n  Bound result 5196\n  Bound result 16041\n  Bound result 4\n  Bound result 1435\n  Bound result 10203\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 1558\n  Bound result 8\n  Bound result 9364\n  Bound result 9\n  Bound result 5740\n  Bound result 2\n  Bound result 4\n  Bound result 4\n  Bound result 860527\n  Bound result 17617\n  Bound result 860527\n  Bound result 17617\n  Bound result 860527\n  Bound result 17617\n  Bound result 860527\n  Bound result 17617\n  Bound result 4639\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 3\n  Bound result 150000\n  Bound result 49824023415549498919930\n  Bound result 150000\n  Bound result 49824023415549498919930\n  Bound result 150000\n  Bound result 49824023415549498919930\n  Bound result 1290346542962811243\n  Bound result 1\n  Bound result 860405\n  Bound result 618234901944798448365366\n  Bound result 3795148443869244578\n  Bound result 13\n  Bound result 2\n  Bound result 1171089380634855316\n  Bound result 4\n  Bound result 18389\n  Bound result 12067\n  Bound result 18389\n  Bound result 12067\n  Bound result 18389\n  Bound result 12067\n  Bound result 18389\n  Bound result 12067\n  Bound result 2192\n  Bound result 14\n  Bound result 1\n  Bound result 13\n  Bound result 18\n  Bound result 18\n  Bound result 15213\n  Bound result 18\n  Bound result 9\n  Bound result 8\n  Bound result 1\n  Bound result 3600\n  Bound result 99095909163969503319594\n  Bound result 4199\n  Bound result 4\n  Bound result 860643\n  Bound result 1274\n  Bound result 860643\n  Bound result 1274\n  Bound result 860643\n  Bound result 1274\n  Bound result 860643\n  Bound result 1274\n  Bound result 12588\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 10\n  Bound result 20\n  Bound result 859\n  Bound result 13122\n  Bound result 14\n  Bound result 996468379969014219\n  Bound result 16\n  Bound result 98977\n  Bound result 3600\n  Bound result 172800\n  Bound result 4\n  Bound result 862385\n  Bound result 2812\n  Bound result 862385\n  Bound result 2812\n  Bound result 862385\n  Bound result 2812\n  Bound result 862385\n  Bound result 2812\n  Bound result 2835717306\n  Bound result 3\n  Bound result 5817\n  Bound result 1\n  Bound result 12\n  Bound result 11\n  Bound result 10\n\n[PASS] test_handlerReachesPayoutAndBurn() (gas: 2028271)\nLogs:\n  Bound result 2\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 2000000000000000000\n  Bound result 1\n  Bound result 1\n  Bound result 259200\n  Bound result 259200\n  Bound result 1\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 12.69s (12.68s CPU time)\n\nRan 11 test suites in 12.69s (25.50s CPU time): 98 tests passed, 0 failed, 1 skipped (99 total tests)\n","passed":true},{"durationMs":112,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"KeptHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"KeptHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"KeptHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"KeptHook.sweep()\",\"KeptHook.unlockCallback(bytes)\",\"KeptToken.approve(address,uint256)\",\"KeptToken.transfer(address,uint256)\",\"KeptToken.transferFrom(address,address,uint256)\",\"KeptVault.cancelProtocol()\",\"KeptVault.check(uint256,uint8)\",\"KeptVault.check(uint256,uint8,uint256)\",\"KeptVault.clearStale(uint256,uint8)\",\"KeptVault.createPledge(address,address,string,(uint8,uint64,uint128,uint64,address,uint256,string,string,string)[],uint256)\",\"KeptVault.executeProtocol()\",\"KeptVault.fund(uint256,uint256)\",\"KeptVault.fundReferee(uint256)\",\"KeptVault.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"KeptVault.proposeProtocol(address,bytes32,address)\",\"KeptVault.setOwner(address)\",\"KeptVault.setPanel(uint16,uint16)\",\"KeptVault.settle(uint256,uint8)\",\"KeptVault.withdrawBudget(uint256)\"],\"files\":{\".gitattributes\":2,\".gitignore\":5,\"ADAPTATION.md\":150,\"README.md\":96,\"dist/apple-touch-icon.png\":8,\"dist/assets/ccip-DEgEpxnr.js\":1,\"dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff\":60,\"dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2\":58,\"dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff\":51,\"dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2\":62,\"dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2\":78,\"dist/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff\":53,\"dist/assets/index-TiwfCIFz.css\":1,\"dist/assets/index-f9ceCkFm.js\":36,\"dist/assets/secp256k1-Desv_BdV.js\":1,\"dist/assets/swarm-DuldE8ej.js\":83,\"dist/assets/utils-Bpv4vmSW.js\":1,\"dist/favicon-32.png\":4,\"dist/favicon.svg\":5,\"dist/icon-512.png\":8,\"dist/index.html\":23,\"docs/ORACLE_PREFLIGHT.json\":384,\"docs/OUTREACH.md\":60,\"docs/SPEC.md\":147,\"docs/SUBMISSION.md\":81,\"docs/VERIFICATION.md\":132,\"docs/brand/generate_logos.py\":62,\"docs/brand/kept-avatar-400.png\":12,\"docs/brand/kept-avatar.png\":34,\"docs/brand/kept-avatar.svg\":7,\"docs/brand/kept-logo-dark.png\":54,\"docs/brand/kept-logo-dark.svg\":61,\"docs/brand/kept-logo.png\":70,\"docs/brand/kept-logo.svg\":61,\"docs/brand/kept-mark-dark.png\":38,\"docs/brand/kept-mark-dark.svg\":59,\"docs/brand/kept-mark.png\":126,\"docs/brand/kept-mark.svg\":59,\"docs/brand/kept-stamp.png\":215,\"docs/brand/kept-stamp.svg\":64,\"docs/brand/kept-x-banner.png\":790,\"docs/brand/kept-x-banner@2x.png\":2387,\"docs/research.md\":61,\"docs/screenshots/local-home-light.png\":833,\"docs/screenshots/local-home.png\":768,\"docs/screenshots/local-how.png\":310,\"docs/screenshots/local-make-pledge.png\":323,\"docs/screenshots/local-mobile.png\":242,\"docs/screenshots/local-pledge.png\":332,\"foundry.toml\":21,\"remappings.txt\":4,\"script/LocalDemo.s.sol\":111,\"scripts/launch/.gitignore\":2,\"scripts/launch/README.md\":61,\"scripts/launch/launch.mjs\":474,\"scripts/launch/package-lock.json\":248,\"scripts/launch/package.json\":14,\"src/KeptHook.sol\":197,\"src/KeptToken.sol\":60,\"src/KeptVault.sol\":664,\"src/OracleAttestation.sol\":239,\"src/interfaces/IIntake.sol\":18,\"src/libraries/HookFlags.sol\":30,\"src/libraries/Questions.sol\":250,\"src/libraries/SpecifiedAmount.sol\":101,\"test/KeptHook.t.sol\":154,\"test/KeptVault.t.sol\":639,\"test/KeptVaultAudit.t.sol\":243,\"test/KeptVaultLaunch.t.sol\":100,\"test/KeptVaultTokenCompatibility.t.sol\":49,\"test/OracleConformance.t.sol\":119,\"test/RealAttestation.t.sol\":66,\"test/VaultInvariant.t.sol\":228,\"test/fork/Robinhood.t.sol\":135,\"test/helpers/HookFixture.sol\":155,\"test/helpers/TestRouter.sol\":70,\"test/helpers/VaultFixture.sol\":190,\"test/mocks/FeeToken.sol\":27,\"test/mocks/MockERC20.sol\":58,\"test/mocks/MockIntake.sol\":64,\"vercel.json\":20,\"web/README.md\":76,\"web/index.html\":19,\"web/package-lock.json\":1015,\"web/package.json\":18,\"web/public/apple-touch-icon.png\":8,\"web/public/favicon-32.png\":4,\"web/public/favicon.svg\":5,\"web/public/icon-512.png\":8,\"web/src/abi/KeptHook.json\":652,\"web/src/abi/KeptToken.json\":244,\"web/src/abi/KeptVault.json\":1940,\"web/src/chain.js\":335,\"web/src/config.js\":30,\"web/src/dom.js\":84,\"web/src/fx.js\":325,\"web/src/hero.js\":149,\"web/src/icons.js\":42,\"web/src/main.js\":1410,\"web/src/store.js\":88,\"web/src/styles.css\":772,\"web/src/swarm.js\":586,\"web/src/ui.js\":219,\"web/vite.config.js\":42},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":7786,"exitCode":0,"name":"slither","output":"[high/medium] reentrancy-balance at src/KeptVault.sol:296: Reentrancy in KeptVault._check(uint256,uint8,uint256) (src/KeptVault.sol#296-335):\n[medium/medium] divide-before-multiply at src/libraries/Questions.sol:139: Questions.isoDate(uint256) (src/libraries/Questions.sol#139-165) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/libraries/Questions.sol:139: Questions.isoDate(uint256) (src/libraries/Questions.sol#139-165) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/libraries/Questions.sol:139: Questions.isoDate(uint256) (src/libraries/Questions.sol#139-165) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/libraries/Questions.sol:139: Questions.isoDate(uint256) (src/libraries/Questions.sol#139-165) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/libraries/Questions.sol:139: Questions.isoDate(uint256) (src/libraries/Questions.sol#139-165) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/KeptVault.sol:634: KeptVault._setProtocol(address,bytes32,address) (src/KeptVault.sol#634-640) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/KeptVault.sol:574: KeptVault.executeProtocol() (src/KeptVault.sol#574-580) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/KeptHook.sol:111: KeptHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/KeptHook.sol#111-140) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/KeptHook.sol:160: KeptHook._accrue(uint256) (src/KeptHook.sol#160-165) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/KeptVault.sol:296: KeptVault._check(uint256,uint8,uint256) (src/KeptVault.sol#296-335) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/KeptHook.sol:174: Reentrancy in KeptHook.sweep() (src/KeptHook.sol#174-186):\n[medium/medium] uninitialized-local at src/KeptVault.sol:236: KeptVault.createPledge(IERC20,address,string,KeptVault.MilestoneInput[],uint256).total (src/KeptVault.sol#236) is a local variable never initialized\n[medium/medium] unused-return at src/KeptHook.sol:174: KeptHook.sweep() (src/KeptHook.sol#174-186) ignores return value by poolManager.unlock() (src/KeptHook.sol#177)\n[medium/medium] unused-return at src/libraries/SpecifiedAmount.sol:24: SpecifiedAmount.filled(IPoolManager,PoolKey,SwapParams) (src/libraries/SpecifiedAmount.sol#24-75) ignores return value by (None,net) = manager.getTickLiquidity(id,next) (src/libraries/SpecifiedAmount.sol#62)\n[low/medium] missing-zero-check at src/KeptVault.sol:588: KeptVault.setOwner(address).next (src/KeptVault.sol#588) lacks a zero-check on :\n[low/medium] reentrancy-benign at src/KeptVault.sol:296: Reentrancy in KeptVault._check(uint256,uint8,uint256) (src/KeptVault.sol#296-335):\n[low/medium] reentrancy-events at src/KeptHook.sol:160: Reentrancy in KeptHook._accrue(uint256) (src/KeptHook.sol#160-165):\n[low/medium] reentrancy-events at src/KeptHook.sol:174: Reentrancy in KeptHook.sweep() (src/KeptHook.sol#174-186):\n[low/medium] timestamp at src/KeptVault.sol:211: KeptVault.createPledge(IERC20,address,string,KeptVault.MilestoneInput[],uint256) (src/KeptVault.sol#211-260) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptHook.sol:160: KeptHook._accrue(uint256) (src/KeptHook.sol#160-165) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:574: KeptVault.executeProtocol() (src/KeptVault.sol#574-580) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:389: KeptVault.clearStale(uint256,uint8) (src/KeptVault.sol#389-395) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptHook.sol:111: KeptHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/KeptHook.sol#111-140) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:296: KeptVault._check(uint256,uint8,uint256) (src/KeptVault.sol#296-335) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:621: KeptVault._verifyWith(OracleAttestation.Attestation,bytes,address) (src/KeptVault.sol#621-632) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptHook.sol:104: KeptHook.feeNow() (src/KeptHook.sol#104-109) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:538: KeptVault._checkOpen(uint256,uint8,uint256) (src/KeptVault.sol#538-553) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:400: KeptVault.settle(uint256,uint8) (src/KeptVault.sol#400-424) uses timestamp for comparisons\n[low/medium] timestamp at src/OracleAttestation.sol:164: OracleAttestationConsumer._verifyAttestation(OracleAttestation.Attestation,bytes) (src/OracleAttestation.sol#164-175) uses timestamp for comparisons\n[low/medium] timestamp at src/KeptVault.sol:634: KeptVault._setProtocol(address,bytes32,address) (src/KeptVault.sol#634-640) uses timestamp for comparisons","passed":true},{"durationMs":875,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/KeptHook.sol:177: Reentrancy: State change after external call\n[low] centralization-risk at src/KeptVault.sol:558: Centralization Risk (4 places)\n[low] costly-loop at src/KeptVault.sol:237: Costly operations inside loop\n[low] internal-function-used-once at src/OracleAttestation.sol:195: Internal Function Used Only Once (6 places)\n[low] large-numeric-literal at src/KeptHook.sol:128: Large Numeric Literal (7 places)\n[low] literal-instead-of-constant at src/KeptHook.sol:128: Literal Instead of Constant (31 places)\n[low] local-variable-shadowing at src/KeptVault.sol:60: Local Variable Shadows State Variable (4 places)\n[low] missing-inheritance at src/KeptToken.sol:5: Missing Inheritance\n[low] require-revert-in-loop at src/KeptVault.sol:237: Loop Contains `require`/`revert` (2 places)\n[low] state-no-address-check at src/KeptVault.sol:589: Address State Variable Set Without Checks\n[low] unchecked-return at src/KeptHook.sol:177: Unchecked Return\n[low] uninitialized-local-variable at src/KeptVault.sol:237: Uninitialized Local Variable (5 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"1a847880daf74236172578aeca6ca775f46d903a847414d2497d6f062c6c0e74","verifiedTreeHash":"e3f5b07cc28ed5a85fe5db5953e6cd14d04b1d85","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":73518,"exitCode":0,"name":"build","output":"Compiling 118 files with Solc 0.8.26\nSolc 0.8.26 finished in 73.42s\nCompiler run successful!\n","passed":true},{"durationMs":12625,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RealAttestation.t.sol:RealAttestationTest\n[PASS] test_liveSignatureRecoversTheLiveSigner() (gas: 12095)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 402.20µs (256.71µs CPU time)\n\nRan 1 test for test/fork/Robinhood.t.sol:RobinhoodForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 580.83µs (0.00ns CPU time)\n\nRan 2 tests for test/KeptVaultTokenCompatibility.t.sol:KeptVaultTokenCompatibilityTest\n[PASS] test_standardTokenSharedPledgesSettleAndRefundIndependently() (gas: 1956008)\n[PASS] test_unsupportedBalanceShrinkCanStrandLastTrancheAndBudget() (gas: 1167841)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.94ms (2.11ms CPU time)\n\nRan 1 test for test/KeptVaultActorsInvariant.t.sol:ActorsHandlerReachTest\n[PASS] test_handlerReachesEveryPath() (gas: 5595952)\nLogs:\n  Bound result 2\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 2000000000000000000\n  Bound result 1\n  Bound result 7200\n  Bound result 500000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 42\n  Bound result 259200\n  Bound result 259200\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.59ms (4.49ms CPU time)\n\nRan 43 tests for test/KeptVault.t.sol:KeptVaultTest\n[PASS] test_attestationCannotBeReplayedOnAnotherCheck() (gas: 1726979)\n[PASS] test_callbackOnlyFromIntake() (gas: 1254102)\n[PASS] test_callbackRejectsExpiredAttestation() (gas: 1264729)\n[PASS] test_callbackRejectsUnknownRequest() (gas: 1254900)\n[PASS] test_callbackRejectsWeakOrMismatchedAttestations() (gas: 1991894)\n[PASS] test_callbackRejectsWrongAnswerType() (gas: 1289194)\n[PASS] test_callbackRejectsWrongSigner() (gas: 1270836)\n[PASS] test_chainEvidenceAcceptsDeployerSettledVerdict() (gas: 1240396)\n[PASS] test_checkNeedsBudget() (gas: 1237961)\n[PASS] test_checkOpenReportsBudget() (gas: 543071)\n[PASS] test_checkPaysIntakeFromBudget() (gas: 1267661)\n[PASS] test_checkRejectsIntakeThatDoesNotPull() (gas: 1014807)\n[PASS] test_checkRejectsRepeatedRequestId() (gas: 1697655)\n[PASS] test_createPullsTokensAndBudget() (gas: 477341)\n[PASS] test_createRejectsBadQuestionStrings() (gas: 2756885)\n[PASS] test_createRejectsTaxedToken() (gas: 1114020)\n[PASS] test_createValidatesMilestones() (gas: 704836)\n[PASS] test_createValidatesPledge() (gas: 192120)\n[PASS] test_falseVerdictKeepsMilestoneOpen() (gas: 1861435)\n[PASS] test_inFlightCheckStaysBoundToItsIntake() (gas: 1486471)\n[PASS] test_isoDate() (gas: 41366)\n[PASS] test_keptPaysBeneficiaryAndReturnsBudget() (gas: 1528583)\n[PASS] test_keptRebatesFromRefereeFund() (gas: 1579314)\n[PASS] test_multiMilestoneMixedOutcomes() (gas: 3152001)\n[PASS] test_newChecksUseTheRotatedSigner() (gas: 1529920)\n[PASS] test_noRebateWhenFundIsShort() (gas: 1424042)\n[PASS] test_oneCheckInFlight() (gas: 1172688)\n[PASS] test_onlyBeneficiaryChecksBeforeDeadline() (gas: 1177243)\n[PASS] test_onlyBeneficiaryChecksEvenAfterDeadline() (gas: 1264896)\n[PASS] test_ownerHasNoPathToLockedTokens() (gas: 540546)\n[PASS] test_panelChangeOnlyAffectsNewPledges() (gas: 871407)\n[PASS] test_panelEvidenceNeedsQuorumAgreement() (gas: 1286460)\n[PASS] test_protocolChangeWaitsSevenDays() (gas: 224290)\n[PASS] test_questionBodies() (gas: 68804)\n[PASS] test_questionOfMatchesPreview() (gas: 496487)\n[PASS] test_settleBurnsAfterStaleLastCheck() (gas: 1368568)\n[PASS] test_settleTwiceReverts() (gas: 528241)\n[PASS] test_settleWaitsForCheckInFlight() (gas: 1450907)\n[PASS] test_signerRotationDoesNotStrandChecksInFlight() (gas: 1496054)\n[PASS] test_staleCheckRetriesAndAttemptsCap() (gas: 1744575)\n[PASS] test_unprovenMilestoneBurns() (gas: 644737)\n[PASS] test_valueTemplateRejectsZeroThreshold() (gas: 195184)\n[PASS] test_withdrawBudgetOnlyWhenFinished() (gas: 844312)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 29.50ms (23.56ms CPU time)\n\nRan 4 tests for test/OracleConformance.t.sol:OracleConformanceTest\n[PASS] test_acceptsTheProtocolSignature() (gas: 20019)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3543)\n[PASS] test_digestMatchesTheProtocol() (gas: 13531)\n[PASS] test_keptVerdictFromTheVectorKey() (gas: 1339588)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 68.98ms (1.34ms CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTokenFirstTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 854544, ~: 849230)\nLogs:\n  Bound result 2\n  Bound result 899495312091442109524812166\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 357042, ~: 362841)\nLogs:\n  Bound result 3166\n  Bound result 268498866\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5887215)\n[PASS] test_callbacksOnlyManager() (gas: 119829)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 209541)\n[PASS] test_onlyFactoryInitializes() (gas: 221547)\n[PASS] test_onlyOnePoolEver() (gas: 45691)\n[PASS] test_partialFillsAllModes() (gas: 2468116)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 563352)\n[PASS] test_sweepFundsTheReferee() (gas: 875763)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 80.17ms (149.07ms CPU time)\n\nRan 3 tests for test/KeptVaultLaunch.t.sol:KeptVaultLaunchTest\n[PASS] test_constructorRejectsNativeValue() (gas: 2066681)\n[PASS] test_exactLaunchArgumentsDeployOnEmptyChainWithoutInitialization() (gas: 6852797)\n[PASS] test_runtimeFitsAndHasNoForbiddenOpcodes() (gas: 31002565)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 150.58ms (52.16ms CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 853235, ~: 847244)\nLogs:\n  Bound result 2\n  Bound result 899495312091442109524812166\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 357618, ~: 357773)\nLogs:\n  Bound result 3166\n  Bound result 268498866\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5883840)\n[PASS] test_callbacksOnlyManager() (gas: 119114)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 218315)\n[PASS] test_onlyFactoryInitializes() (gas: 221037)\n[PASS] test_onlyOnePoolEver() (gas: 45463)\n[PASS] test_partialFillsAllModes() (gas: 2474138)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 574156)\n[PASS] test_sweepFundsTheReferee() (gas: 879784)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 198.54ms (270.96ms CPU time)\n\nRan 14 tests for test/KeptVaultAudit.t.sol:KeptVaultAuditTest\n[PASS] testFuzz_explicitPriceLimit(uint96,uint96) (runs: 256, μ: 916039, ~: 589714)\nLogs:\n  Bound result 5506\n  Bound result 1592962254\n\n[PASS] testFuzz_snapshotCheckClosesAtDeadline(uint8,uint32) (runs: 256, μ: 719897, ~: 704682)\nLogs:\n  Bound result 1\n  Bound result 165194\n\n[PASS] testFuzz_snapshotRejectsVerdictIssuedAfterDeadline(uint8,uint32) (runs: 256, μ: 1559892, ~: 1563568)\nLogs:\n  Bound result 1\n  Bound result 240258\n\n[PASS] testFuzz_snapshotSignedAtDeadlineCanArriveLater(uint8,uint32) (runs: 256, μ: 1582942, ~: 1586696)\nLogs:\n  Bound result 1\n  Bound result 5454\n\n[PASS] test_checkOpenDistinguishesDefaultAndExplicitPriceCaps() (gas: 505594)\n[PASS] test_creatorCanCheckWhenAlsoBeneficiary() (gas: 1404603)\n[PASS] test_creatorCannotExhaustBeneficiaryAttempts() (gas: 1591611)\n[PASS] test_creatorCannotUseExplicitPriceCheckOrClearStaleAsSideEffect() (gas: 1243379)\n[PASS] test_defaultPriceCapRejectsRepricedIntake() (gas: 588079)\n[PASS] test_defaultPriceCapSurvivesTimelockedIntakeReplacement() (gas: 1376226)\n[PASS] test_explicitCapCanAcceptNewPriceAndRebateActualPrice() (gas: 1507048)\n[PASS] test_githubPublicationDeadlineStillAllowsGraceCheck() (gas: 1443934)\n[PASS] test_priceCapFailureDoesNotClearStaleCheck() (gas: 1282371)\n[PASS] test_zeroQuoteRemainsInvalidEvenWithExplicitCap() (gas: 497017)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 198.73ms (483.34ms CPU time)\n\nRan 33 tests for test/KeptVaultFailurePaths.t.sol:KeptVaultFailurePathsTest\n[PASS] testFuzz_setPanelAcceptsExactlyAStrictMajority(uint16,uint16) (runs: 1000, μ: 58933, ~: 58236)\nLogs:\n  Bound result 9\n  Bound result 21\n\n[PASS] testFuzz_settlementSplitsExactly(uint8,uint256,uint96) (runs: 500, μ: 3550120, ~: 3629127)\nLogs:\n  Bound result 2\n  Bound result 324826435\n\n[PASS] test_adminFunctionsAreOwnerOnly() (gas: 95606)\n[PASS] test_attackerIntakeCannotDeliver() (gas: 1948716)\n[PASS] test_attestationIssuedTooFarInTheFutureIsRefused() (gas: 1383449)\n[PASS] test_cancelAndExecuteNeedAPendingChange() (gas: 247717)\n[PASS] test_checkRefusedOnceKeptOrSettled() (gas: 1719481)\n[PASS] test_checkUnknownPledgeOrMilestone() (gas: 585394)\n[PASS] test_clearStaleFailurePathsAndBoundary() (gas: 1518075)\n[PASS] test_constructorPanelEdges() (gas: 13400)\n[PASS] test_constructorRejectsMissingAddresses() (gas: 11494)\n[PASS] test_creatorWithoutAllowanceCannotCreate() (gas: 366975)\n[PASS] test_duplicateDeliveryIsRefused() (gas: 1455648)\n[PASS] test_emptyAndMalleatedSignaturesAreRefused() (gas: 1451766)\n[PASS] test_expiryBeforeIssueIsRefused() (gas: 1288289)\n[PASS] test_fundFailurePaths() (gas: 621946)\n[PASS] test_imdAsPledgeTokenStaysApartFromBudgets() (gas: 1583377)\n[PASS] test_keptSettlementByAnyoneAlwaysPaysTheBeneficiary() (gas: 1423159)\n[PASS] test_lateAnswerAfterBurnIsRefused() (gas: 1370427)\n[PASS] test_noThenKeptPaysOutAndRebatesOnlyTheKeptCheck() (gas: 2019343)\n[PASS] test_ownerHandoverMovesTheRole() (gas: 104374)\n[PASS] test_pledgesAreIsolated() (gas: 2701013)\n[PASS] test_proposeRejectsZeroFields() (gas: 92190)\n[PASS] test_reentrantTokenCannotReenterSettle() (gas: 2945041)\n[PASS] test_renouncedOwnerCannotAdminister() (gas: 114808)\n[PASS] test_reproposalRestartsTheDelayAndExecutesOnce() (gas: 264436)\n[PASS] test_retiredIntakeCannotAnswerTheNewIntakesRequests() (gas: 2209969)\n[PASS] test_settleBoundaryIsStrictlyAfterGrace() (gas: 590082)\n[PASS] test_signatureForAnotherVaultIsRefused() (gas: 1284780)\n[PASS] test_threeNoVerdictsExhaustAttempts() (gas: 2583960)\n[PASS] test_withdrawUnknownPledgeAndEmptyBudget() (gas: 474327)\n[PASS] test_worstCaseCallbackFitsTheStipend() (gas: 4485373)\n[PASS] test_zeroQuoteRefusesCheckAndSpendsNothing() (gas: 547095)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 198.73ms (294.22ms CPU time)\n\nRan 1 test for test/KeptVaultActorsInvariant.t.sol:KeptVaultActorsInvariantTest\n[PASS]\nKeptVaultActorsInvariantTest invariants:\n[PASS] invariant_imdConserved\n[PASS] invariant_openCountMatches\n[PASS] invariant_rulesHold\n[PASS] invariant_teamTokensConserved\n KeptVaultActorsInvariantTest invariants (runs: 64, calls: 6400, reverts: 0)\n\n╭---------------+----------+-------+---------+----------╮\n| Contract      | Selector | Calls | Reverts | Discards |\n+=======================================================+\n| ActorsHandler | answer   | 572   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | check    | 565   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | clear    | 588   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | create   | 561   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | donate   | 599   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | fund     | 606   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | reprice  | 610   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | rotate   | 587   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | settle   | 587   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | wait     | 548   | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| ActorsHandler | withdraw | 577   | 0       | 0        |\n╰---------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 3667\n  Bound result 2\n  Bound result 863181\n  Bound result 3687\n  Bound result 863181\n  Bound result 3687\n  Bound result 16452\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 16\n  Bound result 4613\n  Bound result 739970130128219838\n  Bound result 1\n  Bound result 27400576963\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 13233\n  Bound result 700000000000020902\n  Bound result 10622\n  Bound result 1\n  Bound result 1\n  Bound result 446744073709551616\n  Bound result 1800003600\n  Bound result 700000000000003153\n  Bound result 1\n  Bound result 40\n  Bound result 1\n  Bound result 6245\n  Bound result 1\n  Bound result 16443\n  Bound result 1\n  Bound result 3600\n  Bound result 13334\n  Bound result 1363\n  Bound result 172800\n  Bound result 172800\n  Bound result 4614\n  Bound result 2\n  Bound result 12459\n  Bound result 2\n  Bound result 2\n  Bound result 11335\n  Bound result 1\n  Bound result 1116\n  Bound result 3521045370\n  Bound result 700000000000009007\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 16004\n  Bound result 2\n  Bound result 146096\n  Bound result 1\n  Bound result 2\n  Bound result 4883171\n  Bound result 2487\n  Bound result 2\n  Bound result 1\n  Bound result 700000000000003165\n  Bound result 2\n  Bound result 592299\n  Bound result 7567\n  Bound result 592299\n  Bound result 7567\n  Bound result 2915563882893259358\n  Bound result 3\n  Bound result 52831\n  Bound result 9975\n  Bound result 52831\n  Bound result 9975\n  Bound result 52831\n  Bound result 9975\n  Bound result 14815\n  Bound result 3\n  Bound result 12731\n  Bound result 3120\n  Bound result 12731\n  Bound result 3120\n  Bound result 12731\n  Bound result 3120\n  Bound result 8769\n  Bound result 1024\n  Bound result 659918\n  Bound result 142910593695152323\n  Bound result 360\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 148436\n  Bound result 9184\n  Bound result 148436\n  Bound result 9184\n  Bound result 148436\n  Bound result 9184\n  Bound result 1001847664\n  Bound result 255\n  Bound result 26846\n  Bound result 2\n  Bound result 3\n  Bound result 3\n  Bound result 580830\n  Bound result 10449\n  Bound result 580830\n  Bound result 10449\n  Bound result 580830\n  Bound result 10449\n  Bound result 1890613957026754444\n  Bound result 3922\n  Bound result 519700786133939440\n  Bound result 7\n  Bound result 1\n  Bound result 23742591095\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 10421\n  Bound result 3\n  Bound result 860669\n  Bound result 2966\n  Bound result 860669\n  Bound result 2966\n  Bound result 860669\n  Bound result 2966\n  Bound result 12222\n  Bound result 8\n  Bound result 1\n  Bound result 1538458570946369884\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 6\n  Bound result 8891\n  Bound result 32\n  Bound result 1\n  Bound result 8\n  Bound result 4293\n  Bound result 411729255748599808\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 8\n  Bound result 4784\n  Bound result 700462648975439248\n  Bound result 4\n  Bound result 1678\n  Bound result 59483\n  Bound result 700000000000007877\n  Bound result 4\n  Bound result 505519\n  Bound result 12186\n  Bound result 505519\n  Bound result 12186\n  Bound result 505519\n  Bound result 12186\n  Bound result 505519\n  Bound result 12186\n  Bound result 15254\n  Bound result 449002806354488103\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.82s (5.82s CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS]\nVaultInvariantTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultInvariantTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19445\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 2861\n  Bound result 1\n  Bound result 3455\n  Bound result 1\n  Bound result 3\n  Bound result 862201\n  Bound result 1551288878\n  Bound result 862201\n  Bound result 1551288878\n  Bound result 862201\n  Bound result 1551288878\n  Bound result 2211\n  Bound result 4\n  Bound result 140797\n  Bound result 16326\n  Bound result 140797\n  Bound result 16326\n  Bound result 140797\n  Bound result 16326\n  Bound result 140797\n  Bound result 16326\n  Bound result 17519\n  Bound result 1\n  Bound result 1\n  Bound result 91\n  Bound result 2\n  Bound result 2\n  Bound result 16688\n  Bound result 5878\n  Bound result 16688\n  Bound result 5878\n  Bound result 1242826418\n  Bound result 16959\n  Bound result 2115\n  Bound result 1\n  Bound result 8618\n  Bound result 8471\n  Bound result 16215\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 1245\n  Bound result 2\n  Bound result 1038\n  Bound result 1710\n  Bound result 29054\n  Bound result 2\n  Bound result 3602\n  Bound result 176625812705849878652307\n  Bound result 3602\n  Bound result 176625812705849878652307\n  Bound result 1217\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 4\n  Bound result 14057\n  Bound result 919393289616239719951272\n  Bound result 14057\n  Bound result 919393289616239719951272\n  Bound result 14057\n  Bound result 919393289616239719951272\n  Bound result 14057\n  Bound result 919393289616239719951272\n  Bound result 8236\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 518400\n  Bound result 10809\n  Bound result 518400\n  Bound result 10809\n  Bound result 518400\n  Bound result 10809\n  Bound result 1590248461715315996\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 140\n  Bound result 3692490579\n  Bound result 4\n  Bound result 2\n  Bound result 5717\n  Bound result 150\n  Bound result 5717\n  Bound result 150\n  Bound result 3538\n  Bound result 5\n  Bound result 464\n  Bound result 8\n  Bound result 2636671977782534782\n  Bound result 4\n  Bound result 860440\n  Bound result 1648\n  Bound result 860440\n  Bound result 1648\n  Bound result 860440\n  Bound result 1648\n  Bound result 860440\n  Bound result 1648\n  Bound result 80\n  Bound result 6\n  Bound result 6\n  Bound result 10\n  Bound result 4938\n  Bound result 5\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 4700\n  Bound result 18\n  Bound result 2\n  Bound result 3\n  Bound result 5674\n  Bound result 16232\n  Bound result 5674\n  Bound result 16232\n  Bound result 5674\n  Bound result 16232\n  Bound result 11193\n  Bound result 3\n  Bound result 4\n  Bound result 447\n  Bound result 9\n  Bound result 8\n  Bound result 4\n  Bound result 10333\n  Bound result 4860\n  Bound result 10333\n  Bound result 4860\n  Bound result 10333\n  Bound result 4860\n  Bound result 10333\n  Bound result 4860\n  Bound result 5944\n  Bound result 2273095416\n  Bound result 23295\n  Bound result 2660\n  Bound result 2488\n  Bound result 4\n  Bound result 205065510\n  Bound result 3437\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 1537\n  Bound result 3\n  Bound result 7913\n  Bound result 2\n  Bound result 951009005\n  Bound result 9\n  Bound result 10\n  Bound result 2\n  Bound result 604800\n  Bound result 17180\n  Bound result 604800\n  Bound result 17180\n  Bound result 1005\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 1\n  Bound result 860578\n  Bound result 1970936680571188297\n  Bound result 1772445522144179457\n  Bound result 1\n  Bound result 860406\n  Bound result 10019\n  Bound result 1176198230211895575\n  Bound result 10\n  Bound result 17\n  Bound result 1171089380634855316\n  Bound result 2\n  Bound result 17338\n  Bound result 2\n  Bound result 17338\n  Bound result 2\n  Bound result 10616\n  Bound result 14\n  Bound result 1\n  Bound result 13\n  Bound result 12\n  Bound result 10\n  Bound result 65280\n  Bound result 12\n  Bound result 18\n  Bound result 10\n  Bound result 2\n  Bound result 3600\n  Bound result 2657\n  Bound result 3600\n  Bound result 2657\n  Bound result 1904875905\n  Bound result 4\n  Bound result 860497\n  Bound result 1583\n  Bound result 860497\n  Bound result 1583\n  Bound result 860497\n  Bound result 1583\n  Bound result 860497\n  Bound result 1583\n  Bound result 11709\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 5\n  Bound result 12\n  Bound result 380\n  Bound result 12396\n  Bound result 8\n  Bound result 917316988329423578\n  Bound result 1\n  Bound result 98977\n  Bound result 140\n  Bound result 259200\n  Bound result 2\n  Bound result 862285\n  Bound result 280\n  Bound result 862285\n  Bound result 280\n  Bound result 282\n  Bound result 2\n  Bound result 7248\n  Bound result 4\n  Bound result 18\n  Bound result 1\n  Bound result 10\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 12.49s (12.49s CPU time)\n\nRan 2 tests for test/VaultInvariant.t.sol:VaultHandlerSmokeTest\n[PASS]\nVaultHandlerSmokeTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultHandlerSmokeTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19327\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 5472\n  Bound result 1\n  Bound result 15026\n  Bound result 1\n  Bound result 3\n  Bound result 862201\n  Bound result 5372\n  Bound result 862201\n  Bound result 5372\n  Bound result 862201\n  Bound result 5372\n  Bound result 2810\n  Bound result 3\n  Bound result 140797\n  Bound result 16474\n  Bound result 140797\n  Bound result 16474\n  Bound result 140797\n  Bound result 16474\n  Bound result 17571\n  Bound result 1\n  Bound result 1\n  Bound result 20386\n  Bound result 2\n  Bound result 2\n  Bound result 17140\n  Bound result 6156\n  Bound result 17140\n  Bound result 6156\n  Bound result 3858947846\n  Bound result 16845\n  Bound result 2274\n  Bound result 1\n  Bound result 9189\n  Bound result 8830\n  Bound result 16515\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 1560\n  Bound result 2\n  Bound result 1070\n  Bound result 1710\n  Bound result 29054\n  Bound result 4\n  Bound result 3602\n  Bound result 15639\n  Bound result 3602\n  Bound result 15639\n  Bound result 3602\n  Bound result 15639\n  Bound result 3602\n  Bound result 15639\n  Bound result 179145366892468986\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 4\n  Bound result 805200\n  Bound result 8\n  Bound result 805200\n  Bound result 8\n  Bound result 805200\n  Bound result 8\n  Bound result 805200\n  Bound result 8\n  Bound result 7592\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 518400\n  Bound result 11595\n  Bound result 518400\n  Bound result 11595\n  Bound result 518400\n  Bound result 11595\n  Bound result 518400\n  Bound result 11595\n  Bound result 4099671044\n  Bound result 5\n  Bound result 5\n  Bound result 5\n  Bound result 140\n  Bound result 880\n  Bound result 4\n  Bound result 3\n  Bound result 5880\n  Bound result 229\n  Bound result 5880\n  Bound result 229\n  Bound result 5880\n  Bound result 229\n  Bound result 3430\n  Bound result 5\n  Bound result 698\n  Bound result 3\n  Bound result 1997534664042727860\n  Bound result 4\n  Bound result 17519\n  Bound result 2170\n  Bound result 17519\n  Bound result 2170\n  Bound result 17519\n  Bound result 2170\n  Bound result 17519\n  Bound result 2170\n  Bound result 3569965829\n  Bound result 6\n  Bound result 6\n  Bound result 10\n  Bound result 4938\n  Bound result 5\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 7040\n  Bound result 18\n  Bound result 2\n  Bound result 3\n  Bound result 5505\n  Bound result 16513\n  Bound result 5505\n  Bound result 16513\n  Bound result 5505\n  Bound result 16513\n  Bound result 11473\n  Bound result 7\n  Bound result 4\n  Bound result 10854\n  Bound result 5\n  Bound result 8\n  Bound result 4\n  Bound result 583304\n  Bound result 291\n  Bound result 583304\n  Bound result 291\n  Bound result 583304\n  Bound result 291\n  Bound result 583304\n  Bound result 291\n  Bound result 6377\n  Bound result 3370\n  Bound result 23295\n  Bound result 3340668340\n  Bound result 50736\n  Bound result 4\n  Bound result 1095\n  Bound result 1502939778\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 181\n  Bound result 3\n  Bound result 9445\n  Bound result 2\n  Bound result 4799\n  Bound result 5\n  Bound result 10\n  Bound result 2\n  Bound result 604800\n  Bound result 17322\n  Bound result 604800\n  Bound result 17322\n  Bound result 189\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 1\n  Bound result 860578\n  Bound result 7661146347842653916911\n  Bound result 4652246262386823718\n  Bound result 1\n  Bound result 860406\n  Bound result 9034\n  Bound result 3517634093918686025\n  Bound result 10\n  Bound result 11\n  Bound result 1171089380634855316\n  Bound result 2\n  Bound result 17625\n  Bound result 9849\n  Bound result 17625\n  Bound result 9849\n  Bound result 1103\n  Bound result 14\n  Bound result 1\n  Bound result 18\n  Bound result 12\n  Bound result 10\n  Bound result 21466\n  Bound result 12\n  Bound result 18\n  Bound result 6\n  Bound result 1\n  Bound result 3600\n  Bound result 2237\n  Bound result 1975187046\n  Bound result 4\n  Bound result 860497\n  Bound result 1434\n  Bound result 860497\n  Bound result 1434\n  Bound result 860497\n  Bound result 1434\n  Bound result 860497\n  Bound result 1434\n  Bound result 11949\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 8\n  Bound result 12\n  Bound result 657\n  Bound result 1055239862\n  Bound result 8\n  Bound result 573952591468440069\n  Bound result 5\n  Bound result 98977\n  Bound result 140\n  Bound result 259200\n  Bound result 2\n  Bound result 859658\n  Bound result 5562\n  Bound result 859658\n  Bound result 5562\n  Bound result 281\n  Bound result 6\n  Bound result 5069\n  Bound result 4\n  Bound result 11\n  Bound result 1\n  Bound result 10\n\n[PASS] test_handlerReachesPayoutAndBurn() (gas: 2028271)\nLogs:\n  Bound result 2\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 2000000000000000000\n  Bound result 1\n  Bound result 1\n  Bound result 259200\n  Bound result 259200\n  Bound result 1\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 12.50s (12.49s CPU time)\n\nRan 14 test suites in 12.50s (31.75s CPU time): 133 tests passed, 0 failed, 1 skipped (134 total tests)\n","passed":true},{"durationMs":104,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"KeptHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"KeptHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"KeptHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"KeptHook.sweep()\",\"KeptHook.unlockCallback(bytes)\",\"KeptToken.approve(address,uint256)\",\"KeptToken.transfer(address,uint256)\",\"KeptToken.transferFrom(address,address,uint256)\",\"KeptVault.cancelProtocol()\",\"KeptVault.check(uint256,uint8)\",\"KeptVault.check(uint256,uint8,uint256)\",\"KeptVault.clearStale(uint256,uint8)\",\"KeptVault.createPledge(address,address,string,(uint8,uint64,uint128,uint64,address,uint256,string,string,string)[],uint256)\",\"KeptVault.executeProtocol()\",\"KeptVault.fund(uint256,uint256)\",\"KeptVault.fundReferee(uint256)\",\"KeptVault.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"KeptVault.proposeProtocol(address,bytes32,address)\",\"KeptVault.setOwner(address)\",\"KeptVault.setPanel(uint16,uint16)\",\"KeptVault.settle(uint256,uint8)\",\"KeptVault.withdrawBudget(uint256)\"],\"files\":{\".gitattributes\":2,\".gitignore\":5,\"ADAPTATION.md\":150,\"README.md\":96,\"dist/apple-touch-icon.png\":8,\"dist/assets/ccip-DEgEpxnr.js\":1,\"dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff\":60,\"dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2\":58,\"dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff\":51,\"dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2\":62,\"dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2\":78,\"dist/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff\":53,\"dist/assets/index-TiwfCIFz.css\":1,\"dist/assets/index-f9ceCkFm.js\":36,\"dist/assets/secp256k1-Desv_BdV.js\":1,\"dist/assets/swarm-DuldE8ej.js\":83,\"dist/assets/utils-Bpv4vmSW.js\":1,\"dist/favicon-32.png\":4,\"dist/favicon.svg\":5,\"dist/icon-512.png\":8,\"dist/index.html\":23,\"docs/ORACLE_PREFLIGHT.json\":384,\"docs/OUTREACH.md\":60,\"docs/SPEC.md\":147,\"docs/SUBMISSION.md\":81,\"docs/VERIFICATION.md\":132,\"docs/brand/generate_logos.py\":62,\"docs/brand/kept-avatar-400.png\":12,\"docs/brand/kept-avatar.png\":34,\"docs/brand/kept-avatar.svg\":7,\"docs/brand/kept-logo-dark.png\":54,\"docs/brand/kept-logo-dark.svg\":61,\"docs/brand/kept-logo.png\":70,\"docs/brand/kept-logo.svg\":61,\"docs/brand/kept-mark-dark.png\":38,\"docs/brand/kept-mark-dark.svg\":59,\"docs/brand/kept-mark.png\":126,\"docs/brand/kept-mark.svg\":59,\"docs/brand/kept-stamp.png\":215,\"docs/brand/kept-stamp.svg\":64,\"docs/brand/kept-x-banner.png\":790,\"docs/brand/kept-x-banner@2x.png\":2387,\"docs/research.md\":61,\"docs/screenshots/local-home-light.png\":833,\"docs/screenshots/local-home.png\":768,\"docs/screenshots/local-how.png\":310,\"docs/screenshots/local-make-pledge.png\":323,\"docs/screenshots/local-mobile.png\":242,\"docs/screenshots/local-pledge.png\":332,\"foundry.toml\":21,\"remappings.txt\":4,\"script/LocalDemo.s.sol\":111,\"scripts/launch/.gitignore\":2,\"scripts/launch/README.md\":61,\"scripts/launch/launch.mjs\":474,\"scripts/launch/package-lock.json\":248,\"scripts/launch/package.json\":14,\"src/KeptHook.sol\":197,\"src/KeptToken.sol\":60,\"src/KeptVault.sol\":664,\"src/OracleAttestation.sol\":239,\"src/interfaces/IIntake.sol\":18,\"src/libraries/HookFlags.sol\":30,\"src/libraries/Questions.sol\":250,\"src/libraries/SpecifiedAmount.sol\":101,\"test/KeptHook.t.sol\":154,\"test/KeptVault.t.sol\":639,\"test/KeptVaultActorsInvariant.t.sol\":492,\"test/KeptVaultAudit.t.sol\":243,\"test/KeptVaultFailurePaths.t.sol\":642,\"test/KeptVaultLaunch.t.sol\":100,\"test/KeptVaultTokenCompatibility.t.sol\":49,\"test/OracleConformance.t.sol\":119,\"test/RealAttestation.t.sol\":66,\"test/VaultInvariant.t.sol\":228,\"test/fork/Robinhood.t.sol\":135,\"test/helpers/HookFixture.sol\":155,\"test/helpers/TestRouter.sol\":70,\"test/helpers/VaultFixture.sol\":190,\"test/mocks/FeeToken.sol\":27,\"test/mocks/MockERC20.sol\":58,\"test/mocks/MockIntake.sol\":64,\"vercel.json\":20,\"web/README.md\":76,\"web/index.html\":19,\"web/package-lock.json\":1015,\"web/package.json\":18,\"web/public/apple-touch-icon.png\":8,\"web/public/favicon-32.png\":4,\"web/public/favicon.svg\":5,\"web/public/icon-512.png\":8,\"web/src/abi/KeptHook.json\":652,\"web/src/abi/KeptToken.json\":244,\"web/src/abi/KeptVault.json\":1940,\"web/src/chain.js\":335,\"web/src/config.js\":30,\"web/src/dom.js\":84,\"web/src/fx.js\":325,\"web/src/hero.js\":149,\"web/src/icons.js\":42,\"web/src/main.js\":1410,\"web/src/store.js\":88,\"web/src/styles.css\":772,\"web/src/swarm.js\":586,\"web/src/ui.js\":219,\"web/vite.config.js\":42},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"3c7b8702d105744891f98a67dd434acc18648b10f3969517f19742753b43845d","verifiedTreeHash":"15b27abff51c3e3b934ee29d2932a7a7206bece9","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":130747,"exitCode":0,"name":"build","output":"Compiling 116 files with Solc 0.8.26\nSolc 0.8.26 finished in 130.48s\nCompiler run successful!\n","passed":true},{"durationMs":29413,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/RealAttestation.t.sol:RealAttestationTest\n[PASS] test_liveSignatureRecoversTheLiveSigner() (gas: 12095)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.86ms (1.63ms CPU time)\n\nRan 1 test for test/fork/Robinhood.t.sol:RobinhoodForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 2.56ms (0.00ns CPU time)\n\nRan 2 tests for test/KeptVaultTokenCompatibility.t.sol:KeptVaultTokenCompatibilityTest\n[PASS] test_standardTokenSharedPledgesSettleAndRefundIndependently() (gas: 1956008)\n[PASS] test_unsupportedBalanceShrinkCanStrandLastTrancheAndBudget() (gas: 1167841)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 3.56ms (3.13ms CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTokenFirstTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 854561, ~: 849434)\nLogs:\n  Bound result 715\n  Bound result 899000000000000000000011154\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 356834, ~: 362910)\nLogs:\n  Bound result 3166\n  Bound result 268498866\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5887215)\n[PASS] test_callbacksOnlyManager() (gas: 119829)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 209541)\n[PASS] test_onlyFactoryInitializes() (gas: 221547)\n[PASS] test_onlyOnePoolEver() (gas: 45691)\n[PASS] test_partialFillsAllModes() (gas: 2468116)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 563352)\n[PASS] test_sweepFundsTheReferee() (gas: 875763)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 130.05ms (267.54ms CPU time)\n\nRan 14 tests for test/KeptHook.t.sol:KeptHookTest\n[PASS] testFuzz_crossTicks(bool,bool,uint96,uint16) (runs: 256, μ: 853251, ~: 847340)\nLogs:\n  Bound result 465\n  Bound result 899000000000000206610767428\n\n[PASS] testFuzz_feeAndPartialFills(bool,bool,uint96,uint32,bool) (runs: 256, μ: 357621, ~: 357785)\nLogs:\n  Bound result 39\n  Bound result 7316333\n\n[PASS] test_allModesAtOpeningMidpointAndAfter() (gas: 5883840)\n[PASS] test_callbacksOnlyManager() (gas: 119114)\n[PASS] test_constructorRejectsBadConfig() (gas: 10682)\n[PASS] test_feeSchedule() (gas: 3534370)\n[PASS] test_noLiquidityNoFee() (gas: 218315)\n[PASS] test_onlyFactoryInitializes() (gas: 221037)\n[PASS] test_onlyOnePoolEver() (gas: 45463)\n[PASS] test_partialFillsAllModes() (gas: 2474138)\n[PASS] test_permissionBits() (gas: 5773)\n[PASS] test_sweepDuringUnlockDefers() (gas: 574156)\n[PASS] test_sweepFundsTheReferee() (gas: 879784)\n[PASS] test_sweepIncludesDirectDonations() (gas: 177816)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 132.56ms (274.95ms CPU time)\n\nRan 4 tests for test/OracleConformance.t.sol:OracleConformanceTest\n[PASS] test_acceptsTheProtocolSignature() (gas: 20019)\n[PASS] test_callbackSelectorIsCanonical() (gas: 3543)\n[PASS] test_digestMatchesTheProtocol() (gas: 13531)\n[PASS] test_keptVerdictFromTheVectorKey() (gas: 1339588)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 132.71ms (3.78ms CPU time)\n\nRan 43 tests for test/KeptVault.t.sol:KeptVaultTest\n[PASS] test_attestationCannotBeReplayedOnAnotherCheck() (gas: 1726979)\n[PASS] test_callbackOnlyFromIntake() (gas: 1254102)\n[PASS] test_callbackRejectsExpiredAttestation() (gas: 1264729)\n[PASS] test_callbackRejectsUnknownRequest() (gas: 1254900)\n[PASS] test_callbackRejectsWeakOrMismatchedAttestations() (gas: 1991894)\n[PASS] test_callbackRejectsWrongAnswerType() (gas: 1289194)\n[PASS] test_callbackRejectsWrongSigner() (gas: 1270836)\n[PASS] test_chainEvidenceAcceptsDeployerSettledVerdict() (gas: 1240396)\n[PASS] test_checkNeedsBudget() (gas: 1237961)\n[PASS] test_checkOpenReportsBudget() (gas: 543071)\n[PASS] test_checkPaysIntakeFromBudget() (gas: 1267661)\n[PASS] test_checkRejectsIntakeThatDoesNotPull() (gas: 1014807)\n[PASS] test_checkRejectsRepeatedRequestId() (gas: 1697655)\n[PASS] test_createPullsTokensAndBudget() (gas: 477341)\n[PASS] test_createRejectsBadQuestionStrings() (gas: 2756885)\n[PASS] test_createRejectsTaxedToken() (gas: 1114020)\n[PASS] test_createValidatesMilestones() (gas: 704836)\n[PASS] test_createValidatesPledge() (gas: 192120)\n[PASS] test_falseVerdictKeepsMilestoneOpen() (gas: 1861435)\n[PASS] test_inFlightCheckStaysBoundToItsIntake() (gas: 1486471)\n[PASS] test_isoDate() (gas: 41366)\n[PASS] test_keptPaysBeneficiaryAndReturnsBudget() (gas: 1528583)\n[PASS] test_keptRebatesFromRefereeFund() (gas: 1579314)\n[PASS] test_multiMilestoneMixedOutcomes() (gas: 3152001)\n[PASS] test_newChecksUseTheRotatedSigner() (gas: 1529920)\n[PASS] test_noRebateWhenFundIsShort() (gas: 1424042)\n[PASS] test_oneCheckInFlight() (gas: 1172688)\n[PASS] test_onlyBeneficiaryChecksBeforeDeadline() (gas: 1177243)\n[PASS] test_onlyBeneficiaryChecksEvenAfterDeadline() (gas: 1264896)\n[PASS] test_ownerHasNoPathToLockedTokens() (gas: 540546)\n[PASS] test_panelChangeOnlyAffectsNewPledges() (gas: 871407)\n[PASS] test_panelEvidenceNeedsQuorumAgreement() (gas: 1286460)\n[PASS] test_protocolChangeWaitsSevenDays() (gas: 224290)\n[PASS] test_questionBodies() (gas: 68804)\n[PASS] test_questionOfMatchesPreview() (gas: 496487)\n[PASS] test_settleBurnsAfterStaleLastCheck() (gas: 1368568)\n[PASS] test_settleTwiceReverts() (gas: 528241)\n[PASS] test_settleWaitsForCheckInFlight() (gas: 1450907)\n[PASS] test_signerRotationDoesNotStrandChecksInFlight() (gas: 1496054)\n[PASS] test_staleCheckRetriesAndAttemptsCap() (gas: 1744575)\n[PASS] test_unprovenMilestoneBurns() (gas: 644737)\n[PASS] test_valueTemplateRejectsZeroThreshold() (gas: 195184)\n[PASS] test_withdrawBudgetOnlyWhenFinished() (gas: 844312)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 133.08ms (51.97ms CPU time)\n\nRan 3 tests for test/KeptVaultLaunch.t.sol:KeptVaultLaunchTest\n[PASS] test_constructorRejectsNativeValue() (gas: 2066681)\n[PASS] test_exactLaunchArgumentsDeployOnEmptyChainWithoutInitialization() (gas: 6852797)\n[PASS] test_runtimeFitsAndHasNoForbiddenOpcodes() (gas: 31002565)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 142.55ms (106.70ms CPU time)\n\nRan 14 tests for test/KeptVaultAudit.t.sol:KeptVaultAuditTest\n[PASS] testFuzz_explicitPriceLimit(uint96,uint96) (runs: 256, μ: 916039, ~: 589714)\nLogs:\n  Bound result 5506\n  Bound result 1592962254\n\n[PASS] testFuzz_snapshotCheckClosesAtDeadline(uint8,uint32) (runs: 256, μ: 721577, ~: 704773)\nLogs:\n  Bound result 1\n  Bound result 16159\n\n[PASS] testFuzz_snapshotRejectsVerdictIssuedAfterDeadline(uint8,uint32) (runs: 256, μ: 1562148, ~: 1563659)\nLogs:\n  Bound result 1\n  Bound result 165194\n\n[PASS] testFuzz_snapshotSignedAtDeadlineCanArriveLater(uint8,uint32) (runs: 256, μ: 1585203, ~: 1586952)\nLogs:\n  Bound result 1\n  Bound result 5454\n\n[PASS] test_checkOpenDistinguishesDefaultAndExplicitPriceCaps() (gas: 505594)\n[PASS] test_creatorCanCheckWhenAlsoBeneficiary() (gas: 1404603)\n[PASS] test_creatorCannotExhaustBeneficiaryAttempts() (gas: 1591611)\n[PASS] test_creatorCannotUseExplicitPriceCheckOrClearStaleAsSideEffect() (gas: 1243379)\n[PASS] test_defaultPriceCapRejectsRepricedIntake() (gas: 588079)\n[PASS] test_defaultPriceCapSurvivesTimelockedIntakeReplacement() (gas: 1376226)\n[PASS] test_explicitCapCanAcceptNewPriceAndRebateActualPrice() (gas: 1507048)\n[PASS] test_githubPublicationDeadlineStillAllowsGraceCheck() (gas: 1443934)\n[PASS] test_priceCapFailureDoesNotClearStaleCheck() (gas: 1282371)\n[PASS] test_zeroQuoteRemainsInvalidEvenWithExplicitCap() (gas: 497017)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 143.05ms (429.22ms CPU time)\n\nRan 2 tests for test/VaultInvariant.t.sol:VaultHandlerSmokeTest\n[PASS]\nVaultHandlerSmokeTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultHandlerSmokeTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19327\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 5472\n  Bound result 1\n  Bound result 15026\n  Bound result 1\n  Bound result 4\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 862401\n  Bound result 5372\n  Bound result 2810\n  Bound result 4\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 860591\n  Bound result 16958\n  Bound result 1313867396929476720\n  Bound result 3\n  Bound result 1\n  Bound result 20894\n  Bound result 2\n  Bound result 4\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 17331\n  Bound result 4815\n  Bound result 1181\n  Bound result 16665\n  Bound result 2354\n  Bound result 4\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 861327\n  Bound result 9840\n  Bound result 16717\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 14519\n  Bound result 3\n  Bound result 2438\n  Bound result 1710\n  Bound result 127340\n  Bound result 2\n  Bound result 860419\n  Bound result 42161\n  Bound result 860419\n  Bound result 42161\n  Bound result 1368\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 1\n  Bound result 16105\n  Bound result 49828827948877472595967\n  Bound result 1904875907\n  Bound result 7\n  Bound result 3\n  Bound result 5\n  Bound result 3\n  Bound result 408414\n  Bound result 385\n  Bound result 408414\n  Bound result 385\n  Bound result 408414\n  Bound result 385\n  Bound result 3176891670197620695\n  Bound result 8\n  Bound result 5\n  Bound result 5\n  Bound result 56\n  Bound result 2475\n  Bound result 4\n  Bound result 1\n  Bound result 6107\n  Bound result 230\n  Bound result 5167\n  Bound result 1\n  Bound result 947\n  Bound result 8\n  Bound result 2210211349190551398\n  Bound result 2\n  Bound result 17743\n  Bound result 2833596647402442496\n  Bound result 17743\n  Bound result 2833596647402442496\n  Bound result 15678\n  Bound result 10\n  Bound result 4\n  Bound result 10\n  Bound result 4938\n  Bound result 10\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 6969\n  Bound result 10000\n  Bound result 2\n  Bound result 2\n  Bound result 6181\n  Bound result 16785\n  Bound result 6181\n  Bound result 16785\n  Bound result 10905\n  Bound result 7\n  Bound result 4\n  Bound result 11495\n  Bound result 3\n  Bound result 12\n  Bound result 4\n  Bound result 861203\n  Bound result 5079\n  Bound result 861203\n  Bound result 5079\n  Bound result 861203\n  Bound result 5079\n  Bound result 861203\n  Bound result 5079\n  Bound result 6256\n  Bound result 3502\n  Bound result 23295\n  Bound result 5134\n  Bound result 139520\n  Bound result 4\n  Bound result 797\n  Bound result 3710\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 183\n  Bound result 3\n  Bound result 9187\n  Bound result 9\n  Bound result 2124\n  Bound result 10\n  Bound result 4\n  Bound result 1\n  Bound result 860527\n  Bound result 17426\n  Bound result 600\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 3\n  Bound result 150000\n  Bound result 447292937964381827736327\n  Bound result 150000\n  Bound result 447292937964381827736327\n  Bound result 150000\n  Bound result 447292937964381827736327\n  Bound result 4652246262386823715\n  Bound result 1\n  Bound result 860405\n  Bound result 9196\n  Bound result 2344208622544047332\n  Bound result 13\n  Bound result 16\n  Bound result 1171089380634855316\n  Bound result 4\n  Bound result 860427\n  Bound result 4674\n  Bound result 860427\n  Bound result 4674\n  Bound result 860427\n  Bound result 4674\n  Bound result 860427\n  Bound result 4674\n  Bound result 4000\n  Bound result 14\n  Bound result 1\n  Bound result 7\n  Bound result 18\n  Bound result 18\n  Bound result 1048\n  Bound result 18\n  Bound result 9\n  Bound result 18\n  Bound result 4\n  Bound result 3600\n  Bound result 66681018635293695549992\n  Bound result 3600\n  Bound result 66681018635293695549992\n  Bound result 3600\n  Bound result 66681018635293695549992\n  Bound result 3600\n  Bound result 66681018635293695549992\n  Bound result 2024493548\n  Bound result 4\n  Bound result 860643\n  Bound result 3707953492\n  Bound result 860643\n  Bound result 3707953492\n  Bound result 860643\n  Bound result 3707953492\n  Bound result 860643\n  Bound result 3707953492\n  Bound result 12434\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 8\n  Bound result 20\n  Bound result 859\n  Bound result 13350\n  Bound result 14\n  Bound result 2167207896513718000\n  Bound result 16\n  Bound result 98977\n  Bound result 3600\n  Bound result 172800\n  Bound result 4\n  Bound result 862386\n  Bound result 2963\n  Bound result 862386\n  Bound result 2963\n  Bound result 862386\n  Bound result 2963\n  Bound result 862386\n  Bound result 2963\n  Bound result 2835717306\n  Bound result 4\n  Bound result 5599\n  Bound result 1\n  Bound result 1\n  Bound result 11\n  Bound result 10\n\n[PASS] test_handlerReachesPayoutAndBurn() (gas: 2028271)\nLogs:\n  Bound result 2\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 7200\n  Bound result 1000000000000000000\n  Bound result 2000000000000000000\n  Bound result 1\n  Bound result 1\n  Bound result 259200\n  Bound result 259200\n  Bound result 1\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 29.14s (29.14s CPU time)\n\nRan 1 test for test/VaultInvariant.t.sol:VaultInvariantTest\n[PASS]\nVaultInvariantTest invariants:\n[PASS] invariant_imdAccounted\n[PASS] invariant_settledMilestonesHaveOutcome\n[PASS] invariant_tokensConserved\n VaultInvariantTest invariants (runs: 128, calls: 16384, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| VaultHandler | answer   | 1840  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | check    | 1827  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | clear    | 1771  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | create   | 1866  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | donate   | 1775  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | fund     | 1909  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | settle   | 1811  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | wait     | 1792  | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| VaultHandler | withdraw | 1793  | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2833596647402410961\n  Bound result 19445\n  Bound result 3\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 561392\n  Bound result 2553715449280884589225\n  Bound result 6735\n  Bound result 1\n  Bound result 1\n  Bound result 3241\n  Bound result 1\n  Bound result 2861\n  Bound result 1\n  Bound result 3455\n  Bound result 1\n  Bound result 4\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 862401\n  Bound result 1551288878\n  Bound result 2211\n  Bound result 1\n  Bound result 860591\n  Bound result 16282\n  Bound result 17510\n  Bound result 2\n  Bound result 1\n  Bound result 2451791247615983616\n  Bound result 2\n  Bound result 4\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 16707\n  Bound result 5506\n  Bound result 1242826416\n  Bound result 16959\n  Bound result 2115\n  Bound result 4\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 8618\n  Bound result 8470\n  Bound result 16217\n  Bound result 5\n  Bound result 2\n  Bound result 1970936680571185047\n  Bound result 195956085\n  Bound result 3\n  Bound result 1723020866\n  Bound result 1710\n  Bound result 127340\n  Bound result 2\n  Bound result 860419\n  Bound result 647555205861763807992079\n  Bound result 860419\n  Bound result 647555205861763807992079\n  Bound result 205065511\n  Bound result 6\n  Bound result 2705512146910513357\n  Bound result 1\n  Bound result 13841\n  Bound result 3298891303\n  Bound result 1521356376\n  Bound result 4\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 408414\n  Bound result 10809\n  Bound result 411723527615725136\n  Bound result 7\n  Bound result 5\n  Bound result 5\n  Bound result 56\n  Bound result 2705626677\n  Bound result 4\n  Bound result 3\n  Bound result 5696\n  Bound result 148\n  Bound result 5696\n  Bound result 148\n  Bound result 5696\n  Bound result 148\n  Bound result 3302\n  Bound result 1\n  Bound result 593\n  Bound result 5\n  Bound result 1547204147371810291\n  Bound result 2\n  Bound result 17091\n  Bound result 1671\n  Bound result 17091\n  Bound result 1671\n  Bound result 2547112994207557364\n  Bound result 10\n  Bound result 4\n  Bound result 10\n  Bound result 4938\n  Bound result 10\n  Bound result 3\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 4056\n  Bound result 2\n  Bound result 33312917475121738\n  Bound result 6571\n  Bound result 10000\n  Bound result 2\n  Bound result 2\n  Bound result 567184\n  Bound result 16273\n  Bound result 567184\n  Bound result 16273\n  Bound result 10465\n  Bound result 4\n  Bound result 4\n  Bound result 11916\n  Bound result 3\n  Bound result 12\n  Bound result 4\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 10163\n  Bound result 6225\n  Bound result 6739\n  Bound result 3154\n  Bound result 23295\n  Bound result 2552\n  Bound result 1877\n  Bound result 4\n  Bound result 1212\n  Bound result 3384\n  Bound result 1\n  Bound result 1\n  Bound result 620858\n  Bound result 4216210513948192818899\n  Bound result 3472386685727505259\n  Bound result 1535\n  Bound result 3\n  Bound result 7664\n  Bound result 9\n  Bound result 13835823\n  Bound result 7\n  Bound result 4\n  Bound result 2\n  Bound result 860527\n  Bound result 16651\n  Bound result 860527\n  Bound result 16651\n  Bound result 1237\n  Bound result 4\n  Bound result 1143447654180813311\n  Bound result 3\n  Bound result 150000\n  Bound result 268522786714562930678736\n  Bound result 150000\n  Bound result 268522786714562930678736\n  Bound result 150000\n  Bound result 268522786714562930678736\n  Bound result 2182480387\n  Bound result 1\n  Bound result 860405\n  Bound result 301\n  Bound result 981858843750127194\n  Bound result 13\n  Bound result 2\n  Bound result 1171089380634855316\n  Bound result 4\n  Bound result 17606\n  Bound result 249\n  Bound result 17606\n  Bound result 249\n  Bound result 17606\n  Bound result 249\n  Bound result 17606\n  Bound result 249\n  Bound result 1218\n  Bound result 14\n  Bound result 1\n  Bound result 9\n  Bound result 18\n  Bound result 18\n  Bound result 9993\n  Bound result 18\n  Bound result 9\n  Bound result 18\n  Bound result 1\n  Bound result 3600\n  Bound result 2833596647402410962\n  Bound result 1931921857\n  Bound result 4\n  Bound result 860643\n  Bound result 3231863403\n  Bound result 860643\n  Bound result 3231863403\n  Bound result 860643\n  Bound result 3231863403\n  Bound result 860643\n  Bound result 3231863403\n  Bound result 11840\n  Bound result 7\n  Bound result 1092170414164959108\n  Bound result 1\n  Bound result 20\n  Bound result 658\n  Bound result 12662\n  Bound result 14\n  Bound result 118122910804878860\n  Bound result 6\n  Bound result 98977\n  Bound result 3600\n  Bound result 172800\n  Bound result 4\n  Bound result 862198\n  Bound result 1477\n  Bound result 862198\n  Bound result 1477\n  Bound result 862198\n  Bound result 1477\n  Bound result 862198\n  Bound result 1477\n  Bound result 281\n  Bound result 1\n  Bound result 3212\n  Bound result 1\n  Bound result 1\n  Bound result 11\n  Bound result 10\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 29.16s (29.15s CPU time)\n\nRan 11 test suites in 29.16s (59.12s CPU time): 98 tests passed, 0 failed, 1 skipped (99 total tests)\n","passed":true},{"durationMs":274,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"KeptHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"KeptHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"KeptHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"KeptHook.sweep()\",\"KeptHook.unlockCallback(bytes)\",\"KeptToken.approve(address,uint256)\",\"KeptToken.transfer(address,uint256)\",\"KeptToken.transferFrom(address,address,uint256)\",\"KeptVault.cancelProtocol()\",\"KeptVault.check(uint256,uint8)\",\"KeptVault.check(uint256,uint8,uint256)\",\"KeptVault.clearStale(uint256,uint8)\",\"KeptVault.createPledge(address,address,string,(uint8,uint64,uint128,uint64,address,uint256,string,string,string)[],uint256)\",\"KeptVault.executeProtocol()\",\"KeptVault.fund(uint256,uint256)\",\"KeptVault.fundReferee(uint256)\",\"KeptVault.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"KeptVault.proposeProtocol(address,bytes32,address)\",\"KeptVault.setOwner(address)\",\"KeptVault.setPanel(uint16,uint16)\",\"KeptVault.settle(uint256,uint8)\",\"KeptVault.withdrawBudget(uint256)\"],\"files\":{\".gitattributes\":2,\".gitignore\":5,\"ADAPTATION.md\":150,\"README.md\":96,\"dist/apple-touch-icon.png\":8,\"dist/assets/ccip-DEgEpxnr.js\":1,\"dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff\":60,\"dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2\":58,\"dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff\":51,\"dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2\":62,\"dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2\":78,\"dist/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff\":53,\"dist/assets/index-TiwfCIFz.css\":1,\"dist/assets/index-f9ceCkFm.js\":36,\"dist/assets/secp256k1-Desv_BdV.js\":1,\"dist/assets/swarm-DuldE8ej.js\":83,\"dist/assets/utils-Bpv4vmSW.js\":1,\"dist/favicon-32.png\":4,\"dist/favicon.svg\":5,\"dist/icon-512.png\":8,\"dist/index.html\":23,\"docs/ORACLE_PREFLIGHT.json\":384,\"docs/OUTREACH.md\":60,\"docs/SPEC.md\":147,\"docs/SUBMISSION.md\":81,\"docs/VERIFICATION.md\":132,\"docs/brand/generate_logos.py\":62,\"docs/brand/kept-avatar-400.png\":12,\"docs/brand/kept-avatar.png\":34,\"docs/brand/kept-avatar.svg\":7,\"docs/brand/kept-logo-dark.png\":54,\"docs/brand/kept-logo-dark.svg\":61,\"docs/brand/kept-logo.png\":70,\"docs/brand/kept-logo.svg\":61,\"docs/brand/kept-mark-dark.png\":38,\"docs/brand/kept-mark-dark.svg\":59,\"docs/brand/kept-mark.png\":126,\"docs/brand/kept-mark.svg\":59,\"docs/brand/kept-stamp.png\":215,\"docs/brand/kept-stamp.svg\":64,\"docs/brand/kept-x-banner.png\":790,\"docs/brand/kept-x-banner@2x.png\":2387,\"docs/research.md\":61,\"docs/screenshots/local-home-light.png\":833,\"docs/screenshots/local-home.png\":768,\"docs/screenshots/local-how.png\":310,\"docs/screenshots/local-make-pledge.png\":323,\"docs/screenshots/local-mobile.png\":242,\"docs/screenshots/local-pledge.png\":332,\"foundry.toml\":21,\"launch.json\":18,\"remappings.txt\":4,\"script/LocalDemo.s.sol\":111,\"scripts/launch/.gitignore\":2,\"scripts/launch/README.md\":61,\"scripts/launch/launch.mjs\":474,\"scripts/launch/package-lock.json\":248,\"scripts/launch/package.json\":14,\"src/KeptHook.sol\":197,\"src/KeptToken.sol\":60,\"src/KeptVault.sol\":664,\"src/OracleAttestation.sol\":239,\"src/interfaces/IIntake.sol\":18,\"src/libraries/HookFlags.sol\":30,\"src/libraries/Questions.sol\":250,\"src/libraries/SpecifiedAmount.sol\":101,\"test/KeptHook.t.sol\":154,\"test/KeptVault.t.sol\":639,\"test/KeptVaultAudit.t.sol\":243,\"test/KeptVaultLaunch.t.sol\":100,\"test/KeptVaultTokenCompatibility.t.sol\":49,\"test/OracleConformance.t.sol\":119,\"test/RealAttestation.t.sol\":66,\"test/VaultInvariant.t.sol\":228,\"test/fork/Robinhood.t.sol\":135,\"test/helpers/HookFixture.sol\":155,\"test/helpers/TestRouter.sol\":70,\"test/helpers/VaultFixture.sol\":190,\"test/mocks/FeeToken.sol\":27,\"test/mocks/MockERC20.sol\":58,\"test/mocks/MockIntake.sol\":64,\"vercel.json\":20,\"web/README.md\":76,\"web/index.html\":19,\"web/package-lock.json\":1015,\"web/package.json\":18,\"web/public/apple-touch-icon.png\":8,\"web/public/favicon-32.png\":4,\"web/public/favicon.svg\":5,\"web/public/icon-512.png\":8,\"web/src/abi/KeptHook.json\":652,\"web/src/abi/KeptToken.json\":244,\"web/src/abi/KeptVault.json\":1940,\"web/src/chain.js\":335,\"web/src/config.js\":30,\"web/src/dom.js\":84,\"web/src/fx.js\":325,\"web/src/hero.js\":149,\"web/src/icons.js\":42,\"web/src/main.js\":1410,\"web/src/store.js\":88,\"web/src/styles.css\":772,\"web/src/swarm.js\":586,\"web/src/ui.js\":219,\"web/vite.config.js\":42},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9e04d0c51f9ec62bc93bdc1bbbc0d9c343b24c453eabfeed9dc9a387607383ae","verifiedTreeHash":"8186f98a9cec4ac07b59723c6ab021073a6b2ddd","verifierVersion":"0.1.0+745c1db4"}]}