Skip to content

test_bal_7702_double_auth_reset()

Documentation for tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip7702.py::test_bal_7702_double_auth_reset@20373115.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip7702.py::test_bal_7702_double_auth_reset --fork Amsterdam

Ensure BAL captures the net code change when multiple authorizations occur in the same transaction (double auth).

This test verifies that when: 1. First auth sets delegation to CONTRACT_A 2. Second auth resets delegation to empty (address 0)

Scenario where the transaction is sponsored and self-funded are covered.

The BAL should show the NET change (empty -> empty), not intermediate states. This is a regression test for the bug where the BAL showed the first auth's code but the final state was empty.

Source code in tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_eip7702.py
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
@pytest.mark.parametrize(
    "self_funded",
    [
        pytest.param(False, id="sponsored"),
        pytest.param(True, id="self_funded"),
    ],
)
def test_bal_7702_double_auth_reset(
    pre: Alloc,
    blockchain_test: BlockchainTestFiller,
    self_funded: bool,
) -> None:
    """
    Ensure BAL captures the net code change when multiple authorizations
    occur in the same transaction (double auth).

    This test verifies that when:
    1. First auth sets delegation to CONTRACT_A
    2. Second auth resets delegation to empty (address 0)

    Scenario where the transaction is sponsored and self-funded are covered.

    The BAL should show the NET change (empty -> empty), not intermediate
    states. This is a regression test for the bug where the BAL showed
    the first auth's code but the final state was empty.
    """
    alice = pre.fund_eoa()
    bob = pre.fund_eoa(amount=0)
    relayer = pre.fund_eoa()

    contract_a = pre.deploy_contract(code=Op.STOP)

    # Transaction with double auth:
    # 1. First sets delegation to contract_a
    # 2. Second resets to empty
    tx = Transaction(
        sender=alice if self_funded else relayer,
        to=bob,
        value=10,
        gas_limit=1_000_000,
        gas_price=0xA,
        authorization_list=[
            AuthorizationTuple(
                address=contract_a,
                nonce=1 if self_funded else 0,
                signer=alice,
            ),
            AuthorizationTuple(
                address=0,  # Reset to empty
                nonce=2 if self_funded else 1,
                signer=alice,
            ),
        ],
    )

    alice_nonce = 3 if self_funded else 2
    relayer_nonce = 1 if not self_funded else 0
    relayer_bal_expectation = (
        BalAccountExpectation(
            nonce_changes=[BalNonceChange(block_access_index=1, post_nonce=1)]
        )
        if not self_funded
        else None
    )

    blockchain_test(
        pre=pre,
        blocks=[
            Block(
                txs=[tx],
                expected_block_access_list=BlockAccessListExpectation(
                    account_expectations={
                        alice: BalAccountExpectation(
                            nonce_changes=[
                                BalNonceChange(
                                    block_access_index=1,
                                    post_nonce=alice_nonce,
                                )
                            ],
                            code_changes=[],
                        ),
                        bob: BalAccountExpectation(
                            balance_changes=[
                                BalBalanceChange(
                                    block_access_index=1, post_balance=10
                                )
                            ]
                        ),
                        relayer: relayer_bal_expectation,
                        contract_a: None,
                    }
                ),
            )
        ],
        post={
            alice: Account(nonce=alice_nonce, code=b""),  # Final code is empty
            bob: Account(balance=10),
            relayer: Account(nonce=relayer_nonce),
        },
    )

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.