@@ -12,7 +12,7 @@ const ContextMockCaller = artifacts.require('ContextMockCaller');
1212const  {  shouldBehaveLikeRegularContext }  =  require ( '../utils/Context.behavior' ) ; 
1313
1414contract ( 'ERC2771Context' ,  function  ( accounts )  { 
15-   const  [ ,  trustedForwarder ]  =  accounts ; 
15+   const  [ ,  trustedForwarder ,   other ]  =  accounts ; 
1616
1717  beforeEach ( async  function  ( )  { 
1818    this . forwarder  =  await  MinimalForwarder . new ( ) ; 
@@ -118,5 +118,58 @@ contract('ERC2771Context', function (accounts) {
118118      const  data  =  recipient . contract . methods . msgDataShort ( ) . encodeABI ( ) ; 
119119      await  expectEvent ( receipt ,  'DataShort' ,  {  data } ) ; 
120120    } ) ; 
121+ 
122+     it ( 'multicall poison attack' ,  async  function  ( )  { 
123+       const  attacker  =  Wallet . generate ( ) ; 
124+       const  attackerAddress  =  attacker . getChecksumAddressString ( ) ; 
125+       const  nonce  =  await  this . forwarder . getNonce ( attackerAddress ) ; 
126+ 
127+       const  msgSenderCall  =  web3 . eth . abi . encodeFunctionCall ( 
128+         { 
129+           name : 'msgSender' , 
130+           type : 'function' , 
131+           inputs : [ ] , 
132+         } , 
133+         [ ] , 
134+       ) ; 
135+ 
136+       const  data  =  web3 . eth . abi . encodeFunctionCall ( 
137+         { 
138+           name : 'multicall' , 
139+           type : 'function' , 
140+           inputs : [ 
141+             { 
142+               internalType : 'bytes[]' , 
143+               name : 'data' , 
144+               type : 'bytes[]' , 
145+             } , 
146+           ] , 
147+         } , 
148+         [ [ web3 . utils . encodePacked ( {  value : msgSenderCall ,  type : 'bytes'  } ,  {  value : other ,  type : 'address'  } ) ] ] , 
149+       ) ; 
150+ 
151+       const  req  =  { 
152+         from : attackerAddress , 
153+         to : this . recipient . address , 
154+         value : '0' , 
155+         gas : '100000' , 
156+         data, 
157+         nonce : Number ( nonce ) , 
158+       } ; 
159+ 
160+       const  signature  =  await  ethSigUtil . signTypedMessage ( attacker . getPrivateKey ( ) ,  { 
161+         data : { 
162+           types : this . types , 
163+           domain : this . domain , 
164+           primaryType : 'ForwardRequest' , 
165+           message : req , 
166+         } , 
167+       } ) ; 
168+ 
169+       expect ( await  this . forwarder . verify ( req ,  signature ) ) . to . equal ( true ) ; 
170+ 
171+       const  receipt  =  await  this . forwarder . execute ( req ,  signature ) ; 
172+       await  expectEvent . inTransaction ( receipt . tx ,  ERC2771ContextMock ,  'Sender' ,  {  sender : attackerAddress  } ) ; 
173+     } ) ; 
121174  } ) ; 
122175} ) ; 
0 commit comments