Skip to content
25 changes: 16 additions & 9 deletions EIPS/eip-7708.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
eip: 7708
title: ETH transfers emit a log
description: All ETH transfers emit a log
author: Vitalik Buterin (@vbuterin), Peter Davies (@petertdavies)
author: Vitalik Buterin (@vbuterin), Peter Davies (@petertdavies), Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Carson (@carsons-eels)
discussions-to: https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034
status: Stagnant
status: Draft
type: Standards Track
category: Core
created: 2024-05-17
Expand All @@ -20,24 +20,31 @@ Logs are often used to track when balance changes of assets on Ethereum. Logs wo

## Specification

### Parameters
### ETH transfer logs

* `MAGIC`: `TBD`
A log, identical to a LOG3, is issued for:

### Functionality
- Any nonzero-value-transferring transaction, before any other logs created by EVM execution
- Any nonzero-value `CALL`, at the time that the value transfer executes
- Any nonzero-value-transferring `SELFDESTRUCT`, at the time that the value transfer executes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some edge cases to think about here:

  1. a selfdestruct-to-self for a contract created in the same transaction will immediately burn that balance.
  2. a selfdestruct-to-self for a previously-existing contract will result in no net balance difference even if it is "nonzero-value-transferring"

For the sake of simplicity, I suggest we treat both cases as a transfer of value to self. There is not really a proper way to indicate that the balance is being burned in the case of 1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible from solely the information in the logs (whatever is proposed to be emitted here), the transactions (amount, max prio fee), the receipts (gas used), the block header (base block fee, withdrawals), and the genesis balance (or, whatever the balance was at the time of the fork when this activates) to reconstruct the account balance accurately, in all cases?

Or do we need a second log for burning ETH in these situations?

@jwasinger jwasinger Jan 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we would need a special log to indicate burn in the case of 1.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the case of 2. we can just mark this as a transfer of zero value to self. It's the only case where a value transfer log of this type would be allowed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The special log could either be a LOG2 Burn(from, amount), or reuse the Transfer log (with a destination of system address). The Burn log would probably be cleaner, as it doesn't actually increase the balance of the system address. The Transfer log would be a bit more consistent with ERC20 (no need to combine the result from multiple log topics); but for ERC20 it actually gets credited to zero/burnaddress so it's not the same semantics.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, Selfdestruct(from, amount)? To indicate the special operation? Then, (1) and (2) would be the same?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I like that

Or, Selfdestruct(from, amount)? To indicate the special operation? Then, (1) and (2) would be the same?

This could work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Selfdestruct(from, amount).

@benaadams benaadams Jan 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is not really a proper way to indicate that the balance is being burned in the case of 1.

Isn't burn for ETH a transfer to 0x0? (to null) like emission is a transfer from 0x0

Symbolic burns transfer to 0xdEaD but that's not what we are talking about here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a Transfer, the value is actually credited to the destination.
This Selfdestruct doesn't credit anything. One couldn't reconstruct the actual value of the zero / 0xdead address if the special case isn't denoted as such.


Whenever (i) a nonzero-value `CALL`, (ii) a nonzero-value-transferring `SELFDESTRUCT`, or (iii) a nonzero-value-transferring transaction takes place, issue a log, identical to a LOG3, with three topics: (i) `MAGIC`, (ii) the sender address, (iii) the recipient address. The log data is a big-endian 32-byte encoding of the transfer value.

The `LOG` of a value-transferring transaction should be placed before any logs created by EVM execution. The other two `LOG`s are placed at the time that the value transfer executes.
| Field | Value |
| - | - |
| `address` | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](./eip-4788.md)) |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 0x000..000 better for Rlp encoding?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a byte array, not an int, so does not use varlen encoding.

RLP encoding is 0x94 + 20byte address regardless of value.

There is also an idea of 0xeee...eee: https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034/46?u=metony

Right now it just uses the same system address from EIP-4788

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer 0x0 as is ETH the asset emitting the log; rather than the system

But not strongly held

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, worth a broader discussion. Keep in mind can also change the value lateron if there are multiple opinions about it. For now, would just settle with any one so that implementations can continue.

@Carsons-Eels Carsons-Eels Jan 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if I have this correctly, these are the rough meanings and benefits of each:

  • 0x000...000: The null address is often used to mean "not a contract" and might take less storage on disk.
    • "ETH is the asset emitting the log; rather than the system"
    • Highly compressible (but does not matter for RLP encoding)
  • 0xeee...eee: Some contracts use this to represent native ether, when an address is required.
    • Many Eth apps already use it
    • eth_simulateV1 (in multiple clients) logs ETH transfers with it
    • Backwards Compatibility, since it would be the same as ERC-20 transfer logs
    • De facto standard when contracts support both tokens & ETH
    • Follows ERC-7528: ETH (Native Asset) Address Convention
  • 0xfff...ffe: Since moving ether is done by the "system", the system contract should emit it.
    • Already in use as a system address for EIP-4788: Beacon block root in the

For now I'm going to implement 0xfff...ffe in the spec branch, since that's what this reads. I'll ask for responses from client teams on which they prefer. I can update the spec branch later, we can keep this as is for now or you can update it to match @etan-status your choice. Either way, you're right, needs discussion.

@benaadams can I consider your opinion representative of Nethermind as a whole?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not "my choice", 0xfff..e was the only one depicting a concept of an address for "system originated" in the EIPs.

If the tests use 0xeee..e, can also start with that one. Is confusing if EIP doesn't match the tests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the tests use 0xeee..e, can also start with that one. Is confusing if EIP doesn't match the tests

It was mentioned by @Carsons-Eels two comments above this that the specs and tests will use 0xfff...e and is currently in PR (here). The value in this PR is currently 0xeee...e (here).

Can we agree before merging? From this thread, the agreement looks to be 0xfff...e? Let's go with this for now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

His comment was edited; it used to say 0xeee..e

Will do 0xfff...e then to match his latest comment. Thanks for catching it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

His comment was edited; it used to say 0xeee..e

Ah! That makes sense then :) Thanks!

Comment thread
etan-status marked this conversation as resolved.
Outdated
| `topics[0]` | `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` (`keccak256('Transfer(address,address,uint256)')`) |
| `topics[1]` | `from` address (zero prefixed to fill uint256) |
| `topics[2]` | `to` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |
Comment thread
etan-status marked this conversation as resolved.

## Rationale

This is the simplest possible implementation that ensures that all ETH transfers are implemented in some kind of record that can be easily accessed through making RPC calls into a node, or through asking for a Merkle branch that is hashed into the block root. The log type is compatible with the ERC-20 token standard, but does not introduce any overly-specific ERC-20 features (eg. ABI encodings) into the specification.

### Open questions

1. Should withdrawals also trigger a log? If so, what should the sender address be specified as?
1. Magic value used for `address` and `topics[0]`? For address: (a) `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` (same as `eth_simulateV1`), (b) `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](./eip-4788.md)), (c) zero address
Comment thread
etan-status marked this conversation as resolved.
Outdated
2. Should fee payments trigger a log? It would ensure "completeness", in the sense that you can compute the exact current balance table by watching logs, but it would greatly increase the number of logs, perhaps to an unacceptably high amount.
3. Should withdrawals also trigger a log? They are not associated with transactions.

## Backwards Compatibility

Expand Down
Loading