sherlock-audit / 2024-04-interest-rate-model-judging

9 stars 5 forks source link

Nyx - The liquidator may not liquidate the borrower if the bad debt is more than earningsAccumulator #210

Closed sherlock-admin4 closed 4 months ago

sherlock-admin4 commented 5 months ago

Nyx

high

The liquidator may not liquidate the borrower if the bad debt is more than earningsAccumulator

Summary

Vulnerability Detail

When the liquidator liquidates undercollateralized positions with the liquidate function, the function checks for both fixed positions and floating positions to repay the borrower's debt and seizes his collateral. After that, the function calls the handleBadDebt function to clear the bad debt using the earningsAccumulator. When the clearBadDebt function clears the bad debt from fixed positions, it only clears the bad debt if the amount of earnings accumulator is greater than the bad debt.

if (accumulator >= badDebt) {
          RewardsController memRewardsController = rewardsController;
          if (address(memRewardsController) != address(0)) memRewardsController.handleBorrow(borrower);
          accumulator -= badDebt; 
          totalBadDebt += badDebt; 
          floatingBackupBorrowed -= fixedPools[maturity].repay(position.principal);
          delete fixedBorrowPositions[maturity][borrower];
          account.fixedBorrows = account.fixedBorrows.clearMaturity(maturity);

          emit RepayAtMaturity(maturity, msg.sender, borrower, badDebt, badDebt);
        }

The problem is that when the function clears bad debt from floating positions, it only checks if the accumulator is greater than 0, not checking if the accumulator is greater than the bad debt.

if (account.floatingBorrowShares != 0 && (accumulator = previewRepay(accumulator)) != 0) {
      (uint256 badDebt, ) = noTransferRefund(accumulator, borrower);
      totalBadDebt += badDebt;
    }
    if (totalBadDebt != 0) {
      earningsAccumulator -= totalBadDebt; //@audit 
      emit SpreadBadDebt(borrower, totalBadDebt);
    }

Let’s say the borrower has both fixed and floating positions and liquidating them creates a bad debt. First, the function tries to clear the fixed position’s bad debt if the amount of earning accumulator is enough and updates the accumulator amount after clearing the bad debt. After that, the function will try to clear the floating position’s bad debt if the borrower has the floating position and the accumulator amount is greater than 0. After clearing the fixed position’s bad debt, the earning accumulator can be greater than 0, but it can be less than the bad debt of floating positions. This can cause the liquidate function to revert if the earningsAccumulator is less than the floating positions bad debt.

Impact

The liquidator can not liquidate the borrower and this can cause more bad debt for the protocol.

Code Snippet

https://github.com/sherlock-audit/2024-04-interest-rate-model/blob/main/protocol/contracts/Market.sol#L545-L614

Tool used

Manual Review

Recommendation

The function only needs to repay the bad debt if the remaining accumulator is greater than the floating position bad debt so that the liquidate function doesn’t revert.

santipu03 commented 4 months ago

This issue is invalid because when the bad debt is higher than the earnings, the function won't revert but it will clear the maximum bad debt possible.