Solia saysA CREATE2 factory deploys contracts at deterministic addresses; users can interact with the address before the contract exists, enabling counterfactual deposits and account abstraction.
A CREATE2 factory is a contract that deploys others using CREATE2 with a user-supplied salt. Because the deployed address is fully determined by (factory, salt, initcode), users can send funds to or sign permits for an address that does not yet have any code — and the factory will deploy a contract at that address only when someone calls deploy.
This is the foundation of counterfactual smart-contract wallets (ERC-4337 lineage): users compute their wallet address before any deployment cost is paid, fund it, and only pay for deployment when they actually transact. The demo predicts a wallet address for a user, "deploys", and confirms the address matches.
Power-ups you unlock
Factory contract deploys others via CREATE2 with a user salt
Address is fully determined by (factory, salt, initcode)
Users can interact with an address before any code exists
Pay deployment cost only when needed (lazy deployment)
Foundation of counterfactual account-abstraction wallets
The Reentrancy Reaper attacks — common mistakes
Changing the initcode after users computed addresses (breaks predictions)
Letting users pick salts that collide with other users
Trusting balances at counterfactual addresses without considering frontrunning
Forgetting that the predicted address can be redeployed if not pinned
Boss battlePredict a wallet address from (factory, salt, initcode), then "deploy" and confirm the address matches.
Example code
<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
const H = (s) => { let h=2166136261>>>0; for(const c of s){ h^=c.charCodeAt(0); h=Math.imul(h,16777619); } return '0x' + (h>>>0).toString(16).padStart(8,'0'); };
const predict = (factory, salt, initcode) => H('ff:' + factory + ':' + salt + ':' + H(initcode));
const factory = '0xFactory';
const wallet = '0xUser-alice';
const initcode = 'SmartWallet(owner=' + wallet + ').bytecode';
const salt = 'alice-wallet-v1';
// step 1 — user predicts BEFORE deploy
const predicted = predict(factory, salt, initcode);
// step 2 — funds sent to predicted address while no contract exists
const balance = '0.5 ETH';
// step 3 — factory.deploy(salt, initcode) is later called
const deployed = predict(factory, salt, initcode);
document.getElementById('o').textContent = [
'STEP 1 — predict address (no code exists yet)',
' factory: ' + factory,
' salt: ' + salt,
' predicted → ' + predicted,
'',
'STEP 2 — user funds the predicted address',
' ' + predicted + ' balance: ' + balance + ' (no contract yet)',
'',
'STEP 3 — factory.deploy(salt, initcode) actually deploys',
' deployed → ' + deployed + ' (same as predicted? ' + (predicted === deployed) + ')',
'',
'→ lazy deployment: pay gas only on first real use'
].join('\n');
</script></body></html>