EIP-7610 Reject contract creation at addresses with leftover storage (Revert creation in case of non-empty storage)
Proposed for Inclusion · EVM & execution · EIP status Last Call · created 2024-02-02
Allows a contract to be created at an address only if its storage is empty, in addition to its nonce and code. Creation fails at an address where values remain in storage.
Why it is needed
Ethereum rests on the premise that a deployed contract does not change. To uphold this, EIP-684 allowed a new contract to be created only when the target address has a nonce of 0 and a code length of 0. However, these two conditions alone are not enough. Before EIP-161 took effect, the nonce of a newly deployed contract stayed at 0, so if the constructor wrote storage values, an account could end up with a nonce of 0 and a code length of 0 but with data remaining in storage. There are currently 28 such contracts on mainnet. Under EIP-684, such addresses are still in a deployable state, so how to handle them was unclear, and implementations diverged, with some clients implementing an account reset solely to pass tests. This EIP closes the gap by making creation fail whenever storage is non-empty.
What changes
Today
- If the nonce is 0 and there is no code, a contract can be created at that address even when values remain in storage
- The behavior when deploying to an address with leftover storage was unclear, so implementations differed between clients
- There are 28 contracts on mainnet with a nonce of 0 and no code but with storage remaining
After EIP-7610
- A contract can be created only when storage is empty, in addition to the nonce and code
- At an address with leftover storage, creation fails as if an invalid opcode were encountered
- This rule applies retroactively to all past blocks
Who is affected
- Client teams: An empty storage check is added to the creation condition checks, and there is no longer a need to keep the account reset implementation that was added only to pass tests.
- Contract developer: The immutability of deployed code is enforced as an explicit rule.
- Ordinary users: Unless you deploy to one of the 28 special addresses where only storage remains, you will notice no change.
- EIP-7702 users and wallets: An account with an authorization applied has its nonce incremented, which conflicts with the deployment conditions to begin with, so it is not affected.
In depth
Creation failure conditions: nonce, code, and storage
Whether contract creation is attempted by a creation transaction, the CREATE opcode, the CREATE2 opcode, or for any other reason, creation MUST fail if the target address meets any of the following: the nonce is non-zero, the code length is non-zero, or the storage is non-empty. The failure is handled as if the first byte of the init code were an invalid opcode. This rule MUST apply retroactively to all existing blocks. The first two conditions were already defined by EIP-684, and what this EIP adds is the third condition, the empty storage requirement.
Why it supplements EIP-684: 28 accounts with nonce 0 but leftover storage
EIP-684 requires only two things for deployment: the target address has a nonce of 0 and a code length of 0. However, before EIP-161 took effect, the nonce of a newly deployed contract stayed at 0. So by setting a storage slot in the constructor, it was possible to create a contract with a nonce of 0 and a code length of 0 whose storage is non-empty. As of the time the source was written, 28 such contracts exist on Ethereum mainnet. Under EIP-684, these addresses are still in a redeployable state, so this EIP closes the gap by adding an empty storage condition.
No impact on EIP-7702
This EIP does not affect EIP-7702. In EIP-7702, the authority's nonce always increases after an authorization is applied. Contract deployment is possible only when the nonce is 0, so an account with an authorization applied already conflicts with the deployment conditions. Therefore, adding the empty storage condition does not change the behavior of EIP-7702.
Test status and client implementation inconsistencies
Many tests covering scenarios of deploying to a target with non-empty storage already exist in the ethereum tests repository and execution spec tests. These tests have long been regarded as a problem. Reth and EELS implemented a kind of account reset solely to pass the tests, while Py-evm declared the situation impossible and did not implement an account reset at all. The source holds that refilling the existing tests can provide sufficient test coverage for this EIP.
Security nature and how it applies
This EIP is a security upgrade that enforces the immutability of deployed code. Because it is a change to the execution layer, it requires a hard fork. However, the specification requires the creation failure rule itself to apply retroactively to all existing blocks, not from a particular block onward. If no deployment to an address with leftover storage has ever actually occurred, the execution results of past blocks do not change, and it amounts to only tidying up the definition of the rule consistently.
Progress: removed from Glamsterdam, then fully cancelled
The original document's status is Last Call (deadline 2024-11-20). The fork schedule included the following decisions. On 08.17 at ACDT #92, it was agreed to remove EIP-7610 from Glamsterdam. Geth and Reth already skip the relevant tests, so the judgment was that behavior does not change. On 08.20 at ACDC #185, it was cancelled outright rather than postponed. EIP-8253 in Hegotá removes the root cause, so the rule itself becomes unnecessary. On 09.10 at ACDE #245, it was decided that EIP-8253 would not be added late to Glamsterdam and would instead be handled in Hegotá as originally planned. On 09.14 at ACDT #96, legacy test PR #18 was merged, reverting to the handling of collisions used by the Yellow Paper and EIP-684. The collision handling for the Block Access List (BAL) is left undefined until EIP-8253 is settled.