Skip to content

test_top_frame_execution_charge()

Documentation for tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.py::test_top_frame_execution_charge@26332146.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.py::test_top_frame_execution_charge --fork Amsterdam

Recipient is an existing EIP-7702 delegation, so the top-frame fires the COLD_ACCOUNT_ACCESS execution-gas charge regardless of whether the transaction transfers value.

  • oog: gas limit is one short of covering the execution charge (plus the value-transfer charge when value > 0). The transaction OOGs at charge_gas(COLD_ACCOUNT_ACCESS) before the delegated code runs. The sender pays the full gas_limit and the recipient keeps its pre-tx state.
  • success: gas limit covers the execution charge; the delegated code is a STOP and the transaction lands the value transfer.
  • evm_reverts: the delegated code reverts immediately. The top-frame charge is consumed before dispatch and the two PUSH opcodes that feed the REVERT are paid before the revert; the value transfer is rolled back, the unused EVM budget is returned, and the intrinsic and top-frame gas remain paid.
Source code in tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.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
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
@pytest.mark.parametrize("outcome", ["oog", "success", "evm_reverts"])
@pytest.mark.parametrize(
    "value",
    [
        pytest.param(0, id="zero_value"),
        pytest.param(1, id="non-zero_value"),
    ],
)
def test_top_frame_execution_charge(
    fork: Fork,
    pre: Alloc,
    state_test: StateTestFiller,
    outcome: str,
    value: int,
) -> None:
    """
    Recipient is an existing EIP-7702 delegation, so the top-frame
    fires the ``COLD_ACCOUNT_ACCESS`` execution-gas charge regardless of
    whether the transaction transfers value.

    - ``oog``: gas limit is one short of covering the execution charge
      (plus the value-transfer charge when ``value > 0``). The
      transaction OOGs at ``charge_gas(COLD_ACCOUNT_ACCESS)`` before
      the delegated code runs. The sender pays the full ``gas_limit``
      and the recipient keeps its pre-tx state.
    - ``success``: gas limit covers the execution charge; the delegated
      code is a ``STOP`` and the transaction lands the value transfer.
    - ``evm_reverts``: the delegated code reverts immediately. The
      top-frame charge is consumed before dispatch and the two
      ``PUSH`` opcodes that feed the ``REVERT`` are paid before the
      revert; the value transfer is rolled back, the unused EVM
      budget is returned, and the intrinsic and top-frame gas remain
      paid.
    """
    sender_initial_balance = 10**18
    sender = pre.fund_eoa(sender_initial_balance)

    revert_code = Op.REVERT(0, 0)
    if outcome == "evm_reverts":
        delegated_to = pre.deploy_contract(code=revert_code)
    else:
        delegated_to = pre.deploy_contract(code=Op.STOP)
    target_code = Spec7702.delegation_designation(delegated_to)
    target = pre.deploy_contract(code=target_code)

    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_gas_calculator()(
        sends_value=bool(value),
        recipient_type=RecipientType.DELEGATION_7702,
    )
    assert top_frame_gas > 0, (
        "top-frame execution gas must be non-zero for this scenario"
    )

    gas_price = 1_000_000_000
    if outcome == "oog":
        gas_limit = intrinsic_gas + top_frame_gas - 1
        sender_final_balance = sender_initial_balance - gas_limit * gas_price
        target_balance = 0
    elif outcome == "success":
        total_gas_cost = intrinsic_gas + top_frame_gas
        gas_limit = total_gas_cost + 1000
        sender_final_balance = (
            sender_initial_balance - value - total_gas_cost * gas_price
        )
        target_balance = value
    else:
        # Two ``PUSH`` opcodes feed ``REVERT`` before it halts.
        revert_exec_gas = revert_code.gas_cost(fork)
        gas_used = intrinsic_gas + top_frame_gas + revert_exec_gas
        gas_limit = gas_used + 1000
        # Value transfer is rolled back, so the sender keeps the
        # would-be transferred value. The intrinsic, top-frame, and
        # pre-revert EVM gas stay paid.
        sender_final_balance = sender_initial_balance - gas_used * gas_price
        target_balance = 0

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

    post = {
        sender: Account(nonce=1, balance=sender_final_balance),
        target: Account(balance=target_balance, code=target_code),
    }

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

Parametrized Test Cases

This test generates 6 parametrized test cases across 1 fork.