claimsStarted is the finality latch: once value has moved, the moderator can no longer re-flag the outcome (DESIGN §4 — "finality is value-movement"). Every value-moving entrypoint sets it — except sweepUnclaimedBonus, which deliberately does not (to stop a 1-wei donation from griefing the re-flag window).
When riskWindowStart == 0 (no active-risk window was ever observed — nobody poked during UNDER_ATTACK, or the registry reached CORRUPTED fast), sweepUnclaimedBonus sweeps the entire bonus to recoveryAddress and decrements live totalBonus to zero — a major value movement that does not latch claimsStarted. The moderator can then still make the normal §4 correction from SURVIVED to good-faith CORRUPTED (naming the whitehat who legally rescued the in-scope contract). That re-flag re-snapshots snapshotTotalBonus = totalBonus, which is now zero, so bountyEntitlement = snapshotTotalStaked — the whitehat is entitled to principal only. Per DESIGN §12 the whole pool (principal + bonus) is the whitehat's bounty; the bonus has been captured by the sponsor's recoveryAddress.
The code comment at the decrement even states it drops totalBonus "keeping the accounting honest for any later re-snapshot" — it anticipates the re-snapshot but does not account for it under-funding the whitehat.
Likelihood:
Occurs when riskWindowStart == 0 (the pool never observed the active-risk window — realistic when the whitehat operated at the agreement level and never poked this third-party pool, or the registry reached CORRUPTED quickly).
Occurs when the moderator makes the NORMAL §4 correction — an initial SURVIVED judgement (breach looked out-of-scope) later corrected to good-faith CORRUPTED (determined in-scope). This is the exact use the correction window is designed for, seconds apart — no 180-day wait.
Occurs while the sponsor (or anyone — the sweep is permissionless) calls sweepUnclaimedBonus in the gap; the sponsor is economically incentivised (they own recoveryAddress).
Impact:
The moderator-named whitehat, who performed a legal Safe-Harbor rescue, loses their entire bonus — which can be the majority of the reward the sponsor put up to attract whitehats. It is captured by the sponsor's recoveryAddress.
The stated DESIGN §4 invariant ("finality is value-movement; claimsStarted latches") is violated: the whole bonus leaves the pool without latching, and a subsequent re-flag silently under-funds the bounty.
test/audit/RVS1.t.sol — the leak plus a control proving it is specific to riskWindowStart == 0:
Run: forge test --match-contract RVS1Test -vv
Latch finality in the branch that moves genuinely-reserved bonus (the dust-donation griefing case goes through the other branch, which still does not latch):
Alternatively, on a good-faith CORRUPTED re-flag, reserve the already-swept bonus rather than re-snapshotting the drained totalBonus.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.