Core Contracts

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

Misordering of DebtToken.burn() parameters lead to incorrect token transfer and update

Summary

The debt() function incorrectly returns its parameters, using "amount" and "amountScaled" interchangeably, leading to confusion and potential errors.

Vulnerability Details

In this line from the _repay()

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L418

(uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);

Looking up to the burn() from the DebtToken contract

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/tokens/DebtToken.sol#L181-#L214

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;
}
_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);
return (amount, totalSupply(), amountScaled, balanceIncrease);
}

The issue lies in the return values of the burn() function, which are incorrectly ordered. It returns (amount, totalSupply(), amountScaled, balanceIncrease), but the calling function expects (amountScaled, newTotalSupply, amountBurned, balanceIncrease). This mismatch means that amountScaled is assigned the underlying amount, while amountBurned is assigned the scaled amount (amountScaled).

This discrepancy propagates to the _repay function and affects subsequent operations, such as the asset transfer here:

IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);

Due to the incorrect assignment, this transfers the underlying amount instead of the intended scaled amount, potentially leading to incorrect token accounting or transfer amounts.

Also this line, its incorrectly reduce the user scaled debt balance by amount scaled instead of underlying amount

user.scaledDebtBalance -= amountBurned;

Tools Used

Manual Review

Recommendations

Fix the orders correctly

Updates

Lead Judging Commences

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

LendingPool functions incorrectly assign DebtToken::burn return values, swapping amountScaled and amountBurned, causing wrong token transfers and debt accounting

This is confusing naming but functionally correct. The variable names are misleading, but that's not a vulnerability.

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

LendingPool functions incorrectly assign DebtToken::burn return values, swapping amountScaled and amountBurned, causing wrong token transfers and debt accounting

This is confusing naming but functionally correct. The variable names are misleading, but that's not a vulnerability.

Support

FAQs

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

Give us feedback!