mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Update getAmountsOut to return prices
This commit is contained in:
parent
847ad3b12a
commit
5d9cd6ebd1
|
@ -42,6 +42,10 @@ contract BaseUniswapAdapter {
|
|||
|
||||
// Max slippage percent allowed
|
||||
uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30%
|
||||
// FLash Loan fee set in lending pool
|
||||
uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9;
|
||||
// USD oracle asset address
|
||||
address public constant USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
|
||||
|
||||
ILendingPool public immutable POOL;
|
||||
IPriceOracleGetter public immutable ORACLE;
|
||||
|
@ -56,24 +60,39 @@ contract BaseUniswapAdapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev Given an input asset amount, returns the maximum output amount of the other asset
|
||||
* @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 amountOut
|
||||
* @return uint256 Amount out fo 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 getAmountOut(uint256 amountIn, address reserveIn, address reserveOut)
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
function getAmountsOut(uint256 amountIn, address reserveIn, address reserveOut)
|
||||
external
|
||||
view
|
||||
returns (uint256, uint256, uint256, uint256)
|
||||
{
|
||||
address[] memory path = new address[](2);
|
||||
path[0] = reserveIn;
|
||||
path[1] = reserveOut;
|
||||
// Subtract flash loan fee
|
||||
uint256 finalAmountIn = amountIn.sub(amountIn.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000));
|
||||
|
||||
uint256[] memory amounts = UNISWAP_ROUTER.getAmountsOut(amountIn, path);
|
||||
uint256 amountOut = _getAmountsOut(reserveIn, reserveOut, finalAmountIn);
|
||||
|
||||
return amounts[1];
|
||||
uint256 reserveInDecimals = _getDecimals(reserveIn);
|
||||
uint256 reserveOutDecimals = _getDecimals(reserveOut);
|
||||
|
||||
uint256 outPerInPrice = finalAmountIn
|
||||
.mul(10**18)
|
||||
.mul(10**reserveOutDecimals)
|
||||
.div(amountOut.mul(10**reserveInDecimals));
|
||||
|
||||
return (
|
||||
amountOut,
|
||||
outPerInPrice,
|
||||
_calcUsdValue(reserveIn, amountIn, reserveInDecimals),
|
||||
_calcUsdValue(reserveOut, amountOut, reserveOutDecimals)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,9 +103,9 @@ contract BaseUniswapAdapter {
|
|||
* @return uint256 amountIn
|
||||
*/
|
||||
function getAmountIn(uint256 amountOut, address reserveIn, address reserveOut)
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
address[] memory path = new address[](2);
|
||||
path[0] = reserveIn;
|
||||
|
@ -294,4 +313,39 @@ contract BaseUniswapAdapter {
|
|||
return !(uint256(signature.deadline) == uint256(signature.v) &&
|
||||
uint256(signature.deadline) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the value denominated in USD
|
||||
* @param reserve Address of the reserve
|
||||
* @param amount Amount of the reserve
|
||||
* @param decimals Decimals of the reserve
|
||||
* @return whether or not permit should be called
|
||||
*/
|
||||
function _calcUsdValue(address reserve, uint256 amount, uint256 decimals) internal view returns (uint256) {
|
||||
uint256 ethUsdPrice = _getPrice(USD_ADDRESS);
|
||||
uint256 reservePrice = _getPrice(reserve);
|
||||
|
||||
return amount
|
||||
.mul(reservePrice)
|
||||
.div(10**decimals)
|
||||
.mul(ethUsdPrice)
|
||||
.div(10**18);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Given an input asset amount, returns the maximum output amount of the other asset
|
||||
* @param reserveIn Address of the asset to be swap from
|
||||
* @param reserveOut Address of the asset to be swap to
|
||||
* @param amountIn Amount of reserveIn
|
||||
* @return the output amount
|
||||
*/
|
||||
function _getAmountsOut(address reserveIn, address reserveOut, uint256 amountIn) internal view returns (uint256) {
|
||||
address[] memory path = new address[](2);
|
||||
path[0] = reserveIn;
|
||||
path[1] = reserveOut;
|
||||
|
||||
uint256[] memory amounts = UNISWAP_ROUTER.getAmountsOut(amountIn, path);
|
||||
|
||||
return amounts[1];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import {eContractid} from '../helpers/types';
|
|||
import {AToken} from '../types/AToken';
|
||||
import {StableDebtToken} from '../types/StableDebtToken';
|
||||
import {BUIDLEREVM_CHAINID} from '../helpers/buidler-constants';
|
||||
import {MAX_UINT_AMOUNT} from '../helpers/constants';
|
||||
import {MAX_UINT_AMOUNT, USD_ADDRESS} from '../helpers/constants';
|
||||
const {parseEther} = ethers.utils;
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
@ -41,17 +41,106 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
|||
});
|
||||
|
||||
describe('BaseUniswapAdapter', () => {
|
||||
describe('getAmountOut', () => {
|
||||
it('should return the estimated amountOut for the asset swap', async () => {
|
||||
const {weth, dai, uniswapLiquiditySwapAdapter} = testEnv;
|
||||
describe('getAmountsOut', () => {
|
||||
it('should return the estimated amountOut and prices for the asset swap', async () => {
|
||||
const {weth, dai, uniswapLiquiditySwapAdapter, oracle} = testEnv;
|
||||
|
||||
const amountIn = parseEther('1');
|
||||
const amountOut = parseEther('2');
|
||||
const flashloanPremium = amountIn.mul(9).div(10000);
|
||||
const amountToSwap = amountIn.sub(flashloanPremium);
|
||||
|
||||
await mockUniswapRouter.setAmountOut(amountIn, weth.address, dai.address, amountOut);
|
||||
const wethPrice = await oracle.getAssetPrice(weth.address);
|
||||
const daiPrice = await oracle.getAssetPrice(dai.address);
|
||||
const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
|
||||
|
||||
expect(
|
||||
await uniswapLiquiditySwapAdapter.getAmountOut(amountIn, weth.address, dai.address)
|
||||
).to.be.eq(amountOut);
|
||||
const expectedDaiAmount = await convertToCurrencyDecimals(
|
||||
dai.address,
|
||||
new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
||||
);
|
||||
|
||||
const outPerInPrice = amountToSwap
|
||||
.mul(parseEther('1'))
|
||||
.mul(parseEther('1'))
|
||||
.div(expectedDaiAmount.mul(parseEther('1')));
|
||||
const ethUsdValue = amountIn
|
||||
.mul(wethPrice)
|
||||
.div(parseEther('1'))
|
||||
.mul(usdPrice)
|
||||
.div(parseEther('1'));
|
||||
const daiUsdValue = expectedDaiAmount
|
||||
.mul(daiPrice)
|
||||
.div(parseEther('1'))
|
||||
.mul(usdPrice)
|
||||
.div(parseEther('1'));
|
||||
|
||||
await mockUniswapRouter.setAmountOut(
|
||||
amountToSwap,
|
||||
weth.address,
|
||||
dai.address,
|
||||
expectedDaiAmount
|
||||
);
|
||||
|
||||
const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
|
||||
amountIn,
|
||||
weth.address,
|
||||
dai.address
|
||||
);
|
||||
|
||||
expect(result['0']).to.be.eq(expectedDaiAmount);
|
||||
expect(result['1']).to.be.eq(outPerInPrice);
|
||||
expect(result['2']).to.be.eq(ethUsdValue);
|
||||
expect(result['3']).to.be.eq(daiUsdValue);
|
||||
});
|
||||
it('should work correctly with different decimals', async () => {
|
||||
const {lend, usdc, uniswapLiquiditySwapAdapter, oracle} = testEnv;
|
||||
|
||||
const amountIn = parseEther('10');
|
||||
const flashloanPremium = amountIn.mul(9).div(10000);
|
||||
const amountToSwap = amountIn.sub(flashloanPremium);
|
||||
|
||||
const lendPrice = await oracle.getAssetPrice(lend.address);
|
||||
const usdcPrice = await oracle.getAssetPrice(usdc.address);
|
||||
const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
|
||||
|
||||
const expectedUSDCAmount = await convertToCurrencyDecimals(
|
||||
usdc.address,
|
||||
new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0)
|
||||
);
|
||||
|
||||
const outPerInPrice = amountToSwap
|
||||
.mul(parseEther('1'))
|
||||
.mul('1000000')
|
||||
.div(expectedUSDCAmount.mul(parseEther('1')));
|
||||
|
||||
const lendUsdValue = amountIn
|
||||
.mul(lendPrice)
|
||||
.div(parseEther('1'))
|
||||
.mul(usdPrice)
|
||||
.div(parseEther('1'));
|
||||
|
||||
const usdcUsdValue = expectedUSDCAmount
|
||||
.mul(usdcPrice)
|
||||
.div('1000000')
|
||||
.mul(usdPrice)
|
||||
.div(parseEther('1'));
|
||||
|
||||
await mockUniswapRouter.setAmountOut(
|
||||
amountToSwap,
|
||||
lend.address,
|
||||
usdc.address,
|
||||
expectedUSDCAmount
|
||||
);
|
||||
|
||||
const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
|
||||
amountIn,
|
||||
lend.address,
|
||||
usdc.address
|
||||
);
|
||||
|
||||
expect(result['0']).to.be.eq(expectedUSDCAmount);
|
||||
expect(result['1']).to.be.eq(outPerInPrice);
|
||||
expect(result['2']).to.be.eq(lendUsdValue);
|
||||
expect(result['3']).to.be.eq(usdcUsdValue);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user