1
1
import { ethers } from "ethers" ;
2
- import { Presets , Client } from "userop" ;
3
- import { fundIfRequired } from "../src/helpers" ;
2
+ import { Presets , Client , ISendUserOperationOpts } from "userop" ;
3
+ import { fundIfRequired , getCallGasLimitBenchmark } from "../src/helpers" ;
4
4
import { erc20ABI , testGasABI } from "../src/abi" ;
5
5
import { errorCodes } from "../src/errors" ;
6
6
import config from "../config" ;
7
7
8
+ const opChecks = (
9
+ provider : ethers . providers . JsonRpcProvider
10
+ ) : ISendUserOperationOpts => ( {
11
+ onBuild : async ( op ) => {
12
+ const cgl = ethers . BigNumber . from ( op . callGasLimit ) . toNumber ( ) ;
13
+ const benchmark = await (
14
+ await getCallGasLimitBenchmark ( provider , op . sender , op . callData )
15
+ ) . toNumber ( ) ;
16
+
17
+ expect ( cgl ) . toBeLessThanOrEqual ( benchmark ) ;
18
+ } ,
19
+ } ) ;
20
+
21
+ // TODO: Figure out why CGL is not LTE to benchmark at certain depths/widths.
22
+ // Until then we use this check to prevent regression.
23
+ const opCheckDeep = ( benchmark : number ) : ISendUserOperationOpts => ( {
24
+ onBuild : async ( op ) => {
25
+ expect (
26
+ ethers . BigNumber . from ( op . callGasLimit ) . toNumber ( )
27
+ ) . toBeLessThanOrEqual ( benchmark ) ;
28
+ } ,
29
+ } ) ;
30
+
8
31
describe ( "Without Paymaster" , ( ) => {
9
32
const provider = new ethers . providers . JsonRpcProvider ( config . nodeUrl ) ;
10
33
const signer = new ethers . Wallet ( config . signingKey ) ;
@@ -35,7 +58,8 @@ describe("Without Paymaster", () => {
35
58
36
59
test ( "Sender can transfer 0 ETH" , async ( ) => {
37
60
const response = await client . sendUserOperation (
38
- acc . execute ( acc . getSender ( ) , 0 , "0x" )
61
+ acc . execute ( acc . getSender ( ) , 0 , "0x" ) ,
62
+ { ...opChecks ( provider ) }
39
63
) ;
40
64
const event = await response . wait ( ) ;
41
65
@@ -45,7 +69,8 @@ describe("Without Paymaster", () => {
45
69
test ( "Sender can transfer half ETH balance" , async ( ) => {
46
70
const balance = await provider . getBalance ( acc . getSender ( ) ) ;
47
71
const response = await client . sendUserOperation (
48
- acc . execute ( acc . getSender ( ) , balance . div ( 2 ) , "0x" )
72
+ acc . execute ( acc . getSender ( ) , balance . div ( 2 ) , "0x" ) ,
73
+ { ...opChecks ( provider ) }
49
74
) ;
50
75
const event = await response . wait ( ) ;
51
76
@@ -63,7 +88,8 @@ describe("Without Paymaster", () => {
63
88
. add ( ethers . BigNumber . from ( op . verificationGasLimit ) . mul ( 3 ) )
64
89
) ;
65
90
const response = await client . sendUserOperation (
66
- acc . execute ( acc . getSender ( ) , balance . sub ( maxFee ) , "0x" )
91
+ acc . execute ( acc . getSender ( ) , balance . sub ( maxFee ) , "0x" ) ,
92
+ { ...opChecks ( provider ) }
67
93
) ;
68
94
const event = await response . wait ( ) ;
69
95
@@ -80,7 +106,8 @@ describe("Without Paymaster", () => {
80
106
acc . getSender ( ) ,
81
107
balance ,
82
108
] )
83
- )
109
+ ) ,
110
+ { ...opChecks ( provider ) }
84
111
) ;
85
112
const event = await response . wait ( ) ;
86
113
@@ -100,7 +127,10 @@ describe("Without Paymaster", () => {
100
127
] )
101
128
) ;
102
129
}
103
- const response = await client . sendUserOperation ( acc . executeBatch ( to , data ) ) ;
130
+ const response = await client . sendUserOperation (
131
+ acc . executeBatch ( to , data ) ,
132
+ { ...opChecks ( provider ) }
133
+ ) ;
104
134
const event = await response . wait ( ) ;
105
135
106
136
expect ( event ?. args . success ) . toBe ( true ) ;
@@ -114,7 +144,8 @@ describe("Without Paymaster", () => {
114
144
config . testGas ,
115
145
0 ,
116
146
testGas . interface . encodeFunctionData ( "recursiveCall" , [ 32 , 0 , 32 ] )
117
- )
147
+ ) ,
148
+ { ...opChecks ( provider ) }
118
149
) ;
119
150
} catch ( error : any ) {
120
151
expect ( error ?. error . code ) . toBe ( errorCodes . executionReverted ) ;
@@ -125,6 +156,10 @@ describe("Without Paymaster", () => {
125
156
describe ( "With zero value" , ( ) => {
126
157
[ 0 , 2 , 4 , 8 , 16 ] . forEach ( ( depth ) => {
127
158
test ( `Sender can make contract interactions with ${ depth } recursive calls` , async ( ) => {
159
+ let opts = opChecks ( provider ) ;
160
+ if ( depth === 8 ) opts = opCheckDeep ( 1195400 ) ;
161
+ if ( depth === 16 ) opts = opCheckDeep ( 4364942 ) ;
162
+
128
163
const response = await client . sendUserOperation (
129
164
acc . execute (
130
165
config . testGas ,
@@ -134,7 +169,8 @@ describe("Without Paymaster", () => {
134
169
0 ,
135
170
depth ,
136
171
] )
137
- )
172
+ ) ,
173
+ opts
138
174
) ;
139
175
const event = await response . wait ( ) ;
140
176
@@ -146,6 +182,10 @@ describe("Without Paymaster", () => {
146
182
describe ( "With non-zero value" , ( ) => {
147
183
[ 0 , 2 , 4 , 8 , 16 ] . forEach ( ( depth ) => {
148
184
test ( `Sender can make contract interactions with ${ depth } recursive calls` , async ( ) => {
185
+ let opts = opChecks ( provider ) ;
186
+ if ( depth === 8 ) opts = opCheckDeep ( 1261728 ) ;
187
+ if ( depth === 16 ) opts = opCheckDeep ( 4498665 ) ;
188
+
149
189
const response = await client . sendUserOperation (
150
190
acc . execute (
151
191
config . testGas ,
@@ -155,7 +195,8 @@ describe("Without Paymaster", () => {
155
195
0 ,
156
196
depth ,
157
197
] )
158
- )
198
+ ) ,
199
+ opts
159
200
) ;
160
201
const event = await response . wait ( ) ;
161
202
@@ -167,6 +208,10 @@ describe("Without Paymaster", () => {
167
208
describe ( "With multiple stacks per depth" , ( ) => {
168
209
[ 0 , 1 , 2 , 3 ] . forEach ( ( depth ) => {
169
210
test ( `Sender can make contract interactions with ${ depth } recursive calls` , async ( ) => {
211
+ let opts = opChecks ( provider ) ;
212
+ if ( depth === 2 ) opts = opCheckDeep ( 865684 ) ;
213
+ if ( depth === 3 ) opts = opCheckDeep ( 7925084 ) ;
214
+
170
215
const width = depth ;
171
216
const response = await client . sendUserOperation (
172
217
acc . execute (
@@ -177,7 +222,8 @@ describe("Without Paymaster", () => {
177
222
width ,
178
223
depth ,
179
224
] )
180
- )
225
+ ) ,
226
+ opts
181
227
) ;
182
228
const event = await response . wait ( ) ;
183
229
0 commit comments