When the moderator re-flags a good-faith CORRUPTED outcome to correct a mistakenly-named attacker more than 180 days after the pool's first good-faith CORRUPTED flag, the corruptedClaimDeadline is recomputed from the original _firstGoodFaithCorruptedAt timestamp (which is never reset). The deadline is already expired, so the newly-named correct whitehat cannot claim the bounty. The full pool is swept to the sponsor's recoveryAddress — a permanent, irreversible loss of the entire bounty for the intended beneficiary.
Normal behavior: flagOutcome(CORRUPTED, true, attacker) names a whitehat attacker and starts a 180-day claim window via corruptedClaimDeadline. DESIGN.md §4 documents that re-flagging is explicitly supported to "fix a typo'd outcome/attacker before any participant locks in the wrong distribution." Re-flagging is gated only by claimsStarted == false.
The issue: _firstGoodFaithCorruptedAt is set exactly once — on the first-ever good-faith CORRUPTED flag — and is never reset for the lifetime of the pool (lines 363-372). On re-flag, corruptedClaimDeadline is always derived from this original anchor:
If >180 days have elapsed since the first flag, the re-computed deadline is in the past. The state machine allows the transition (claimsStarted is still false), the attacker field updates, OutcomeFlagged emits — but the liveness property is broken: the newly-named attacker cannot claim (ClaimWindowExpired), and anyone can sweep the pool to recoveryAddress via sweepUnclaimedCorrupted().
The gap: DESIGN.md §4 says re-flagging exists to "fix a typo'd attacker" (unqualified promise). The implementation silently fails at this purpose after 180 days. The code comment at L368-369 acknowledges the mechanism but DESIGN.md — the authoritative reference per the contest brief — does not document this limitation as a known issue or accepted tradeoff.
Likelihood: Low
Moderator must initially name the wrong attacker address (typo, identity dispute, unresponsive whitehat)
180 days must elapse before the correction is made
The correction window is generous, but real-world Safe Harbor agreements involve legal coordination, identity verification, and DAO governance delays that can extend beyond 180 days
No attacker action required; purely a function of moderator operational timeline
Impact: High
Complete, permanent, irreversible loss of the correctly-named whitehat's entire bounty entitlement (up to 100% of snapshotTotalStaked + snapshotTotalBonus)
Full pool diverted to the sponsor's recoveryAddress — a windfall to the sponsor at the whitehat's expense
The failure is silent: the re-flag transaction succeeds, emits OutcomeFlagged, and updates the attacker field, giving no on-chain signal that the correction is useless
Permissionless: once the re-flag lands with an expired deadline, any third party can immediately trigger sweepUnclaimedCorrupted() — no window for intervention
Run: forge test --match-contract PoC_CorruptedBountyDeadlineExpired -vvv
Result: [PASS] test_poc_corruptedClaimDeadline_expiredOnReflag() (gas: 619243)
Option 1 (preferred): Reset _firstGoodFaithCorruptedAt when the attacker address changes on re-flag, giving a fresh 180-day window to a newly-named identity while preserving the non-extendable deadline for same-attacker re-confirmations:
Option 2 (simpler, fail-loud): Revert the re-flag if the recomputed corruptedClaimDeadline would already be expired, forcing the moderator to use an alternate resolution path rather than silently committing a dead state:
Both options preserve the invariant that the deadline must never be extendable for the same attacker while ensuring the documented "fix a typo'd attacker" workflow actually works.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.