@@ -33,9 +33,9 @@ contract BatchNoConversionPayments is Ownable {
33
33
uint256 internal feeDenominator = 10000 ;
34
34
35
35
/** payerAuthorized is set to true only when needed for batch Eth conversion */
36
- bool internal payerAuthorized;
36
+ bool internal payerAuthorized = false ;
37
37
/** batchPayment function is the caller */
38
- bool internal batchPaymentOrigin;
38
+ bool internal batchPaymentOrigin = false ;
39
39
40
40
/** transferBackRemainingEth is set to false only if the payer use batchRouter
41
41
and call both batchEthPayments and batchConversionEthPaymentsWithReference */
@@ -63,7 +63,7 @@ contract BatchNoConversionPayments is Ownable {
63
63
* feeAmount: The fee amount, denominated in the first currency of `path` for conversion payment
64
64
* maxToSpend: Only for conversion payment:
65
65
* Maximum amount the payer wants to spend, denominated in the last currency of `path`:
66
- * it includes fee proxy but NOT the batchFee
66
+ * it includes fee proxy but NOT the batch fees to pay
67
67
* maxRateTimespan: Only for conversion payment:
68
68
* Max acceptable times span for conversion rates, ignored if zero
69
69
*/
@@ -181,31 +181,37 @@ contract BatchNoConversionPayments is Ownable {
181
181
if (batchPaymentOrigin != true ) {
182
182
batchFeeAmountUSD = 0 ;
183
183
}
184
- // amount is used to get the total amount, and then used as batch fee amount
185
- uint256 amount = 0 ;
186
184
uint256 amountAndFee = 0 ;
185
+ uint256 batchFeeAmount = 0 ;
187
186
for (uint256 i = 0 ; i < conversionDetails.length ; i++ ) {
188
- amount += conversionDetails[i].requestAmount;
189
187
amountAndFee += conversionDetails[i].requestAmount + conversionDetails[i].feeAmount;
188
+ batchFeeAmount += conversionDetails[i].requestAmount;
190
189
}
190
+ batchFeeAmount = (batchFeeAmount * batchFee) / feeDenominator;
191
+
192
+ // batchFeeToPay and batchFeeAmountUSD are updated if needed
193
+ (batchFeeAmount, batchFeeAmountUSD) = calculateBatchFeeToPay (
194
+ batchFeeAmount,
195
+ conversionDetails[0 ].path[0 ],
196
+ batchFeeAmountUSD,
197
+ pathsToUSD
198
+ );
191
199
192
- // Transfer the amount and fee from the payer to the batch contract
193
200
IERC20 requestedToken = IERC20 (conversionDetails[0 ].path[0 ]);
194
- require (
195
- requestedToken.allowance (msg .sender , address (this )) >= amountAndFee,
196
- 'Insufficient allowance for batch to pay '
201
+
202
+ contractAllowanceApprovalTransfer (
203
+ requestedToken,
204
+ amountAndFee,
205
+ batchFeeAmount,
206
+ address (paymentErc20Proxy)
197
207
);
198
- require (requestedToken.balanceOf (msg .sender ) >= amountAndFee, 'Not enough funds ' );
208
+
209
+ // Payer pays batch fee amount
199
210
require (
200
- safeTransferFrom (conversionDetails[0 ].path[0 ], address ( this ), amountAndFee ),
201
- 'payment transferFrom() failed '
211
+ safeTransferFrom (conversionDetails[0 ].path[0 ], feeAddress, batchFeeAmount ),
212
+ 'Batch fee transferFrom() failed '
202
213
);
203
214
204
- // Batch contract approve Erc20FeeProxy to spend the token
205
- if (requestedToken.allowance (address (this ), address (paymentErc20Proxy)) < amountAndFee) {
206
- approvePaymentProxyToSpend (address (requestedToken), address (paymentErc20Proxy));
207
- }
208
-
209
215
// Batch contract pays the requests using Erc20FeeProxy
210
216
for (uint256 i = 0 ; i < conversionDetails.length ; i++ ) {
211
217
ConversionDetail memory cD = conversionDetails[i];
@@ -219,24 +225,6 @@ contract BatchNoConversionPayments is Ownable {
219
225
);
220
226
}
221
227
222
- // amount is updated into batch fee amount
223
- amount = (amount * batchFee) / feeDenominator;
224
- // Check if the payer has enough funds to pay batch fee
225
- require (requestedToken.balanceOf (msg .sender ) >= amount, 'Not enough funds for the batch fee ' );
226
-
227
- // Payer pays batch fee amount
228
- // amount that represents batchFeeToPay updated if needed
229
- (amount, batchFeeAmountUSD) = calculateBatchFeeToPay (
230
- amount,
231
- conversionDetails[0 ].path[0 ],
232
- batchFeeAmountUSD,
233
- pathsToUSD
234
- );
235
- require (
236
- safeTransferFrom (conversionDetails[0 ].path[0 ], feeAddress, amount),
237
- 'Batch fee transferFrom() failed '
238
- );
239
-
240
228
return batchFeeAmountUSD;
241
229
}
242
230
@@ -265,34 +253,15 @@ contract BatchNoConversionPayments is Ownable {
265
253
266
254
// The payer transfers tokens to the batch contract and pays batch fee
267
255
for (uint256 i = 0 ; i < uTokens.length && uTokens[i].amountAndFee > 0 ; i++ ) {
268
- IERC20 requestedToken = IERC20 (uTokens[i].tokenAddress);
269
256
uTokens[i].batchFeeAmount = (uTokens[i].batchFeeAmount * batchFee) / feeDenominator;
270
-
271
- require (
272
- requestedToken.allowance (msg .sender , address (this )) >=
273
- uTokens[i].amountAndFee + uTokens[i].batchFeeAmount,
274
- 'Insufficient allowance for batch to pay '
275
- );
276
- // Check if the payer can pay the amount, the fee, and the batchFee
277
- require (
278
- requestedToken.balanceOf (msg .sender ) >= uTokens[i].amountAndFee + uTokens[i].batchFeeAmount,
279
- 'Not enough funds '
280
- );
281
-
282
- // Transfer only the amount and fee required for the token on the batch contract
283
- require (
284
- safeTransferFrom (uTokens[i].tokenAddress, address (this ), uTokens[i].amountAndFee),
285
- 'payment transferFrom() failed '
257
+ IERC20 requestedToken = IERC20 (uTokens[i].tokenAddress);
258
+ contractAllowanceApprovalTransfer (
259
+ requestedToken,
260
+ uTokens[i].amountAndFee,
261
+ uTokens[i].batchFeeAmount,
262
+ address (paymentErc20Proxy)
286
263
);
287
264
288
- // Batch contract approves Erc20FeeProxy to spend the token
289
- if (
290
- requestedToken.allowance (address (this ), address (paymentErc20Proxy)) <
291
- uTokens[i].amountAndFee
292
- ) {
293
- approvePaymentProxyToSpend (address (requestedToken), address (paymentErc20Proxy));
294
- }
295
-
296
265
// Payer pays batch fee amount
297
266
298
267
uint256 batchFeeToPay = uTokens[i].batchFeeAmount;
@@ -329,6 +298,46 @@ contract BatchNoConversionPayments is Ownable {
329
298
* Helper functions
330
299
*/
331
300
301
+ /**
302
+ * It:
303
+ * - checks that the batch contract has enough allowance from the payer
304
+ * - checks that the payer has enough fund, including batch fees
305
+ * - does the transfer of token from the payer to the batch contract
306
+ * - increases the allowance of the contract to use the payment proxy if needed
307
+ * @param requestedToken The token to pay
308
+ * @param amountAndFee The amount and the fee for a token to pay
309
+ * @param batchFeeAmount The batch fee amount for a token to pay
310
+ * @param paymentProxyAddress The payment proxy address used to pay
311
+ */
312
+ function contractAllowanceApprovalTransfer (
313
+ IERC20 requestedToken ,
314
+ uint256 amountAndFee ,
315
+ uint256 batchFeeAmount ,
316
+ address paymentProxyAddress
317
+ ) internal {
318
+ // Check proxy's allowance from user
319
+ require (
320
+ requestedToken.allowance (msg .sender , address (this )) >= amountAndFee,
321
+ 'Insufficient allowance for batch to pay '
322
+ );
323
+ // Check user's funds to pay amounts, it is an approximation for conversion payment
324
+ require (
325
+ requestedToken.balanceOf (msg .sender ) >= amountAndFee + batchFeeAmount,
326
+ 'Not enough funds, including fees '
327
+ );
328
+
329
+ // Transfer the amount and fee required for the token on the batch contract
330
+ require (
331
+ safeTransferFrom (address (requestedToken), address (this ), amountAndFee),
332
+ 'payment transferFrom() failed '
333
+ );
334
+
335
+ // Batch contract approves Erc20ConversionProxy to spend the token
336
+ if (requestedToken.allowance (address (this ), paymentProxyAddress) < amountAndFee) {
337
+ approvePaymentProxyToSpend (address (requestedToken), paymentProxyAddress);
338
+ }
339
+ }
340
+
332
341
/**
333
342
* It create a list of unique tokens used and the amounts associated.
334
343
* It only considers tokens having: requestAmount + feeAmount > 0.
0 commit comments