diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index d2dc7b8a..64b5e9ce 100644 --- a/contracts/adapters/BaseUniswapAdapter.sol +++ b/contracts/adapters/BaseUniswapAdapter.sol @@ -150,7 +150,9 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt require(expectedMinAmountOut < minAmountOut, 'minAmountOut exceed max slippage'); - IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), amountToSwap); + // Approves the transfer for the swap. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), 0); + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), amountToSwap); address[] memory path; if (useEthPath) { @@ -207,7 +209,9 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt require(maxAmountToSwap < expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage'); - IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), maxAmountToSwap); + // Approves the transfer for the swap. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), 0); + IERC20(assetToSwapFrom).safeApprove(address(UNISWAP_ROUTER), maxAmountToSwap); address[] memory path; if (useEthPath) { @@ -483,7 +487,7 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt amountsWithoutWeth = resultAmounts; return - (amountsWithWeth[2] > amountsWithoutWeth[1]) + (amountsWithWeth[0] < amountsWithoutWeth[0] && amountsWithWeth[0] != 0) ? (amountsWithWeth, pathWithWeth) : (amountsWithoutWeth, simplePath); } catch { diff --git a/contracts/adapters/UniswapLiquiditySwapAdapter.sol b/contracts/adapters/UniswapLiquiditySwapAdapter.sol index aaf13406..daac3547 100644 --- a/contracts/adapters/UniswapLiquiditySwapAdapter.sol +++ b/contracts/adapters/UniswapLiquiditySwapAdapter.sol @@ -170,7 +170,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { ); // Deposit new reserve - IERC20(assetToSwapToList[vars.i]).approve(address(LENDING_POOL), vars.receivedAmount); + IERC20(assetToSwapToList[vars.i]).safeApprove(address(LENDING_POOL), 0); + IERC20(assetToSwapToList[vars.i]).safeApprove(address(LENDING_POOL), vars.receivedAmount); LENDING_POOL.deposit(assetToSwapToList[vars.i], vars.receivedAmount, msg.sender, 0); } } @@ -186,6 +187,16 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { * @param permitSignature List of struct containing the permit signature * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise */ + + struct SwapLiquidityLocalVars { + address aToken; + uint256 aTokenInitiatorBalance; + uint256 amountToSwap; + uint256 receivedAmount; + uint256 flashLoanDebt; + uint256 amountToPull; + } + function _swapLiquidity( address assetFrom, address assetTo, @@ -197,28 +208,36 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { PermitSignature memory permitSignature, bool useEthPath ) internal { - address aToken = _getReserveData(assetFrom).aTokenAddress; + SwapLiquidityLocalVars memory vars; - uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(initiator); - uint256 amountToSwap = - swapAllBalance && aTokenInitiatorBalance.sub(premium) <= amount - ? aTokenInitiatorBalance.sub(premium) - : amount; + vars.aToken = _getReserveData(assetFrom).aTokenAddress; - uint256 receivedAmount = - _swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive, useEthPath); + vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(initiator); + vars.amountToSwap = swapAllBalance && vars.aTokenInitiatorBalance.sub(premium) <= amount + ? vars.aTokenInitiatorBalance.sub(premium) + : amount; + + vars.receivedAmount = _swapExactTokensForTokens( + assetFrom, + assetTo, + vars.amountToSwap, + minAmountToReceive, + useEthPath + ); // Deposit new reserve - IERC20(assetTo).approve(address(LENDING_POOL), receivedAmount); - LENDING_POOL.deposit(assetTo, receivedAmount, initiator, 0); + IERC20(assetTo).safeApprove(address(LENDING_POOL), 0); + IERC20(assetTo).safeApprove(address(LENDING_POOL), vars.receivedAmount); + LENDING_POOL.deposit(assetTo, vars.receivedAmount, initiator, 0); - uint256 flashLoanDebt = amount.add(premium); - uint256 amountToPull = amountToSwap.add(premium); + vars.flashLoanDebt = amount.add(premium); + vars.amountToPull = vars.amountToSwap.add(premium); - _pullAToken(assetFrom, aToken, initiator, amountToPull, permitSignature); + _pullAToken(assetFrom, vars.aToken, initiator, vars.amountToPull, permitSignature); // Repay flash loan - IERC20(assetFrom).approve(address(LENDING_POOL), flashLoanDebt); + IERC20(assetFrom).safeApprove(address(LENDING_POOL), 0); + IERC20(assetFrom).safeApprove(address(LENDING_POOL), vars.flashLoanDebt); } /** diff --git a/contracts/adapters/UniswapRepayAdapter.sol b/contracts/adapters/UniswapRepayAdapter.sol index e8966cc2..b1c95337 100644 --- a/contracts/adapters/UniswapRepayAdapter.sol +++ b/contracts/adapters/UniswapRepayAdapter.sol @@ -141,8 +141,9 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ); } - // Repay debt - IERC20(debtAsset).approve(address(LENDING_POOL), amountToRepay); + // Repay debt. Approves 0 first to comply with tokens that implement the anti frontrunning approval fix + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amountToRepay); LENDING_POOL.repay(debtAsset, amountToRepay, debtRateMode, msg.sender); } @@ -171,8 +172,9 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ) internal { DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset); - // Repay debt - IERC20(debtAsset).approve(address(LENDING_POOL), amount); + // Repay debt. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount); uint256 repaidAmount = IERC20(debtAsset).balanceOf(address(this)); LENDING_POOL.repay(debtAsset, amount, rateMode, initiator); repaidAmount = repaidAmount.sub(IERC20(debtAsset).balanceOf(address(this))); @@ -216,8 +218,9 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ); } - // Repay flash loan - IERC20(debtAsset).approve(address(LENDING_POOL), amount.add(premium)); + // Repay flashloan. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix. + IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0); + IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount.add(premium)); } /**