Describe the normal behavior in one or more sentences
When an agreement passes through an active-risk state (UNDER_ATTACK / PROMOTION_REQUESTED) during the pool's term, the pool is meant to record that risk by sealing riskWindowStart via _observePoolState(). Stakers who held their position through that risk window are then rewarded from the bonus pool through the k=2 time-weighted _bonusShare calculation on resolution.
Explain the specific issue or problem in one or more sentences
Sealing riskWindowStart is lazy: it only happens if some caller invokes a state-touching function (stake / withdraw / pokeRiskWindow) WHILE the registry is in an active-risk state. If a real active-risk window opens and closes between pool interactions (e.g. a short attack while pool activity is low), the first poke lands only after the registry already reached PRODUCTION. _observePoolState then seals riskWindowEnd but leaves riskWindowStart == 0, and pokeRiskWindow() does not revert because its guard only trips when BOTH markers are zero. On resolution _bonusShare returns 0 for every staker, and the full totalBonus sweeps to the sponsor-controlled recoveryAddress. Stakers carried real risk yet receive zero bonus.
Acknowledgement of DESIGN.md §5/§6: the design text discusses the general "no observable risk → bonus pays zero → sweeps to recovery" rule, and frames a missing seal as "nobody interacted with the pool for the entire interval." This report is narrower: the risk window was real and non-trivial, but shorter than the gap between pool interactions, so it closes before the FIRST poke lands — even with an attentive staker set. §6's stated mitigation ("any counterparty can pokeRiskWindow the instant the registry transitions") presumes a party actively watching the registry mempool in real time; for an ordinary staker set that assumption does not hold, and here its failure mode is a total bonus loss for honest stakers rather than the "~zero bias" §7 accepts for the T-anchoring residual. Submitted as Low so the sponsor can decide whether a proactive seal is warranted; if judged an accepted residual, it at least flags that the residual's worst case is 100% bonus forfeiture, not a bounded redistribution.
Likelihood:
Reason 1
Occurs whenever the registry's active-risk interval (UNDER_ATTACK -> PRODUCTION) is shorter than the gap between pool interactions, so no caller observes the pool during active risk. This is a plain timing property, not attacker-controlled — a fast attack or a period of low pool activity is enough.
Reason 2
Ordinary stakers are not watching the registry mempool in real time, so the "anyone can pokeRiskWindow at the transition" mitigation does not reliably fire in practice.
Impact:
Impact 1
Stakers who held risk for the full term receive zero bonus on resolution, losing 100% of the bonus they economically earned.
Impact 2
The entire totalBonus is redirected to the sponsor-controlled recoveryAddress instead of the stakers, i.e. a bonus-only transfer of value from stakers to the sponsor. No principal is lost, hence Low.
The test deploys the pool through the real
ConfidencePoolFactoryand uses aMutableAttackRegistrywhose state can be advanced. The staker deposits atNEW_DEPLOYMENT; a realUNDER_ATTACK → PRODUCTIONwindow then passes with no pool call in between;pokeRiskWindow()is called only afterwards. The test assertsriskWindowStart() == 0despite the risk, and thatclaimExpired()pays the staker principal only while the full bonus sweeps torecoveryAddress. Passes withforge test.
When a terminal state is first observed and no risk window was ever sealed, set riskWindowStart to a conservative lower bound (the observation block). This keeps the bonus flowing to stakers via the amount-weighted globalScore==0 fallback instead of sweeping it to recoveryAddress. Alternatively, explicitly document this "risk-window-shorter-than-poll-interval" case as an accepted residual so integrators can price it in.
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.