A good-faith CORRUPTED outcome must award the entire pool (principal + bonus) to the named whitehat (DESIGN.md §12). A permissionless sweepUnclaimedBonus() run while the outcome is still mutable (before any claim) permanently removes the bonus, so a later good-faith CORRUPTED re-flag awards the whitehat only the principal — the bonus is misrouted to recoveryAddress.
sweepUnclaimedBonus() (ConfidencePool.sol:474) requires only outcome ∈ {SURVIVED, EXPIRED} and, by design, does not latch claimsStarted (:503-506, to protect the re-flag window from a 1-wei donation griefer). On a SURVIVED outcome with riskWindowStart == 0 it reserves only totalEligibleStake (:483-488), sweeps the whole bonus to recoveryAddress, and permanently sets totalBonus = 0 (:499-501).
Because claimsStarted stays false, the moderator can still re-flag SURVIVED → good-faith CORRUPTED (:327, allowed pre-claim; SURVIVED is valid on a CORRUPTED registry per DESIGN.md §8). flagOutcome re-snapshots snapshotTotalBonus = totalBonus = 0 (:358), so bountyEntitlement = snapshotTotalStaked + 0 (:362) — the whitehat loses the entire bonus.
This violates §12 (entire-pool bounty) and §4's own rule ("once value has left the contract, a corrective re-flag cannot be honored without breaking balance accounting"): the bonus leaves via the sweep, yet the re-flag is still honored and breaks the distribution. Impact: a legitimate good-faith whitehat is shorted the entire bonus (misrouted to recoveryAddress); value is conserved (no insolvency) → Medium.
Likelihood: Medium — all preconditions are documented as normal: riskWindowStart == 0 (nobody poked during active-risk, §5); the moderator uses the supported SURVIVED → good-faith CORRUPTED correction (§4); any EOA calls sweepUnclaimedBonus() in between (front-runnable the instant SURVIVED is flagged).
Impact: Medium — the good-faith whitehat is deprived of the entire bonus B; no insolvency.
test/unit/PoCBonusStrip.t.sol (reuses BaseConfidencePoolTest), run forge test --match-contract PoCBonusStrip: both pass — clean path bountyEntitlement == P+B (250e18); sweep+reflag path == P (200e18), whitehat receives only P, bonus B (50e18) stranded at recoveryAddress.
When sweepUnclaimedBonus removes bonus from totalBonus (the riskWindowStart == 0 / no-stakers branch), latch a finality flag (claimsStarted = true, or a dedicated bonusSwept) so a later good-faith CORRUPTED re-flag cannot re-snapshot a depleted pool. The 1-wei-griefer concern does not apply to this branch (it only fires when genuinely-unowed bonus leaves). Alternatively: block the sweep while the outcome is mutable, or derive the good-faith CORRUPTED bountyEntitlement from the pre-sweep balance.
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.