@@ -11,7 +11,6 @@ const parseInitCode = initCode => ({
11
11
/// Global ERC-4337 environment helper.
12
12
class ERC4337Helper {
13
13
constructor ( ) {
14
- this . cache = new Map ( ) ;
15
14
this . envAsPromise = Promise . all ( [ ethers . provider . getNetwork ( ) , ethers . deployContract ( 'Create2Mock' ) ] ) . then (
16
15
( [ { chainId } , factory ] ) => ( {
17
16
chainId,
@@ -25,17 +24,14 @@ class ERC4337Helper {
25
24
}
26
25
27
26
async newAccount ( name , extraArgs = [ ] , params = { } ) {
28
- const { factory } = await this . wait ( ) ;
27
+ const { factory, chainId } = await this . wait ( ) ;
29
28
30
- if ( ! this . cache . has ( name ) ) {
31
- await ethers . getContractFactory ( name ) . then ( factory => this . cache . set ( name , factory ) ) ;
32
- }
33
- const accountFactory = this . cache . get ( name ) ;
29
+ const accountFactory = await ethers . getContractFactory ( name ) ;
34
30
35
31
if ( params . erc7702signer ) {
36
32
const delegate = await accountFactory . deploy ( ...extraArgs ) ;
37
33
const instance = await params . erc7702signer . getAddress ( ) . then ( address => accountFactory . attach ( address ) ) ;
38
- return new ERC7702SmartAccount ( instance , delegate , this ) ;
34
+ return new ERC7702SmartAccount ( instance , chainId , delegate ) ;
39
35
} else {
40
36
const initCode = await accountFactory
41
37
. getDeployTransaction ( ...extraArgs )
@@ -46,34 +42,18 @@ class ERC4337Helper {
46
42
const instance = await senderCreator . createSender
47
43
. staticCall ( initCode )
48
44
. then ( address => accountFactory . attach ( address ) ) ;
49
- return new SmartAccount ( instance , initCode , this ) ;
50
- }
51
- }
52
-
53
- async fillUserOp ( userOp ) {
54
- if ( ! userOp . nonce ) {
55
- userOp . nonce = await entrypoint . getNonce ( userOp . sender , 0 ) ;
56
- }
57
- if ( ethers . isAddressable ( userOp . paymaster ) ) {
58
- userOp . paymaster = await ethers . resolveAddress ( userOp . paymaster ) ;
59
- userOp . paymasterVerificationGasLimit ??= 100_000n ;
60
- userOp . paymasterPostOpGasLimit ??= 100_000n ;
61
- userOp . paymasterAndData = ethers . solidityPacked (
62
- [ 'address' , 'uint128' , 'uint128' ] ,
63
- [ userOp . paymaster , userOp . paymasterVerificationGasLimit , userOp . paymasterPostOpGasLimit ] ,
64
- ) ;
45
+ return new SmartAccount ( instance , chainId , initCode ) ;
65
46
}
66
- return userOp ;
67
47
}
68
48
}
69
49
70
50
/// Represent one ERC-4337 account contract.
71
51
class SmartAccount extends ethers . BaseContract {
72
- constructor ( instance , initCode , helper ) {
52
+ constructor ( instance , chainId , initCode ) {
73
53
super ( instance . target , instance . interface , instance . runner , instance . deployTx ) ;
74
54
this . address = instance . target ;
55
+ this . chainId = chainId ;
75
56
this . initCode = initCode ;
76
- this . helper = helper ;
77
57
}
78
58
79
59
async deploy ( account = this . runner ) {
@@ -82,48 +62,44 @@ class SmartAccount extends ethers.BaseContract {
82
62
return this ;
83
63
}
84
64
85
- createOp ( userOp = { } ) {
86
- return this . helper
87
- . fillUserOp ( { sender : this , ...userOp } )
88
- . then ( filledUserOp => new UserOperationWithContext ( filledUserOp ) ) ;
65
+ async createUserOp ( userOp = { } ) {
66
+ userOp . sender ??= this ;
67
+ userOp . nonce ??= await entrypoint . getNonce ( userOp . sender , 0 ) ;
68
+ if ( ethers . isAddressable ( userOp . paymaster ) ) {
69
+ userOp . paymaster = await ethers . resolveAddress ( userOp . paymaster ) ;
70
+ userOp . paymasterVerificationGasLimit ??= 100_000n ;
71
+ userOp . paymasterPostOpGasLimit ??= 100_000n ;
72
+ }
73
+ return new UserOperationWithContext ( userOp ) ;
89
74
}
90
75
}
91
76
92
- class ERC7702SmartAccount extends ethers . BaseContract {
93
- constructor ( instance , delegate , helper ) {
94
- super ( instance . target , instance . interface , instance . runner , instance . deployTx ) ;
95
- this . address = instance . target ;
77
+ class ERC7702SmartAccount extends SmartAccount {
78
+ constructor ( instance , chainId , delegate ) {
79
+ super ( instance , chainId ) ;
96
80
this . delegate = delegate ;
97
- this . helper = helper ;
98
81
}
99
82
100
83
async deploy ( ) {
101
84
await ethers . provider . getCode ( this . delegate ) . then ( code => setCode ( this . target , code ) ) ;
102
85
return this ;
103
86
}
104
-
105
- createOp ( userOp = { } ) {
106
- return this . helper
107
- . fillUserOp ( { sender : this , ...userOp } )
108
- . then ( filledUserOp => new UserOperationWithContext ( filledUserOp ) ) ;
109
- }
110
87
}
111
88
112
89
class UserOperationWithContext extends UserOperation {
113
90
constructor ( params ) {
114
91
super ( params ) ;
115
- this . params = params ;
92
+ this . initCode = params . sender ?. initCode ;
93
+ this . chainId = params . sender ?. chainId ;
116
94
}
117
95
118
96
addInitCode ( ) {
119
- const { initCode } = this . params . sender ;
120
- if ( ! initCode ) throw new Error ( 'No init code available for the sender of this user operation' ) ;
121
- return Object . assign ( this , parseInitCode ( initCode ) ) ;
97
+ if ( ! this . initCode ) throw new Error ( 'No init code available for the sender of this user operation' ) ;
98
+ return Object . assign ( this , parseInitCode ( this . initCode ) ) ;
122
99
}
123
100
124
101
hash ( ) {
125
- const { chainId } = this . params . sender . helper . env ;
126
- return super . hash ( entrypoint , chainId ) ;
102
+ return super . hash ( entrypoint , this . chainId ) ;
127
103
}
128
104
}
129
105
0 commit comments