Skip to content

test_bal_4788_selfdestruct_to_beacon_root()

Documentation for tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip4788.py::test_bal_4788_selfdestruct_to_beacon_root@20373115.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip4788.py::test_bal_4788_selfdestruct_to_beacon_root --fork Amsterdam

Ensure BAL captures SELFDESTRUCT to beacon root address alongside system call storage writes.

Single block with pre-execution system call writing beacon root to storage, followed by transaction where contract selfdestructs sending funds to BEACON_ROOTS_ADDRESS. Tests that same address can appear in BAL with different change types (storage_changes and balance_changes) at different transaction indices.

Source code in tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip4788.py
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
def test_bal_4788_selfdestruct_to_beacon_root(
    pre: Alloc,
    blockchain_test: BlockchainTestFiller,
    fork: Fork,
) -> None:
    """
    Ensure BAL captures SELFDESTRUCT to beacon root address alongside
    system call storage writes.

    Single block with pre-execution system call writing beacon root to
    storage, followed by transaction where contract selfdestructs sending
    funds to BEACON_ROOTS_ADDRESS. Tests that same address can appear in
    BAL with different change types (storage_changes and balance_changes)
    at different transaction indices.
    """
    alice = pre.fund_eoa()

    block_timestamp = 12
    beacon_root = Hash(0xABCDEF)
    contract_balance = 100

    # Contract that selfdestructs to beacon root address
    selfdestruct_code = Op.SELFDESTRUCT(BEACON_ROOTS_ADDRESS)
    selfdestruct_contract = pre.deploy_contract(
        code=selfdestruct_code,
        balance=contract_balance,
    )

    tx = Transaction(
        sender=alice,
        to=selfdestruct_contract,
        gas_limit=fork.transaction_gas_limit_cap(),
    )

    # Build BAL expectations starting with system call
    account_expectations = beacon_root_system_call_expectations(
        block_timestamp, beacon_root
    )

    # Add balance change from selfdestruct to beacon root address
    account_expectations[BEACON_ROOTS_ADDRESS].balance_changes = [
        BalBalanceChange(block_access_index=1, post_balance=contract_balance)
    ]

    # Add transaction-specific expectations
    account_expectations[alice] = BalAccountExpectation(
        nonce_changes=[BalNonceChange(block_access_index=1, post_nonce=1)],
    )
    account_expectations[selfdestruct_contract] = BalAccountExpectation(
        balance_changes=[
            BalBalanceChange(block_access_index=1, post_balance=0)
        ],
    )

    block = Block(
        txs=[tx],
        parent_beacon_block_root=beacon_root,
        timestamp=block_timestamp,
        expected_block_access_list=BlockAccessListExpectation(
            account_expectations=account_expectations
        ),
    )

    blockchain_test(
        pre=pre,
        blocks=[block],
        post={
            alice: Account(nonce=1),
            BEACON_ROOTS_ADDRESS: Account(balance=contract_balance),
        },
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.