Core Contracts

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

Incorrect Token Burn Scaling in function burn() in Rtoken.sol

Summary

The variable amountScaled is calculated using amount.rayMul(index), but it is never actually used in the function. This leads to a potential issue where scaled token balances are not properly reduced upon burning, which could cause inconsistencies in the accounting system.

Vulnerability Details

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
if (amount == 0) {
return (0, totalSupply(), 0);
}
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
>> uint256 amountScaled = amount.rayMul(index); // Unused variable
_userState[from].index = index.toUint128();
>> _burn(from, amount.toUint128()); // not used amountScaled
if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount);
}
emit Burn(from, receiverOfUnderlying, amount, index);
return (amount, totalSupply(), amount);
}

Unused Calculation

  • The function computes amountScaled = amount.rayMul(index);, which converts the amount from underlying tokens to scaled tokens.

  • However, amountScaled is never used in the actual burn operation. Instead, _burn(from, amount.toUint128()); burns the raw amount.

Potential Accounting Issues

  • If the protocol tracks balances in scaled form, the incorrect burn method could lead to inconsistencies in the accounting system.

  • This could create unexpected balance discrepancies, especially in interest-bearing token models where scaling is critical.

Impact

  • Incorrect Token Burning: The function may not reduce the correct amount of scaled tokens, leading to inaccurate supply tracking.

  • Potential Accounting Inconsistencies: If scaled tokens are meant to be burned, but raw tokens are burned instead, it could desynchronize token balances from expected values.

  • Hidden Logical Error: Even if this doesn't immediately break functionality, it may cause long-term imbalances in the reserve system.

Tools Used

Manual Review

Recommendations

Use amountScaled in the _burn() Function

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
if (amount == 0) {
return (0, totalSupply(), 0);
}
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index); // Unused variable
_userState[from].index = index.toUint128();
_burn(from, amount.toUint128());
if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount);
}
emit Burn(from, receiverOfUnderlying, amount, index);
return (amount, totalSupply(), amount);
}
Updates

Lead Judging Commences

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

RToken::burn incorrectly burns amount (asset units) instead of amountScaled (token units), breaking token economics and interest-accrual mechanism

Support

FAQs

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

Give us feedback!