Skip to content

Commit fe54c2e

Browse files
chore(test-tests): Fix EIP-7825 gas-cap test (ethereum#2250)
* fix: EIP-7825 gas-cap tests to compute access-list and auth-list bounds from fork intrinsic-cost logic, restoring amsterdam compatibility after EIP-7981 repricing * fix: ruff * fix: spencer feedback Co-authored-by: spencer <spencer.tb@ethereum.org> * fix: spencer feedback Co-authored-by: spencer <spencer.tb@ethereum.org> * fix: fix * fix: spencer feedback --------- Co-authored-by: spencer <spencer.tb@ethereum.org>
1 parent 916d723 commit fe54c2e

1 file changed

Lines changed: 72 additions & 46 deletions

File tree

tests/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Cap](https://eips.ethereum.org/EIPS/eip-7825).
66
"""
77

8-
from typing import List
8+
from typing import Callable, List
99

1010
import pytest
1111
from execution_testing import (
@@ -36,6 +36,27 @@
3636
REFERENCE_SPEC_VERSION = ref_spec_7825.version
3737

3838

39+
def max_count_with_intrinsic_cost_at_most(
40+
cost_fn: Callable[[int], int], gas_limit: int
41+
) -> int:
42+
"""Return the largest count where cost_fn(count) <= gas_limit."""
43+
low = 0
44+
high = 1
45+
46+
while cost_fn(high) <= gas_limit:
47+
low = high
48+
high *= 2
49+
50+
while low < high:
51+
mid = (low + high + 1) // 2
52+
if cost_fn(mid) <= gas_limit:
53+
low = mid
54+
else:
55+
high = mid - 1
56+
57+
return low
58+
59+
3960
def tx_gas_limit_cap_tests(fork: Fork) -> List[ParameterSet]:
4061
"""
4162
Return a list of tests for transaction gas limit cap parametrized for each
@@ -483,21 +504,22 @@ def test_tx_gas_limit_cap_access_list_with_diff_keys(
483504
assert tx_gas_limit_cap is not None, (
484505
"Fork does not have a transaction gas limit cap"
485506
)
486-
gas_available = tx_gas_limit_cap - intrinsic_cost()
487-
488-
gas_costs = fork.gas_costs()
489-
gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS
490-
gas_per_storage_key = gas_costs.G_ACCESS_LIST_STORAGE
507+
access_address = Address("0x1234567890123456789012345678901234567890")
491508

492-
gas_after_address = gas_available - gas_per_address
493-
num_storage_keys = gas_after_address // gas_per_storage_key + int(
494-
exceed_tx_gas_limit
495-
)
509+
def intrinsic_cost_for_num_storage_keys(storage_key_count: int) -> int:
510+
return intrinsic_cost(
511+
access_list=[
512+
AccessList(
513+
address=access_address,
514+
storage_keys=[Hash(i) for i in range(storage_key_count)],
515+
)
516+
]
517+
)
496518

497-
access_address = Address("0x1234567890123456789012345678901234567890")
498-
storage_keys = []
499-
for i in range(num_storage_keys):
500-
storage_keys.append(Hash(i))
519+
num_storage_keys = max_count_with_intrinsic_cost_at_most(
520+
intrinsic_cost_for_num_storage_keys, tx_gas_limit_cap
521+
) + int(exceed_tx_gas_limit)
522+
storage_keys = [Hash(i) for i in range(num_storage_keys)]
501523

502524
access_list = [
503525
AccessList(
@@ -568,23 +590,23 @@ def test_tx_gas_limit_cap_access_list_with_diff_addr(
568590
assert tx_gas_limit_cap is not None, (
569591
"Fork does not have a transaction gas limit cap"
570592
)
571-
gas_available = tx_gas_limit_cap - intrinsic_cost()
572593

573-
gas_costs = fork.gas_costs()
574-
gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS
575-
gas_per_storage_key = gas_costs.G_ACCESS_LIST_STORAGE
594+
def make_access_list(account_count: int) -> List[AccessList]:
595+
return [
596+
AccessList(
597+
address=Address(i + 1),
598+
storage_keys=[Hash(i)],
599+
)
600+
for i in range(account_count)
601+
]
576602

577-
account_num = gas_available // (
578-
gas_per_address + gas_per_storage_key
579-
) + int(exceed_tx_gas_limit)
603+
def intrinsic_cost_for_num_accounts(account_count: int) -> int:
604+
return intrinsic_cost(access_list=make_access_list(account_count))
580605

581-
access_list = [
582-
AccessList(
583-
address=pre.fund_eoa(),
584-
storage_keys=[Hash(i)],
585-
)
586-
for i in range(account_num)
587-
]
606+
account_num = max_count_with_intrinsic_cost_at_most(
607+
intrinsic_cost_for_num_accounts, tx_gas_limit_cap
608+
) + int(exceed_tx_gas_limit)
609+
access_list = make_access_list(account_num)
588610

589611
correct_intrinsic_cost = intrinsic_cost(access_list=access_list)
590612
if exceed_tx_gas_limit:
@@ -645,36 +667,40 @@ def test_tx_gas_limit_cap_authorized_tx(
645667
assert tx_gas_limit_cap is not None, (
646668
"Fork does not have a transaction gas limit cap"
647669
)
648-
gas_available = tx_gas_limit_cap - intrinsic_cost()
649670

650-
gas_costs = fork.gas_costs()
651-
gas_per_address = gas_costs.G_ACCESS_LIST_ADDRESS
671+
def make_access_list(auth_count: int) -> List[AccessList]:
672+
return [
673+
AccessList(
674+
address=Address(i + 1),
675+
storage_keys=[],
676+
)
677+
for i in range(auth_count)
678+
]
679+
680+
def intrinsic_cost_for_auth_list_length(auth_count: int) -> int:
681+
return intrinsic_cost(
682+
access_list=make_access_list(auth_count),
683+
authorization_list_or_count=auth_count,
684+
)
652685

653-
per_empty_account_cost = 25_000
654-
auth_list_length = gas_available // (
655-
gas_per_address + per_empty_account_cost
686+
auth_list_length = max_count_with_intrinsic_cost_at_most(
687+
intrinsic_cost_for_auth_list_length, tx_gas_limit_cap
656688
) + int(exceed_tx_gas_limit)
657689

658690
# EIP-7702 authorization transaction cost:
659691
# 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 *
660-
# access list storage key count + 2400 * access list address count +
661-
# PER_EMPTY_ACCOUNT_COST * authorization list length
692+
# access list storage key count + 2400 * access list address count + access
693+
# list data cost + PER_EMPTY_ACCOUNT_COST * authorization list length
662694
#
663-
# There is no calldata and no storage keys in this test case and the access
664-
# address list count is equal to the authorization list length
665-
#
666-
# total cost = 21000 + (2400 + 25_000) * auth_list_length
695+
# There is no calldata and no storage keys in this test case.
696+
# However, each access-list address includes data bytes that may contribute
697+
# additional cost depending on fork repricing.
667698

668699
auth_address = pre.deploy_contract(code=Op.STOP)
669700

670701
auth_signers = [pre.fund_eoa() for _ in range(auth_list_length)]
671-
672702
access_list = [
673-
AccessList(
674-
address=addr,
675-
storage_keys=[],
676-
)
677-
for addr in auth_signers
703+
AccessList(address=addr, storage_keys=[]) for addr in auth_signers
678704
]
679705

680706
auth_tuples = [

0 commit comments

Comments
 (0)