Predictable Contracts: Understanding CREATE and CREATE2 in Ethereum

2 min read

October 5, 2025

Predictable Contracts: Understanding CREATE and CREATE2 in Ethereum

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 that address.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

Botón Anterior
The Day an Email Broke Single Sign-On

Previous Issue

Enjoyed the article?

Subscribe to the newsletter and get technical insights, cybersecurity tips, and development content straight to your inbox. Or support my work with a coffee ☕ if you found it useful!

📫 Subscribe now ☕ Buy me a coffee