A minimal CREATE2 factory is inserted as a system contract in the precompile range, to enable deterministic deployments at identical addresses across EVM chains that adopt it.
Motivation
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).
Another important use case is in account abstraction. Accounts tied to a single chain are difficult to explain to users and can cause loss of funds. Smart contract accounts must be multi-chain, like EOAs, or 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:
A keyless transaction is crafted using Nick’s method that can be posted permissionlessly to new chains. For this to work, the chain must support legacy transactions without EIP-155 replay protection, and the fixed gas price and gas limit must be sufficiently high, but not so high as to exceed the limits of the chain.
Private keys held by some party are used to sign creation transactions for each chain as needed. This creates a dependency on that party, does not provide a hard guarantee that the factory will be available on every chain, and can also irreversibly fail if transactions are not properly parameterized.
A private key is intentionally leaked so that any party can permissionlessly create an EIP-7702 signed delegation and deploy a factory from the leaked account. While this approach improves on the previous two, its reliance on ECDSA keys makes it non-quantum-resistant, and will fail once chains stop supporting ECDSA keys. Additionally, it requires EIP-7702, an orthogonal feature which is not guaranteed to spread to all chains; for example, those chains that tackle account abstraction through other means have no use for it, and arguably weaker ecosystem pressure to implement it (compared to other EIPs) given that it is a feature not directly used by applications (which instead access AA capabilities through an abstraction like EIP-5792). Lastly, there is a possibility that a future upgrade allows EIP-7702 delegations to become permanent, which breaks this scheme.
Factories already deployed on other chains (by any of the previous methods) are inserted in a new chain at genesis or via a hard fork. This has not been widely adopted by chains, despite the standardization efforts of RIP-7740. Since these factories are applications deployed by users through normal means, this kind of hardcoding of accounts may be seen by chain developers as too intrusive.
This EIP aims to coordinate a widely available multi-chain CREATE2 factory without the above downsides by placing a factory in the precompile range.
Specification
Parameters
FACTORY_ADDRESS = 0x0B
Factory Contract
Upon activation of this EIP, set the code of FACTORY_ADDRESS to 60203610602f5760003560203603806020600037600034f5806026573d600060003e3d6000fd5b60005260206000f35b60006000fd, corresponding 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
Rationale
Precompile-range system contract
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.
Input validation
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.
No frontrunning protection
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.
Not a new transaction type
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.
Constantinople target, avoidance of 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.
Test Cases
TBD
Security Considerations
Frontrunnable deployments
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.