From 45f47b44dd47b4cd0757fbaefa0fcbc008a45b59 Mon Sep 17 00:00:00 2001 From: zhoujia6139 Date: Sat, 27 Aug 2022 01:35:50 +0800 Subject: [PATCH 1/3] a liquidation fail case. --- test-suites/liquidation-with-fee.spec.ts | 108 +++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/test-suites/liquidation-with-fee.spec.ts b/test-suites/liquidation-with-fee.spec.ts index ff01fca6b..377275635 100644 --- a/test-suites/liquidation-with-fee.spec.ts +++ b/test-suites/liquidation-with-fee.spec.ts @@ -26,6 +26,114 @@ makeSuite('Pool Liquidation: Add fee to liquidations', (testEnv) => { await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); }); + it('position should be liquidated when turn on liquidation protocol fee.', async () => { + const { pool, users, usdc, weth, oracle, configurator, helpersContract } = testEnv; + + const depositor = users[0]; + const borrower = users[1]; + const liquidator = users[2]; + + //1, prepare asset price. + await oracle.setAssetPrice(usdc.address, '1000000000000000'); //weth = 1000 usdc + + //2, depositor deposit 100000 usdc and 10 eth + await usdc + .connect(depositor.signer) + ['mint(uint256)'](await convertToCurrencyDecimals(usdc.address, '10000')); + await usdc.connect(depositor.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool + .connect(depositor.signer) + .supply( + usdc.address, + await convertToCurrencyDecimals(usdc.address, '10000'), + depositor.address, + 0 + ); + + await weth + .connect(depositor.signer) + ['mint(uint256)'](convertToCurrencyDecimals(weth.address, '10')); + await weth.connect(depositor.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool + .connect(depositor.signer) + .supply(weth.address, convertToCurrencyDecimals(weth.address, '10'), depositor.address, 0); + + //3, borrower deposit 10 eth, borrow 5000 usdc + await weth + .connect(borrower.signer) + ['mint(uint256)'](convertToCurrencyDecimals(weth.address, '10')); + await weth.connect(borrower.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool + .connect(borrower.signer) + .supply(weth.address, convertToCurrencyDecimals(weth.address, '10'), borrower.address, 0); + + await pool + .connect(borrower.signer) + .borrow( + usdc.address, + await convertToCurrencyDecimals(usdc.address, '5000'), + RateMode.Variable, + 0, + borrower.address + ); + + //4, liquidator deposit 10000 usdc and borrow 5 eth. + await usdc + .connect(liquidator.signer) + ['mint(uint256)'](await convertToCurrencyDecimals(usdc.address, '20000')); + await usdc.connect(liquidator.signer).approve(pool.address, MAX_UINT_AMOUNT); + await pool + .connect(liquidator.signer) + .supply( + usdc.address, + await convertToCurrencyDecimals(usdc.address, '10000'), + liquidator.address, + 0 + ); + + await pool + .connect(liquidator.signer) + .borrow( + weth.address, + convertToCurrencyDecimals(weth.address, '5'), + RateMode.Variable, + 0, + liquidator.address + ); + + //5, advance block to make ETH income index > 1 + await increaseTime(86400); + + //6, decrease weth price to allow liquidation + await oracle.setAssetPrice(usdc.address, '20000000000000000'); //weth = 500 usdc + + //7, turn on liquidation protocol fee + expect(await configurator.setLiquidationProtocolFee(weth.address, 500)); + const wethLiquidationProtocolFee = await helpersContract.getLiquidationProtocolFee( + weth.address + ); + expect(wethLiquidationProtocolFee).to.be.eq(500); + + const tryMaxTimes = 20; + for (let i = 1; i <= tryMaxTimes; i++) { + const tmpSnap = await evmSnapshot(); + await increaseTime(i); + expect( + await pool + .connect(liquidator.signer) + .liquidationCall(weth.address, usdc.address, borrower.address, MAX_UINT_AMOUNT, false) + ); + + if (i !== tryMaxTimes) { + await evmRevert(tmpSnap); + } + } + + expect(await weth.balanceOf(liquidator.address)).to.be.gt( + convertToCurrencyDecimals(weth.address, '5') + ); + }); + it('Sets the WETH protocol liquidation fee to 1000 (10.00%)', async () => { const { configurator, weth, aave, helpersContract } = testEnv; From 623730b3db4146281a11c5424938d339c4005357 Mon Sep 17 00:00:00 2001 From: zhoujia6139 Date: Sat, 27 Aug 2022 01:43:14 +0800 Subject: [PATCH 2/3] fix: solution to fix liquidation failed case. --- contracts/protocol/libraries/logic/LiquidationLogic.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contracts/protocol/libraries/logic/LiquidationLogic.sol b/contracts/protocol/libraries/logic/LiquidationLogic.sol index 7d91d3365..090565baf 100644 --- a/contracts/protocol/libraries/logic/LiquidationLogic.sol +++ b/contracts/protocol/libraries/logic/LiquidationLogic.sol @@ -191,6 +191,12 @@ library LiquidationLogic { // Transfer fee to treasury if it is non-zero if (vars.liquidationProtocolFeeAmount != 0) { + uint256 index = collateralReserve.getNormalizedIncome(); + uint256 aTokenAmount = vars.liquidationProtocolFeeAmount.rayDiv(index); + uint256 aTokenBalance = vars.collateralAToken.scaledBalanceOf(params.user); + if (aTokenAmount > aTokenBalance) { + vars.liquidationProtocolFeeAmount = aTokenBalance.rayMul(index); + } vars.collateralAToken.transferOnLiquidation( params.user, vars.collateralAToken.RESERVE_TREASURY_ADDRESS(), From e99112c990b121d7207c150746e0c4f7adcfbba4 Mon Sep 17 00:00:00 2001 From: zhoujia6139 Date: Fri, 11 Nov 2022 22:33:25 +0800 Subject: [PATCH 3/3] Update contracts/protocol/libraries/logic/LiquidationLogic.sol Co-authored-by: Ernesto Boado --- .../protocol/libraries/logic/LiquidationLogic.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/protocol/libraries/logic/LiquidationLogic.sol b/contracts/protocol/libraries/logic/LiquidationLogic.sol index 090565baf..d06d9bff8 100644 --- a/contracts/protocol/libraries/logic/LiquidationLogic.sol +++ b/contracts/protocol/libraries/logic/LiquidationLogic.sol @@ -191,11 +191,12 @@ library LiquidationLogic { // Transfer fee to treasury if it is non-zero if (vars.liquidationProtocolFeeAmount != 0) { - uint256 index = collateralReserve.getNormalizedIncome(); - uint256 aTokenAmount = vars.liquidationProtocolFeeAmount.rayDiv(index); - uint256 aTokenBalance = vars.collateralAToken.scaledBalanceOf(params.user); - if (aTokenAmount > aTokenBalance) { - vars.liquidationProtocolFeeAmount = aTokenBalance.rayMul(index); + uint256 liquidityIndex = collateralReserve.getNormalizedIncome(); + uint256 scaledDownLiquidationProtocolFee = vars.liquidationProtocolFeeAmount.rayDiv(liquidityIndex); + uint256 scaledDownUserBalance = vars.collateralAToken.scaledBalanceOf(params.user); + // To avoid trying to send more aTokens than available on balance, due to 1 wei imprecision + if (scaledDownLiquidationProtocolFee > scaledDownUserBalance) { + vars.liquidationProtocolFeeAmount = scaledDownUserBalance.rayMul(liquidityIndex); } vars.collateralAToken.transferOnLiquidation( params.user,