Skip to content

Commit 2b5f86a

Browse files
evm: Precompile Tests (#3189)
* Add tests for blake2f precompile * Add tests for ripemd160 precompile * Test out of gas error for ecrecover precompile * evm: Fix blake2f test --------- Co-authored-by: Jochem Brouwer <[email protected]>
1 parent 98fc3ab commit 2b5f86a

File tree

3 files changed

+169
-2
lines changed

3 files changed

+169
-2
lines changed

packages/evm/test/precompiles/01-ecrecover.spec.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,24 @@ describe('Precompiles: ECRECOVER', () => {
2525

2626
const prefixedMessage = bytesToUnprefixedHex(keccak256(hexToBytes(`0x${prefix}${_hash}`)))
2727
const data = hexToBytes(`0x${prefixedMessage}${_v}${_r}${_s}`)
28-
const result = await ECRECOVER({
28+
let result = await ECRECOVER({
2929
data,
3030
gasLimit: BigInt(0xffff),
3131
common,
3232
_EVM: evm,
3333
})
34-
3534
assert.deepEqual(
3635
bytesToHex(result.returnValue.slice(-20)),
3736
address,
3837
'should recover expected address'
3938
)
39+
40+
result = await ECRECOVER({
41+
data,
42+
gasLimit: BigInt(0x1),
43+
common,
44+
_EVM: evm,
45+
})
46+
assert.equal(result.exceptionError?.error, 'out of gas', 'should error when not enough gas')
4047
})
4148
})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Chain, Common, Hardfork } from '@ethereumjs/common'
2+
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
3+
import { assert, describe, it } from 'vitest'
4+
5+
import { EVM, getActivePrecompiles } from '../../src/index.js'
6+
7+
const input =
8+
'38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02'
9+
const expected = '0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6'
10+
11+
describe('Precompiles: RIPEMD160', () => {
12+
it('RIPEMD160', async () => {
13+
// Test reference: https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/contracts_test.go#L217
14+
15+
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Petersburg })
16+
const evm = new EVM({
17+
common,
18+
})
19+
const addressStr = '0000000000000000000000000000000000000003'
20+
const RIPEMD160 = getActivePrecompiles(common).get(addressStr)!
21+
22+
const data = hexToBytes(`0x${input}`)
23+
let result = await RIPEMD160({
24+
data,
25+
gasLimit: BigInt(0xffff),
26+
common,
27+
_EVM: evm,
28+
})
29+
assert.deepEqual(
30+
bytesToHex(result.returnValue),
31+
`0x${expected}`,
32+
'should generate expected value'
33+
)
34+
35+
result = await RIPEMD160({
36+
data,
37+
gasLimit: BigInt(0x1),
38+
common,
39+
_EVM: evm,
40+
})
41+
assert.equal(result.exceptionError?.error, 'out of gas', 'should error when not enough gas')
42+
})
43+
})
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { Chain, Common, Hardfork } from '@ethereumjs/common'
2+
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
3+
import { assert, describe, it } from 'vitest'
4+
5+
import { EVM, getActivePrecompiles } from '../../src/index.js'
6+
7+
const validCases = [
8+
{
9+
input:
10+
'0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
11+
expected:
12+
'08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b',
13+
name: 'vector 4',
14+
gas: 0,
15+
},
16+
{
17+
input:
18+
'0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
19+
expected:
20+
'ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923',
21+
name: 'vector 5',
22+
gas: 12,
23+
},
24+
{
25+
input:
26+
'0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000',
27+
expected:
28+
'75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735',
29+
name: 'vector 6',
30+
gas: 12,
31+
},
32+
{
33+
input:
34+
'0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
35+
expected:
36+
'b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421',
37+
name: 'vector 7',
38+
gas: 1,
39+
},
40+
{
41+
input:
42+
'007A120048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
43+
expected:
44+
'6d2ce9e534d50e18ff866ae92d70cceba79bbcd14c63819fe48752c8aca87a4bb7dcc230d22a4047f0486cfcfb50a17b24b2899eb8fca370f22240adb5170189',
45+
name: 'vector 8',
46+
gas: 8000000,
47+
},
48+
]
49+
50+
const malformedCases = [
51+
{
52+
input: '',
53+
expectedError: 'value out of range',
54+
name: 'vector 0: empty input',
55+
},
56+
{
57+
input:
58+
'00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
59+
expectedError: 'value out of range',
60+
name: 'vector 1: less than 213 bytes input',
61+
},
62+
{
63+
input:
64+
'000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001',
65+
expectedError: 'value out of range',
66+
name: 'vector 2: more than 213 bytes input',
67+
},
68+
{
69+
input:
70+
'0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002',
71+
expectedError: 'value out of range',
72+
name: 'vector 3: incorrect final block indicator flag',
73+
},
74+
]
75+
76+
describe('Precompiles: BLAKE2F', () => {
77+
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul })
78+
// Test references: https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/testdata/precompiles/blake2F.json
79+
// https://github.com/ethereum/go-ethereum/blob/e206d3f8975bd98cc86d14055dca40f996bacc60/core/vm/contracts_test.go#L73
80+
81+
const evm = new EVM({
82+
common,
83+
})
84+
const addressStr = '0000000000000000000000000000000000000009'
85+
const BLAKE2F = getActivePrecompiles(common).get(addressStr)!
86+
87+
for (const t of validCases) {
88+
it(`BLAKE2F valid cases: ${t.name}`, async () => {
89+
const data = hexToBytes(`0x${t.input}`)
90+
const result = await BLAKE2F({
91+
data,
92+
gasLimit: BigInt(0xffffff),
93+
common,
94+
_EVM: evm,
95+
})
96+
assert.equal(
97+
bytesToHex(result.returnValue),
98+
`0x${t.expected}`,
99+
'should generate expected value'
100+
)
101+
assert.deepEqual(result.executionGasUsed, BigInt(t.gas), 'should use expected amount of gas')
102+
})
103+
}
104+
105+
for (const t of malformedCases) {
106+
it(`BLAKE2F malformed cases: ${t.name}`, async () => {
107+
const data = hexToBytes(`0x${t.input}`)
108+
const result = await BLAKE2F({
109+
data,
110+
gasLimit: BigInt(0xffff),
111+
common,
112+
_EVM: evm,
113+
})
114+
assert.equal(result.exceptionError?.error, t.expectedError, 'should generate expected error')
115+
})
116+
}
117+
})

0 commit comments

Comments
 (0)