feat: EIP-7708 — synthetic ETH transfer/burn logs (Amsterdam)#13
Merged
garyschulte merged 4 commits intoConsensys:mainfrom Apr 1, 2026
Merged
feat: EIP-7708 — synthetic ETH transfer/burn logs (Amsterdam)#13garyschulte merged 4 commits intoConsensys:mainfrom
garyschulte merged 4 commits intoConsensys:mainfrom
Conversation
garyschulte
requested changes
Mar 20, 2026
Collaborator
garyschulte
left a comment
There was a problem hiding this comment.
LGTM, but cursor bot is on top of the topic error and burn log emission issue
Emits Transfer and Burn logs from address 0xff..fe on all ETH movements for Amsterdam+. Transfer logs are emitted immediately on CALL/CREATE value transfers and SELFDESTRUCT-to-different-address. Burn logs are emitted immediately for SELFDESTRUCT-to-self (same-tx-created or pre-Cancun). Pending burns are checkpointed and reverted with call frames. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous implementation had two bugs: 1. `addPendingBurn()` was never called — `pending_burns` was always empty, so `emitBurnLogs()` in postExecution was a no-op. The only burn logs emitted were at SELFDESTRUCT opcode time via `addEip7708BurnLog` directly, missing any ETH that arrived at the selfdestructed address afterwards. 2. Accounts that SELFDESTRUCT to a *different* beneficiary (and are therefore in `accounts_to_delete`) were never registered for the finalization burn check, even though they can receive ETH after the opcode returns. Per the EELS reference (amsterdam/vm/instructions/system.py and fork.py): - At opcode time: emit a Burn log for the balance held *now* (self-to-self), or a Transfer log for the ETH moved to a different beneficiary. - At finalization (after coinbase priority-fee payment): for every account in `accounts_to_delete`, re-read its current `evm_state` balance and emit a *second* Burn log if non-zero. This captures ETH that arrives post-opcode: payer contracts calling into the destructed address, or the coinbase contract receiving its miner tip. This produces the two separate Burn log entries that the spec tests expect for cases like `test_selfdestruct_finalization_after_priority_fee` (coinbase SD + priority fee) and `test_finalization_burn_logs` (post-SD payer funding). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The last 8 bytes of EIP7708_BURN_TOPIC were 717fce85f713ab57 instead of
71a0fdb75d397ca5.
keccak256("Burn(address,uint256)")
= 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5
All Burn logs emitted with the wrong constant would be unrecognizable by
any conforming indexer or client.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: garyschulte <garyschulte@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Implements EIP-7708 for the Amsterdam hardfork.
Emits synthetic
TransferandBurnlogs from the reserved address0xff..fffffffffffffffeon all ETH movements, making ETH flows visible in the log stream without requiring ERC-20 wrapping.Log types
Transfer(address indexed from, address indexed to, uint256 amount)— emitted for every ETH transfer (CALL, CREATE, TX value, SELFDESTRUCT to different address)Burn(address indexed addr, uint256 amount)— emitted when ETH is destroyed (SELFDESTRUCT to self on a same-tx-created account or pre-Cancun)Burn log emission — two-phase approach
Per the EELS reference (
amsterdam/vm/instructions/system.py+fork.py):SELFDESTRUCTexecutes, a Burn log is emitted immediately for the balance held at that moment.postExecution), for every account inaccounts_to_delete, the currentevm_statebalance is re-read. If non-zero (ETH arrived after the opcode — payer call or coinbase tip), a second Burn log is emitted.This produces two separate Burn log entries for the same address when applicable, exactly matching the EELS spec.
Burn logs from the finalization pass are emitted in ascending address order, matching EELS.
Changes
src/primitives/main.zig—EIP7708_LOG_ADDRESS,EIP7708_TRANSFER_TOPIC,EIP7708_BURN_TOPICconstantssrc/context/journal.zig—PendingBurnstruct,pending_burnslist onJournalInner, helper methods (addEip7708TransferLog,addEip7708BurnLog,addPendingBurn,emitBurnLogs), checkpoint/revert support,SELFDESTRUCTlog emissionsrc/interpreter/host.zig— Transfer log emission on precompile calls, regular CALLs, and CREATEsrc/handler/mainnet_builder.zig— Transfer log for TX-level value transfer;emitBurnLogs()call inpostExecutionPart of Amsterdam hardfork
Related PRs: EIP-7843 (SLOTNUM), EIP-8024 (DUPN/SWAPN/EXCHANGE), EIP-7954 (max code size), EIP-8037 (state gas reservoir)
Note
Medium Risk
Changes EVM execution semantics around log emission for ETH movements (CALL/CREATE/TX value and
SELFDESTRUCT) and adds a deferred finalization pass, so incorrect ordering/checkpointing could break spec compliance or log expectations.Overview
Implements EIP-7708 synthetic ETH flow logs for Amsterdam by emitting
Transferlogs on all value movements (tx value transfer,CALL/precompile calls, andCREATE) andBurnlogs for qualifyingSELFDESTRUCTcases.Adds a deferred-burn mechanism in the journal (
pending_burnswith checkpoint/revert support) and apostExecutionfinalization step to sort addresses and emit any additionalBurnlogs after coinbase payment.Also centralizes blob base fee update fraction resolution via
CfgEnv.blobBaseFeeUpdateFraction()in the spec test runner and updates a create-path error return toCreateResult.failure().Written by Cursor Bugbot for commit e1c0f99. This will update automatically on new commits. Configure here.