2020-10-27 12:17:33 +00:00
|
|
|
// SPDX-License-Identifier: agpl-3.0
|
|
|
|
pragma solidity ^0.6.8;
|
|
|
|
pragma experimental ABIEncoderV2;
|
|
|
|
|
|
|
|
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
|
|
|
|
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
|
|
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
|
|
|
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
|
|
|
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @title UniswapLiquiditySwapAdapter
|
|
|
|
* @notice Uniswap V2 Adapter to swap liquidity using a flash loan.
|
|
|
|
* @author Aave
|
|
|
|
**/
|
|
|
|
contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
|
|
|
|
2020-11-02 20:33:00 +00:00
|
|
|
struct SwapParams {
|
|
|
|
address[] assetToSwapToList;
|
|
|
|
uint256 slippage;
|
|
|
|
PermitParams permitParams;
|
|
|
|
}
|
|
|
|
|
2020-10-27 12:17:33 +00:00
|
|
|
constructor(
|
2020-10-30 19:59:25 +00:00
|
|
|
ILendingPoolAddressesProvider addressesProvider,
|
|
|
|
IUniswapV2Router02 uniswapRouter
|
2020-10-27 12:17:33 +00:00
|
|
|
)
|
|
|
|
public
|
2020-10-30 19:59:25 +00:00
|
|
|
BaseUniswapAdapter(addressesProvider, uniswapRouter)
|
2020-10-27 12:17:33 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Swaps the received reserve amount from the flashloan into the asset specified in the params.
|
|
|
|
* The received funds from the swap are then deposited into the protocol on behalf of the user.
|
|
|
|
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and
|
|
|
|
* repay the flash loan.
|
2020-10-27 14:22:16 +00:00
|
|
|
* @param assets Address to be swapped
|
|
|
|
* @param amounts Amount of the reserve to be swapped
|
|
|
|
* @param premiums Fee of the flash loan
|
2020-10-30 19:59:25 +00:00
|
|
|
* @param initiator Address of the user
|
2020-10-27 12:17:33 +00:00
|
|
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
2020-10-30 19:59:25 +00:00
|
|
|
* address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited
|
2020-10-27 12:17:33 +00:00
|
|
|
* uint256 slippage The max slippage percentage allowed for the swap
|
2020-11-02 20:33:00 +00:00
|
|
|
* uint256[] deadline List of deadlines 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[] s List of s param for the permit signature
|
2020-10-27 12:17:33 +00:00
|
|
|
*/
|
|
|
|
function executeOperation(
|
2020-10-27 14:22:16 +00:00
|
|
|
address[] calldata assets,
|
|
|
|
uint256[] calldata amounts,
|
|
|
|
uint256[] calldata premiums,
|
2020-10-30 19:59:25 +00:00
|
|
|
address initiator,
|
2020-10-27 12:17:33 +00:00
|
|
|
bytes calldata params
|
|
|
|
) external override returns (bool) {
|
2020-10-30 19:59:25 +00:00
|
|
|
require(msg.sender == address(POOL), "CALLER_MUST_BE_LENDING_POOL");
|
|
|
|
|
2020-11-02 20:33:00 +00:00
|
|
|
SwapParams memory decodedParams = _decodeParams(params);
|
|
|
|
|
|
|
|
require(
|
|
|
|
decodedParams.slippage < MAX_SLIPPAGE_PERCENT && decodedParams.slippage >= MIN_SLIPPAGE_PERCENT,
|
|
|
|
'SLIPPAGE_OUT_OF_RANGE'
|
|
|
|
);
|
|
|
|
|
|
|
|
require(
|
|
|
|
decodedParams.assetToSwapToList.length == assets.length
|
|
|
|
&& assets.length == decodedParams.permitParams.deadline.length
|
|
|
|
&& assets.length == decodedParams.permitParams.v.length
|
|
|
|
&& assets.length == decodedParams.permitParams.r.length
|
|
|
|
&& assets.length == decodedParams.permitParams.s.length,
|
|
|
|
'INCONSISTENT_PARAMS'
|
|
|
|
);
|
2020-10-27 12:17:33 +00:00
|
|
|
|
2020-10-30 19:59:25 +00:00
|
|
|
for (uint256 i = 0; i < assets.length; i++) {
|
2020-11-02 20:33:00 +00:00
|
|
|
uint256 receivedAmount = swapExactTokensForTokens(
|
|
|
|
assets[i],
|
|
|
|
decodedParams.assetToSwapToList[i],
|
|
|
|
amounts[i],
|
|
|
|
decodedParams.slippage
|
|
|
|
);
|
2020-10-27 12:17:33 +00:00
|
|
|
|
2020-10-30 19:59:25 +00:00
|
|
|
// Deposit new reserve
|
2020-11-02 20:33:00 +00:00
|
|
|
IERC20(decodedParams.assetToSwapToList[i]).approve(address(POOL), receivedAmount);
|
|
|
|
POOL.deposit(decodedParams.assetToSwapToList[i], receivedAmount, initiator, 0);
|
2020-10-27 12:17:33 +00:00
|
|
|
|
2020-10-30 19:59:25 +00:00
|
|
|
uint256 flashLoanDebt = amounts[i].add(premiums[i]);
|
2020-11-02 20:33:00 +00:00
|
|
|
pullATokenAndRepayFlashLoan(
|
|
|
|
assets[i],
|
|
|
|
initiator,
|
|
|
|
flashLoanDebt,
|
|
|
|
PermitSignature(
|
|
|
|
decodedParams.permitParams.deadline[i],
|
|
|
|
decodedParams.permitParams.v[i],
|
|
|
|
decodedParams.permitParams.r[i],
|
|
|
|
decodedParams.permitParams.s[i]
|
|
|
|
)
|
|
|
|
);
|
2020-10-30 19:59:25 +00:00
|
|
|
}
|
2020-10-27 12:17:33 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-27 19:33:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Swaps an `amountToSwap` of an asset to another and deposits the funds on behalf of the user without using a flashloan.
|
|
|
|
* This method can be used when the user has no debts.
|
|
|
|
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and
|
|
|
|
* perform the swap.
|
2020-10-30 19:59:25 +00:00
|
|
|
* @param assetToSwapFromList List of addresses of the underlying asset to be swap from
|
|
|
|
* @param assetToSwapToList List of addresses of the underlying asset to be swap to and deposited
|
|
|
|
* @param amountToSwapList List of amounts to be swapped
|
2020-10-27 19:33:07 +00:00
|
|
|
* @param slippage The max slippage percentage allowed for the swap
|
2020-11-02 20:33:00 +00:00
|
|
|
* uint256[] deadline List of deadlines 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[] s List of s param for the permit signature
|
2020-10-27 19:33:07 +00:00
|
|
|
*/
|
|
|
|
function swapAndDeposit(
|
2020-10-30 19:59:25 +00:00
|
|
|
address[] calldata assetToSwapFromList,
|
|
|
|
address[] calldata assetToSwapToList,
|
|
|
|
uint256[] calldata amountToSwapList,
|
2020-11-02 20:33:00 +00:00
|
|
|
uint256 slippage,
|
|
|
|
PermitSignature[] calldata permitParams
|
2020-10-27 19:33:07 +00:00
|
|
|
) external {
|
2020-10-30 19:59:25 +00:00
|
|
|
require(
|
2020-11-02 20:33:00 +00:00
|
|
|
assetToSwapFromList.length == assetToSwapToList.length
|
|
|
|
&& assetToSwapFromList.length == amountToSwapList.length
|
|
|
|
&& assetToSwapFromList.length == permitParams.length,
|
2020-10-30 19:59:25 +00:00
|
|
|
'INCONSISTENT_PARAMS'
|
|
|
|
);
|
|
|
|
|
|
|
|
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
|
2020-11-02 20:33:00 +00:00
|
|
|
pullAToken(
|
|
|
|
assetToSwapFromList[i],
|
|
|
|
msg.sender,
|
|
|
|
amountToSwapList[i],
|
|
|
|
permitParams[i]
|
|
|
|
);
|
2020-10-27 19:33:07 +00:00
|
|
|
|
2020-10-30 19:59:25 +00:00
|
|
|
uint256 receivedAmount = swapExactTokensForTokens(
|
|
|
|
assetToSwapFromList[i],
|
|
|
|
assetToSwapToList[i],
|
|
|
|
amountToSwapList[i],
|
|
|
|
slippage
|
|
|
|
);
|
2020-10-27 19:33:07 +00:00
|
|
|
|
2020-10-30 19:59:25 +00:00
|
|
|
// Deposit new reserve
|
|
|
|
IERC20(assetToSwapToList[i]).approve(address(POOL), receivedAmount);
|
|
|
|
POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
|
|
|
|
}
|
2020-10-27 19:33:07 +00:00
|
|
|
}
|
2020-11-02 20:33:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Decodes debt information encoded in flashloan params
|
|
|
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
|
|
|
* address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited
|
|
|
|
* uint256 slippage The max slippage percentage allowed for the swap
|
|
|
|
* uint256[] deadline List of deadlines for the permit signature
|
|
|
|
* uint256[] deadline List of deadlines 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[] s List of s param for the permit signature
|
|
|
|
* @return SwapParams struct containing decoded params
|
|
|
|
*/
|
|
|
|
function _decodeParams(bytes memory params) internal returns (SwapParams memory) {
|
|
|
|
(
|
|
|
|
address[] memory assetToSwapToList,
|
|
|
|
uint256 slippage,
|
|
|
|
uint256[] memory deadline,
|
|
|
|
uint8[] memory v,
|
|
|
|
bytes32[] memory r,
|
|
|
|
bytes32[] memory s
|
|
|
|
) = abi.decode(params, (address[], uint256, uint256[], uint8[], bytes32[], bytes32[]));
|
|
|
|
|
|
|
|
return SwapParams(assetToSwapToList, slippage, PermitParams(deadline, v, r, s));
|
|
|
|
}
|
2020-10-27 12:17:33 +00:00
|
|
|
}
|