Normal behavior:
When the registry is CORRUPTED and the breach is in-scope, the moderator flags flagOutcome(CORRUPTED, true, attackerAddress). The named whitehat's bountyEntitlement is set to snapshotTotalStaked + snapshotTotalBonus — the full pool — as intended by docs/DESIGN.md §12. The moderator may correct an erroneous flag before any claim is made, since claimsStarted is only set on the first actual claim.
The issue:
sweepUnclaimedBonus() is callable by anyone at any time after a SURVIVED or EXPIRED outcome is flagged, and it intentionally does not set claimsStarted (by design, to preserve the moderator's re-flag window). When riskWindowStart == 0 (no active-risk interaction was ever observed), there is no bonus reservation — the full totalBonus is freeBalance and immediately sweepable to recoveryAddress.
This creates a griefing window: a moderator who mis-flags SURVIVED (e.g., initially believing the breach was out-of-scope) can have the entire bonus pool swept to recoveryAddress before they re-flag. When they subsequently re-flag CORRUPTED (good-faith), snapshotTotalBonus re-snapshots from totalBonus, which is now 0 after the sweep. The named whitehat's bountyEntitlement is permanently reduced to principal-only, even though the bonus was legitimately theirs.
Likelihood:
The moderator makes an error and initially flags SURVIVED on a CORRUPTED registry (e.g., they first believe the breach is out-of-scope, then learn it is in-scope)
A monitoring bot or griefer observes the SURVIVED flag on-chain and calls sweepUnclaimedBonus() in the same or next block before the moderator can correct
Impact:
The named whitehat attacker permanently loses the bonus portion of their bounty — they receive snapshotTotalStaked only instead of snapshotTotalStaked + snapshotTotalBonus
The swept bonus goes to recoveryAddress (the sponsor's address), not to the griefer — so the sponsor benefits from the moderator's error at the whitehat's expense
No loss of principal; stakers are unaffected
Run with:
Expected output: [PASS] test_L01_grieferReducesWhitehatBounty()
The core tension is that sweepUnclaimedBonus must not set claimsStarted (to preserve the re-flag window), but also must not drain totalBonus while a re-flag could still name a whitehat. Two options:
Option A — Gate the bonus sweep on claimsStarted:
When riskWindowStart == 0, allow sweeping only principal-excess (donations), but protect the snapshot bonus until the re-flag window closes.
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.