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.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.