I propose to align on the following potential EIP that enables etching of the runtime bytecode onto the derived address by anyone.
I have been thinking about this since the creation of the YAC3F CREATE3 factory ( GitHub - radeksvarz/yac3f: Yet Another CREATE3 Factory ) and discussion on Pascal’s and Matt’s CreateX ( 📖 Private Key Management of `CreateX` Deployer · pcaversaccio/createx · Discussion #61 · GitHub ) seeing how the deterministic deployment infra must be over complicated and cost ineffective (e.g. multiple passes of bytecode in calldata).
I also wonder why such an uncomplicated improvement was not put on the table with EIP 7702 and other AA, which would benefit from it for its adoption.
Therefore I am inviting at least @pcaversaccio + @mds1 (CreateX deployments), @PaulRBerg + @zerosnacks and others (Foundry and Reth), @holiman and others (Geth), @mudgen (Diamonds), @yoavw and others (AA) and anyone to give their opinion / co-author and advocate such EIP.
Abstract
This EIP proposes a new precompile that allows contracts to be created at addresses derived directly from their runtime bytecode. This facilitates deterministic deployments based on code content and enhances the capabilities of externally owned accounts (EOAs), in line with the concepts of EIP-7702.
Motivation
Deterministic deployments: Addresses the challenge of deploying contracts deterministically across different Ethereum Virtual Machine (EVM) compatible chains, especially when specific deployment factories (e.g. CREATE2, CREATE3) are not available.
Trustless and independent deployments: Allows anyone to deploy the same contract to the identical address across compatible EVM chains.
Enhanced EOAs: Supports the adoption of EIP-7702 enhanced EOAs / Smart accounts.
Reduction of the calldata: Eliminates the need to include initcode, reducing calldata size during deployment and multiple calldata passes when using factories
Improved security: Intrinsically linking code to its address can improve security and limit phishing attempts by making it harder to deploy malicious code under a seemingly benign address.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Precompile Address: yet TBD (example: 0x00000000000000000000000000000000000000ee).
Input Parameters: runtimeBytecode: bytes - The runtime bytecode of the contract to be deployed.
Output Parameters: contractAddress: address - The address of the deployed contract.
Functionality
Address derivation: The contract address is calculated as the rightmost 20 bytes (160 bits) of the Keccak-256 hash of the provided runtimeBytecode.
Contrary to the CREATE opcode, neither msg.sender, nor sender’s nonce is taken into consideration. Contrary to the CREATE2 opcode neither msg.sender, nor initcode, nor salt are taken into account.
Deployment: The runtimeBytecode is deployed to the derived contractAddress.
Error handling:
The precompile should handle errors similarly to the CREATE/CREATE2 opcode.
State changes done by the current context are reverted in these cases:
Not enough gas.
Not enough values on the stack.
The current execution context is from a STATICCALL (since Byzantium fork) or an EXTSTATICCALL (since EOF fork).
Provided runtimeBytecode size is greater than the chain’s maximum runtimecode size.
Collisions of resulting address with the sanctioned range.
Sanctioned address range:
0x0 … 0xff
0x0000000000000000000000000000000000000100 and 0x00000000000000000000000000000000000001ff as defined in EIP-7587
In the case the resulting address is calculated within these ranges, the precompile reverts. Authors of the contract are advised to add an arbitrary byte to the runtimebyteCode as a workaround.
Gas cost:
Similar to the CREATE opcode with modifications, where init code cost and deployment_code_execution_cost are 0 as there is no initialization code to execute.
The new contract address is added to the warm addresses.
Rationale
No initcode
Initcode traditionally serves two primary purposes: initializing contract storage and generating runtime bytecode. However, this precompile is designed to bypass both of these steps. The runtime bytecode is directly provided as input, and the intention is to deploy it without any initial storage setup. This design choice is deliberate, aiming to create contracts with immutable bytecode at addresses derived solely from their code content. Consequently, initcode becomes redundant and irrelevant in this context.
Precompile
The choice to implement this functionality as a precompile, rather than a new opcode:
Precompiles can be used by all contracts, and EOAs directly. This EIP mitigates the problems with the CREATE2 opcode that led to the need for the CREATE2 factory.
Introducing a new opcode increases the complexity of the core EVM. Precompiles, being external to the core execution engine, minimize the impact on the protocol’s complexity.
Backwards Compatibility
This EIP introduces a new precompile and does not affect existing contracts or functionality.
Security Considerations
Immutable code:
Any change to the runtime bytecode, would change the address of the contract.