Description
ConfidencePool distributes bonus rewards using a k=2 time-weighted formula that gives
early stakers a disproportionately larger share than late entrants. The formula relies
on riskWindowStart as the floor timestamp for every staker's effective entry time.
The specific issue: contributeBonus() calls _observePoolState() as a side effect,
which seals riskWindowStart = block.timestamp on the first call during UNDER_ATTACK
state. Any address can call contributeBonus(1 wei) to seal this one-way latch at a
delayed timestamp — retroactively clamping all pre-risk stakers to that late time and
destroying their time-weighted advantage.
Root Cause
Note: DESIGN.md §7 acknowledges a timing residual and calls it an
"accepted contested public race." However, contributeBonus(1 wei)
is NOT a race — it is a zero-cost, uncontested action:
pokeRiskWindow() has no economic reward for honest callers
The attacker loses nothing if the pool resolves CORRUPTED (1 wei donated)
There is no counterparty with incentive to front-run a 1-wei contribution
The "race collapses to ~zero bias" assumption requires an economically
incentivized observer that does not exist in this vector
Risk
Likelihood:
The registry transitions to UNDER_ATTACK without any guaranteed on-chain notification
pokeRiskWindow() has zero economic incentive for honest callers
The attacker needs only 1 wei and monitoring of the registry state
MEV bots can automate this by watching for UNDER_ATTACK transitions in the mempool
Impact:
Early stakers lose up to 69% of their fair bonus share
In a $100K bonus pool: honest staker loses ~$69,000 from a 1-wei attack
The attacker has zero capital at risk (1 wei is the total cost)
DESIGN.md §3 guarantee ("late deposits crushed to ~zero") is violated
Proof of Concept
Run with: forge test --match-test test_OneWei_SealsRiskWindow -vvv
Attack steps:
Alice stakes 100 ether at t=0 (pre-risk, genuine early staker)
Registry enters UNDER_ATTACK at t=1000 — nobody calls pokeRiskWindow()
Mallory calls contributeBonus(1 wei) at t=5000
riskWindowStart sealed at 5000 instead of 1000 (true attack time)
Alice's bonus drops from 764 tokens (fair) to 500 tokens (manipulated)
Alice loses 264 tokens (34.5%) from a 1-wei attack with zero capital at risk
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.