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 assetToSwapTo,
uint256 amountToSwap,
uint256 minAmountOut
uint256 minAmountOut,
bool useEthPath
) internal returns (uint256) {
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
@ -149,9 +150,17 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
IERC20(assetToSwapFrom).approve(address(UNISWAP_ROUTER), amountToSwap);
address[] memory path = new address[](2);
path[0] = assetToSwapFrom;
path[1] = assetToSwapTo;
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;
}
uint256[] memory amounts =
UNISWAP_ROUTER.swapExactTokensForTokens(
amountToSwap,
@ -374,7 +383,7 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
uint256 amountOut
) internal view returns (AmountCalc memory) {
(uint256[] memory amounts, address[] memory path) =
_getAmountsIn(reserveIn, reserveOut, amountOut);
_getAmountsInAndPath(reserveIn, reserveOut, amountOut);
// Add flash loan fee
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
* @return uint256[] amounts Array containing the amountIn and amountOut for a swap
*/
function _getAmountsIn(
function _getAmountsInAndPath(
address reserveIn,
address reserveOut,
uint256 amountOut
@ -419,14 +428,43 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
uint256[] memory resultAmounts
) {
amounts = resultAmounts;
return (amounts, simplePath);
} catch {
pathWithWeth[0] = reserveIn;
pathWithWeth[1] = WETH_ADDRESS;
pathWithWeth[2] = reserveOut;
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;
bool[] swapAllBalance;
PermitParams permitParams;
bool[] useEthPath;
}
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
@ -71,7 +72,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
assets.length == decodedParams.permitParams.deadline.length &&
assets.length == decodedParams.permitParams.v.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'
);
@ -90,13 +92,22 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
decodedParams.permitParams.v[i],
decodedParams.permitParams.r[i],
decodedParams.permitParams.s[i]
)
),
decodedParams.useEthPath[i]
);
}
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
* 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
* bytes32 r 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(
address[] calldata assetToSwapFromList,
address[] calldata assetToSwapToList,
uint256[] calldata amountToSwapList,
uint256[] calldata minAmountsToReceive,
PermitSignature[] calldata permitParams
PermitSignature[] calldata permitParams,
bool[] calldata useEthPath
) external {
require(
assetToSwapFromList.length == assetToSwapToList.length &&
@ -129,26 +142,29 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
'INCONSISTENT_PARAMS'
);
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
address aToken = _getReserveData(assetToSwapFromList[i]).aTokenAddress;
SwapAndDepositLocalVars memory vars;
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(msg.sender);
uint256 amountToSwap =
amountToSwapList[i] > aTokenInitiatorBalance ? aTokenInitiatorBalance : amountToSwapList[i];
for (vars.i = 0; vars.i < assetToSwapFromList.length; vars.i++) {
vars.aToken = _getReserveData(assetToSwapFromList[vars.i]).aTokenAddress;
_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(
assetToSwapFromList[i],
assetToSwapToList[i],
amountToSwap,
minAmountsToReceive[i]
assetToSwapFromList[vars.i],
assetToSwapToList[vars.i],
vars.amountToSwap,
minAmountsToReceive[vars.i],
useEthPath[vars.i]
);
// Deposit new reserve
IERC20(assetToSwapToList[i]).approve(address(LENDING_POOL), receivedAmount);
LENDING_POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
IERC20(assetToSwapToList[vars.i]).approve(address(LENDING_POOL), vars.receivedAmount);
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 swapAllBalance Flag indicating if all the user balance should be swapped
* @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(
address assetFrom,
@ -170,7 +187,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
address initiator,
uint256 minAmountToReceive,
bool swapAllBalance,
PermitSignature memory permitSignature
PermitSignature memory permitSignature,
bool useEthPath
) internal {
address aToken = _getReserveData(assetFrom).aTokenAddress;
@ -181,7 +199,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
: amount;
uint256 receivedAmount =
_swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive);
_swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive, useEthPath);
// Deposit new reserve
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
* bytes32[] r List of r 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
*/
function _decodeParams(bytes memory params) internal pure returns (SwapParams memory) {
@ -218,11 +237,12 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
uint256[] memory deadline,
uint8[] memory v,
bytes32[] memory r,
bytes32[] memory s
bytes32[] memory s,
bool[] memory useEthPath
) =
abi.decode(
params,
(address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[])
(address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[], bool[])
);
return
@ -230,7 +250,8 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
assetToSwapToList,
minAmountsToReceive,
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 rateMode;
PermitSignature permitSignature;
bool useEthPath;
}
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
@ -65,7 +66,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
decodedParams.rateMode,
initiator,
premiums[0],
decodedParams.permitSignature
decodedParams.permitSignature,
decodedParams.useEthPath
);
return true;
@ -82,6 +84,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
* @param debtRepayAmount Amount of the debt to be repaid
* @param debtRateMode Rate mode of the debt to be repaid
* @param permitSignature struct containing the permit signature
* @param useEthPath struct containing the permit signature
*/
function swapAndRepay(
address collateralAsset,
@ -89,7 +93,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 collateralAmount,
uint256 debtRepayAmount,
uint256 debtRateMode,
PermitSignature calldata permitSignature
PermitSignature calldata permitSignature,
bool useEthPath
) external {
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset);
@ -109,7 +114,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
}
// 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');
// Pull aTokens from user
@ -159,7 +164,8 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 rateMode,
address initiator,
uint256 premium,
PermitSignature memory permitSignature
PermitSignature memory permitSignature,
bool useEthPath
) internal {
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
@ -176,7 +182,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
}
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');
// Pull aTokens from user
@ -227,15 +233,17 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32));
bytes32 s,
bool useEthPath
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32, bool));
return
RepayParams(
collateralAsset,
collateralAmount,
rateMode,
PermitSignature(permitAmount, deadline, v, r, s)
PermitSignature(permitAmount, deadline, v, r, s),
useEthPath
);
}
}