ConfidencePoolFactory.createPool() is intended to deploy and initialize a new EIP-1167
ConfidencePool clone for each valid agreement. It derives a per-agreement salt, deploys the
clone, initializes it, and registers the pool.
BattleChain uses native zkSync EraVM semantics. The factory relies on OpenZeppelin's
Clones.cloneDeterministic, which builds minimal-proxy creation bytecode in memory and deploys it
through raw assembly CREATE2. Native EraVM does not support deploying arbitrary dynamically
assembled bytecode through this EVM-style deployment path; zkSync requires compiler-known bytecode
hashes and its ContractDeployer mechanism.
As a result, every createPool() call reverts at clone deployment with
Errors.FailedDeployment(). No pool can be created, initialized, or registered.
The affected OpenZeppelin implementation executes:
The mstore calls are not the issue: they correctly construct and initialize the required
55-byte byte range. The failure is native EraVM's inability to deploy that dynamically assembled
minimal-proxy bytecode through raw assembly CREATE2.
Likelihood:
Every valid pool-creation request reaches Clones.cloneDeterministic after passing factory
validation.
zkSync Foundry compiling the actual factory emits an EraVM warning on OpenZeppelin's raw
create2 instruction.
A native zkSync execution reproduces the revert deterministically.
Impact:
Agreement owners cannot create new pools.
No clone can be initialized or recorded in _poolsByAgreement.
The protocol's primary pool-creation lifecycle is unavailable on its intended chain.
The deterministic PoC is test/fresh/ZkSyncCreate2PoC.t.sol. It deploys the real
ConfidencePool implementation, ConfidencePoolFactory behind its real ERC1967Proxy, and the
required token, registry, and agreement mocks. It then invokes a valid createPool() call and
asserts the native EraVM failure:
Run with native zkSync Foundry:
Observed result:
For comparison, the ordinary EVM factory test succeeds:
Replace EIP-1167 raw assembly clone deployment with a zkSync-native-compatible deployment flow.
Deploy a concrete pool using Solidity's native deployment syntax:
Use constructor-based immutable configuration or a zkSync-compatible initialization design.
Use zkSync's ContractDeployer system contract or supported deployment library with
compiler-known factoryDeps.
Alternatively, explicitly deploy the protocol as EVM bytecode through zkSync's EVM Bytecode
Interpreter, then add deployment tests proving createPool() succeeds, the clone has code,
initialization succeeds, and delegated pool calls execute correctly.
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.