Skip to content

Commit bb83ec9

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

File tree

4 files changed

+358
-0
lines changed

4 files changed

+358
-0
lines changed

Diff for: converted-ethereum-tests.txt

+3
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

Diff for: docs/CHANGELOG.md

+2
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

Diff for: tests/berlin/eip2929_gas_cost_increases/__init__.py

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

0 commit comments

Comments
 (0)