Skip to content

test_calldata_floor_survives_state_refund()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_calldata_floor.py::test_calldata_floor_survives_state_refund@622620d8.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_calldata_floor.py::test_calldata_floor_survives_state_refund --fork Amsterdam

Verify a refund cannot push the sender's bill under the floor.

The transaction runs a 0 to x to 0 cycle, which both refunds its state charge and earns a write-cost refund, while carrying enough calldata for the floor to bind. The floor is applied after refunds, so the sender still pays it in full.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_calldata_floor.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
@pytest.mark.valid_from("EIP8037")
def test_calldata_floor_survives_state_refund(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
) -> None:
    """
    Verify a refund cannot push the sender's bill under the floor.

    The transaction runs a 0 to x to 0 cycle, which both refunds its
    state charge and earns a write-cost refund, while carrying enough
    calldata for the floor to bind. The floor is applied after refunds,
    so the sender still pays it in full.
    """
    code = Op.SSTORE(0, 1) + Op.SSTORE(
        0,
        0,
        # gas accounting
        key_warm=True,
        original_value=0,
        current_value=1,
        new_value=0,
    )
    assert code.refund(fork) > 0, "the cycle must earn a refund"

    calldata = b"\x00" * 5000
    floor = fork.transaction_data_floor_cost_calculator()(data=calldata)
    intrinsic = fork.transaction_intrinsic_cost_calculator()(
        calldata=calldata,
        return_cost_deducted_prior_execution=True,
    )
    pre_refund_gas = intrinsic + code.execution_cost(fork)
    execution_refund = code.refund(fork) - code.state_refund(fork)
    post_refund_gas = pre_refund_gas - min(
        pre_refund_gas // fork.max_refund_quotient(), execution_refund
    )
    assert floor > post_refund_gas, (
        "the floor must bind after the refund is applied"
    )

    contract = pre.deploy_contract(code=code)

    tx = Transaction(
        to=contract,
        data=calldata,
        state_gas_reservoir=Op.SSTORE(new_value=1).state_cost(fork),
        sender=pre.fund_eoa(),
        expected_receipt=TransactionReceipt(cumulative_gas_used=floor),
    )
    state_test(
        pre=pre,
        post={contract: Account(storage={0: 0})},
        tx=tx,
        blockchain_test_header_verify=Header(gas_used=floor),
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.