mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Refactor repayAdapter to flash loan the debt asset instead of the collateral
This commit is contained in:
parent
b48b50208a
commit
43d05c2bdf
|
@ -16,18 +16,10 @@ import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||||
**/
|
**/
|
||||||
contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
|
|
||||||
/*
|
|
||||||
* STANDARD: Use the provided amounts parameters
|
|
||||||
* ALL_DEBT: Repay the whole debt balance
|
|
||||||
* ALL_COLLATERAL: Use all the collateral balance to repay the max amount of debt
|
|
||||||
*/
|
|
||||||
enum RepayMode {STANDARD, ALL_DEBT, ALL_COLLATERAL}
|
|
||||||
|
|
||||||
struct RepayParams {
|
struct RepayParams {
|
||||||
address assetToSwapTo;
|
address collateralAsset;
|
||||||
uint256 repayAmount;
|
uint256 collateralAmount;
|
||||||
uint256 rateMode;
|
uint256 rateMode;
|
||||||
RepayMode repayMode;
|
|
||||||
PermitSignature permitSignature;
|
PermitSignature permitSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,17 +32,17 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Swaps the received reserve amount into the asset specified in the params. The received funds from the swap are
|
* @dev Uses the received funds from the flash loan to repay a debt on the protocol on behalf of the user. Then pulls
|
||||||
* then used to repay a debt on the protocol on behalf of the user.
|
* the collateral from the user and swaps it to repay the flash loan.
|
||||||
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and
|
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset, swap it
|
||||||
* repay the flash loan.
|
* and repay the flash loan.
|
||||||
* @param assets Address to be swapped
|
* @param assets Address to be swapped
|
||||||
* @param amounts Amount of the reserve to be swapped
|
* @param amounts Amount of the reserve to be swapped
|
||||||
* @param premiums Fee of the flash loan
|
* @param premiums Fee of the flash loan
|
||||||
* @param initiator Address of the user
|
* @param initiator Address of the user
|
||||||
* @param params Additional variadic field to include extra params. Expected parameters:
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
||||||
* address Address of the reserve to be swapped to and repay
|
* address collateralAsset Address of the reserve to be swapped
|
||||||
* uint256 repayAmount Amount of debt to be repaid
|
* uint256 collateralAmount Amount of reserve to be swapped
|
||||||
* uint256 rateMode Rate modes of the debt to be repaid
|
* uint256 rateMode Rate modes of the debt to be repaid
|
||||||
* RepayMode repayMode Enum indicating the repaid mode
|
* RepayMode repayMode Enum indicating the repaid mode
|
||||||
* uint256 permitAmount Amount for the permit signature
|
* uint256 permitAmount Amount for the permit signature
|
||||||
|
@ -71,13 +63,12 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
RepayParams memory decodedParams = _decodeParams(params);
|
RepayParams memory decodedParams = _decodeParams(params);
|
||||||
|
|
||||||
_swapAndRepay(
|
_swapAndRepay(
|
||||||
|
decodedParams.collateralAsset,
|
||||||
assets[0],
|
assets[0],
|
||||||
decodedParams.assetToSwapTo,
|
|
||||||
amounts[0],
|
amounts[0],
|
||||||
decodedParams.repayAmount,
|
decodedParams.collateralAmount,
|
||||||
decodedParams.rateMode,
|
decodedParams.rateMode,
|
||||||
initiator,
|
initiator,
|
||||||
decodedParams.repayMode,
|
|
||||||
premiums[0],
|
premiums[0],
|
||||||
decodedParams.permitSignature
|
decodedParams.permitSignature
|
||||||
);
|
);
|
||||||
|
@ -86,12 +77,12 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Perform the swap and the repay of the debt
|
* @dev Perform the repay of the debt, pulls the initiator collateral and swaps to repay the flash loan
|
||||||
*
|
*
|
||||||
* @param assetFrom Address of token to be swapped
|
* @param assetFrom Address of token to be swapped
|
||||||
* @param assetTo Address of token to be received
|
* @param assetTo Address of debt token to be received from the swap
|
||||||
* @param amount Amount of the reserve to be swapped
|
* @param amount Amount of the debt to be repaid
|
||||||
* @param repayAmount Amount of the debt to be repaid
|
* @param collateralAmount Amount of the reserve to be swapped
|
||||||
* @param rateMode Rate mode of the debt to be repaid
|
* @param rateMode Rate mode of the debt to be repaid
|
||||||
* @param initiator Address of the user
|
* @param initiator Address of the user
|
||||||
* @param premium Fee of the flash loan
|
* @param premium Fee of the flash loan
|
||||||
|
@ -101,61 +92,39 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
address assetFrom,
|
address assetFrom,
|
||||||
address assetTo,
|
address assetTo,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 repayAmount,
|
uint256 collateralAmount,
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
address initiator,
|
address initiator,
|
||||||
RepayMode repayMode,
|
|
||||||
uint256 premium,
|
uint256 premium,
|
||||||
PermitSignature memory permitSignature
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
uint256 debtRepayAmount;
|
|
||||||
uint256 amountSwapped;
|
|
||||||
|
|
||||||
ReserveLogic.ReserveData memory reserveData = _getReserveData(assetFrom);
|
|
||||||
|
|
||||||
if (repayMode == RepayMode.ALL_COLLATERAL) {
|
|
||||||
uint256 aTokenInitiatorBalance = IERC20(reserveData.aTokenAddress).balanceOf(initiator);
|
|
||||||
amountSwapped = aTokenInitiatorBalance.sub(premium);
|
|
||||||
|
|
||||||
debtRepayAmount = _swapExactTokensForTokens(assetFrom, assetTo, amountSwapped, repayAmount);
|
|
||||||
} else {
|
|
||||||
if (repayMode == RepayMode.ALL_DEBT) {
|
|
||||||
ReserveLogic.ReserveData memory reserveDebtData = _getReserveData(assetTo);
|
|
||||||
|
|
||||||
address debtToken = ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.STABLE
|
|
||||||
? reserveDebtData.stableDebtTokenAddress
|
|
||||||
: reserveDebtData.variableDebtTokenAddress;
|
|
||||||
|
|
||||||
debtRepayAmount = IERC20(debtToken).balanceOf(initiator);
|
|
||||||
} else {
|
|
||||||
debtRepayAmount = repayAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
amountSwapped = _swapTokensForExactTokens(assetFrom, assetTo, amount, debtRepayAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repay debt
|
// Repay debt
|
||||||
IERC20(assetTo).approve(address(POOL), debtRepayAmount);
|
IERC20(assetTo).approve(address(POOL), amount);
|
||||||
POOL.repay(assetTo, debtRepayAmount, rateMode, initiator);
|
POOL.repay(assetTo, amount, rateMode, initiator);
|
||||||
// In the case the repay amount provided exceeded the actual debt, send the leftovers to the user
|
uint256 debtRepayLeftovers = IERC20(assetTo).balanceOf(address(this));
|
||||||
_sendRepayLeftovers(assetTo, initiator);
|
|
||||||
|
|
||||||
uint256 flashLoanDebt = amount.add(premium);
|
uint256 flashLoanDebt = amount.add(premium);
|
||||||
uint256 amountToPull = amountSwapped.add(premium);
|
uint256 neededForFlashLoanDebt = flashLoanDebt.sub(debtRepayLeftovers);
|
||||||
|
|
||||||
_pullAToken(assetFrom, reserveData.aTokenAddress, initiator, amountToPull, permitSignature);
|
// Pull aTokens from user
|
||||||
|
ReserveLogic.ReserveData memory reserveData = _getReserveData(assetFrom);
|
||||||
|
_pullAToken(assetFrom, reserveData.aTokenAddress, initiator, collateralAmount, permitSignature);
|
||||||
|
|
||||||
|
uint256 amountSwapped = _swapTokensForExactTokens(assetFrom, assetTo, collateralAmount, neededForFlashLoanDebt);
|
||||||
|
|
||||||
|
// Send collateral leftovers from swap to the user
|
||||||
|
_sendLeftovers(assetFrom, initiator);
|
||||||
|
|
||||||
// Repay flashloan
|
// Repay flashloan
|
||||||
IERC20(assetFrom).approve(address(POOL), flashLoanDebt);
|
IERC20(assetTo).approve(address(POOL), flashLoanDebt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Decodes debt information encoded in flashloan params
|
* @dev Decodes debt information encoded in flashloan params
|
||||||
* @param params Additional variadic field to include extra params. Expected parameters:
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
||||||
* address Address of the reserve to be swapped to and repay
|
* address collateralAsset Address of the reserve to be swapped
|
||||||
* uint256 repayAmount Amount of debt to be repaid
|
* uint256 collateralAmount Amount of reserve to be swapped
|
||||||
* uint256 rateMode Rate modes of the debt to be repaid
|
* uint256 rateMode Rate modes of the debt to be repaid
|
||||||
* RepayMode repayMode Enum indicating the repaid mode
|
|
||||||
* uint256 permitAmount Amount for the permit signature
|
* uint256 permitAmount Amount for the permit signature
|
||||||
* uint256 deadline Deadline for the permit signature
|
* uint256 deadline Deadline for the permit signature
|
||||||
* uint8 v V param for the permit signature
|
* uint8 v V param for the permit signature
|
||||||
|
@ -165,22 +134,20 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
*/
|
*/
|
||||||
function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) {
|
function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) {
|
||||||
(
|
(
|
||||||
address assetToSwapTo,
|
address collateralAsset,
|
||||||
uint256 repayAmount,
|
uint256 collateralAmount,
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
RepayMode repayMode,
|
|
||||||
uint256 permitAmount,
|
uint256 permitAmount,
|
||||||
uint256 deadline,
|
uint256 deadline,
|
||||||
uint8 v,
|
uint8 v,
|
||||||
bytes32 r,
|
bytes32 r,
|
||||||
bytes32 s
|
bytes32 s
|
||||||
) = abi.decode(params, (address, uint256, uint256, RepayMode, uint256, uint256, uint8, bytes32, bytes32));
|
) = abi.decode(params, (address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32));
|
||||||
|
|
||||||
return RepayParams(
|
return RepayParams(
|
||||||
assetToSwapTo,
|
collateralAsset,
|
||||||
repayAmount,
|
collateralAmount,
|
||||||
rateMode,
|
rateMode,
|
||||||
repayMode,
|
|
||||||
PermitSignature(
|
PermitSignature(
|
||||||
permitAmount,
|
permitAmount,
|
||||||
deadline,
|
deadline,
|
||||||
|
@ -196,7 +163,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* @param asset address of the asset
|
* @param asset address of the asset
|
||||||
* @param user address
|
* @param user address
|
||||||
*/
|
*/
|
||||||
function _sendRepayLeftovers(address asset, address user) internal {
|
function _sendLeftovers(address asset, address user) internal {
|
||||||
uint256 assetLeftover = IERC20(asset).balanceOf(address(this));
|
uint256 assetLeftover = IERC20(asset).balanceOf(address(this));
|
||||||
|
|
||||||
if (assetLeftover > 0) {
|
if (assetLeftover > 0) {
|
||||||
|
|
|
@ -259,10 +259,9 @@ export const buildLiquiditySwapParams = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const buildRepayAdapterParams = (
|
export const buildRepayAdapterParams = (
|
||||||
assetToSwapTo: tEthereumAddress,
|
collateralAsset: tEthereumAddress,
|
||||||
repayAmount: BigNumberish,
|
collateralAmount: BigNumberish,
|
||||||
rateMode: BigNumberish,
|
rateMode: BigNumberish,
|
||||||
repayMode: BigNumberish,
|
|
||||||
permitAmount: BigNumberish,
|
permitAmount: BigNumberish,
|
||||||
deadline: BigNumberish,
|
deadline: BigNumberish,
|
||||||
v: BigNumberish,
|
v: BigNumberish,
|
||||||
|
@ -276,11 +275,10 @@ export const buildRepayAdapterParams = (
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
|
||||||
'uint8',
|
'uint8',
|
||||||
'bytes32',
|
'bytes32',
|
||||||
'bytes32',
|
'bytes32',
|
||||||
],
|
],
|
||||||
[assetToSwapTo, repayAmount, rateMode, repayMode, permitAmount, deadline, v, r, s]
|
[collateralAsset, collateralAmount, rateMode, permitAmount, deadline, v, r, s]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2085,19 +2085,19 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
|
||||||
|
.multipliedBy(1.0009)
|
||||||
|
.toFixed(0);
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2107,8 +2107,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2116,7 +2116,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.to.emit(uniswapRepayAdapter, 'Swapped')
|
.to.emit(uniswapRepayAdapter, 'Swapped')
|
||||||
.withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount);
|
.withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
|
||||||
|
|
||||||
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
||||||
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
||||||
|
@ -2170,9 +2170,6 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
const liquidityToSwap = amountWETHtoSwap;
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||||
const deadline = MAX_UINT_AMOUNT;
|
const deadline = MAX_UINT_AMOUNT;
|
||||||
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
||||||
|
@ -2195,13 +2192,16 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
|
|
||||||
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
|
|
||||||
|
const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
|
||||||
|
.multipliedBy(1.0009)
|
||||||
|
.toFixed(0);
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
|
||||||
liquidityToSwap,
|
liquidityToSwap,
|
||||||
deadline,
|
deadline,
|
||||||
v,
|
v,
|
||||||
|
@ -2214,8 +2214,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2223,7 +2223,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.to.emit(uniswapRepayAdapter, 'Swapped')
|
.to.emit(uniswapRepayAdapter, 'Swapped')
|
||||||
.withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount);
|
.withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
|
||||||
|
|
||||||
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
||||||
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
||||||
|
@ -2257,19 +2257,15 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
const liquidityToSwap = amountWETHtoSwap;
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2278,8 +2274,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
uniswapRepayAdapter
|
uniswapRepayAdapter
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.executeOperation(
|
.executeOperation(
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params
|
params
|
||||||
|
@ -2309,19 +2305,15 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
const liquidityToSwap = amountWETHtoSwap;
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2331,8 +2323,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2360,19 +2352,15 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
const liquidityToSwap = amountWETHtoSwap;
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2382,8 +2370,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2408,22 +2396,18 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
// Open user Debt
|
// Open user Debt
|
||||||
await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
|
await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
|
||||||
|
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, amountWETHtoSwap);
|
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
|
||||||
const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
|
const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
|
||||||
const flashloanAmount = new BigNumber(bigMaxAmountToSwap.toString()).div(1.0009).toFixed(0);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap);
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap);
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
bigMaxAmountToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2433,8 +2417,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2482,26 +2466,27 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
const liquidityToSwap = amountWETHtoSwap;
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
||||||
|
const userWethBalanceBefore = await weth.balanceOf(userAddress);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
const actualWEthSwapped = new BigNumber(liquidityToSwap.toString())
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
const actualWEthSwapped = new BigNumber(flashloanAmount.toString())
|
|
||||||
.multipliedBy(0.995)
|
.multipliedBy(0.995)
|
||||||
.toFixed(0);
|
.toFixed(0);
|
||||||
|
|
||||||
const leftOverWeth = new BigNumber(flashloanAmount).minus(actualWEthSwapped);
|
const leftOverWeth = new BigNumber(liquidityToSwap.toString()).minus(actualWEthSwapped);
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
|
||||||
|
|
||||||
|
const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
|
||||||
|
.multipliedBy(1.0009)
|
||||||
|
.toFixed(0);
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
expectedDaiAmount,
|
liquidityToSwap,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2511,8 +2496,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[expectedDaiAmount.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2520,13 +2505,14 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.to.emit(uniswapRepayAdapter, 'Swapped')
|
.to.emit(uniswapRepayAdapter, 'Swapped')
|
||||||
.withArgs(weth.address, dai.address, actualWEthSwapped.toString(), expectedDaiAmount);
|
.withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt);
|
||||||
|
|
||||||
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
||||||
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
||||||
const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
|
const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
|
||||||
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
||||||
const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
|
const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
|
||||||
|
const userWethBalance = await weth.balanceOf(userAddress);
|
||||||
|
|
||||||
expect(adapterAEthBalance).to.be.eq(Zero);
|
expect(adapterAEthBalance).to.be.eq(Zero);
|
||||||
expect(adapterWethBalance).to.be.eq(Zero);
|
expect(adapterWethBalance).to.be.eq(Zero);
|
||||||
|
@ -2534,13 +2520,11 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
|
expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
|
||||||
expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
|
expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
|
||||||
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
||||||
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(liquidityToSwap));
|
expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
expect(userAEthBalance).to.be.gte(
|
expect(userWethBalance).to.be.gte(userWethBalanceBefore.add(leftOverWeth.toString()));
|
||||||
userAEthBalanceBefore.sub(liquidityToSwap).add(leftOverWeth.toString())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly swap tokens and repay the whole stable debt', async () => {
|
it('should correctly swap tokens and repay the whole stable debt with no leftovers', async () => {
|
||||||
const {
|
const {
|
||||||
users,
|
users,
|
||||||
pool,
|
pool,
|
||||||
|
@ -2580,19 +2564,16 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
// Add a % to repay on top of the debt
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
const amountToRepay = new BigNumber(expectedDaiAmount.toString())
|
||||||
|
.multipliedBy(1.1)
|
||||||
|
.toFixed(0);
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
|
|
||||||
// Passed amount to repay is smaller than debt,
|
|
||||||
// but repayAllDebt flag is enabled so the whole debt should be paid
|
|
||||||
const amountToRepay = expectedDaiAmount.div(2);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
amountToRepay,
|
liquidityToSwap,
|
||||||
1,
|
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -2605,8 +2586,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[amountToRepay.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2628,7 +2609,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly swap tokens and repay the whole variable debt', async () => {
|
it('should correctly swap tokens and repay the whole variable debt with no leftovers', async () => {
|
||||||
const {
|
const {
|
||||||
users,
|
users,
|
||||||
pool,
|
pool,
|
||||||
|
@ -2670,20 +2651,17 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
// Add a % to repay on top of the debt
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
const amountToRepay = new BigNumber(expectedDaiAmount.toString())
|
||||||
|
.multipliedBy(1.1)
|
||||||
|
.toFixed(0);
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
|
||||||
|
|
||||||
// Passed amount to repay is smaller than debt,
|
|
||||||
// but repayAllDebt flag is enabled so the whole debt should be paid
|
|
||||||
const amountToRepay = expectedDaiAmount.div(2);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
const params = buildRepayAdapterParams(
|
||||||
dai.address,
|
weth.address,
|
||||||
amountToRepay,
|
liquidityToSwap,
|
||||||
2,
|
2,
|
||||||
1,
|
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -2695,8 +2673,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
.connect(user)
|
.connect(user)
|
||||||
.flashLoan(
|
.flashLoan(
|
||||||
uniswapRepayAdapter.address,
|
uniswapRepayAdapter.address,
|
||||||
[weth.address],
|
[dai.address],
|
||||||
[flashloanAmount.toString()],
|
[amountToRepay.toString()],
|
||||||
[0],
|
[0],
|
||||||
userAddress,
|
userAddress,
|
||||||
params,
|
params,
|
||||||
|
@ -2717,192 +2695,6 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
||||||
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should swap and repay debt using all the collateral for a bigger debt', async () => {
|
|
||||||
const {
|
|
||||||
users,
|
|
||||||
pool,
|
|
||||||
weth,
|
|
||||||
aWETH,
|
|
||||||
oracle,
|
|
||||||
dai,
|
|
||||||
uniswapRepayAdapter,
|
|
||||||
helpersContract,
|
|
||||||
} = testEnv;
|
|
||||||
const user = users[0].signer;
|
|
||||||
const userAddress = users[0].address;
|
|
||||||
|
|
||||||
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
||||||
|
|
||||||
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
||||||
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
||||||
dai.address,
|
|
||||||
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
const userDebt = new BigNumber(expectedDaiAmount.toString()).multipliedBy(1.1).toFixed(0);
|
|
||||||
// Open user Debt
|
|
||||||
await pool.connect(user).borrow(dai.address, userDebt, 1, 0, userAddress);
|
|
||||||
|
|
||||||
const daiStableDebtTokenAddress = (
|
|
||||||
await helpersContract.getReserveTokensAddresses(dai.address)
|
|
||||||
).stableDebtTokenAddress;
|
|
||||||
|
|
||||||
const daiStableDebtContract = await getContract<StableDebtToken>(
|
|
||||||
eContractid.StableDebtToken,
|
|
||||||
daiStableDebtTokenAddress
|
|
||||||
);
|
|
||||||
|
|
||||||
const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
|
|
||||||
|
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
const actualWEthSwapped = new BigNumber(flashloanAmount.toString())
|
|
||||||
.multipliedBy(0.995)
|
|
||||||
.toFixed(0);
|
|
||||||
|
|
||||||
// Remove other balance
|
|
||||||
await aWETH
|
|
||||||
.connect(user)
|
|
||||||
.transfer(users[1].address, userAEthBalanceBefore.sub(actualWEthSwapped));
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToReturn(weth.address, expectedDaiAmount);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
|
||||||
dai.address,
|
|
||||||
expectedDaiAmount,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool
|
|
||||||
.connect(user)
|
|
||||||
.flashLoan(
|
|
||||||
uniswapRepayAdapter.address,
|
|
||||||
[weth.address],
|
|
||||||
[flashloanAmount.toString()],
|
|
||||||
[0],
|
|
||||||
userAddress,
|
|
||||||
params,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
|
|
||||||
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
||||||
const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
|
|
||||||
expect(adapterAEthBalance).to.be.eq(Zero);
|
|
||||||
expect(adapterWethBalance).to.be.eq(Zero);
|
|
||||||
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
||||||
expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
|
|
||||||
expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
|
|
||||||
expect(userAEthBalance).to.be.eq(Zero);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should swap and repay debt using all the collateral for a smaller debt', async () => {
|
|
||||||
const {
|
|
||||||
users,
|
|
||||||
pool,
|
|
||||||
weth,
|
|
||||||
aWETH,
|
|
||||||
oracle,
|
|
||||||
dai,
|
|
||||||
uniswapRepayAdapter,
|
|
||||||
helpersContract,
|
|
||||||
} = testEnv;
|
|
||||||
const user = users[0].signer;
|
|
||||||
const userAddress = users[0].address;
|
|
||||||
|
|
||||||
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
||||||
|
|
||||||
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
||||||
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
||||||
dai.address,
|
|
||||||
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
const userDebt = new BigNumber(expectedDaiAmount.toString()).multipliedBy(0.9).toFixed(0);
|
|
||||||
// Open user Debt
|
|
||||||
await pool.connect(user).borrow(dai.address, userDebt, 1, 0, userAddress);
|
|
||||||
|
|
||||||
const daiStableDebtTokenAddress = (
|
|
||||||
await helpersContract.getReserveTokensAddresses(dai.address)
|
|
||||||
).stableDebtTokenAddress;
|
|
||||||
|
|
||||||
const daiStableDebtContract = await getContract<StableDebtToken>(
|
|
||||||
eContractid.StableDebtToken,
|
|
||||||
daiStableDebtTokenAddress
|
|
||||||
);
|
|
||||||
|
|
||||||
const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
|
|
||||||
|
|
||||||
const liquidityToSwap = amountWETHtoSwap;
|
|
||||||
await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
|
|
||||||
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
||||||
|
|
||||||
// Subtract the FL fee from the amount to be swapped 0,09%
|
|
||||||
const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
|
|
||||||
|
|
||||||
const actualWEthSwapped = new BigNumber(flashloanAmount.toString())
|
|
||||||
.multipliedBy(0.995)
|
|
||||||
.toFixed(0);
|
|
||||||
|
|
||||||
// Remove other balance
|
|
||||||
await aWETH
|
|
||||||
.connect(user)
|
|
||||||
.transfer(users[1].address, userAEthBalanceBefore.sub(actualWEthSwapped));
|
|
||||||
|
|
||||||
await mockUniswapRouter.connect(user).setAmountToReturn(weth.address, expectedDaiAmount);
|
|
||||||
|
|
||||||
const params = buildRepayAdapterParams(
|
|
||||||
dai.address,
|
|
||||||
expectedDaiAmount,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool
|
|
||||||
.connect(user)
|
|
||||||
.flashLoan(
|
|
||||||
uniswapRepayAdapter.address,
|
|
||||||
[weth.address],
|
|
||||||
[flashloanAmount.toString()],
|
|
||||||
[0],
|
|
||||||
userAddress,
|
|
||||||
params,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
|
|
||||||
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
||||||
const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
|
|
||||||
|
|
||||||
expect(adapterAEthBalance).to.be.eq(Zero);
|
|
||||||
expect(adapterWethBalance).to.be.eq(Zero);
|
|
||||||
expect(adapterDaiBalance).to.be.eq(Zero); // Validate there are no leftovers
|
|
||||||
expect(userDaiStableDebtAmountBefore).to.be.gte(userDebt);
|
|
||||||
expect(userDaiStableDebtAmount).to.be.eq(Zero);
|
|
||||||
expect(userAEthBalance).to.be.eq(Zero);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user