Skip to content

Commit 12035a8

Browse files
committed
Identity precompile test conversions
Add identity returndata test cases Add identity tests for CALL Add tests for large inputs/outputs
1 parent db9f3c3 commit 12035a8

File tree

5 files changed

+308
-2
lines changed

5 files changed

+308
-2
lines changed

Diff for: converted-ethereum-tests.txt

+16-1
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,25 @@ GeneralStateTests/VMTests/vmTests/push.json
100100
([#1067](https://github.com/ethereum/execution-spec-tests/pull/1067))
101101
GeneralStateTests/stPreCompiledContracts/blake2B.json
102102

103-
([#1067](https://github.com/ethereum/execution-spec-tests/pull/1120))
103+
([#1120](https://github.com/ethereum/execution-spec-tests/pull/1120))
104104
GeneralStateTests/stPreCompiledContracts/idPrecomps.json
105105

106106
([#1244](https://github.com/ethereum/execution-spec-tests/pull/1244))
107107
GeneralStateTests/stPreCompiledContracts/delegatecall09Undefined.json
108108
GeneralStateTests/stPreCompiledContracts2/CALLBlake2f.json
109109
GeneralStateTests/stPreCompiledContracts2/CALLCODEBlake2f.json
110+
111+
([#1344](https://github.com/ethereum/execution-spec-tests/pull/1344))
112+
GeneralStateTests/stPreCompiledContracts/identity_to_bigger.json
113+
GeneralStateTests/stPreCompiledContracts/identity_to_smaller.json
114+
GeneralStateTests/stPreCompiledContracts2/CallIdentitiy_0.json
115+
GeneralStateTests/stPreCompiledContracts2/CallIdentitiy_1.json
116+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_1_nonzeroValue.json
117+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_2.json
118+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_3.json
119+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_4.json
120+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_4_gas17.json
121+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_4_gas18.json
122+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_5.json
123+
GeneralStateTests/stPreCompiledContracts2/CallIdentity_6_inputShorterThanOutput.json
124+

Diff for: docs/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ consume cache --help
6767
- ✨ Add additional test coverage for EIP-152 Blake2 precompiles ([#1244](https://github.com/ethereum/execution-spec-tests/pull/1244)). Refactor to add variables for spec constants and common fixture code. ([#1395](https://github.com/ethereum/execution-spec-tests/pull/1395)).
6868
- ✨ Add EIP-7702 incorrect-rlp-encoding tests ([#1347](https://github.com/ethereum/execution-spec-tests/pull/1347)).
6969
- ✨ Add EIP-2935 tests for all call opcodes ([#1379](https://github.com/ethereum/execution-spec-tests/pull/1379)).
70+
- ✨ Add test cases Identity precompiles ([#1344](https://github.com/ethereum/execution-spec-tests/pull/1344)).
7071

7172
## [v4.1.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.1.0) - 2025-03-11
7273

@@ -106,6 +107,7 @@ The following changes may be potentially breaking (all clients were tested with
106107
- ✨ Add EIP-7698 failed nonce and short data tests ([#1211](https://github.com/ethereum/execution-spec-tests/pull/1211)).
107108
- ✨ Add EIP-2537 additional pairing precompile tests cases, and then update all BLS12 test vectors ([#1275](https://github.com/ethereum/execution-spec-tests/pull/1275), [#1289](https://github.com/ethereum/execution-spec-tests/pull/1289)).
108109
- ✨ Add EIP-7685 and EIP-7002 test cases for additional request type combinations and modified withdrawal contract that allows more withdrawals ([#1340](https://github.com/ethereum/execution-spec-tests/pull/1340)).
110+
- ✨ Add test cases for EIP-152 Blake2 and Identity precompiles ([#1244](https://github.com/ethereum/execution-spec-tests/pull/1244)).
109111

110112
## [v4.0.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.0.0) - 2025-02-14 - 💕
111113

Diff for: tests/frontier/precompiles/test_identity.py

+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
"""abstract: Test identity precompile output size."""
2+
3+
import pytest
4+
5+
from ethereum_test_base_types.composite_types import Storage
6+
from ethereum_test_tools import (
7+
Account,
8+
Alloc,
9+
Bytecode,
10+
Environment,
11+
StateTestFiller,
12+
Transaction,
13+
)
14+
from ethereum_test_tools import Opcodes as Op
15+
16+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-152.md"
17+
REFERENCE_SPEC_VERSION = "5510973b40973b6aa774f04c9caba823c8ff8460"
18+
19+
IDENTITY_PRECOMPILE_ADDRESS = 0x04
20+
21+
22+
class CallInputs:
23+
"""Defines inputs to CALL for the Identity precompile."""
24+
25+
def __init__(
26+
self,
27+
gas=0x1F4,
28+
value=0x0,
29+
args_offset=0x0,
30+
args_size=0x20,
31+
ret_offset=0x0,
32+
ret_size=0x20,
33+
):
34+
"""Create a new instance with the provided values."""
35+
self.gas = gas
36+
self.value = value
37+
self.args_offset = args_offset
38+
self.args_size = args_size
39+
self.ret_offset = ret_offset
40+
self.ret_size = ret_size
41+
42+
43+
@pytest.mark.valid_from("Byzantium")
44+
@pytest.mark.parametrize(
45+
[
46+
"inputs",
47+
"store_values_code",
48+
"stored_value_offset",
49+
"expected_stored_value",
50+
"call_succeeds",
51+
],
52+
[
53+
pytest.param(CallInputs(gas=0xFF), Op.MSTORE(0, 0x1), 0x0, 0x1, 0x1, id="identity_0"),
54+
pytest.param(
55+
CallInputs(args_size=0x0),
56+
Op.MSTORE(0, 0x0),
57+
0x0,
58+
0x0,
59+
True,
60+
id="identity_1",
61+
),
62+
pytest.param(
63+
CallInputs(gas=0x30D40, value=0x13, args_size=0x0),
64+
Bytecode(),
65+
0x0,
66+
0x0,
67+
False,
68+
id="identity_1_nonzero",
69+
),
70+
pytest.param(
71+
CallInputs(args_size=0x25),
72+
Op.MSTORE(0, 0xF34578907F),
73+
0x0,
74+
0xF34578907F,
75+
True,
76+
id="identity_2",
77+
),
78+
pytest.param(
79+
CallInputs(args_size=0x25),
80+
Op.MSTORE(0, 0xF34578907F),
81+
0x0,
82+
0xF34578907F,
83+
True,
84+
id="identity_3",
85+
),
86+
pytest.param(
87+
CallInputs(gas=0x64),
88+
Op.MSTORE(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF),
89+
0x0,
90+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
91+
True,
92+
id="identity_4",
93+
),
94+
pytest.param(
95+
CallInputs(gas=0x11),
96+
Op.MSTORE(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF),
97+
0x0,
98+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
99+
False,
100+
id="identity_4_gas17",
101+
),
102+
pytest.param(
103+
CallInputs(gas=0x12),
104+
Op.MSTORE(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF),
105+
0x0,
106+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
107+
True,
108+
id="identity_4_gas18",
109+
),
110+
],
111+
)
112+
def test_call_identity_precompile(
113+
state_test: StateTestFiller,
114+
pre: Alloc,
115+
inputs: CallInputs,
116+
store_values_code: Bytecode,
117+
stored_value_offset: int,
118+
expected_stored_value: int,
119+
call_succeeds: int,
120+
):
121+
"""Test identity precompile RETURNDATA is sized correctly based on the input size."""
122+
env = Environment()
123+
storage = Storage()
124+
125+
account = pre.deploy_contract(
126+
store_values_code
127+
+ Op.SSTORE(
128+
storage.store_next(call_succeeds),
129+
Op.CALL(
130+
gas=inputs.gas,
131+
address=IDENTITY_PRECOMPILE_ADDRESS,
132+
value=inputs.value,
133+
args_offset=inputs.args_offset,
134+
args_size=inputs.args_size,
135+
ret_offset=inputs.ret_offset,
136+
ret_size=inputs.ret_size,
137+
),
138+
)
139+
+ Op.SSTORE(storage.store_next(expected_stored_value), Op.MLOAD(stored_value_offset))
140+
+ Op.STOP,
141+
storage=storage.canary(),
142+
)
143+
144+
tx = Transaction(
145+
to=account,
146+
sender=pre.fund_eoa(),
147+
gas_limit=365_224,
148+
)
149+
150+
post = {account: Account(storage=storage)}
151+
152+
state_test(env=env, pre=pre, post=post, tx=tx)
153+
154+
155+
@pytest.mark.valid_from("Byzantium")
156+
@pytest.mark.parametrize(
157+
[
158+
"inputs",
159+
"store_values_code",
160+
"stored_value_offset",
161+
"expected_stored_value",
162+
"call_succeeds",
163+
],
164+
[
165+
pytest.param(
166+
CallInputs(gas=0x258, args_size=0xF4240),
167+
Op.MSTORE(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF),
168+
0x0,
169+
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
170+
False,
171+
id="identity_5",
172+
),
173+
pytest.param(
174+
CallInputs(gas=0x258, ret_size=0x40),
175+
Op.MSTORE(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
176+
+ Op.MSTORE(0x20, 0x1234),
177+
0x20,
178+
0x1234,
179+
True,
180+
id="identity_6",
181+
),
182+
],
183+
)
184+
def test_call_identity_precompile_large_params(
185+
state_test: StateTestFiller,
186+
pre: Alloc,
187+
inputs: CallInputs,
188+
store_values_code: Bytecode,
189+
stored_value_offset: int,
190+
expected_stored_value: int,
191+
call_succeeds: int,
192+
):
193+
"""Test identity precompile when out of gas occurs."""
194+
env = Environment()
195+
storage = Storage()
196+
197+
account = pre.deploy_contract(
198+
store_values_code
199+
+ Op.SSTORE(
200+
storage.store_next(call_succeeds),
201+
Op.CALL(
202+
gas=inputs.gas,
203+
address=IDENTITY_PRECOMPILE_ADDRESS,
204+
value=inputs.value,
205+
args_offset=inputs.args_offset,
206+
args_size=inputs.args_size,
207+
ret_offset=inputs.ret_offset,
208+
ret_size=inputs.ret_size,
209+
),
210+
)
211+
+ Op.SSTORE(storage.store_next(expected_stored_value), Op.MLOAD(stored_value_offset))
212+
+ Op.STOP,
213+
storage=storage.canary(),
214+
)
215+
216+
tx = Transaction(
217+
to=account,
218+
sender=pre.fund_eoa(),
219+
gas_limit=10_000_000,
220+
)
221+
222+
post = {account: Account(storage=storage)}
223+
224+
state_test(env=env, pre=pre, post=post, tx=tx)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""abstract: Test identity precompile output size."""
2+
3+
import pytest
4+
5+
from ethereum_test_tools import (
6+
Account,
7+
Alloc,
8+
Environment,
9+
StateTestFiller,
10+
Transaction,
11+
)
12+
from ethereum_test_tools import Opcodes as Op
13+
14+
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-152.md"
15+
REFERENCE_SPEC_VERSION = "5510973b40973b6aa774f04c9caba823c8ff8460"
16+
17+
IDENTITY_PRECOMPILE_ADDRESS = 0x04
18+
19+
20+
@pytest.mark.valid_from("Byzantium")
21+
@pytest.mark.parametrize(
22+
["args_size", "output_size", "returndatasize"],
23+
[
24+
pytest.param(16, 32, 16, id="output_16"),
25+
pytest.param(32, 16, 32, id="output_32"),
26+
],
27+
)
28+
def test_identity_precompile_returndata(
29+
state_test: StateTestFiller,
30+
pre: Alloc,
31+
args_size: int,
32+
output_size: int,
33+
returndatasize: int,
34+
):
35+
"""Test identity precompile RETURNDATA is sized correctly based on the input size."""
36+
env = Environment()
37+
38+
account = pre.deploy_contract(
39+
Op.MSTORE(0, 0)
40+
+ Op.GAS
41+
+ Op.MSTORE(0, 0x112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00)
42+
+ Op.CALL(
43+
address=IDENTITY_PRECOMPILE_ADDRESS,
44+
args_offset=0,
45+
args_size=args_size,
46+
output_offset=0x10,
47+
output_size=output_size,
48+
)
49+
+ Op.POP
50+
+ Op.SSTORE(0, Op.RETURNDATASIZE)
51+
+ Op.STOP,
52+
storage={0: 0xDEADBEEF},
53+
)
54+
55+
tx = Transaction(
56+
to=account,
57+
sender=pre.fund_eoa(),
58+
gas_limit=1_000_000,
59+
protected=True,
60+
)
61+
62+
# Delegatecall to the precompile will fail and consume the specified gas amount
63+
# Otherwise delegatecall will succeed and no gas will be consumed
64+
post = {account: Account(storage={0: returndatasize})}
65+
66+
state_test(env=env, pre=pre, post=post, tx=tx)

Diff for: tests/istanbul/eip152_blake2/test_blake2.py

-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ def test_blake2b(
406406
"""Test BLAKE2b precompile."""
407407
env = Environment()
408408

409-
account = pre.deploy_contract(blake2b_contract_bytecode, storage={0: 0xDEADBEEF})
410409
account = pre.deploy_contract(blake2b_contract_bytecode, storage={0: 0xDEADBEEF})
411410
sender = pre.fund_eoa()
412411

0 commit comments

Comments
 (0)