Skip to content

test_block_2d_gas_valid_when_cumulative_exceeds_limit()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py::test_block_2d_gas_valid_when_cumulative_exceeds_limit@c74f1a67.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py::test_block_2d_gas_valid_when_cumulative_exceeds_limit --fork Amsterdam

Verify block validity under 2D gas when sum(txGasUsed) > gas_limit.

EIP-8037 block validity: max(regular, state) <= gas_limit. Receipt cumulative_gas_used sums both dimensions per-tx, so it can legitimately exceed gas_limit. Clients must not use the 1D cumulative check for block validation.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py
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
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
@pytest.mark.valid_from("EIP8037")
def test_block_2d_gas_valid_when_cumulative_exceeds_limit(
    blockchain_test: BlockchainTestFiller,
    pre: Alloc,
    fork: Fork,
) -> None:
    """
    Verify block validity under 2D gas when sum(txGasUsed) > gas_limit.

    EIP-8037 block validity: max(regular, state) <= gas_limit.
    Receipt cumulative_gas_used sums both dimensions per-tx, so it
    can legitimately exceed gas_limit. Clients must not use the 1D
    cumulative check for block validation.
    """
    block_gas_limit = 100_000_000

    sstore_code = Op.SSTORE(0, 1, new_value=1)
    sstore_state_gas = sstore_code.state_cost(fork)

    tx_regular = (
        sstore_code.regular_cost(fork)
        + fork.transaction_intrinsic_cost_calculator()()
    )
    tx_state = sstore_state_gas
    tx_gas_used = tx_regular + tx_state

    assert tx_state > tx_regular
    block_gas_used = tx_state

    env = Environment(gas_limit=block_gas_limit)
    tx_limit = tx_gas_used + 1000

    # Strict rule counts full `tx.gas` per dimension; state is the
    # binding one (tx_state > tx_regular), so every `tx_limit` must
    # fit the remaining state gas.
    num_txs = (block_gas_limit - tx_limit) // tx_state + 1
    two_d_bound = num_txs * block_gas_used
    one_d_bound = num_txs * tx_gas_used
    assert two_d_bound <= block_gas_limit < one_d_bound

    txs = []
    post = {}
    for _ in range(num_txs):
        storage = Storage()
        contract = pre.deploy_contract(
            code=Op.SSTORE(storage.store_next(1), 1),
        )
        txs.append(
            Transaction(
                to=contract,
                gas_limit=tx_limit,
                sender=pre.fund_eoa(),
            ),
        )
        post[contract] = Account(storage=storage)

    blockchain_test(
        genesis_environment=env,
        pre=pre,
        blocks=[
            Block(
                txs=txs,
                gas_limit=block_gas_limit,
                header_verify=Header(
                    gas_used=num_txs * block_gas_used,
                ),
            ),
        ],
        post=post,
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.