Skip to content

Commit d91b18b

Browse files
fselmonerolation
andcommitted
fix(specs): Fix zero value withdrawals BAL tracking (#29)
* fix(specs): Fix zero value withdrawals BAL tracking * docs(specs): rename 'finalize' to 'normalize' in comments * docs(specs): remove reference to uint128 for balance tracking --------- Co-authored-by: Toni Wahrstätter <[email protected]> Co-authored-by: Toni Wahrstätter <[email protected]>
1 parent b4648cd commit d91b18b

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

src/ethereum/forks/amsterdam/block_access_lists/tracker.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class StateChangeTracker:
9797
"""
9898
Cache of pre-transaction balance values, keyed by address.
9999
This cache is cleared at the start of each transaction and used by
100-
finalize_transaction_changes to filter out balance changes where
100+
normalize_balance_changes to filter out balance changes where
101101
the final balance equals the initial balance.
102102
"""
103103

@@ -293,7 +293,7 @@ def capture_pre_balance(
293293
to ensure we capture the pre-transaction balance correctly. The cache is
294294
cleared at the beginning of each transaction.
295295
296-
This is used by finalize_transaction_changes to determine which balance
296+
This is used by normalize_balance_changes to determine which balance
297297
changes should be filtered out.
298298
299299
Parameters
@@ -331,9 +331,7 @@ def track_balance_change(
331331
Track a balance change for an account.
332332
333333
Records the new balance after any balance-affecting operation, including
334-
transfers, gas payments, block rewards, and withdrawals. The balance is
335-
encoded as a 16-byte value (uint128) which is sufficient for the total
336-
ETH supply.
334+
transfers, gas payments, block rewards, and withdrawals.
337335
338336
Parameters
339337
----------
@@ -454,7 +452,7 @@ def handle_in_transaction_selfdestruct(
454452
code changes from the current transaction are also removed.
455453
456454
Note: Balance changes are handled separately by
457-
finalize_transaction_changes.
455+
normalize_balance_changes.
458456
459457
Parameters
460458
----------
@@ -495,22 +493,25 @@ def handle_in_transaction_selfdestruct(
495493
]
496494

497495

498-
def finalize_transaction_changes(
496+
def normalize_balance_changes(
499497
tracker: StateChangeTracker, state: "State"
500498
) -> None:
501499
"""
502-
Finalize changes for the current transaction.
500+
Normalize balance changes for the current block access index.
503501
504-
This method is called at the end of each transaction execution to filter
505-
out spurious balance changes. It removes all balance changes for addresses
506-
where the post-transaction balance equals the pre-transaction balance.
502+
This method filters out spurious balance changes by removing all balance
503+
changes for addresses where the post-execution balance equals the
504+
pre-execution balance.
507505
508506
This is crucial for handling cases like:
509507
- In-transaction self-destructs where an account with 0 balance is created
510508
and destroyed, resulting in no net balance change
511509
- Round-trip transfers where an account receives and sends equal amounts
510+
- Zero-amount withdrawals where the balance doesn't actually change
512511
513-
Only actual state changes are recorded in the Block Access List.
512+
This should be called at the end of any operation that tracks balance
513+
changes (transactions, withdrawals, etc.). Only actual state changes are
514+
recorded in the Block Access List.
514515
515516
Parameters
516517
----------

src/ethereum/forks/amsterdam/fork.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
from .block_access_lists.builder import build_block_access_list
3333
from .block_access_lists.rlp_utils import compute_block_access_list_hash
3434
from .block_access_lists.tracker import (
35-
finalize_transaction_changes,
35+
capture_pre_balance,
3636
handle_in_transaction_selfdestruct,
37+
normalize_balance_changes,
3738
set_block_access_index,
3839
track_balance_change,
3940
)
@@ -1022,9 +1023,9 @@ def process_transaction(
10221023
)
10231024
destroy_account(block_env.state, address)
10241025

1025-
# EIP-7928: Finalize transaction changes
1026+
# EIP-7928: Normalize balance changes for this transaction
10261027
# Remove balance changes where post-tx balance equals pre-tx balance
1027-
finalize_transaction_changes(
1028+
normalize_balance_changes(
10281029
block_env.state.change_tracker,
10291030
block_env.state,
10301031
)
@@ -1067,6 +1068,12 @@ def increase_recipient_balance(recipient: Account) -> None:
10671068
rlp.encode(wd),
10681069
)
10691070

1071+
# Capture pre-balance before modification (even for zero withdrawals)
1072+
# This ensures the address appears in BAL per EIP-7928
1073+
capture_pre_balance(
1074+
block_env.state.change_tracker, wd.address, block_env.state
1075+
)
1076+
10701077
modify_state(block_env.state, wd.address, increase_recipient_balance)
10711078

10721079
# Track balance change for BAL
@@ -1076,6 +1083,14 @@ def increase_recipient_balance(recipient: Account) -> None:
10761083
block_env.state.change_tracker, wd.address, U256(new_balance)
10771084
)
10781085

1086+
# EIP-7928: Normalize balance changes for this withdrawal
1087+
# Remove balance changes where post-withdrawal balance
1088+
# equals pre-withdrawal balance
1089+
normalize_balance_changes(
1090+
block_env.state.change_tracker,
1091+
block_env.state,
1092+
)
1093+
10791094
if account_exists_and_is_empty(block_env.state, wd.address):
10801095
destroy_account(block_env.state, wd.address)
10811096

0 commit comments

Comments
 (0)