Predictable Contracts: Understanding CREATE and CREATE2 in Ethereum
2 min read
October 5, 2025

Table of contents
Hi everyone,
In this edition I want to dive into something that sits at the core of Ethereum: how contract addresses are generated. If you’ve ever wondered how attackers can predict where a smart contract will live before it’s even deployed, this one’s for you.
The Classic Way: CREATE
Traditionally, contracts are deployed with the CREATE
opcode. Solidity handles this every time you write:
MyContract c = new MyContract();
Under the hood, the EVM computes the new address as:
keccak256(rlp([sender, nonce]))[12:]
Where:
- sender = the deployer’s address
- nonce = the deployer’s transaction count
This means that if you know an account’s address and nonce, you can deterministically calculate where its next contract will be deployed.
The New Paradigm: CREATE2
Introduced with EIP-1014 the CREATE2
opcode gives developers more control. Solidity exposes it with:
new MyContract{salt: _salt}();
Where:
keccak256(0xff ++ sender ++ salt ++ keccak256(init_code))[12:]
- salt = a user-provided value
- init_code = the contract’s creation bytecode
This allows developers to precompute an address before the contract exists, a key feature for counterfactual contracts, meta-transactions, and smart wallets.
Risks and Attack Scenarios
While powerful, both CREATE
and CREATE2
introduce interesting risks. Some ideas that usually come to mind when reviewing contracts that rely on these patterns are:
- 🔒 Front-running & squatting: attackers can preemptively deploy contracts at addresses others plan to use.
- 👻 Shadow contracts: malicious contracts can be deployed at expected addresses if salts aren’t carefully controlled.
- ♻️ Code replacement: with
CREATE2
, a contract can be destroyed and redeployed at the same address dangerous if external systems assume code immutability. - 💸 Value pre-funding abuse: attackers can send ETH to precomputed addresses (even if no contract is deployed there) to change assumptions, grief users, or create unexpected states. This is low-cost and often overlooked protocols that implicitly assume zero balance or an unused address can be tripped by simple pre-funding.
Mitigation Tips
On the other hand, some good practices that could be applied here are:
- 🧂 Use unique, unpredictable salts when working with
CREATE2
to avoid predictable deployments or collisions. - 🔒 Guard against re-initialization in contracts that might be redeployed (e.g., use initialization flags tied to constructor arguments or immutable codehash checks).
- 💰 Don’t rely on zero balance assumptions. Explicitly check the code hash (
extcodehash
) and verify thataddress.balance
is within expected bounds. - ⏳ Reserve counterfactual addresses safely: consider time-locked reservations or an on-chain registration step before allowing sensitive actions.
- 🧪 Test pre-funded scenarios: include cases where the target address already holds ETH or ERC20 tokens.
- 📝 Verify the bytecode hash if immutability is assumed
REATE2
allows redeployment at the same address.
Thanks for reading hope this gives you a few new angles to test in your own reviews.
See you in the next one!
Stay sharp,
Ruben
Chapters

Previous Issue