The moderator re-flag a pool's outcome until the first value-moving claim latches claimsStarted; the design ties this finality to value movement, so a correction (e.g. SURVIVED → good-faith CORRUPTED) is honored only while no funds have left the pool. Every value-moving entrypoint (claimSurvived, claimCorrupted, claimAttackerBounty, sweepUnclaimedCorrupted, claimExpired) sets claimsStarted = true.
sweepUnclaimedBonus is the sole exception: when riskWindowStart == 0 it transfers the entire accounted bonus (snapshotTotalBonus) to recoveryAddress and decrements totalBonus, but deliberately leaves claimsStarted == false. A subsequent, still-permitted correction to good-faith CORRUPTED then recomputes bountyEntitlement against the now-depleted totalBonus, so the named whitehat is paid the whole pool minus the already-swept bonus. (The entitlement recomputation itself is intentional — it prevents a MustClaimBountyFirst brick — so the root cause is the window staying open across the sweep, not the arithmetic.)
Likelihood:
Occurs when the registry reads CORRUPTED with no active-risk state ever observed by the pool (riskWindowStart == 0), the moderator's first flag is SURVIVED (an out-of-scope judgment that is later revised), and a sweepUnclaimedBonus call lands before the correction.
The sweep is permissionless and its beneficiary is the sponsor-controlled recoveryAddress, giving the sponsor a direct incentive to call it the moment SURVIVED is flagged; a single on-chain transaction reliably precedes a slow off-chain forensic correction.
Impact:
The named whitehat receives the pool principal only, short by the full swept bonus; the difference is permanently stranded at recoveryAddress and unrecoverable through the pool.
The loss is bounded only by snapshotTotalBonus, which is unbounded — the sponsor's own bonus contributions can be arbitrarily large.
Add the test code below to test/unit/SweepBonusReflagPoC.t.sol and run forge test --match-path "SweepBonusReflag" - Two runs, identical inputs (100 stake, 50 bonus, registry CORRUPTED, riskWindowStart == 0); the only difference is a single sweep between the flag and the correction. Both pass against the repo's mocks.
Close the re-flag window whenever the sweep moves accounted bonus (the riskWindowStart == 0 / no-stakers branch that decrements totalBonus), while leaving the donation-only path open so a 1-wei donation cannot grief the window:
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.