Stakers commit capital for an agreement's full term and are rewarded from the bonus pool when it survives (the README states stakers are "rewarded if the agreement survives"). In the DESIGN.md doc, point 5 gates that reward on riskWindowStart != 0, and point 9 defends the "no window → no bonus" rule on the premise that stakers could seal the window during an active-risk interval.
On this path that premise is false: an agreement reaches terminal PRODUCTION (survived) without any active-risk state, so riskWindowStart stays 0 and pokeRiskWindow() reverts RiskWindowNotReached throughout ATTACK_REQUESTED — the window can never be sealed. _bonusShare then returns 0 for every staker and sweepUnclaimedBonus sends 100% of the bonus to the sponsor's recoveryAddress. A surviving agreement, underwritten for its full term, pays its stakers nothing — contradicting both the protocol's stated survival-reward purpose and the justification given in point 9 of the DESIGN.md doc.
Likelihood:
Occurs whenever an agreement reaches `PRODUCTION` via the registry's deadline auto-promotion: an agreement with `attackRequested && !attackApproved` returns `PRODUCTION` once `block.timestamp >= deadlineTimestamp` (`AttackRegistry._getAgreementState`), purely time-based, requiring only that the DAO does not activate the requested attack before its deadline — an ordinary, non-adversarial lifecycle event, not a trusted-actor attack.
Occurs on every such promotion regardless of staker behavior: `pokeRiskWindow()` reverts throughout `ATTACK_REQUESTED`, so stakers have no action available to seal the window and avoid the outcome.
Occurs on a genuine survival: the agreement reaches the terminal survived state, so the bonus that exists to reward survival is owed by the protocol's stated design, yet paid to no one who earned it.
Impact:
The full bonus pool is routed to the sponsor's recoveryAddress instead of the stakers, on the exact "survived" outcome the bonus is meant to reward — a mismatch between the implementation and the protocol's stated "rewarded if they survive" purpose, on a path DESIGN.md poinr 9's fairness rationale does not actually cover.
Stakers who committed capital for the agreement's full term receive zero reward. Principal is not at risk (`sweepUnclaimedBonus` reserves `totalEligibleStake`), which bounds this to reward misallocation rather than fund loss.
Save as test/unit/ZZBonusStrand.t.sol (depends only on the shipped test/helpers/BaseConfidencePoolTest.sol) and run forge test --match-path 'test/unit/ZZBonusStrand.t.sol' -vv → passes.
The riskWindowStart == 0 branch currently pays every staker zero and sweeps the full bonus to the sponsor. Routing a survived/expired outcome into the contract's existing amount-weighted fallback (the globalScore == 0 branch already present in _bonusShare) instead pays the bonus to the stakers who underwrote the surviving agreement, resolving the spec-vs-implementation inconsistency. Alternatively, if the zero-bonus-on-no-window behavior is intended, update the protocol's "rewarded if they survive" description to document the carve-out.
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.