EIP-3171 was an EIP that introduced a new native opcode (CREATE3) that enabled deterministic contract creation similar to that of CREATE2 but with the initcode removed from the address derivation formula. Unfortunately, the EIP was rejected, in part due to the emergence of a popular application-layer approximation bearing the same name. However, this approximation leveraged a combination of the CREATE and CREATE2 opcodes to achieve its functionality, and in doing so increased the compute cost of mining efficient addresses by severalfold while also breaking compatibility with existing salt mining tooling.
CREATE4 is a different approach to approximating the functionality lost in the rejection of EIP-3171. Despite the name, the address derivation formula for CREATE4 is significantly closer to what a native CREATE3 opcode would have possessed than the original CREATE3 app-layer implementation was. Because CREATE4 uses a single CREATE2 call with a fixed initCode under the hood, create2crunch can be used to mine CREATE4 salts for efficient addresses at no additional compute cost over CREATE2 mining.
- Store the
deployedCodeof the desired contract somewhere on-chain (in order of gas cost) - Expose the
deployedCodevia a getter function with support for returning from both transient storage and from a contract address based on previously set flags in storage. This ensures that the method of code storage does not affect the address derivation formula. CREATE2with a user's salt and "bootstrap"initCodecontaining their address somewhere (for front-running protection) that queries thedeployedCodefrom the getter function and returns it.- We now have a process that can be used to deploy any bytecode with a deterministic address based on the
msg.senderand a salt.
For Create4Factory, the initCode is constructed as follows:
- Executable constructor:
3636363636335af13d36363e3d36f3 - Deployer address (user calling
create4):ffffffffffffffffffffffffffffffffffffffff(20-byte salt)
Result: 0x3636363636335af13d36363e3d36f3<deployer address>
If we have
Create4Factoryaddress:0xe358511cd9bf45c8a4d4aaf96ad5f6234ad20282(note: not the real-world address!)- Deployer address:
0xab5801a7d398351b8be11c439e05c5b3259aec9b(Vb)
Our initCode would be:
0x3636363636335af13d36363e3d36f3ab5801a7d398351b8be11c439e05c5b3259aec9b
- Deterministic contract address based on
msg.sender+ salt - Simple,
CREATE2-compatible address derivation formula with ideal compute cost - Front-running protection
- Cheaper than CREATE3 for smaller contracts on chains with EIP-1153 support
- Same contract addresses on different EVM networks (even those without support for EIP-1153)
- Supports any EVM compatible chain with support for CREATE2 (& PUSH0)
- ~1.93-1.95x deployment cost increase for chains without EIP-1153 (transient storage) support
- ~7-10% deployment cost increase for chains with EIP-1153 support
- No constructor support (deployed bytecode must be precomputed)
None yet :)
Call the create4 method on the Create4Factory, provide the contract creationCode (on EIP-1153 networks) or the address of a deployed contract containing the code you want to deploy (on non-EIP-1153 networks) and a salt. Different contract codes will result on the same address as long as the same salt is provided.
We compare the approximate cost of deploying a contract consisting of N FF bytes from an EOA via CREATE2 and CREATE4
- Transient storage:
create4(bytes, bytes32)vsCREATE2 - Deployed code:
create4(address, bytes32)vsCREATE2
Note: deployed code benchmarks also consider the cost of deploying the code from an EOA before calling create4(address, bytes32)
The code for the benchmarks can be found in test/Gasbench.t.sol and the results may be reproduced locally by running:
forge test --use bin/solc --match-contract C4GasBench -vv-
Transient storage: 1.072x more expensive than CREATE2
-
Deployed code: 1.931x more expensive than CREATE2
- Transient storage: 1.080x more expensive than CREATE2
- Deployed code: 1.935x more expensive than CREATE2
- Transient storage: 1.095x more expensive than CREATE2
- Deployed code: 1.943x more expensive than CREATE2
- Transient storage: 3.075x more expensive than CREATE2
- Deployed code: 2.902x more expensive than CREATE2
forge install dyedm1/create4forge build --use bin/solcforge test --use bin/solcforge fmt//SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.20;
import {Create4} from "lib/create4/src/Create4Factory.sol";
contract CreateMe {
function test() external view returns (uint256) {
return 0x1337;
}
}
contract Deployer {
function deployChild() external {
Create4Factory(0x0000000000000000000000000000000000000000).create4(type(CreateMe).deploymentCode, bytes32(0x1337));
}
}Code in this repository is licensed under GPLv3 unless otherwise indicated (see LICENSE file).