Updated to receive theindication on which path to use from outside

This commit is contained in:
The3D 2020-12-02 15:30:57 +01:00
parent a25bdd9280
commit d611b1e8dc
3 changed files with 103 additions and 36 deletions

View File

@ -131,7 +131,8 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
address assetToSwapFrom, address assetToSwapFrom,
address assetToSwapTo, address assetToSwapTo,
uint256 amountToSwap, uint256 amountToSwap,
uint256 minAmountOut uint256 minAmountOut,
bool useEthPath
) internal returns (uint256) { ) internal returns (uint256) {
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
uint256 toAssetDecimals = _getDecimals(assetToSwapTo); uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
@ -149,9 +150,17 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), amountToSwap); IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), amountToSwap);
address[] memory path = new address[](2); address[] memory path;
path[0] = assetToSwapFrom; if (useEthPath) {
path[1] = assetToSwapTo; 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;
}
uint256[] memory amounts = uint256[] memory amounts =
UNISWAP_ROUTER.swapExactTokensForTokens( UNISWAP_ROUTER.swapExactTokensForTokens(
amountToSwap, amountToSwap,
@ -374,7 +383,7 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
uint256 amountOut uint256 amountOut
) internal view returns (AmountCalc memory) { ) internal view returns (AmountCalc memory) {
(uint256[] memory amounts, address[] memory path) = (uint256[] memory amounts, address[] memory path) =
_getAmountsIn(reserveIn, reserveOut, amountOut); _getAmountsInAndPath(reserveIn, reserveOut, amountOut);
// Add flash loan fee // Add flash loan fee
uint256 finalAmountIn = amounts[0].add(amounts[0].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000)); uint256 finalAmountIn = amounts[0].add(amounts[0].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000));
@ -404,7 +413,7 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
* @param amountOut Amount of reserveOut * @param amountOut Amount of reserveOut
* @return uint256[] amounts Array containing the amountIn and amountOut for a swap * @return uint256[] amounts Array containing the amountIn and amountOut for a swap
*/ */
function _getAmountsIn( function _getAmountsInAndPath(
address reserveIn, address reserveIn,
address reserveOut, address reserveOut,
uint256 amountOut uint256 amountOut
@ -419,14 +428,43 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
uint256[] memory resultAmounts uint256[] memory resultAmounts
) { ) {
amounts = resultAmounts; amounts = resultAmounts;
return (amounts, simplePath);
} catch { } catch {
pathWithWeth[0] = reserveIn; pathWithWeth[0] = reserveIn;
pathWithWeth[1] = WETH_ADDRESS; pathWithWeth[1] = WETH_ADDRESS;
pathWithWeth[2] = reserveOut; pathWithWeth[2] = reserveOut;
amounts = UNISWAP_ROUTER.getAmountsIn(amountOut, pathWithWeth); amounts = UNISWAP_ROUTER.getAmountsIn(amountOut, pathWithWeth);
return (amounts, pathWithWeth);
}
}
/**
* @dev Calculates the input asset amount required to buy the given output asset amount
* @param reserveIn Address of the asset to be swap from
* @param reserveOut Address of the asset to be swap to
* @param amountOut Amount of reserveOut
* @return uint256[] amounts Array containing the amountIn and amountOut for a swap
*/
function _getAmountsIn(
address reserveIn,
address reserveOut,
uint256 amountOut,
bool useEthPath
) internal view returns (uint256[] memory) {
address[] memory path;
if (useEthPath) {
path = new address[](3);
path[0] = reserveIn;
path[1] = WETH_ADDRESS;
path[2] = reserveOut;
} else {
path = new address[](2);
path[0] = reserveIn;
path[1] = reserveOut;
} }
return (amounts, (pathWithWeth[0] != address(0) ? pathWithWeth : simplePath)); return UNISWAP_ROUTER.getAmountsIn(amountOut, path);
} }
} }

View File

@ -26,6 +26,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
uint256[] minAmountsToReceive; uint256[] minAmountsToReceive;
bool[] swapAllBalance; bool[] swapAllBalance;
PermitParams permitParams; PermitParams permitParams;
bool[] useEthPath;
} }
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter) constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
@ -71,7 +72,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
assets.length == decodedParams.permitParams.deadline.length && assets.length == decodedParams.permitParams.deadline.length &&
assets.length == decodedParams.permitParams.v.length && assets.length == decodedParams.permitParams.v.length &&
assets.length == decodedParams.permitParams.r.length && assets.length == decodedParams.permitParams.r.length &&
assets.length == decodedParams.permitParams.s.length, assets.length == decodedParams.permitParams.s.length &&
assets.length == decodedParams.useEthPath.length,
'INCONSISTENT_PARAMS' 'INCONSISTENT_PARAMS'
); );
@ -90,13 +92,22 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
decodedParams.permitParams.v[i], decodedParams.permitParams.v[i],
decodedParams.permitParams.r[i], decodedParams.permitParams.r[i],
decodedParams.permitParams.s[i] decodedParams.permitParams.s[i]
) ),
decodedParams.useEthPath[i]
); );
} }
return true; return true;
} }
struct SwapAndDepositLocalVars {
uint256 i;
uint256 aTokenInitiatorBalance;
uint256 amountToSwap;
uint256 receivedAmount;
address aToken;
}
/** /**
* @dev Swaps an amount of an asset to another and deposits the new asset amount on behalf of the user without using * @dev Swaps an amount of an asset to another and deposits the new asset amount on behalf of the user without using
* a flash loan. This method can be used when the temporary transfer of the collateral asset to this contract * a flash loan. This method can be used when the temporary transfer of the collateral asset to this contract
@ -113,13 +124,15 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
* uint8 v param for the permit signature * uint8 v param for the permit signature
* bytes32 r param for the permit signature * bytes32 r param for the permit signature
* bytes32 s param for the permit signature * bytes32 s param for the permit signature
* @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise
*/ */
function swapAndDeposit( function swapAndDeposit(
address[] calldata assetToSwapFromList, address[] calldata assetToSwapFromList,
address[] calldata assetToSwapToList, address[] calldata assetToSwapToList,
uint256[] calldata amountToSwapList, uint256[] calldata amountToSwapList,
uint256[] calldata minAmountsToReceive, uint256[] calldata minAmountsToReceive,
PermitSignature[] calldata permitParams PermitSignature[] calldata permitParams,
bool[] calldata useEthPath
) external { ) external {
require( require(
assetToSwapFromList.length == assetToSwapToList.length && assetToSwapFromList.length == assetToSwapToList.length &&
@ -129,26 +142,29 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
'INCONSISTENT_PARAMS' 'INCONSISTENT_PARAMS'
); );
for (uint256 i = 0; i < assetToSwapFromList.length; i++) { SwapAndDepositLocalVars memory vars;
address aToken = _getReserveData(assetToSwapFromList[i]).aTokenAddress;
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(msg.sender); for (vars.i = 0; vars.i < assetToSwapFromList.length; vars.i++) {
uint256 amountToSwap = vars.aToken = _getReserveData(assetToSwapFromList[vars.i]).aTokenAddress;
amountToSwapList[i] > aTokenInitiatorBalance ? aTokenInitiatorBalance : amountToSwapList[i];
_pullAToken(assetToSwapFromList[i], aToken, msg.sender, amountToSwap, permitParams[i]); vars.aTokenInitiatorBalance = IERC20(vars.aToken).balanceOf(msg.sender);
vars.amountToSwap =
amountToSwapList[vars.i] > vars.aTokenInitiatorBalance ? vars.aTokenInitiatorBalance : amountToSwapList[vars.i];
uint256 receivedAmount = _pullAToken(assetToSwapFromList[vars.i], vars.aToken, msg.sender, vars.amountToSwap, permitParams[vars.i]);
vars.receivedAmount =
_swapExactTokensForTokens( _swapExactTokensForTokens(
assetToSwapFromList[i], assetToSwapFromList[vars.i],
assetToSwapToList[i], assetToSwapToList[vars.i],
amountToSwap, vars.amountToSwap,
minAmountsToReceive[i] minAmountsToReceive[vars.i],
useEthPath[vars.i]
); );
// Deposit new reserve // Deposit new reserve
IERC20(assetToSwapToList[i]).approve(address(LENDING_POOL), receivedAmount); IERC20(assetToSwapToList[vars.i]).approve(address(LENDING_POOL), vars.receivedAmount);
LENDING_POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0); LENDING_POOL.deposit(assetToSwapToList[vars.i], vars.receivedAmount, msg.sender, 0);
} }
} }
@ -161,6 +177,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
* @param minAmountToReceive Min amount to be received from the swap * @param minAmountToReceive Min amount to be received from the swap
* @param swapAllBalance Flag indicating if all the user balance should be swapped * @param swapAllBalance Flag indicating if all the user balance should be swapped
* @param permitSignature List of struct containing the permit signature * @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
*/ */
function _swapLiquidity( function _swapLiquidity(
address assetFrom, address assetFrom,
@ -170,7 +187,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
address initiator, address initiator,
uint256 minAmountToReceive, uint256 minAmountToReceive,
bool swapAllBalance, bool swapAllBalance,
PermitSignature memory permitSignature PermitSignature memory permitSignature,
bool useEthPath
) internal { ) internal {
address aToken = _getReserveData(assetFrom).aTokenAddress; address aToken = _getReserveData(assetFrom).aTokenAddress;
@ -181,7 +199,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
: amount; : amount;
uint256 receivedAmount = uint256 receivedAmount =
_swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive); _swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive, useEthPath);
// Deposit new reserve // Deposit new reserve
IERC20(assetTo).approve(address(LENDING_POOL), receivedAmount); IERC20(assetTo).approve(address(LENDING_POOL), receivedAmount);
@ -207,6 +225,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
* uint8[] v List of v param for the permit signature * uint8[] v List of v param for the permit signature
* bytes32[] r List of r param for the permit signature * bytes32[] r List of r param for the permit signature
* bytes32[] s List of s param for the permit signature * bytes32[] s List of s param for the permit signature
* bool[] useEthPath true if the swap needs to occur using ETH in the routing, false otherwise
* @return SwapParams struct containing decoded params * @return SwapParams struct containing decoded params
*/ */
function _decodeParams(bytes memory params) internal pure returns (SwapParams memory) { function _decodeParams(bytes memory params) internal pure returns (SwapParams memory) {
@ -218,11 +237,12 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
uint256[] memory deadline, uint256[] memory deadline,
uint8[] memory v, uint8[] memory v,
bytes32[] memory r, bytes32[] memory r,
bytes32[] memory s bytes32[] memory s,
bool[] memory useEthPath
) = ) =
abi.decode( abi.decode(
params, params,
(address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[]) (address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[], bool[])
); );
return return
@ -230,7 +250,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
assetToSwapToList, assetToSwapToList,
minAmountsToReceive, minAmountsToReceive,
swapAllBalance, swapAllBalance,
PermitParams(permitAmount, deadline, v, r, s) PermitParams(permitAmount, deadline, v, r, s),
useEthPath
); );
} }
} }

View File

@ -19,6 +19,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 collateralAmount; uint256 collateralAmount;
uint256 rateMode; uint256 rateMode;
PermitSignature permitSignature; PermitSignature permitSignature;
bool useEthPath;
} }
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter) constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
@ -65,7 +66,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
decodedParams.rateMode, decodedParams.rateMode,
initiator, initiator,
premiums[0], premiums[0],
decodedParams.permitSignature decodedParams.permitSignature,
decodedParams.useEthPath
); );
return true; return true;
@ -82,6 +84,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
* @param debtRepayAmount Amount of the debt to be repaid * @param debtRepayAmount Amount of the debt to be repaid
* @param debtRateMode Rate mode of the debt to be repaid * @param debtRateMode Rate mode of the debt to be repaid
* @param permitSignature struct containing the permit signature * @param permitSignature struct containing the permit signature
* @param useEthPath struct containing the permit signature
*/ */
function swapAndRepay( function swapAndRepay(
address collateralAsset, address collateralAsset,
@ -89,7 +93,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 collateralAmount, uint256 collateralAmount,
uint256 debtRepayAmount, uint256 debtRepayAmount,
uint256 debtRateMode, uint256 debtRateMode,
PermitSignature calldata permitSignature PermitSignature calldata permitSignature,
bool useEthPath
) external { ) external {
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset); DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset); DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset);
@ -109,7 +114,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
} }
// Get exact collateral needed for the swap to avoid leftovers // Get exact collateral needed for the swap to avoid leftovers
(uint256[] memory amounts,) = _getAmountsIn(collateralAsset, debtAsset, amountToRepay); uint256[] memory amounts = _getAmountsIn(collateralAsset, debtAsset, amountToRepay, useEthPath);
require(amounts[0] <= maxCollateralToSwap, 'slippage too high'); require(amounts[0] <= maxCollateralToSwap, 'slippage too high');
// Pull aTokens from user // Pull aTokens from user
@ -159,7 +164,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 rateMode, uint256 rateMode,
address initiator, address initiator,
uint256 premium, uint256 premium,
PermitSignature memory permitSignature PermitSignature memory permitSignature,
bool useEthPath
) internal { ) internal {
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset); DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
@ -176,7 +182,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
} }
uint256 neededForFlashLoanDebt = repaidAmount.add(premium); uint256 neededForFlashLoanDebt = repaidAmount.add(premium);
(uint256[] memory amounts,) = _getAmountsIn(collateralAsset, debtAsset, neededForFlashLoanDebt); uint256[] memory amounts = _getAmountsIn(collateralAsset, debtAsset, neededForFlashLoanDebt, useEthPath);
require(amounts[0] <= maxCollateralToSwap, 'slippage too high'); require(amounts[0] <= maxCollateralToSwap, 'slippage too high');
// Pull aTokens from user // Pull aTokens from user
@ -227,15 +233,17 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 deadline, uint256 deadline,
uint8 v, uint8 v,
bytes32 r, bytes32 r,
bytes32 s bytes32 s,
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32)); bool useEthPath
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32, bool));
return return
RepayParams( RepayParams(
collateralAsset, collateralAsset,
collateralAmount, collateralAmount,
rateMode, rateMode,
PermitSignature(permitAmount, deadline, v, r, s) PermitSignature(permitAmount, deadline, v, r, s),
useEthPath
); );
} }
} }