The protocol is designed to reward stakers based on how long their capital was exposed during the risk window. In normal operation, early stakers should earn most of the bonus, while very late UNDER_ATTACK deposits should earn little to none.
However, the contract still allows staking after riskWindowStart has already been sealed. If the pool is then resolved in the same timestamp, _bonusShare() computes globalScore == 0 and falls back to pure amount-weighted distribution.
At that point, the bonus is no longer based on risk exposure. It is split only by stake size.
This means a whale can wait until the pool is already UNDER_ATTACK, deposit a very large amount, and then capture nearly the full sponsor bonus if resolution happens in the same timestamp.
Root + Impact
The issue comes from the interaction between:
stake(), which still allows deposits during UNDER_ATTACK
_markRiskWindowStart(), which normalizes existing stake to the current timestamp
_bonusShare(), which falls back to amount-weighted payout when globalScore == 0
Likelihood:
The pool explicitly allows deposits while the registry is UNDER_ATTACK, so no special privilege is required.
The moderator can resolve immediately after the attacker joins, creating the same-timestamp condition needed for the fallback path.
Impact:
A late whale can extract almost all of the sponsor-funded bonus with effectively zero observed at-risk time.
Honest early stakers, who actually bore the intended risk, can be diluted to a negligible share of the reward.
PoC Walkthrough
Alice deposits before any risk exists.
The pool enters UNDER_ATTACK, which seals riskWindowStart.
The attacker then deposits a much larger amount after the risk window has already opened.
The moderator resolves in the same timestamp.
Because no measurable time elapsed between riskWindowStart and riskWindowEnd, the quadratic weighting collapses and globalScore == 0.
The contract falls back to amount-weighted payout using snapshotTotalStaked.
Since the attacker is now the overwhelming majority of total stake, they receive almost the full bonus despite not meaningfully bearing risk.
Prevent post-risk deposits from participating in the globalScore == 0 fallback.
The simplest fix is to stop allowing deposits once riskWindowStart != 0.
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.