From 2add014fe5a03698009fe6e21b5f2b8abaa6da2c Mon Sep 17 00:00:00 2001 From: The3D Date: Wed, 15 Jul 2020 16:44:20 +0200 Subject: [PATCH 1/3] Fixes issue on LiquidationManager --- .../LendingPoolLiquidationManager.sol | 17 ++++++++----- test/liquidation-atoken.spec.ts | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol index 967a0087..e5c5b8b7 100644 --- a/contracts/lendingpool/LendingPoolLiquidationManager.sol +++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol @@ -201,16 +201,12 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl //of _collateral to cover the actual amount that is being liquidated, hence we liquidate //a smaller amount - vars.collateralAtoken = AToken(payable(collateralReserve.aTokenAddress)); - - //if principalAmountNeeded < vars.ActualAmountToLiquidate, there isn't enough - //of _collateral to cover the actual amount that is being liquidated, hence we liquidate - //a smaller amount - if (vars.principalAmountNeeded < vars.actualAmountToLiquidate) { vars.actualAmountToLiquidate = vars.principalAmountNeeded; } + vars.collateralAtoken = AToken(payable(collateralReserve.aTokenAddress)); + //if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve if (!_receiveAToken) { uint256 currentAvailableCollateral = IERC20(_collateral).universalBalanceOf( @@ -224,6 +220,10 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl } } + //update the principal reserve + principalReserve.updateCumulativeIndexesAndTimestamp(); + principalReserve.updateInterestRates(_reserve, vars.actualAmountToLiquidate, 0); + if (vars.userVariableDebt >= vars.actualAmountToLiquidate) { IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn( _user, @@ -245,6 +245,11 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl vars.collateralAtoken.transferOnLiquidation(_user, msg.sender, vars.maxCollateralToLiquidate); } else { //otherwise receives the underlying asset + + //updating collateral reserve + collateralReserve.updateCumulativeIndexesAndTimestamp(); + collateralReserve.updateInterestRates(_collateral, 0, vars.maxCollateralToLiquidate); + //burn the equivalent amount of atoken vars.collateralAtoken.burnOnLiquidation(_user, vars.maxCollateralToLiquidate); vars.collateralAtoken.transferUnderlyingTo(msg.sender, vars.maxCollateralToLiquidate); diff --git a/test/liquidation-atoken.spec.ts b/test/liquidation-atoken.spec.ts index 8019ad21..a523fb05 100644 --- a/test/liquidation-atoken.spec.ts +++ b/test/liquidation-atoken.spec.ts @@ -197,6 +197,18 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => 'Invalid principal available liquidity' ); + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gt( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual( new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), 'Invalid collateral available liquidity' @@ -317,6 +329,18 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => 'Invalid principal available liquidity' ); + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gt( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + expect(ethReserveDataAfter.availableLiquidity).to.be.bignumber.almostEqual( new BigNumber(ethReserveDataBefore.availableLiquidity.toString()).toFixed(0), 'Invalid collateral available liquidity' From 4d2406a5e182afc91d85f13c2b473bddb2e9f090 Mon Sep 17 00:00:00 2001 From: The3D Date: Wed, 15 Jul 2020 16:49:56 +0200 Subject: [PATCH 2/3] Fixed liquidation tests --- test/liquidation-underlying.spec.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/liquidation-underlying.spec.ts b/test/liquidation-underlying.spec.ts index bb3db061..be3e0401 100644 --- a/test/liquidation-underlying.spec.ts +++ b/test/liquidation-underlying.spec.ts @@ -182,6 +182,18 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', 'Invalid user debt after liquidation' ); + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(daiReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gt( + daiReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(daiReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + daiReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + expect(daiReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( new BigNumber(daiReserveDataBefore.availableLiquidity).plus(amountToLiquidate).toFixed(0), 'Invalid principal available liquidity' @@ -309,6 +321,18 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', 'Invalid user borrow balance after liquidation' ); + //the liquidity index of the principal reserve needs to be bigger than the index before + expect(usdcReserveDataAfter.liquidityIndex.toString()).to.be.bignumber.gt( + usdcReserveDataBefore.liquidityIndex.toString(), + 'Invalid liquidity index' + ); + + //the principal APY after a liquidation needs to be lower than the APY before + expect(usdcReserveDataAfter.liquidityRate.toString()).to.be.bignumber.lt( + usdcReserveDataBefore.liquidityRate.toString(), + 'Invalid liquidity APY' + ); + expect(usdcReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual( new BigNumber(usdcReserveDataBefore.availableLiquidity).plus(amountToLiquidate).toFixed(0), 'Invalid principal available liquidity' From 60b30fe91ead1549a5b9c9d5bd06b83c379b750c Mon Sep 17 00:00:00 2001 From: The3D Date: Wed, 15 Jul 2020 16:51:48 +0200 Subject: [PATCH 3/3] Removed unused function --- contracts/libraries/ReserveLogic.sol | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/contracts/libraries/ReserveLogic.sol b/contracts/libraries/ReserveLogic.sol index 0c9ed550..d3edac1c 100644 --- a/contracts/libraries/ReserveLogic.sol +++ b/contracts/libraries/ReserveLogic.sol @@ -300,25 +300,6 @@ library ReserveLogic { updateInterestRates(_reserve, _reserveAddress, _income, 0); } - /** - * @dev updates the state of the core as a consequence of a liquidation action. - * @param _collateralReserve the collateral reserve that is being liquidated - * @param _collateralToLiquidate the amount of collateral being liquidated - * @param _liquidatorReceivesAToken true if the liquidator will receive aTokens, false otherwise - **/ - function updateStateOnLiquidationAsCollateral( - ReserveData storage _collateralReserve, - address _collateralReserveAddress, - uint256 _collateralToLiquidate, - bool _liquidatorReceivesAToken - ) external { - _collateralReserve.updateCumulativeIndexesAndTimestamp(); - - if (!_liquidatorReceivesAToken) { - updateInterestRates(_collateralReserve, _collateralReserveAddress, 0, _collateralToLiquidate); - } - } - /** * @dev gets the total liquidity in the reserve. The total liquidity is the balance of the core contract + total borrows * @param _reserve the reserve address