Skip to content

Commit 2c55972

Browse files
committed
feat(tests): tests for ripemd-160 precompile
sourced from `evmone` unit tests
1 parent 2d7dac9 commit 2c55972

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Test fixtures for use by clients are available for each release on the [Github r
2525
- 🐞 Fix BALs opcode OOG test vectors by updating the Amsterdam commit hash in specs and validating appropriately on the testing side ([#2293](https://github.com/ethereum/execution-spec-tests/pull/2293)).
2626
- ✨ Fix test vector for BALs SSTORE with OOG by pointing to updated specs; add new boundary conditions cases for SSTORE w/ OOG ([#2297](https://github.com/ethereum/execution-spec-tests/pull/2297)).
2727
- ✨ Expand cases to test *CALL opcodes causing OOG ([#1703](https://github.com/ethereum/execution-specs/pull/1703)).
28+
- ✨ Add tests for `modexp` and `ripemd` precompiled contracts ([#1691](https://github.com/ethereum/execution-specs/pull/1691))
2829

2930
## [v5.3.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v5.3.0) - 2025-10-09
3031

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""Tests RIPEMD-160 precompiled contract."""
2+
3+
import pytest
4+
from execution_testing import (
5+
Account,
6+
Alloc,
7+
Environment,
8+
StateTestFiller,
9+
Transaction,
10+
)
11+
from execution_testing.forks.forks.forks import Byzantium
12+
from execution_testing.forks.helpers import Fork
13+
from execution_testing.vm import Opcodes as Op
14+
15+
16+
@pytest.mark.valid_from("Frontier")
17+
@pytest.mark.parametrize(
18+
"msg, output",
19+
[
20+
pytest.param(
21+
b"abc",
22+
bytes.fromhex("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
23+
id="ripemd_abc",
24+
),
25+
pytest.param(
26+
b"message digest",
27+
bytes.fromhex("5d0689ef49d2fae572b881b123a85ffa21595f36"),
28+
id="ripemd_message_digest",
29+
),
30+
pytest.param(
31+
b"abcdefghijklmnopqrstuvwxyz",
32+
bytes.fromhex("f71c27109c692c1b56bbdceb5b9d2865b3708dbc"),
33+
id="ripemd_alphabet",
34+
),
35+
pytest.param(
36+
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
37+
bytes.fromhex("12a053384a9c0c88e405a06c27dcf49ada62eb2b"),
38+
id="ripemd_long",
39+
),
40+
pytest.param(
41+
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
42+
bytes.fromhex("b0e20b6e3116640286ed3a87a5713079b21f5189"),
43+
id="ripemd_alnum",
44+
),
45+
pytest.param(
46+
b"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
47+
bytes.fromhex("9b752e45573d4b39f4dbd3323cab82bf63326bfb"),
48+
id="ripemd_numeric",
49+
),
50+
pytest.param(
51+
b"The quick brown fox jumps over the lazy dog",
52+
bytes.fromhex("37f332f68db77bd9d7edd4969571ad671cf9dd3b"),
53+
id="ripemd_quick_brown_fox",
54+
),
55+
pytest.param(
56+
b"a" * 0,
57+
bytes.fromhex("9c1185a5c5e9fc54612808977ee8f548b2258d31"),
58+
id="ripemd_a_0",
59+
),
60+
pytest.param(
61+
b"a" * 1,
62+
bytes.fromhex("0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
63+
id="ripemd_a_1",
64+
),
65+
pytest.param(
66+
b"a" * 54,
67+
bytes.fromhex("a57fa1577740fd73b6859dd20e090cdac4d2af36"),
68+
id="ripemd_a_54",
69+
),
70+
pytest.param(
71+
b"a" * 55,
72+
bytes.fromhex("0d8a8c9063a48576a7c97e9f95253a6e53ff6765"),
73+
id="length fits into the first block",
74+
),
75+
pytest.param(
76+
b"a" * 56,
77+
bytes.fromhex("e72334b46c83cc70bef979e15453706c95b888be"),
78+
id="ripemd_a_56",
79+
),
80+
pytest.param(
81+
b"a" * 57,
82+
bytes.fromhex("eed82d19d597ab275b550ff3d6e0bc2a75350388"),
83+
id="ripemd_a_57",
84+
),
85+
pytest.param(
86+
b"a" * 63,
87+
bytes.fromhex("e640041293fe663b9bf3f8c21ffecac03819e6b2"),
88+
id="ripemd_a_63",
89+
),
90+
pytest.param(
91+
b"a" * 64,
92+
bytes.fromhex("9dfb7d374ad924f3f88de96291c33e9abed53e32"),
93+
id="full block",
94+
),
95+
pytest.param(
96+
b"a" * 65,
97+
bytes.fromhex("99724bb11811e7166af38f671b6a082d8ab4960b"),
98+
id="ripemd_a_65",
99+
),
100+
pytest.param(
101+
b"a" * 119,
102+
bytes.fromhex("23e398ff2bac815aa1bbb57ca2a669c841872919"),
103+
id="ripemd_a_119",
104+
),
105+
pytest.param(
106+
b"a" * 120,
107+
bytes.fromhex("c476770a6dae31fcee8d25efe6559a05c8024595"),
108+
id="ripemd_a_120",
109+
),
110+
pytest.param(
111+
b"a" * 121,
112+
bytes.fromhex("725c88a6f41605e99477a1478607d3fe25ced606"),
113+
id="ripemd_a_121",
114+
),
115+
pytest.param(
116+
b"a" * 127,
117+
bytes.fromhex("64f2d68b85f394e2e4f49009c4bd50224c2698ed"),
118+
id="ripemd_a_127",
119+
),
120+
pytest.param(
121+
b"a" * 128,
122+
bytes.fromhex("8dfdfb32b2ed5cb41a73478b4fd60cc5b4648b15"),
123+
id="two blocks",
124+
),
125+
pytest.param(
126+
b"a" * 129,
127+
bytes.fromhex("62bb9091f499f294f15aa5b951df4d9744d50cf2"),
128+
id="ripemd_a_129",
129+
),
130+
pytest.param(
131+
b"a" * 10_000,
132+
bytes.fromhex("eb33e86b2400cc0a11707be717a35a9acf074a58"),
133+
id="ripemd_a_10000",
134+
),
135+
],
136+
)
137+
def test_precompiles(
138+
state_test: StateTestFiller,
139+
pre: Alloc,
140+
fork: Fork,
141+
msg: bytes,
142+
output: bytes,
143+
) -> None:
144+
"""
145+
Tests the behavior of `RIPEMD-160` precompiled contract.
146+
"""
147+
env = Environment()
148+
149+
account = pre.deploy_contract(
150+
code=Op.CALLDATACOPY(0, 0, len(msg))
151+
+ Op.MLOAD(0)
152+
+ Op.CALL(
153+
gas=50_000,
154+
address="0x03", # RIPEMD-160 precompile address
155+
args_offset=0,
156+
args_size=len(msg),
157+
ret_offset=len(msg),
158+
ret_size=32,
159+
)
160+
+ Op.SSTORE(0, Op.MLOAD(len(msg)))
161+
+ Op.STOP,
162+
storage={0: 0xDEADBEEF},
163+
)
164+
165+
tx = Transaction(
166+
to=account,
167+
sender=pre.fund_eoa(),
168+
gas_limit=1_000_0000,
169+
data=msg,
170+
protected=fork >= Byzantium,
171+
)
172+
173+
post = {account: Account(storage={0: output})}
174+
175+
state_test(env=env, pre=pre, post=post, tx=tx)

0 commit comments

Comments
 (0)