@@ -19,7 +19,7 @@ contract OrdersTest is Test {
19
19
uint256 amount = 200 ;
20
20
uint256 deadline = block .timestamp ;
21
21
22
- event OutputFilled ( uint256 indexed originChainId , address indexed recipient , address indexed token , uint256 amount );
22
+ event Filled (Output[] outputs );
23
23
24
24
event Order (uint256 deadline , Input[] inputs , Output[] outputs );
25
25
@@ -176,6 +176,65 @@ contract OrdersTest is Test {
176
176
vm.expectRevert (OrderOrigin.OnlyBuilder.selector );
177
177
target.sweep (recipient, token);
178
178
}
179
+
180
+ function test_fill_ETH () public {
181
+ outputs[0 ].token = address (0 );
182
+
183
+ vm.expectEmit ();
184
+ emit Filled (outputs);
185
+ target.fill {value: amount}(outputs);
186
+
187
+ // ETH is transferred to recipient
188
+ assertEq (recipient.balance, amount);
189
+ }
190
+
191
+ function test_fill_ERC20 () public {
192
+ vm.expectEmit ();
193
+ emit Filled (outputs);
194
+ vm.expectCall (token, abi.encodeWithSelector (ERC20 .transferFrom.selector , address (this ), recipient, amount));
195
+ target.fill (outputs);
196
+ }
197
+
198
+ function test_fill_both () public {
199
+ // add ETH output
200
+ outputs.push (Output (address (0 ), amount * 2 , recipient, chainId));
201
+
202
+ // expect Outputs are filled, ERC20 is transferred
203
+ vm.expectEmit ();
204
+ emit Filled (outputs);
205
+ vm.expectCall (token, abi.encodeWithSelector (ERC20 .transferFrom.selector , address (this ), recipient, amount));
206
+ target.fill {value: amount * 2 }(outputs);
207
+
208
+ // ETH is transferred to recipient
209
+ assertEq (recipient.balance, amount * 2 );
210
+ }
211
+
212
+ // fill multiple ETH outputs
213
+ function test_fill_multiETH () public {
214
+ // change first output to ETH
215
+ outputs[0 ].token = address (0 );
216
+ // add second ETH oputput
217
+ outputs.push (Output (address (0 ), amount * 2 , recipient, chainId));
218
+
219
+ // expect Order event is initiated
220
+ vm.expectEmit ();
221
+ emit Filled (outputs);
222
+ target.fill {value: amount * 3 }(outputs);
223
+
224
+ // ETH is transferred to recipient
225
+ assertEq (recipient.balance, amount * 3 );
226
+ }
227
+
228
+ function test_fill_underflowETH () public {
229
+ // change first output to ETH
230
+ outputs[0 ].token = address (0 );
231
+ // add second ETH output
232
+ outputs.push (Output (address (0 ), 1 , recipient, chainId));
233
+
234
+ // total ETH outputs should be `amount` + 1; function should underflow only sending `amount`
235
+ vm.expectRevert ();
236
+ target.fill {value: amount}(outputs);
237
+ }
179
238
}
180
239
181
240
contract OrdersFuzzTest is Test {
@@ -184,7 +243,7 @@ contract OrdersFuzzTest is Test {
184
243
185
244
uint256 deadline = block .timestamp + 100 ;
186
245
187
- event OutputFilled ( uint256 indexed originChainId , address indexed recipient , address indexed token , uint256 amount );
246
+ event Filled (Output[] outputs );
188
247
189
248
event Order (uint256 deadline , Input[] inputs , Output[] outputs );
190
249
@@ -202,7 +261,7 @@ contract OrdersFuzzTest is Test {
202
261
203
262
function testFuzz_initiate (Input[] memory fuzzInputs , Output[] memory fuzzOutputs ) public {
204
263
// can only use vm.assume 256 * 256 times, and we do 256 fuzz runs
205
- vm.assume (fuzzInputs.length < 256 );
264
+ vm.assume (fuzzInputs.length < 250 );
206
265
// setup the fuzz test by ensuring ETH and ERC20 amounts are available
207
266
uint256 totalETH;
208
267
for (uint256 i; i < fuzzInputs.length ; i++ ) {
@@ -212,19 +271,7 @@ contract OrdersFuzzTest is Test {
212
271
continue ;
213
272
}
214
273
215
- // ERC20 inputs must be one of the tokens we've deployed
216
- vm.assume (isToken[fuzzInputs[i].token]);
217
- // mint the token amount to ensure the address has it
218
- TestERC20 (fuzzInputs[i].token).mint (address (this ), fuzzInputs[i].amount);
219
- // approve the target to spend the total token amount
220
- TestERC20 (fuzzInputs[i].token).approve (address (target), type (uint256 ).max);
221
- // expect the token amount to be transferred
222
- vm.expectCall (
223
- fuzzInputs[i].token,
224
- abi.encodeWithSelector (
225
- ERC20 .transferFrom.selector , address (this ), address (target), fuzzInputs[i].amount
226
- )
227
- );
274
+ _setupToken (fuzzInputs[i].token, fuzzInputs[i].amount, address (target));
228
275
}
229
276
// deal the total ETH amount to ensure the address has it
230
277
vm.deal (address (this ), address (this ).balance + totalETH);
@@ -233,4 +280,36 @@ contract OrdersFuzzTest is Test {
233
280
emit Order (deadline, fuzzInputs, fuzzOutputs);
234
281
target.initiate {value: totalETH}(deadline, fuzzInputs, fuzzOutputs);
235
282
}
283
+
284
+ function testFuzz_fill (Output[] memory fuzzOutputs ) public {
285
+ // can only use vm.assume 256 * 256 times, and we do 256 fuzz runs
286
+ vm.assume (fuzzOutputs.length < 250 );
287
+ // setup the fuzz test by ensuring ETH and ERC20 amounts are available
288
+ uint256 totalETH;
289
+ for (uint256 i; i < fuzzOutputs.length ; i++ ) {
290
+ if (fuzzOutputs[i].token == address (0 )) {
291
+ totalETH += fuzzOutputs[i].amount;
292
+ continue ;
293
+ }
294
+
295
+ _setupToken (fuzzOutputs[i].token, fuzzOutputs[i].amount, fuzzOutputs[i].recipient);
296
+ }
297
+ // deal the total ETH amount to ensure the address has it
298
+ vm.deal (address (this ), address (this ).balance + totalETH);
299
+
300
+ vm.expectEmit ();
301
+ emit Filled (fuzzOutputs);
302
+ target.fill {value: totalETH}(fuzzOutputs);
303
+ }
304
+
305
+ function _setupToken (address token , uint256 amount , address recipient ) internal {
306
+ // ERC20 inputs must be one of the tokens we've deployed
307
+ vm.assume (isToken[token]);
308
+ // mint the token amount to ensure the address has it
309
+ TestERC20 (token).mint (address (this ), amount);
310
+ // approve the target to spend the total token amount
311
+ TestERC20 (token).approve (address (target), type (uint256 ).max);
312
+ // expect the token amount to be transferred
313
+ vm.expectCall (token, abi.encodeWithSelector (ERC20 .transferFrom.selector , address (this ), recipient, amount));
314
+ }
236
315
}
0 commit comments