The permissionless claimExpired() function fails to auto-resolve a pool to CORRUPTED if the upstream agreement registry transitions directly to CORRUPTED without ever entering an active-risk state (UNDER_ATTACK or PROMOTION_REQUESTED), leaving riskWindowStart == 0. Consequently, stakers can invoke claimExpired() post-expiry to lock the outcome as EXPIRED and receive a full refund, permanently preventing the moderator from flagging CORRUPTED to sweep the funds to the recovery address
Under normal operation, if an agreement is corrupted, pool stakers are supposed to lose their capital, which is swept to the recoveryAddress or used to pay attacker bounties. However, if the registry skips active-risk states (moving straight from NEW_DEPLOYMENT to CORRUPTED), the pool clone's local riskWindowStart variable remains 0. When a staker invokes claimExpired(), the contract checks state == CORRUPTED && riskWindowStart != 0. Since riskWindowStart is 0, this check fails, causing the pool to resolve to EXPIRED and lock claimsStarted = true. This permanently disables the moderator's authority to override the outcome to CORRUPTED.
Likelihood:
Active-Risk Staging Skip: The upstream registry transitions directly to CORRUPTED without ever entering/observing the UNDER_ATTACK or PROMOTION_REQUESTED states.
Moderator Delay: The moderator fails to flag CORRUPTED before the pool expires and the first staker calls claimExpired().
Impact:
Lockout of Correct Outcome: The pool is resolved as EXPIRED, permanently locking claimsStarted = true.
Bypassed Sweep Penalty: Stakers withdraw their full principal plus any bonus shares, evading the penalty sweep to the recovery address meant to settle the
The test below stakes tokens for Alice, transitions the registry state directly to CORRUPTED, warps past expiry, and executes claimExpired(). Alice's call succeeds in resolving the pool to EXPIRED instead of CORRUPTED because riskWindowStart is 0, permanently blocking the moderator's override.
If the registry is CORRUPTED at expiry, the pool must not default to EXPIRED even if the risk window was never observed locally. Allow the moderator's offline judgment to remain the sole authority by omitting the riskWindowStart != 0 constraint on the auto-CORRUPTED check, or wait until the grace window has elapsed.
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.