Skip to content

test_create_tx_header_gas_used()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_create.py::test_create_tx_header_gas_used@87aba1a3.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_create.py::test_create_tx_header_gas_used --fork Amsterdam

Verify block header gas_used for a successful CREATE transaction.

A contract creation tx (to=None) with known gas costs. Compute exact gas_used from first principles and verify against the block header. Catches bugs where clients report gas_limit instead of actual consumed gas.

For a fresh target the top-frame NEW_ACCOUNT state gas is charged and dominates the regular gas, so gas_used == NEW_ACCOUNT. For a pre-existing balance-only leaf the target is not EMPTY pre-tx, so the top-frame NEW_ACCOUNT is never charged: net state gas is zero and only the regular dimension remains. The block-level calldata floor tops up that regular remainder, so the expected value is the greater of the regular intrinsic and the floor, and fails if a stray NEW_ACCOUNT is charged.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_create.py
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
@pytest.mark.parametrize(
    "target",
    [
        pytest.param("new", id="new_account"),
        pytest.param("existing", id="existing_account"),
    ],
)
@pytest.mark.pre_alloc_mutable()
@pytest.mark.valid_from("EIP8037")
def test_create_tx_header_gas_used(
    blockchain_test: BlockchainTestFiller,
    pre: Alloc,
    fork: Fork,
    target: str,
) -> None:
    """
    Verify block header gas_used for a successful CREATE transaction.

    A contract creation tx (to=None) with known gas costs. Compute
    exact gas_used from first principles and verify against the block
    header. Catches bugs where clients report gas_limit instead of
    actual consumed gas.

    For a fresh target the top-frame NEW_ACCOUNT state gas is charged and
    dominates the regular gas, so gas_used == NEW_ACCOUNT. For a
    pre-existing balance-only leaf the target is not EMPTY pre-tx, so the
    top-frame NEW_ACCOUNT is never charged: net state gas is zero and only
    the regular dimension remains. The block-level calldata floor tops up
    that regular remainder, so the expected value is the greater of the
    regular intrinsic and the floor, and fails if a stray NEW_ACCOUNT is
    charged.
    """
    gas_costs = fork.gas_costs()
    initcode = Op.STOP
    create_state_gas = fork.create_state_gas(code_size=1)

    if target == "existing":
        sender = pre.fund_eoa(nonce=0)
        contract_address = compute_create_address(address=sender, nonce=0)
        # Balance-only leaf: alive and deployable, so the creation
        # succeeds and (being non-EMPTY pre-tx) the top-frame NEW_ACCOUNT
        # is never charged.
        pre.fund_address(contract_address, amount=1)
    else:
        sender = pre.fund_eoa()

    tx = Transaction(
        to=None,
        data=initcode,
        state_gas_reservoir=create_state_gas,
        sender=sender,
    )

    # block_gas_used = max(block_regular, block_state)
    if target == "existing":
        intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
        # Regular-only creation intrinsic; STOP initcode deploys empty
        # code (zero deposit) and the pre-existing target adds no state
        # gas. The block-level calldata floor tops up this small regular
        # remainder and, being the larger of the two, is what the header
        # reflects (the floor applies to block-level regular gas).
        regular_intrinsic = intrinsic_cost(
            calldata=bytes(initcode),
            contract_creation=True,
            return_cost_deducted_prior_execution=True,
        )
        floor = fork.transaction_data_floor_cost_calculator()(
            data=bytes(initcode), contract_creation=True
        )
        assert floor > regular_intrinsic, (
            "the floor must bind for this arm to pin floor-in-header"
        )
        expected_gas_used = max(regular_intrinsic, floor)
    else:
        # For a minimal CREATE tx deploying Op.STOP (1 byte),
        # state gas (new account) dominates regular gas.
        expected_gas_used = gas_costs.NEW_ACCOUNT

    blockchain_test(
        pre=pre,
        blocks=[
            Block(
                txs=[tx],
                header_verify=Header(gas_used=expected_gas_used),
            ),
        ],
        post={},
    )

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.