Skip to content

Misc Amsterdam eip fixes#4251

Merged
gabrocheleau merged 6 commits into
masterfrom
amsterdam-fixes
Mar 6, 2026
Merged

Misc Amsterdam eip fixes#4251
gabrocheleau merged 6 commits into
masterfrom
amsterdam-fixes

Conversation

@ScottyPoi

@ScottyPoi ScottyPoi commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

This PR fixes several Amsterdam EIP-7708 / EIP-7928 integration issues across EVM, VM, and BAL serialization.

Fixes failling test fixtures from v500_mixed_with_other_eips


  • Align EIP-7708 log emission with the execution-spec fixtures:

    • emit transfer logs for all non-DELEGATECALL value transfers, including self-transfer and CALLCODE
    • prepend transfer logs for precompile calls
    • emit SELFDESTRUCT-to-self logs for nonzero balances even when EIP-6780 prevents balance zeroing
    • adjust dynamic gas handling so the OOG boundary matches expected account-creation behavior
  • Fix block-level access list serialization and cleanup:

    • canonicalize quantity-like BAL fields during RLP serialization (0x / 0x0 / 0x00 / odd-length values)
    • sort BAL entries canonically before hashing
    • preserve prior transaction balance history when removing net-zero balance changes
    • include SYSTEM_ADDRESS only when it has real BAL content
  • Exclude synthetic BAL writes introduced by post-block system calls:

    • snapshot/restore the SYSTEM_ADDRESS BAL entry around EIP-7002 / EIP-7251 system runCall() execution so internal caller bookkeeping does not leak into the block BAL
  • Add coverage:

    • BAL unit tests for canonical quantity serialization and conditional system-address inclusion
    • execution-spec blockchain assertion that fixture BAL JSON hashes to the header blockAccessListHash

Copilot AI review requested due to automatic review settings February 28, 2026 03:41

Copilot AI left a comment

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.

Pull request overview

Fixes Amsterdam EIP-7708 / EIP-7928 integration mismatches by adjusting EVM log emission semantics, tightening BAL (block-level access list) canonical serialization/hashing rules, and preventing synthetic system-call BAL touches from leaking into block BAL outputs.

Changes:

  • Update EIP-7708 transfer/selfdestruct log emission behavior (including precompile log ordering) and adjust EIP-7928 CALL gas OOG boundary behavior.
  • Canonicalize BAL serialization (quantity-like normalization, canonical sorting, system-address conditional inclusion) and preserve prior tx balance history on net-zero cleanup.
  • Add tests asserting BAL canonical serialization and that fixture BAL hashes to header.blockAccessListHash.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/vm/test/tester/executionSpecBlockchain.test.ts Adds an assertion that fixture BAL hash matches the block header blockAccessListHash.
packages/vm/src/requests.ts Snapshots/restores the SYSTEM_ADDRESS BAL entry around EIP-7002/EIP-7251 system runCall() to avoid leaking synthetic touches.
packages/util/test/bal.spec.ts Adds BAL unit tests for canonical quantity-like encoding and conditional SYSTEM_ADDRESS omission/inclusion.
packages/util/src/bal.ts Implements BAL canonical ordering/normalization updates, net-zero balance cleanup refinement, and conditional SYSTEM_ADDRESS inclusion.
packages/evm/src/opcodes/gas.ts Adjusts EIP-7928 CALL gas checking so new-account gas can OOG after committing target access.
packages/evm/src/interpreter.ts Ensures EIP-7708 selfdestruct-to-self log can emit even when EIP-6780 prevents balance zeroing.
packages/evm/src/evm.ts Emits EIP-7708 transfer logs for all non-DELEGATECALL value transfers and prepends logs for precompile calls.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 167 to +172
const results = await vm.evm.runCall({
caller: systemAddress,
gasLimit: vm.common.param('systemCallGasLimit'),
to: consolidationsAddress,
})
restoreSystemAccessEntry(vm, systemAddressHex, balSnapshot)

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

Same issue as above: if vm.evm.runCall() throws, the BAL snapshot for SYSTEM_ADDRESS won't be restored. Use a try/finally to ensure restoreSystemAccessEntry() always executes.

Suggested change
const results = await vm.evm.runCall({
caller: systemAddress,
gasLimit: vm.common.param('systemCallGasLimit'),
to: consolidationsAddress,
})
restoreSystemAccessEntry(vm, systemAddressHex, balSnapshot)
let results
try {
results = await vm.evm.runCall({
caller: systemAddress,
gasLimit: vm.common.param('systemCallGasLimit'),
to: consolidationsAddress,
})
} finally {
restoreSystemAccessEntry(vm, systemAddressHex, balSnapshot)
}

Copilot uses AI. Check for mistakes.
Comment thread packages/util/src/bal.ts
Comment on lines 243 to +255
const storageChanges = (
Object.entries(data.storageChanges) as [BALStorageKeyHex, BALRawStorageChange[]][]
)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([slot, changes]) => [normalizeHexForRLP(slot), changes.sort((a, b) => a[0] - b[0])])
.sort((a, b) => compareLexicographicHexOrBytes(a[0], b[0]))
.map(([slot, changes]) => [
normalizeHexForRLP(slot),
changes
.sort((a, b) => a[0] - b[0])
.map(
([index, value]) =>
[index, normalizeBytesForRLPQuantity(value)] as BALRawStorageChange,
),
])

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

storageChanges are sorted before slot normalization (normalizeHexForRLP(slot)), but normalization strips leading zeros. If JSON/inputs contain padded slots (e.g. 0x00ff), the pre-normalization order can differ from the canonical post-normalization order, producing a non-canonical RLP/hash. Sort using the normalized slot bytes (e.g. normalize first, then sort on the normalized value) to ensure deterministic canonical ordering.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +133
const systemAddressHex = systemAddress.toString()
const balSnapshot = cloneSystemAccessEntry(vm, systemAddressHex)
const results = await vm.evm.runCall({
caller: systemAddress,
gasLimit: vm.common.param('systemCallGasLimit'),
to: withdrawalsAddress,
})
restoreSystemAccessEntry(vm, systemAddressHex, balSnapshot)

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

restoreSystemAccessEntry() is not guaranteed to run if vm.evm.runCall() throws (e.g., an invalid precompile can throw from runPrecompile). This can leak the system address BAL entry into subsequent processing. Wrap the runCall() in a try { ... } finally { restoreSystemAccessEntry(...) } so restoration happens even on exceptions.

Copilot uses AI. Check for mistakes.

@gabrocheleau gabrocheleau left a comment

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.

Hey @ScottyPoi ! nice work.
Would you be able to fix the build issue? The issue is related to the request.ts file.

Also I'm noticing some AI copilot comments on the PR related to try/catch & restoration. Would be great if you can evaluate if those are relevant or not. Would then give this a manual review and merge.
Thanks

@codecov

codecov Bot commented Mar 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.58824% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.25%. Comparing base (f428577) to head (b5bfefc).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 87.33% <ø> (ø)
blockchain 88.85% <ø> (ø)
common 93.44% <ø> (ø)
evm 61.24% <75.00%> (-0.01%) ⬇️
mpt 89.65% <ø> (ø)
statemanager 78.10% <ø> (ø)
static 91.35% <ø> (ø)
tx 88.01% <ø> (ø)
util 80.81% <90.47%> (+0.48%) ⬆️
vm 55.61% <31.81%> (-0.30%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Mar 5, 2026

Copy link
Copy Markdown

📦 Bundle Size Analysis

Package Size (min+gzip) Δ
binarytree 17.5 KB 🔴 +0.0 KB (+0.03%)
block 43.7 KB 🟢 -0.0 KB (-0.01%)
blockchain 69.8 KB ⚪ ±0%
common 25.4 KB ⚪ ±0%
devp2p 17.7 KB ⚪ ±0%
e2store 87.2 KB ⚪ ±0%
ethash 61.6 KB ⚪ ±0%
evm 62.3 KB 🔴 +0.2 KB (+0.27%)
genesis 272.2 KB ⚪ ±0%
mpt 21.9 KB ⚪ ±0%
rlp 1.7 KB ⚪ ±0%
statemanager 41.3 KB ⚪ ±0%
testdata 43.8 KB ⚪ ±0%
tx 20.8 KB 🔴 +0.0 KB (+0.03%)
util 13.1 KB 🔴 +0.1 KB (+1.10%)
vm 154.5 KB 🔴 +0.3 KB (+0.21%)
wallet 15.0 KB ⚪ ±0%

Values are minified+gzipped bundles of each package entry. Workspace deps are bundled; external deps are excluded.

Generated by bundle-size workflow

@gabrocheleau gabrocheleau merged commit e143fda into master Mar 6, 2026
35 of 36 checks passed
@holgerd77 holgerd77 deleted the amsterdam-fixes branch March 10, 2026 14:22
web3iocore pushed a commit to tronweb3/tvmjs-monorepo that referenced this pull request Jun 1, 2026
* evm: align 7708 logs

* util: normalize BAL output

* vm: ignore system call BAL

* test(vm): check fixture BAL hash

* fix linting

---------

Co-authored-by: ScottyPoi <scott.simpson@ethereum.org>
Co-authored-by: Gabriel Rocheleau <18757482+gabrocheleau@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants