Add view method to estimate swaps outputs

This commit is contained in:
Gerardo Nardelli 2020-10-27 16:32:09 -03:00
parent 96e74cf707
commit e5d37e1a8c
3 changed files with 94 additions and 10 deletions

View File

@ -42,6 +42,48 @@ contract BaseUniswapAdapter {
uniswapRouter = _uniswapRouter;
}
/**
* @dev Given an input asset amount, returns the maximum output amount of the other asset
* @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
*/
function getAmountOut(uint256 amountIn, address reserveIn, address reserveOut)
public
view
returns (uint256)
{
address[] memory path = new address[](2);
path[0] = reserveIn;
path[1] = reserveOut;
uint256[] memory amounts = uniswapRouter.getAmountsOut(amountIn, path);
return amounts[1];
}
/**
* @dev Returns the minimum input asset amount required to buy the given output asset amount
* @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 amountIn
*/
function getAmountIn(uint256 amountOut, address reserveIn, address reserveOut)
public
view
returns (uint256)
{
address[] memory path = new address[](2);
path[0] = reserveIn;
path[1] = reserveOut;
uint256[] memory amounts = uniswapRouter.getAmountsIn(amountOut, path);
return amounts[0];
}
/**
* @dev Swaps an `amountToSwap` of an asset to another
* @param assetToSwapFrom Origin asset
@ -191,7 +233,27 @@ contract BaseUniswapAdapter {
}
/**
* @dev Take action with the swap left overs as configured in the parameters
* @dev Pull the ATokens from the user
* @param reserve address of the asset
* @param user address
* @param amount of tokens to be transferred to the contract
*/
function pullAToken(
address reserve,
address user,
uint256 amount
) internal {
address reserveAToken = getAToken(reserve);
// transfer from user to adapter
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
// withdraw reserve
pool.withdraw(reserve, amount);
}
/**
* @dev Pull the ATokens from the user and use them to repay the flashloan
* @param reserve address of the asset
* @param user address
* @param flashLoanDebt need to be repaid
@ -201,13 +263,7 @@ contract BaseUniswapAdapter {
address user,
uint256 flashLoanDebt
) internal {
address reserveAToken = getAToken(reserve);
// transfer from user to adapter
IERC20(reserveAToken).safeTransferFrom(user, address(this), flashLoanDebt);
// withdraw reserve
pool.withdraw(reserve, flashLoanDebt);
pullAToken(reserve, user, flashLoanDebt);
// Repay flashloan
IERC20(reserve).approve(address(pool), flashLoanDebt);

View File

@ -17,4 +17,8 @@ interface IUniswapV2Router02 {
address to,
uint deadline
) external returns (uint256[] memory amounts);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

View File

@ -8,6 +8,8 @@ import {MintableERC20} from '../tokens/MintableERC20.sol';
contract MockUniswapV2Router02 is IUniswapV2Router02 {
uint256 internal _amountToReturn;
uint256 internal _amountToSwap;
mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsIn;
mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsOut;
function setAmountToReturn(uint256 amount) public {
_amountToReturn = amount;
@ -35,8 +37,8 @@ contract MockUniswapV2Router02 is IUniswapV2Router02 {
}
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
uint /* amountOut */,
uint /* amountInMax */,
address[] calldata path,
address to,
uint /* deadline */
@ -50,4 +52,26 @@ contract MockUniswapV2Router02 is IUniswapV2Router02 {
amounts[0] = _amountToSwap;
amounts[1] = _amountToReturn;
}
function setAmountOut(uint amountIn, address reserveIn, address reserveOut, uint amountOut) public {
_amountsOut[reserveIn][reserveOut][amountIn] = amountOut;
}
function setAmountIn(uint amountOut, address reserveIn, address reserveOut, uint amountIn) public {
_amountsIn[reserveIn][reserveOut][amountOut] = amountIn;
}
function getAmountsOut(uint amountIn, address[] calldata path) external view override returns (uint[] memory) {
uint256[] memory amounts = new uint256[](2);
amounts[0] = amountIn;
amounts[1] = _amountsOut[path[0]][path[1]][amountIn];
return amounts;
}
function getAmountsIn(uint amountOut, address[] calldata path) external view override returns (uint[] memory) {
uint256[] memory amounts = new uint256[](2);
amounts[0] = _amountsIn[path[0]][path[1]][amountOut];
amounts[1] = amountOut;
return amounts;
}
}