Affected: ConfidencePool.sol:649-658 · ConfidencePool.sol:530-555
pokeRiskWindow() remains callable after expiry. _markRiskWindowStart caps the value at expiry but still writes a non-zero latch. A stakeless caller can therefore seal riskWindowStart = expiry during a post-expiry UNDER_ATTACK interval; once the registry reaches CORRUPTED and the 180-day grace elapses without moderator resolution, claimExpired() selects auto-CORRUPTED instead of EXPIRED and every remaining staker's principal is diverted to recoveryAddress.
DESIGN.md §5 bounds the backstop: "cannot apply when no risk window was observed" during the term. §6 pre-accepts pokeRiskWindow only "during the active-risk interval the registry passes through" — pool activity is the alternative sealing path. Post-expiry, stake/withdraw/contributeBonus are closed, pokeRiskWindow is the only executable entrypoint, and no symmetric counter-actor exists — the acceptance in §6 does not extend here.
Likelihood: Narrow — requires post-expiry registry advance to CORRUPTED and 180-day moderator absence. Each step reachable via public entrypoints; moderator absence is exactly the backstop's stated scenario.
Impact: Pool-wide principal (and bonus) diverted to recoveryAddress. Control run confirms EXPIRED refund without the poke.
Actor: Fully permissionless, stakeless, unprivileged.
Reject the post-expiry poke; post-expiry, resolution goes exclusively through claimExpired.
Save as test/PoC_79919d88.t.sol and run forge test --match-contract PoC_79919d88 -vv.
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.