Skip to content

Commit 85b7f8a

Browse files
authored
feat(tests): 8037-Add tests for 7702 interactions (ethereum#2722)
* feat(tests): 8037 - test 7702 auth state-gas tests for top-level failure * refactor(tests): Fix per PR reviews
1 parent 5416cbb commit 85b7f8a

1 file changed

Lines changed: 183 additions & 0 deletions

File tree

tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_set_code.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
Storage,
2727
Transaction,
2828
TransactionException,
29+
TransactionReceipt,
2930
)
3031

32+
from tests.prague.eip7702_set_code_tx.spec import Spec as Spec7702
33+
3134
from .spec import ref_spec_8037
3235

3336
REFERENCE_SPEC_GIT_PATH = ref_spec_8037.git_path
@@ -1253,3 +1256,183 @@ def test_existing_auth_refund_survives_top_level_revert(
12531256
tx=tx,
12541257
blockchain_test_header_verify=Header(gas_used=expected_gas_used),
12551258
)
1259+
1260+
1261+
@pytest.mark.parametrize(
1262+
"failure_mode",
1263+
[
1264+
pytest.param("revert", id="revert"),
1265+
pytest.param("halt", id="halt"),
1266+
pytest.param("oog", id="oog"),
1267+
],
1268+
)
1269+
@pytest.mark.parametrize(
1270+
"authority_exists",
1271+
[
1272+
pytest.param(False, id="new_account"),
1273+
pytest.param(True, id="existing_account"),
1274+
],
1275+
)
1276+
@pytest.mark.valid_from("EIP8037")
1277+
def test_auth_state_gas_in_header_after_failure(
1278+
state_test: StateTestFiller,
1279+
pre: Alloc,
1280+
fork: Fork,
1281+
failure_mode: str,
1282+
authority_exists: bool,
1283+
) -> None:
1284+
"""
1285+
Verify block header reflects intrinsic state gas from a 7702
1286+
authorization when the top-level tx fails.
1287+
1288+
Execution state gas is zeroed on failure but intrinsic state gas
1289+
is preserved. For existing-account auths the spec subtracts the
1290+
auth refund from `tx_state_gas`, reducing the state component.
1291+
The delegation indicator persists (set before the execution
1292+
snapshot). Parametrized across all failure modes (revert/halt/oog)
1293+
and authority states (new vs existing).
1294+
"""
1295+
gas_limit_cap = fork.transaction_gas_limit_cap()
1296+
assert gas_limit_cap is not None
1297+
1298+
auth_intrinsic_state = fork.transaction_intrinsic_state_gas(
1299+
authorization_count=1,
1300+
)
1301+
intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
1302+
intrinsic_total = intrinsic_cost(authorization_list_or_count=1)
1303+
intrinsic_regular = intrinsic_total - auth_intrinsic_state
1304+
auth_refund = (
1305+
fork.gas_costs().REFUND_AUTH_PER_EXISTING_ACCOUNT
1306+
if authority_exists
1307+
else 0
1308+
)
1309+
1310+
delegate = pre.deploy_contract(code=Op.STOP)
1311+
1312+
if failure_mode == "revert":
1313+
revert_code = Op.REVERT(0, 0)
1314+
target = pre.deploy_contract(code=revert_code)
1315+
elif failure_mode == "halt":
1316+
target = pre.deploy_contract(code=Op.INVALID)
1317+
else:
1318+
target = pre.deploy_contract(code=Op.JUMPDEST + Op.JUMP(0x0))
1319+
1320+
if authority_exists:
1321+
signer = pre.fund_eoa()
1322+
else:
1323+
signer = pre.fund_eoa(0)
1324+
1325+
tx_gas = gas_limit_cap + auth_intrinsic_state
1326+
1327+
tx = Transaction(
1328+
ty=4,
1329+
to=target,
1330+
gas_limit=tx_gas,
1331+
sender=pre.fund_eoa(),
1332+
authorization_list=[
1333+
AuthorizationTuple(
1334+
address=delegate,
1335+
nonce=0,
1336+
signer=signer,
1337+
),
1338+
],
1339+
)
1340+
1341+
if failure_mode == "revert":
1342+
block_regular = intrinsic_regular + revert_code.gas_cost(fork)
1343+
else:
1344+
block_regular = tx_gas - auth_intrinsic_state
1345+
1346+
expected_gas_used = max(block_regular, auth_intrinsic_state - auth_refund)
1347+
1348+
state_test(
1349+
pre=pre,
1350+
post={
1351+
signer: Account(
1352+
code=Spec7702.delegation_designation(delegate),
1353+
),
1354+
},
1355+
tx=tx,
1356+
blockchain_test_header_verify=Header(gas_used=expected_gas_used),
1357+
)
1358+
1359+
1360+
@pytest.mark.parametrize(
1361+
"authority_exists",
1362+
[
1363+
pytest.param(False, id="new_account"),
1364+
pytest.param(True, id="existing_account"),
1365+
],
1366+
)
1367+
@pytest.mark.valid_from("EIP8037")
1368+
def test_auth_sender_billing_after_failure(
1369+
state_test: StateTestFiller,
1370+
pre: Alloc,
1371+
fork: Fork,
1372+
authority_exists: bool,
1373+
) -> None:
1374+
"""
1375+
Verify sender billing distinguishes new vs existing account auth
1376+
on top-level failure.
1377+
1378+
For existing accounts, set_delegation refunds new-account state
1379+
gas to the reservoir. On REVERT, the restored reservoir reduces
1380+
the sender's bill via the billing formula. The sender pays less
1381+
than in the new-account case by exactly the refund amount.
1382+
"""
1383+
gas_limit_cap = fork.transaction_gas_limit_cap()
1384+
assert gas_limit_cap is not None
1385+
1386+
auth_intrinsic_state = fork.transaction_intrinsic_state_gas(
1387+
authorization_count=1,
1388+
)
1389+
intrinsic_cost = fork.transaction_intrinsic_cost_calculator()
1390+
intrinsic_total = intrinsic_cost(authorization_list_or_count=1)
1391+
intrinsic_regular = intrinsic_total - auth_intrinsic_state
1392+
new_account_refund = fork.gas_costs().REFUND_AUTH_PER_EXISTING_ACCOUNT
1393+
1394+
delegate = pre.deploy_contract(code=Op.STOP)
1395+
target = pre.deploy_contract(code=Op.REVERT(0, 0))
1396+
1397+
if authority_exists:
1398+
signer = pre.fund_eoa()
1399+
else:
1400+
signer = pre.fund_eoa(0)
1401+
1402+
tx_gas = gas_limit_cap + auth_intrinsic_state
1403+
1404+
revert_gas = (Op.REVERT(0, 0)).gas_cost(fork)
1405+
auth_refund = new_account_refund if authority_exists else 0
1406+
expected_cumulative = intrinsic_total + revert_gas - auth_refund
1407+
expected_gas_used = max(
1408+
intrinsic_regular + revert_gas,
1409+
auth_intrinsic_state - auth_refund,
1410+
)
1411+
1412+
tx = Transaction(
1413+
ty=4,
1414+
to=target,
1415+
gas_limit=tx_gas,
1416+
sender=pre.fund_eoa(),
1417+
authorization_list=[
1418+
AuthorizationTuple(
1419+
address=delegate,
1420+
nonce=0,
1421+
signer=signer,
1422+
),
1423+
],
1424+
expected_receipt=TransactionReceipt(
1425+
cumulative_gas_used=expected_cumulative,
1426+
),
1427+
)
1428+
1429+
state_test(
1430+
pre=pre,
1431+
post={
1432+
signer: Account(
1433+
code=Spec7702.delegation_designation(delegate),
1434+
),
1435+
},
1436+
tx=tx,
1437+
blockchain_test_header_verify=Header(gas_used=expected_gas_used),
1438+
)

0 commit comments

Comments
 (0)