Normal behavior: createPool should only allow pools for accounts genuinely covered by the given Safe Harbor agreement — the accounts' actual AttackRegistry binding should match agreement.
Specific issue: createPool validates only agreement provenance (isAgreementValid) and caller ownership (owner() == msg.sender) — it never checks that each account is bound to agreement in the AttackRegistry. Because the caller is the agreement's own owner, and scope is self-reported by the agreement contract, an attacker can create a throwaway agreement, list any accounts as "in scope," and spin up a factory-listed ConfidencePool that resolves against their own agreement's state instead of the accounts' real binding agreement.
Likelihood:
The factory never imports or calls IAttackRegistry, so no code path in createPool could catch this regardless of caller behavior.
Creating an agreement via AgreementFactory and calling owner() on your own contract is permissionless and zero-cost — not a rare precondition.
BattleChain's DAO review (approveAttack) only gates an agreement's own transition into UNDER_ATTACK; it never gates createPool, which requires no particular registry state. A throwaway agreement can sit in NOT_DEPLOYED forever, never reviewed by the DAO, while still backing a live pool.
Impact:
Stakers and bonus contributors treat "factory-created" as a legitimacy signal; a pool resolving against the wrong agreement's state silently breaks that assumption.
Pool resolution (SURVIVED/CORRUPTED/EXPIRED) decouples from the named accounts' real security status, since _getAgreementState reads the attacker's throwaway agreement — misrouting pre-funded bonus and staked principal.
The test below shows an attacker creating their own agreement, self-listing a real, unrelated protocol contract as "in scope," and successfully spinning up a factory-listed pool around it — despite the registry confirming that contract is not actually bound to the attacker's agreement.
Add a binding check against the AttackRegistry alongside the existing scope check, so a pool can only be created when each account's true bound agreement matches the one being used. This costs one external call per scoped account and rejects pool creation before any clone is deployed.
BattleChain's DAO approval process (approveAttack) only gates an agreement's own transition into UNDER_ATTACK — it screens for mainnet-copycat bytecode and confirms deployment origin via getContractDeployer. It does not gate ConfidencePoolFactory.createPool, which never requires any particular registry state. An attacker's throwaway agreement can remain in NOT_DEPLOYED indefinitely — never submitted for DAO review at all — while still backing a live, factory-listed ConfidencePool. The DAO checklist is therefore not a mitigating control for this finding.
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.