2020-09-14 13:02:48 +00:00
import { makeSuite , TestEnv } from './helpers/make-suite' ;
import { ProtocolErrors , RateMode } from '../helpers/types' ;
import { APPROVAL_AMOUNT_LENDING_POOL , oneEther } from '../helpers/constants' ;
import { convertToCurrencyDecimals , getMockFlashLoanReceiver } from '../helpers/contracts-helpers' ;
import { parseEther , parseUnits } from 'ethers/lib/utils' ;
import { BigNumber } from 'bignumber.js' ;
import { MockFlashLoanReceiver } from '../types/MockFlashLoanReceiver' ;
const { expect } = require ( 'chai' ) ;
makeSuite ( 'Pausable Pool' , ( testEnv : TestEnv ) = > {
let _mockFlashLoanReceiver = { } as MockFlashLoanReceiver ;
const {
IS_PAUSED ,
TRANSFER_NOT_ALLOWED ,
INVALID_FROM_BALANCE_AFTER_TRANSFER ,
INVALID_TO_BALANCE_AFTER_TRANSFER ,
INVALID_HF ,
} = ProtocolErrors ;
before ( async ( ) = > {
_mockFlashLoanReceiver = await getMockFlashLoanReceiver ( ) ;
} ) ;
it ( 'User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees' , async ( ) = > {
const { users , pool , dai , aDai , configurator } = testEnv ;
const amountDAItoDeposit = await convertToCurrencyDecimals ( dai . address , '1000' ) ;
await dai . connect ( users [ 0 ] . signer ) . mint ( amountDAItoDeposit ) ;
// user 0 deposits 1000 DAI
await dai . connect ( users [ 0 ] . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool
. connect ( users [ 0 ] . signer )
. deposit ( dai . address , amountDAItoDeposit , users [ 0 ] . address , '0' ) ;
const user0Balance = await aDai . balanceOf ( users [ 0 ] . address ) ;
const user1Balance = await aDai . balanceOf ( users [ 1 ] . address ) ;
// Configurator pauses the pool
await configurator . pausePool ( ) ;
// User 0 tries the transfer to User 1
await expect (
aDai . connect ( users [ 0 ] . signer ) . transfer ( users [ 1 ] . address , amountDAItoDeposit )
) . to . revertedWith ( TRANSFER_NOT_ALLOWED ) ;
const pausedFromBalance = await aDai . balanceOf ( users [ 0 ] . address ) ;
const pausedToBalance = await aDai . balanceOf ( users [ 1 ] . address ) ;
expect ( pausedFromBalance ) . to . be . equal (
user0Balance . toString ( ) ,
INVALID_TO_BALANCE_AFTER_TRANSFER
) ;
expect ( pausedToBalance . toString ( ) ) . to . be . equal (
user1Balance . toString ( ) ,
INVALID_FROM_BALANCE_AFTER_TRANSFER
) ;
// Configurator unpauses the pool
await configurator . unpausePool ( ) ;
// User 0 succeeds transfer to User 1
await aDai . connect ( users [ 0 ] . signer ) . transfer ( users [ 1 ] . address , amountDAItoDeposit ) ;
const fromBalance = await aDai . balanceOf ( users [ 0 ] . address ) ;
const toBalance = await aDai . balanceOf ( users [ 1 ] . address ) ;
expect ( fromBalance . toString ( ) ) . to . be . equal (
user0Balance . sub ( amountDAItoDeposit ) ,
INVALID_FROM_BALANCE_AFTER_TRANSFER
) ;
expect ( toBalance . toString ( ) ) . to . be . equal (
user1Balance . add ( amountDAItoDeposit ) ,
INVALID_TO_BALANCE_AFTER_TRANSFER
) ;
} ) ;
it ( 'User 0 deposits 1000 DAI but reverts due pool is paused' , async ( ) = > {
const { users , pool , dai , aDai , configurator } = testEnv ;
const amountDAItoDeposit = await convertToCurrencyDecimals ( dai . address , '1000' ) ;
await dai . connect ( users [ 0 ] . signer ) . mint ( amountDAItoDeposit ) ;
// user 0 deposits 1000 DAI
await dai . connect ( users [ 0 ] . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
// Configurator pauses the pool
await configurator . pausePool ( ) ;
await expect (
pool . connect ( users [ 0 ] . signer ) . deposit ( dai . address , amountDAItoDeposit , users [ 0 ] . address , '0' )
) . to . revertedWith ( IS_PAUSED ) ;
// Configurator unpauses the pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'User 0 burns 1000 aDAI but reverts due pool is paused' , async ( ) = > {
const { users , pool , dai , aDai , configurator } = testEnv ;
const amountDAItoDeposit = await convertToCurrencyDecimals ( dai . address , '1000' ) ;
await dai . connect ( users [ 0 ] . signer ) . mint ( amountDAItoDeposit ) ;
// user 0 deposits 1000 DAI
await dai . connect ( users [ 0 ] . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool
. connect ( users [ 0 ] . signer )
. deposit ( dai . address , amountDAItoDeposit , users [ 0 ] . address , '0' ) ;
// Configurator pauses the pool
await configurator . pausePool ( ) ;
// user tries to burn
await expect (
pool . connect ( users [ 0 ] . signer ) . withdraw ( dai . address , amountDAItoDeposit )
) . to . revertedWith ( IS_PAUSED ) ;
// Configurator unpauses the pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'Repay with collateral' , async ( ) = > {
const { pool , weth , dai , usdc , users , mockSwapAdapter , oracle , configurator } = testEnv ;
const user = users [ 6 ] ;
const liquidator = users [ 5 ] ;
// Pause the pool
await configurator . pausePool ( ) ;
// Try to execute liquidation
await expect (
pool
. connect ( liquidator . signer )
. repayWithCollateral (
weth . address ,
usdc . address ,
user . address ,
'1' ,
mockSwapAdapter . address ,
'0x'
)
) . revertedWith ( IS_PAUSED ) ;
// Unpause the pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'Flash loan' , async ( ) = > {
const { dai , pool , weth , users , configurator } = testEnv ;
const caller = users [ 3 ] ;
const flashAmount = parseEther ( '0.8' ) ;
await _mockFlashLoanReceiver . setFailExecutionTransfer ( true ) ;
// Pause pool
await configurator . pausePool ( ) ;
await expect (
pool
. connect ( caller . signer )
. flashLoan ( _mockFlashLoanReceiver . address , weth . address , flashAmount , 1 , '0x10' , '0' )
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'Liquidation call' , async ( ) = > {
const { users , pool , usdc , oracle , weth , configurator } = testEnv ;
const depositor = users [ 3 ] ;
const borrower = users [ 4 ] ;
//mints USDC to depositor
await usdc
. connect ( depositor . signer )
. mint ( await convertToCurrencyDecimals ( usdc . address , '1000' ) ) ;
//approve protocol to access depositor wallet
await usdc . connect ( depositor . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
//user 3 deposits 1000 USDC
const amountUSDCtoDeposit = await convertToCurrencyDecimals ( usdc . address , '1000' ) ;
await pool
. connect ( depositor . signer )
. deposit ( usdc . address , amountUSDCtoDeposit , depositor . address , '0' ) ;
//user 4 deposits 1 ETH
const amountETHtoDeposit = await convertToCurrencyDecimals ( weth . address , '1' ) ;
//mints WETH to borrower
await weth . connect ( borrower . signer ) . mint ( amountETHtoDeposit ) ;
//approve protocol to access borrower wallet
await weth . connect ( borrower . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool
. connect ( borrower . signer )
. deposit ( weth . address , amountETHtoDeposit , borrower . address , '0' ) ;
//user 4 borrows
const userGlobalData = await pool . getUserAccountData ( borrower . address ) ;
const usdcPrice = await oracle . getAssetPrice ( usdc . address ) ;
const amountUSDCToBorrow = await convertToCurrencyDecimals (
usdc . address ,
new BigNumber ( userGlobalData . availableBorrowsETH . toString ( ) )
. div ( usdcPrice . toString ( ) )
. multipliedBy ( 0.9502 )
. toFixed ( 0 )
) ;
await pool
. connect ( borrower . signer )
2020-09-14 17:59:00 +00:00
. borrow ( usdc . address , amountUSDCToBorrow , RateMode . Stable , '0' , borrower . address ) ;
2020-09-14 13:02:48 +00:00
// Drops HF below 1
await oracle . setAssetPrice (
usdc . address ,
new BigNumber ( usdcPrice . toString ( ) ) . multipliedBy ( 1.2 ) . toFixed ( 0 )
) ;
//mints dai to the liquidator
await usdc . mint ( await convertToCurrencyDecimals ( usdc . address , '1000' ) ) ;
await usdc . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
const userReserveDataBefore = await pool . getUserReserveData ( usdc . address , borrower . address ) ;
const amountToLiquidate = new BigNumber ( userReserveDataBefore . currentStableDebt . toString ( ) )
. multipliedBy ( 0.5 )
. toFixed ( 0 ) ;
// Pause pool
await configurator . pausePool ( ) ;
// Do liquidation
expect (
pool . liquidationCall ( weth . address , usdc . address , borrower . address , amountToLiquidate , true )
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'User 6 deposits WETH and DAI, then borrows USDC at Variable' , async ( ) = > {
const { pool , weth , dai , usdc , users , configurator , mockSwapAdapter } = testEnv ;
const user = users [ 5 ] ;
const amountWETHToDeposit = parseEther ( '10' ) ;
const amountDAIToDeposit = parseEther ( '120' ) ;
const amountToBorrow = parseUnits ( '65' , 6 ) ;
await weth . connect ( user . signer ) . mint ( amountWETHToDeposit ) ;
await weth . connect ( user . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool . connect ( user . signer ) . deposit ( weth . address , amountWETHToDeposit , user . address , '0' ) ;
await dai . connect ( user . signer ) . mint ( amountDAIToDeposit ) ;
await dai . connect ( user . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool . connect ( user . signer ) . deposit ( dai . address , amountDAIToDeposit , user . address , '0' ) ;
2020-09-14 17:59:00 +00:00
await pool . connect ( user . signer ) . borrow ( usdc . address , amountToBorrow , 2 , 0 , user . address ) ;
2020-09-14 13:02:48 +00:00
const amountToRepay = parseUnits ( '65' , 6 ) ;
await mockSwapAdapter . setAmountToReturn ( amountToRepay ) ;
// Pause pool
await configurator . pausePool ( ) ;
// Try to repay
await expect (
pool
. connect ( user . signer )
. repayWithCollateral (
weth . address ,
usdc . address ,
user . address ,
amountToRepay ,
mockSwapAdapter . address ,
'0x'
)
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'User 2 deposits WETH and DAI, then borrows USDC at Variable, then tries to swap to stable but pool is paused' , async ( ) = > {
const { pool , weth , dai , usdc , users , configurator , mockSwapAdapter } = testEnv ;
const user = users [ 1 ] ;
const amountWETHToDeposit = parseEther ( '10' ) ;
const amountDAIToDeposit = parseEther ( '120' ) ;
const amountToBorrow = parseUnits ( '65' , 6 ) ;
await weth . connect ( user . signer ) . mint ( amountWETHToDeposit ) ;
await weth . connect ( user . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool . connect ( user . signer ) . deposit ( weth . address , amountWETHToDeposit , user . address , '0' ) ;
await dai . connect ( user . signer ) . mint ( amountDAIToDeposit ) ;
await dai . connect ( user . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool . connect ( user . signer ) . deposit ( dai . address , amountDAIToDeposit , user . address , '0' ) ;
2020-09-14 17:59:00 +00:00
await pool . connect ( user . signer ) . borrow ( usdc . address , amountToBorrow , 2 , 0 , user . address ) ;
2020-09-14 13:02:48 +00:00
// Pause pool
await configurator . pausePool ( ) ;
// Try to repay
await expect (
pool . connect ( user . signer ) . swapBorrowRateMode ( usdc . address , RateMode . Stable )
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'User 2 tries to rebalance stable borrow rate' , async ( ) = > {
const { pool , dai , users , configurator } = testEnv ;
const user = users [ 1 ] ;
// Pause pool
await configurator . pausePool ( ) ;
await expect (
pool . connect ( user . signer ) . rebalanceStableBorrowRate ( dai . address , user . address )
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
it ( 'User 2 tries to rebalance stable borrow rate' , async ( ) = > {
const { pool , weth , users , configurator } = testEnv ;
const user = users [ 1 ] ;
const amountWETHToDeposit = parseEther ( '1' ) ;
await weth . connect ( user . signer ) . mint ( amountWETHToDeposit ) ;
await weth . connect ( user . signer ) . approve ( pool . address , APPROVAL_AMOUNT_LENDING_POOL ) ;
await pool . connect ( user . signer ) . deposit ( weth . address , amountWETHToDeposit , user . address , '0' ) ;
// Pause pool
await configurator . pausePool ( ) ;
await expect (
pool . connect ( user . signer ) . setUserUseReserveAsCollateral ( weth . address , false )
) . revertedWith ( IS_PAUSED ) ;
// Unpause pool
await configurator . unpausePool ( ) ;
} ) ;
} ) ;