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