Skip to main content

CREATE2 Deterministic Deployment

The Simple Way
var create2 = web3.Eth.Create2DeterministicDeploymentProxyService;
var address = create2.CalculateCreate2Address(deployment, salt);
var receipt = await create2.DeployContractRequestAndWaitForReceiptAsync(deployment, salt);

Predict the address, then deploy — same address on every chain with the same salt.

CREATE2 lets you deploy a contract to a predictable address that depends only on the deployer address, a salt, and the contract bytecode. This is useful for counterfactual deployments (predicting addresses before deployment), deploying the same contract to the same address across multiple chains, and factory patterns.

Nethereum provides Create2DeterministicDeploymentProxyService accessible via web3.Eth.Create2DeterministicDeploymentProxyService.

dotnet add package Nethereum.Web3

How CREATE2 Addressing Works

The CREATE2 address is computed as:

address = keccak256(0xff ++ deployerAddress ++ salt ++ keccak256(bytecode))[12:]

This means the resulting address is fully deterministic -- if you know the deployer, salt, and bytecode, you can compute the address before deployment.

Predict a Contract Address

Calculate the CREATE2 address without deploying:

using Nethereum.Web3;
using Nethereum.Contracts.Create2Deployment;

var web3 = new Web3(account, rpcUrl);
var create2Service = web3.Eth.Create2DeterministicDeploymentProxyService;

var salt = "0x0000000000000000000000000000000000000000000000000000000000000001";

var predictedAddress = create2Service
.CalculateCreate2Address<MyContractDeployment>(
new MyContractDeployment { /* constructor args */ },
proxyAddress,
salt);

Console.WriteLine($"Contract will deploy to: {predictedAddress}");

Check If Already Deployed

Before deploying, check if the contract already exists at the predicted address:

var alreadyDeployed = await create2Service
.HasContractAlreadyDeployedAsync(predictedAddress);

if (!alreadyDeployed)
{
// Safe to deploy
}

Deploy via CREATE2 Proxy

The service uses a deterministic deployment proxy. First ensure the proxy is deployed, then deploy your contract through it:

var web3 = new Web3(account, rpcUrl);
var create2Service = web3.Eth.Create2DeterministicDeploymentProxyService;

var salt = "0x0000000000000000000000000000000000000000000000000000000000000001";

// Deploy your contract via CREATE2
var result = await create2Service
.DeployContractRequestAndWaitForReceiptAsync<MyContractDeployment>(
new MyContractDeployment { /* constructor args */ },
proxyAddress,
salt);

Console.WriteLine($"Deployed to: {result.ContractAddress}");
Console.WriteLine($"Transaction: {result.TransactionHash}");

Deploy the Proxy Itself

If the deterministic deployment proxy isn't deployed on your chain yet:

var proxyAddress = await create2Service
.DeployProxyAndGetContractAddressAsync();

Console.WriteLine($"Proxy deployed at: {proxyAddress}");

Check If Proxy Exists

var proxyDeployed = await create2Service
.HasProxyBeenDeployedAsync(proxyAddress);

EIP-155 Chain-Specific Deployment

For chain-specific deterministic deployments (where the deployment transaction includes the chain ID):

var deployment = await create2Service
.GenerateEIP155DeterministicDeploymentAsync();

This creates a deployment that is specific to the current chain, producing a different proxy address per chain but with a deterministic result on each chain.

Key Types

  • Create2DeterministicDeploymentProxyService -- main service accessible via web3.Eth.Create2DeterministicDeploymentProxyService
  • Create2ContractDeploymentTransactionResult -- result containing ContractAddress and TransactionHash
  • ContractUtils.CalculateCreate2Address() -- low-level address calculation utility

Common Patterns

TaskMethod
Predict addresscreate2Service.CalculateCreate2Address<T>(deployment, proxy, salt)
Check if deployedcreate2Service.HasContractAlreadyDeployedAsync(address)
Deploy contractcreate2Service.DeployContractRequestAndWaitForReceiptAsync<T>(deployment, proxy, salt)
Deploy proxycreate2Service.DeployProxyAndGetContractAddressAsync()
Check proxy existscreate2Service.HasProxyBeenDeployedAsync(proxyAddress)
EIP-155 deploymentcreate2Service.GenerateEIP155DeterministicDeploymentAsync()

Next Steps