After the Pool observes a terminal Registry state, a legitimate migration, recovery, or configuration change may make the same agreement report active risk again. The Pool can then write riskWindowStart later than the existing riskWindowEnd and accept new stake. Settlement against the old terminal timestamp gives the post-terminal entrant a positive k=2 bonus weight, allowing a large late stake to dilute existing stakers' bonus.
This is Low severity. Incorrect bonus redistribution is Medium impact, but the path requires a Registry migration or recovery that fails to preserve terminal history, making likelihood Low. Once that condition exists, any address can exploit it by staking without Registry administrative rights.
Normally, riskWindowStart must not be later than riskWindowEnd, and only stake that bore risk during that interval should participate in bonus allocation. The Pool reads getAttackRegistry() live and intentionally does not cache the attack-registry pointer in order to support Registry migration.
_observePoolState() records the start and end with separate zero-value checks. Each field can only be written once, but the code does not enforce that the start precedes the end. If the Pool first observes PRODUCTION or CORRUPTED, then a migrated Registry reports UNDER_ATTACK or PROMOTION_REQUESTED, the Pool creates an inverted time axis.
For example, Alice stakes 100 and the Pool has 100 bonus. At t1, the Pool observes PRODUCTION from the old Registry and sets riskWindowEnd = t1. At t2 > t1, a migrated Registry reports UNDER_ATTACK; Bob stakes 10,000, causing riskWindowStart = t2. When the replacement Registry reports PRODUCTION and the moderator flags SURVIVED, outcomeFlaggedAt remains t1. The k=2 formula squares (t1 - t2), cannot distinguish the negative time difference, and awards Bob about 10,000 / 10,100 of the bonus even though he entered after the Pool observed terminal state.
DESIGN.md treats the Registry pointer as a trusted dependency, but it also states that pointer caching is avoided to support legitimate migration and that a Registry rewind must not reopen withdrawals. The existing one-way latch prevents reopening withdrawal only; it does not seal the bonus timeline or prohibit later deposits. This report therefore does not assume a malicious owner forges Registry data. It identifies missing state-continuity protection in the supported migration model.
Likelihood:
The Pool records a terminal riskWindowEnd before outcome finalization.
A Registry migration, state recovery, or pointer update fails to preserve the agreement's terminal history and reports active risk.
Any external address calls stake() during that reading; no moderator authorization, signature, or non-standard token is required.
Impact:
riskWindowStart > riskWindowEnd breaks the risk-timeline invariant and makes post-terminal stake bonus eligible.
An attacker can use a large stake to capture nearly all bonus and dilute existing stakers. Principal remains returnable on the SURVIVED path.
Treat a terminal state already observed by the Pool as a local one-way latch rather than relying exclusively on later live Registry reads.
The Registry migration layer should also guarantee continuity of terminal state for each agreement, and the Pool should test the invariant riskWindowStart <= riskWindowEnd whenever both values are nonzero.
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.