ConfidencePool.stake() sets the one-way expiryLocked latch on the first deposit, after which
setExpiry() reverts ExpiryLocked. This is the mechanism designed to protect
reliance on the deadline: "once anyone has deposited against a given deadline … the sponsor cannot
move it."
ConfidencePool.contributeBonus() commits value into totalBonus but never sets expiryLocked.
A bonus contribution is an irrevocable deposit and there is no bonus-withdrawal function anywhere in
the contract, yet it leaves the latch open.
As a result, when a bonus is contributed before the first stake, the sponsor can still call
setExpiry(type(uint32).max - 1) and push the deadline decades into the future, after the
contributor's capital is already committed. Unlike a staker, a bonus contributor has no withdraw
escape hatch, so the design stipulation "exit until risk materializes" defense that neutralizes every other
pre-attack sponsor lever does not apply to them; the committed bonus cannot be reclaimed.
This issue is limited to the pre-stake window (expiryLocked == false). Once any stake is placed
the latch closes and the deadline is fixed for the bonus contributor as well.
Likelihood
The condition is reached whenever a bonus is contributed while expiryLocked is still false and the sponsor then calls setExpiry.
No special registry state is required; the sponsor may additionally pause() to guarantee no
staker ever stakes and closes the latch.
The sponsor is the agreement owner, so the lever is always available to them at zero cost.
Impact
The bonus contributor's committed capital is locked far past the deadline it was contributed
against — up to the uint32 ceiling (~year 2106) — with no reclaim path: there is no bonus
withdrawal, and claimExpired reverts PoolNotExpired until the new far expiry.
The harm is a liveness / time-value griefing of a participant who by design has no exit; the
capital is effectively dead for the extension period.
A bonus contributed to a
pool that attracts no stakers already sweeps to recoveryAddress under normal operation, so the
sponsor gains nothing beyond delay.
ttestPoC_ContributeBonus_DoesNotLockExpiry_SponsorMovesDeadlineAfterCommit demonstrates the asymmetry . The core assertion:
Run with:
Set the latch on any value-committing deposit, mirroring stake():
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.