mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Add repayAllDebt flag to repay the whole debt with collateral
This commit is contained in:
parent
4fb43f7aff
commit
6e9defe14c
|
@ -224,9 +224,8 @@ contract BaseUniswapAdapter {
|
||||||
* @dev Get the aToken associated to the asset
|
* @dev Get the aToken associated to the asset
|
||||||
* @return address of the aToken
|
* @return address of the aToken
|
||||||
*/
|
*/
|
||||||
function _getAToken(address asset) internal view returns (address) {
|
function _getReserveData(address asset) internal view returns (ReserveLogic.ReserveData memory) {
|
||||||
ReserveLogic.ReserveData memory reserve = POOL.getReserveData(asset);
|
return POOL.getReserveData(asset);
|
||||||
return reserve.aTokenAddress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -126,7 +126,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
|
for (uint256 i = 0; i < assetToSwapFromList.length; i++) {
|
||||||
address aToken = _getAToken(assetToSwapFromList[i]);
|
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];
|
||||||
|
@ -172,7 +172,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
bool swapAllBalance,
|
bool swapAllBalance,
|
||||||
PermitSignature memory permitSignature
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
address aToken = _getAToken(assetFrom);
|
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 = swapAllBalance ? aTokenInitiatorBalance.sub(premium) : amount;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddresses
|
||||||
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
|
||||||
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.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 {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title UniswapRepayAdapter
|
* @title UniswapRepayAdapter
|
||||||
|
@ -20,6 +21,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
LeftoverAction leftOverAction;
|
LeftoverAction leftOverAction;
|
||||||
uint256 repayAmount;
|
uint256 repayAmount;
|
||||||
uint256 rateMode;
|
uint256 rateMode;
|
||||||
|
bool repayAllDebt;
|
||||||
PermitSignature permitSignature;
|
PermitSignature permitSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* (1) Direct transfer to user
|
* (1) Direct transfer to user
|
||||||
* uint256 repayAmount Amount of debt to be repaid
|
* uint256 repayAmount Amount of debt to be repaid
|
||||||
* uint256 rateMode Rate modes of the debt to be repaid
|
* uint256 rateMode Rate modes of the debt to be repaid
|
||||||
|
* bool repayAllDebt Flag indicating if all the debt should be repaid
|
||||||
* 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
|
||||||
|
@ -72,6 +75,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
decodedParams.rateMode,
|
decodedParams.rateMode,
|
||||||
initiator,
|
initiator,
|
||||||
decodedParams.leftOverAction,
|
decodedParams.leftOverAction,
|
||||||
|
decodedParams.repayAllDebt,
|
||||||
premiums[0],
|
premiums[0],
|
||||||
decodedParams.permitSignature
|
decodedParams.permitSignature
|
||||||
);
|
);
|
||||||
|
@ -100,9 +104,21 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
address initiator,
|
address initiator,
|
||||||
LeftoverAction leftOverAction,
|
LeftoverAction leftOverAction,
|
||||||
|
bool repayAllDebt,
|
||||||
uint256 premium,
|
uint256 premium,
|
||||||
PermitSignature memory permitSignature
|
PermitSignature memory permitSignature
|
||||||
) internal {
|
) internal {
|
||||||
|
|
||||||
|
if (repayAllDebt) {
|
||||||
|
ReserveLogic.ReserveData memory reserveDebtData = _getReserveData(assetTo);
|
||||||
|
|
||||||
|
address debtToken = ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.STABLE
|
||||||
|
? reserveDebtData.stableDebtTokenAddress
|
||||||
|
: reserveDebtData.variableDebtTokenAddress;
|
||||||
|
|
||||||
|
repayAmount = IERC20(debtToken).balanceOf(initiator);
|
||||||
|
}
|
||||||
|
|
||||||
_swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount);
|
_swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount);
|
||||||
|
|
||||||
// Repay debt
|
// Repay debt
|
||||||
|
@ -110,7 +126,12 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
POOL.repay(assetTo, repayAmount, rateMode, initiator);
|
POOL.repay(assetTo, repayAmount, rateMode, initiator);
|
||||||
|
|
||||||
uint256 flashLoanDebt = amount.add(premium);
|
uint256 flashLoanDebt = amount.add(premium);
|
||||||
_pullATokenAndRepayFlashLoan(assetFrom, initiator, flashLoanDebt, permitSignature);
|
|
||||||
|
ReserveLogic.ReserveData memory reserveData = _getReserveData(assetFrom);
|
||||||
|
_pullAToken(assetFrom, reserveData.aTokenAddress, initiator, flashLoanDebt, permitSignature);
|
||||||
|
|
||||||
|
// Repay flashloan
|
||||||
|
IERC20(assetFrom).approve(address(POOL), flashLoanDebt);
|
||||||
|
|
||||||
// Take care of reserve leftover from the swap
|
// Take care of reserve leftover from the swap
|
||||||
_sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator);
|
_sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator);
|
||||||
|
@ -125,6 +146,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
* (1) Direct transfer to user
|
* (1) Direct transfer to user
|
||||||
* uint256 repayAmount Amount of debt to be repaid
|
* uint256 repayAmount Amount of debt to be repaid
|
||||||
* uint256 rateMode Rate modes of the debt to be repaid
|
* uint256 rateMode Rate modes of the debt to be repaid
|
||||||
|
* bool repayAllDebt Flag indicating if all the debt should be repaid
|
||||||
* 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
|
||||||
|
@ -138,18 +160,20 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
LeftoverAction leftOverAction,
|
LeftoverAction leftOverAction,
|
||||||
uint256 repayAmount,
|
uint256 repayAmount,
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
|
bool repayAllDebt,
|
||||||
uint256 permitAmount,
|
uint256 permitAmount,
|
||||||
uint256 deadline,
|
uint256 deadline,
|
||||||
uint8 v,
|
uint8 v,
|
||||||
bytes32 r,
|
bytes32 r,
|
||||||
bytes32 s
|
bytes32 s
|
||||||
) = abi.decode(params, (address, LeftoverAction, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32));
|
) = abi.decode(params, (address, LeftoverAction, uint256, uint256, bool, uint256, uint256, uint8, bytes32, bytes32));
|
||||||
|
|
||||||
return RepayParams(
|
return RepayParams(
|
||||||
assetToSwapTo,
|
assetToSwapTo,
|
||||||
leftOverAction,
|
leftOverAction,
|
||||||
repayAmount,
|
repayAmount,
|
||||||
rateMode,
|
rateMode,
|
||||||
|
repayAllDebt,
|
||||||
PermitSignature(
|
PermitSignature(
|
||||||
permitAmount,
|
permitAmount,
|
||||||
deadline,
|
deadline,
|
||||||
|
@ -159,24 +183,4 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
* @param permitSignature struct containing the permit signature
|
|
||||||
*/
|
|
||||||
function _pullATokenAndRepayFlashLoan(
|
|
||||||
address reserve,
|
|
||||||
address user,
|
|
||||||
uint256 flashLoanDebt,
|
|
||||||
PermitSignature memory permitSignature
|
|
||||||
) internal {
|
|
||||||
address reserveAToken = _getAToken(reserve);
|
|
||||||
_pullAToken(reserve, reserveAToken, user, flashLoanDebt, permitSignature);
|
|
||||||
|
|
||||||
// Repay flashloan
|
|
||||||
IERC20(reserve).approve(address(POOL), flashLoanDebt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,7 @@ export const buildRepayAdapterParams = (
|
||||||
leftoverAction: BigNumberish,
|
leftoverAction: BigNumberish,
|
||||||
repayAmount: BigNumberish,
|
repayAmount: BigNumberish,
|
||||||
rateMode: BigNumberish,
|
rateMode: BigNumberish,
|
||||||
|
repayAllDebt: BigNumberish,
|
||||||
permitAmount: BigNumberish,
|
permitAmount: BigNumberish,
|
||||||
deadline: BigNumberish,
|
deadline: BigNumberish,
|
||||||
v: BigNumberish,
|
v: BigNumberish,
|
||||||
|
@ -256,12 +257,24 @@ export const buildRepayAdapterParams = (
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
'uint256',
|
||||||
|
'bool',
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint256',
|
'uint256',
|
||||||
'uint8',
|
'uint8',
|
||||||
'bytes32',
|
'bytes32',
|
||||||
'bytes32',
|
'bytes32',
|
||||||
],
|
],
|
||||||
[assetToSwapTo, leftoverAction, repayAmount, rateMode, permitAmount, deadline, v, r, s]
|
[
|
||||||
|
assetToSwapTo,
|
||||||
|
leftoverAction,
|
||||||
|
repayAmount,
|
||||||
|
rateMode,
|
||||||
|
repayAllDebt,
|
||||||
|
permitAmount,
|
||||||
|
deadline,
|
||||||
|
v,
|
||||||
|
r,
|
||||||
|
s,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1959,7 +1959,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.only('UniswapRepayAdapter', () => {
|
describe('UniswapRepayAdapter', () => {
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('should deploy with correct parameters', async () => {
|
it('should deploy with correct parameters', async () => {
|
||||||
const {addressesProvider} = testEnv;
|
const {addressesProvider} = testEnv;
|
||||||
|
@ -2062,6 +2062,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2166,6 +2167,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
expectedDaiAmount,
|
expectedDaiAmount,
|
||||||
1,
|
1,
|
||||||
|
0,
|
||||||
liquidityToSwap,
|
liquidityToSwap,
|
||||||
deadline,
|
deadline,
|
||||||
v,
|
v,
|
||||||
|
@ -2234,6 +2236,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2286,6 +2289,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2337,6 +2341,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2388,6 +2393,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2466,6 +2472,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2563,6 +2570,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
);
|
);
|
||||||
|
@ -2597,6 +2605,182 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
|
||||||
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(liquidityToSwap));
|
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
expect(wethBalance).to.be.eq(wethBalanceBefore.add(leftOverWeth.toString()));
|
expect(wethBalance).to.be.eq(wethBalanceBefore.add(leftOverWeth.toString()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should correctly swap tokens and repay the whole stable 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Open user Debt
|
||||||
|
await pool.connect(user).borrow(dai.address, expectedDaiAmount, 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);
|
||||||
|
|
||||||
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
dai.address,
|
||||||
|
0,
|
||||||
|
amountToRepay,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
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);
|
||||||
|
|
||||||
|
expect(adapterWethBalance).to.be.eq(Zero);
|
||||||
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
||||||
|
expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
|
||||||
|
expect(userDaiStableDebtAmount).to.be.eq(Zero);
|
||||||
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
||||||
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly swap tokens and repay the whole variable 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Open user Debt
|
||||||
|
await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
|
||||||
|
|
||||||
|
const daiStableVariableTokenAddress = (
|
||||||
|
await helpersContract.getReserveTokensAddresses(dai.address)
|
||||||
|
).variableDebtTokenAddress;
|
||||||
|
|
||||||
|
const daiVariableDebtContract = await getContract<StableDebtToken>(
|
||||||
|
eContractid.VariableDebtToken,
|
||||||
|
daiStableVariableTokenAddress
|
||||||
|
);
|
||||||
|
|
||||||
|
const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.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);
|
||||||
|
|
||||||
|
await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount);
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
dai.address,
|
||||||
|
0,
|
||||||
|
amountToRepay,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
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 userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress);
|
||||||
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
||||||
|
|
||||||
|
expect(adapterWethBalance).to.be.eq(Zero);
|
||||||
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
||||||
|
expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount);
|
||||||
|
expect(userDaiVariableDebtAmount).to.be.eq(Zero);
|
||||||
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
|
||||||
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user