Core Contracts

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

The totalSupply function in the DebtToken.sol contract reports a lower total debt than what users actually owe

Summary

The totalSupply function in the DebtToken.sol contract reports a lower total debt than what users actually owe because it divides the debt amount by the interest index instead of multiplying it. This makes the protocol show less debt than there really is, which can mislead users and systems.

Vulnerability Details

The totalSupply function, is supposed to tell everyone the total amount of debt in the system, including interest. In lending contracts like this, debt grows over time as interest adds up, and this growth is tracked by a number called the "usage index." The index starts at 1.0 and increases like 1.1 if there’s 10% interest, showing how much bigger the debt has gotten.

function totalSupply() public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledSupply = super.totalSupply();
return scaledSupply.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
}

Here, super.totalSupply() grabs the raw total debt stored in the contract, like 100 tokens if that’s what was borrowed and recorded.
ILendingPool(_reservePool).getNormalizedDebt() gets the current index, say 1.1, showing 10% interest has built up.
rayDiv divides the raw debt by the index (100 / 1.1 ≈ 90.91).
The issue is that it uses rayDiv when it should use rayMul. Dividing by the index shrinks the number, but the total debt should grow bigger to include interest.

When someone borrows, say 100 tokens at index 1.0:
The contract stores 100 in super.totalSupply() via the mint function:

uint256 amountToMint = amount + balanceIncrease;
_mint(onBehalfOf, amountToMint.toUint128());

Here, amountToMint is the full debt (e.g., 100), and _mint adds it to the total supply.
As time passes and the index rises to 1.1, the actual debt becomes 100 * 1.1 = 110 tokens because of interest. The balanceOf function gets this right:

function balanceOf(address account) public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledBalance = super.balanceOf(account);
return scaledBalance.rayMul(ILendingPool(_reservePool).getNormalizedDebt());
}

It multiplies by the index (100 * 1.1 = 110), showing the true debt for one user.
But totalSupply does the opposite:
100 / 1.1 ≈ 90.91. This is smaller than the original 100 and way less than the real debt of 110.

Dividing by a number bigger than 1 (like 1.1) makes the result smaller. Imagine you owe $100, and interest makes it $110. If someone accidentally divides $100 by 1.1, they’d say you owe $90.91 which is wrong and less than even the starting amount! The total debt should increase with interest, not shrink.

The raw debt in super.totalSupply() is the actual amount borrowed and recorded—like 100 tokens. As the index grows, totalSupply should scale it up to match the real debt with interest. But rayDiv scales it down instead, flipping the logic backward and underreporting what’s owed.

Impact

  1. It tells users and systems the total debt is lower than it is.

  2. If other parts of the system rely on totalSupply to balance funds, underreporting could mess up how money is managed, risking shortages

Tools Used

Manual Review

Recommendations

To fix this, change totalSupply to multiply instead of divide:

function totalSupply() public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledSupply = super.totalSupply();
return scaledSupply.rayMul(ILendingPool(_reservePool).getNormalizedDebt());
}
Updates

Lead Judging Commences

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

DebtToken::totalSupply incorrectly uses rayDiv instead of rayMul, severely under-reporting total debt and causing lending protocol accounting errors

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

DebtToken::totalSupply incorrectly uses rayDiv instead of rayMul, severely under-reporting total debt and causing lending protocol accounting errors

Support

FAQs

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