This ERC defines a permissionless and deterministic deployment mechanism across all EVM-compatible chains. It uses the EIP-7702 Set Code for EOAs (0x4) transaction type to deploy a universal CREATE2 factory contract to a fixed address (0xC0DEb853af168215879d284cc8B4d0A645fA9b0E) with known bytecode. The factory can then create any new contract to a deterministic address using the EIP-1014 CREATE2 (0xf5) opcode. It does not require preinstalls, secret keys, or chain-specific infrastructure.
Ensuring that contracts share the same address and code on multiple chains is a hard problem. It is typically done by having a known CREATE2 factory contract at a specific address that can further deterministically deploy new contracts using the CREATE2 (0xf5) opcode.
However, there is a bootstrapping problem: how do you get a CREATE2 factory contract with a specific address and code?
There are currently three main approaches to this problem:
Use Nick's method to randomly generate a signature for a transaction without EIP-155 replay protection that deploys the CREATE2 factory. Nick's method ensures that there is no known private key for the account that deploys the CREATE2 factory, meaning that the resulting contract will have a deterministic address and code on all chains. This strategy is used by the Deterministic Deployment Proxy (deployed to 0x4e59b44847b379578588920ca78fbf26c0b4956c, including on Ethereum Mainnet), one of the most widely used CREATE2 factory contracts.
Downsides:
Keep a carefully guarded secret key and use it to sign transactions to deploy CREATE2 factory contracts. The resulting contract will have a deterministic address and code on all chains where the transaction at a given nonce of the deployer account is a CREATE2 factory deployment, which can be verified post-deployment to ensure trustlessness. Additionally, this method does not have the same gas sensitivity downsides as Nick's method, as the private key can sign a creation transaction with appropriate gas parameters at the time of execution. This is the strategy used by the Safe Singleton Factory and CreateX (deployed to 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7 and 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed respectively, including on Ethereum Mainnet).
Downsides:
Have popular CREATE2 deployment factories deployed on new chains by default. This is, for example, what OP Stack and ZKsync do as part of their preinstalls, including the CREATE2 factory contracts mentioned above. This ensures that the CREATE2 factory contracts have known addresses and codes.
Downsides:
0x4 TransactionsThis ERC proposes a permissionless alternative fourth mechanism to the existing ones described above with none of their downsides. Additionally, it standardizes a set of deployment parameters for a universal CREATE2 factory deployment. This ensures a common CREATE2 factory for the community instead of multiple competing copies with slightly different codes at different addresses. This single CREATE2 factory copy can bootstrap additional deterministic deployment infrastructure (such as the comprehensive CreateX universal contract deployer).
Benefits
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
| Parameter | Value |
|---|---|
DEPLOYER_PRIVATE_KEY | 0x942ba639ec667bdded6d727ad2e483648a34b584f916e6b826fdb7b512633731 |
CREATE2_FACTORY_INIT_CODE | 0x7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3 |
CREATE2_FACTORY_SALT | 0x000000000000000000000000000000000000000000000000000000000001bec5 |
| Derived Parameter | Value |
|---|---|
DEPLOYER_ADDRESS | 0x962560A0333190D57009A0aAAB7Bfa088f58461C |
CREATE2_FACTORY_ADDRESS | 0xC0DEb853af168215879d284cc8B4d0A645fA9b0E |
CREATE2_FACTORY_RUNTIME_CODE | 0x60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f3 |
CREATE2_FACTORY_CODE_HASH | 0x2ad75e1e9642e6fce7d293d52fa5a8f62a79a2079abb7402256add02d6e8bc30 |
DEPLOYER_PRIVATE_KEY with address DEPLOYER_ADDRESS.CREATE2 (0xf5) opcode, allowing smart contracts to be deployed to deterministic addresses.CREATE2 (0xf5) deployment of the CREATE2 factory contract.The bootstrap contract MUST execute the following or equivalent bootstrapping code as an EIP-7702 delegation target for the deployer account:
The bootstrap contract MAY implement additional features such as:
DEPLOYER_PRIVATE_KEY delegating to the bootstrap contract.0x4 transaction with the authorization from step 2; the transaction MUST call DEPLOYER_ADDRESS (either directly or indirectly) which delegates to the bootstrap contract and MUST perform the CREATE2 (0xf5) of the CREATE2_FACTORY_INIT_CODE with CREATE2_FACTORY_SALT in the bootstrapping code.Assuming successful execution of the bootstrapping code without reverting in the context of the deployer, the CREATE2 factory contract will be deployed to CREATE2_FACTORY_ADDRESS with code CREATE2_FACTORY_RUNTIME_CODE and code hash CREATE2_FACTORY_CODE_HASH.
The deployment mechanism was chosen such that it is uniquely parameterized by the DEPLOYER_ADDRESS (which itself is derived from the DEPLOYER_PRIVATE_KEY and is therefore deterministic), the CREATE2_FACTORY_INIT_CODE and the CREATE2_FACTORY_SALT which are both fixed and deterministic. Additionally, since the DEPLOYER_ADDRESS will deploy the CREATE2 factory contract with the CREATE2 (0xf5) opcode, this guarantees that the address and code of the contract are deterministic.
The use of a publicly known private key enables this mechanism, as anyone can permissionlessly generate a delegation signature to any bootstrap contract that would cause the DEPLOYER_ADDRESS to execute the specified CREATE2 (0xf5) operation and deploy the factory contract to a completely deterministic address. Because of the use of CREATE2 (0xf5), the CREATE2 factory will be deployed to CREATE2_FACTORY_ADDRESS if and only if it is deployed with CREATE2_FACTORY_INIT_CODE, thus guaranteeing a deployed code hash of CREATE2_FACTORY_CODE_HASH. Additionally, the semantics of CREATE2 (0xf5) make it so no transaction executed by DEPLOYER_ADDRESS can permanently block the deployment of the CREATE2 factory contract to CREATE2_FACTORY_ADDRESS.
One issue with this method is that because the DEPLOYER_PRIVATE_KEY is public, anyone can sign alternative delegations or transactions and front-run a legitimate CREATE2 factory deployment. The front-running would increase the nonce of the DEPLOYER_ADDRESS account and render the EIP-7702 authorization in the legitimate CREATE2 factory deployment transaction invalid, causing the deployment to potentially fail. This is not considered to be a serious issue, however, as:
Another known issue with this method is that a future network upgrade may introduce new mechanisms (such as a new opcode or transaction type) to permanently set an account's code. If this were to happen, and since the DEPLOYER_PRIVATE_KEY is publicly known, the DEPLOYER_ADDRESS account's code could be mistakenly or maliciously set to something that does not execute the necessary bootstrapping code, permanently preventing any future deployment of the CREATE2 factory contract. If this ERC were to gain sufficient adoption, this is not believed to be an issue as:
DEPLOYER_PRIVATE_KEY would no longer have any value on Ethereum Mainnet.CREATE2_FACTORY_ADDRESS has code CREATE2_FACTORY_RUNTIME_CODE.Instead of using a publicly known DEPLOYER_PRIVATE_KEY, Nick's method can be used to generate a random EIP-7702 authorization signature. This would prevent the front-running and forward compatibility issues described above.
However, in order for Nick's method to work, the EIP-7702 authorization message that is signed, defined as keccak(MAGIC || rlp([chain_id, address, nonce])), must be constant. MAGIC is already a constant; chain_id can be trivially fixed to 0 to specify a chain-agnostic EIP-7702 authorization; nonce can also be trivially fixed to 0 because Nick's method ensures the authority has no known private key, meaning it cannot sign another message that would increment the nonce. However, fixing address is problematic. Doing so would require a contract with specific code to be deployed to the same address on all chains, which is the original bootstrapping problem the proposed permissionless CREATE2 factory aims to solve. Therefore, this creates a "chicken and egg problem", making it not a viable way to generate an EIP-7702 authorization signature.
This mechanism allows the DEPLOYER_ADDRESS to do any CREATE2 (0xf5) deployment, so it would be possible to forgo the intermediary CREATE2 factory contract and use the deployer technique for all deployments. There are multiple downsides to this, however:
Unfortunately, EIP-7702 type 0x4 transactions are restricted to to values that are not null, meaning that you cannot simultaneously deploy the bootstrap contract and delegate to it in a single transaction.
The DEPLOYER_PRIVATE_KEY was chosen as the private key at derivation path m/44'/60'/0'/0/0 for the mnemonic make code code code code code code code code code code coconut.
The CREATE2_FACTORY_SALT was chosen as the first salt value starting from 0 such that the CREATE2 factory's ERC-55 checksum address starts with the case sensitive 0xC0DE... prefix. A verifiable method for mining a vanity address for the CREATE2 factory contract was chosen in order to ensure that the ERC authors did not find a CREATE2 hash collision on the CREATE2_FACTORY_ADDRESS that they can exploit at some point in the future.
The CREATE2 factory has a similar interface to existing implementations. Namely, it accepts salt || init_code as input, which is a 32-byte salt value concatenated with the init_code of the contract to deploy. It will execute a CREATE2 with the specified salt and init_code, deploying a contract with init_code to keccak256(0xff || CREATE2_FACTORY_ADDRESS || salt || keccak256(init_code))[12:]. This contract returns the address of the created contract padded to 32 bytes. This differs from some existing implementations, but was done to maintain consistency with the 32-byte word size on the EVM (same encoding as ecrecover precompile for example). A product of this is that the return data from CREATE2 factory is compatible with the Solidity ABI. In the case where the execution of init_code were to fail, any revert data is propagated to the caller.
Throughout both the CREATE2 factory contract initialization and runtime code, RETURNDATASIZE (0x3d) is used to push 0 onto the stack instead of the dedicated PUSH0 (0x5f) opcode. This is done to increase compatibility with chains that support EIP-7702 but not EIP-3855, while remaining a 1-byte and 2-gas opcode.
The CREATE2_FACTORY_INIT_CODE corresponds to the following assembly:
The CREATE2_FACTORY_RUNTIME_CODE corresponds to the following assembly:
There are a few backwards compatibility considerations with the new proposal:
This proposal includes a reference implementation of a bootstrap contract to which the deployer account can delegate. The reference implementation expects a call to Bootstrap to the function deploy() in an EIP-7702 type 0x4 transaction including the EIP-7702 authorization delegating DEPLOYER_ADDRESS to Bootstrap (NOTE: the Bootstrap is called as an entry point, instead of calling DEPLOYER_ADDRESS directly which allows the contract to do some up-front checks to minimize gas griefing risk):
A minimal bootstrap contract implementation is also possible (although this has a higher potential for gas griefing). The minimal bootstrap contract expects a call directly to the DEPLOYER_ADDRESS in an EIP-7702 type 0x4 transaction including the EIP-7702 authorization delegating DEPLOYER_ADDRESS to MiniBootstrap:
It is possible to front-run transactions that invalidate the deployer's EIP-7702 delegation and cause the deployment to fail. This, however, comes at a gas cost to the attacker, with limited benefit beyond delaying the deployment of the CREATE2 factory. Additionally, persistent attackers can be circumvented by either using private transaction queues or working with block builders directly to ensure that the EIP-7702 bootstrapping transaction is not front-run.
If new EVM opcodes or transaction types are introduced in future network upgrades that allow an account to permanently set its code, then this method is no longer guaranteed to work. The deployer account can permanently change its code to a contract that does not have the required bootstrapping code. This can trivially be done by a malicious actor using the publicly known DEPLOYER_PRIVATE_KEY and would prevent any future deployments of CREATE2 factory.
Copyright and related rights waived via CC0.