Incorrect accounting of utilization, supply / borrow rates due to vulnerable implementation in IsolateLogic::executeIsolateLiquidate
mediumLines of code
Vulnerability details
Impact
Incorrect accounting of utilization, supply / borrow rates due to vulnerable implementation in IsolateLogic::executeIsolateLiquidate.
Proof of Concept
When an isolate loan ( borrow against a single nft token) is auctioned and liquidated, the liquidator (caller of IsolateLogic::executeIsolateLiquidate) may need to repay extra amount of debt(vars.totalExtraAmount) if the bid amount doesn't fully cover total debt(vars.totalBorrowAmount).
The problem is the above case is not correctly implemented when interests rates are updated (InterestLogic.updateInterestRates(poolData, debtAssetData, (vars.totalBorrowAmount + vars.totalExtraAmount), 0)).
In InterestLogic::updateInterestRates, utilization is recalculated based on liquidityAdded and liquidityTaken. In the context of IsolateLogic::executeIsolateLiquidate, the liquidtyAdded for a loan is the repayment of debt (vars.borrowAmount) which includes loanData.bidAmount + extraAmount.
solidity//src/libraries/logic/IsolateLogic.sol function executeIsolateLiquidate(InputTypes.ExecuteIsolateLiquidateParams memory params) internal { ... for (vars.nidx = 0; vars.nidx < params.nftTokenIds.length; vars.nidx++) { ... // Last bid can not cover borrow amount and liquidator need pay the extra amount if (loanData.bidAmount < vars.borrowAmount) { |> vars.extraBorrowAmounts[vars.nidx] = vars.borrowAmount - loanData.bidAmount;//@audit-info note: vars.borrowAmount = extraAmount + loanData.bidAmount } ... // update interest rate according latest borrow amount (utilizaton) //@audit (vars.totalBorrowAmount + vars.totalExtraAmount) is incorrect input, which inflates `liquidityAdded` in updateInterestRates. |> InterestLogic.updateInterestRates(poolData, debtAssetData, (vars.totalBorrowAmount + vars.totalExtraAmount), 0); // bid already in pool and now repay the borrow but need to increase liquidity //@audit-info note: only total debt (vars.totalBorrowAmount) are added to liquidity. |> VaultLogic.erc20TransferOutBidAmountToLiqudity(debtAssetData, vars.totalBorrowAmount); ...
In InterestLogic::updateInterestRates, (vars.totalBorrowAmount + vars.totalExtraAmount) inflates liquidityAdded, which inflates vars.availableLiquidityPlusDebt and deflates utilization rate vars.assetUtilizationRate. This will cause an inflated borrow rate / supply rate based on the interest rate model.
solidityfunction updateInterestRates( DataTypes.PoolData storage poolData, DataTypes.AssetData storage assetData, uint256 liquidityAdded, uint256 liquidityTaken ) internal { ... // calculate the total asset supply vars.availableLiquidityPlusDebt = assetData.availableLiquidity + |> liquidityAdded - liquidityTaken + vars.totalAssetDebt; if (vars.availableLiquidityPlusDebt > 0) { vars.assetUtilizationRate = vars.totalAssetDebt.rayDiv(vars.availableLiquidityPlusDebt); } ... vars.nextGroupBorrowRate = IInterestRateModel(loopGroupData.rateModel).calculateGroupBorrowRate( vars.loopGroupId, vars.assetUtilizationRate ); ...
Flows: IsolateLiquidation::isolateLiquidate ->IsolateLogic.executeIsolateLiquidate -> InterestLogic.updateInterestRates
Tools Used
Manual
Recommended Mitigation Steps
Consider changing into InterestLogic.updateInterestRates(poolData, debtAssetData, vars.totalBorrowAmount, 0)
Assessed type
Error
