The protocol intends to prevent stakers from entering immediately before a known successful resolution and earning bonus without bearing meaningful risk.
For this reason, deposits are blocked during PROMOTION_REQUESTED, the state preceding the normal transition to PRODUCTION:
The documented rationale is that PROMOTION_REQUESTED represents the closing portion of the risk window, so deposits are blocked to prevent a staker from entering immediately before survival becomes final.
However, the upstream Attack Registry contains an instantPromote() function that can transition an agreement directly from UNDER_ATTACK to PRODUCTION, entirely bypassing PROMOTION_REQUESTED.
The pinned upstream implementation explicitly permits instantPromote() from UNDER_ATTACK:
The normal promotion route first enters PROMOTION_REQUESTED and applies a three-day delay, but instantPromote() intentionally bypasses that process.
An unprivileged searcher can observe a pending instantPromote() transaction and place a stake() transaction immediately before it:
The pool contains a funded bonus.
The agreement is in UNDER_ATTACK.
The registry moderator submits instantPromote().
A searcher places stake() immediately before that transaction.
The stake succeeds because the pool still observes UNDER_ATTACK.
instantPromote() executes directly afterward and permanently sets the agreement to PRODUCTION.
The late staker's principal is now safe, since PRODUCTION is terminal.
The late staker can claim a bonus despite bearing effectively no corruption risk.
The issue is especially severe when the attacker becomes the only eligible staker. Bonus shares are relative rather than absolute, so a sole staker receives the entire bonus regardless of how little time they were exposed.
If the risk window opens and closes at the same timestamp, _bonusShare() deliberately falls back to an amount-weighted distribution:
For a sole last-block staker:
and therefore:
The result contradicts the purpose of blocking deposits during the normal closing window. The protection applies only when the registry uses PROMOTION_REQUESTED, but the trusted upstream state machine contains a separate direct survival transition that bypasses it. The relevant pool behavior and intended deposit gating are contained in the submitted repository. :contentReference[oaicite:2]{index=2}
A searcher or sequencer can extract the complete bonus pool while bearing little or no economic risk.
The attack does not require the searcher to control the pool, the agreement, or the registry moderator. It only requires transaction-ordering visibility around a legitimate instantPromote() operation.
Consequences include:
theft of up to 100% of the contributed bonus;
dilution of honest stakers if other stakes exist;
risk-free or near-risk-free reward extraction;
failure of the intended PROMOTION_REQUESTED late-entry protection;
an MEV opportunity around every emergency promotion from UNDER_ATTACK.
The attacker's principal is not exposed to a meaningful corruption interval because the known terminal PRODUCTION transition executes immediately after their deposit.
The impact is Medium because the full bonus can be extracted, although existing staker principal is not stolen.
The likelihood is Medium because exploitation requires an instantPromote() operation from UNDER_ATTACK and transaction ordering ahead of that operation.
Add the following test to a contract inheriting BaseConfidencePoolTest:
A second test can demonstrate dilution of existing stakers:
The protocol should not rely solely on PROMOTION_REQUESTED to provide a closing window, because the upstream registry allows a direct UNDER_ATTACK -> PRODUCTION transition.
The most robust fix is to require every survival transition to pass through a non-depositable delay state. At the registry level, instantPromote() should either:
enter PROMOTION_REQUESTED with an abbreviated but nonzero delay; or
expose an INSTANT_PROMOTION_REQUESTED state that closes pool deposits before finalization.
If the upstream registry cannot be changed, the pool should impose a minimum bonus-eligibility duration.
For example, store each deposit's block number or timestamp and exclude deposits that have not matured before the terminal transition:
A stronger version should apply the minimum duration per deposit rather than per user, preserving the existing per-deposit weighting semantics.
The zero-score fallback should also not reward a newly entered staker when the measured risk duration is zero. Instead, distinguish between:
longstanding stake for which the window could not produce a time spread; and
stake entered in the same block as the terminal transition.
At minimum, deposits made in the terminal-transition block should receive no bonus:
The mitigation must cover every direct transition to PRODUCTION, not only the normal PROMOTION_REQUESTED route.
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.