Skip to content

Latest commit

 

History

History
61 lines (39 loc) · 2.98 KB

056.md

File metadata and controls

61 lines (39 loc) · 2.98 KB

Small Shamrock Rook

Medium

Flash loan liquidations to liquidate LST borrowers can be DoS'd

Summary

When calling liquidateLstBorrower(), there is a bool _flashloan parameter, to determine whether the debt will be repaid via the user's own LST, or the vault's LST. This can be DoS'd due to the minBorrowAmountAllowPartialLiquidation.

Root Cause

In liquidateLstBorrower(), the liquidation must be a full liquidation, unless the borrowAmount of the borrower is greater than minBorrowAmountAllowPartialLiquidation, which is 10 ether.

The problem is that when there is high util, and a large amount of LST is borrowed, there can be less than 10 ether available in the NumaVault.

This causes flash loan liquidations (which use the vault's LST to repay the debt) to revert here:

IERC20(lstToken).approve(address(cLstToken), lstAmount);
cLstToken.liquidateBorrow(
    _borrower,
    lstAmount,
    CTokenInterface(address(cNuma))
);

(since the lstAmount is not available in the contract)

If the loan to be liquidated is 9.9 ether, it has to be liquidated fully. And since a flashloan liquidation is not possible, the only way is for the liquidation bot to have 9.9e18 ($40k+) of rETH ready, which is unreasonable.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. Large amounts of rETH (e.g 9e18) are separately borrowed from the vault, until the available funds is less than 9e18
  2. NUMA price drops, causing the positions to be liquidatable
  3. The positions cannot be liquidated via the _flashloan option, due to the lack of funds in the vault. They cannot be partially liquidated since they are less than 10e18 rETH. The liquidator bots will need to have 9e18 rETH to liquidate each position.

Impact

Flash loan liquidations of LST borrows will revert. For large borrows which cannot be partially liquidated (like 9.9 rETH), the liquidator bot will have to have 9.9 rETH in order for the liquidation to occur. Due to not being liquidatable, the position can go into bad debt causing loss to NUMA holders.

PoC

No response

Mitigation

The following recommendation to be applied here ensures that partial liquidations can occur when the LST balance of the vault is less than the preset min amount. This would allow flash loan liquidations to occur using the available vault funds and liquidate any unhealthy loans.

        uint minAmount = minBorrowAmountAllowPartialLiquidation;
        if (borrowAmount < minAmount) minAmount = borrowAmount;
+       if (lstToken.balanceOf(address(this)) < minAmount) minAmount = lstToken.balanceOf(address(this));
        require(lstAmount >= minAmount, "min liquidation");