EIP-3607 Blocking transactions from addresses with deployed code (Reject transactions from senders with deployed code)

Final · Security & privacy · EIP status Final · created 2021-06-10

Declares invalid any transaction whose sending account is an address that already has contract code deployed. It is a rule that prevents fund theft attacks that exploit address collisions.

Why it is needed

Ethereum addresses are fairly short at 160 bits, so with roughly 2^80 operations an attacker can create a collision in which an externally owned account (EOA, a regular account controlled by a private key) and a contract share the same address. The source estimates this is feasible within a year for about 10 billion dollars in hardware and electricity costs. An attacker could deploy a contract that looks safe, such as a token wrapper or an AMM, at such a collision address to gather user funds, and then drain that money using the private key for the same address. However, the Yellow Paper did not specify the case of sending a transaction from an account with deployed code, and most clients allowed such transactions. This EIP fixes in the rules that such transactions are always prohibited, blocking the most serious attack.

What changes

Today

After EIP-3607

Who is affected

In depth

Specification: code hash check and rejection rule

A transaction whose tx.sender has a CODEHASH different from EMPTYCODEHASH MUST be rejected as invalid. EMPTYCODEHASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, the hash of empty code. Clients must reject an invalid transaction and not include it in a block, and a block that contains such a transaction must be treated as invalid. In other words, this is a consensus rule that applies to both individual transaction validation and block validation.

Attack cost estimate: 2^80 operations and cycle finding

If an attacker generates 2^80 EOA keys and simulates a contract deployment from each EOA, about one collision is expected. The naive approach would need to store 2^80 addresses, which takes 2.4*10^25 bytes (24 yottabytes) of memory, but a cycle finding algorithm can find a collision without large storage. The original text estimates that an investment of about 10 billion dollars in hardware and electricity could find a collision between a contract and an EOA in roughly one year. Moving to 256-bit addresses would raise the complexity to 2^128, which makes the attack infeasible for the foreseeable future, but the background is that this EIP can solve the problem now, even with 160-bit addresses.

Nature: a clarification of undefined behavior, not an upgrade

It has always been an expected property that a contract account's behavior is constrained by its code, meaning the account's funds cannot suddenly be spent with some private key. In the past, it was only implicitly assumed that 160-bit addresses give enough collision resistance for such a case to be impossible. The original text therefore explains that this EIP should be read not as an explicit upgrade of the consensus rules, but as a clarification of protocol behavior for a case that was previously undefined.

Three remaining attack paths

This EIP blocks only the most serious path and does not eliminate every collision attack. First, an attack remains in which users are persuaded to send funds to a pre-deployment address. Some applications, such as state channels, require this behavior. Second, if a chain reorganization (reorg) after the contract deployment removes the deployment transaction, the funds can be accessed with the private key. Third, even if a contract was announced as burning its contents, such as ERC20 tokens, through selfdestruct, the funds remain accessible with the key of that address. The original text considers these scenarios much harder to exploit and less profitable, so they are unlikely to be economically viable.

Reference implementation: EOA check after the nonce check

Add this check to the state transition checks after verifying that the sender account's nonce is correct. The sender account is the address recovered from the transaction signature. If the sender account's CodeHash differs from EmptyCodeHash, return ErrSenderNoEOA. A diff applying this to go-ethereum is provided as an asset of the original text. The test case allocates 1 ether and the code 0xB0B0FACE to the address 0x71562b71999873DB5b286dF957af199Ec94617F7 in genesis, and specifies that every transaction signed with the corresponding private key must be rejected and not included in a block.

Compatibility: can be a soft fork, RPC exceptions allowed

The original text considers it unlikely that this attack has already happened on mainnet, because it would have become known if it had. There is also no reason to use a contract that is also an EOA as a feature. The same effect can be obtained by adding a method to the contract, and nobody would spend billions of dollars to find a collision. However, private networks may have such accounts in genesis, so they need to be checked. Some multisig contracts use eth_call or eth_estimateGas as if sent from their own address, so clients may turn the rule off for these RPC calls. Because the new validity rule is a strict subset of the existing rules, it can be implemented as a soft fork, and because it only invalidates some previously valid transactions, it is a pure security hardening with no security downsides. This EIP has been finalized with Final status.

Original EIP · ← EIPs