mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
adoption to the latest
This commit is contained in:
parent
b4a0841577
commit
a21757d0fc
|
|
@ -8,70 +8,65 @@ import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||||
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
||||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
|
||||||
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
||||||
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
||||||
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
||||||
import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol';
|
import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol';
|
||||||
|
import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol';
|
||||||
|
import {IBaseUniswapAdapter} from './interfaces/IBaseUniswapAdapter.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title BaseUniswapAdapter
|
* @title BaseUniswapAdapter
|
||||||
* @notice Implements the logic for performing assets swaps in Uniswap V2
|
* @notice Implements the logic for performing assets swaps in Uniswap V2
|
||||||
* @author Aave
|
* @author Aave
|
||||||
**/
|
**/
|
||||||
contract BaseUniswapAdapter {
|
abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapter {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using PercentageMath for uint256;
|
using PercentageMath for uint256;
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
struct PermitSignature {
|
|
||||||
uint256 amount;
|
|
||||||
uint256 deadline;
|
|
||||||
uint8 v;
|
|
||||||
bytes32 r;
|
|
||||||
bytes32 s;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AmountCalc {
|
|
||||||
uint256 calculatedAmount;
|
|
||||||
uint256 relativePrice;
|
|
||||||
uint256 amountInUsd;
|
|
||||||
uint256 amountOutUsd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max slippage percent allowed
|
// Max slippage percent allowed
|
||||||
uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30%
|
uint256 public constant override MAX_SLIPPAGE_PERCENT = 3000; // 30%
|
||||||
// FLash Loan fee set in lending pool
|
// FLash Loan fee set in lending pool
|
||||||
uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9;
|
uint256 public constant override FLASHLOAN_PREMIUM_TOTAL = 9;
|
||||||
// USD oracle asset address
|
// USD oracle asset address
|
||||||
address public constant USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
|
address public constant override USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
|
||||||
|
|
||||||
ILendingPool public immutable POOL;
|
IPriceOracleGetter public immutable override ORACLE;
|
||||||
IPriceOracleGetter public immutable ORACLE;
|
IUniswapV2Router02 public immutable override UNISWAP_ROUTER;
|
||||||
IUniswapV2Router02 public immutable UNISWAP_ROUTER;
|
|
||||||
|
|
||||||
event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount);
|
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
|
||||||
|
public
|
||||||
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter) public {
|
FlashLoanReceiverBase(addressesProvider)
|
||||||
POOL = ILendingPool(addressesProvider.getLendingPool());
|
{
|
||||||
ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle());
|
ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle());
|
||||||
UNISWAP_ROUTER = uniswapRouter;
|
UNISWAP_ROUTER = uniswapRouter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices
|
* @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices
|
||||||
* @param amountIn Amount of reserveIn
|
* @param amountIn Amount of reserveIn
|
||||||
* @param reserveIn Address of the asset to be swap from
|
* @param reserveIn Address of the asset to be swap from
|
||||||
* @param reserveOut Address of the asset to be swap to
|
* @param reserveOut Address of the asset to be swap to
|
||||||
* @return uint256 Amount out of the reserveOut
|
* @return uint256 Amount out of the reserveOut
|
||||||
* @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals)
|
* @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals)
|
||||||
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
*/
|
*/
|
||||||
function getAmountsOut(uint256 amountIn, address reserveIn, address reserveOut)
|
function getAmountsOut(
|
||||||
|
uint256 amountIn,
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut
|
||||||
|
)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (uint256, uint256, uint256, uint256)
|
override
|
||||||
|
returns (
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256
|
||||||
|
)
|
||||||
{
|
{
|
||||||
AmountCalc memory results = _getAmountsOutData(reserveIn, reserveOut, amountIn);
|
AmountCalc memory results = _getAmountsOutData(reserveIn, reserveOut, amountIn);
|
||||||
|
|
||||||
|
|
@ -93,10 +88,20 @@ contract BaseUniswapAdapter {
|
||||||
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
*/
|
*/
|
||||||
function getAmountsIn(uint256 amountOut, address reserveIn, address reserveOut)
|
function getAmountsIn(
|
||||||
|
uint256 amountOut,
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut
|
||||||
|
)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (uint256, uint256, uint256, uint256)
|
override
|
||||||
|
returns (
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256
|
||||||
|
)
|
||||||
{
|
{
|
||||||
AmountCalc memory results = _getAmountsInData(reserveIn, reserveOut, amountOut);
|
AmountCalc memory results = _getAmountsInData(reserveIn, reserveOut, amountOut);
|
||||||
|
|
||||||
|
|
@ -121,20 +126,18 @@ contract BaseUniswapAdapter {
|
||||||
address assetToSwapTo,
|
address assetToSwapTo,
|
||||||
uint256 amountToSwap,
|
uint256 amountToSwap,
|
||||||
uint256 minAmountOut
|
uint256 minAmountOut
|
||||||
)
|
) internal returns (uint256) {
|
||||||
internal
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
|
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
|
||||||
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
|
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
|
||||||
|
|
||||||
uint256 fromAssetPrice = _getPrice(assetToSwapFrom);
|
uint256 fromAssetPrice = _getPrice(assetToSwapFrom);
|
||||||
uint256 toAssetPrice = _getPrice(assetToSwapTo);
|
uint256 toAssetPrice = _getPrice(assetToSwapTo);
|
||||||
|
|
||||||
uint256 expectedMinAmountOut = amountToSwap
|
uint256 expectedMinAmountOut =
|
||||||
.mul(fromAssetPrice.mul(10**toAssetDecimals))
|
amountToSwap
|
||||||
.div(toAssetPrice.mul(10**fromAssetDecimals))
|
.mul(fromAssetPrice.mul(10**toAssetDecimals))
|
||||||
.percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(MAX_SLIPPAGE_PERCENT));
|
.div(toAssetPrice.mul(10**fromAssetDecimals))
|
||||||
|
.percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(MAX_SLIPPAGE_PERCENT));
|
||||||
|
|
||||||
require(expectedMinAmountOut < minAmountOut, 'minAmountOut exceed max slippage');
|
require(expectedMinAmountOut < minAmountOut, 'minAmountOut exceed max slippage');
|
||||||
|
|
||||||
|
|
@ -143,7 +146,14 @@ contract BaseUniswapAdapter {
|
||||||
address[] memory path = new address[](2);
|
address[] memory path = new address[](2);
|
||||||
path[0] = assetToSwapFrom;
|
path[0] = assetToSwapFrom;
|
||||||
path[1] = assetToSwapTo;
|
path[1] = assetToSwapTo;
|
||||||
uint256[] memory amounts = UNISWAP_ROUTER.swapExactTokensForTokens(amountToSwap, minAmountOut, path, address(this), block.timestamp);
|
uint256[] memory amounts =
|
||||||
|
UNISWAP_ROUTER.swapExactTokensForTokens(
|
||||||
|
amountToSwap,
|
||||||
|
minAmountOut,
|
||||||
|
path,
|
||||||
|
address(this),
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[1]);
|
emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[1]);
|
||||||
|
|
||||||
|
|
@ -164,20 +174,18 @@ contract BaseUniswapAdapter {
|
||||||
address assetToSwapTo,
|
address assetToSwapTo,
|
||||||
uint256 maxAmountToSwap,
|
uint256 maxAmountToSwap,
|
||||||
uint256 amountToReceive
|
uint256 amountToReceive
|
||||||
)
|
) internal returns (uint256) {
|
||||||
internal
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
|
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
|
||||||
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
|
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
|
||||||
|
|
||||||
uint256 fromAssetPrice = _getPrice(assetToSwapFrom);
|
uint256 fromAssetPrice = _getPrice(assetToSwapFrom);
|
||||||
uint256 toAssetPrice = _getPrice(assetToSwapTo);
|
uint256 toAssetPrice = _getPrice(assetToSwapTo);
|
||||||
|
|
||||||
uint256 expectedMaxAmountToSwap = amountToReceive
|
uint256 expectedMaxAmountToSwap =
|
||||||
.mul(toAssetPrice.mul(10**fromAssetDecimals))
|
amountToReceive
|
||||||
.div(fromAssetPrice.mul(10**toAssetDecimals))
|
.mul(toAssetPrice.mul(10**fromAssetDecimals))
|
||||||
.percentMul(PercentageMath.PERCENTAGE_FACTOR.add(MAX_SLIPPAGE_PERCENT));
|
.div(fromAssetPrice.mul(10**toAssetDecimals))
|
||||||
|
.percentMul(PercentageMath.PERCENTAGE_FACTOR.add(MAX_SLIPPAGE_PERCENT));
|
||||||
|
|
||||||
require(maxAmountToSwap < expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage');
|
require(maxAmountToSwap < expectedMaxAmountToSwap, 'maxAmountToSwap exceed max slippage');
|
||||||
|
|
||||||
|
|
@ -186,7 +194,14 @@ contract BaseUniswapAdapter {
|
||||||
address[] memory path = new address[](2);
|
address[] memory path = new address[](2);
|
||||||
path[0] = assetToSwapFrom;
|
path[0] = assetToSwapFrom;
|
||||||
path[1] = assetToSwapTo;
|
path[1] = assetToSwapTo;
|
||||||
uint256[] memory amounts = UNISWAP_ROUTER.swapTokensForExactTokens(amountToReceive, maxAmountToSwap, path, address(this), block.timestamp);
|
uint256[] memory amounts =
|
||||||
|
UNISWAP_ROUTER.swapTokensForExactTokens(
|
||||||
|
amountToReceive,
|
||||||
|
maxAmountToSwap,
|
||||||
|
path,
|
||||||
|
address(this),
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[1]);
|
emit Swapped(assetToSwapFrom, assetToSwapTo, amounts[0], amounts[1]);
|
||||||
|
|
||||||
|
|
@ -215,7 +230,7 @@ contract BaseUniswapAdapter {
|
||||||
* @return address of the aToken
|
* @return address of the aToken
|
||||||
*/
|
*/
|
||||||
function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) {
|
function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) {
|
||||||
return POOL.getReserveData(asset);
|
return LENDING_POOL.getReserveData(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -249,7 +264,7 @@ contract BaseUniswapAdapter {
|
||||||
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
|
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
|
||||||
|
|
||||||
// withdraw reserve
|
// withdraw reserve
|
||||||
POOL.withdraw(reserve, amount, address(this));
|
LENDING_POOL.withdraw(reserve, amount, address(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -259,7 +274,8 @@ contract BaseUniswapAdapter {
|
||||||
* @return whether or not permit should be called
|
* @return whether or not permit should be called
|
||||||
*/
|
*/
|
||||||
function _usePermit(PermitSignature memory signature) internal pure returns (bool) {
|
function _usePermit(PermitSignature memory signature) internal pure returns (bool) {
|
||||||
return !(uint256(signature.deadline) == uint256(signature.v) && uint256(signature.deadline) == 0);
|
return
|
||||||
|
!(uint256(signature.deadline) == uint256(signature.v) && uint256(signature.deadline) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -269,15 +285,15 @@ contract BaseUniswapAdapter {
|
||||||
* @param decimals Decimals of the reserve
|
* @param decimals Decimals of the reserve
|
||||||
* @return whether or not permit should be called
|
* @return whether or not permit should be called
|
||||||
*/
|
*/
|
||||||
function _calcUsdValue(address reserve, uint256 amount, uint256 decimals) internal view returns (uint256) {
|
function _calcUsdValue(
|
||||||
|
address reserve,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 decimals
|
||||||
|
) internal view returns (uint256) {
|
||||||
uint256 ethUsdPrice = _getPrice(USD_ADDRESS);
|
uint256 ethUsdPrice = _getPrice(USD_ADDRESS);
|
||||||
uint256 reservePrice = _getPrice(reserve);
|
uint256 reservePrice = _getPrice(reserve);
|
||||||
|
|
||||||
return amount
|
return amount.mul(reservePrice).div(10**decimals).mul(ethUsdPrice).div(10**18);
|
||||||
.mul(reservePrice)
|
|
||||||
.div(10**decimals)
|
|
||||||
.mul(ethUsdPrice)
|
|
||||||
.div(10**18);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -291,7 +307,11 @@ contract BaseUniswapAdapter {
|
||||||
* uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
* uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
* uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
* uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
*/
|
*/
|
||||||
function _getAmountsOutData(address reserveIn, address reserveOut, uint256 amountIn) internal view returns (AmountCalc memory) {
|
function _getAmountsOutData(
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut,
|
||||||
|
uint256 amountIn
|
||||||
|
) internal view returns (AmountCalc memory) {
|
||||||
// Subtract flash loan fee
|
// Subtract flash loan fee
|
||||||
uint256 finalAmountIn = amountIn.sub(amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000));
|
uint256 finalAmountIn = amountIn.sub(amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000));
|
||||||
|
|
||||||
|
|
@ -304,17 +324,18 @@ contract BaseUniswapAdapter {
|
||||||
uint256 reserveInDecimals = _getDecimals(reserveIn);
|
uint256 reserveInDecimals = _getDecimals(reserveIn);
|
||||||
uint256 reserveOutDecimals = _getDecimals(reserveOut);
|
uint256 reserveOutDecimals = _getDecimals(reserveOut);
|
||||||
|
|
||||||
uint256 outPerInPrice = finalAmountIn
|
uint256 outPerInPrice =
|
||||||
.mul(10**18)
|
finalAmountIn.mul(10**18).mul(10**reserveOutDecimals).div(
|
||||||
.mul(10**reserveOutDecimals)
|
amounts[1].mul(10**reserveInDecimals)
|
||||||
.div(amounts[1].mul(10**reserveInDecimals));
|
);
|
||||||
|
|
||||||
return AmountCalc(
|
return
|
||||||
amounts[1],
|
AmountCalc(
|
||||||
outPerInPrice,
|
amounts[1],
|
||||||
_calcUsdValue(reserveIn, amountIn, reserveInDecimals),
|
outPerInPrice,
|
||||||
_calcUsdValue(reserveOut, amounts[1], reserveOutDecimals)
|
_calcUsdValue(reserveIn, amountIn, reserveInDecimals),
|
||||||
);
|
_calcUsdValue(reserveOut, amounts[1], reserveOutDecimals)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -328,7 +349,11 @@ contract BaseUniswapAdapter {
|
||||||
* uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
* uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
* uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
* uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
*/
|
*/
|
||||||
function _getAmountsInData(address reserveIn, address reserveOut, uint256 amountOut) internal view returns (AmountCalc memory) {
|
function _getAmountsInData(
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut,
|
||||||
|
uint256 amountOut
|
||||||
|
) internal view returns (AmountCalc memory) {
|
||||||
uint256[] memory amounts = _getAmountsIn(reserveIn, reserveOut, amountOut);
|
uint256[] memory amounts = _getAmountsIn(reserveIn, reserveOut, amountOut);
|
||||||
|
|
||||||
// Add flash loan fee
|
// Add flash loan fee
|
||||||
|
|
@ -337,27 +362,32 @@ contract BaseUniswapAdapter {
|
||||||
uint256 reserveInDecimals = _getDecimals(reserveIn);
|
uint256 reserveInDecimals = _getDecimals(reserveIn);
|
||||||
uint256 reserveOutDecimals = _getDecimals(reserveOut);
|
uint256 reserveOutDecimals = _getDecimals(reserveOut);
|
||||||
|
|
||||||
uint256 inPerOutPrice = amountOut
|
uint256 inPerOutPrice =
|
||||||
.mul(10**18)
|
amountOut.mul(10**18).mul(10**reserveInDecimals).div(
|
||||||
.mul(10**reserveInDecimals)
|
finalAmountIn.mul(10**reserveOutDecimals)
|
||||||
.div(finalAmountIn.mul(10**reserveOutDecimals));
|
);
|
||||||
|
|
||||||
return AmountCalc(
|
return
|
||||||
finalAmountIn,
|
AmountCalc(
|
||||||
inPerOutPrice,
|
finalAmountIn,
|
||||||
_calcUsdValue(reserveIn, finalAmountIn, reserveInDecimals),
|
inPerOutPrice,
|
||||||
_calcUsdValue(reserveOut, amountOut, reserveOutDecimals)
|
_calcUsdValue(reserveIn, finalAmountIn, reserveInDecimals),
|
||||||
);
|
_calcUsdValue(reserveOut, amountOut, reserveOutDecimals)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Calculates the input asset amount required to buy the given output asset amount
|
* @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 reserveIn Address of the asset to be swap from
|
||||||
* @param reserveOut Address of the asset to be swap to
|
* @param reserveOut Address of the asset to be swap to
|
||||||
* @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(address reserveIn, address reserveOut, uint256 amountOut) internal view returns (uint256[] memory) {
|
function _getAmountsIn(
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut,
|
||||||
|
uint256 amountOut
|
||||||
|
) internal view returns (uint256[] memory) {
|
||||||
address[] memory path = new address[](2);
|
address[] memory path = new address[](2);
|
||||||
path[0] = reserveIn;
|
path[0] = reserveIn;
|
||||||
path[1] = reserveOut;
|
path[1] = reserveOut;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ pragma experimental ABIEncoderV2;
|
||||||
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
|
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
|
||||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||||
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
||||||
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
|
|
||||||
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,8 +12,7 @@ import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
* @notice Uniswap V2 Adapter to swap liquidity.
|
* @notice Uniswap V2 Adapter to swap liquidity.
|
||||||
* @author Aave
|
* @author Aave
|
||||||
**/
|
**/
|
||||||
contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter {
|
||||||
|
|
||||||
struct PermitParams {
|
struct PermitParams {
|
||||||
uint256[] amount;
|
uint256[] amount;
|
||||||
uint256[] deadline;
|
uint256[] deadline;
|
||||||
|
|
@ -30,10 +28,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
PermitParams permitParams;
|
PermitParams permitParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
|
||||||
ILendingPoolAddressesProvider addressesProvider,
|
|
||||||
IUniswapV2Router02 uniswapRouter
|
|
||||||
)
|
|
||||||
public
|
public
|
||||||
BaseUniswapAdapter(addressesProvider, uniswapRouter)
|
BaseUniswapAdapter(addressesProvider, uniswapRouter)
|
||||||
{}
|
{}
|
||||||
|
|
@ -64,19 +59,19 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address initiator,
|
address initiator,
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external override returns (bool) {
|
) external override returns (bool) {
|
||||||
require(msg.sender == address(POOL), "CALLER_MUST_BE_LENDING_POOL");
|
require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL');
|
||||||
|
|
||||||
SwapParams memory decodedParams = _decodeParams(params);
|
SwapParams memory decodedParams = _decodeParams(params);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
assets.length == decodedParams.assetToSwapToList.length
|
assets.length == decodedParams.assetToSwapToList.length &&
|
||||||
&& assets.length == decodedParams.minAmountsToReceive.length
|
assets.length == decodedParams.minAmountsToReceive.length &&
|
||||||
&& assets.length == decodedParams.swapAllBalance.length
|
assets.length == decodedParams.swapAllBalance.length &&
|
||||||
&& assets.length == decodedParams.permitParams.amount.length
|
assets.length == decodedParams.permitParams.amount.length &&
|
||||||
&& 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,
|
||||||
'INCONSISTENT_PARAMS'
|
'INCONSISTENT_PARAMS'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -127,10 +122,10 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
PermitSignature[] calldata permitParams
|
PermitSignature[] calldata permitParams
|
||||||
) external {
|
) external {
|
||||||
require(
|
require(
|
||||||
assetToSwapFromList.length == assetToSwapToList.length
|
assetToSwapFromList.length == assetToSwapToList.length &&
|
||||||
&& assetToSwapFromList.length == amountToSwapList.length
|
assetToSwapFromList.length == amountToSwapList.length &&
|
||||||
&& assetToSwapFromList.length == minAmountsToReceive.length
|
assetToSwapFromList.length == minAmountsToReceive.length &&
|
||||||
&& assetToSwapFromList.length == permitParams.length,
|
assetToSwapFromList.length == permitParams.length,
|
||||||
'INCONSISTENT_PARAMS'
|
'INCONSISTENT_PARAMS'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -138,26 +133,22 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address aToken = _getReserveData(assetToSwapFromList[i]).aTokenAddress;
|
address aToken = _getReserveData(assetToSwapFromList[i]).aTokenAddress;
|
||||||
|
|
||||||
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(msg.sender);
|
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(msg.sender);
|
||||||
uint256 amountToSwap = amountToSwapList[i] > aTokenInitiatorBalance ? aTokenInitiatorBalance : amountToSwapList[i];
|
uint256 amountToSwap =
|
||||||
|
amountToSwapList[i] > aTokenInitiatorBalance ? aTokenInitiatorBalance : amountToSwapList[i];
|
||||||
|
|
||||||
_pullAToken(
|
_pullAToken(assetToSwapFromList[i], aToken, msg.sender, amountToSwap, permitParams[i]);
|
||||||
assetToSwapFromList[i],
|
|
||||||
aToken,
|
|
||||||
msg.sender,
|
|
||||||
amountToSwap,
|
|
||||||
permitParams[i]
|
|
||||||
);
|
|
||||||
|
|
||||||
uint256 receivedAmount = _swapExactTokensForTokens(
|
uint256 receivedAmount =
|
||||||
assetToSwapFromList[i],
|
_swapExactTokensForTokens(
|
||||||
assetToSwapToList[i],
|
assetToSwapFromList[i],
|
||||||
amountToSwap,
|
assetToSwapToList[i],
|
||||||
minAmountsToReceive[i]
|
amountToSwap,
|
||||||
);
|
minAmountsToReceive[i]
|
||||||
|
);
|
||||||
|
|
||||||
// Deposit new reserve
|
// Deposit new reserve
|
||||||
IERC20(assetToSwapToList[i]).approve(address(POOL), receivedAmount);
|
IERC20(assetToSwapToList[i]).approve(address(LENDING_POOL), receivedAmount);
|
||||||
POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
|
LENDING_POOL.deposit(assetToSwapToList[i], receivedAmount, msg.sender, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,20 +175,17 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address aToken = _getReserveData(assetFrom).aTokenAddress;
|
address aToken = _getReserveData(assetFrom).aTokenAddress;
|
||||||
|
|
||||||
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(initiator);
|
uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(initiator);
|
||||||
uint256 amountToSwap = swapAllBalance && aTokenInitiatorBalance.sub(premium) <= amount
|
uint256 amountToSwap =
|
||||||
? aTokenInitiatorBalance.sub(premium)
|
swapAllBalance && aTokenInitiatorBalance.sub(premium) <= amount
|
||||||
: amount;
|
? aTokenInitiatorBalance.sub(premium)
|
||||||
|
: amount;
|
||||||
|
|
||||||
uint256 receivedAmount = _swapExactTokensForTokens(
|
uint256 receivedAmount =
|
||||||
assetFrom,
|
_swapExactTokensForTokens(assetFrom, assetTo, amountToSwap, minAmountToReceive);
|
||||||
assetTo,
|
|
||||||
amountToSwap,
|
|
||||||
minAmountToReceive
|
|
||||||
);
|
|
||||||
|
|
||||||
// Deposit new reserve
|
// Deposit new reserve
|
||||||
IERC20(assetTo).approve(address(POOL), receivedAmount);
|
IERC20(assetTo).approve(address(LENDING_POOL), receivedAmount);
|
||||||
POOL.deposit(assetTo, receivedAmount, initiator, 0);
|
LENDING_POOL.deposit(assetTo, receivedAmount, initiator, 0);
|
||||||
|
|
||||||
uint256 flashLoanDebt = amount.add(premium);
|
uint256 flashLoanDebt = amount.add(premium);
|
||||||
uint256 amountToPull = amountToSwap.add(premium);
|
uint256 amountToPull = amountToSwap.add(premium);
|
||||||
|
|
@ -205,7 +193,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
_pullAToken(assetFrom, aToken, initiator, amountToPull, permitSignature);
|
_pullAToken(assetFrom, aToken, initiator, amountToPull, permitSignature);
|
||||||
|
|
||||||
// Repay flash loan
|
// Repay flash loan
|
||||||
IERC20(assetFrom).approve(address(POOL), flashLoanDebt);
|
IERC20(assetFrom).approve(address(LENDING_POOL), flashLoanDebt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -231,19 +219,18 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
uint8[] memory v,
|
uint8[] memory v,
|
||||||
bytes32[] memory r,
|
bytes32[] memory r,
|
||||||
bytes32[] memory s
|
bytes32[] memory s
|
||||||
) = abi.decode(params, (address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[]));
|
) =
|
||||||
|
abi.decode(
|
||||||
|
params,
|
||||||
|
(address[], uint256[], bool[], uint256[], uint256[], uint8[], bytes32[], bytes32[])
|
||||||
|
);
|
||||||
|
|
||||||
return SwapParams(
|
return
|
||||||
assetToSwapToList,
|
SwapParams(
|
||||||
minAmountsToReceive,
|
assetToSwapToList,
|
||||||
swapAllBalance,
|
minAmountsToReceive,
|
||||||
PermitParams(
|
swapAllBalance,
|
||||||
permitAmount,
|
PermitParams(permitAmount, deadline, v, r, s)
|
||||||
deadline,
|
);
|
||||||
v,
|
|
||||||
r,
|
|
||||||
s
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ pragma experimental ABIEncoderV2;
|
||||||
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
|
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
|
||||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||||
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
||||||
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
|
|
||||||
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
||||||
|
|
||||||
|
|
@ -14,8 +13,7 @@ import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
||||||
* @notice Uniswap V2 Adapter to perform a repay of a debt with collateral.
|
* @notice Uniswap V2 Adapter to perform a repay of a debt with collateral.
|
||||||
* @author Aave
|
* @author Aave
|
||||||
**/
|
**/
|
||||||
contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
contract UniswapRepayAdapter is BaseUniswapAdapter {
|
||||||
|
|
||||||
struct RepayParams {
|
struct RepayParams {
|
||||||
address collateralAsset;
|
address collateralAsset;
|
||||||
uint256 collateralAmount;
|
uint256 collateralAmount;
|
||||||
|
|
@ -23,10 +21,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
PermitSignature permitSignature;
|
PermitSignature permitSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(ILendingPoolAddressesProvider addressesProvider, IUniswapV2Router02 uniswapRouter)
|
||||||
ILendingPoolAddressesProvider addressesProvider,
|
|
||||||
IUniswapV2Router02 uniswapRouter
|
|
||||||
)
|
|
||||||
public
|
public
|
||||||
BaseUniswapAdapter(addressesProvider, uniswapRouter)
|
BaseUniswapAdapter(addressesProvider, uniswapRouter)
|
||||||
{}
|
{}
|
||||||
|
|
@ -58,20 +53,20 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address initiator,
|
address initiator,
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external override returns (bool) {
|
) external override returns (bool) {
|
||||||
require(msg.sender == address(POOL), "CALLER_MUST_BE_LENDING_POOL");
|
require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL');
|
||||||
|
|
||||||
RepayParams memory decodedParams = _decodeParams(params);
|
RepayParams memory decodedParams = _decodeParams(params);
|
||||||
|
|
||||||
_swapAndRepay(
|
_swapAndRepay(
|
||||||
decodedParams.collateralAsset,
|
decodedParams.collateralAsset,
|
||||||
assets[0],
|
assets[0],
|
||||||
amounts[0],
|
amounts[0],
|
||||||
decodedParams.collateralAmount,
|
decodedParams.collateralAmount,
|
||||||
decodedParams.rateMode,
|
decodedParams.rateMode,
|
||||||
initiator,
|
initiator,
|
||||||
premiums[0],
|
premiums[0],
|
||||||
decodedParams.permitSignature
|
decodedParams.permitSignature
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -99,9 +94,10 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
|
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
|
||||||
DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset);
|
DataTypes.ReserveData memory debtReserveData = _getReserveData(debtAsset);
|
||||||
|
|
||||||
address debtToken = DataTypes.InterestRateMode(debtRateMode) == DataTypes.InterestRateMode.STABLE
|
address debtToken =
|
||||||
? debtReserveData.stableDebtTokenAddress
|
DataTypes.InterestRateMode(debtRateMode) == DataTypes.InterestRateMode.STABLE
|
||||||
: debtReserveData.variableDebtTokenAddress;
|
? debtReserveData.stableDebtTokenAddress
|
||||||
|
: debtReserveData.variableDebtTokenAddress;
|
||||||
|
|
||||||
uint256 currentDebt = IERC20(debtToken).balanceOf(msg.sender);
|
uint256 currentDebt = IERC20(debtToken).balanceOf(msg.sender);
|
||||||
uint256 amountToRepay = debtRepayAmount <= currentDebt ? debtRepayAmount : currentDebt;
|
uint256 amountToRepay = debtRepayAmount <= currentDebt ? debtRepayAmount : currentDebt;
|
||||||
|
|
@ -117,21 +113,32 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
require(amounts[0] <= maxCollateralToSwap, 'slippage too high');
|
require(amounts[0] <= maxCollateralToSwap, 'slippage too high');
|
||||||
|
|
||||||
// Pull aTokens from user
|
// Pull aTokens from user
|
||||||
_pullAToken(collateralAsset, collateralReserveData.aTokenAddress, msg.sender, amounts[0], permitSignature);
|
_pullAToken(
|
||||||
|
collateralAsset,
|
||||||
|
collateralReserveData.aTokenAddress,
|
||||||
|
msg.sender,
|
||||||
|
amounts[0],
|
||||||
|
permitSignature
|
||||||
|
);
|
||||||
|
|
||||||
// Swap collateral for debt asset
|
// Swap collateral for debt asset
|
||||||
_swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], amountToRepay);
|
_swapTokensForExactTokens(collateralAsset, debtAsset, amounts[0], amountToRepay);
|
||||||
} else {
|
} else {
|
||||||
// Pull aTokens from user
|
// Pull aTokens from user
|
||||||
_pullAToken(collateralAsset, collateralReserveData.aTokenAddress, msg.sender, amountToRepay, permitSignature);
|
_pullAToken(
|
||||||
|
collateralAsset,
|
||||||
|
collateralReserveData.aTokenAddress,
|
||||||
|
msg.sender,
|
||||||
|
amountToRepay,
|
||||||
|
permitSignature
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repay debt
|
// Repay debt
|
||||||
IERC20(debtAsset).approve(address(POOL), amountToRepay);
|
IERC20(debtAsset).approve(address(LENDING_POOL), amountToRepay);
|
||||||
POOL.repay(debtAsset, amountToRepay, debtRateMode, msg.sender);
|
LENDING_POOL.repay(debtAsset, amountToRepay, debtRateMode, msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Perform the repay of the debt, pulls the initiator collateral and swaps to repay the flash loan
|
* @dev Perform the repay of the debt, pulls the initiator collateral and swaps to repay the flash loan
|
||||||
*
|
*
|
||||||
|
|
@ -157,9 +164,9 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
|
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
|
||||||
|
|
||||||
// Repay debt
|
// Repay debt
|
||||||
IERC20(debtAsset).approve(address(POOL), amount);
|
IERC20(debtAsset).approve(address(LENDING_POOL), amount);
|
||||||
uint256 repaidAmount = IERC20(debtAsset).balanceOf(address(this));
|
uint256 repaidAmount = IERC20(debtAsset).balanceOf(address(this));
|
||||||
POOL.repay(debtAsset, amount, rateMode, initiator);
|
LENDING_POOL.repay(debtAsset, amount, rateMode, initiator);
|
||||||
repaidAmount = repaidAmount.sub(IERC20(debtAsset).balanceOf(address(this)));
|
repaidAmount = repaidAmount.sub(IERC20(debtAsset).balanceOf(address(this)));
|
||||||
|
|
||||||
if (collateralAsset != debtAsset) {
|
if (collateralAsset != debtAsset) {
|
||||||
|
|
@ -195,7 +202,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repay flash loan
|
// Repay flash loan
|
||||||
IERC20(debtAsset).approve(address(POOL), amount.add(premium));
|
IERC20(debtAsset).approve(address(LENDING_POOL), amount.add(premium));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -223,17 +230,12 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
bytes32 s
|
bytes32 s
|
||||||
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32));
|
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32));
|
||||||
|
|
||||||
return RepayParams(
|
return
|
||||||
collateralAsset,
|
RepayParams(
|
||||||
collateralAmount,
|
collateralAsset,
|
||||||
rateMode,
|
collateralAmount,
|
||||||
PermitSignature(
|
rateMode,
|
||||||
permitAmount,
|
PermitSignature(permitAmount, deadline, v, r, s)
|
||||||
deadline,
|
);
|
||||||
v,
|
|
||||||
r,
|
|
||||||
s
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
83
contracts/adapters/interfaces/IBaseUniswapAdapter.sol
Normal file
83
contracts/adapters/interfaces/IBaseUniswapAdapter.sol
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
// SPDX-License-Identifier: agpl-3.0
|
||||||
|
pragma solidity 0.6.12;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
|
||||||
|
import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol';
|
||||||
|
|
||||||
|
interface IBaseUniswapAdapter {
|
||||||
|
event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount);
|
||||||
|
|
||||||
|
struct PermitSignature {
|
||||||
|
uint256 amount;
|
||||||
|
uint256 deadline;
|
||||||
|
uint8 v;
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 s;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AmountCalc {
|
||||||
|
uint256 calculatedAmount;
|
||||||
|
uint256 relativePrice;
|
||||||
|
uint256 amountInUsd;
|
||||||
|
uint256 amountOutUsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MAX_SLIPPAGE_PERCENT() external returns (uint256);
|
||||||
|
|
||||||
|
function FLASHLOAN_PREMIUM_TOTAL() external returns (uint256);
|
||||||
|
|
||||||
|
function USD_ADDRESS() external returns (address);
|
||||||
|
|
||||||
|
function ORACLE() external returns (IPriceOracleGetter);
|
||||||
|
|
||||||
|
function UNISWAP_ROUTER() external returns (IUniswapV2Router02);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices
|
||||||
|
* @param amountIn Amount of reserveIn
|
||||||
|
* @param reserveIn Address of the asset to be swap from
|
||||||
|
* @param reserveOut Address of the asset to be swap to
|
||||||
|
* @return uint256 Amount out of the reserveOut
|
||||||
|
* @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals)
|
||||||
|
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
|
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
|
*/
|
||||||
|
function getAmountsOut(
|
||||||
|
uint256 amountIn,
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices
|
||||||
|
* @param amountOut Amount of reserveOut
|
||||||
|
* @param reserveIn Address of the asset to be swap from
|
||||||
|
* @param reserveOut Address of the asset to be swap to
|
||||||
|
* @return uint256 Amount in of the reserveIn
|
||||||
|
* @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals)
|
||||||
|
* @return uint256 In amount of reserveIn value denominated in USD (8 decimals)
|
||||||
|
* @return uint256 Out amount of reserveOut value denominated in USD (8 decimals)
|
||||||
|
*/
|
||||||
|
function getAmountsIn(
|
||||||
|
uint256 amountOut,
|
||||||
|
address reserveIn,
|
||||||
|
address reserveOut
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256,
|
||||||
|
uint256
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {HardhatUserConfig} from 'hardhat/types';
|
import { HardhatUserConfig } from 'hardhat/types';
|
||||||
|
|
||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {accounts} from './test-wallets.js';
|
import { accounts } from './test-wallets.js';
|
||||||
import {eEthereumNetwork} from './helpers/types';
|
import { eEthereumNetwork } from './helpers/types';
|
||||||
import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants';
|
import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants';
|
||||||
|
|
||||||
import '@nomiclabs/hardhat-ethers';
|
import '@nomiclabs/hardhat-ethers';
|
||||||
import '@nomiclabs/hardhat-waffle';
|
import '@nomiclabs/hardhat-waffle';
|
||||||
|
|
@ -27,7 +30,7 @@ const MAINNET_FORK = process.env.MAINNET_FORK === 'true';
|
||||||
|
|
||||||
// Prevent to load scripts before compilation and typechain
|
// Prevent to load scripts before compilation and typechain
|
||||||
if (!SKIP_LOAD) {
|
if (!SKIP_LOAD) {
|
||||||
['misc', 'migrations', 'dev', 'full', 'verifications'].forEach((folder) => {
|
['misc', 'migrations', 'dev', 'full', 'verifications', 'deployments'].forEach((folder) => {
|
||||||
const tasksPath = path.join(__dirname, 'tasks', folder);
|
const tasksPath = path.join(__dirname, 'tasks', folder);
|
||||||
fs.readdirSync(tasksPath)
|
fs.readdirSync(tasksPath)
|
||||||
.filter((pth) => pth.includes('.ts'))
|
.filter((pth) => pth.includes('.ts'))
|
||||||
|
|
@ -73,7 +76,7 @@ const buidlerConfig: HardhatUserConfig = {
|
||||||
solidity: {
|
solidity: {
|
||||||
version: '0.6.12',
|
version: '0.6.12',
|
||||||
settings: {
|
settings: {
|
||||||
optimizer: {enabled: true, runs: 200},
|
optimizer: { enabled: true, runs: 200 },
|
||||||
evmVersion: 'istanbul',
|
evmVersion: 'istanbul',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -109,7 +112,7 @@ const buidlerConfig: HardhatUserConfig = {
|
||||||
chainId: BUIDLEREVM_CHAINID,
|
chainId: BUIDLEREVM_CHAINID,
|
||||||
throwOnTransactionFailures: true,
|
throwOnTransactionFailures: true,
|
||||||
throwOnCallFailures: true,
|
throwOnCallFailures: true,
|
||||||
accounts: accounts.map(({secretKey, balance}: {secretKey: string; balance: string}) => ({
|
accounts: accounts.map(({ secretKey, balance }: { secretKey: string; balance: string }) => ({
|
||||||
privateKey: secretKey,
|
privateKey: secretKey,
|
||||||
balance,
|
balance,
|
||||||
})),
|
})),
|
||||||
|
|
|
||||||
62
package-lock.json
generated
62
package-lock.json
generated
|
|
@ -9504,14 +9504,6 @@
|
||||||
"prr": "~1.0.1",
|
"prr": "~1.0.1",
|
||||||
"semver": "~5.4.1",
|
"semver": "~5.4.1",
|
||||||
"xtend": "~4.0.0"
|
"xtend": "~4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
|
||||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"merkle-patricia-tree": {
|
"merkle-patricia-tree": {
|
||||||
|
|
@ -9901,14 +9893,6 @@
|
||||||
"prr": "~1.0.1",
|
"prr": "~1.0.1",
|
||||||
"semver": "~5.4.1",
|
"semver": "~5.4.1",
|
||||||
"xtend": "~4.0.0"
|
"xtend": "~4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
|
||||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"merkle-patricia-tree": {
|
"merkle-patricia-tree": {
|
||||||
|
|
@ -10200,14 +10184,6 @@
|
||||||
"prr": "~1.0.1",
|
"prr": "~1.0.1",
|
||||||
"semver": "~5.4.1",
|
"semver": "~5.4.1",
|
||||||
"xtend": "~4.0.0"
|
"xtend": "~4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
|
||||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"merkle-patricia-tree": {
|
"merkle-patricia-tree": {
|
||||||
|
|
@ -10459,14 +10435,6 @@
|
||||||
"prr": "~1.0.1",
|
"prr": "~1.0.1",
|
||||||
"semver": "~5.4.1",
|
"semver": "~5.4.1",
|
||||||
"xtend": "~4.0.0"
|
"xtend": "~4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
|
||||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"merkle-patricia-tree": {
|
"merkle-patricia-tree": {
|
||||||
|
|
@ -12428,6 +12396,17 @@
|
||||||
"safe-buffer": "~5.1.1",
|
"safe-buffer": "~5.1.1",
|
||||||
"string_decoder": "~1.1.1",
|
"string_decoder": "~1.1.1",
|
||||||
"util-deprecate": "~1.0.1"
|
"util-deprecate": "~1.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
|
|
@ -12436,6 +12415,11 @@
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|
@ -14250,6 +14234,12 @@
|
||||||
"integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==",
|
"integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"semver-greatest-satisfied-range": {
|
"semver-greatest-satisfied-range": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz",
|
||||||
|
|
@ -16306,14 +16296,6 @@
|
||||||
"prr": "~1.0.1",
|
"prr": "~1.0.1",
|
||||||
"semver": "~5.4.1",
|
"semver": "~5.4.1",
|
||||||
"xtend": "~4.0.0"
|
"xtend": "~4.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"semver": {
|
|
||||||
"version": "5.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
|
||||||
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"merkle-patricia-tree": {
|
"merkle-patricia-tree": {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
"print-contracts:main": "npm run hardhat:main -- print-contracts",
|
"print-contracts:main": "npm run hardhat:main -- print-contracts",
|
||||||
"print-contracts:ropsten": "npm run hardhat:main -- print-contracts",
|
"print-contracts:ropsten": "npm run hardhat:main -- print-contracts",
|
||||||
"dev:deployUIProvider": "npm run hardhat:kovan deploy-UiPoolDataProvider",
|
"dev:deployUIProvider": "npm run hardhat:kovan deploy-UiPoolDataProvider",
|
||||||
|
"dev:deployUniswapRepayAdapter": "npm run hardhat:kovan deploy-UniswapRepayAdapter",
|
||||||
"kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Aave",
|
"kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Aave",
|
||||||
"ropsten:verify": "npm run hardhat:ropsten verify:general -- --all --pool Aave",
|
"ropsten:verify": "npm run hardhat:ropsten verify:general -- --all --pool Aave",
|
||||||
"mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave",
|
"mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave",
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import {task} from '@nomiclabs/buidler/config';
|
import { task } from 'hardhat/config';
|
||||||
|
|
||||||
import {UiPoolDataProviderFactory} from '../../types';
|
import { UiPoolDataProviderFactory } from '../../types';
|
||||||
import {verifyContract} from '../../helpers/etherscan-verification';
|
import { verifyContract } from '../../helpers/etherscan-verification';
|
||||||
import {eContractid} from '../../helpers/types';
|
import { eContractid } from '../../helpers/types';
|
||||||
|
|
||||||
task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`)
|
task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`)
|
||||||
.addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.')
|
.addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.')
|
||||||
.setAction(async ({verify}, localBRE) => {
|
.setAction(async ({ verify }, localBRE) => {
|
||||||
await localBRE.run('set-bre');
|
await localBRE.run('set-DRE');
|
||||||
|
|
||||||
if (!localBRE.network.config.chainId) {
|
if (!localBRE.network.config.chainId) {
|
||||||
throw new Error('INVALID_CHAIN_ID');
|
throw new Error('INVALID_CHAIN_ID');
|
||||||
|
|
@ -21,7 +21,7 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider
|
||||||
).deploy();
|
).deploy();
|
||||||
await uiPoolDataProvider.deployTransaction.wait();
|
await uiPoolDataProvider.deployTransaction.wait();
|
||||||
console.log('uiPoolDataProvider.address', uiPoolDataProvider.address);
|
console.log('uiPoolDataProvider.address', uiPoolDataProvider.address);
|
||||||
await verifyContract(eContractid.UiPoolDataProvider, uiPoolDataProvider.address, []);
|
await verifyContract(uiPoolDataProvider.address, []);
|
||||||
|
|
||||||
console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`);
|
console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
30
tasks/deployments/deploy-UniswapRepayAdapter.ts
Normal file
30
tasks/deployments/deploy-UniswapRepayAdapter.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { task } from 'hardhat/config';
|
||||||
|
|
||||||
|
import { UniswapRepayAdapterFactory } from '../../types';
|
||||||
|
import { verifyContract } from '../../helpers/etherscan-verification';
|
||||||
|
|
||||||
|
const CONTRACT_NAME = 'UniswapRepayAdapter';
|
||||||
|
|
||||||
|
task(`deploy-${CONTRACT_NAME}`, `Deploys the UniswapRepayAdapter contract`)
|
||||||
|
.addFlag('verify', 'Verify UniswapRepayAdapter contract via Etherscan API.')
|
||||||
|
.setAction(async ({ verify }, localBRE) => {
|
||||||
|
await localBRE.run('set-DRE');
|
||||||
|
|
||||||
|
if (!localBRE.network.config.chainId) {
|
||||||
|
throw new Error('INVALID_CHAIN_ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n- UniswapRepayAdapter deployment`);
|
||||||
|
const args = [
|
||||||
|
'0x9fe532197ad76c5a68961439604c037eb79681f0',
|
||||||
|
'0xfcd87315f0e4067070ade8682fcdbc3006631441',
|
||||||
|
];
|
||||||
|
const uniswapRepayAdapter = await new UniswapRepayAdapterFactory(
|
||||||
|
await localBRE.ethers.provider.getSigner()
|
||||||
|
).deploy(args[0], args[1]);
|
||||||
|
await uniswapRepayAdapter.deployTransaction.wait();
|
||||||
|
console.log('uniswapRepayAdapter.address', uniswapRepayAdapter.address);
|
||||||
|
await verifyContract(uniswapRepayAdapter.address, args);
|
||||||
|
|
||||||
|
console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user