FoundrySolidityLayer 2
7.25 ETH
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

setPoolScope guard ordering blocks last-chance scope update

Description

_observePoolState() at Pool:638 runs before the scopeLocked guard at Pool:639. Since _observePoolState() has the side effect of setting scopeLocked = true when the registry leaves pre-attack staging (NOT_DEPLOYED/NEW_DEPLOYMENT), the observation inside setPoolScope() self-defeats the intended update.

Pool:636 function setPoolScope(accounts)
Pool:638 _observePoolState() // side effect: may set scopeLocked=true
Pool:639 if (scopeLocked) revert // catches the side effect, reverts
Pool:640 _replaceScope(accounts) // never reached

The lock trigger at Pool:787-792:

if (!scopeLocked && state != NOT_DEPLOYED && state != NEW_DEPLOYMENT) {
scopeLocked = true;
}

Risk

Likelihood: Medium. Any registry transition past pre-attack staging that the pool hasn't yet observed will cause the next setPoolScope() call to self-revert. This includes the common NEW_DEPLOYMENT → ATTACK_REQUESTED transition. A front-running pokeRiskWindow() by anyone can also trigger this.

Impact: Medium. The scope is permanently frozen at its old value. A stale scope causes the moderator to make SURVIVED vs CORRUPTED decisions against an outdated account list — directly affecting fund distribution. DESIGN.md §8 guarantees "the sponsor can update scope freely while the registry is in NOT_DEPLOYED / NEW_DEPLOYMENT" — the ordering bug breaks this guarantee.

Mitigation

Hoist the scopeLocked guard before _observePoolState():

function setPoolScope(address[] calldata accounts) external onlyOwner {
+ if (scopeLocked) revert ScopePostLockImmutable();
_observePoolState();
if (scopeLocked) revert ScopePostLockImmutable();
_replaceScope(accounts);
}

The early guard prevents unnecessary external calls when already locked. The post-observation guard still catches the case where the observation itself triggers the lock — this is correct behavior (scope should lock when the registry leaves staging).

Updates

Lead Judging Commences

inallhonesty Lead Judge
27 days ago
inallhonesty Lead Judge 22 days ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

Known Design #8

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!