The pool owner may modify the covered accounts only during NOT_DEPLOYED or NEW_DEPLOYMENT. Observing any later registry state must set scopeLocked permanently, protecting the coverage commitment made to stakers.
During ATTACK_REQUESTED, _observePoolState() sets scopeLocked = true. However, this state does not set riskWindowStart or riskWindowEnd, causing pokeRiskWindow() to revert and roll back the scope lock. When the registry subsequently rejects the attack request and returns to NOT_DEPLOYED, the owner can replace the pool scope.
Likelihood:
This occurs when the registry reaches ATTACK_REQUESTED, no successful stake, withdrawal, or bonus contribution persists the scope lock, and a caller uses pokeRiskWindow().
The exploitable window appears when the registry moderator subsequently rejects the attack request, returning the agreement to NOT_DEPLOYED, after which the pool owner replaces the scope.
Impact:
Existing stakers lose the permanent scope commitment they expected once the agreement passed pre-attack staging.
The owner can broaden or narrow coverage, potentially changing a future breach from SURVIVED to CORRUPTED or vice versa. This can change the destination of the entire pool’s principal and bonus.
Add the following test to ConfidencePool.scope.t.sol:
Treat persisting the scope lock as a successful observation, even when neither risk-window timestamp was created:
This allows an ATTACK_REQUESTED observation to complete and permanently store scopeLocked = true, while calls during NOT_DEPLOYED and NEW_DEPLOYMENT continue reverting as before.
Impact - Low Nothing moves when the scope is swapped, and the state afterward is pre-attack, so any staker who notices can withdraw in full. _replaceScope emits ScopeUpdated, which puts the change on-chain where it can be seen. Real loss needs a restarted attack cycle that breaches one of the substituted accounts with the original staker still in the pool, at which point their principal funds a CORRUPTED payout for coverage they never chose. Likelihood - Medium The step the sponsor cannot force is the moderator rejecting the attack request, though rejections are an ordinary registry operation. The rest they can arrange. Neither observation path can seal the lock in this state, and pausing the pool shuts the deposit routes, leaving only a full-exit withdraw to do it. So reaching the mutable-scope condition is not hard; what holds the severity down is how much has to go wrong afterward for anyone to actually lose money.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.