11import { 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" ;
44import { erc20ABI , testGasABI } from "../src/abi" ;
55import { errorCodes } from "../src/errors" ;
66import config from "../config" ;
77
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+
831describe ( "Without Paymaster" , ( ) => {
932 const provider = new ethers . providers . JsonRpcProvider ( config . nodeUrl ) ;
1033 const signer = new ethers . Wallet ( config . signingKey ) ;
@@ -35,7 +58,8 @@ describe("Without Paymaster", () => {
3558
3659 test ( "Sender can transfer 0 ETH" , async ( ) => {
3760 const response = await client . sendUserOperation (
38- acc . execute ( acc . getSender ( ) , 0 , "0x" )
61+ acc . execute ( acc . getSender ( ) , 0 , "0x" ) ,
62+ { ...opChecks ( provider ) }
3963 ) ;
4064 const event = await response . wait ( ) ;
4165
@@ -45,7 +69,8 @@ describe("Without Paymaster", () => {
4569 test ( "Sender can transfer half ETH balance" , async ( ) => {
4670 const balance = await provider . getBalance ( acc . getSender ( ) ) ;
4771 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 ) }
4974 ) ;
5075 const event = await response . wait ( ) ;
5176
@@ -63,7 +88,8 @@ describe("Without Paymaster", () => {
6388 . add ( ethers . BigNumber . from ( op . verificationGasLimit ) . mul ( 3 ) )
6489 ) ;
6590 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 ) }
6793 ) ;
6894 const event = await response . wait ( ) ;
6995
@@ -80,7 +106,8 @@ describe("Without Paymaster", () => {
80106 acc . getSender ( ) ,
81107 balance ,
82108 ] )
83- )
109+ ) ,
110+ { ...opChecks ( provider ) }
84111 ) ;
85112 const event = await response . wait ( ) ;
86113
@@ -100,7 +127,10 @@ describe("Without Paymaster", () => {
100127 ] )
101128 ) ;
102129 }
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+ ) ;
104134 const event = await response . wait ( ) ;
105135
106136 expect ( event ?. args . success ) . toBe ( true ) ;
@@ -114,7 +144,8 @@ describe("Without Paymaster", () => {
114144 config . testGas ,
115145 0 ,
116146 testGas . interface . encodeFunctionData ( "recursiveCall" , [ 32 , 0 , 32 ] )
117- )
147+ ) ,
148+ { ...opChecks ( provider ) }
118149 ) ;
119150 } catch ( error : any ) {
120151 expect ( error ?. error . code ) . toBe ( errorCodes . executionReverted ) ;
@@ -125,6 +156,10 @@ describe("Without Paymaster", () => {
125156 describe ( "With zero value" , ( ) => {
126157 [ 0 , 2 , 4 , 8 , 16 ] . forEach ( ( depth ) => {
127158 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+
128163 const response = await client . sendUserOperation (
129164 acc . execute (
130165 config . testGas ,
@@ -134,7 +169,8 @@ describe("Without Paymaster", () => {
134169 0 ,
135170 depth ,
136171 ] )
137- )
172+ ) ,
173+ opts
138174 ) ;
139175 const event = await response . wait ( ) ;
140176
@@ -146,6 +182,10 @@ describe("Without Paymaster", () => {
146182 describe ( "With non-zero value" , ( ) => {
147183 [ 0 , 2 , 4 , 8 , 16 ] . forEach ( ( depth ) => {
148184 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+
149189 const response = await client . sendUserOperation (
150190 acc . execute (
151191 config . testGas ,
@@ -155,7 +195,8 @@ describe("Without Paymaster", () => {
155195 0 ,
156196 depth ,
157197 ] )
158- )
198+ ) ,
199+ opts
159200 ) ;
160201 const event = await response . wait ( ) ;
161202
@@ -167,6 +208,10 @@ describe("Without Paymaster", () => {
167208 describe ( "With multiple stacks per depth" , ( ) => {
168209 [ 0 , 1 , 2 , 3 ] . forEach ( ( depth ) => {
169210 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+
170215 const width = depth ;
171216 const response = await client . sendUserOperation (
172217 acc . execute (
@@ -177,7 +222,8 @@ describe("Without Paymaster", () => {
177222 width ,
178223 depth ,
179224 ] )
180- )
225+ ) ,
226+ opts
181227 ) ;
182228 const event = await response . wait ( ) ;
183229
0 commit comments