The moderator may re-flag a pool's outcome before the first claim, so an incorrect resolution can be corrected before any value is distributed. The protocol states the guarantee that makes this safe: "Once value has left the contract, a corrective re-flag cannot be honored" and "Finality is correctly tied to value movement" (docs/DESIGN.md §4). Under a good-faith CORRUPTED outcome, the entire pool is owed to the named whitehat.
The guarantee does not hold. sweepUnclaimedBonus is permissionless and transfers the accounted bonus out of the pool to recoveryAddress, yet it is the one value-moving path that never sets the claimsStarted finality latch. The correction window therefore remains open after the bonus has left the contract. When the moderator then corrects SURVIVED → good-faith CORRUPTED, flagOutcome re-snapshots a totalBonus the sweep has already drained, so the whitehat's bounty is computed against an emptied pool while the bonus sits permanently at recoveryAddress.
This defect is independent of whether the risk window was observed — it is purely a missing finality latch on a value-moving function.
Likelihood:
The moderator uses the documented correction path — flags SURVIVED on a CORRUPTED registry (an initial "breach was out of this pool's scope" judgement), then corrects to good-faith CORRUPTED once the in-scope breach is confirmed — and any account calls the public sweepUnclaimedBonus in the interval between the two flags.
The bonus is sweepable during a SURVIVED resolution whenever totalEligibleStake == 0 (stakers have exited during the pre-attack window, which the protocol permits), so the sweep succeeds even when the risk window was fully observed on-chain.
Impact:
The named whitehat's good-faith CORRUPTED bounty is short by the entire bonus; where the pool holds only the bonus, the corrected bounty is 0 and the whitehat receives nothing.
The bonus is captured by the sponsor-controlled recoveryAddress instead of paying the whitehat, and a documented spec guarantee — the moderator's correction window, and "finality tied to value movement" — is silently void for any funds a permissionless sweep has already moved.
Save as test/ReflagBonusDiversion.t.sol and run forge test --match-test test_reflag_bonus_diverted_observedWindow -vvv. It reuses the repo's BaseConfidencePoolTest harness and passes. Note the risk window is positively observed (riskWindowStart != 0), isolating this from any observation-related issue — the loss is caused solely by the sweep moving value without latching finality.
Treat a sweep of accounted bonus as the distribution-locking event it is, latching finality exactly as a claim does. The dust-donation protection is preserved: a sweep of donated excess does not enter the totalBonus-reducing branch and so still does not latch.
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.