Core Contracts

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

`DebtToken::burn`'s Return Values are wrong

Summary

The return values in DebtToken::burn are in incorrect order compared to the natspec, causing LendingPool::_repay & LendingPool::finalizeLiquidation to transfer incorrect token amounts when users repay their debt.

Vulnerability Details

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/DebtToken.sol#L213)

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/DebtToken.sol#L175-L179)

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L422)

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L525)

Current implementation:

return (amount, totalSupply(), amountScaled, balanceIncrease);

Documentation states order should be:

* @return A tuple containing:
* - uint256: The amount of scaled tokens burned
* - uint256: The new total supply after burning
* - uint256: The amount of underlying tokens burned
* - uint256: The balance increase due to interest
*/

In LendingPool::finalizeLiquidation, the values are destructured assuming the documented order:

// Burn DebtTokens from the user
(uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) = IDebtToken(reserve.reserveDebtTokenAddress).burn(userAddress, userDebt, reserve.usageIndex);
// Transfer reserve assets from Stability Pool to cover the debt
IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);

In LendingPool::_repay, the values are destructured assuming the documented order:

(uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);
// Uses amountScaled (which is actually amount) for transfer
IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);

This causes the protocol to transfer the unscaled amount when it should transfer the scaled amount, making users transfer more tokens than they should when repaying debt with accrued interest.

Example:

  • User debt of 100 tokens accrues to 200 tokens (index doubles)

  • User repays or gets liquidiated 50 tokens

  • Protocol transfers 50 tokens when it should transfer ~25 tokens (scaled by new index)

Impact

Users are forced to transfer more tokens than necessary when repaying debt or getting liquidated with accrued interest, as the protocol uses unscaled amounts instead of scaled amounts due to the return value ordering.

Tools Used

Foundry

Recommendations

Fix the return value order in DebtToken::burn:

- return (amount, totalSupply(), amountScaled, balanceIncrease);
+ return (amountScaled, totalSupply(), amount, balanceIncrease);
Updates

Lead Judging Commences

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