Pool scope operations involving the desynced account are permanently blocked with no recovery path. The root cause lies in the Agreement contract, but the pool is the victim — it correctly validates against a corrupted data source.
_replaceScope validates every new pool scope account against IAgreement.isContractInScope. If the agreement reports an account as in-scope, the pool accepts it. The agreement's internal cache and array are supposed to stay in sync.
The BattleChain Agreement.addAccounts has a documented duplicate-address footgun: _addToBattleChainScope dedupes via a cache mapping, but s_accounts stores all copies. After removeAccounts, the cache entry is cleared but a duplicate survives in s_accounts. isContractInScope (which reads the cache) returns false while the account logically belongs. Any _replaceScope call including this desynced account reverts with AccountNotInAgreementScope, permanently blocking pool scope operations.
Likelihood:
Impact:
Runnable Proof of Concept
Forge output:
Root cause must be fixed in Agreement.addAccounts by deduplicating s_accounts at add time. Pool-side mitigation is limited — the pool correctly validates against the agreement.
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.