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 repayments when the protocol is paused. However, the finalizeLiquidation function, which forces liquidations after the grace period ends, lacks this restriction. This discrepancy means that borrowers who wish to repay during the grace period may be unable to do so if the protocol is paused, while liquidations can still proceed. As a result, borrowers may be unfairly liquidated despite their intent 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 blocks 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 can still be called when the protocol is paused, allowing liquidations to proceed even though repayments are blocked.

Scenario Leading to Unfair Liquidation

  • Suppose a borrower is given a 7-day grace period to repay their loan after being liquidated.

  • On day 5, the protocol is paused, which prevents new liquidations and blocks repayments.

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

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

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


Impact

  • Unfair Liquidations: Borrowers may be liquidated against their will due to a protocol pause, despite their intention to repay.

  • Financial Losses: Borrowers could lose their collateral even though they have the funds to repay.


Recommendations

  1. Allow Repayments Even When Paused

    • Remove the whenNotPaused modifier from the repay function, or add an exception that allows 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 the whenNotPaused modifier to finalizeLiquidation to ensure that liquidations are paused when 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 protocol 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 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unfair Liquidation As Repayment / closeLiquidation Paused While Liquidations Enabled

inallhonesty Lead Judge 7 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.

Give us feedback!