Skip to content

test_auth_state_gas_in_header_on_dispatch_revert()

Documentation for tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_authorization_oog.py::test_auth_state_gas_in_header_on_dispatch_revert@26332146.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_authorization_oog.py::test_auth_state_gas_in_header_on_dispatch_revert --fork Amsterdam

The state gas of an applied authorization is counted in the block's state dimension when the dispatched call reverts.

The header gas_used is max(block_execution_gas, block_state_gas). The authorization creates and delegates a fresh authority (218,790 state gas), which dominates the small execution side (intrinsic + ACCOUNT_WRITE + the pre-revert execution), so a correct accounting yields gas_used == 218,790 even though the dispatched call reverts -- the delegation, and the state it grew, persist.

A regression that refills the authorization's state gas on the frame's rollback collapses tx_state_gas to zero and the header to the small execution sum, which balance-only state tests cannot distinguish from a correctly-split total.

Source code in tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_authorization_oog.py
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
def test_auth_state_gas_in_header_on_dispatch_revert(
    fork: Fork,
    pre: Alloc,
    blockchain_test: BlockchainTestFiller,
) -> None:
    """
    The state gas of an applied authorization is counted in the block's
    state dimension when the dispatched call reverts.

    The header ``gas_used`` is ``max(block_execution_gas,
    block_state_gas)``. The authorization creates and delegates a fresh
    authority (218,790 state gas), which dominates the small execution
    side (intrinsic + ``ACCOUNT_WRITE`` + the pre-revert execution), so
    a correct accounting yields ``gas_used == 218,790`` even though the
    dispatched call reverts -- the delegation, and the state it grew,
    persist.

    A regression that refills the authorization's state gas on the
    frame's rollback collapses ``tx_state_gas`` to zero and the header
    to the small execution sum, which balance-only state tests cannot
    distinguish from a correctly-split total.
    """
    sender = pre.fund_eoa()

    revert_code = Op.REVERT(0, 0)
    recipient = pre.deploy_contract(code=revert_code)

    auth = build_authorization(pre, AuthorizationAction.CREATES_ACCOUNT)
    authorization_list = [auth.authorization]

    intrinsic_execution = _intrinsic_execution(
        fork, authorization_list, recipient_type=RecipientType.CONTRACT
    )
    auth_execution = fork.transaction_top_frame_gas_calculator()(
        recipient_type=RecipientType.CONTRACT,
        authorizations=authorization_list,
    )
    auth_state = fork.transaction_top_frame_state_gas(
        recipient_type=RecipientType.CONTRACT,
        authorizations=authorization_list,
    )
    revert_exec_gas = revert_code.gas_cost(fork)

    execution_total = intrinsic_execution + auth_execution + revert_exec_gas
    assert auth_state > execution_total, (
        "the state dimension must dominate for the header to pin it"
    )
    expected_gas_used = max(execution_total, auth_state)

    tx = Transaction(
        sender=sender,
        to=recipient,
        value=0,
        authorization_list=authorization_list,
    )

    blockchain_test(
        pre=pre,
        blocks=[
            Block(
                txs=[tx],
                header_verify=Header(gas_used=expected_gas_used),
            ),
        ],
        post={
            sender: Account(nonce=1),
            auth.authority: auth.applied_account,
            recipient: Account(code=revert_code, balance=0),
        },
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.