Skip to content

Markdown Content

Below is the verbatim markdown content from tests/amsterdam/eip7928_block_level_access_lists/test_cases.md@20373115.

EIP-7928 Block Access Lists (BAL) Test Cases

Function Name Goal Setup Expectation Status
test_bal_nonce_changes Ensure BAL captures changes to nonce Alice sends 100 wei to Bob BAL MUST include changes to Alice's nonce. ✅ Completed
test_bal_balance_changes Ensure BAL captures changes to balance Alice sends 100 wei to Bob BAL MUST include balance change for Alice, Bob, and Coinbase ✅ Completed
test_bal_code_changes Ensure BAL captures changes to account code Alice deploys factory contract that creates new contract BAL MUST include code changes for newly deployed contract ✅ Completed
test_selfdestruct_to_account (TangerineWhistle) Ensure BAL captures SELFDESTRUCT success boundary for account beneficiaries Victim executes SELFDESTRUCT(beneficiary) at exact gas boundary. Tests final gas boundary where operation completes. Parametrized: is_success (exact_gas/exact_gas_minus_1), beneficiary (EOA/contract), warm (cold/warm where warm=Berlin+), same_tx (pre_deploy/same_tx), originator_balance (0/1), beneficiary_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas: Beneficiary in BAL with balance_changes, victim destroyed (pre-Cancun/same_tx) or preserved (>=Cancun). exact_gas_minus_1: OOG, beneficiary in BAL only if G_NEW_ACCOUNT was part of gas calculation. ✅ Completed
test_selfdestruct_state_access_boundary (TangerineWhistle) Ensure BAL correctly tracks beneficiary access at state access boundary (consensus check) Victim executes SELFDESTRUCT(beneficiary) at state access boundary (base + cold). Verifies beneficiary is accessed before G_NEW_ACCOUNT check. Parametrized: is_success (exact_gas/exact_gas_minus_1), beneficiary (EOA/contract), warm (cold/warm), same_tx, originator_balance (0/1), beneficiary_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas: Beneficiary IN BAL (state accessed). exact_gas_minus_1: Beneficiary NOT in BAL (OOG before state access). Operation may succeed at exact_gas if no G_NEW_ACCOUNT needed. ✅ Completed
test_selfdestruct_to_self (TangerineWhistle) Ensure BAL captures SELFDESTRUCT where beneficiary is self at gas boundary Victim executes SELFDESTRUCT(ADDRESS) - selfdestructs to itself. Always warm, always alive (no G_NEW_ACCOUNT, no cold access). Gas = G_BASE + G_SELF_DESTRUCT. Parametrized: is_success (exact_gas/exact_gas_minus_1), originator_balance (0/1), same_tx (pre_deploy/same_tx). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas_minus_1: Victim in BAL with unchanged state. exact_gas: Pre-Cancun/same_tx: destroyed, balance=0. >=Cancun pre-existing: preserved with original balance. ✅ Completed
test_selfdestruct_to_precompile (TangerineWhistle) Ensure BAL captures SELFDESTRUCT success boundary for precompile beneficiaries Victim executes SELFDESTRUCT(precompile) at exact gas boundary. Precompiles are always warm (no cold access charge). Parametrized: is_success (exact_gas/exact_gas_minus_1), all precompiles via @pytest.mark.with_all_precompiles, same_tx (pre_deploy/same_tx), originator_balance (0/1), beneficiary_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas: Precompile in BAL with balance_changes, victim destroyed (pre-Cancun/same_tx) or preserved (>=Cancun). exact_gas_minus_1: OOG, precompile in BAL only if G_NEW_ACCOUNT was part of gas calculation. ✅ Completed
test_selfdestruct_to_precompile_state_access_boundary (TangerineWhistle) Ensure BAL correctly tracks precompile access at state access boundary (consensus check) Victim executes SELFDESTRUCT(precompile) at state access boundary (base only, precompiles always warm). Verifies precompile is accessed before G_NEW_ACCOUNT check. Parametrized: is_success (exact_gas/exact_gas_minus_1), all precompiles, same_tx, originator_balance (0/1), beneficiary_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas: Precompile IN BAL (state accessed). exact_gas_minus_1: Precompile NOT in BAL (OOG before state access). Operation may succeed at exact_gas if no G_NEW_ACCOUNT needed. ✅ Completed
test_selfdestruct_to_system_contract (Cancun) Ensure BAL captures SELFDESTRUCT success boundary for system contract beneficiaries Victim executes SELFDESTRUCT(system_contract) at exact gas boundary. System contracts are always warm (no cold access charge) and always have code (no G_NEW_ACCOUNT charge). Gas = G_VERY_LOW + G_SELF_DESTRUCT. Parametrized: is_success (exact_gas/exact_gas_minus_1), all system contracts via @pytest.mark.with_all_system_contracts, same_tx (pre_deploy/same_tx), originator_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. exact_gas: System contract in BAL with balance_changes if originator had balance, victim destroyed (same_tx) or balance=0 (pre-existing). exact_gas_minus_1: OOG, system contract not in BAL (no state access). ✅ Completed
test_initcode_selfdestruct_to_self (TangerineWhistle) Ensure BAL captures SELFDESTRUCT during initcode where beneficiary is self Initcode executes SELFDESTRUCT(ADDRESS) during CREATE, before any code is deployed. Contract has nonce=1 (post-EIP-161), making it non-empty. Always warm (executing contract), no G_NEW_ACCOUNT (nonce > 0). Gas boundary testing not possible (CREATE uses all available gas). Parametrized: originator_balance (0/1). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. Contract created and destroyed in same tx - victim has empty BAL changes. Caller has nonce_changes (incremented by CREATE) and balance_changes if originator had balance. Victim is NONEXISTENT in post state. ✅ Completed
test_bal_account_access_target Ensure BAL captures target addresses of account access opcodes Alice calls Oracle contract which uses account access opcodes (BALANCE, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, CALL, CALLCODE, DELEGATECALL, STATICCALL) on TargetContract. BAL MUST include Alice, Oracle, and TargetContract with empty changes for TargetContract and nonce changes for Alice. ✅ Completed
test_bal_call_no_delegation_and_oog_before_target_access Ensure BAL handles OOG before target access and success for non-delegated CALL Parametrized: target warm/cold, target empty/existing, value 0/1, memory expansion, OOG boundary (before_target_access/success). OOG: target in BAL ONLY if pre-warmed. Success: target always in BAL with balance changes when value > 0. ✅ Completed
test_bal_call_no_delegation_oog_after_target_access Ensure BAL includes target but excludes value transfer when OOG after target access Hardcoded: empty target, value=1 (required for create_cost gap). Parametrized: warm/cold, memory expansion. Target always in BAL. No balance changes (value transfer fails after G_NEW_ACCOUNT check). ✅ Completed
test_bal_call_7702_delegation_and_oog Ensure BAL handles OOG at all 4 boundaries for CALL to 7702 delegated accounts Parametrized: target warm/cold, delegation warm/cold, value 0/1, memory expansion, OOG boundary (before_target_access/after_target_access/success_minus_1/success). OOG before: neither in BAL. OOG after & success_minus_1: target in BAL, delegation NOT in BAL (static check optimization). Success: all in BAL. ✅ Completed
test_bal_callcode_nested_value_transfer Ensure BAL captures balance changes from nested value transfers when CALLCODE executes target code that itself makes CALL with value Alice calls Oracle contract (200 wei balance) which uses CALLCODE to execute TargetContract's code; that code makes a nested CALL transferring 100 wei to Bob. BAL MUST include Alice (nonce changes), Oracle (balance change to 100 wei), Bob (balance change to 100 wei), and TargetContract (empty changes). ✅ Completed
test_bal_delegated_storage_writes Ensure BAL captures delegated storage writes via DELEGATECALL and CALLCODE Alice calls Oracle contract which uses DELEGATECALL/CALLCODE to TargetContract that writes 0x42 to slot 0x01. BAL MUST include Alice (nonce changes), Oracle (storage changes for slot 0x01 = 0x42), and TargetContract (empty changes). ✅ Completed
test_bal_delegated_storage_reads Ensure BAL captures delegated storage reads via DELEGATECALL and CALLCODE Alice calls Oracle contract (with slot 0x01 = 0x42) which uses DELEGATECALL/CALLCODE to TargetContract that reads from slot 0x01. BAL MUST include Alice (nonce changes), Oracle (storage reads for slot 0x01), and TargetContract (empty changes). ✅ Completed
test_bal_block_rewards BAL tracks fee recipient balance changes from block rewards Alice sends 100 wei to Bob with Charlie as fee recipient BAL MUST include fee recipient Charlie with balance_changes reflecting transaction fees collected from the block. ✅ Completed
test_bal_2930_account_listed_but_untouched Ensure BAL excludes listed but untouched account Alice sends a simple eth transfer tx to Bob with EIP-2930 access list including Oracle BAL MUST NOT include any entry for Oracle because it wasn't accessed. ✅ Completed
test_bal_2930_slot_listed_but_untouched Ensure BAL excludes listed but untouched storage slots Alice sends tx with EIP-2930 access list including (PureCalculator, slot=0x01); PureCalculator executes pure arithmetic (adding two numbers) without touching slot 0x01 BAL MUST NOT include any entry for PureCalculator's slot 0x01 because it doesn't access state ✅ Completed
test_bal_2930_slot_listed_and_unlisted_writes Ensure BAL includes storage writes regardless of access list presence Alice sends tx with EIP-2930 access list including (StorageWriter, slot=0x01); StorageWriter executes SSTORE to slots 0x01 and 0x02 BAL MUST include storage_changes for StorageWriter's slots 0x01 and 0x02 ✅ Completed
test_bal_2930_slot_listed_and_unlisted_reads Ensure BAL includes storage reads regardless of access list presence Alice sends tx with EIP-2930 access list including (StorageReader, slot=0x01); StorageReader executes SLOAD from slots 0x01 and 0x02 BAL MUST include storage_reads for StorageReader's slots 0x01 and 0x02 ✅ Completed
test_bal_self_transfer BAL handles self-transfers correctly Alice sends 100 wei to Alice BAL MUST include one entry for Alice with balance_changes reflecting gas cost only (value cancels out) and nonce change. ✅ Completed
test_bal_zero_value_transfer BAL handles zero-value transfers correctly Alice sends 0 wei to Bob BAL MUST include Alice with balance_changes (gas cost only) and nonce change, and Bob in account_changes with empty balance_changes. ✅ Completed
test_bal_noop_storage_write Ensure BAL includes storage read but not write for no-op writes where pre-state equals post-state Contract with pre-existing storage value 0x42 in slot 0x01; transaction executes SSTORE(0x01, 0x42) (writing same value) BAL MUST include the contract address with storage_reads for slot 0x01 since it was accessed, but MUST NOT include it in storage_changes (no actual state change). ✅ Completed
test_bal_fully_unmutated_account Ensure BAL captures account that has zero net mutations Alice sends 0 wei to Oracle which writes same pre-existing value to storage BAL MUST include Alice with nonce_changes and balance changes (gas), Oracle with storage_reads for accessed slot but empty storage_changes. ✅ Completed
test_bal_net_zero_balance_transfer BAL includes accounts with net-zero balance change but excludes them from balance changes Contract receives and sends same amount to recipient using CALL or SELFDESTRUCT BAL MUST include contract in account_changes without balance_changes (net zero). BAL MUST record non-zero balance_changes for recipient. ✅ Completed
test_bal_system_dequeue_consolidations_eip7251 BAL tracks post-exec system dequeues for consolidations Pre-populate EIP-7251 consolidation requests; produce a block where dequeues occur BAL MUST include the 7251 system contract with storage_changes (queue slots 0–3) using block_access_index = len(txs). ✅ Completed
test_bal_withdrawal_contract_cross_index Ensure withdrawal system contract shows storage changes at both tx and post-execution indices Alice sends withdrawal request to EIP-7002 system contract. Slots 0x01 (count) and 0x03 (tail) are incremented during tx (index 1) and reset during post-execution dequeue (index 2). BAL MUST include withdrawal request contract with storage_changes for slots 0x01 and 0x03, each with two slot_changes: one at block_access_index=1 (tx) and one at block_access_index=2 (post-exec). ✅ Completed
test_bal_consolidation_contract_cross_index Ensure consolidation system contract shows storage changes at both tx and post-execution indices Alice sends consolidation request to EIP-7251 system contract. Slots 0x01 (count) and 0x03 (tail) are incremented during tx (index 1) and reset during post-execution dequeue (index 2). BAL MUST include consolidation request contract with storage_changes for slots 0x01 and 0x03, each with two slot_changes: one at block_access_index=1 (tx) and one at block_access_index=2 (post-exec). ✅ Completed
test_bal_noop_write_filtering Ensure BAL filters NOOP storage writes (writing same value or 0 to empty slot) Contract writes 0 to uninitialized slot 1 (noop), 42 to slot 2 (real change), 100 to slot 3 (same as pre-state, noop), 200 to slot 4 (different from pre-state 150, real change). BAL MUST include storage_changes only for slots 2 and 4 (actual changes). Slots 1 and 3 MUST NOT appear in storage_changes (no-op writes filtered). ✅ Completed
test_bal_system_contract_noop_filtering Ensure system contract post-execution calls filter net-zero storage writes Simple transfer that doesn't interact with system contracts. Post-execution system calls read withdrawal/consolidation contract slots 0-3 but don't modify them. Withdrawal and consolidation system contracts MUST have storage_reads for slots 0x00-0x03 but MUST NOT have storage_changes (no actual modifications occurred). ✅ Completed
test_bal_aborted_storage_access Ensure BAL captures storage access in aborted transactions correctly Alice calls contract that reads storage slot 0x01, writes to slot 0x02, then aborts with REVERT/INVALID BAL MUST include storage_reads for slots 0x01 and 0x02 (aborted writes become reads), empty storage_changes. Only nonce changes for Alice. ✅ Completed
test_bal_aborted_account_access Ensure BAL captures account access in aborted transactions for all account accessing opcodes Alice calls AbortContract that performs account access operations (BALANCE, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, CALL, CALLCODE, DELEGATECALL, STATICCALL) on TargetContract and aborts via REVERT/INVALID BAL MUST include Alice, TargetContract, and AbortContract in account_changes and nonce changes for Alice. ✅ Completed
test_bal_pure_contract_call Ensure BAL captures contract access for pure computation calls Alice calls PureContract that performs pure arithmetic (ADD operation) without storage or balance changes BAL MUST include Alice and PureContract in account_changes, and nonce_changes for Alice. ✅ Completed
test_bal_create_storage_op_then_selfdestruct_same_tx BAL correctly demotes ephemeral storage operations to storage_reads when a contract is created and destroyed in the same tx (combined coverage for read and write storage_op cases — replaces test_bal_create2_to_A_read_then_selfdestruct and test_bal_create2_to_A_write_then_selfdestruct). Parametrized: @pytest.mark.with_all_create_opcodes + storage_op ∈ ["read", "write"]. Address A is pre-funded via pre.fund_address. Alice sends a single tx calling a factory that deploys a contract at A via the parametrized create opcode; init code is either SLOAD(B)+SELFDESTRUCT or SSTORE(B, v)+SELFDESTRUCT (beneficiary = separate EOA). BAL MUST include A with balance_changes [(1, 0)] (outflow to beneficiary on destruction). Slot B MUST appear under storage_reads, NOT storage_changes (write demoted to read because the contract is destroyed same-tx). A MUST NOT have nonce_changes or code_changes. Beneficiary has balance_changes reflecting receipt of fund at index 1. ✅ Completed
test_bal_precompile_funded BAL records precompile value transfer with or without balance change Alice sends value to precompile (all precompiles) via direct transaction. Parameterized: (1) with value (1 ETH), (2) without value (0 ETH). For with_value: BAL MUST include precompile with balance_changes. For no_value: BAL MUST include precompile with empty balance_changes. No storage_changes or code_changes in either case. ✅ Completed
test_bal_precompile_call_opcode BAL records the precompile address regardless of call opcode. Parametrized: @pytest.mark.with_all_precompiles × @pytest.mark.with_all_call_opcodes. Alice calls Oracle which invokes the precompile via the parametrized call opcode. For DELEGATECALL/CALLCODE the precompile provides the code but is not the call target, so its access has to be recorded explicitly rather than incidentally. BAL MUST include the precompile address with empty changes for all four call opcodes. Oracle has empty changes (called but no state mutation), Alice has nonce_changes. ✅ Completed
test_bal_7702_delegated_create BAL tracks EIP-7702 delegation indicator write and contract creation Alice sends a type-4 (7702) tx authorizing herself to delegate to Deployer code which executes CREATE BAL MUST include for Alice: code_changes (delegation indicator), nonce_changes (increment from 7702 processing), and balance_changes (post-gas). For Child: code_changes (runtime bytecode) and nonce_changes = 1. ✅ Completed
test_bal_7702_delegation_create Ensure BAL captures creation of EOA delegation Alice authorizes delegation to contract Oracle. Transaction sends 10 wei to Bob. Two variants: (1) Self-funded: Alice sends 7702 tx herself. (2) Sponsored: Relayer sends 7702 tx on Alice's behalf. BAL MUST include Alice: code_changes (delegation designation 0xef0100\|\|address(Oracle)),nonce_changes (increment). Bob: balance_changes (receives 10 wei). For sponsored variant, BAL MUST also include Relayer:nonce_changes.Oracle MUST NOT be present in BAL - the account is never accessed. ✅ Completed
test_bal_7702_delegation_update Ensure BAL captures update of existing EOA delegation Alice first delegates to Oracle1, then in second tx updates delegation to Oracle2. Each transaction sends 10 wei to Bob. Two variants: (1) Self-funded: Alice sends both 7702 txs herself. (2) Sponsored: Relayer sends both 7702 txs on Alice's behalf. BAL MUST include Alice: first tx has code_changes (delegation designation 0xef0100\|\|address(Oracle1)),nonce_changes. Second tx hascode_changes (delegation designation 0xef0100\|\|address(Oracle2)),nonce_changes. Bob:balance_changes (receives 10 wei on each tx). For sponsored variant, BAL MUST also include Relayer:nonce_changes for both transactions. Oracle1 and Oracle2 MUST NOT be present in BAL - accounts are never accessed. ✅ Completed
test_bal_7702_delegation_clear Ensure BAL captures clearing of EOA delegation Alice first delegates to Oracle, then in second tx clears delegation by authorizing to 0x0 address. Each transaction sends 10 wei to Bob. Two variants: (1) Self-funded: Alice sends both 7702 txs herself. (2) Sponsored: Relayer sends both 7702 txs on Alice's behalf. BAL MUST include Alice: first tx has code_changes (delegation designation 0xef0100\|\|address(Oracle)), nonce_changes. Second tx has code_changes (empty code - delegation cleared), nonce_changes. Bob: balance_changes (receives 10 wei on each tx). For sponsored variant, BAL MUST also include Relayer: nonce_changes for both transactions. Oracle and 0x0 address MUST NOT be present in BAL - accounts are never accessed. ✅ Completed
test_bal_7702_delegated_storage_access Ensure BAL captures storage operations when calling a delegated EIP-7702 account Alice has delegated her account to Oracle. Oracle contract contains code that reads from storage slot 0x01 and writes to storage slot 0x02. Bob sends 10 wei to Alice (the delegated account), which executes Oracle's code. BAL MUST include Alice: balance_changes (receives 10 wei), storage_changes for slot 0x02 (write operation performed in Alice's storage), storage_reads for slot 0x01 (read operation from Alice's storage). Bob: nonce_changes (sender), balance_changes (loses 10 wei plus gas costs). Oracle (account access). ✅ Completed
test_bal_7702_invalid_nonce_authorization Ensure BAL handles failed authorization due to wrong nonce Relayer sends sponsored transaction to Bob (10 wei transfer succeeds) but Alice's authorization to delegate to Oracle uses incorrect nonce, causing silent authorization failure BAL MUST include Alice with empty changes (account access), Bob with balance_changes (receives 10 wei), Relayer with nonce_changes. MUST NOT include Oracle (authorization failed, no delegation) ✅ Completed
test_bal_7702_invalid_chain_id_authorization Ensure BAL handles failed authorization due to wrong chain id Relayer sends sponsored transaction to Bob (10 wei transfer succeeds) but Alice's authorization to delegate to Oracle uses incorrect chain id, causing authorization failure before account access BAL MUST include Bob with balance_changes (receives 10 wei), Relayer with nonce_changes. MUST NOT include Alice (authorization fails before loading account) or Oracle (authorization failed, no delegation) ✅ Completed
test_call_into_self_delegating_set_code Self-delegation degenerate one-hop case (companion to test_call_into_chain_delegating_set_code). File: tests/prague/eip7702_set_code_tx/test_set_code_txs.py. Parametrized over @pytest.mark.with_all_call_opcodes. auth_signer auths itself as its own delegation target. entry_address issues call_opcode(auth_signer). EVM resolves once: auth_signer's code is the designator pointing back to auth_signer; the second hop is not followed, so the 0xef0100... bytecode runs as legacy code → INVALID → returns 0. auth_signer MUST appear with nonce_changes and code_changes (delegation designator to itself). entry_address MUST have storage_reads=[0] (no-op SSTORE demoted). No additional delegation-target entry is created because the target coincides with the authority. ✅ Completed
test_bal_7702_invalid_authority_has_code_authorization Ensure BAL handles failed authorization where the authority already has non-empty, non-delegation code (EIP-7702 step-5 rejection, post-load). Alice is pre-allocated with code=Op.STOP and nonce=1. Relayer sends sponsored tx to Bob (10 wei transfer). Authorization tuple delegates Alice to Oracle with matching nonce. EIP-7702 step 5 rejects because Alice's code is non-empty and not a delegation designator. BAL MUST include Bob with balance_changes (10 wei), Relayer with nonce_changes, and Alice with empty changes (loaded at step 4 then rejected at step 5). MUST NOT include Oracle (delegation target never loaded). ✅ Completed
test_signature_s_out_of_range Ensure BAL excludes the authority when the EIP-7702 auth signature has an out-of-range s value (EIP-2 low-s rule, ecrecover fails before authority is loaded). File: tests/prague/eip7702_set_code_tx/test_set_code_txs.py. auth_signer signs a normal auth tuple delegating to set_code_to_address; the tuple is then mutated so s = SECP256K1N - s and v is flipped, producing a high-s signature. Sender (a separate EOA) sends the tx to entry_address which executes SSTORE(1, 1). BAL MUST include sender with nonce_changes at block_access_index=1 and entry_address with storage_changes for slot 1 (post=1). BAL MUST NOT include auth_signer (auth fails at ecrecover, before the authority is added to accessed_addresses) or set_code_to_address (target is never loaded as an execution target). ✅ Completed
test_nonce_validity Ensure BAL correctly records EIP-7702 auth-tuple nonce-field validity across pre-load (nonce >= 2**64-1), success, and post-load (account.nonce != auth.nonce) branches. File: tests/prague/eip7702_set_code_tx/test_set_code_txs.py. Parametrized over (account_nonce, authorization_nonce): (1) (MAX, MAX) pre-load rejection at step 2, (2) (MAX-1, MAX-1) successful auth, (3) (0, 1) post-load nonce mismatch, (4) (1, 0) post-load nonce mismatch. entry_address always does SSTORE(success_slot, 1) + CALL(auth_signer) + SSTORE(return_slot, RETURNDATASIZE). Valid auth (case 2): auth_signer MUST have nonce_changes (post=account_nonce+1) and code_changes (delegation designation); set_code_to_address MUST appear with empty changes (loaded as execution target via delegation dispatch); entry_address has storage_changes for both slot 1 and slot 2 (post=1). Invalid auth (cases 1, 3, 4): auth_signer MUST appear with empty changes (the subsequent CALL touches it, even though the auth processing did or did not add it); set_code_to_address MUST NOT be in BAL; entry_address has storage_changes for slot 1 and storage_reads for slot 2 (the SSTORE(0, 0) no-op is demoted per EIP-7928). Sender always has nonce_changes. ✅ Completed
test_call_into_chain_delegating_set_code Ensure BAL respects EIP-7702 one-hop delegation resolution when A delegates to B and B delegates back to A. File: tests/prague/eip7702_set_code_tx/test_set_code_txs.py. Parameterized over @pytest.mark.with_all_call_opcodes. Two auths: auth_signer_1 -> auth_signer_2, then auth_signer_2 -> auth_signer_1. entry_address issues call_opcode(auth_signer_1) and stores the return code in slot 0. The EVM resolves A -> B once, then runs B's 0xef0100... bytecode as legacy code; 0xef is INVALID, so the call frame aborts and returns 0. BAL MUST include only auth_signer_1 and auth_signer_2 from the delegation chain (each with nonce_changes and code_changes for its delegation designator). No third address is ever loaded because the second hop is never followed. entry_address MUST have storage_reads for slot 0 (the SSTORE(slot, 0) is a no-op write and is demoted per EIP-7928) and no storage_changes. Sender has nonce_changes. ✅ Completed
test_bal_7702_multi_hop_delegation_chain Multi-hop EIP-7702 delegation: chain resolves A→B→C and loop resolves A→B→A. In both cases the EVM follows the delegation once and runs B's 0xef0100<dest> bytecode, which aborts on the INVALID 0xef opcode. Parametrized over destination_is_loop ∈ [False, True]. auth_a delegates to auth_b; auth_b delegates to either target_c (chain) or back to auth_a (loop). Entry contract has storage[0] = 0xDEAD (witness) and issues CALL(auth_a) then stores the return code in slot 0. auth_a and auth_b MUST appear with nonce_changes and code_changes (each successful auth). In chain, target_c MUST NOT appear in BAL. entry_address has storage_changes for slot 0 with post_value=0 (0xDEAD overwritten by the failed CALL's return code 0). Sender has nonce_changes. ✅ Completed
test_set_code_to_precompile Covers the BAL recording of a precompile address when reached via EIP-7702 delegation dispatch — across all 4 call opcodes and all precompiles. Companion to test_bal_precompile_call_opcode for the direct-call path. File: tests/prague/eip7702_set_code_tx/test_set_code_txs.py. @pytest.mark.with_all_call_opcodes × @pytest.mark.with_all_precompiles. EOA auth_signer delegates to a precompile address. A caller contract invokes call_opcode(auth_signer); EIP-7702 resolves the delegation to the precompile (whose code is treated as empty per spec). When EIP-7928 is enabled, BAL MUST include auth_signer with nonce_changes and code_changes (delegation designator), and MUST include the precompile address with empty changes (loaded as execution target via delegation dispatch). ✅ Completed
test_bal_7702_delegated_via_call_opcode Ensure BAL captures delegation target when a contract uses *CALL opcodes to call a delegated account Pre-deployed contract Alice delegated to Oracle. Caller contract uses CALL/CALLCODE/DELEGATECALL/STATICCALL to call Alice. Bob sends transaction to Caller. BAL MUST include Bob: nonce_changes. Caller: empty changes (account access). Alice: empty changes (account access - delegated account being called). Oracle: empty changes (delegation target access). ✅ Completed
test_bal_7702_null_address_delegation_no_code_change Ensure BAL does not record spurious code changes for net-zero code operations Alice sends transaction with authorization delegating to NULL_ADDRESS (0x0), which sets code to b"" on an account that already has b"" code. Transaction sends 10 wei to Bob. BAL MUST include Alice with nonce_changes (tx nonce + auth nonce increment) but MUST NOT include code_changes (setting b"" -> b"" is net-zero and filtered out). Bob: balance_changes (receives 10 wei). This ensures net-zero code change is not recorded. ✅ Completed
test_bal_7702_double_auth_reset Ensure BAL tracks multiple 7702 nonce increments but filters net-zero code change Single transaction contains two EIP-7702 authorizations for Alice: (1) first auth sets delegation 0xef0100\|\|Oracle, (2) second auth clears delegation back to empty. Transaction sends 10 wei to Bob. Two variants: (a) Self-funded: Alice is tx sender (one tx nonce bump + two auth bumps → nonce 0→3). (b) Sponsored: Relayer is tx sender (Alice only in auths → nonce 0→2 for Alice, plus one nonce bump for Relayer). Variant (a): BAL MUST include Alice with nonce_changes 0→3. Variant (b): BAL MUST include Alice with nonce_changes 0→2 and Relayer with its own nonce_changes. For both variants, BAL MUST NOT include code_changes for Alice (net code is empty), MUST include Bob with balance_changes (receives 10 wei), and Oracle MUST NOT appear in BAL. ✅ Completed
test_bal_7702_double_auth_swap Ensure BAL captures final code when double auth swaps delegation targets Relayer sends transaction with two authorizations for Alice: (1) First auth sets delegation to CONTRACT_A at nonce=0, (2) Second auth changes delegation to CONTRACT_B at nonce=1. Transaction sends 10 wei to Bob. Per EIP-7702, only the last authorization takes effect. BAL MUST include Alice with nonce_changes (both auths increment nonce to 2) and code_changes (final code is delegation designation for CONTRACT_B, not CONTRACT_A). Bob: balance_changes (receives 10 wei). Relayer: nonce_changes. Neither CONTRACT_A nor CONTRACT_B appear in BAL during delegation setup (never accessed). This ensures BAL shows final state, not intermediate changes. ✅ Completed
test_bal_sstore_and_oog Ensure BAL handles OOG during SSTORE execution at various gas boundaries (EIP-2200 stipend and implicit SLOAD) Alice calls contract that attempts SSTORE to cold slot 0x01. Parameterized: (1) OOG at EIP-2200 stipend check (2300 gas after PUSH opcodes) - fails before implicit SLOAD, (2) OOG at stipend + 1 (2301 gas) - passes stipend check but fails after implicit SLOAD, (3) OOG at exact gas - 1, (4) Successful SSTORE with exact gas. For case (1): BAL MUST NOT include slot 0x01 in storage_reads or storage_changes (fails before implicit SLOAD). For cases (2) and (3): BAL MUST include slot 0x01 in storage_reads (implicit SLOAD occurred) but MUST NOT include in storage_changes (write didn't complete). For case (4): BAL MUST include slot 0x01 in storage_changes only (successful write; read is filtered by builder). ✅ Completed
test_bal_sstore_static_context SSTORE in static context must not leak storage reads into BAL Contract A STATICCALLs Contract B which attempts SSTORE. Parametrized: original_value (0, nonzero) to catch clients that perform the implicit SLOAD before the static check. Contract B IS in BAL (accessed via STATICCALL) but MUST NOT have storage_reads. ✅ Completed
test_bal_sload_and_oog Ensure BAL handles OOG during SLOAD execution correctly Alice calls contract that attempts SLOAD from cold slot 0x01. Parameterized: (1) OOG at SLOAD opcode (insufficient gas), (2) Successful SLOAD execution. For OOG case: BAL MUST NOT contain slot 0x01 in storage_reads since storage wasn't accessed. For success case: BAL MUST contain slot 0x01 in storage_reads. ✅ Completed
test_bal_balance_and_oog Ensure BAL handles OOG during BALANCE opcode execution correctly Alice calls contract that attempts BALANCE opcode on cold target account. Parameterized: (1) OOG at BALANCE opcode (insufficient gas), (2) Successful BALANCE execution. For OOG case: BAL MUST NOT include target account (wasn't accessed). For success case: BAL MUST include target account in account_changes. ✅ Completed
test_bal_account_touch_system_address Ensure BAL includes SYSTEM_ADDRESS when a regular transaction touches it via any account-accessing opcode Alice calls a contract that executes one of BALANCE, EXTCODESIZE, EXTCODEHASH, EXTCODECOPY, CALL, or STATICCALL against SYSTEM_ADDRESS. Parametrized over the six opcodes. BAL MUST include SYSTEM_ADDRESS as an account-only entry for every opcode because the address experienced a real EVM state access. This is distinct from excluding the synthetic system-operation caller. ✅ Completed
test_bal_extcodesize_and_oog Ensure BAL handles OOG during EXTCODESIZE opcode execution correctly Alice calls contract that attempts EXTCODESIZE opcode on cold target contract. Parameterized: (1) OOG at EXTCODESIZE opcode (insufficient gas), (2) Successful EXTCODESIZE execution. For OOG case: BAL MUST NOT include target contract (wasn't accessed). For success case: BAL MUST include target contract in account_changes. ✅ Completed
test_bal_delegatecall_no_delegation_and_oog_before_target_access Ensure BAL handles OOG before target access and success for non-delegated DELEGATECALL Parametrized: target warm/cold, memory expansion, OOG boundary (before_target_access/success). OOG: target in BAL ONLY if pre-warmed. Success: target always in BAL. ✅ Completed
test_bal_delegatecall_7702_delegation_and_oog Ensure BAL handles OOG at all 4 boundaries for DELEGATECALL to 7702 delegated accounts Parametrized: target warm/cold, delegation warm/cold, memory expansion, OOG boundary (before_target_access/after_target_access/success_minus_1/success). OOG before: neither in BAL. OOG after & success_minus_1: target in BAL, delegation NOT in BAL (static check optimization). Success: all in BAL. ✅ Completed
test_bal_callcode_no_delegation_and_oog_before_target_access Ensure BAL handles OOG before target access and success for non-delegated CALLCODE Parametrized: target warm/cold, value 0/1, memory expansion, OOG boundary (before_target_access/success). OOG: target in BAL ONLY if pre-warmed. Success: target always in BAL. ✅ Completed
test_bal_callcode_7702_delegation_and_oog Ensure BAL handles OOG at all 4 boundaries for CALLCODE to 7702 delegated accounts Parametrized: target warm/cold, delegation warm/cold, value 0/1, memory expansion, OOG boundary (before_target_access/after_target_access/success_minus_1/success). OOG before: neither in BAL. OOG after & success_minus_1: target in BAL, delegation NOT in BAL (static check optimization). Success: all in BAL. ✅ Completed
test_bal_staticcall_no_delegation_and_oog_before_target_access Ensure BAL handles OOG before target access and success for non-delegated STATICCALL Parametrized: target warm/cold, memory expansion, OOG boundary (before_target_access/success). OOG: target in BAL ONLY if pre-warmed. Success: target always in BAL. ✅ Completed
test_bal_staticcall_7702_delegation_and_oog Ensure BAL handles OOG at all 4 boundaries for STATICCALL to 7702 delegated accounts Parametrized: target warm/cold, delegation warm/cold, memory expansion, OOG boundary (before_target_access/after_target_access/success_minus_1/success). OOG before: neither in BAL. OOG after & success_minus_1: target in BAL, delegation NOT in BAL (static check optimization). Success: all in BAL. ✅ Completed
test_bal_extcodecopy_and_oog Ensure BAL handles OOG during EXTCODECOPY at various failure points Alice calls contract that attempts EXTCODECOPY from cold target contract. Parameterized: (1) Successful EXTCODECOPY, (2) OOG at cold access (insufficient gas for account access), (3) OOG at memory expansion with large offset (64KB offset, gas covers cold access + copy but NOT memory expansion), (4) OOG at memory expansion boundary (256 byte offset, gas is exactly 1 less than needed). For success case: BAL MUST include target contract. For all OOG cases: BAL MUST NOT include target contract. Gas for ALL components (cold access + copy + memory expansion) must be checked BEFORE recording account access. ✅ Completed
test_bal_multiple_balance_changes_same_account Ensure BAL tracks multiple balance changes to same account across transactions Alice funds Bob (starts at 0) in tx0 with exact amount needed. Bob spends everything in tx1 to Charlie. Bob's balance: 0 → funding_amount → 0 BAL MUST include Bob with two balance_changes: one at txIndex=1 (receives funds) and one at txIndex=2 (balance returns to 0). This tests balance tracking across two transactions. ✅ Completed
test_bal_multiple_storage_writes_same_slot Ensure BAL tracks multiple writes to same storage slot across transactions Alice calls contract 3 times in same block. Contract increments slot 1 on each call: 0 → 1 → 2 → 3 BAL MUST include contract with slot 1 having three slot_changes: txIndex=1 (value 1), txIndex=2 (value 2), txIndex=3 (value 3). Each transaction's write must be recorded separately. ✅ Completed
test_bal_nested_delegatecall_storage_writes_net_zero Ensure BAL correctly filters net-zero storage changes across nested DELEGATECALL frames Parametrized by nesting depth (1-3). Root contract has slot 0 = 1. Each frame writes a different intermediate value via DELEGATECALL chain, deepest frame writes back to original value (1). Example depth=2: 1 → 2 → 3 → 1 BAL MUST include root contract with storage_reads for slot 0 but MUST NOT include storage_changes (net-zero). All delegate contracts MUST have empty changes. Tests that frame merging correctly removes parent's intermediate writes when child reverts to pre-tx value. ✅ Completed
test_bal_cross_tx_storage_revert_to_zero Ensure BAL captures storage changes when tx2 reverts slot back to original value (blobhash regression test) Alice sends tx1 writing slot 0=0xABCD (from 0x0), then tx2 writing slot 0=0x0 (back to original) BAL MUST include contract with slot 0 having two slot_changes: txIndex=1 (0xABCD) and txIndex=2 (0x0). Cross-transaction net-zero MUST NOT be filtered. ✅ Completed
test_bal_intra_tx_multiple_sstores_same_slot Ensure BAL coalesces consecutive SSTOREs to the same slot within one tx into a single storage change with the final post-value Contract executes SSTORE(0x01, 0xAA) + SSTORE(0x01, 0xBB) + SSTORE(0x01, 0xCC) in one tx. Parametrized by pre_value: slot_starts_empty (0x00), slot_starts_nonzero (0x11), intermediate_equals_pre (0xBB, where the second write transiently matches the pre-state). BAL MUST include contract with slot 0x01 having exactly one slot_changes entry: txIndex=1, post_value=0xCC. Intermediate values 0xAA and 0xBB MUST NOT appear as separate entries (enforced via absent_values). ✅ Completed
test_bal_intra_tx_sstores_same_slot_net_zero Ensure BAL filters net-zero result when multiple SSTOREs to the same slot occur within one tx Parametrized: nonzero_pre_returns_to_pre (pre=0xCC, writes 0xAA→0xBB→0xCC) and empty_pre_ephemeral_writes (pre=0x00, writes 0xAA→0xBB→0x00). Final value equals pre-state in both cases. BAL MUST include contract with slot 0x01 in storage_reads (slot was accessed) and MUST NOT include slot 0x01 in storage_changes (net-zero). ✅ Completed
test_bal_create_contract_init_revert Ensure BAL correctly handles CREATE when parent call reverts Caller calls factory, factory executes CREATE (succeeds), then factory REVERTs rolling back the CREATE BAL MUST include Alice with nonce_changes. Caller and factory with no changes (reverted). Created contract address appears in BAL but MUST NOT have nonce_changes or code_changes (CREATE was rolled back). Contract address MUST NOT exist in post-state. ✅ Completed
test_bal_create_oog_code_deposit Ensure BAL correctly handles CREATE OOG during code deposit Alice calls factory contract that executes CREATE with init code returning 10,000 bytes. Transaction has insufficient gas for code deposit. Factory nonce increments, CREATE returns 0 and stores in slot 1. BAL MUST include Alice with nonce_changes. Factory with nonce_changes (incremented by CREATE) and storage_changes (slot 1 = 0). Contract address with empty changes (read during collision check). MUST NOT include nonce or code changes for contract address (rolled back on OOG). Contract address MUST NOT exist in post-state. ✅ Completed
test_bal_create_early_failure Ensure BAL correctly handles CREATE that fails before accessing contract address Factory (balance=50) attempts CREATE(value=100). CREATE fails due to insufficient endowment (100 > 50). Factory stores CREATE result (0) in slot 0. BAL MUST include Alice with nonce_changes. Factory with storage_changes (slot 0 = 0) but MUST NOT have nonce_changes (CREATE failed before nonce increment). Contract address MUST NOT appear in BAL (never accessed - CREATE failed before track_address). This is distinct from collision/OOG failures where contract address IS in BAL. ✅ Completed
test_bal_invalid_missing_nonce Verify clients reject blocks with BAL missing required nonce changes Alice sends transaction to Bob; BAL modifier removes Alice's nonce change entry Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate that all sender accounts have nonce changes recorded. ✅ Completed
test_bal_invalid_nonce_value Verify clients reject blocks with incorrect nonce values in BAL Alice sends transaction to Bob; BAL modifier changes Alice's nonce to incorrect value Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate nonce values match actual state transitions. ✅ Completed
test_bal_invalid_storage_value Verify clients reject blocks with incorrect storage values in BAL Alice calls contract that writes to storage; BAL modifier changes storage value to incorrect value Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate storage change values match actual state transitions. ✅ Completed
test_bal_invalid_tx_order Verify clients reject blocks with incorrect transaction indices in BAL Alice sends transaction; BAL modifier swaps transaction indices incorrectly Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate transaction ordering matches actual block execution order. ✅ Completed
test_bal_invalid_account Verify clients reject blocks with incorrect account addresses in BAL Alice sends transaction; BAL modifier includes wrong account address Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate all account addresses in BAL were actually accessed. ✅ Completed
test_bal_invalid_duplicate_account Verify clients reject blocks with duplicate account entries in BAL Alice sends transaction; BAL modifier duplicates Alice's account entry Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST ensure each account appears at most once in BAL. ✅ Completed
test_bal_invalid_account_order Verify clients reject blocks with incorrect account ordering in BAL Alice sends transaction to Bob; BAL modifier reverses account order (BAL requires sorted order) Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate accounts are in canonical sorted order. ✅ Completed
test_bal_invalid_complex_corruption Verify clients reject blocks with multiple BAL corruptions Alice calls contract with storage writes; BAL has multiple issues: wrong account, missing nonce, wrong storage value Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST detect any corruption regardless of other issues. ✅ Completed
test_bal_invalid_missing_account Verify clients reject blocks whose BAL omits an account that was touched during block execution Parameterized test: balance_change — Alice sends a value transfer to Bob; BAL modifier removes Bob's entry (recipient had a balance change). access_only — Alice calls a contract that executes BALANCE against a target account without changing it; BAL modifier removes the target account's entry (accessed-but-unchanged). Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate all accessed accounts are present, including accessed-but-unchanged accounts with empty change lists. ✅ Completed
test_bal_invalid_balance_value Verify clients reject blocks with incorrect balance values in BAL Alice sends value to Bob; BAL modifier changes balance to incorrect value Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate balance change values match actual state transitions. ✅ Completed
test_bal_empty_block_no_coinbase Ensure BAL correctly handles empty blocks without including coinbase Block with 0 transactions, no withdrawals. System contracts may perform operations (EIP-2935 parent hash, EIP-4788 beacon root if active). BAL MUST NOT include the coinbase/fee recipient (receives no fees). BAL MAY include system contract addresses (EIP-2935 HISTORY_STORAGE_ADDRESS, EIP-4788 BEACON_ROOTS_ADDRESS) with storage_changes at block_access_index=0 (pre-execution system operations). ✅ Completed
test_bal_coinbase_zero_tip Ensure BAL includes coinbase even when priority fee is zero Block with 1 transaction: Alice sends 5 wei to Bob with priority fee = 0 (base fee burned post-EIP-1559) BAL MUST include Alice with balance_changes (gas cost) and nonce_changes. BAL MUST include Bob with balance_changes. BAL MUST include coinbase with empty changes. ✅ Completed
test_bal_withdrawal_empty_block Ensure BAL captures withdrawal balance changes in empty block Charlie starts with 1 gwei. Block with 0 transactions and 1 withdrawal of 10 gwei to Charlie BAL MUST include Charlie with balance_changes at block_access_index = 1. Charlie's balance_changes MUST show final balance of 11 gwei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_and_transaction Ensure BAL captures both transaction and withdrawal balance changes Block with 1 transaction: Alice sends 5 wei to Bob. 1 withdrawal of 10 gwei to Charlie BAL MUST include Alice with nonce_changes and balance_changes at block_access_index = 1. BAL MUST include Bob with balance_changes at block_access_index = 1. BAL MUST include Charlie with balance_changes at block_access_index = 2 showing final balance after receiving 10 gwei. All other fields for Charlie MUST be empty. ✅ Completed
test_bal_withdrawal_to_nonexistent_account Ensure BAL captures withdrawal to non-existent account Block with 1 withdrawal of 10 gwei to non-existent account Charlie BAL MUST include Charlie with balance_changes at block_access_index = 1 showing final balance of 10 gwei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_no_evm_execution Ensure BAL captures withdrawal without triggering EVM execution Contract Oracle with storage slot 0x01 = 0x42. Oracle code writes to slot 0x01 when called. Block with 1 withdrawal of 10 gwei to Oracle BAL MUST include Oracle with balance_changes at block_access_index = 1 showing final balance after receiving 10 gwei. Storage slot 0x01 MUST remain 0x42 and all other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_and_state_access_same_account Ensure BAL captures both state access and withdrawal to same address Contract Oracle with storage slot 0x01 = 0x42. Block with 1 transaction: Alice calls Oracle (reads from slot 0x01, writes to slot 0x02). 1 withdrawal of 10 gwei to Oracle BAL MUST include Oracle with storage_reads for slot 0x01 and storage_changes for slot 0x02 at block_access_index = 1. Oracle MUST also have balance_changes at block_access_index = 2 showing final balance after receiving 10 gwei. Both state access and withdrawal MUST be captured. ✅ Completed
test_bal_withdrawal_and_value_transfer_same_address Ensure BAL captures both transaction value transfer and withdrawal to same address Block with 1 transaction: Alice sends 5 gwei to Bob. 1 withdrawal of 10 gwei to Bob BAL MUST include Alice with nonce_changes and balance_changes at block_access_index = 1. BAL MUST include Bob with balance_changes at block_access_index = 1 showing balance after receiving 5 gwei. Bob MUST also have balance_changes at block_access_index = 2 showing balance after receiving 10 gwei withdrawal. Bob's final post-state balance MUST be 15 gwei (cumulative). ✅ Completed
test_bal_multiple_withdrawals_same_address Ensure BAL accumulates multiple withdrawals to same address Block with 3 withdrawals to Charlie: 5 gwei, 10 gwei, 15 gwei BAL MUST include Charlie with balance_changes at block_access_index = 1 showing final balance of 30 gwei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_and_selfdestruct Ensure BAL captures withdrawal to self-destructed contract address Contract Oracle with 100 gwei balance. Block with 1 transaction: Oracle self-destructs sending balance to Bob. 1 withdrawal of 50 gwei to Oracle's address BAL MUST include Oracle with balance_changes showing 0 balance at block_access_index = 1 (after self-destruct). BAL MUST include Bob with balance_changes showing 100 gwei received from self-destruct at block_access_index = 1. Oracle MUST also have balance_changes at block_access_index = 2 showing 50 gwei after withdrawal. Both self-destruct and withdrawal MUST be captured. ✅ Completed
test_bal_withdrawal_and_new_contract Ensure BAL captures withdrawal to newly created contract Block with 1 transaction: Alice deploys contract Oracle with 5 gwei initial balance. 1 withdrawal of 10 gwei to Oracle BAL MUST include Oracle with code_changes and balance_changes showing 5 gwei at block_access_index = 1. Oracle MUST also have balance_changes at block_access_index = 2 showing balance after receiving 10 gwei withdrawal. Oracle's final post-state balance MUST be 15 gwei (cumulative). ✅ Completed
test_bal_zero_withdrawal Ensure BAL handles zero-amount withdrawal correctly Block with 0 transactions and 1 zero-amount withdrawal (0 gwei) to Charlie. Two variations: Charlie has existing balance (5 gwei) or Charlie is non-existent. BAL MUST include Charlie at block_access_index = 1 with empty changes. Balance remains unchanged. ✅ Completed
test_bal_withdrawal_to_precompiles Ensure BAL captures withdrawal to precompile addresses Block with 1 withdrawal of 10 gwei to precompile address (all precompiles) BAL MUST include precompile address with balance_changes at block_access_index = 1 showing final balance of 10 gwei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_largest_amount Ensure BAL captures withdrawal with largest amount Block with 1 withdrawal of maximum uint64 value (2^64-1 gwei) to Charlie BAL MUST include Charlie with balance_changes at block_access_index = 1 showing final balance of (2^64-1) * 10^9 wei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_withdrawal_to_coinbase Ensure BAL captures withdrawal to coinbase address Block with 1 transaction: Alice sends 5 wei to Bob. 1 withdrawal of 10 gwei to coinbase/fee recipient BAL MUST include coinbase with balance_changes at block_access_index = 1 showing balance after transaction fees. Coinbase MUST also have balance_changes at block_access_index = 2 showing balance after receiving 10 gwei withdrawal. Coinbase's final post-state balance MUST include both transaction fees and withdrawal. ✅ Completed
test_bal_withdrawal_to_coinbase_empty_block Ensure BAL captures withdrawal to coinbase even when there are no transactions (no fees) Block with 0 transactions and 1 withdrawal of 10 gwei to coinbase/fee recipient BAL MUST include coinbase with balance_changes at block_access_index = 1 showing final balance of 10 gwei. All other fields (storage_reads, storage_changes, nonce_changes, code_changes) MUST be empty. ✅ Completed
test_bal_nonexistent_value_transfer Ensure BAL captures non-existent account on value transfer Alice sends value (0 wei or 1 ETH) to non-existent account Bob (address never funded or accessed before) via direct transfer For zero value: BAL MUST include Alice with nonce_changes and Bob (non-existent) with empty changes. For positive value: BAL MUST include Bob with balance_changes showing received amount. ✅ Completed
test_bal_nonexistent_account_access_read_only Ensure BAL captures non-existent account accessed via read-only account-reading opcodes Alice calls Oracle contract which uses read-only account access opcodes (BALANCE, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, STATICCALL, DELEGATECALL) on non-existent account Bob. BAL MUST include Alice with nonce_changes, Oracle with empty changes, and Bob with empty changes (account accessed but no state modifications). ✅ Completed
test_bal_nonexistent_account_access_value_transfer Ensure BAL captures non-existent account accessed via CALL/CALLCODE with value transfers Alice calls Oracle contract which uses CALL or CALLCODE on non-existent account Bob. Tests both zero and positive value transfers. BAL MUST include Alice with nonce_changes. For CALL with positive value: Oracle with balance_changes (loses value), Bob with balance_changes (receives value). For CALLCODE with value or zero value transfers: Oracle and Bob with empty changes (CALLCODE self-transfer = net zero). ✅ Completed
test_bal_storage_write_read_same_frame Ensure BAL captures write precedence over read in same call frame (writes shadow reads) Alice calls Oracle which writes (SSTORE) value 0x42 to slot 0x01, then reads (SLOAD) from slot 0x01 in the same call frame BAL MUST include Oracle with slot 0x01 in storage_changes showing final value 0x42. Slot 0x01 MUST NOT appear in storage_reads (write shadows the subsequent read in same frame). ✅ Completed
test_bal_storage_write_read_cross_frame Ensure BAL captures write precedence over read across call frames (writes shadow reads cross-frame) Alice calls Oracle. First call reads slot 0x01 (sees initial value), writes 0x42 to slot 0x01, then calls itself (via CALL, DELEGATECALL, or CALLCODE). Second call reads slot 0x01 (sees 0x42) and exits. BAL MUST include Oracle with slot 0x01 in storage_changes showing final value 0x42. Slot 0x01 MUST NOT appear in storage_reads (write shadows both the read before it in same frame and the read in the recursive call). ✅ Completed
test_bal_create_transaction_empty_code Ensure BAL does not record spurious code changes for CREATE transaction deploying empty code Alice sends CREATE transaction with empty initcode (deploys code b""). Contract address gets nonce = 1 and code = b"". BAL MUST include Alice with nonce_changes and created contract with nonce_changes but MUST NOT include code_changes for contract (setting b"" -> b"" is net-zero). ✅ Completed
test_bal_cross_block_ripemd160_state_leak Ensure internal EVM state for precompile handling does not leak between blocks Block 1: Alice calls RIPEMD-160 (0x03) with zero value (RIPEMD-160 must be pre-funded). Block 2: Bob's transaction triggers an exception (stack underflow). BAL for Block 1 MUST include RIPEMD-160. BAL for Block 2 MUST NOT include RIPEMD-160 (never accessed in Block 2). Internal state from Parity Touch Bug (EIP-161) handling must be reset between blocks. ✅ Completed
test_bal_all_transaction_types Ensure BAL correctly captures state changes from all transaction types in a single block Single block with 5 transactions: Type 0 (Legacy), Type 1 (EIP-2930 Access List), Type 2 (EIP-1559), Type 3 (EIP-4844 Blob), Type 4 (EIP-7702 Set Code). Each tx writes to contract storage. Note: Access list addresses are pre-warmed but NOT recorded in BAL (no state access). BAL MUST include: (1) All 5 senders with nonce_changes. (2) Contracts 0-3 with storage_changes. (3) Alice (7702 target) with nonce_changes, code_changes (delegation), storage_changes. (4) Oracle (delegation source) with empty changes. ✅ Completed
test_bal_create2_collision Ensure BAL handles CREATE2 address collision correctly Factory contract (nonce=1, storage slot 0=0xDEAD) executes CREATE2(salt=0, initcode) targeting address that already has code=STOP, nonce=1. Pre-deploy contract at calculated CREATE2 target address before factory deployment. BAL MUST include: (1) Factory with nonce_changes (1→2, incremented even on failed CREATE2), storage_changes for slot 0 (0xDEAD→0, stores failure). (2) Collision address with empty changes (accessed during collision check, no state changes). CREATE2 returns 0. Collision address MUST NOT have nonce_changes or code_changes. ✅ Completed
test_bal_create_selfdestruct_to_self_with_call Ensure BAL handles init code that calls external contract then selfdestructs to itself Factory executes CREATE2 with endowment=100. Init code (embedded in factory via CODECOPY): (1) CALL(Oracle, 0) - Oracle writes to its storage slot 0x01. (2) SSTORE(0x01, 0x42) - write to own storage. (3) SELFDESTRUCT(SELF) - selfdestruct to own address. Contract created and destroyed in same tx. BAL MUST include: (1) Factory with nonce_changes, balance_changes (loses 100). (2) Oracle with storage_changes for slot 0x01 (external call succeeded). (3) Created address with storage_reads for slot 0x01 (aborted write becomes read) - MUST NOT have nonce_changes, code_changes, storage_changes, or balance_changes (ephemeral contract, balance burned via SELFDESTRUCT to self). ✅ Completed
test_bal_selfdestruct_to_7702_delegation Ensure BAL correctly handles SELFDESTRUCT to a 7702 delegated account (no code execution on recipient) Tx1: Alice authorizes delegation to Oracle (sets code to 0xef0100\|\|Oracle). Tx2: Victim contract (balance=100) executes SELFDESTRUCT(Alice). Two separate transactions in same block. Note: Alice starts with initial balance which accumulates with selfdestruct. BAL MUST include: (1) Alice at block_access_index=1 with code_changes (delegation), nonce_changes. (2) Alice at block_access_index=2 with balance_changes (receives selfdestruct). (3) Victim at block_access_index=2 with balance_changes (100→0). Oracle MUST NOT appear in tx2 - per EVM spec, SELFDESTRUCT transfers balance without executing recipient code, so delegation target is never accessed. ✅ Completed
test_bal_call_revert_insufficient_funds Ensure BAL handles value-transferring call failure due to insufficient balance (not OOG), with and without 7702 delegation Caller contract (balance=100, storage slot 0x02=0xDEAD) executes: SLOAD(0x01), call_opcode(target, value=1000), SSTORE(0x02, result). The call fails because 1000 > 100. Parametrized: (1) call_opcode over CALL and CALLCODE via with_all_call_opcodes(selector=...), (2) delegated (target is plain EOA vs. 7702-delegated EOA pointing to delegation_target=STOP), (3) target_is_warm (cold/warm via EIP-2930 access list), (4) delegation_is_warm (only when delegated). BAL MUST include: (1) Caller with storage_reads for slot 0x01, storage_changes for slot 0x02 (value=0, call returned failure). (2) Target with empty changes - accessed before balance check fails. (3) When delegated: delegation_target with empty changes - delegation is loaded before balance check fails (unlike the OOG cases in test_bal_call_7702_delegation_and_oog where the static-check optimization avoids the delegation load). Access-list warming does NOT add to BAL on its own, so the BAL is identical across warm/cold variants. ✅ Completed
test_bal_lexicographic_address_ordering Ensure BAL enforces strict lexicographic byte-wise ordering Pre-fund three addresses with specific byte patterns: addr_low = 0x0000...0001, addr_mid = 0x0000...0100, addr_high = 0x0100...0000. Contract touches them in reverse order: BALANCE(addr_high), BALANCE(addr_low), BALANCE(addr_mid). Additionally, include two endian-trap addresses that are byte-reversals of each other: addr_endian_low = 0x0100000000000000000000000000000000000002, addr_endian_high = 0x0200000000000000000000000000000000000001. Note: reverse(addr_endian_low) = addr_endian_high. Correct lexicographic order: addr_endian_low < addr_endian_high (0x01 < 0x02 at byte 0). If implementation incorrectly reverses bytes before comparing, it would get addr_endian_low > addr_endian_high (wrong). BAL account list MUST be sorted lexicographically by address bytes: addr_low < addr_mid < addr_high < addr_endian_low < addr_endian_high, regardless of access order. The endian-trap addresses specifically catch byte-reversal bugs where addresses are compared with wrong byte order. Complements test_bal_invalid_account_order which tests rejection; this tests correct generation. ✅ Completed
test_bal_gas_limit_boundary Ensure BAL max items gas limit boundary is enforced for empty blocks Empty block with gas limit set to the exact boundary where bal_items <= block_gas_limit // GAS_BLOCK_ACCESS_LIST_ITEM. Parameterized: (1) at_boundary (gas limit = exact minimum, passes), (2) below_boundary (gas limit = exact minimum - 1, fails). At boundary: block MUST be accepted. Below boundary: block MUST be rejected with BLOCK_ACCESS_LIST_GAS_LIMIT_EXCEEDED exception. ✅ Completed
test_bal_transient_storage_not_tracked Ensure BAL excludes EIP-1153 transient storage operations Contract executes: TSTORE(0x01, 0x42) (transient write), TLOAD(0x01) (transient read), SSTORE(0x02, result) (persistent write using transient value). BAL MUST include slot 0x02 in storage_changes (persistent storage was modified). BAL MUST NOT include slot 0x01 in storage_reads or storage_changes (transient storage is not persisted, not needed for stateless execution). This verifies TSTORE/TLOAD don't pollute BAL. ✅ Completed
test_bal_withdrawal_to_7702_delegation Ensure BAL correctly handles withdrawal to a 7702 delegated account (no code execution on recipient) Tx1: Alice authorizes delegation to Oracle (sets code to 0xef0100\|\|Oracle). Withdrawal: 10 gwei sent to Alice. Single block with tx + withdrawal. BAL MUST include: (1) Alice at block_access_index=1 with code_changes (delegation), nonce_changes. (2) Alice at block_access_index=2 with balance_changes (receives withdrawal). Oracle MUST NOT appear - withdrawals credit balance without executing recipient code, so delegation target is never accessed. This complements test_bal_selfdestruct_to_7702_delegation (selfdestruct) and test_bal_withdrawal_no_evm_execution (withdrawal to contract). ✅ Completed
test_init_collision_create_tx Ensure BAL tracks CREATE collisions correctly (pre-Amsterdam test with BAL) CREATE transaction targeting address with existing storage aborts BAL MUST show empty expectations for collision address (no changes occur due to abort) ✅ Completed
test_call_to_pre_authorized_oog Ensure BAL handles OOG during EIP-7702 delegation access (pre-Amsterdam test with BAL) Call to delegated account that OOGs before accessing delegation contract BAL MUST include auth_signer (code read for delegation check) but MUST NOT include delegation contract (OOG before access) ✅ Completed
test_selfdestruct_created_in_same_tx_with_revert Ensure BAL tracks selfdestruct with revert correctly (pre-Amsterdam test with BAL) Contract created and selfdestructed in same tx with nested revert BAL MUST track storage reads and balance changes for selfdestruct even with reverts ✅ Completed
test_value_transfer_gas_calculation Ensure BAL correctly tracks OOG scenarios for CALL/CALLCODE/DELEGATECALL/STATICCALL (pre-Amsterdam test with BAL) Nested calls with precise gas limits to test OOG behavior. For CALL with OOG: target account is read. For CALLCODE/DELEGATECALL/STATICCALL with OOG: target account NOT read (OOG before state access) For CALL: target in BAL even with OOG. For CALLCODE/DELEGATECALL/STATICCALL: target NOT in BAL when OOG (state access deferred until after gas check) ✅ Completed
test_bal_call_with_value_in_static_context Ensure BAL does NOT include target when CALL with value fails in static context static_caller uses STATICCALL to call caller. caller attempts CALL(target, value=1) which must fail due to static context. Target is an empty account. BAL MUST NOT include target because static context check (is_static && value > 0) must happen BEFORE any account access or BAL tracking. BAL MUST include static_caller with storage_changes (STATICCALL succeeded), caller with empty changes. ✅ Completed
test_staticcall_reentrant_call_to_precompile Ensure BAL captures STATICCALL reentry with CALL to precompile Contract STATICCALLs itself. On reentry (CALLVALUE=0), attempts CALL to precompile with parametrized value. File: tests/byzantium/eip214_staticcall/test_staticcall.py. call_value=0: target with storage_changes (slot 0=1), precompile with empty changes. call_value>0: target with storage_reads (slot 0), precompile NOT in BAL (reverted before accessed). ✅ Completed
test_staticcall_call_to_precompile Ensure BAL captures STATICCALL → CALL to precompile chain Contract A STATICCALLs contract B. B attempts CALL to precompile. File: tests/byzantium/eip214_staticcall/test_staticcall.py. call_value=0: contract_a with markers, contract_b empty (STATICCALLed), precompile empty. call_value>0: contract_a with storage_reads for slot 1, precompile NOT in BAL. ✅ Completed
test_staticcall_nested_call_to_precompile Ensure BAL captures nested CALL → STATICCALL → CALL to precompile Contract B CALLs A. A STATICCALLs C. C attempts CALL to precompile. File: tests/byzantium/eip214_staticcall/test_staticcall.py. call_value=0: all contracts with markers/empty, precompile empty. call_value>0: contract_a with storage_reads for slot 1, precompile NOT in BAL. ✅ Completed
test_staticcall_call_to_precompile_from_contract_init Ensure BAL captures STATICCALL to precompile during CREATE init Contract A CREATEs contract. Init code STATICCALLs B which CALLs precompile. File: tests/byzantium/eip214_staticcall/test_staticcall.py. call_value=0: contract_a with markers/nonce, created_contract with markers/nonce, contract_b empty, precompile empty. call_value>0: created_contract with storage_reads for slot 1, precompile NOT in BAL. ✅ Completed
test_bal_4788_simple Ensure BAL captures beacon root storage writes during pre-execution system call Block with 2 normal user transactions: Alice sends 10 wei to Charlie, Bob sends 10 wei to Charlie. At block start (pre-execution), SYSTEM_ADDRESS calls BEACON_ROOTS_ADDRESS to store parent beacon root BAL MUST include at block_access_index=0: BEACON_ROOTS_ADDRESS with two storage_changes (timestamp slot and beacon root slot); SYSTEM_ADDRESS MUST NOT be included in BAL. At block_access_index=1: Alice with nonce_changes, Charlie with balance_changes (10 wei). At block_access_index=2: Bob with nonce_changes, Charlie with balance_changes (20 wei total). ✅ Completed
test_bal_4788_empty_block Ensure BAL captures beacon root storage writes in empty block Block with no transactions. At block start (pre-execution), SYSTEM_ADDRESS calls BEACON_ROOTS_ADDRESS to store parent beacon root BAL MUST include at block_access_index=0: BEACON_ROOTS_ADDRESS with two storage_changes (timestamp slot and beacon root slot); SYSTEM_ADDRESS MUST NOT be included in BAL. No transaction-related BAL entries. ✅ Completed
test_bal_4788_query Ensure BAL captures storage reads when querying beacon root (valid and invalid queries) with optional value transfer Parameterized test: Block 1 stores beacon root at timestamp 12. Block 2 queries with three timestamp scenarios (valid=12, invalid non-zero=42, invalid zero=0) and value (0 or 100 wei). Valid query (timestamp=12): reads both timestamp and root slots, writes returned value. If value > 0, beacon root contract receives balance. Invalid query with non-zero timestamp (timestamp=42): reads only timestamp slot before reverting, query contract has implicit SLOAD recorded (SSTORE reverts), no value transferred. Invalid query with zero timestamp (timestamp=0): reverts immediately without any storage access, query contract has implicit SLOAD recorded, no value transferred. Block 1 BAL: System call writes. Block 2 BAL MUST include at block_access_index=0: System call writes for block 2. Valid case (timestamp=12) at block_access_index=1: BEACON_ROOTS_ADDRESS with storage_reads [timestamp_slot, root_slot] and balance_changes if value > 0, query contract with storage_changes. Invalid non-zero case (timestamp=42) at block_access_index=1: BEACON_ROOTS_ADDRESS with storage_reads [timestamp_slot only] and NO balance_changes (reverted), query contract with storage_reads [0] and NO storage_changes. Invalid zero case (timestamp=0) at block_access_index=1: BEACON_ROOTS_ADDRESS with NO storage_reads (reverts before access) and NO balance_changes, query contract with storage_reads [0] and NO storage_changes. ✅ Completed
test_bal_4788_invalid_calldata_size Ensure BAL correctly handles EIP-4788 queries with invalid calldata size Parameterized test: Query contract calls BEACON_ROOTS_ADDRESS with variable-size calldata (0, 31, or 33 bytes) and value (0 or 100 wei). EIP-4788 requires exactly 32 bytes of calldata; any other size reverts before any storage access. BAL MUST include at block_access_index=0: BEACON_ROOTS_ADDRESS with storage_changes from system call. At block_access_index=1: BEACON_ROOTS_ADDRESS with NO storage_reads (reverts before access) and NO balance_changes (value not transferred), query contract with storage_reads [0] (implicit from no-op SSTORE) and NO storage_changes. If value > 0, query contract retains balance. Alice with nonce_changes. ✅ Completed
test_bal_4788_selfdestruct_to_beacon_root Ensure BAL captures SELFDESTRUCT to beacon root address alongside system call storage writes Single block: Pre-execution system call writes beacon root to storage. Transaction: Alice calls contract (pre-funded with 100 wei) that selfdestructs with BEACON_ROOTS_ADDRESS as beneficiary. BAL MUST include at block_access_index=0: BEACON_ROOTS_ADDRESS with storage_changes (timestamp and root slots from system call). At block_access_index=1: Alice with nonce_changes, contract with balance_changes (100→0), BEACON_ROOTS_ADDRESS with balance_changes (receives 100 wei). ✅ Completed
test_selfdestruct_send_to_sender Ensure BAL tracks SELFDESTRUCT sending all funds back to the tx sender (no burn). Multi-fork: valid_from TangerineWhistle, BAL expectations applied from Amsterdam via is_eip_enabled(7928). File: tests/tangerine_whistle/eip150_operation_gas_costs/test_eip150_selfdestruct.py. Parametrized over originator_balance: [0, 100]. Pre-deployed contract victim with code=SELFDESTRUCT(CALLER) and the given balance. Alice (tx.sender) sends tx directly to victim; no intermediate caller. Pre-Cancun: victim destroyed. >=Cancun (EIP-6780, non-same-tx): victim preserved with balance 0. When EIP-7928 is enabled, BAL MUST include Alice with nonce_changes coalesced with balance_changes (Alice is both sender and beneficiary). Victim has balance_changes 100→0 when funded, otherwise empty changes — and MUST NOT have code_changes or nonce_changes. ✅ Completed
test_bal_7002_clean_sweep Ensure BAL correctly tracks "clean sweep" where all withdrawal requests are dequeued in same block (requests ≤ MAX). Parameterized: (1) pubkey first 32 bytes zero / non-zero, (2) amount zero / non-zero Alice sends transaction to WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS with 1 withdrawal request. Validator pubkey has either first 32 bytes zero or non-zero. Amount is either zero or non-zero. Since 1 ≤ MAX_WITHDRAWAL_REQUESTS_PER_BLOCK, post-execution system call dequeues all requests ("clean sweep"), resetting head and tail to 0. BAL MUST include Alice with nonce_changes at block_access_index=1. WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS MUST have: balance_changes at block_access_index=1 (receives fee), storage_reads for excess, head, and slot 5 (first 32 bytes of pubkey) if zero. At block_access_index=1 (tx enqueue): storage_changes for count (0→1), tail (0→1), slot 4 (source address), slot 5 (first 32 bytes, ONLY if non-zero), slot 6. At block_access_index=2 (post-exec dequeue): storage_changes for count (1→0), tail (1→0). Clean sweep invariant: when all requests dequeued, both head and tail reset to 0. ✅ Completed
test_bal_7002_partial_sweep Ensure BAL correctly tracks queue overflow when requests exceed MAX, demonstrating partial sweep in block 1 and cleanup in block 2 Block 1: 20 different EOAs each send withdrawal request to WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS. Since 20 > MAX_WITHDRAWAL_REQUESTS_PER_BLOCK, only first MAX requests dequeued ("partial sweep"), leaving 4 in queue. Block 2: Empty block (no transactions), remaining 4 requests dequeued ("clean sweep"), queue becomes empty. Block 1 BAL MUST include all 20 senders with nonce_changes at respective block_access_index (1-20). WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS at each tx: storage_changes for count (increments to 20), tail (increments to 20). At block_access_index=21 (post-exec partial dequeue): storage_changes for count (20→0), head (0→MAX). Partial sweep: head advances by MAX, tail stays 20, queue has 4 remaining (tail - head = 4). Block 2 BAL MUST include WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS at block_access_index=1 (post-exec clean sweep): storage_changes for head (MAX→0), tail (20→0). Clean sweep: both head and tail reset to 0, queue empty. ✅ Completed
test_bal_7002_no_withdrawal_requests Ensure BAL captures EIP-7002 system contract dequeue operation even when block has no withdrawal requests Block with 1 transaction: Alice sends 10 wei to Bob. No withdrawal requests submitted. BAL MUST include Alice with nonce_changes at block_access_index=1. BAL MUST include Bob with balance_changes at block_access_index=1. BAL MUST include EIP-7002 system contract (WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS) with storage_reads for slots: excess (slot 0), count (slot 1), head (slot 2), tail (slot 3). System contract MUST NOT have storage_changes (no writes occur when queue is empty). This test demonstrates that the post-execution dequeue operation always runs and reads queue state, even when no requests are present. ✅ Completed
test_bal_7002_request_from_contract Ensure BAL captures withdrawal request from contract with correct source address Alice calls RelayContract which internally calls EIP-7002 system contract with withdrawal request. Withdrawal request should have source_address = RelayContract (not Alice). BAL MUST include Alice with nonce_changes at block_access_index=1. BAL MUST include RelayContract with balance_changes (fee paid to system contract) at block_access_index=1. BAL MUST include system contract with balance_changes, storage_reads, and storage_changes (queue modified). Source address in withdrawal request MUST be RelayContract. Clean sweep: count and tail reset to 0 at block_access_index=2. ✅ Completed
test_bal_7002_request_invalid Ensure BAL correctly handles invalid withdrawal request scenarios Parameterized test with 8 invalid scenarios: (1) insufficient_fee (fee=0), (2) calldata_too_short (55 bytes), (3) calldata_too_long (57 bytes), (4) oog (insufficient gas), (5-7) invalid_call_type (DELEGATECALL/STATICCALL/CALLCODE), (8) contract_reverts. Tests both EOA and contract-based withdrawal requests. BAL MUST include sender with nonce_changes at block_access_index=1. BAL MUST include system contract with storage_reads for slots: excess (slot 0), count (slot 1), head (slot 2), tail (slot 3). System contract MUST NOT have storage_changes (transaction failed, no queue modification). ✅ Completed
test_bal_invalid_extraneous_entries Verify clients reject blocks with any type of extraneous BAL entries Alice sends 100 wei to Oracle contract (which reads storage slot 0). Charlie is uninvolved in this transaction. A valid BAL is created containing nonce change for Alice, balance change and storage read for Oracle. The BAL is corrupted by adding various extraneous entries: (1) extra_nonce, (2) extra_balance, (3) extra_code, (4) extra_storage_write_touched (slot 0 - already read), (5) extra_storage_write_untouched (slot 1 - not accessed), (6) extra_storage_write_uninvolved_account (Charlie - uninvolved account), (7) extra_account_access (Charlie), (8) extra_storage_read (slot 999). Each tested at block_access_index 1 (same tx), 2 (system tx), 3 (out of bounds). Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST detect any extraneous entries in BAL. ✅ Completed
test_bal_invalid_duplicate_entries Verify clients reject blocks where BAL violates uniqueness constraints Oracle writes storage, reads storage, and CREATEs a contract. BAL is corrupted with duplicate entries: (1) duplicate_nonce_change, (2) duplicate_balance_change, (3) duplicate_code_change, (4) duplicate_storage_slot, (5) duplicate_storage_read, (6) duplicate_slot_change, (7) storage_key_in_both_changes_and_reads. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Each block_access_index must appear at most once per change list, each storage key at most once in storage_changes and storage_reads, and no key in both. ✅ Completed
test_bal_invalid_missing_withdrawal_account Verify clients reject blocks where BAL is missing an account modified only by a withdrawal Alice sends 5 wei to Bob (1 transaction). Charlie receives 10 gwei withdrawal. BAL modifier removes Charlie's entry entirely. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST detect that Charlie's balance was modified by the withdrawal but has no corresponding BAL entry. ✅ Completed
test_bal_invalid_missing_withdrawal_account_empty_block Verify clients reject blocks where BAL is missing a withdrawal-modified account in an empty block Charlie receives 10 gwei withdrawal in block with no transactions. BAL modifier removes Charlie's entry entirely. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST detect withdrawal-modified accounts even when no transactions are present. ✅ Completed
test_bal_invalid_hash_mismatch Verify clients reject blocks where the BAL hash in the header does not match the actual BAL content Alice sends value to Bob. BAL content is valid but header hash is overridden to a wrong value via rlp_modifier. Unlike other invalid BAL tests (which corrupt BAL content with matching hash), this keeps the BAL valid but injects a wrong header hash. Block MUST be rejected with INVALID_BAL_HASH or INVALID_BLOCK_HASH exception. Clients MUST re-derive the BAL from block execution and compare its hash to the header, not just verify the BAL content is self-consistent. ✅ Completed
test_bal_invalid_field_entries Verify clients reject blocks with missing or incorrect field-level BAL entries Oracle writes storage slot 1, reads storage slot 2, and CREATEs a small contract. A valid BAL is created, then corrupted by parameterized modifier: (1) missing_storage_change: Oracle's storage writes removed, (2) missing_storage_read: Oracle's storage reads removed, (3) missing_code_change: created contract's code change removed, (4) wrong_code_value: created contract's deployed bytecode changed to wrong value. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate all field-level BAL entries: storage writes, storage reads, and code changes. ✅ Completed
test_bal_invalid_withdrawal_balance_value Verify clients reject blocks where BAL has an incorrect balance value for a withdrawal-modified account Charlie receives 10 gwei withdrawal in an empty block. BAL modifier changes Charlie's post-balance from the correct 10_000_000_000 wei to 999. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate withdrawal balance values match actual withdrawal amounts (including gwei-to-wei conversion). ✅ Completed
test_bal_invalid_missing_coinbase Verify clients reject blocks where BAL is missing the coinbase/fee recipient Alice sends 100 wei to Bob with gas_price > base_fee so coinbase (charlie) receives a non-zero tip. BAL modifier removes charlie's entry entirely. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST include fee recipients that received tips in the BAL. ✅ Completed
test_bal_invalid_coinbase_balance_value Verify clients reject blocks where BAL has an incorrect balance for the coinbase/fee recipient Same setup as test_bal_invalid_missing_coinbase. BAL modifier changes charlie's post-balance from the actual tip to 999. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Clients MUST validate coinbase balance values match actual fee accounting (priority fee x gas used). ✅ Completed
test_bal_invalid_extraneous_coinbase Verify clients reject blocks with a spurious coinbase entry when coinbase received no fees Parameterized: (1) empty_block: no txs, no withdrawals — only system contracts in valid BAL, (2) withdrawal_only: no txs, one withdrawal to a different address — withdrawals don't pay fees so coinbase is still untouched. BAL modifier appends spurious coinbase entry with empty changes. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST exception. Coinbase MUST NOT appear in BAL when it receives no transaction tips, even if the block has other state-modifying activity (withdrawals). ✅ Completed
test_bal_invalid_surplus_system_address_from_system_call Verify clients reject a BAL containing SYSTEM_ADDRESS solely due to a system operation caller Empty block with an EIP-4788 pre-execution system call to BEACON_ROOTS_ADDRESS. Helper beacon_root_system_call_expectations builds the valid baseline BAL: BEACON_ROOTS_ADDRESS has timestamp/root storage changes at block_access_index=0, while SYSTEM_ADDRESS is marked absent (None). The fixture BAL is then corrupted by appending an empty SYSTEM_ADDRESS entry. Block MUST be rejected with INVALID_BLOCK_ACCESS_LIST. The synthetic system caller address MUST NOT be accepted unless it experienced an actual state access. ✅ Completed
test_bal_2935_simple Ensure BAL captures EIP-2935 history storage writes during pre-execution system call alongside normal transactions Block with 2 normal user transactions: Alice sends 10 wei to Charlie, Bob sends 10 wei to Charlie. At block start (pre-execution), SYSTEM_ADDRESS calls HISTORY_STORAGE_ADDRESS to store parent block hash. BAL MUST include HISTORY_STORAGE_ADDRESS with storage_changes (ring buffer slot 0, empty slot_changes since parent hash is framework-computed); SYSTEM_ADDRESS MUST NOT be included in BAL. At block_access_index=1: Alice with nonce_changes, Charlie with balance_changes (10 wei). At block_access_index=2: Bob with nonce_changes, Charlie with balance_changes (20 wei total). ✅ Completed
test_bal_2935_empty_block Ensure BAL captures EIP-2935 history storage writes in empty block Block with no transactions. At block start (pre-execution), SYSTEM_ADDRESS calls HISTORY_STORAGE_ADDRESS to store parent block hash. BAL MUST include HISTORY_STORAGE_ADDRESS with storage_changes (ring buffer slot 0, empty slot_changes); SYSTEM_ADDRESS MUST NOT be included in BAL. No transaction-related BAL entries. ✅ Completed
test_bal_2935_query Ensure BAL captures storage reads when querying EIP-2935 historical block hashes (valid and invalid queries) with optional value transfer Parameterized test: Block 1 (empty, stores genesis hash via system call). Block 2: Oracle contract queries HISTORY_STORAGE_ADDRESS with block number. Two block number scenarios (valid=0 genesis hash, invalid=1042 out of range) and value (0 or 100 wei). Valid query (block_number=0): reads genesis hash slot, oracle writes returned value. If value > 0, history storage contract receives balance. Invalid query (block_number=1042, out of range): reverts before storage access, oracle has implicit SLOAD recorded, value stays in oracle (not transferred to history storage). Block 2 BAL MUST include: Valid case at block_access_index=1: HISTORY_STORAGE_ADDRESS with storage_reads [slot 0] and balance_changes if value > 0, oracle with storage_changes (empty slot_changes). Invalid case at block_access_index=1: HISTORY_STORAGE_ADDRESS with NO storage_reads (reverts before access) and NO balance_changes, oracle with storage_reads [0], NO storage_changes, and balance_changes if value > 0 (value stays in oracle). Alice with nonce_changes at block_access_index=1. ✅ Completed
test_bal_2935_selfdestruct_to_history_storage Ensure BAL captures SELFDESTRUCT to EIP-2935 history storage address Single block: Transaction where Alice calls contract (pre-funded with 100 wei) that selfdestructs with HISTORY_STORAGE_ADDRESS as beneficiary. BAL MUST include at block_access_index=1: Alice with nonce_changes, contract with balance_changes (100→0), HISTORY_STORAGE_ADDRESS with balance_changes (receives 100 wei). ✅ Completed
test_bal_2935_invalid_calldata_size Ensure BAL correctly handles EIP-2935 queries with invalid calldata size (reverts before any storage access) Parameterized test: Block 1 stores genesis hash via system call. Block 2: Oracle contract calls HISTORY_STORAGE_ADDRESS with invalid calldata sizes (0, 31, 33 bytes). EIP-2935 requires exactly 32 bytes calldata; any other size causes immediate revert before storage access. Optional value transfer (0 or 100 wei). Block 2 BAL MUST include: HISTORY_STORAGE_ADDRESS with NO storage_reads (calldata size check fails before any SLOAD) and NO balance_changes (call reverts). Oracle with storage_reads [0] (implicit SLOAD from no-op SSTORE), NO storage_changes, and balance_changes if value > 0 (value stays in oracle on revert). Alice with nonce_changes. ✅ Completed
test_bal_create2_selfdestruct_then_recreate_same_block Ensure BAL handles (tx1) CREATE2+SELFDESTRUCT then (tx2) CREATE2 "resurrection" of the same address in the same block. Parametrized over pre_balance: [0, 100]. Two identical txs invoke the same factory with the same initcode (same hash → same CREATE2 address A). The factory branches on its own storage[1]: on the first tx, slot 1 is 0 so the factory CREATE2's then CALLs A (runtime SELFDESTRUCTs to beneficiary) and records the CALL's return code in slot 1; on the second tx, slot 1 is non-zero so only CREATE2 runs and A persists. When pre_balance > 0, A is pre-funded so Tx1's SELFDESTRUCT transfers a real balance. At block_access_index=1 (destructed A): MUST NOT include nonce_changes or code_changes for A (EIP-7928 SELFDESTRUCT-in-tx semantics). balance_changes for A appears only when pre-funded. Beneficiary appears with balance_changes if pre-funded, otherwise empty() (SELFDESTRUCT touches the beneficiary even with 0 value). At block_access_index=2 (resurrection): A has nonce_changes (post=1) and code_changes (post=runtime). Factory's storage[1] = 1 confirms the Tx1 CALL went through. ✅ Completed
test_bal_call_with_value_in_static_context CALL with nonzero value in static context: target NOT in BAL Parametrized: target_is_warm (cold/warm via access list), target_has_code (EOA/contract). Static check must fire before account access. target MUST NOT appear in BAL. Balances unchanged. ✅ Completed
test_bal_create_in_static_context CREATE/CREATE2 in static context: created address NOT in BAL Parametrized: @pytest.mark.with_all_create_opcodes, value (0/1). Static check must fire before balance check, address computation, or nonce increment. Created address MUST NOT appear in BAL. Factory nonce unchanged. ✅ Completed
test_bal_selfdestruct_in_static_context SELFDESTRUCT in static context: beneficiary NOT in BAL Parametrized: beneficiary_is_warm (cold/warm via access list), caller_balance (0/100). Static check must fire before beneficiary access or balance transfer. beneficiary MUST NOT appear in BAL. Balances unchanged. ✅ Completed
test_bal_call_opcode_succeeds_in_static_context All call opcodes (no value) succeed in static context Parametrized: @pytest.mark.with_all_call_opcodes. Caller invokes call_opcode(target) inside STATICCALL. target MUST appear in BAL. Ensures clients don't over-restrict beyond EIP-214. ✅ Completed
test_bal_callcode_with_value_in_static_context CALLCODE with nonzero value succeeds in static context EIP-214 explicitly excludes CALLCODE from write-protection. Caller invokes CALLCODE(value=1, target) inside STATICCALL. target MUST appear in BAL. Ensures clients don't apply CALL-with-value restriction to CALLCODE. ✅ Completed
test_bal_create_and_oog CREATE/CREATE2 OOG boundary test at three gas levels Parametrized: @pytest.mark.with_all_create_opcodes, OutOfGasBoundary (OOG_BEFORE_TARGET_ACCESS, OOG_AFTER_TARGET_ACCESS, SUCCESS). BEFORE and AFTER differ by 1 gas, proving the static cost boundary. OOG_BEFORE: created address MUST NOT appear in BAL. OOG_AFTER: created address IS in BAL as empty() (accessed, state reverted). SUCCESS: created address in BAL with nonce_changes/code_changes. ✅ Completed