Core Contracts

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

Double scaling in `_repay` function and unused `scaledAmount` in `LendingPool.sol`

Summary

The _repay function in the LendingPool contract applies debt scaling incorrectly by using the rayDiv function twice during the repayment calculation. Additionally, a locally computed scaledAmount is calculated but never used. These issues can result in borrowers repaying only the principal without covering the accrued interest.

Vulnerability Details

  1. Double Debt Scaling

    • The function first retrieves the user's total debt:

      uint256 userDebt = IDebtToken(reserve.reserveDebtTokenAddress).balanceOf(onBehalfOf);
    • It then scales this debt by applying:

      uint256 userScaledDebt = userDebt.rayDiv(reserve.usageIndex);

      This operation is intended to adjust the debt based on the reserve’s current usage index.

    • Next, after capping the repayment amount:

      uint256 actualRepayAmount = (amount > userScaledDebt) ? userScaledDebt : amount;

      the function applies the scaling a second time:

      uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);

      Issue: This second scaling erroneously divides by the usageIndex again, resulting in an incorrect (and lower) repayment value.

  2. Unused Computed scaledAmount:

    • The scaledAmount computed by the second call to rayDiv is not utilized in any subsequent logic. Instead, the repayment continues using values returned by the DebtToken.burn function:

      (uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
      IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);
    • Since scaledAmount is discarded, the intended correction for scaling is never applied.

  3. Underpayment of Interest:

    • The misinterpretation of scaling, combined with the reliance on the return value from the burn function, leads to a situation where the repayment amount does not account for accrued interest.

    • As a result, borrowers could repay only the principal amount, bypassing the interest component. This undermines the intended financial mechanics of the protocol.

Impact

  • Underpayment of Interest:
    Borrowers might repay only the principal without covering the accrued interest, distorting the debt repayment process.

  • Inaccurate Debt Accounting:
    The protocol’s internal accounting will fail to accurately capture the full debt obligation, potentially leading to an overstated debt balance and flawed interest rate calculations.

  • Exploitation Risk:
    Malicious users could exploit this flaw to minimize their repayment, paying less than their true debt obligation over time, which could erode the protocol’s revenue and stability.

Proof-of-Concept (POC) Example

  1. Scenario Setup:

    • A borrower takes out a loan, providing NFT collateral.

    • Over time, interest accrues, increasing the effective debt.

  2. Repayment Attempt:

    • The borrower initiates a repayment transaction with an amount that exceeds their scaled debt.

    • The _repay function computes the scaled debt (userScaledDebt) and then determines actualRepayAmount.

  3. Double Scaling and Ignored Value:

    • The function incorrectly applies rayDiv a second time on actualRepayAmount, producing scaledAmount.

    • However, scaledAmount is never used in the subsequent transfer or debt token burn operation.

  4. Outcome:

    • The repayment relies on the unscaled value returned from the burn function.

    • The borrower effectively repays only the principal, leaving accrued interest unpaid.

    • This results in a persistent overstatement of debt and incorrect interest accruals.

Tools Used

Manual review

Recommendations

  1. Remove the Second Scaling:

    • Eliminate the redundant scaling operation:

      // Remove this line:
      uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);
    • This ensures that the repayment amount is correctly computed only once.

  2. Integrate the Correct Scaled Value:

    • If additional scaling is required, ensure that the correctly computed value is used throughout the repayment logic.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

LendingPool::_repay double scales the debt

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

LendingPool::_repay double scales the debt

Support

FAQs

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

Give us feedback!