The _replaceScope() function iterates over the accounts array and makes an external call to IAgreement(agreement).isContractInScope(account) for every element. The only validation on the array is that it is non-empty. There is no upper bound on its length. A sufficiently large scope array consumes enough gas to approach or exceed the block gas limit, causing the transaction to revert. If this occurs during initialize(), the clone contract is already deployed by the factory before initialize is called, so the gas spent on deployment is wasted. If it occurs during setPoolScope(), the function becomes permanently uncallable with any scope — the owner is locked out of scope updates even with a small valid scope, because the function is still callable but the scope-lock gate (scopeLocked) is independent of the gas issue.
Likelihood: Low
Requires the pool owner to pass a maliciously large accounts array — the owner is a trusted role
The owner pays their own gas, so self-griefing is irrational
The primary concern is accidental: a sponsor with hundreds of BattleChain accounts in their agreement could legitimately exceed practical gas limits when initializing the pool
Impact: Low
During initialize(): the clone deployment gas is wasted because the factory deploys the clone (line 87 of ConfidencePoolFactory.sol) before calling initialize
During setPoolScope(): the function reverts after consuming gas, but scope changes are retryable with a smaller array (as long as scopeLocked is false)
No funds are at risk — this is a gas-wasting / liveness concern
File: L14-ScopeNoMaxLength.poc.t.sol
Run with:
Add a MAX_SCOPE_SIZE constant (e.g. 100 accounts) and validate the array length against it in _replaceScope(). This bounds the per-iteration gas cost to a predictable ceiling and prevents both accidental and malicious gas exhaustion. The value of 100 is chosen to comfortably fit within any EVM-compatible L2 block gas limit even with the external isContractInScope call per account, while exceeding any realistic BattleChain agreement scope size. The check is also added to ConfidencePoolFactory.createPool() so that invalid scope sizes are caught before the clone is deployed, saving the caller from wasted deployment gas.
Also add the check in ConfidencePoolFactory.createPool() before deploying the clone:
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.