Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Valid

Lack of incentives in liquidation may cause liquidations to not happen, leaving protocol with bad debt & loss of funds

Summary

In LendingPool-> the liquidation process lacks two significant incentives that would streamline the liquidation process and more importantly ensure that the protocol minimizes possible loss and damage from User's positions that lose value and become liquidatable.

These lack of incentives, under circumstances, that make a user's NFT used as collateral - lose value sharply - will actually incentivize the user to never repay their debt and allow the liquidation to happen as the financial benefit from allowing the liquidation will be greater than if repaying their debt. Which ends with the protocol taking on bad debt, and financial loss.

Vulnerability Details

In LendingPool-> there is functionality to allow a grace period, that is multiple days after the initiateLiquidation begins, which gives the user the option to pay ALL of their debt back to avoid liquidation.

There is nothing inherintly wrong with that, but the current lack of incentives of the protocol actually incentivize the user to not repay their debt under certain conditions, particularly when a user becomes insolvent.

Scenario:

  • user has 1 NFT deposited, worth 100 as collateral.

  • LiquidationThresholdis 80% , so user can borrow up to 80.

  • User has borrowed 80, and total debt of the user is 80.

  • Their health factor is ok and above the threshold to be liquidated.

** But, the NFT takes a sharp decline after some adverse event and is now worth 50.

  • The user now has 50 collateral

  • 80 total debt

  • their health factor is below the threshold and liquidation is initiated

** The user now has until the end of the grace period to pay ALL of their debt back and avoid liquidation. The user does this in 2 steps: 1st, call repayand repay ALL of their debt, and then call closeLiquidation-> stopping the liquidation.

function _repay(uint256 amount, address onBehalfOf) internal {
uint256 userDebt = IDebtToken(reserve.reserveDebtTokenAddress).balanceOf(onBehalfOf);
uint256 userScaledDebt = userDebt.rayDiv(reserve.usageIndex);
// If amount is greater than userDebt, cap it at userDebt
uint256 actualRepayAmount = amount > userScaledDebt ? userScaledDebt : amount;
uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);
// Burn DebtTokens from the user whose debt is being repaid (onBehalfOf)
// is not actualRepayAmount because we want to allow paying extra dust and we will then cap there
(uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);
// Transfer reserve assets from the caller (msg.sender) to the reserve
IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);

** The user must repay ALL of their debt here in repay. The user is able to input any amount, and repay any amount they specify, but for the purpose of stopping the liquidation they need to repay ALL of their debt -> this is ensured in the next step closeLiquidation-> which checks that the user debt is beneath the dustThreshold-> which is 1e6. That is tiny, becasue the tokens are 1e18. So that is considered by the protocol to symbolize 0 debt.

/**
* @notice Allows a user to repay their debt and close the liquidation within the grace period
*/
function closeLiquidation() external nonReentrant whenNotPaused {
uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
if (userDebt > DUST_THRESHOLD) revert DebtNotZero();

** So the user can only avoid liquidation by paying off their entire debt.

BUT, in this scenario:

  • The user has collateral now worth 50

  • total debt worth 80.

Why would the user pay 80 to the protocol when their collateral is only worth 50 ? The incentive now for the user is to allow the liquidation to go through.

  1. The second Incentive that the protocol lacks is the lack of incentive for someone to call initiateLiquidation

* @notice Allows anyone to initiate the liquidation process if a user's health factor is below threshold
* @param userAddress The address of the user to liquidate
*/
function initiateLiquidation(address userAddress) external nonReentrant whenNotPaused {

The user that calls this function receives no reward for calling it. This will delay the speed and efficiency at which liquidations begin, which allow collateral to fall in value even more before a liquidation is initiated. In tandem with the grace period, this lack of efficiency and speed can multiply the risk of the given scenario.

Impact

The protocol will pay the 80 debt and transfer the NFT worth 50 to the StabilityPool-> the protocol loses 30 worth of value, and the user walks away with 30 more than they should have.

The protocol will get only 50 worth of the 80 debt they issued to the user:

  • Protocol has a loss of 30

This becomes way more significant with inflated values.

Tools Used

Manual Review

Recommendations

  1. Incentivize a user to call initiateLiquidationby paying the user who calls the function a fee for doing so. This will ensure the proper incentives for liquidations to be started rapidly and efficiently, approving the overall efficiency of the protocol's liquidation process and reduces risks of untimely liquidations.

  2. This would involve a change in the repayment process for the user when they have a liquidation started, but an option is:

    • Allow a user to repay the amount of debt that would bring their health factor back to an acceptable level.

    • In the above scenario, the user would be incentivized to actually repay their debt and stop the liquidation if they were able to pay a portion of their debt that raised their helath factor to an acceptable level again:

    • The user new collateral is: 50

    • Their total debt is 80

    • given the 80% liquidationThreshold, the user is able to borrow up to 80% of 50 -> 40

    • The user can now pay 40 debt back to raise their health factor to an acceptable level.

    • This incentivizes the user to repay 40 debt and keep their position from being liquidated.

    • The protocol receives repayment of debt, and still has collateral that is again greater than the amount they have lent out.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Design choice
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

inallhonesty Lead Judge 22 days ago
Submission Judgement Published
Validated
Assigned finding tags:

No incentive to liquidate

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.