Skip to content

Commit 82800a0

Browse files
committed
EIP-2929 gas cost increase test conversions
1 parent 86f02a8 commit 82800a0

File tree

4 files changed

+357
-0
lines changed

4 files changed

+357
-0
lines changed

converted-ethereum-tests.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,6 @@ GeneralStateTests/stPreCompiledContracts/blake2B.json
100100

101101
([#1067](https://github.com/ethereum/execution-spec-tests/pull/1120))
102102
GeneralStateTests/stPreCompiledContracts/idPrecomps.json
103+
104+
([#1305](https://github.com/ethereum/execution-spec-tests/pull/1305))
105+
GeneralStateTests/stPreCompiledContracts/precompsEIP2929Cancun.json

docs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ consume cache --help
4949

5050
### 🧪 Test Cases
5151

52+
- ✨ Add EIP-7692929 gas cost increase tests ([#1305](https://github.com/ethereum/execution-spec-tests/pull/1305)).
53+
5254
## [v4.1.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.1.0) - 2025-03-11
5355

5456
### 💥 Breaking Changes
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""
2+
abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)
3+
Test cases for [EIP-2929: Gas cost increases for state access opcodes(https://eips.ethereum.org/EIPS/eip-2929).
4+
"""
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
"""Tests supported precompiled contracts."""
2+
3+
from typing import Iterator, Tuple
4+
5+
import pytest
6+
7+
from ethereum_test_forks.base_fork import Fork
8+
from ethereum_test_forks.forks.forks import Cancun, Prague
9+
from ethereum_test_tools import (
10+
Account,
11+
Alloc,
12+
Environment,
13+
StateTestFiller,
14+
Transaction,
15+
)
16+
from ethereum_test_tools.vm.opcode import Opcodes as Op
17+
from ethereum_test_vm.bytecode import Bytecode
18+
19+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md"
20+
REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b"
21+
22+
UPPER_BOUND = 0xFF
23+
NUM_UNSUPPORTED_PRECOMPILES = 8
24+
25+
26+
def contract_bytecode(**call_kwargs) -> Bytecode:
27+
"""Generate bytecode for the contract to be tested."""
28+
return (
29+
Op.GAS
30+
+ Op.CALL(**call_kwargs)
31+
+ Op.POP
32+
+ Op.SUB(Op.SWAP1, Op.GAS)
33+
+ Op.GAS
34+
+ Op.CALL(**call_kwargs)
35+
+ Op.POP
36+
+ Op.SUB(Op.SWAP1, Op.GAS)
37+
+ Op.SWAP1
38+
+ Op.SSTORE(0, Op.SUB)
39+
+ Op.STOP
40+
)
41+
42+
43+
def initial_setup_bytecode(sender: Account) -> Bytecode:
44+
"""Generate bytecode for the initial setup to be tested."""
45+
return (
46+
Op.MSTORE(0, 0) + Op.MSTORE(0x100, 0xDEADBEEF) + Op.CALL(address=sender, value=1) + Op.POP
47+
)
48+
49+
50+
def call_addresses_and_expected_output(fork: Fork) -> Iterator[Tuple[str, bool]]:
51+
"""
52+
Yield the addresses of precompiled contracts and their support status for a given fork.
53+
54+
Args:
55+
fork (Fork): The fork instance containing precompiled contract information.
56+
57+
Yields:
58+
Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a
59+
boolean indicating whether the address is a supported precompile.
60+
61+
"""
62+
supported_precompiles = fork.precompiles()
63+
64+
num_unsupported = NUM_UNSUPPORTED_PRECOMPILES
65+
for address in range(1, UPPER_BOUND + 1):
66+
if address in supported_precompiles:
67+
address = hex(address)
68+
precompile_exists = True
69+
yield pytest.param(
70+
address,
71+
precompile_exists,
72+
id=f"address_{address}_precompile_{precompile_exists}",
73+
)
74+
elif num_unsupported > 0:
75+
# Check unsupported precompiles up to NUM_UNSUPPORTED_PRECOMPILES
76+
address = hex(address)
77+
precompile_exists = False
78+
yield pytest.param(
79+
address,
80+
precompile_exists,
81+
id=f"address_{address}_precompile_{precompile_exists}",
82+
)
83+
num_unsupported -= 1
84+
85+
86+
@pytest.mark.valid_from("Cancun")
87+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
88+
def test_call_params_value_0(
89+
state_test: StateTestFiller,
90+
pre: Alloc,
91+
fork: Fork,
92+
address: str,
93+
precompile_exists: int,
94+
):
95+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
96+
env = Environment()
97+
98+
account = pre.deploy_contract(
99+
initial_setup_bytecode(pre.fund_eoa(amount=0)) + contract_bytecode(address=address),
100+
storage={0: 0xDEADBEEF},
101+
)
102+
103+
tx = Transaction(
104+
to=account,
105+
sender=pre.fund_eoa(),
106+
gas_limit=1_000_000,
107+
protected=True,
108+
)
109+
110+
expected_gas_cost_change = hex(0x0)
111+
if not precompile_exists:
112+
expected_gas_cost_change = hex(0x09C4)
113+
elif fork == Cancun and address in ["0x9", "0xa"]:
114+
expected_gas_cost_change = hex(0xDEADBEEF)
115+
elif fork == Prague and address in [
116+
"0x9",
117+
"0xa",
118+
"0xb",
119+
"0xc",
120+
"0xd",
121+
"0xe",
122+
"0xf",
123+
"0x10",
124+
"0x11",
125+
]:
126+
expected_gas_cost_change = hex(0xDEADBEEF)
127+
128+
post = {account: Account(storage={0: expected_gas_cost_change})}
129+
130+
state_test(env=env, pre=pre, post=post, tx=tx)
131+
132+
133+
@pytest.mark.valid_from("Cancun")
134+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
135+
def test_call_params_value_1(
136+
state_test: StateTestFiller,
137+
pre: Alloc,
138+
fork: Fork,
139+
address: str,
140+
precompile_exists: int,
141+
):
142+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
143+
env = Environment()
144+
145+
account = pre.deploy_contract(
146+
initial_setup_bytecode(pre.fund_eoa(amount=0))
147+
+ contract_bytecode(address=address, value=1),
148+
storage={0: 0xDEADBEEF},
149+
)
150+
151+
tx = Transaction(
152+
to=account,
153+
sender=pre.fund_eoa(),
154+
gas_limit=1_000_000,
155+
protected=True,
156+
)
157+
158+
expected_gas_cost_change = hex(0x0)
159+
if not precompile_exists:
160+
expected_gas_cost_change = hex(0x6B6C)
161+
elif fork >= Cancun and address in ["0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8"]:
162+
expected_gas_cost_change = hex(0x61A8)
163+
elif fork == Prague and address in ["0x9", "0xa"]:
164+
expected_gas_cost_change = hex(0xDEADBEEF)
165+
166+
post = {account: Account(storage={0: expected_gas_cost_change})}
167+
168+
state_test(env=env, pre=pre, post=post, tx=tx)
169+
170+
171+
@pytest.mark.valid_from("Cancun")
172+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
173+
def test_call_params_value_0_args_size_1(
174+
state_test: StateTestFiller,
175+
pre: Alloc,
176+
fork: Fork,
177+
address: str,
178+
precompile_exists: int,
179+
):
180+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
181+
env = Environment()
182+
183+
account = pre.deploy_contract(
184+
initial_setup_bytecode(pre.fund_eoa(amount=0))
185+
+ contract_bytecode(address=address, args_size=1),
186+
storage={0: 0xDEADBEEF},
187+
)
188+
189+
tx = Transaction(
190+
to=account,
191+
sender=pre.fund_eoa(),
192+
gas_limit=1_000_000,
193+
protected=True,
194+
)
195+
196+
expected_gas_cost_change = hex(0x0)
197+
if not precompile_exists:
198+
expected_gas_cost_change = hex(0x09C4)
199+
elif fork >= Cancun and address in ["0x8", "0x9", "0xa"]:
200+
expected_gas_cost_change = hex(0xDEADBEEF)
201+
elif fork == Prague and address in [
202+
"0xb",
203+
"0xc",
204+
"0xd",
205+
"0xe",
206+
"0xf",
207+
"0x10",
208+
"0x11",
209+
]:
210+
expected_gas_cost_change = hex(0xDEADBEEF)
211+
212+
post = {account: Account(storage={0: expected_gas_cost_change})}
213+
214+
state_test(env=env, pre=pre, post=post, tx=tx)
215+
216+
217+
@pytest.mark.valid_from("Cancun")
218+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
219+
def test_call_params_value_1_args_size_1(
220+
state_test: StateTestFiller,
221+
pre: Alloc,
222+
fork: Fork,
223+
address: str,
224+
precompile_exists: int,
225+
):
226+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
227+
env = Environment()
228+
229+
account = pre.deploy_contract(
230+
initial_setup_bytecode(pre.fund_eoa(amount=0))
231+
+ contract_bytecode(address=address, value=1, args_size=1),
232+
storage={0: 0xDEADBEEF},
233+
)
234+
235+
tx = Transaction(
236+
to=account,
237+
sender=pre.fund_eoa(),
238+
gas_limit=1_000_000,
239+
protected=True,
240+
)
241+
242+
expected_gas_cost_change = hex(0x0)
243+
if not precompile_exists:
244+
expected_gas_cost_change = hex(0x6B6C)
245+
elif fork >= Cancun and address in ["0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7"]:
246+
expected_gas_cost_change = hex(0x61A8)
247+
elif fork == Cancun and address in ["0x8", "0x9", "0xa"]:
248+
expected_gas_cost_change = hex(0xDEADBEEF)
249+
250+
post = {account: Account(storage={0: expected_gas_cost_change})}
251+
252+
state_test(env=env, pre=pre, post=post, tx=tx)
253+
254+
255+
@pytest.mark.valid_from("Cancun")
256+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
257+
def test_call_params_value_0_output_size_1(
258+
state_test: StateTestFiller,
259+
pre: Alloc,
260+
fork: Fork,
261+
address: str,
262+
precompile_exists: int,
263+
):
264+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
265+
env = Environment()
266+
267+
account = pre.deploy_contract(
268+
initial_setup_bytecode(pre.fund_eoa(amount=0))
269+
+ contract_bytecode(address=address, output_size=1),
270+
storage={0: 0xDEADBEEF},
271+
)
272+
273+
tx = Transaction(
274+
to=account,
275+
sender=pre.fund_eoa(),
276+
gas_limit=1_000_000,
277+
protected=True,
278+
)
279+
280+
expected_gas_cost_change = hex(0x0)
281+
if not precompile_exists:
282+
expected_gas_cost_change = hex(0x9C4)
283+
elif fork == Cancun and address in ["0x8", "0x9", "0xa"]:
284+
expected_gas_cost_change = hex(0xDEADBEEF)
285+
elif fork == Prague and address in [
286+
"0x9",
287+
"0xa",
288+
"0xb",
289+
"0xc",
290+
"0xd",
291+
"0xe",
292+
"0xf",
293+
"0x10",
294+
"0x11",
295+
]:
296+
expected_gas_cost_change = hex(0xDEADBEEF)
297+
298+
post = {account: Account(storage={0: expected_gas_cost_change})}
299+
300+
state_test(env=env, pre=pre, post=post, tx=tx)
301+
302+
303+
@pytest.mark.valid_from("Cancun")
304+
@pytest.mark.parametrize_by_fork("address,precompile_exists", call_addresses_and_expected_output)
305+
def test_call_params_value_1_output_size_1(
306+
state_test: StateTestFiller,
307+
pre: Alloc,
308+
fork: Fork,
309+
address: str,
310+
precompile_exists: int,
311+
):
312+
"""Tests equal gas consumption of CALL operation for the given addresses and parameters."""
313+
env = Environment()
314+
315+
account = pre.deploy_contract(
316+
initial_setup_bytecode(pre.fund_eoa(amount=0))
317+
+ contract_bytecode(address=address, value=1, output_size=1),
318+
storage={0: 0xDEADBEEF},
319+
)
320+
321+
tx = Transaction(
322+
to=account,
323+
sender=pre.fund_eoa(),
324+
gas_limit=1_000_000,
325+
protected=True,
326+
)
327+
328+
expected_gas_cost_change = hex(0x0)
329+
if not precompile_exists:
330+
expected_gas_cost_change = hex(0x6B6C)
331+
elif fork >= Cancun and address in ["0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8"]:
332+
expected_gas_cost_change = hex(0x61A8)
333+
elif fork == Cancun and address in ["0x9", "0xa"]:
334+
expected_gas_cost_change = hex(0xDEADBEEF)
335+
elif fork == Prague and address in [
336+
"0xb",
337+
"0xc",
338+
"0xd",
339+
"0xe",
340+
"0xf",
341+
"0x10",
342+
"0x11",
343+
]:
344+
expected_gas_cost_change = hex(0xDEADBEEF)
345+
346+
post = {account: Account(storage={0: expected_gas_cost_change})}
347+
348+
state_test(env=env, pre=pre, post=post, tx=tx)

0 commit comments

Comments
 (0)