GOMTU Crypto
guidePart 33 of 41 in this guide

Ethereum CREATE2 Explained: Deterministic Contract Addresses

Learn how Ethereum CREATE2 predicts a contract address from a factory, salt, and init code, with Solidity examples, use cases, and security checks.

GOMTU
GOMTU
Crypto Research · September 4, 2026 · 7 min read
Share𝕏in
Ethereum CREATE2 Explained: Deterministic Contract Addresses

Sometimes an application needs to know a contract's address before that contract exists. A wallet may want a stable account address before deployment, or a multichain system may need predictable infrastructure. Ethereum's CREATE2 opcode makes that possible, but prediction is only reliable when every input is controlled. It belongs in your blockchain basics toolkit because a familiar-looking address is not, by itself, proof of familiar code.

This guide explains the address formula, Solidity syntax, practical uses, and failure modes using protocol and compiler documentation. It is a deployment primitive—not a guarantee that the future contract is safe.

What CREATE2 changes

Advertisement

Ordinary CREATE derives a new contract address from the creator's address and nonce. Think of it like taking the next numbered ticket at a service desk: the result depends on how many tickets the creator has already issued. Ethereum account nonces therefore affect ordinary deployment addresses.

CREATE2, introduced by EIP-1014, replaces that sequence dependency with explicit ingredients. It is more like a reserved locker: the factory, a chosen salt, and the package being installed determine the locker number. You can calculate that number before installation.

The opcode computes:

address = last20bytes(
  keccak256(0xff ++ deployer ++ salt ++ keccak256(init_code))
)

The inputs are precise:

  • 0xff is a one-byte domain separator.
  • deployer is the 20-byte address executing CREATE2, usually a factory contract.
  • salt is a 32-byte value selected by the deployment scheme.
  • init_code is the creation code that runs to produce the contract's runtime code.

The last 20 bytes of the final hash become the address. The chain ID is not an input. However, getting the same address on two EVM chains still requires the same deployer address, salt, and init-code hash on both chains.

Init code is not runtime code

This distinction causes many prediction mistakes. Init code includes the contract's creation bytecode and encoded constructor arguments. The EVM executes it once; its output becomes the runtime bytecode stored at the new account.

Changing a constructor argument changes the init-code hash and therefore the predicted address. Changing compiler version, optimizer settings, linked-library addresses, or source metadata can change creation bytecode too. Two contracts that behave alike may still land at different addresses because their init code differs by one byte.

The reverse deserves attention as well. The Solidity documentation warns that a constructor can read external state and produce different runtime bytecode across separate creations even when creation bytecode is the same. Address prediction commits to init code, not automatically to every environmental fact the constructor observes.

How to use CREATE2 in Solidity

Solidity exposes salted creation through new Contract{salt: salt}(arguments). A minimal factory can predict and deploy the same address:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
contract Vault {
    address public immutable owner;
 
    constructor(address owner_) {
        owner = owner_;
    }
}
 
contract VaultFactory {
    function predict(bytes32 salt, address owner)
        public
        view
        returns (address)
    {
        bytes memory initCode = abi.encodePacked(
            type(Vault).creationCode,
            abi.encode(owner)
        );
 
        bytes32 digest = keccak256(
            abi.encodePacked(
                bytes1(0xff),
                address(this),
                salt,
                keccak256(initCode)
            )
        );
 
        return address(uint160(uint256(digest)));
    }
 
    function deploy(bytes32 salt, address owner)
        external
        returns (Vault vault)
    {
        vault = new Vault{salt: salt}(owner);
        require(address(vault) == predict(salt, owner));
    }
}

The deployment call and prediction must encode constructor arguments identically. abi.encode(owner) is appended to type(Vault).creationCode, so a different owner produces a different destination.

Production code should also define who may deploy, whether salts are user-specific, how value is forwarded, and what happens if the destination already contains code. Established libraries can reduce encoding mistakes, but you still need to understand which factory address their prediction uses.

Where deterministic addresses help

Counterfactual interactions

EIP-1014 was motivated by interactions with addresses that do not yet contain code. Participants can agree on the potential address and deploy the specified contract only if it becomes necessary, such as during a dispute. “Counterfactual” here means reasoning about a contract that could be deployed under known conditions—not pretending code already exists.

Smart accounts and onboarding

A wallet system can calculate a user's future smart-account address before paying deployment gas. Assets or permissions can be associated with that destination, then a factory deploys the account when the user first needs onchain execution. The operational design must prevent an unintended party from choosing initialization data or taking ownership.

Repeatable infrastructure across chains

If the same trusted factory exists at the same address and receives identical salt and init code, CREATE2 can place a contract at the same address on multiple EVM chains. ERC-2470's singleton factory is an early standardized approach to a permissionless deterministic factory. A newer proposal, EIP-7997, specifies a minimal shared factory for EVM chains. Always check a proposal's current status and verify deployed bytecode on each target chain instead of assuming universal availability.

Minimal proxy clones

Factories can combine deterministic deployment with minimal proxies to create predictable instances that delegate to an implementation. This is useful for repeated accounts or vaults, but it adds implementation and initialization assumptions. Review the proxy execution model separately.

CREATE2 risks and limitations

Predictable does not mean deployed

An address can receive native currency or tokens before code exists. If the intended deployment later becomes impossible—because inputs were recorded incorrectly, the factory is unavailable, or deployment reverts—those assets may be stuck. Confirm the full derivation and test deployment before pre-funding an address.

Public salts are not access control

Anyone can see a salt sent to a public mempool. If a permissionless factory lets any caller submit the same init code and salt, another account may deploy first. The code at the address can still be the expected code, yet the timing can disrupt a workflow. If caller identity or ownership matters, bind it into the salt or constructor data and enforce authorization in the factory.

Address collisions revert

EIP-1014 applies the existing collision rule: creation fails when the destination already has nonzero nonce or nonempty code. Reusing the same factory, salt, and init code is therefore not an overwrite mechanism. EIP-1014 also notes that SELFDESTRUCT does not let a contract be destroyed and recreated within the same transaction.

Constructor behavior can widen the trust boundary

The address formula hashes init code, but a constructor may inspect external contracts, balances, block context, or other state. Audit what the constructor reads and verify the resulting runtime bytecode after deployment. A predicted address should be treated as a commitment to a deployment recipe, not a universal code identity.

Cross-chain assumptions can fail

The same salt is insufficient. A different factory address, linked library, compiler output, constructor argument, or chain-specific dependency changes the result or behavior. Verify the factory's runtime bytecode and recompute the destination for every chain.

Deployment checklist

  • Pin compiler version, optimizer settings, source, libraries, and constructor arguments
  • Record the exact factory address, salt, init code, and init-code hash
  • Compute the address independently and compare it with the factory's helper
  • Check the destination's nonce and code before deployment
  • Bind user identity or ownership into inputs when front-running matters
  • Avoid pre-funding until a test proves the intended deployment path
  • Verify deployed runtime bytecode and initialized state after creation
  • Repeat factory-code and address checks on every target chain

FAQ

Does CREATE2 deploy without gas?

No. It changes address derivation, not the need to execute init code and pay deployment gas. EIP-1014 also charges for hashing init code.

Does the salt need to be secret?

Usually no. It is an address input, not a password. If revealing it creates a race, the factory design needs authorization or caller-bound inputs rather than relying on secrecy in a public mempool.

Can I change constructor arguments and keep the address?

No, not with the same factory and salt. Constructor arguments are part of init code, so changing them changes its hash and the resulting address.

Is CREATE2 the same as an upgradeable proxy?

No. CREATE2 chooses where a new contract is created. A proxy keeps an address while delegating execution to another implementation. A system can use both patterns, but their risks are different.

Predict the recipe, then verify the result

CREATE2 replaces deployment order with a deterministic recipe: factory, salt, and init code. That makes precomputed accounts, counterfactual workflows, and repeatable infrastructure possible. The safe workflow is equally deterministic: freeze every input, recompute independently, control deployment authority, inspect the destination, and verify runtime code plus initialization afterward.

This article is educational, not financial advice. Smart-contract transactions can be irreversible and crypto assets are volatile; test on the correct network, use only funds you can afford to lose, verify current primary documentation, and do your own research (DYOR).

Primary sources

Advertisement

Keep learning

Explore related topics

More from GOMTU