EIP-4337 account factories: CREATE2, initCode, and counterfactual addresses

EIP-4337 factories: initCode, CREATE2, counterfactual addresses. First UserOperation deploys and cross-chain registry hygiene. Practical notes for IBEx.

3 min read

Who this is for

  • Wallet platform engineers
  • DevOps for multichain apps
  • Smart contract developers

Pros / cons

ProsCons
  • Users receive addresses before funding
  • Deterministic addresses simplify bridging UX
  • Deployment can piggyback first UserOperation
  • Factory bugs are high impact
  • Initializer mistakes are hard to repair
  • Cross-chain parity requires disciplined registries

Key takeaways

  • Pin factory bytecode and initializer ABIs in CI
  • Simulate first operation on forked state
  • Maintain a chain address book with version metadata

Factory pattern motivation in abstracted accounts

Smart contract wallets need bytecode on-chain before they can validate UserOperations, but forcing users to submit a standalone deployment transaction creates onboarding friction and splits the mental model of the first action. EIP-4337 allows bundlers to carry deployment intent inside initCode attached to a UserOperation so that the account address can be computed counterfactually while the EntryPoint path ensures atomicity relative to validation rules. Factories implement this by exposing methods that deploy proxies or minimal bytecode shells with CREATE2, embedding immutable implementation references and initializer calldata that sets owners, modules, and guard configurations. The factory therefore becomes part of the trust boundary: a flawed factory can deploy accounts with unintended logic or parameters, and a compromised factory admin key could redirect new users to malicious implementations. IBEx Network teams advise treating factories like critical infrastructure with multisig upgrades, timelocks where appropriate, and explicit versioning in documentation. Product narratives should explain to users that their address exists deterministically even before deployment, which matters for prefunding flows and for dapps that display deposit addresses. Security reviews must include replay considerations across chains where chain id enters CREATE2 salts or initializer arguments.

initCode structure, gas, and bundler simulation

initCode concatenates factory address and calldata that invokes the deployment method, enabling the EntryPoint to perform deployment during the UserOperation pipeline when the account bytecode is not yet present. Gas estimation must account for deployment cost plus validation cost, which can dominate totals for lightweight first transactions. Bundlers simulate the entire path to ensure deployment succeeds with the provided factory parameters and that post-deployment validation hooks behave as expected. Mismatches frequently arise when initializer calldata omits a required argument or when proxy admin rights differ between test and production factories. Debugging requires traces that show both factory execution and subsequent validateUserOp invocations on the freshly deployed account. IBEx monitoring recommends tagging first-time deployments separately in metrics so operators can detect spikes in factory failures after upgrades. When using modular accounts, ensure initializer calls enable only the modules intended for first launch; lazy module attachment can reduce blast radius. Some teams deploy through audited generic factories while others deploy custom factories per brand; economic and security trade-offs differ, but operational complexity rises with bespoke bytecode without strong release engineering.

Cross-chain determinism and address book hygiene

Deterministic addresses ease UX when users expect the same identity across networks, but determinism requires identical factory logic, salts, and initializer data on each chain. Small divergences—different implementation addresses, updated initializer ABIs, or missing factory deployment on a new chain—fragment address books and confuse support. Maintain internal registries that map chain id to factory address, implementation address, and audit report identifiers. Automated checks in CI should fail releases when a chain configuration is missing or stale relative to mainnet references. Bridges and custodians often rely on address parity; document when parity is intentionally broken for regulatory or technical reasons to prevent silent asset loss. IBEx customers should run periodic audits of counterfactual predictions by recomputing addresses with production libraries against on-chain code hashes. User interfaces should surface chain availability states rather than showing a uniform address list that hides missing deployments. When migrating factories, communicate migration windows and provide tooling to detect legacy addresses that still hold balances.

Security review checklist for factory deployments

Review initializer access control, whether uninitialized proxies can be seized, and whether CREATE2 salts resist griefing attacks that squat addresses. Examine delegatecall surfaces in implementation contracts and verify storage slot layouts align with proxy patterns used. Test reentrancy paths during deployment because factory and initializer combinations occasionally introduce subtle ordering bugs. Ensure events emit sufficient data for indexers to reconstruct account ownership changes from the first block. Run invariant tests that simulate malicious factories attempting to deploy code that bypasses expected validateUserOp behavior. IBEx security playbooks include third-party audit scheduling tied to factory version bumps, not only implementation bumps. Operations should store deployment transaction hashes immutably for compliance evidence. Finally, educate customer support on the difference between not-deployed-yet and deployed-but-empty states, because users conflate them when balances read zero on explorers.

Frequently asked questions

Can someone else deploy my counterfactual address first?

With correct CREATE2 parameters, deployment is deterministic. Whether third parties can front-run depends on factory access rules and whether initCode is public; design policies and monitor mempool if that is a concern.

Why did my first UserOperation fail after an upgrade?

Factory or implementation address changes alter derived addresses or initializer expectations. Replay tests on forked state after upgrades catch these mismatches early.

Should factories be upgradeable?

Upgradeability helps patch bugs but expands trust assumptions. Many teams use immutable factories for critical paths or combine timelocked upgrades with monitoring and migration plans.