@@ -15,9 +15,20 @@ async function fixture() {
15
15
const forwarderAsSigner = await impersonate ( forwarder . target ) ;
16
16
const context = await ethers . deployContract ( 'ERC2771ContextMock' , [ forwarder ] ) ;
17
17
const domain = await getDomain ( forwarder ) ;
18
- const types = { ForwardRequest } ;
19
18
20
- return { sender, other, forwarder, forwarderAsSigner, context, domain, types } ;
19
+ const prepareAndSignRequest = async ( signer , request ) => {
20
+ // request.to is mandatory
21
+ request . from ??= signer . address ;
22
+ request . value ??= 0n ;
23
+ request . data ??= '0x' ;
24
+ request . gas ??= 100000n ;
25
+ request . nonce ??= await forwarder . nonces ( signer ) ;
26
+ request . deadline ??= MAX_UINT48 ;
27
+ request . signature = await signer . signTypedData ( domain , { ForwardRequest } , request ) ;
28
+ return request ;
29
+ } ;
30
+
31
+ return { sender, other, forwarder, forwarderAsSigner, context, prepareAndSignRequest } ;
21
32
}
22
33
23
34
describe ( 'ERC2771Context' , function ( ) {
@@ -26,11 +37,11 @@ describe('ERC2771Context', function () {
26
37
} ) ;
27
38
28
39
it ( 'recognize trusted forwarder' , async function ( ) {
29
- expect ( await this . context . isTrustedForwarder ( this . forwarder ) ) . to . be . true ;
40
+ await expect ( this . context . isTrustedForwarder ( this . forwarder ) ) . to . eventually . be . true ;
30
41
} ) ;
31
42
32
43
it ( 'returns the trusted forwarder' , async function ( ) {
33
- expect ( await this . context . trustedForwarder ( ) ) . to . equal ( this . forwarder ) ;
44
+ await expect ( this . context . trustedForwarder ( ) ) . to . eventually . equal ( this . forwarder ) ;
34
45
} ) ;
35
46
36
47
describe ( 'when called directly' , function ( ) {
@@ -40,23 +51,12 @@ describe('ERC2771Context', function () {
40
51
describe ( 'when receiving a relayed call' , function ( ) {
41
52
describe ( 'msgSender' , function ( ) {
42
53
it ( 'returns the relayed transaction original sender' , async function ( ) {
43
- const nonce = await this . forwarder . nonces ( this . sender ) ;
44
- const data = this . context . interface . encodeFunctionData ( 'msgSender' ) ;
45
-
46
- const req = {
47
- from : await this . sender . getAddress ( ) ,
48
- to : await this . context . getAddress ( ) ,
49
- value : 0n ,
50
- data,
51
- gas : 100000n ,
52
- nonce,
53
- deadline : MAX_UINT48 ,
54
- } ;
55
-
56
- req . signature = await this . sender . signTypedData ( this . domain , this . types , req ) ;
57
-
58
- expect ( await this . forwarder . verify ( req ) ) . to . be . true ;
54
+ const req = await this . prepareAndSignRequest ( this . sender , {
55
+ to : this . context . target ,
56
+ data : this . context . interface . encodeFunctionData ( 'msgSender' ) ,
57
+ } ) ;
59
58
59
+ await expect ( this . forwarder . verify ( req ) ) . to . eventually . be . true ;
60
60
await expect ( this . forwarder . execute ( req ) ) . to . emit ( this . context , 'Sender' ) . withArgs ( this . sender ) ;
61
61
} ) ;
62
62
@@ -72,62 +72,38 @@ describe('ERC2771Context', function () {
72
72
it ( 'returns the relayed transaction original data' , async function ( ) {
73
73
const args = [ 42n , 'OpenZeppelin' ] ;
74
74
75
- const nonce = await this . forwarder . nonces ( this . sender ) ;
76
- const data = this . context . interface . encodeFunctionData ( 'msgData' , args ) ;
77
-
78
- const req = {
79
- from : await this . sender . getAddress ( ) ,
80
- to : await this . context . getAddress ( ) ,
81
- value : 0n ,
82
- data,
83
- gas : 100000n ,
84
- nonce,
85
- deadline : MAX_UINT48 ,
86
- } ;
87
-
88
- req . signature = this . sender . signTypedData ( this . domain , this . types , req ) ;
89
-
90
- expect ( await this . forwarder . verify ( req ) ) . to . be . true ;
75
+ const req = await this . prepareAndSignRequest ( this . sender , {
76
+ to : this . context . target ,
77
+ data : this . context . interface . encodeFunctionData ( 'msgData' , args ) ,
78
+ } ) ;
91
79
80
+ await expect ( this . forwarder . verify ( req ) ) . to . eventually . be . true ;
92
81
await expect ( this . forwarder . execute ( req ) )
93
82
. to . emit ( this . context , 'Data' )
94
- . withArgs ( data , ...args ) ;
83
+ . withArgs ( req . data , ...args ) ;
95
84
} ) ;
96
85
} ) ;
97
86
98
87
it ( 'returns the full original data when calldata length is less than 20 bytes (address length)' , async function ( ) {
99
88
const data = this . context . interface . encodeFunctionData ( 'msgDataShort' ) ;
100
89
101
90
// The forwarder doesn't produce calls with calldata length less than 20 bytes so `this.forwarderAsSigner` is used instead.
102
- await expect ( await this . context . connect ( this . forwarderAsSigner ) . msgDataShort ( ) )
91
+ await expect ( this . context . connect ( this . forwarderAsSigner ) . msgDataShort ( ) )
103
92
. to . emit ( this . context , 'DataShort' )
104
93
. withArgs ( data ) ;
105
94
} ) ;
106
95
} ) ;
107
96
108
97
it ( 'multicall poison attack' , async function ( ) {
109
- const nonce = await this . forwarder . nonces ( this . sender ) ;
110
- const data = this . context . interface . encodeFunctionData ( 'multicall' , [
111
- [
112
- // poisoned call to 'msgSender()'
113
- ethers . concat ( [ this . context . interface . encodeFunctionData ( 'msgSender' ) , this . other . address ] ) ,
114
- ] ,
115
- ] ) ;
116
-
117
- const req = {
118
- from : await this . sender . getAddress ( ) ,
119
- to : await this . context . getAddress ( ) ,
120
- value : 0n ,
121
- data,
122
- gas : 100000n ,
123
- nonce,
124
- deadline : MAX_UINT48 ,
125
- } ;
126
-
127
- req . signature = await this . sender . signTypedData ( this . domain , this . types , req ) ;
128
-
129
- expect ( await this . forwarder . verify ( req ) ) . to . be . true ;
98
+ const req = await this . prepareAndSignRequest ( this . sender , {
99
+ to : this . context . target ,
100
+ data : this . context . interface . encodeFunctionData ( 'multicall' , [
101
+ // poisonned call to 'msgSender()'
102
+ [ ethers . concat ( [ this . context . interface . encodeFunctionData ( 'msgSender' ) , this . other . address ] ) ] ,
103
+ ] ) ,
104
+ } ) ;
130
105
106
+ await expect ( this . forwarder . verify ( req ) ) . to . eventually . be . true ;
131
107
await expect ( this . forwarder . execute ( req ) ) . to . emit ( this . context , 'Sender' ) . withArgs ( this . sender ) ;
132
108
} ) ;
133
109
} ) ;
0 commit comments