Smart-contract developers often need to deploy their contracts with consistent addresses across various Ethereum Virtual Machine (EVM) networks. At Merkl, like many other protocols, this ensures users can interact with the same contract address on each network where the protocol is deployed.
In this article, we'll examine various techniques to deploy smart contracts at deterministic addresses.
The original CREATE
opcode
The CREATE
opcode (a low-level instruction executed by the EVM) is the traditional method used to deploy a smart contract on EVM networks. It can be invoked by an externally owned account (EOA) or a contract to deploy a new contract.
Address calculation — the address of the new deployed contract is calculated as follows (find out more here):
address = keccak256(rlp([sender_address,sender_nonce]))[12 :]
The address is a function of senderAddress
and nonce
, where:
senderAddress
is the address of the account deploying the contract (an EOA or a smart-contract)nonce
is the number of transactions or contracts previously sent or created by the sender.
At Merkl, we typically use this opcode to deploy our contract implementation from the same EOA across multiple networks, ensuring that the EOA has never previously sent transactions across the network.
While this method offers some predictability, it's not ideal for cases where a contract needs to be deployed at the same address on different chains without depending on previous state or nonce values.
The skinny CREATE2 opcode
CREATE2
was introduced in EIP-1014 as an improvement over the CREATE
opcode, offering more control and determinism in contract deployment.
Address Calculation — the address for a contract deployed via CREATE2
is determined by the following formula (find out more here):
initialisation_code = memory[offset:offset+size]
address = keccak256(0xff + sender_address + salt + keccak256(initialisation_code))[12:]
0xff
is a single byte constant,senderAddress
is the address initiating the contract deployment,salt
is a user-defined value (often a random or unique string that ensures uniqueness),initialisation_code
is the result from compiling the contract source code, along with any constructor arguments encoded into it. Any modification, even a single whitespace in the Solidity code will result in a different bytecode.
Using a salt
, developers can control where the contract is deployed by providing a predictable identifier. As long as the same values for senderAddress
, salt
, and initialisation_code
are used, developers can deploy a contract at the same address on different chains.
Unlike CREATE
, developers can deploy contracts to predetermined addresses, regardless of the sender's nonce. This opcode makes the contract address entirely deterministic.
The multichain alternative CREATE3
CREATE3
is a proposal introduced in EIP-3171 that extends both features of CREATE
and CREATE2
. Though the proposal was closed due to inactivity, 0xsequence implemented a workaround until it eventually gets merged.
Address Calculation: The address is no longer tied to the implementation code, allowing a contract to be deployed at the same address using only the senderAddress
and a salt
as arguments.
As shown in the code snippet above, it:
- first deploys a proxy using
CREATE2
- then calls the proxy with the init code, which deploys the contract using
CREATE
, thus the deployed contract address only depends on thesenderAddress
and thesalt
.
Since it doesn't rely on the contract bytecode, CREATE3
allows contracts to be deployed at the same address even with different constructor arguments and initialization bytecode, making it more suitable for multi-chain setups than CREATE2
.
Deterministic smart contract deployment on EVM-compatible chains offers substantial benefits in terms of control, predictability, and flexibility. From the basic CREATE
opcode to more sophisticated methods like CREATE2
and CREATE3
, developers now have more options to deploy contracts at specific addresses with confidence.
Special mention to CREATEX
, a factory smart-contract deployed on more than 130 chains today. As mentioned in their README.md, their factory is "a special smart contract that is used to create and deploy other smart contracts on EVM-compatible blockchains using contract creation opcodes", including CREATE
, CREATE2
, CREATE3
.
Sources:
- EVM codes - https://www.evm.codes/
- EIP-1014 - https://eips.ethereum.org/EIPS/eip-1014
- EIP-3171 - EIP-3171
- Rareskills - https://www.rareskills.io/post/ethereum-contract-creation-code
- CreateX - https://github.com/pcaversaccio/createx