diff --git a/test-suites/test-aave/authorized-flashloan.spec.ts b/test-suites/test-aave/authorized-flashloan.spec.ts deleted file mode 100644 index 6178b7ef..00000000 --- a/test-suites/test-aave/authorized-flashloan.spec.ts +++ /dev/null @@ -1,522 +0,0 @@ -import BigNumber from 'bignumber.js'; - -import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../../helpers/constants'; -import { convertToCurrencyDecimals, getContract } from '../../helpers/contracts-helpers'; -import { ethers } from 'ethers'; -import { MockFlashLoanReceiver } from '../../types/MockFlashLoanReceiver'; -import { ProtocolErrors, eContractid } from '../../helpers/types'; -import { VariableDebtToken } from '../../types/VariableDebtToken'; -import { StableDebtToken } from '../../types/StableDebtToken'; -import { - getMockFlashLoanReceiver, - getStableDebtToken, - getVariableDebtToken, -} from '../../helpers/contracts-getters'; - -const { expect } = require('chai'); - -makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { - let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; - const { - VL_COLLATERAL_BALANCE_IS_0, - TRANSFER_AMOUNT_EXCEEDS_BALANCE, - LP_INVALID_FLASHLOAN_MODE, - SAFEERC20_LOWLEVEL_CALL, - LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN, - LP_BORROW_ALLOWANCE_NOT_ENOUGH, - } = ProtocolErrors; - - before(async () => { - _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); - }); - - it('Authorize flash borowers', async () => { - const { deployer, pool, weth, configurator, users } = testEnv; - await configurator.authorizeFlashBorrower(deployer.address); - await configurator.authorizeFlashBorrower(users[1].address); - await configurator.authorizeFlashBorrower(users[2].address); - await configurator.authorizeFlashBorrower(users[3].address); - await configurator.authorizeFlashBorrower(users[4].address); - await configurator.authorizeFlashBorrower(users[5].address); - }); - - it('Deposits WETH into the reserve', async () => { - const { pool, weth } = testEnv; - const userAddress = await pool.signer.getAddress(); - const amountToDeposit = ethers.utils.parseEther('1'); - - await weth.mint(amountToDeposit); - - await weth.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - await pool.deposit(weth.address, amountToDeposit, userAddress, '0'); - }); - - it('Takes WETH flash loan with mode = 0, returns the funds correctly', async () => { - const { pool, helpersContract, weth } = testEnv; - - await pool.flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - ethers.utils.parseUnits('10000'); - - const reserveData = await helpersContract.getReserveData(weth.address); - - const currentLiquidityRate = reserveData.liquidityRate; - const currentLiquidityIndex = reserveData.liquidityIndex; - - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - expect(totalLiquidity.toString()).to.be.equal('1000000000000000000'); - expect(currentLiquidityRate.toString()).to.be.equal('0'); - expect(currentLiquidityIndex.toString()).to.be.equal('1000000000000000000000000000'); - }); - - it('Takes an ETH flash loan with mode = 0 as big as the available liquidity', async () => { - const { pool, helpersContract, weth } = testEnv; - - const reserveDataBefore = await helpersContract.getReserveData(weth.address); - const txResult = await pool.flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - ['1000000000000000000'], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - const reserveData = await helpersContract.getReserveData(weth.address); - - const currentLiquidityRate = reserveData.liquidityRate; - const currentLiquidityIndex = reserveData.liquidityIndex; - - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - expect(totalLiquidity.toString()).to.be.equal('1000000000000000000'); - expect(currentLiquidityRate.toString()).to.be.equal('0'); - expect(currentLiquidityIndex.toString()).to.be.equal('1000000000000000000000000000'); - }); - - it('Takes WETH flashloan, does not return the funds with mode = 0. (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('Takes WETH flash loan, simulating a receiver as EOA (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - await _mockFlashLoanReceiver.setSimulateEOA(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN); - }); - - it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - await _mockFlashLoanReceiver.setSimulateEOA(false); - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [ethers.utils.parseEther('0.8')], - [4], - caller.address, - '0x10', - '0' - ) - ).to.be.reverted; - }); - - it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[1]; - - await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); - - const borrowedAmount = await convertToCurrencyDecimals(weth.address, '0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [borrowedAmount], - [2], - caller.address, - '0x10', - '0' - ); - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - ethers.utils.parseUnits('10000'); - - const fees = 0; - - const reserveData = await helpersContract.getReserveData(weth.address); - - let totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) - .plus(reserveData.totalStableDebt.toString()) - .plus(reserveData.totalVariableDebt.toString()); - - expect(totalLiquidity.toString()).to.be.equal( - ethers.BigNumber.from('1000000000000000000').add(fees) - ); - - const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const callerDebt = await wethDebtToken.balanceOf(caller.address); - - expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); - }); - - it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => { - const { pool, weth, users } = testEnv; - const caller = users[1]; - - await expect( - pool.connect(caller.signer).flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - ['1000000000000000001'], //slightly higher than the available liquidity - [2], - caller.address, - '0x10', - '0' - ), - TRANSFER_AMOUNT_EXCEEDS_BALANCE - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => { - const { pool, deployer, weth, users } = testEnv; - const caller = users[1]; - - await expect( - pool.flashLoan( - deployer.address, - [weth.address], - ['1000000000000000000'], - [2], - caller.address, - '0x10', - '0' - ) - ).to.be.reverted; - }); - - it('Deposits USDC into the reserve', async () => { - const { usdc, pool } = testEnv; - const userAddress = await pool.signer.getAddress(); - - await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); - - await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); - - await pool.deposit(usdc.address, amountToDeposit, userAddress, '0'); - }); - - it('Takes out a 500 USDC flashloan, returns the funds correctly', async () => { - const { usdc, pool, helpersContract, deployer: depositor } = testEnv; - - await _mockFlashLoanReceiver.setFailExecutionTransfer(false); - - const reserveDataBefore = await helpersContract.getReserveData(usdc.address); - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await pool.flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [0], - _mockFlashLoanReceiver.address, - '0x10', - '0' - ); - - const reserveDataAfter = helpersContract.getReserveData(usdc.address); - - const reserveData = await helpersContract.getReserveData(usdc.address); - const userData = await helpersContract.getUserReserveData(usdc.address, depositor.address); - - const totalLiquidity = reserveData.availableLiquidity - .add(reserveData.totalStableDebt) - .add(reserveData.totalVariableDebt) - .toString(); - const currentLiquidityRate = reserveData.liquidityRate.toString(); - const currentLiquidityIndex = reserveData.liquidityIndex.toString(); - const currentUserBalance = userData.currentATokenBalance.toString(); - - const expectedLiquidity = await convertToCurrencyDecimals(usdc.address, '1000'); - - expect(totalLiquidity).to.be.equal(expectedLiquidity, 'Invalid total liquidity'); - expect(currentLiquidityRate).to.be.equal('0', 'Invalid liquidity rate'); - expect(currentLiquidityIndex).to.be.equal( - new BigNumber('1.00000').multipliedBy(oneRay).toFixed(), - 'Invalid liquidity index' - ); - expect(currentUserBalance.toString()).to.be.equal(expectedLiquidity, 'Invalid user balance'); - }); - - it('Takes out a 500 USDC flashloan with mode = 0, does not return the funds. (revert expected)', async () => { - const { usdc, pool, users } = testEnv; - const caller = users[2]; - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [2], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(VL_COLLATERAL_BALANCE_IS_0); - }); - - it('Caller deposits 5 WETH as collateral, Takes a USDC flashloan with mode = 2, does not return the funds. A loan for caller is created', async () => { - const { usdc, pool, weth, users, helpersContract } = testEnv; - - const caller = users[2]; - - await weth.connect(caller.signer).mint(await convertToCurrencyDecimals(weth.address, '5')); - - await weth.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(weth.address, '5'); - - await pool.connect(caller.signer).deposit(weth.address, amountToDeposit, caller.address, '0'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - const flashloanAmount = await convertToCurrencyDecimals(usdc.address, '500'); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [usdc.address], - [flashloanAmount], - [2], - caller.address, - '0x10', - '0' - ); - const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - usdc.address - ); - - const usdcDebtToken = await getVariableDebtToken(variableDebtTokenAddress); - - const callerDebt = await usdcDebtToken.balanceOf(caller.address); - - expect(callerDebt.toString()).to.be.equal('500000000', 'Invalid user debt'); - }); - - it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => { - const { dai, pool, weth, users } = testEnv; - const caller = users[3]; - - await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); - - const flashAmount = ethers.utils.parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(false); - await _mockFlashLoanReceiver.setAmountToApprove(flashAmount.div(2)); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [0], - caller.address, - '0x10', - '0' - ) - ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); - }); - - it('Caller takes a WETH flashloan with mode = 1', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[3]; - - const flashAmount = ethers.utils.parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [1], - caller.address, - '0x10', - '0' - ); - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); - - const callerDebt = await wethDebtToken.balanceOf(caller.address); - - expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); - }); - - it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[5]; - const onBehalfOf = users[4]; - - // Deposit 1000 dai for onBehalfOf user - await dai.connect(onBehalfOf.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); - - await dai.connect(onBehalfOf.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); - - const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); - - await pool - .connect(onBehalfOf.signer) - .deposit(dai.address, amountToDeposit, onBehalfOf.address, '0'); - - const flashAmount = ethers.utils.parseEther('0.8'); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await expect( - pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [1], - onBehalfOf.address, - '0x10', - '0' - ) - ).to.be.revertedWith(LP_BORROW_ALLOWANCE_NOT_ENOUGH); - }); - - it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. A loan for onBehalfOf is creatd.', async () => { - const { dai, pool, weth, users, helpersContract } = testEnv; - - const caller = users[5]; - const onBehalfOf = users[4]; - - const flashAmount = ethers.utils.parseEther('0.8'); - - const reserveData = await pool.getReserveData(weth.address); - - const stableDebtToken = await getStableDebtToken(reserveData.stableDebtTokenAddress); - - // Deposited for onBehalfOf user already, delegate borrow allowance - await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, flashAmount); - - await _mockFlashLoanReceiver.setFailExecutionTransfer(true); - - await pool - .connect(caller.signer) - .flashLoan( - _mockFlashLoanReceiver.address, - [weth.address], - [flashAmount], - [1], - onBehalfOf.address, - '0x10', - '0' - ); - - const { stableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( - weth.address - ); - - const wethDebtToken = await getStableDebtToken(stableDebtTokenAddress); - - const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); - - expect(onBehalfOfDebt.toString()).to.be.equal( - '800000000000000000', - 'Invalid onBehalfOf user debt' - ); - }); -}); diff --git a/test-suites/test-aave/flashloan.spec.ts b/test-suites/test-aave/flashloan.spec.ts index 57c74a49..963d0961 100644 --- a/test-suites/test-aave/flashloan.spec.ts +++ b/test-suites/test-aave/flashloan.spec.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js'; import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, oneRay } from '../../helpers/constants'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, oneRay } from '../../helpers/constants'; import { convertToCurrencyDecimals, getContract } from '../../helpers/contracts-helpers'; import { ethers } from 'ethers'; import { MockFlashLoanReceiver } from '../../types/MockFlashLoanReceiver'; @@ -31,8 +31,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); }); - it('Deposits WETH into the reserve', async () => { - const { pool, weth } = testEnv; + it('Deposits WETH and AAVE into the reserve', async () => { + const { pool, weth, aave } = testEnv; const userAddress = await pool.signer.getAddress(); const amountToDeposit = ethers.utils.parseEther('1'); @@ -41,15 +41,30 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await weth.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); await pool.deposit(weth.address, amountToDeposit, userAddress, '0'); + + await aave.mint(amountToDeposit); + + await aave.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool.deposit(aave.address, amountToDeposit, userAddress, '0'); }); - it('Takes WETH flashloan with mode = 0, returns the funds correctly', async () => { + it('Takes WETH flash loan with mode = 0, returns the funds correctly', async () => { const { pool, helpersContract, weth } = testEnv; + const flashBorrowedAmount = ethers.utils.parseEther('0.8'); + const fees = new BigNumber(flashBorrowedAmount.mul(9).div(10000).toString()); + + let reserveData = await helpersContract.getReserveData(weth.address); + + const totalLiquidityBefore = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + await pool.flashLoan( _mockFlashLoanReceiver.address, [weth.address], - [ethers.utils.parseEther('0.8')], + [flashBorrowedAmount], [0], _mockFlashLoanReceiver.address, '0x10', @@ -58,19 +73,63 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { ethers.utils.parseUnits('10000'); - const reserveData = await helpersContract.getReserveData(weth.address); + reserveData = await helpersContract.getReserveData(weth.address); const currentLiquidityRate = reserveData.liquidityRate; const currentLiquidityIndex = reserveData.liquidityIndex; - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + const totalLiquidityAfter = new BigNumber(reserveData.availableLiquidity.toString()) .plus(reserveData.totalStableDebt.toString()) .plus(reserveData.totalVariableDebt.toString()); - expect(totalLiquidity.toString()).to.be.equal('1000720000000000000'); + expect(totalLiquidityBefore.plus(fees).toString()).to.be.equal(totalLiquidityAfter.toString()); expect(currentLiquidityRate.toString()).to.be.equal('0'); expect(currentLiquidityIndex.toString()).to.be.equal('1000720000000000000000000000'); }); + it('Takes an authorized AAVE flash loan with mode = 0, returns the funds correctly', async () => { + const { + pool, + helpersContract, + aave, + configurator, + users: [, , , authorizedUser], + } = testEnv; + await configurator.authorizeFlashBorrower(authorizedUser.address); + + const flashBorrowedAmount = ethers.utils.parseEther('0.8'); + const fees = new BigNumber(0); + + let reserveData = await helpersContract.getReserveData(aave.address); + + const totalLiquidityBefore = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + await pool + .connect(authorizedUser.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [aave.address], + [flashBorrowedAmount], + [0], + _mockFlashLoanReceiver.address, + '0x10', + '0' + ); + + ethers.utils.parseUnits('10000'); + + reserveData = await helpersContract.getReserveData(aave.address); + + const currentLiquidityRate = reserveData.liquidityRate; + const currentLiquidityIndex = reserveData.liquidityIndex; + + const totalLiquidityAfter = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidityBefore.plus(fees).toString()).to.be.equal(totalLiquidityAfter.toString()); + }); it('Takes an ETH flashloan with mode = 0 as big as the available liquidity', async () => { const { pool, helpersContract, weth } = testEnv; @@ -179,6 +238,12 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await _mockFlashLoanReceiver.setFailExecutionTransfer(false); + let reserveData = await helpersContract.getReserveData(weth.address); + + let totalLiquidityBefore = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + await pool .connect(caller.signer) .flashLoan( @@ -197,14 +262,14 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const fees = borrowedAmount.mul(9).div(10000); - const reserveData = await helpersContract.getReserveData(weth.address); + reserveData = await helpersContract.getReserveData(weth.address); - const totalLiquidity = new BigNumber(reserveData.availableLiquidity.toString()) + const totalLiquidityAfter = new BigNumber(reserveData.availableLiquidity.toString()) .plus(reserveData.totalStableDebt.toString()) .plus(reserveData.totalVariableDebt.toString()); - expect(totalLiquidity.toString()).to.be.equal( - ethers.BigNumber.from('1001620648000000000').add(fees) + expect(totalLiquidityAfter.toString()).to.be.equal( + ethers.BigNumber.from(totalLiquidityBefore.toString()).add(fees) ); const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); @@ -212,6 +277,72 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const callerDebt = await wethDebtToken.balanceOf(caller.address); expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); + + // repays debt for later, so no interest accrue + await weth.connect(caller.signer).mint(await convertToCurrencyDecimals(weth.address, '1000')); + await weth.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(caller.signer).repay(weth.address, MAX_UINT_AMOUNT, 2, caller.address); + }); + it('Authorized borrower deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { + const { + dai, + pool, + weth, + users: [, , , authorizedUser], + helpersContract, + } = testEnv; + + const caller = authorizedUser; + + await dai.connect(caller.signer).mint(await convertToCurrencyDecimals(dai.address, '1000')); + + await dai.connect(caller.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await pool.connect(caller.signer).deposit(dai.address, amountToDeposit, caller.address, '0'); + + const borrowedAmount = await convertToCurrencyDecimals(weth.address, '0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + let reserveData = await helpersContract.getReserveData(weth.address); + + let totalLiquidityBefore = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + await pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [borrowedAmount], + [2], + caller.address, + '0x10', + '0' + ); + const { variableDebtTokenAddress } = await helpersContract.getReserveTokensAddresses( + weth.address + ); + ethers.utils.parseUnits('10000'); + + const fees = 0; + + reserveData = await helpersContract.getReserveData(weth.address); + + let totalLiquidityAfter = new BigNumber(reserveData.availableLiquidity.toString()) + .plus(reserveData.totalStableDebt.toString()) + .plus(reserveData.totalVariableDebt.toString()); + + expect(totalLiquidityAfter.toString()).to.be.equal(totalLiquidityBefore.toString()); + + const wethDebtToken = await getVariableDebtToken(variableDebtTokenAddress); + + const callerDebt = await wethDebtToken.balanceOf(caller.address); + + expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt'); }); it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => {