Skip to content

Commit

Permalink
EIP: Reject transactions from senders with deployed code (ethereum#3607)
Browse files Browse the repository at this point in the history
Do not allow transactions for which `tx.sender` has any code deployed, i.e. `tx.sender` has `CODESIZE != 0`
  • Loading branch information
dankrad authored and PhABC committed Jan 25, 2022
1 parent 227675c commit 494336a
Showing 1 changed file with 94 additions and 0 deletions.
94 changes: 94 additions & 0 deletions EIPS/eip-3607.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
eip: 3607
title: Reject transactions from senders with deployed code
author: Dankrad Feist (@dankrad), Dmitry Khovratovich (@khovratovich), Marius van der Wijden (@MariusVanDerWijden)
discussions-to: https://github.com/ethereum/EIPs/issues/3608
status: Draft
type: Standards Track
category: Core
created: 2021-06-10
---

## Simple Summary

Do not allow transactions for which `tx.sender` has any code deployed, i.e. `tx.sender` has `CODESIZE != 0`

## Abstract

Ethereum addresses are currently only 160 bits long. This means it is possible to create a collision between a contract account and an Externally Owned Account (EOA) using an estimated `2**80` computing operations, which is feasible now given a large budget (ca. 10 billion USD). The fix in this EIP prevents the worst possible attack, where a safe looking contract (e.g. a token wrapper or an AMM-type contract) is deployed to attract user funds, which can then be spent using the EOA key for the same address. The fix is to never allow to use an address that already has code deployed as an EOA address.

## Motivation

### Generating address collisions

By creating keys for `2**80` EOAs and simulating the deployment of `2**80` contracts from these EOAs (one each), one expects to find about one collision where an EOA has the same address as one contract.

This very simple form of the attack requires the storage of `2**80` addresses, which is a practical barrier: It would require `2.4*10**25` bytes of memory (24 Yottabyte). However, there are cycle finding algorithms that can perform the collision search without requiring large amounts of storage. An estimate for the complexity has been made [here](https://hackmd.io/Vzhp5YJyTT-LhWm_s0JQpA). We estimate that a collision between a contract and an EOA could be found in about one year with an investment of ca. US$10 billion in hardware and electricity.

### Background

There is currently a discussion to move to 256-bit addresses on Ethereum, which would increase collision resistance to a complexity of `2**128` which is currently thought infeasible for the foreseeable future. However, with 160 bit addresses, the collision problem can be effectively solved now, as demonstrated above.

Most attacks that can occur via address collisions are quite impractical: They involve users sending funds to an address before a contract is deployed. This is a very rare application in practice and users can easily circumvent the attack by never sending funds to a contract until it has been safely deployed with enough confirmations.

However, the yellow paper does not explicitly specify how a client should handle the case where a transaction is sent from an account that already has contract code deployed; presumably because this was considered infeasible at the time. The assumption is that most client would allow this transaction in their current state.

This EIP is to specify this behaviour to always forbid such transactions. This fixes most realistic or serious attacks due to address collisions.


## Specification

Any transaction where `tx.sender` has a `CODESIZE != 0` MUST be rejected as invalid.

## Rationale

We note that it was always the expected that a contract account's behaviour is constrainted by the code in that contract -- which means that the account's funds should not suddenly be spendable by some private key. It was just implicitly assumed in the past that a 160 bit address length is enough to provide collision resistance, and thus that this case could never occur. In that sense, this EIP should be seen as a clarification of protocol behaviour in a previously undefined case rather than an explicit upgrade of consensus rules.

This does not exclude all possible attack vectors, only the most serious one. Further possible attack vectors via address collisions between contracts and EOAs are:
1. An attacker can convince a user to send funds to an account before it is deployed. Some applications require this behaviour (e.g. state channels).
2. A chain reorg can happen after a contract is deployed. If the reorg removes the contract deployment transaction the funds can still be accessed using the private key.
3. A contract can self desctruct, with the stated intention that ERC20s (or other tokens) in the contract would be burned. However, they can now be accessed by a key for that address.

All these scenarios are much harder to exploit for an attacker, and likely have much lower yield making the attacks unlikely to be economically viable.

## Backwards Compatibility

It is unlikely that an attack like this has already occurred on the Ethereum mainnet, or we would very likely have heard of it. It is inconceivable that someone would use this as a "feature" to make a contract an EOA at the same time, when they could simply do this by adding some methods to the contract instead of spending billions on building hardware to find hash collisions.

Private networks may have deployed contracts which also work as EOAs at genesis and should check that this upgrade does not impact their workflows.

## Test Cases

Given a genesis allocation of
```
Address: 0x71562b71999873DB5b286dF957af199Ec94617F7
Balance: 1000000000000000000 // 1 ether
Nonce: 0,
Code: 0xB0B0FACE",
```
Every transaction send by the private key corresponding to `0x715656...` (
`b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291`) fails.

A set of test cases can be found [here](https://github.com/ethereum/tests/pull/879)

## Reference Implementation

The following check must be added to the state transition checks after checking that the nonce of the sender is correct.
```go
// Make sure the sender is an EOA
if codesize := st.state.GetCodeSize(st.msg.From()); codesize != 0 {
return ErrSenderNoEOA
}
```

An implementation in go-ethereum can be found [here](https://github.com/ethereum/go-ethereum/pull/23002)

## Security Considerations

This EIP is a strict security upgrade: It simply makes some transactions that were formerly valid now invalid. There is no legitimate use for such transactions, so there should be no security downsides.

This EIP can be implemented as a soft fork because the new validity rules are a strict superset of the previous validity rules.


## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 comments on commit 494336a

Please sign in to comment.