The sponsor can update expiry until the first successful stake sets expiryLocked. Deposits during UNDER_ATTACK are intentionally allowed, and that same staking call observes the active risk state and disables withdrawal through riskWindowStart.
A staker can inspect a pool, see a reasonable expiry, and submit the first stake. The sponsor can front-run that transaction with setExpiry(type(uint32).max) or another far future timestamp. The staker's transaction still succeeds, locks the new expiry, records riskWindowStart, and loses the withdrawal escape hatch.
The result is a practically indefinite lock of the first staker's principal unless the moderator resolves the pool or the unexpected new deadline finally arrives. A terminal registry state alone does not release funds: claimSurvived() requires the pool outcome to be set, and claimExpired() remains unavailable until the manipulated expiry.
The same root cause also lets the sponsor resurrect an expired but never-staked pool. setExpiry() only checks expiryLocked, the new minimum lead time, and the uint32 ceiling; it does not require the old expiry to still be in the future. That means a pool that looked expired and unusable can be made stakeable again before the first successful stake. This supports the first staker expiry mutation risk rather than creating a separate issue.
Likelihood:
The victim is the first successful staker in the pool, before expiryLocked is set.
The pool is already in UNDER_ATTACK, so the first stake records riskWindowStart and disables withdrawal.
Impact:
The victim's principal can be locked until an unexpectedly distant deadline, potentially near the uint32 timestamp ceiling, unless the moderator resolves the pool first.
The victim cannot recover through withdraw() because the same stake that locked the changed expiry also sealed the risk window.
test/unit/ConfidencePool.branches.t.sol:ConfidencePoolBranchesTest.testFirstActiveRiskStakeLocksCurrentExpiry
Make staking check the expiry the staker accepted, or block expiry changes after the agreement has reached active risk.
The sponsor should also be prevented from changing expiry after the registry is no longer in a safely withdrawable state.
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.