Core Contracts

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

Unaccounted Balance Increase in Debt Token Burn Function Leads to Incorrect Burn Amount

Summary

In the burn function of the DebtToken contract, the calculated balanceIncrease (accrued interest) is not added to the burn amount, leading to incorrect burn calculations and potential accounting discrepancies.

Vulnerability Details

The issue occurs in the interest calculation section:

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; // @audit balanceIncrease is not added to the amount
}

The problem exists because:

  • The code calculates balanceIncrease correctly

  • But then has a no-op assignment amount = amount

  • The balanceIncrease should be added to amount to account for accrued interest

  • This leads to burning less than the actual debt amount

Correct implementation should be:

if (_userState[from].index != 0 && _userState[from].index < index) {
uint256 borrowIndex = ILendingPool(_reservePool).getNormalizedDebt();
balanceIncrease = userBalance.rayMul(borrowIndex) - userBalance.rayMul(_userState[from].index);
amount += balanceIncrease; // Add accrued interest to burn amount
}

Impact

  • Users burn less debt tokens than they should

  • Accrued interest is not properly burned

  • Protocol's debt accounting becomes inaccurate

  • Creates discrepancy between actual debt and recorded debt

  • Could lead to unbacked debt in the system

  • Users might retain debt tokens that should have been burned

Tools Used

Manual Review

Recommendations

function burn(
address from,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256, uint256) {
if (from == address(0)) revert InvalidAddress();
if (amount == 0) {
return (0, totalSupply(), 0, 0);
}
uint256 userBalance = balanceOf(from);
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; // Add accrued interest
}
_userState[from].index = index.toUint128();
// Rest of the function...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
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.

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
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.

Support

FAQs

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