From 773bdd252b311a1929c26b9339ace1b78c41e533 Mon Sep 17 00:00:00 2001 From: The3D Date: Thu, 14 Jan 2021 15:21:42 +0100 Subject: [PATCH] Added latest fixes --- contracts/adapters/BaseUniswapAdapter.sol | 28 ++++++++--- .../adapters/UniswapLiquiditySwapAdapter.sol | 46 +++++++++++++------ contracts/adapters/UniswapRepayAdapter.sol | 21 +++++---- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/contracts/adapters/BaseUniswapAdapter.sol b/contracts/adapters/BaseUniswapAdapter.sol index 8cd80faf..b04bc8a1 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) { @@ -190,7 +192,8 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt address assetToSwapFrom, address assetToSwapTo, uint256 maxAmountToSwap, - uint256 amountToReceive + uint256 amountToReceive, + bool useEthPath ) internal returns (uint256) { uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); uint256 toAssetDecimals = _getDecimals(assetToSwapTo); @@ -206,11 +209,22 @@ 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) { + path = new address[](3); + path[0] = assetToSwapFrom; + path[1] = WETH_ADDRESS; + path[2] = assetToSwapTo; + } else { + path = new address[](2); + path[0] = assetToSwapFrom; + path[1] = assetToSwapTo; + } - address[] memory path = new address[](2); - path[0] = assetToSwapFrom; - path[1] = assetToSwapTo; uint256[] memory amounts = UNISWAP_ROUTER.swapTokensForExactTokens( amountToReceive, @@ -472,7 +486,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..44745ad5 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,33 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { PermitSignature memory permitSignature, bool useEthPath ) internal { - address aToken = _getReserveData(assetFrom).aTokenAddress; + + SwapLiquidityLocalVars memory vars; + + vars.aToken = _getReserveData(assetFrom).aTokenAddress; - uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(initiator); - uint256 amountToSwap = - swapAllBalance && aTokenInitiatorBalance.sub(premium) <= amount - ? aTokenInitiatorBalance.sub(premium) + vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(initiator); + vars.amountToSwap = + swapAllBalance && vars.aTokenInitiatorBalance.sub(premium) <= amount + ? vars.aTokenInitiatorBalance.sub(premium) : amount; - uint256 receivedAmount = - _swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive, useEthPath); + 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); } /** @@ -261,4 +277,4 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter { useEthPath ); } -} +} \ No newline at end of file diff --git a/contracts/adapters/UniswapRepayAdapter.sol b/contracts/adapters/UniswapRepayAdapter.sol index b5ce12bb..c4e7817e 100644 --- a/contracts/adapters/UniswapRepayAdapter.sol +++ b/contracts/adapters/UniswapRepayAdapter.sol @@ -129,7 +129,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ); // Swap collateral for debt asset - _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], amountToRepay); + _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], amountToRepay, useEthPath); } else { // Pull aTokens from user _pullAToken( @@ -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))); @@ -198,7 +200,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { ); // Swap collateral asset to the debt asset - _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], neededForFlashLoanDebt); + _swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], neededForFlashLoanDebt, useEthPath); } else { // Pull aTokens from user _pullAToken( @@ -210,8 +212,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)); } /** @@ -253,4 +256,4 @@ contract UniswapRepayAdapter is BaseUniswapAdapter { useEthPath ); } -} +} \ No newline at end of file