A minimal CREATE2
factory is inserted as a system contract in the precompile range, to enable deterministic deployments at identical addresses across EVM chains. This benefits developer experience, user experience, and security, in particular for multi-chain and cross-chain applications, including account abstraction.
There are now a large number of EVM chains where users want to transact and developers want to deploy applications, and we can expect this number to continue to grow in line with Ethereum's rollup-centric roadmap and the general adoption of programmable blockchains.
Most applications support multiple chains and aspire to support as many as possible, and their developers widely prefer to deploy contracts at identical addresses across all chains, a setup which we will call multi-chain deterministic deployment.
This kind of deployment reduces the number of addresses that must be distributed to use the application, so that it no longer scales with the number of supported chains. This simplification has many benefits throughout the stack: interfaces and SDKs need to embed and trust fewer addresses, and other contracts that depend on them can be implemented without chain-specific customization (which in turn makes them amenable to multi-chain deployment).
This kind of deployment is also highly desirable and important for account abstraction. Without it, a user's smart contract accounts are deployed at different addresses on different chains, and each account is tied to a single chain. This limitation is difficult to explain to users and has caused loss of funds. If smart contract accounts cannot be multi-chain like EOAs, they offer downgraded UX and are more prone to error.
There is currently no native or fully robust way to perform multi-chain deterministic deployments. While CREATE2
enables deterministic deployments, the created address is computed from that of the contract that invokes the instruction, so a factory that is itself multi-chain is required for bootstrapping. Four workarounds are currently known to deploy such a factory, each with their own issues:
This EIP aims to coordinate a widely available multi-chain CREATE2
factory without the above downsides by placing a factory in the precompile range.
FACTORY_ADDRESS
= 0x0B
Upon activation of this EIP, the account at FACTORY_ADDRESS
becomes a contract that, when called, invokes the CREATE2
instruction (EIP-1014) with a salt equal to the first 32 bytes of the call's input data, init code equal to the remaining data, and value equal to the call's value. If input data is smaller than 32 bytes, the call reverts with empty return data. If creation fails (CREATE2
outputs 0
), the call reverts with return data equal to that of the creation frame.
Specifically, the code of FACTORY_ADDRESS
is set to 60203610602f5760003560203603806020600037600034f5806026573d600060003e3d6000fd5b60005260206000f35b60006000fd
. This code implements the specification above and corresponds to the following assembly:
#pragma target "constantinople"
;; Input: salt (32 bytes) || initcode (variable size)
;; Verify input is at least 32 bytes long.
push 32
calldatasize
lt
jumpi @throw
;; Load salt.
push 0
calldataload
;; Compute initcodesize = calldatasize - 32.
push 32
calldatasize
sub
;; Copy initcode to memory at position 0.
dup1
push 32
push 0
calldatacopy
;; Invoke create2 with salt and initcode, forwarding all callvalue.
push 0
callvalue
create2
;; Check if create2 produced nonzero.
dup1
push @success
jumpi
;; Fallthrough if zero, and revert with identical returndata.
returndatasize
push 0
push 0
returndatacopy
returndatasize
push 0
revert
;; On success, return the created address.
success:
push 0
mstore
push 32
push 0
return
throw:
push 0
push 0
revert
Unlike previous system contracts, this factory cannot be deployed using a normal transaction because, as explained in the Motivation section, that transaction could not be guaranteed to be valid on other chains. Since the purpose of this factory is to be available in all EVM chains that a contract could be deployed to, an irregular insertion of the code into a special address seems necessary.
The address 0x0b
(0x000000000000000000000000000000000000000b
) is chosen as the next lowest address after existing precompiles, on the assumption that other EVM chains would have reserved this range for future Ethereum precompiles.
The factory reverts if the input is smaller than 32 bytes, the minimum size that contains a nonce, to provide an explicit error when the factory is not correctly invoked.
As explained in the Security Considerations, deployments using this factory can potentially be frontrun.
A different factory could avoid this issue if it invokes CREATE2
with a salt computed from the caller address in combination with the caller-provided salt input. This prevents frontrunning, but makes deployments permissioned to a deployer account, without the ability to recover permissionless deployments across chains because of the bootstrapping problem this EIP is itself meant to solve.
A factory could also support both permissioned and permissionless deployments by making the mechanism opt-in. However, the addition of this complexity to an otherwise very simple contract was deemed unnecessary, since once the bootstrapping problem is solved, further factories with a more comprehensive set of features and security measures can be deterministically deployed across chains. We expect this to be the case.
An alternative approach would consist of a new creation transaction type where the address of the created contract is computed in a way independent of the transaction origin. A system contract was considered a simpler approach that will be more robust to changes in the base layer in the future or across chains.
PUSH0
The system contract is written to avoid the use of newer opcodes such as PUSH0
to make it viable to be adopted by chains that don't yet support them, decoupling the decision to adopt this EIP from that of adopting other EIPs.
TBD
The deployment of contracts that read the environment (ORIGIN
, NUMBER
, etc.) may be frontrun and created with attacker-chosen parameters. It's recommended to use this factory to deploy fully deterministic contracts only.
Copyright and related rights waived via CC0.