The borrow balance is not calculated correctly in the getLoanLiquidity function.
Vulnerability Details
When the executeLiquidation function is called, the prepareLiquidation function calculates violators' effective collateral and borrow balance with the getLoanLiquidity function. Then, the function checks whether the violator is liquidatable.
When we look at the getLoanLiquidity function, if the loan is a stable borrow, the function calculates the borrow balance with the calcStableBorrowBalance function.
However, the problem is that the function calls the calcBorrowBalance function wrongly. The updated borrow index needs to be the first function parameter, and the old borrow index needs to be the second function parameter. Like in the updateLoanBorrowInterests function.
As we can see in the updateLoanBorrowInterests function, it first updates the lastInterestIndex and then correctly calls the calcBorrowBalance.
Impact Details
Wrongly Calculating the borrow balance in the getLoanLiquidity can result in a lower borrow balance for the violator, which may also cause the liquidate function to revert even if the violator is in the liquidatable state.
References
Proof of concept
Proof of Concept
LoanManager.test.ts
it("Test borrow balance",async () => { const { hub, loanManager, loanManagerAddress, pools, loanId, accountId, loanTypeId, borrowAmount, usdcStableInterestRate, } = await loadFixture(depositEtherAndStableBorrowUSDCFixture); const { pool, poolId } = pools.USDC; const userLoanBefore = await loanManager.getUserLoan(loanId); const oldBorrow = userLoanBefore[5][0];// calculate interest const timestamp = (await getLatestBlockTimestamp()) +getRandomInt(SECONDS_IN_HOUR); await time.setNextBlockTimestamp(timestamp);// Updated interest index const newInterestIndex =calcBorrowInterestIndex( oldBorrow.stableInterestRate, oldBorrow.lastInterestIndex,BigInt(timestamp) - oldBorrow.lastStableUpdateTimestamp,true );// Correctly calculated borrow balance like in the updateLoanBorrowInterests function const borrowBalance =calcBorrowBalance(oldBorrow.balance, newInterestIndex, oldBorrow.lastInterestIndex); console.log("Correct borrow balance", borrowBalance);// Wrongly calculated borrow balance like in the calcStableBorrowBalance function const wrongBorrowBalance =calcBorrowBalance(oldBorrow.balance, oldBorrow.lastInterestIndex, newInterestIndex); console.log("Wrong borrow balance", wrongBorrowBalance); });