Core Contracts

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

Forced Liquidation Due to `whenNotPaused` Modifier on `repay` Function

Summary

The LendingPool contract’s repay function is restricted by the whenNotPaused modifier, preventing borrowers from repaying when the protocol is paused. However, the finalizeLiquidation function, which executes forced liquidations after the grace period, does not have this restriction. This creates a scenario where a borrower who intends to repay within their grace period is unable to do so if the protocol is paused, while liquidation can still proceed. As a result, borrowers may be unfairly liquidated despite their intention to repay.

Vulnerability Details

Issue Explanation

  1. Repay Function is Restricted by whenNotPaused

    function repay(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
    _repay(amount, msg.sender);
    }
    • This function prevents repayments when the protocol is paused.

  2. Finalization of Liquidation is NOT Restricted by whenNotPaused

    function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
    // Executes forced liquidation after the grace period ends
    }
    • This function remains callable even when the protocol is paused, allowing liquidations to continue while repayments are blocked.

Scenario Leading to Unfair Liquidation

  • Suppose a borrower is liquidated and given a 7-day grace period to repay.

  • On day 5, the protocol is paused, preventing new liquidations and blocking repayments.

  • On day 6, the borrower attempts to repay, but fails due to whenNotPaused.

  • On day 7, the grace period expires, and since finalizeLiquidation is not restricted by whenNotPaused, the borrower is forcefully liquidated.

  • Outcome: The borrower gets unfairly liquidated even though they intended to repay within the grace period.

Impact

  • Unfair Liquidations: Borrowers are forced into liquidation due to a protocol pause, even if they had the funds to repay.

  • Financial Losses: Borrowers lose their collateral despite intending to fulfill their obligations.

Recommendations

  1. Allow Repayments Even When Paused

    • Remove whenNotPaused from the repay function, or add an exception allowing borrowers under liquidation to repay.
      Fix:

    function repay(uint256 amount) external nonReentrant onlyValidAmount(amount) {
    _repay(amount, msg.sender);
    }
  2. Pause Liquidations Along with Repayments

    • Add whenNotPaused to finalizeLiquidation, ensuring that liquidations don’t proceed if repayments are blocked.
      Fix:

    function finalizeLiquidation(address userAddress) external nonReentrant whenNotPaused onlyStabilityPool {
    // Now liquidation cannot proceed while paused
    }
  3. Extend Grace Period During Pauses

    • If the protocol is paused, extend the borrower’s grace period until the system is unpaused.
      Fix:

    function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
    if (paused()) {
    gracePeriodEnd[userAddress] += getPausedDuration();
    return;
    }
    // Proceed with liquidation
    }
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unfair Liquidation As Repayment / closeLiquidation Paused While Liquidations Enabled

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unfair Liquidation As Repayment / closeLiquidation Paused While Liquidations Enabled

Support

FAQs

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