Skip to content

test_zero_amount()

Documentation for tests/shanghai/eip4895_withdrawals/test_withdrawals.py::test_zero_amount@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/shanghai/eip4895_withdrawals/test_withdrawals.py::test_zero_amount --fork Bogota

Test withdrawal scenarios with a zero amount in a single block.

All the withdrawals in the following scenarios are included in one block.

  1. Two withdrawals of zero amount to two different addresses; one to an untouched account, one to an account with a balance.

  2. As 1., but with an additional withdrawal with positive value.

  3. As 2., but with an additional withdrawal containing the maximum value possible.

  4. As 3., but with order of withdrawals in the block reversed.

Source code in tests/shanghai/eip4895_withdrawals/test_withdrawals.py
@pytest.mark.parametrize(
    "test_case",
    list(ZeroAmountTestCases),
    ids=[case.value for case in ZeroAmountTestCases],
)
@pytest.mark.eels_base_coverage
def test_zero_amount(
    blockchain_test: BlockchainTestFiller,
    pre: Alloc,
    test_case: ZeroAmountTestCases,
) -> None:
    """
    Test withdrawal scenarios with a zero amount in a single block.

    All the withdrawals in the following scenarios are included in one block.

    1. Two withdrawals of zero amount to two different addresses; one to an
        untouched account, one to an account with a balance.

    2. As 1., but with an additional withdrawal with positive value.

    3. As 2., but with an additional withdrawal containing the maximum value
       possible.

    4. As 3., but with order of withdrawals in the block reversed.
    """
    empty_accounts = [pre.fund_eoa(0) for _ in range(3)]
    zero_balance_contract = pre.deploy_contract(Op.STOP)

    all_withdrawals = [
        # No value, untouched account
        Withdrawal(
            index=0,
            validator_index=0,
            address=empty_accounts[0],
            amount=0,
        ),
        # No value, touched account
        Withdrawal(
            index=0,
            validator_index=0,
            address=zero_balance_contract,
            amount=0,
        ),
        # Withdrawal with value
        Withdrawal(
            index=1,
            validator_index=0,
            address=empty_accounts[1],
            amount=1,
        ),
        # Withdrawal with maximum amount
        Withdrawal(
            index=2,
            validator_index=0,
            address=empty_accounts[2],
            amount=2**64 - 1,
        ),
    ]
    all_post: Dict[Address, Account | None] = {
        empty_accounts[0]: Account.NONEXISTENT,
        zero_balance_contract: Account(code=Op.STOP, balance=0),
        empty_accounts[1]: Account(balance=ONE_GWEI),
        empty_accounts[2]: Account(balance=(2**64 - 1) * ONE_GWEI),
    }

    withdrawals: List[Withdrawal] = []
    post: Dict[Address, Account | None]
    if test_case == ZeroAmountTestCases.TWO_ZERO:
        withdrawals = all_withdrawals[0:2]
        post = {
            account: all_post[account]
            for account in [empty_accounts[0], zero_balance_contract]
        }
    elif test_case == ZeroAmountTestCases.THREE_ONE_WITH_VALUE:
        withdrawals = all_withdrawals[0:3]
        post = {
            account: all_post[account]
            for account in [
                empty_accounts[0],
                zero_balance_contract,
                empty_accounts[1],
            ]
        }
    elif test_case == ZeroAmountTestCases.FOUR_ONE_WITH_MAX:
        withdrawals = all_withdrawals
        post = all_post
    elif test_case == ZeroAmountTestCases.FOUR_ONE_WITH_MAX_REVERSED:
        for i, w in enumerate(reversed(all_withdrawals)):
            withdrawals.append(
                Withdrawal(
                    index=i,
                    validator_index=w.validator_index,
                    address=w.address,
                    amount=w.amount,
                )
            )
        post = all_post

    blockchain_test(
        pre=pre,
        post=post,
        blocks=[Block(withdrawals=withdrawals)],
    )

Parametrized Test Cases

This test generates 4 parametrized test cases across 6 forks.