Skip to content

execution: system calls do not touch SystemAddress, drop its BAL filter - #24504

Merged
taratorio merged 2 commits into
mainfrom
chfast/bal-system-address
Oct 2, 2026
Merged

taratorio merged 2 commits into
mainfrom
chfast/bal-system-address

Conversation

@chfast

@chfast chfast commented Oct 2, 2026

Copy link
Copy Markdown
Member

Every zero-value system call touched its caller, which put SystemAddress
into the block access list, and AsBlockAccessList then dropped it unless a
user tx had a non-revertable access to it. That heuristic also dropped real
accesses: a zero-amount withdrawal to SystemAddress and a delegation to it.

By the EIP-7928 spec, being the caller of a system call is not a state
access, so a system call no longer touches its caller (AuRa keeps the touch
for its empty system account) and SystemAddress follows the same BAL rules
as any other address.

IntraBlockState.SubBalance still turns a zero debit of SystemAddress into a
touch on every chain. Block execution never debits SystemAddress (every
caller passes a recovered sender or a contract address), so only RPC calls
from 0xff..fe (eth_call, eth_simulateV1, trace_call) reach it; it is left as
is and its comment corrected.

Open question (Gnosis): AuRa keeps the system-call touch of SystemAddress while the BAL filter is gone, so an AuRa chain activating Amsterdam would carry SystemAddress as an access-only entry in every BAL. No AuRa chain has Amsterdam scheduled; whether Gnosis BALs should include it needs to be agreed with Nethermind.

@chfast
chfast requested a review from taratorio October 2, 2026 10:00
@yperbasis yperbasis added this to the 3.8.0 milestone Oct 2, 2026
@yperbasis yperbasis added the Glamsterdam https://eips.ethereum.org/EIPS/eip-7773 label Oct 2, 2026
@yperbasis
yperbasis requested a balanced review from Copilot October 2, 2026 10:01
@taratorio
taratorio enabled auto-merge October 2, 2026 10:05

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.

Copilot review overview

🟡 Changes recommended

The remaining witness filter can omit SystemAddress proofs required for zero-amount withdrawal replay.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Updates EIP-7928 handling so system-call callers are not treated as state accesses, while preserving AuRa behavior.

Changes:

  • Skip caller touches for non-AuRa zero-value system calls.
  • Remove the SystemAddress-specific BAL filter.
  • Add BAL regressions for withdrawals and EIP-7702 delegation.
File Description
rpc/​jsonrpc/​eth_call.go Updates SystemAddress witness rationale.
execution/​vm/​runtime/​runtime_test.go Tests standard and AuRa system calls.
execution/​vm/​instructions.go Generalizes BALANCE documentation.
execution/​vm/​evm.go Restricts caller touching to AuRa.
execution/​state/​versionedio.go Removes the SystemAddress BAL exception.
execution/​state/​versionedio_test.go Tests ordinary BAL treatment.
execution/​state/​intra_block_state.go Clarifies AuRa touch behavior.
execution/​engineapi/​engine_api_bal_test.go Adds withdrawal and delegation regressions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread rpc/jsonrpc/eth_call.go
Comment on lines +741 to +742
// On AuRa the stateless verifier navigates the system address (system-call msg.sender),
// so its path must be in the witness.
Comment thread rpc/jsonrpc/eth_call.go
Comment on lines +741 to 745
// On AuRa the stateless verifier navigates the system address (system-call msg.sender),
// so its path must be in the witness.
// collectAccessedState drops it per EIP-7928 — a witness-content rule for the
// debug_executionWitness format that does not apply to this op-stream witness.
accessed.Addresses[common.Address(params.SystemAddress.Value())] = struct{}{}
@taratorio

Copy link
Copy Markdown
Member

@taratorio

Copy link
Copy Markdown
Member

also passes ethereum/execution-specs#3681

@taratorio

Copy link
Copy Markdown
Member

@chfast fyi looks like CI has some issues

chfast added 2 commits October 2, 2026 13:57
A zero-amount withdrawal to SystemAddress and a call to an EOA delegated
(EIP-7702) to SystemAddress are state accesses, so by the EIP-7928 spec
SystemAddress must be in the block access list. Both are omitted today.
Every zero-value system call touched its caller, which put SystemAddress
into the block access list, and AsBlockAccessList then dropped it unless a
user tx had a non-revertable access to it. That heuristic also dropped real
accesses: a zero-amount withdrawal to SystemAddress and a delegation to it.

By the EIP-7928 spec, being the caller of a system call is not a state
access, so a system call no longer touches its caller (AuRa keeps the touch
for its empty system account) and SystemAddress follows the same BAL rules
as any other address.

IntraBlockState.SubBalance still turns a zero debit of SystemAddress into a
touch on every chain. Block execution never debits SystemAddress (every
caller passes a recovered sender or a contract address), so only RPC calls
from 0xff..fe (eth_call, eth_simulateV1, trace_call) reach it; it is left as
is and its comment corrected.
@chfast
chfast force-pushed the chfast/bal-system-address branch from 4566a68 to 524670b Compare October 2, 2026 12:00
@taratorio
taratorio added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit a5c6f2d Oct 2, 2026
132 checks passed
@taratorio
taratorio deleted the chfast/bal-system-address branch October 2, 2026 13:21
@Sahil-4555

Copy link
Copy Markdown
Collaborator

Hi, Erigon v3.7.1 (the Sepolia Glamsterdam release) doesn't include #24504. After the fork (Oct 6, 13:53 UTC), any Sepolia user can split it with one 7702 tx that delegates an EOA to 0xff…fe and calls it, because v3.7.1 leaves SYSTEM_ADDRESS out of the BAL. I tested it on the releases: v3.7.1 rejects the geth-built block (BAL mismatch), and reth 2.7.0, geth 1.17.7 and Nethermind 2.1.0 all reject the block v3.7.1 builds. With main (6922d4d), all four agree. The execution-specs #3681 test test_bal_7702_delegation_to_system_address fails on v3.7.1 and passes on main. Could #24504 be backported for a 3.7.2 before the fork?

mh0lt added a commit that referenced this pull request Oct 6, 2026
Reconciles the dependency-wait Block-STM executor and write-side validation
onto current main, on top of Alex's #24456 (refold/write-only-moved-slots) which
is the current branch HEAD. 23 conflicts resolved keeping the branch architecture
and folding main's orthogonal, non-validation changes.

Branch architecture kept (the substantive change):
- dependency-wait scheduler: a worker parks mid-EVM on its read dependency and
  resumes, instead of aborting and re-queueing (exec3_parallel, runDepOrderValidation)
- write-side validation: validity stamped at write time (valStatus, noValueRead)
  rather than re-derived on the read side

main's orthogonal changes folded in:
- domain_shared: no-ctx FlushPendingUpdates, kv.UnderlyingTx, InitBlockOverlay/NewMemoryBatch
- state API drift for main's vm: ResolveCode -> accounts.Code, StopAccessRecording
  (#24555), asOfStateReader.BindsWorkerTx (#23722), trie.EmptyRoot -> empty.RootHash
- FlushVersionedWrites kept 3-arg (branch), normalized tree-wide
- #24504: drop the stale SystemAddress BAL filter in versionedio.AsBlockAccessList
  to match main's auto-merged evm.go (system calls no longer touch their caller);
  without this the auto-merged engineapi SystemAddress BAL tests fail

Removed tests for branch-dropped code (WriteSet.Normalize/MergeInto, revival reader),
main's committer-level prefetch test (#24479, branch wires prefetch differently),
and the two obsolete SystemAddress-filter tests.

ReadStamp reports !ok so the vm frame slot-cache (#24551) stays off: the dep-wait
path parks mid-frame and a dependency can change without a journal bump, which a
journal-stamped cache would miss.

Deferred to follow-ups (main perf coupled to its read-side design): BAL branch-prefetch
(#24479), vm frame slot-cache (#24551), committed-base/warm-read path.
mh0lt added a commit that referenced this pull request Oct 9, 2026
Reconciles the dependency-wait Block-STM executor and write-side validation
onto current main (46 commits since merge-base 48d3a16). 23 conflicts
resolved keeping the branch architecture and folding main's orthogonal,
non-validation changes.

Branch architecture kept (the substantive change):
- dependency-wait scheduler: a worker parks mid-EVM on its read dependency and
  resumes, instead of aborting and re-queueing (exec3_parallel, runDepOrderValidation)
- write-side validation: validity stamped at write time (valStatus, noValueRead)
  rather than re-derived on the read side

main's orthogonal changes folded in:
- domain_shared: no-ctx FlushPendingUpdates, kv.UnderlyingTx, InitBlockOverlay/NewMemoryBatch
- state API drift for main's vm: ResolveCode -> accounts.Code, StopAccessRecording
  (#24555), asOfStateReader.BindsWorkerTx (#23722), trie.EmptyRoot -> empty.RootHash
- FlushVersionedWrites kept 3-arg (branch), normalized tree-wide
- #24504: drop the stale SystemAddress BAL filter in versionedio.AsBlockAccessList
  to match main's auto-merged evm.go (system calls no longer touch their caller);
  without this the auto-merged engineapi SystemAddress BAL tests fail

Removed tests for branch-dropped code (WriteSet.Normalize/MergeInto, revival reader),
main's prefetch test (feature deferred), and the two obsolete SystemAddress-filter tests.

Deferred to follow-ups (main perf coupled to its read-side design, not folded into
this consensus merge): BAL branch-prefetch (#24479), vm frame slot-cache (#24551,
ReadStamp reports !ok so the cache stays off), committed-base/warm-read path.
mh0lt added a commit that referenced this pull request Oct 9, 2026
… (valueStatus)

Reconciles the dependency-wait Block-STM executor + write-side validation onto
current main, keeping the write-time valueStatus net-zero correctness mechanism
(WriteCell.valStatus: ValueUnchanged is the only state skipped from the
domain/commitment projection) rather than the consumer-side StoragesChanged
re-derivation of #24456.

Branch architecture kept: dependency-wait scheduler (park mid-EVM on a read
dependency, not abort+re-queue) and write-side validation (valueStatus stamped at
write, noValueRead). main's orthogonal changes folded in (no-ctx FlushPendingUpdates,
ResolveCode->accounts.Code, StopAccessRecording, BindsWorkerTx, empty.RootHash,
3-arg FlushVersionedWrites, #24504 SystemAddress BAL filter removal, writeBalanceVersioned
prev param, CreateAccount no-heap-alloc, memreader multi-block BodyWithRawTransactions).
keithchew pushed a commit to keithchew/erigon that referenced this pull request Oct 11, 2026
…AL filter (erigontech#24583)

Cherry-pick of erigontech#24504 to release/3.7.

The upstream BAL and zero-value system-call regressions fail on the
release base and pass with this backport. Resolved a blank-line conflict
in removed BAL-filter tests; the code changes match upstream.

Co-authored-by: Paweł Bylica <pawel@ethereum.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Glamsterdam https://eips.ethereum.org/EIPS/eip-7773

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants