initial refactoring of liquidation-atoken.spec

This commit is contained in:
andyk 2020-06-18 17:36:37 +03:00
parent 9e76bcf765
commit d1f21118c1
4 changed files with 419 additions and 545 deletions

View File

@ -58,6 +58,10 @@ export enum ProtocolErrors {
INCONSISTENT_PROTOCOL_BALANCE = "The actual balance of the protocol is inconsistent", INCONSISTENT_PROTOCOL_BALANCE = "The actual balance of the protocol is inconsistent",
TOO_SMALL_FLASH_LOAN = "The requested amount is too small for a flashLoan.", TOO_SMALL_FLASH_LOAN = "The requested amount is too small for a flashLoan.",
NOT_ENOUGH_LIQUIDITY_TO_BORROW = "There is not enough liquidity available to borrow", NOT_ENOUGH_LIQUIDITY_TO_BORROW = "There is not enough liquidity available to borrow",
HF_IS_NOT_BELLOW_THRESHOLD = "Health factor is not below the threshold",
INVALID_HF = "Invalid health factor",
USER_DID_NOT_BORROW_SPECIFIED = "User did not borrow the specified currency",
INVALID_COLLATERAL_TO_LIQUIDATE = "Invalid collateral to liquidate",
} }
export type tEthereumAddress = string; export type tEthereumAddress = string;

View File

@ -63,6 +63,7 @@ import {MockAggregator} from "../types/MockAggregator";
import {LendingRateOracle} from "../types/LendingRateOracle"; import {LendingRateOracle} from "../types/LendingRateOracle";
import {LendingPoolCore} from "../types/LendingPoolCore"; import {LendingPoolCore} from "../types/LendingPoolCore";
import {LendingPoolConfigurator} from "../types/LendingPoolConfigurator"; import {LendingPoolConfigurator} from "../types/LendingPoolConfigurator";
import { initializeMakeSuite } from './helpers/make-suite';
const deployAllMockTokens = async (deployer: Signer) => { const deployAllMockTokens = async (deployer: Signer) => {
const tokens: {[symbol: string]: MockContract | MintableErc20} = {}; const tokens: {[symbol: string]: MockContract | MintableErc20} = {};
@ -642,6 +643,7 @@ before(async () => {
const [deployer, secondaryWallet] = await getEthersSigners(); const [deployer, secondaryWallet] = await getEthersSigners();
console.log("-> Deploying test environment..."); console.log("-> Deploying test environment...");
await buildTestEnv(deployer, secondaryWallet); await buildTestEnv(deployer, secondaryWallet);
await initializeMakeSuite();
console.log("\n***************"); console.log("\n***************");
console.log("Setup and snapshot finished"); console.log("Setup and snapshot finished");
console.log("***************\n"); console.log("***************\n");

View File

@ -1,5 +1,4 @@
import {evmRevert, evmSnapshot, BRE} from "../../helpers/misc-utils"; import {evmRevert, evmSnapshot, BRE} from "../../helpers/misc-utils";
import {TEST_SNAPSHOT_ID} from "../../helpers/constants";
import {Signer} from "ethers"; import {Signer} from "ethers";
import { import {
getEthersSigners, getEthersSigners,
@ -9,8 +8,8 @@ import {
getAaveProtocolTestHelpers, getAaveProtocolTestHelpers,
getAToken, getAToken,
getMintableErc20, getMintableErc20,
getLendingPoolConfiguratorProxy, getLendingPoolConfiguratorProxy, getPriceOracle,
} from "../../helpers/contracts-helpers"; } from '../../helpers/contracts-helpers';
import {tEthereumAddress} from "../../helpers/types"; import {tEthereumAddress} from "../../helpers/types";
import {LendingPool} from "../../types/LendingPool"; import {LendingPool} from "../../types/LendingPool";
import {LendingPoolCore} from "../../types/LendingPoolCore"; import {LendingPoolCore} from "../../types/LendingPoolCore";
@ -23,6 +22,7 @@ import {LendingPoolConfigurator} from "../../types/LendingPoolConfigurator";
import chai from "chai"; import chai from "chai";
// @ts-ignore // @ts-ignore
import bignumberChai from "chai-bignumber"; import bignumberChai from "chai-bignumber";
import { PriceOracle } from '../../types/PriceOracle';
chai.use(bignumberChai()); chai.use(bignumberChai());
export interface SignerWithAddress { export interface SignerWithAddress {
@ -36,9 +36,11 @@ export interface TestEnv {
core: LendingPoolCore; core: LendingPoolCore;
configurator: LendingPoolConfigurator; configurator: LendingPoolConfigurator;
addressesProvider: LendingPoolAddressesProvider; addressesProvider: LendingPoolAddressesProvider;
oracle: PriceOracle;
helpersContract: AaveProtocolTestHelpers; helpersContract: AaveProtocolTestHelpers;
dai: MintableErc20; dai: MintableErc20;
aDai: AToken; aDai: AToken;
usdc: MintableErc20;
} }
let buidlerevmSnapshotId: string = "0x1"; let buidlerevmSnapshotId: string = "0x1";
@ -48,9 +50,7 @@ const setBuidlerevmSnapshotId = (id: string) => {
} }
}; };
export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) { const testEnv: TestEnv = {
describe(name, () => {
const testEnv: TestEnv = {
deployer: {} as SignerWithAddress, deployer: {} as SignerWithAddress,
users: [] as SignerWithAddress[], users: [] as SignerWithAddress[],
pool: {} as LendingPool, pool: {} as LendingPool,
@ -58,12 +58,13 @@ export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) {
configurator: {} as LendingPoolConfigurator, configurator: {} as LendingPoolConfigurator,
addressesProvider: {} as LendingPoolAddressesProvider, addressesProvider: {} as LendingPoolAddressesProvider,
helpersContract: {} as AaveProtocolTestHelpers, helpersContract: {} as AaveProtocolTestHelpers,
oracle: {} as PriceOracle,
dai: {} as MintableErc20, dai: {} as MintableErc20,
aDai: {} as AToken, aDai: {} as AToken,
} as TestEnv; usdc: {} as MintableErc20,
before(async () => { } as TestEnv;
console.time("makeSuite");
setBuidlerevmSnapshotId(await evmSnapshot()); export async function initializeMakeSuite() {
const [_deployer, ...restSigners] = await getEthersSigners(); const [_deployer, ...restSigners] = await getEthersSigners();
const deployer: SignerWithAddress = { const deployer: SignerWithAddress = {
address: await _deployer.getAddress(), address: await _deployer.getAddress(),
@ -80,27 +81,34 @@ export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) {
testEnv.pool = await getLendingPool(); testEnv.pool = await getLendingPool();
testEnv.core = await getLendingPoolCore(); testEnv.core = await getLendingPoolCore();
testEnv.configurator = await getLendingPoolConfiguratorProxy(); testEnv.configurator = await getLendingPoolConfiguratorProxy();
testEnv.oracle = await getPriceOracle();
testEnv.addressesProvider = await getLendingPoolAddressesProvider(); testEnv.addressesProvider = await getLendingPoolAddressesProvider();
testEnv.helpersContract = await getAaveProtocolTestHelpers(); testEnv.helpersContract = await getAaveProtocolTestHelpers();
const aDaiAddress = (await testEnv.helpersContract.getAllATokens()).find( const aDaiAddress = (await testEnv.helpersContract.getAllATokens()).find(
(aToken) => aToken.symbol === "aDAI" (aToken) => aToken.symbol === "aDAI"
)?.tokenAddress; )?.tokenAddress;
const daiAddress = ( const reservesTokens = await testEnv.helpersContract.getAllReservesTokens();
await await testEnv.helpersContract.getAllReservesTokens() const daiAddress = reservesTokens.find(token => token.symbol === "DAI")?.tokenAddress;
).find((token) => token.symbol === "DAI")?.tokenAddress; const usdcAddress = reservesTokens.find(token => token.symbol === "USDC")?.tokenAddress;
if (!aDaiAddress) { if (!aDaiAddress) {
console.log(`atoken-modifiers.spec: aDAI not correctly initialized`); console.log(`atoken-modifiers.spec: aDAI not correctly initialized`);
process.exit(1); process.exit(1);
} }
if (!daiAddress) { if (!daiAddress || !usdcAddress) {
console.log(`atoken-modifiers.spec: DAI not correctly initialized`); console.log(`atoken-modifiers.spec: USDC or DAI not correctly initialized`);
process.exit(1); process.exit(1);
} }
testEnv.aDai = await getAToken(aDaiAddress); testEnv.aDai = await getAToken(aDaiAddress);
testEnv.dai = await getMintableErc20(daiAddress); testEnv.dai = await getMintableErc20(daiAddress);
console.timeEnd("makeSuite"); testEnv.usdc = await getMintableErc20(usdcAddress);
}
export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) {
describe(name, () => {
before(async () => {
setBuidlerevmSnapshotId(await evmSnapshot());
}); });
tests(testEnv); tests(testEnv);
after(async () => { after(async () => {

View File

@ -1,493 +1,353 @@
// import { import BigNumber from 'bignumber.js';
// LendingPoolInstance,
// LendingPoolCoreInstance, import {BRE} from '../helpers/misc-utils';
// IPriceOracleInstance, import {APPROVAL_AMOUNT_LENDING_POOL_CORE, MOCK_ETH_ADDRESS, oneEther} from '../helpers/constants';
// ATokenInstance, import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
// LendingPoolAddressesProviderInstance, import {makeSuite} from './helpers/make-suite';
// MintableERC20Instance, import {ProtocolErrors, RateMode} from '../helpers/types';
// } from '../utils/typechain-types/truffle-contracts';
// import { const {expect} = require('chai');
// ContractId,
// IReserveParams, makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => {
// iATokenBase, const {
// iAavePoolAssets, HF_IS_NOT_BELLOW_THRESHOLD,
// iAssetsWithoutETH, INVALID_HF,
// ITestEnvWithoutInstances, USER_DID_NOT_BORROW_SPECIFIED,
// RateMode, INVALID_COLLATERAL_TO_LIQUIDATE,
// } from '../utils/types'; } = ProtocolErrors;
// import BigNumber from 'bignumber.js';
// import { it('LIQUIDATION - Deposits ETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => {
// APPROVAL_AMOUNT_LENDING_POOL_CORE, const {dai, users, core, pool, oracle} = testEnv;
// oneEther, const depositor = users[0];
// ETHEREUM_ADDRESS, const borrower = users[1];
// } from '../utils/constants';
// import {testEnvProviderWithoutInstances} from '../utils/truffle/dlp-tests-env'; //mints DAI to depositor
// import {convertToCurrencyDecimals} from '../utils/misc-utils'; await dai.connect(depositor.signer).mint(await convertToCurrencyDecimals(dai.address, '1000'));
// import {getTruffleContractInstance} from '../utils/truffle/truffle-core-utils';
//approve protocol to access depositor wallet
// const expectRevert = require('@openzeppelin/test-helpers').expectRevert; await dai.connect(depositor.signer).approve(core.address, APPROVAL_AMOUNT_LENDING_POOL_CORE);
// const {expect} = require('chai'); //user 1 deposits 1000 DAI
const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000');
// const almostEqual: any = function(this: any, expected: any, actual: any): any { await pool.connect(depositor.signer).deposit(dai.address, amountDAItoDeposit, '0');
// this.assert(
// expected.plus(new BigNumber(1)).eq(actual) || //user 2 deposits 1 ETH
// expected.plus(new BigNumber(2)).eq(actual) || const amountETHtoDeposit = await convertToCurrencyDecimals(MOCK_ETH_ADDRESS, '1');
// actual.plus(new BigNumber(1)).eq(expected) || await pool
// actual.plus(new BigNumber(2)).eq(expected) || .connect(borrower.signer)
// expected.eq(actual), .deposit(MOCK_ETH_ADDRESS, amountETHtoDeposit, '0', {value: amountETHtoDeposit});
// 'expected #{act} to be almost equal #{exp}',
// 'expected #{act} to be different from #{exp}', await pool.connect(borrower.signer).deposit(MOCK_ETH_ADDRESS, amountETHtoDeposit, '0', {
// expected.toString(), value: amountETHtoDeposit,
// actual.toString() });
// );
// }; //user 2 borrows
// require('chai').use(function(chai: any, utils: any) { const userGlobalData = await pool.getUserAccountData(borrower.address);
// chai.Assertion.overwriteMethod('almostEqual', function(original: any) { const daiPrice = await oracle.getAssetPrice(dai.address);
// return function(this: any, value: any) {
// if (utils.flag(this, 'bignumber')) { const amountDAIToBorrow = await convertToCurrencyDecimals(
// var expected = new BigNumber(value); dai.address,
// var actual = new BigNumber(this._obj); new BigNumber(userGlobalData.availableBorrowsETH.toString())
// almostEqual.apply(this, [expected, actual]); .div(daiPrice.toString())
// } else { .multipliedBy(0.95)
// original.apply(this, arguments); .toFixed(0)
// } );
// };
// }); await pool
// }); .connect(borrower.signer)
.borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0');
// contract('LendingPool liquidation - liquidator receiving aToken', async ([deployer, ...users]) => {
// let _testEnvProvider: ITestEnvWithoutInstances; const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
// let _lendingPoolInstance: LendingPoolInstance; console.log('userGlobalDataAfter.healthFactor', userGlobalDataAfter.healthFactor.toString());
// let _lendingPoolCoreInstance: LendingPoolCoreInstance;
// let _lendingPoolAddressesProviderInstance: LendingPoolAddressesProviderInstance; expect(userGlobalDataAfter.currentLiquidationThreshold).to.be.bignumber.equal(
// let _priceOracleInstance: IPriceOracleInstance; '80',
// let _aTokenInstances: iATokenBase<ATokenInstance>; 'Invalid liquidation threshold'
// let _tokenInstances: iAssetsWithoutETH<MintableERC20Instance>; );
// let _daiAddress: string; //someone tries to liquidate user 2
await expect(
// let _reservesParams: iAavePoolAssets<IReserveParams>; pool.liquidationCall(MOCK_ETH_ADDRESS, dai.address, borrower.address, 1, true)
).to.be.revertedWith(HF_IS_NOT_BELLOW_THRESHOLD);
// let _depositorAddress: string; });
// let _borrowerAddress: string;
it('LIQUIDATION - Drop the health factor below 1', async () => {
// let _web3: Web3; const {dai, users, pool, oracle} = testEnv;
const borrower = users[1];
// let _initialDepositorETHBalance: string;
const daiPrice = await oracle.getAssetPrice(dai.address);
// before('Initializing LendingPool test variables', async () => {
// console.time('setup-test'); //halving the price of ETH - means doubling the DAIETH exchange rate
// _testEnvProvider = await testEnvProviderWithoutInstances(artifacts, [deployer, ...users]); console.log('DAI price before', daiPrice.toString());
// const { await oracle.setAssetPrice(
// getWeb3, dai.address,
// getAllAssetsInstances, new BigNumber(daiPrice.toString()).multipliedBy(1.15).toFixed(0)
// getFirstBorrowerAddressOnTests, );
// getFirstDepositorAddressOnTests, console.log('DAI price after', (await oracle.getAssetPrice(dai.address)).toString());
// getAavePoolReservesParams,
// getLendingPoolInstance, const userGlobalData = await pool.getUserAccountData(borrower.address);
// getLendingPoolCoreInstance,
// getPriceOracleInstance, expect(userGlobalData.healthFactor).to.be.bignumber.lt(oneEther.toFixed(0), INVALID_HF);
// getATokenInstances, });
// getLendingPoolAddressesProviderInstance,
// } = _testEnvProvider; it('LIQUIDATION - Tries to liquidate a different currency than the loan principal', async () => {
const {pool, users} = testEnv;
// const instances = await Promise.all([ const borrower = users[1];
// getLendingPoolInstance(), //user 2 tries to borrow
// getLendingPoolCoreInstance(), await expect(
// getPriceOracleInstance(), pool.liquidationCall(
// getATokenInstances(), MOCK_ETH_ADDRESS,
// getLendingPoolAddressesProviderInstance(), MOCK_ETH_ADDRESS,
// getAllAssetsInstances(), borrower.address,
// ]); oneEther.toString(),
true
// _reservesParams = await getAavePoolReservesParams(); )
// _lendingPoolInstance = instances[0]; ).revertedWith(USER_DID_NOT_BORROW_SPECIFIED);
// _lendingPoolCoreInstance = instances[1]; });
// _priceOracleInstance = instances[2];
// _aTokenInstances = instances[3]; it(
// _lendingPoolAddressesProviderInstance = instances[4]; 'LIQUIDATION - Tries to liquidate a different ' + 'collateral than the borrower collateral',
// _tokenInstances = instances[5]; async () => {
// _daiAddress = _tokenInstances.DAI.address; const {pool, dai, users} = testEnv;
// _depositorAddress = await getFirstDepositorAddressOnTests(); const borrower = users[1];
// _borrowerAddress = await getFirstBorrowerAddressOnTests();
await expect(
// _web3 = await getWeb3(); pool.liquidationCall(dai.address, dai.address, borrower.address, oneEther.toString(), true)
// _initialDepositorETHBalance = await _web3.eth.getBalance(_depositorAddress); ).revertedWith(INVALID_COLLATERAL_TO_LIQUIDATE);
// console.timeEnd('setup-test'); }
// }); );
// it('LIQUIDATION - Deposits ETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => { it('LIQUIDATION - Liquidates the borrow', async () => {
// const {DAI: daiInstance} = _tokenInstances; const {pool, dai, core, users, addressesProvider, oracle} = testEnv;
const borrower = users[1];
// const aEthInstance: ATokenInstance = await getTruffleContractInstance(
// artifacts, //mints dai to the caller
// ContractId.AToken,
// await _lendingPoolCoreInstance.getReserveATokenAddress(ETHEREUM_ADDRESS) await dai.mint(await convertToCurrencyDecimals(dai.address, '1000'));
// );
//approve protocol to access depositor wallet
// //mints DAI to depositor await dai.approve(core.address, APPROVAL_AMOUNT_LENDING_POOL_CORE);
// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, '1000'), {
// from: _depositorAddress, const userReserveDataBefore = await pool.getUserReserveData(dai.address, borrower.address);
// });
const daiReserveDataBefore = await pool.getReserveData(dai.address);
// //approve protocol to access depositor wallet const ethReserveDataBefore = await pool.getReserveData(MOCK_ETH_ADDRESS);
// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE, {
// from: _depositorAddress, const amountToLiquidate = new BigNumber(userReserveDataBefore.currentBorrowBalance.toString())
// }); .div(2)
.toFixed(0);
// //user 1 deposits 1000 DAI
// const amountDAItoDeposit = await convertToCurrencyDecimals(_daiAddress, '1000'); await pool.liquidationCall(
MOCK_ETH_ADDRESS,
// await _lendingPoolInstance.deposit(_daiAddress, amountDAItoDeposit, '0', { dai.address,
// from: _depositorAddress, borrower.address,
// }); amountToLiquidate,
true
// //user 2 deposits 1 ETH );
// const amountETHtoDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, '1');
const userReserveDataAfter = await pool.getUserReserveData(dai.address, borrower.address);
// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHtoDeposit, '0', {
// from: _borrowerAddress, const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
// value: amountETHtoDeposit,
// }); const daiReserveDataAfter = await pool.getReserveData(dai.address);
const ethReserveDataAfter = await pool.getReserveData(MOCK_ETH_ADDRESS);
// //user 2 borrows
const feeAddress = await addressesProvider.getTokenDistributor();
// const userGlobalData: any = await _lendingPoolInstance.getUserAccountData(_borrowerAddress);
// const daiPrice = await _priceOracleInstance.getAssetPrice(_daiAddress); const feeAddressBalance = await BRE.ethers.provider.getBalance(feeAddress);
// const amountDAIToBorrow = await convertToCurrencyDecimals( const collateralPrice = (await oracle.getAssetPrice(MOCK_ETH_ADDRESS)).toString();
// _daiAddress, const principalPrice = (await oracle.getAssetPrice(dai.address)).toString();
// new BigNumber(userGlobalData.availableBorrowsETH)
// .div(daiPrice) const collateralDecimals = (await core.getReserveDecimals(MOCK_ETH_ADDRESS)).toString();
// .multipliedBy(0.95) const principalDecimals = (await core.getReserveDecimals(dai.address)).toString();
// .toFixed(0)
// ); const expectedCollateralLiquidated = new BigNumber(principalPrice)
.times(new BigNumber(amountToLiquidate).times(105))
// await _lendingPoolInstance.borrow(_daiAddress, amountDAIToBorrow, RateMode.Stable, '0', { .times(new BigNumber(10).pow(collateralDecimals))
// from: _borrowerAddress, .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// }); .decimalPlaces(0, BigNumber.ROUND_DOWN);
// const userGlobalDataAfter: any = await _lendingPoolInstance.getUserAccountData( const expectedFeeLiquidated = new BigNumber(principalPrice)
// _borrowerAddress .times(new BigNumber(userReserveDataBefore.originationFee.toString()).times(105))
// ); .times(new BigNumber(10).pow(collateralDecimals))
.div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// expect(userGlobalDataAfter.currentLiquidationThreshold).to.be.bignumber.equal( .div(100)
// '80', .decimalPlaces(0, BigNumber.ROUND_DOWN);
// 'Invalid liquidation threshold'
// ); expect(userGlobalDataAfter.healthFactor).to.be.bignumber.gt(
oneEther.toFixed(0),
// //user 2 tries to borrow 'Invalid health factor'
// await expectRevert( );
// _lendingPoolInstance.liquidationCall(
// ETHEREUM_ADDRESS, expect(userReserveDataAfter.originationFee).to.be.bignumber.eq(
// _daiAddress, '0',
// _borrowerAddress, 'Origination fee should be repaid'
// amountDAIToBorrow, );
// true
// ), expect(feeAddressBalance).to.be.bignumber.gt('0');
// 'Health factor is not below the threshold'
// ); expect(userReserveDataAfter.principalBorrowBalance).to.be.bignumber.almostEqual(
// }); new BigNumber(userReserveDataBefore.currentBorrowBalance.toString())
.minus(amountToLiquidate)
// it('LIQUIDATION - Drop the health factor below 1', async () => { .toFixed(0),
// const daiPrice = await _priceOracleInstance.getAssetPrice(_daiAddress); 'Invalid user borrow balance after liquidation'
);
// //halving the price of ETH - means doubling the DAIETH exchange rate
expect(daiReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// await _priceOracleInstance.setAssetPrice( new BigNumber(daiReserveDataBefore.availableLiquidity.toString())
// _daiAddress, .plus(amountToLiquidate)
// new BigNumber(daiPrice).multipliedBy(1.15).toFixed(0) .toFixed(0),
// ); 'Invalid principal available liquidity'
);
// const userGlobalData: any = await _lendingPoolInstance.getUserAccountData(_borrowerAddress);
expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// expect(userGlobalData.healthFactor).to.be.bignumber.lt( new BigNumber(ethReserveDataBefore.availableLiquidity.toString())
// oneEther.toFixed(0), .minus(expectedFeeLiquidated)
// 'Invalid health factor' .toFixed(0),
// ); 'Invalid collateral available liquidity'
// }); );
});
// it('LIQUIDATION - Tries to liquidate a different currency than the loan principal', async () => {
// //user 2 tries to borrow it(
// await expectRevert( 'User 3 deposits 1000 USDC, user 4 1 ETH,' +
// _lendingPoolInstance.liquidationCall( ' user 4 borrows - drops HF, liquidates the borrow',
// ETHEREUM_ADDRESS, async () => {
// ETHEREUM_ADDRESS, const {users, core, pool, usdc, oracle, addressesProvider} = testEnv;
// _borrowerAddress, const depositor = users[3];
// oneEther, const borrower = users[4];
// true //mints USDC to depositor
// ), await usdc
// 'User did not borrow the specified currency' .connect(depositor.signer)
// ); .mint(await convertToCurrencyDecimals(usdc.address, '1000'));
// });
//approve protocol to access depositor wallet
// it('LIQUIDATION - Tries to liquidate a different collateral than the borrower collateral', async () => { await usdc.connect(depositor.signer).approve(core.address, APPROVAL_AMOUNT_LENDING_POOL_CORE);
// //user 2 tries to borrow
// await expectRevert( //user 3 deposits 1000 USDC
// _lendingPoolInstance.liquidationCall( const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000');
// _daiAddress,
// _daiAddress, await pool.connect(depositor.signer).deposit(usdc.address, amountUSDCtoDeposit, '0');
// _borrowerAddress,
// oneEther, //user 4 deposits 1 ETH
// true const amountETHtoDeposit = await convertToCurrencyDecimals(MOCK_ETH_ADDRESS, '1');
// ),
// 'Invalid collateral to liquidate' await pool.connect(borrower.signer).deposit(MOCK_ETH_ADDRESS, amountETHtoDeposit, '0', {
// ); value: amountETHtoDeposit,
// }); });
// it('LIQUIDATION - Liquidates the borrow', async () => { //user 4 borrows
// const {DAI: daiInstance} = _tokenInstances; const userGlobalData = await pool.getUserAccountData(borrower.address);
// //mints dai to the caller const usdcPrice = await oracle.getAssetPrice(usdc.address);
// await daiInstance.mint(await convertToCurrencyDecimals(daiInstance.address, '1000')); const amountUSDCToBorrow = await convertToCurrencyDecimals(
usdc.address,
// //approve protocol to access depositor wallet new BigNumber(userGlobalData.availableBorrowsETH.toString())
// await daiInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE); .div(usdcPrice.toString())
.multipliedBy(0.95)
// const userReserveDataBefore: any = await _lendingPoolInstance.getUserReserveData( .toFixed(0)
// _daiAddress, );
// _borrowerAddress
// ); await pool
.connect(borrower.signer)
// const daiReserveDataBefore: any = await _lendingPoolInstance.getReserveData(_daiAddress); .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0');
// const ethReserveDataBefore: any = await _lendingPoolInstance.getReserveData(ETHEREUM_ADDRESS);
//drops HF below 1
// const amountToLiquidate = new BigNumber(userReserveDataBefore.currentBorrowBalance)
// .div(2) await oracle.setAssetPrice(
// .toFixed(0); usdc.address,
new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0)
// await _lendingPoolInstance.liquidationCall( );
// ETHEREUM_ADDRESS,
// _daiAddress, //mints dai to the liquidator
// _borrowerAddress,
// amountToLiquidate, await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000'));
// true
// ); //approve protocol to access depositor wallet
await usdc.approve(core.address, APPROVAL_AMOUNT_LENDING_POOL_CORE);
// const userReserveDataAfter: any = await _lendingPoolInstance.getUserReserveData(
// _daiAddress, const userReserveDataBefore = await pool.getUserReserveData(usdc.address, borrower.address);
// _borrowerAddress
// ); const usdcReserveDataBefore = await pool.getReserveData(usdc.address);
const ethReserveDataBefore = await pool.getReserveData(MOCK_ETH_ADDRESS);
// const userGlobalDataAfter: any = await _lendingPoolInstance.getUserAccountData(
// _borrowerAddress const amountToLiquidate = new BigNumber(userReserveDataBefore.currentBorrowBalance.toString())
// ); .div(2)
.toFixed(0);
// const daiReserveDataAfter: any = await _lendingPoolInstance.getReserveData(_daiAddress);
// const ethReserveDataAfter: any = await _lendingPoolInstance.getReserveData(ETHEREUM_ADDRESS); await pool.liquidationCall(
MOCK_ETH_ADDRESS,
// const feeAddress = await _lendingPoolAddressesProviderInstance.getTokenDistributor(); usdc.address,
borrower.address,
// const feeAddressBalance = await web3.eth.getBalance(feeAddress); amountToLiquidate,
true
// const collateralPrice = await _priceOracleInstance.getAssetPrice(ETHEREUM_ADDRESS); );
// const principalPrice = await _priceOracleInstance.getAssetPrice(_daiAddress);
const userReserveDataAfter = await pool.getUserReserveData(usdc.address, borrower.address);
// const collateralDecimals = await _lendingPoolCoreInstance.getReserveDecimals(ETHEREUM_ADDRESS);
// const principalDecimals = await _lendingPoolCoreInstance.getReserveDecimals(_daiAddress); const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
// const expectedCollateralLiquidated = new BigNumber(principalPrice) const usdcReserveDataAfter = await pool.getReserveData(usdc.address);
// .times(new BigNumber(amountToLiquidate).times(105)) const ethReserveDataAfter = await pool.getReserveData(MOCK_ETH_ADDRESS);
// .times(new BigNumber(10).pow(collateralDecimals))
// .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals))) const feeAddress = await addressesProvider.getTokenDistributor();
// .decimalPlaces(0, BigNumber.ROUND_DOWN);
const feeAddressBalance = await BRE.ethers.provider.getBalance(feeAddress);
// const expectedFeeLiquidated = new BigNumber(principalPrice)
// .times(new BigNumber(userReserveDataBefore.originationFee).times(105)) const collateralPrice = (await oracle.getAssetPrice(MOCK_ETH_ADDRESS)).toString();
// .times(new BigNumber(10).pow(collateralDecimals)) const principalPrice = (await oracle.getAssetPrice(usdc.address)).toString();
// .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// .div(100) const collateralDecimals = (await core.getReserveDecimals(MOCK_ETH_ADDRESS)).toString();
// .decimalPlaces(0, BigNumber.ROUND_DOWN); const principalDecimals = (await core.getReserveDecimals(usdc.address)).toString();
// expect(userGlobalDataAfter.healthFactor).to.be.bignumber.gt( const expectedCollateralLiquidated = new BigNumber(principalPrice)
// oneEther.toFixed(0), .times(new BigNumber(amountToLiquidate).times(105))
// 'Invalid health factor' .times(new BigNumber(10).pow(collateralDecimals))
// ); .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
.decimalPlaces(0, BigNumber.ROUND_DOWN);
// expect(userReserveDataAfter.originationFee).to.be.bignumber.eq(
// '0', const expectedFeeLiquidated = new BigNumber(principalPrice)
// 'Origination fee should be repaid' .times(new BigNumber(userReserveDataBefore.originationFee.toString()).times(105))
// ); .times(new BigNumber(10).pow(collateralDecimals))
.div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// expect(feeAddressBalance).to.be.bignumber.gt('0'); .div(100)
.decimalPlaces(0, BigNumber.ROUND_DOWN);
// expect(userReserveDataAfter.principalBorrowBalance).to.be.bignumber.almostEqual(
// new BigNumber(userReserveDataBefore.currentBorrowBalance).minus(amountToLiquidate).toFixed(0), expect(userGlobalDataAfter.healthFactor).to.be.bignumber.gt(
// 'Invalid user borrow balance after liquidation' oneEther.toFixed(0),
// ); 'Invalid health factor'
);
// expect(daiReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// new BigNumber(daiReserveDataBefore.availableLiquidity).plus(amountToLiquidate).toFixed(0), expect(userReserveDataAfter.originationFee).to.be.bignumber.eq(
// 'Invalid principal available liquidity' '0',
// ); 'Origination fee should be repaid'
);
// expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// new BigNumber(ethReserveDataBefore.availableLiquidity) expect(feeAddressBalance).to.be.bignumber.gt('0');
// .minus(expectedFeeLiquidated)
// .toFixed(0), expect(userReserveDataAfter.principalBorrowBalance).to.be.bignumber.almostEqual(
// 'Invalid collateral available liquidity' new BigNumber(userReserveDataBefore.currentBorrowBalance.toString())
// ); .minus(amountToLiquidate)
// }); .toFixed(0),
'Invalid user borrow balance after liquidation'
// it('User 3 deposits 1000 USDC, user 4 1 ETH, user 4 borrows - drops HF, liquidates the borrow', async () => { );
// const {USDC: usdcInstance} = _tokenInstances;
expect(usdcReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// //mints USDC to depositor new BigNumber(usdcReserveDataBefore.availableLiquidity.toString())
// await usdcInstance.mint(await convertToCurrencyDecimals(usdcInstance.address, '1000'), { .plus(amountToLiquidate)
// from: users[3], .toFixed(0),
// }); 'Invalid principal available liquidity'
);
// //approve protocol to access depositor wallet
// await usdcInstance.approve( expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// _lendingPoolCoreInstance.address, new BigNumber(ethReserveDataBefore.availableLiquidity.toString())
// APPROVAL_AMOUNT_LENDING_POOL_CORE, .minus(expectedFeeLiquidated)
// { .toFixed(0),
// from: users[3], 'Invalid collateral available liquidity'
// } );
// ); }
);
// //user 3 deposits 1000 USDC });
// const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdcInstance.address, '1000');
// await _lendingPoolInstance.deposit(usdcInstance.address, amountUSDCtoDeposit, '0', {
// from: users[3],
// });
// //user 4 deposits 1 ETH
// const amountETHtoDeposit = await convertToCurrencyDecimals(ETHEREUM_ADDRESS, '1');
// await _lendingPoolInstance.deposit(ETHEREUM_ADDRESS, amountETHtoDeposit, '0', {
// from: users[4],
// value: amountETHtoDeposit,
// });
// //user 4 borrows
// const userGlobalData: any = await _lendingPoolInstance.getUserAccountData(users[4]);
// const usdcPrice = await _priceOracleInstance.getAssetPrice(usdcInstance.address);
// const amountUSDCToBorrow = await convertToCurrencyDecimals(
// usdcInstance.address,
// new BigNumber(userGlobalData.availableBorrowsETH)
// .div(usdcPrice)
// .multipliedBy(0.95)
// .toFixed(0)
// );
// await _lendingPoolInstance.borrow(
// usdcInstance.address,
// amountUSDCToBorrow,
// RateMode.Stable,
// '0',
// {
// from: users[4],
// }
// );
// //drops HF below 1
// await _priceOracleInstance.setAssetPrice(
// usdcInstance.address,
// new BigNumber(usdcPrice).multipliedBy(1.2).toFixed(0)
// );
// //mints dai to the liquidator
// await usdcInstance.mint(await convertToCurrencyDecimals(usdcInstance.address, '1000'));
// //approve protocol to access depositor wallet
// await usdcInstance.approve(_lendingPoolCoreInstance.address, APPROVAL_AMOUNT_LENDING_POOL_CORE);
// const userReserveDataBefore: any = await _lendingPoolInstance.getUserReserveData(
// usdcInstance.address,
// users[4]
// );
// const usdcReserveDataBefore: any = await _lendingPoolInstance.getReserveData(
// usdcInstance.address
// );
// const ethReserveDataBefore: any = await _lendingPoolInstance.getReserveData(ETHEREUM_ADDRESS);
// const amountToLiquidate = new BigNumber(userReserveDataBefore.currentBorrowBalance)
// .div(2)
// .toFixed(0);
// await _lendingPoolInstance.liquidationCall(
// ETHEREUM_ADDRESS,
// usdcInstance.address,
// users[4],
// amountToLiquidate,
// true
// );
// const userReserveDataAfter: any = await _lendingPoolInstance.getUserReserveData(
// usdcInstance.address,
// users[4]
// );
// const userGlobalDataAfter: any = await _lendingPoolInstance.getUserAccountData(users[4]);
// const usdcReserveDataAfter: any = await _lendingPoolInstance.getReserveData(
// usdcInstance.address
// );
// const ethReserveDataAfter: any = await _lendingPoolInstance.getReserveData(ETHEREUM_ADDRESS);
// const feeAddress = await _lendingPoolAddressesProviderInstance.getTokenDistributor();
// const feeAddressBalance = await web3.eth.getBalance(feeAddress);
// const collateralPrice = await _priceOracleInstance.getAssetPrice(ETHEREUM_ADDRESS);
// const principalPrice = await _priceOracleInstance.getAssetPrice(usdcInstance.address);
// const collateralDecimals = await _lendingPoolCoreInstance.getReserveDecimals(ETHEREUM_ADDRESS);
// const principalDecimals = await _lendingPoolCoreInstance.getReserveDecimals(
// usdcInstance.address
// );
// const expectedCollateralLiquidated = new BigNumber(principalPrice)
// .times(new BigNumber(amountToLiquidate).times(105))
// .times(new BigNumber(10).pow(collateralDecimals))
// .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// .decimalPlaces(0, BigNumber.ROUND_DOWN);
// const expectedFeeLiquidated = new BigNumber(principalPrice)
// .times(new BigNumber(userReserveDataBefore.originationFee).times(105))
// .times(new BigNumber(10).pow(collateralDecimals))
// .div(new BigNumber(collateralPrice).times(new BigNumber(10).pow(principalDecimals)))
// .div(100)
// .decimalPlaces(0, BigNumber.ROUND_DOWN);
// expect(userGlobalDataAfter.healthFactor).to.be.bignumber.gt(
// oneEther.toFixed(0),
// 'Invalid health factor'
// );
// expect(userReserveDataAfter.originationFee).to.be.bignumber.eq(
// '0',
// 'Origination fee should be repaid'
// );
// expect(feeAddressBalance).to.be.bignumber.gt('0');
// expect(userReserveDataAfter.principalBorrowBalance).to.be.bignumber.almostEqual(
// new BigNumber(userReserveDataBefore.currentBorrowBalance).minus(amountToLiquidate).toFixed(0),
// 'Invalid user borrow balance after liquidation'
// );
// expect(usdcReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// new BigNumber(usdcReserveDataBefore.availableLiquidity).plus(amountToLiquidate).toFixed(0),
// 'Invalid principal available liquidity'
// );
// expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual(
// new BigNumber(ethReserveDataBefore.availableLiquidity)
// .minus(expectedFeeLiquidated)
// .toFixed(0),
// 'Invalid collateral available liquidity'
// );
// });
// });