DESIGN.md §4 allows the moderator to re-flag a pool's outcome pre-claim to correct a typo'd flag (e.g. SURVIVED → CORRUPTED). DESIGN.md §12 promises the named whitehat "the entire pool is the named attacker's bounty" — bountyEntitlement = snapshotTotalStaked + snapshotTotalBonus.
When riskWindowStart == 0 (no pool interaction observed the registry during active-risk states), sweepUnclaimedBonus treats the entire snapshotTotalBonus as unowed by stakers and sweeps it to recoveryAddress (DESIGN.md §5: "no observable risk → bonus sweeps to recoveryAddress"). The sweep does not set claimsStarted (lines 503-505), so the moderator's re-flag window stays open. A subsequent re-flag to good-faith CORRUPTED re-snapshots snapshotTotalBonus from the now-depleted live totalBonus = 0 (line 358), setting bountyEntitlement = snapshotTotalStaked + 0. The whitehat receives only principal; the bonus is permanently gone to the sponsor's recoveryAddress.
Likelihood:
The sponsor (who controls recoveryAddress) has direct economic incentive to preserve riskWindowStart == 0: calling pokeRiskWindow() or any pool function during active-risk states would seal the window and forfeit the sweep path. No protocol-level keeper automatically calls it.
Whitehats audit the agreement's in-scope contracts, not the ConfidencePool clone. They have no reason to interact with the pool before being named attacker — and they can't know they'll be named until after the moderator validates their disclosure and flags CORRUPTED.
Stakers' default mode is passive: they deposit pre-attack and wait for resolution. No pool interaction is required during the active-risk interval, so "no staker poked for the entire UNDER_ATTACK period" is a plausible operating condition, not a pathological edge.
The moderator correction path is explicitly sanctioned by DESIGN.md §4 ("re-flag pre-claim so the moderator can fix a typo'd outcome"). A normal operational flow — moderator optimistically flags SURVIVED before a whitehat disclosure arrives, then corrects to CORRUPTED — is not a malicious moderator, just timing.
Impact:
The whitehat attacker's bounty is reduced from snapshotTotalStaked + snapshotTotalBonus to snapshotTotalStaked only, permanently losing the bonus pool to the sponsor's recoveryAddress. This violates the DESIGN.md §12 bounty promise: "the entire pool is the named attacker's bounty".
The sponsor captures the swept bonus directly via recoveryAddress, which they can redirect at any time via setRecoveryAddress (no state gate). This creates a direct economic incentive for the sponsor to preserve riskWindowStart == 0 and front-run the moderator's correction.
Run: forge test --match-test testM01BonusSweptBeforeCorruptedReflag -vvv
Always reserving snapshotTotalBonus for live stakers ensures the bonus cannot be swept before the re-flag window closes (it only opens when stakers exist). Donations/dust above the reserve remain sweepable. After claimsStarted (first genuine claim), the re-flag window closes and residual bonus becomes sweepable normally. No new DoS, reentrancy, or invariant violations — the sweep still works for donations above the reserve.
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.