Skip to content

test_top_frame_charges_delegation_is_recipient()

Documentation for tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_warmth_invariants.py::test_top_frame_charges_delegation_is_recipient@622620d8.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_warmth_invariants.py::test_top_frame_charges_delegation_is_recipient --fork Amsterdam

Recipient holds a pre-existing EIP-7702 delegation pointing back at itself. The delegation target is the recipient, which is warm, so the top-frame charges WARM_ACCESS, and then the dispatched EVM frame runs the recipient's code -- which is the delegation prefix 0xef 01 00 <addr>. The leading 0xef decodes as the INVALID opcode, consuming the remaining EVM budget. The intrinsic and top-frame gas remain paid; the value transfer is rolled back.

Source code in tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_warmth_invariants.py
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
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
@pytest.mark.parametrize(
    "value",
    [
        pytest.param(0, id="zero_value"),
        pytest.param(1, id="non-zero_value"),
    ],
)
def test_top_frame_charges_delegation_is_recipient(
    fork: Fork,
    pre: Alloc,
    state_test: StateTestFiller,
    value: int,
) -> None:
    """
    Recipient holds a pre-existing EIP-7702 delegation pointing back
    at itself. The delegation target is the recipient, which is warm,
    so the top-frame charges ``WARM_ACCESS``, and then the dispatched
    EVM frame runs the recipient's code -- which *is* the delegation
    prefix ``0xef 01 00 <addr>``. The leading ``0xef`` decodes as the
    ``INVALID`` opcode, consuming the remaining EVM budget. The
    intrinsic and top-frame gas remain paid; the value transfer is
    rolled back.
    """
    sender_initial_balance = 10**18
    sender = pre.fund_eoa(sender_initial_balance)

    # Pre-allocate an EOA that delegates to itself. The 1-wei balance
    # keeps the account alive at top-frame check time so the
    # ``NEW_ACCOUNT`` charge does not fire.
    target = pre.fund_eoa(amount=1, delegation="Self")
    target_code = Spec7702.delegation_designation(target)

    intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(
        sends_value=bool(value),
        recipient_type=RecipientType.DELEGATION_7702,
        return_cost_deducted_prior_execution=True,
    )
    top_frame_gas = fork.transaction_top_frame_execution_gas(
        sends_value=bool(value),
        recipient_type=RecipientType.DELEGATION_7702,
        delegation_warm=True,
    )

    # The dispatched frame burns the entire EVM budget on the
    # ``INVALID`` opcode and the value transfer is rolled back, so the
    # sender pays the full ``gas_limit``.
    gas_price = 1_000_000_000
    gas_limit = intrinsic_gas + top_frame_gas + 50_000

    tx = Transaction(
        sender=sender,
        to=target,
        value=value,
        gas_limit=gas_limit,
        gas_price=gas_price,
    )

    sender_final_balance = sender_initial_balance - gas_limit * gas_price

    post = {
        sender: Account(nonce=1, balance=sender_final_balance),
        # Value transfer rolled back by the ``INVALID``; the pre-tx
        # 1-wei balance is preserved.
        target: Account(balance=1, code=target_code),
    }

    state_test(pre=pre, tx=tx, post=post)

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.