sweepUnclaimedBonus() intentionally does not set claimsStarted, allowing the moderator's pre-claim re-flag window to remain open. However, it does decrement totalBonus when riskWindowStart == 0. If the moderator first flags SURVIVED (judging the breach out-of-scope), anyone can sweep the bonus to recoveryAddress, draining totalBonus to zero. When the moderator then re-flags to CORRUPTED (good-faith), the new snapshot captures totalBonus == 0, so bountyEntitlement excludes the bonus entirely. The whitehat attacker loses their entitled bonus portion.
The attack requires riskWindowStart == 0 (registry skipped active-risk states). Under this condition:
Moderator flags SURVIVED — permitted because CORRUPTED registry state is accepted for SURVIVED when the breach is out-of-pool-scope (DESIGN.md §8)
Anyone calls sweepUnclaimedBonus():
outcome == SURVIVED passes the gate (line 475)
riskWindowStart == 0 means bonus is not owed to stakers (line 499)
totalBonus -= amount drains bonus to zero (line 499)
claimsStarted is intentionally NOT set (line 503-504)
Moderator discovers error and re-flags CORRUPTED with goodFaith=true:
claimsStarted == false so re-flag is allowed (line 327)
snapshotTotalBonus = totalBonus = 0 (line 358) — bonus already gone
bountyEntitlement = snapshotTotalStaked + 0 — attacker loses bonus
The comment on line 503 explains the design rationale: setting claimsStarted would let a 1 wei donation block the moderator's re-flag window. But the current design allows real value (the entire bonus pool) to leave the contract during that same window, corrupting the re-flag snapshot.
Likelihood:
Requires riskWindowStart == 0 (registry skips active-risk states)
Requires moderator to flag SURVIVED then correct to CORRUPTED
Anyone can call sweepUnclaimedBonus between the two flags
Impact:
Whitehat attacker loses their entire bonus entitlement
In the PoC: 30 ONE out of 180 ONE total (16.7% loss)
Bonus portion scales with totalBonus — could be larger in production
Result: PASS — bountyEntitlement: 150 ONE (expected 180), lost_bonus: 30 ONE, attacker_received: 150 ONE
Snapshot totalBonus before decrementing in sweepUnclaimedBonus, or prevent sweep during the re-flag 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.