Core Contracts

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

Flawed Logic and Incorrect Returns in DebtToken `burn` Function Enable Under-Repayment of Debt

Summary

The burn function in the DebtToken contract contains significant logic errors, including incorrect handling of the balanceIncrease parameter and flawed return values. These issues allow users to repay less interest than owed, potentially closing loans prematurely and jeopardizing the protocol's solvency.

Vulnerability Details

The burn function's logic and return values are flawed in several ways:

  1. Incorrect balanceIncrease Handling: The balanceIncrease parameter, which represents the accrued interest, is not correctly incorporated into the calculation of the amount burned. This means that users are not repaying the full amount of interest they owe.

  2. Flawed Return Values: The function's return values are in the wrong order and do not accurately reflect the amounts burned and scaled. This can mislead external systems relying on this data.

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256, uint256) {
// ... other code ...
uint256 amountScaled = amount.rayMul(index); // Scaled amount
uint256 balanceIncrease = 0;
if (_userState[from].index != 0 && _userState[from].index < index) {
uint256 borrowIndex = ILendingPool(_reservePool).getNormalizedDebt();
balanceIncrease = userBalance.rayMul(borrowIndex) - userBalance.rayMul(_userState[from].index);
amount = amount; // INCORRECT: balanceIncrease is not used
}
// ... other code ...
// INCORRECT: Wrong return values
return (amountScaled, totalSupply(), amount, 0); // Should be (amountScaled, newTotalSupply, amountBurned, balanceIncrease)
}

Impact

  • Under-Repayment of Debt: Users can repay their loans without paying the full accrued interest, leading to a loss of revenue for the protocol.

  • Premature Loan Closure: Because users are not paying the full interest, loans may appear to be fully repaid when they are not, allowing users to close their positions prematurely.

  • Protocol Insolvency: If a significant number of users exploit this vulnerability, the protocol could face substantial losses and potentially become insolvent.

  • Incorrect return value: The incorrect return values lets user to repay only the principal amount without the accrued interest.

Proof of Concept

  1. Alice borrows 100 units of an asset.

  2. The loan accrues interest, and the balanceIncrease is calculated to be 10 units.

  3. Alice calls reay to repay her loan and the function burn in debt token is invoked.

  4. The burn function calculates amountScaled (e.g., to 110 if the index is 1.1).

  5. The _burn function is called with the original amount (100), not including the interest (10).

  6. Alice repays only 100 units, effectively avoiding paying the 10 units of interest.

  7. The burn function returns incorrect values, further obscuring the issue.

Recommended Mitigation

To address this vulnerability, the burn function should be updated to correctly handle the balanceIncrease parameter and return the appropriate values. The correct

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256, uint256) {
// ... other code ...
uint256 balanceIncrease = 0;
if (_userState[from].index != 0 && _userState[from].index < index) {
uint256 borrowIndex = ILendingPool(_reservePool).getNormalizedDebt();
balanceIncrease = userBalance.rayMul(borrowIndex) - userBalance.rayMul(_userState[from].index);
- amount = amount;
+ amount += balanceIncrease;
}
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
_burn(from, amount.toUint128());
emit Burn(from, amountScaled, index);
// ... other code ...
- return (amount, totalSupply(), amountScaled, balanceIncrease); // Incorrect return values
+ return (amountScaled, totalSupply(), amount, balanceIncrease); // Correct return values
}
Updates

Lead Judging Commences

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

DebtToken::burn calculates balanceIncrease (interest) but never applies it, allowing borrowers to repay loans without paying accrued interest

Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.

DebtToken::burn returns items in the wrong order

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

DebtToken::burn calculates balanceIncrease (interest) but never applies it, allowing borrowers to repay loans without paying accrued interest

Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.

DebtToken::burn returns items in the wrong order

Support

FAQs

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

Give us feedback!