@@ -2,6 +2,8 @@ const { ethers } = require('hardhat');
22const { expect } = require ( 'chai' ) ;
33const { spawn } = require ( 'child_process' ) ;
44
5+ const hardhat = 'hardhat' ;
6+ const anvil = 'anvil' ;
57const anvilPort = 8546 ;
68const ProofError = {
79 NO_ERROR : 0 ,
@@ -20,26 +22,44 @@ const ProofError = {
2022} ;
2123
2224async function fixture ( ) {
23- const anvil = spawn ( 'anvil' , [ '--port' , anvilPort ] , {
25+ const anvilProcess = spawn ( 'anvil' , [ '--port' , anvilPort ] , {
2426 timeout : 30000 ,
2527 } ) ; // Method eth_getProof is not supported with default Hardhat Network
2628 await new Promise ( resolve => {
27- anvil . stdout . once ( 'data' , resolve ) ;
29+ anvilProcess . stdout . once ( 'data' , resolve ) ;
2830 } ) ;
2931 if ( process . env . ANVIL_LOGS === 'true' ) {
30- anvil . stdout . on ( 'data' , function ( data ) {
32+ anvilProcess . stdout . on ( 'data' , function ( data ) {
3133 console . log ( data . toString ( ) ) ;
3234 } ) ;
3335 }
34- const provider = new ethers . JsonRpcProvider ( `http://localhost:${ anvilPort } ` ) ;
35- const account = await provider . getSigner ( 0 ) ;
36- const mock = ( await ethers . deployContract ( '$TrieProof' , account ) ) . connect ( account ) ;
37- const storage = ( await ethers . deployContract ( 'StorageSlotMock' , account ) ) . connect ( account ) ;
36+ const [ provider , account , storage ] = [ { } , { } , { } ] ;
37+ for ( const providerType of [ hardhat , anvil ] ) {
38+ provider [ providerType ] =
39+ providerType === anvil ? new ethers . JsonRpcProvider ( `http://localhost:${ anvilPort } ` ) : ethers . provider ;
40+ account [ providerType ] = await provider [ providerType ] . getSigner ( 0 ) ;
41+ storage [ providerType ] = ( await ethers . deployContract ( 'StorageSlotMock' , account [ providerType ] ) ) . connect (
42+ account [ providerType ] ,
43+ ) ;
44+ }
45+ const mock = ( await ethers . deployContract ( '$TrieProof' , account [ hardhat ] ) ) . connect ( account [ hardhat ] ) ; // only required on hardhat network
46+ const getProof = async function ( contract , slot , tx ) {
47+ const { storageHash, storageProof } = await this . provider [ anvil ] . send ( 'eth_getProof' , [
48+ contract [ anvil ] . target ,
49+ [ slot ] ,
50+ tx ? ethers . toBeHex ( tx [ anvil ] . blockNumber ) : 'latest' ,
51+ ] ) ;
52+ const { key, value, proof } = storageProof [ 0 ] ;
53+ return { key, value, proof, storageHash } ;
54+ } ;
55+
3856 return {
39- anvil ,
57+ anvilProcess ,
4058 provider,
41- mock ,
59+ account ,
4260 storage,
61+ mock,
62+ getProof,
4363 } ;
4464}
4565
@@ -49,36 +69,24 @@ describe('TrieProof', function () {
4969 } ) ;
5070
5171 afterEach ( async function ( ) {
52- this . anvil . kill ( ) ;
72+ this . anvilProcess . kill ( ) ;
5373 } ) ;
5474
5575 describe ( 'verify' , function ( ) {
5676 it ( 'returns true for a valid proof with leaf' , async function ( ) {
5777 const slot = ethers . ZeroHash ;
58- const tx = await this . storage . setUint256Slot ( slot , 42 ) ;
59- const response = await this . provider . send ( 'eth_getProof' , [
60- this . storage . target ,
61- [ slot ] ,
62- ethers . toBeHex ( tx . blockNumber ) ,
63- ] ) ;
64- const { storageHash, storageProof } = response ;
65- const { key, value, proof } = storageProof [ 0 ] ;
78+ const tx = await call ( this . storage , 'setUint256Slot' , [ slot , 42 ] ) ;
79+ const { key, value, proof, storageHash } = await this . getProof ( this . storage , slot , tx ) ;
6680 const result = await this . mock . $verify ( key , value , proof , storageHash ) ;
6781 expect ( result ) . is . true ;
6882 } ) ;
6983
7084 it ( 'returns true for a valid proof with extension' , async function ( ) {
7185 const slot0 = ethers . ZeroHash ;
7286 const slot1 = '0x0000000000000000000000000000000000000000000000000000000000000001' ;
73- await this . storage . setUint256Slot ( slot0 , 42 ) ;
74- const tx = await this . storage . setUint256Slot ( slot1 , 43 ) ;
75- const response = await this . provider . send ( 'eth_getProof' , [
76- this . storage . target ,
77- [ slot1 ] ,
78- ethers . toBeHex ( tx . blockNumber ) ,
79- ] ) ;
80- const { storageHash, storageProof } = response ;
81- const { key, value, proof } = storageProof [ 0 ] ;
87+ await call ( this . storage , 'setUint256Slot' , [ slot0 , 42 ] ) ;
88+ const tx = await call ( this . storage , 'setUint256Slot' , [ slot1 , 43 ] ) ;
89+ const { key, value, proof, storageHash } = await this . getProof ( this . storage , slot1 , tx ) ;
8290 const result = await this . mock . $verify ( key , value , proof , storageHash ) ;
8391 expect ( result ) . is . true ;
8492 } ) ;
@@ -93,13 +101,8 @@ describe('TrieProof', function () {
93101
94102 it ( 'fails to process proof with invalid root hash' , async function ( ) {
95103 const slot = ethers . ZeroHash ;
96- const tx = await this . storage . setUint256Slot ( slot , 42 ) ;
97- const { storageHash, storageProof } = await this . provider . send ( 'eth_getProof' , [
98- this . storage . target ,
99- [ slot ] ,
100- ethers . toBeHex ( tx . blockNumber ) ,
101- ] ) ;
102- const { key, proof } = storageProof [ 0 ] ;
104+ const tx = await call ( this . storage , 'setUint256Slot' , [ slot , 42 ] ) ;
105+ const { key, proof, storageHash } = await this . getProof ( this . storage , slot , tx ) ;
103106 const [ processedValue , error ] = await this . mock . $processProof ( key , proof , ethers . keccak256 ( storageHash ) ) ; // Corrupt root hash
104107 expect ( processedValue ) . to . equal ( '0x' ) ;
105108 expect ( error ) . to . equal ( ProofError . INVALID_ROOT_HASH ) ;
@@ -108,14 +111,9 @@ describe('TrieProof', function () {
108111 it ( 'fails to process proof with invalid internal large hash' , async function ( ) {
109112 const slot0 = ethers . ZeroHash ;
110113 const slot1 = '0x0000000000000000000000000000000000000000000000000000000000000001' ;
111- await this . storage . setUint256Slot ( slot0 , 42 ) ;
112- const tx = await this . storage . setUint256Slot ( slot1 , 43 ) ;
113- const { storageHash, storageProof } = await this . provider . send ( 'eth_getProof' , [
114- this . storage . target ,
115- [ slot1 ] ,
116- ethers . toBeHex ( tx . blockNumber ) ,
117- ] ) ;
118- const { key, proof } = storageProof [ 0 ] ;
114+ await call ( this . storage , 'setUint256Slot' , [ slot0 , 42 ] ) ;
115+ const tx = await call ( this . storage , 'setUint256Slot' , [ slot1 , 43 ] ) ;
116+ const { key, proof, storageHash } = await this . getProof ( this . storage , slot1 , tx ) ;
119117 proof [ 1 ] = ethers . toBeHex ( BigInt ( proof [ 1 ] ) + 1n ) ; // Corrupt internal large node hash
120118 const [ processedValue , error ] = await this . mock . $processProof ( key , proof , storageHash ) ;
121119 expect ( processedValue ) . to . equal ( '0x' ) ;
@@ -133,13 +131,8 @@ describe('TrieProof', function () {
133131
134132 it ( 'fails to process proof with invalid extra proof' , async function ( ) {
135133 const slot0 = ethers . ZeroHash ;
136- const tx = await this . storage . setUint256Slot ( slot0 , 42 ) ;
137- const { storageHash, storageProof } = await this . provider . send ( 'eth_getProof' , [
138- this . storage . target ,
139- [ slot0 ] ,
140- ethers . toBeHex ( tx . blockNumber ) ,
141- ] ) ;
142- const { key, proof } = storageProof [ 0 ] ;
134+ const tx = await call ( this . storage , 'setUint256Slot' , [ slot0 , 42 ] ) ;
135+ const { key, proof, storageHash } = await this . getProof ( this . storage , slot0 , tx ) ;
143136 proof [ 1 ] = ethers . encodeRlp ( [ ] ) ; // extra proof element
144137 const [ processedValue , error ] = await this . mock . $processProof ( key , proof , storageHash ) ;
145138 expect ( processedValue ) . to . equal ( '0x' ) ;
@@ -176,3 +169,16 @@ describe('TrieProof', function () {
176169 } ) ;
177170 } ) ;
178171} ) ;
172+
173+ /**
174+ * Call a method on both Hardhat and Anvil networks
175+ * @returns txs on both networks
176+ */
177+ async function call ( contract , method , args ) {
178+ const hardhatTx = await contract [ hardhat ] [ method ] ( ...args ) ;
179+ const anvilTx = await contract [ anvil ] [ method ] ( ...args ) ;
180+ return {
181+ [ hardhat ] : hardhatTx ,
182+ [ anvil ] : anvilTx ,
183+ } ;
184+ }
0 commit comments