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.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.