Core Contracts

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

Incorrect Handling of Scaled Amount in RToken::_burn()

Summary

The burn function incorrectly uses the raw amount instead of the scaled amountScaled when burning tokens and transferring underlying assets. This leads to an inconsistency in accounting, where the actual burned amount does not reflect the proper scaled value based on the index, potentially leading to incorrect balances and value discrepancies.

Vulnerability Details

Code Snippet

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;
}
// @audit-issue ---->> amount scaled not used
uint256 amountScaled = amount.rayMul(index);
_userState[from].index = index.toUint128();
_burn(from, amount.toUint128()); // Incorrect: should burn `amountScaled`
if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount); // Incorrect: should transfer `amountScaled`
}
emit Burn(from, receiverOfUnderlying, amount, index);
return (amount, totalSupply(), amount);
}

Issue Explanation

The function is designed to burn an amount of tokens and transfer the underlying asset accordingly. However, it incorrectly:

  1. Burns the raw amount instead of amountScaled: The function calculates amountScaled using rayMul(index), but does not use it in the _burn function. As a result, the burned token amount does not reflect the proper scaling factor, leading to incorrect accounting.

  2. Transfers the raw amount instead of amountScaled: The safeTransfer function sends amount tokens instead of amountScaled, which means the receiver gets an unscaled amount, causing an imbalance between the burned tokens and the redeemed underlying assets.

  3. Double Index Update: _userState[from].index = index.toUint128(); is set twice, which is unnecessary and redundant.

Impact

  • Accounting Inconsistencies: The burned amount does not properly reflect the intended value, leading to incorrect total supply calculations.

  • Potential Exploitation: If the contract relies on correct burning mechanics for financial accuracy, users might be able to withdraw more assets than they should.

  • Balance Discrepancies: The underlying asset transfers do not align with the scaled burned amount, leading to incorrect distributions.

Tools Used

Manual review.

Recommendations

To fix this issue:

  1. Use amountScaled instead of amount in _burn:

_burn(from, amountScaled.toUint128());
  1. Transfer amountScaled instead of amount:

IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amountScaled);
  1. Remove redundant index updates:

_userState[from].index = index.toUint128(); // Keep only one update

Conclusion

This vulnerability could lead to financial inconsistencies and incorrect balance accounting within the protocol. Implementing the proposed fixes will ensure proper scaling and accurate token burns and transfers.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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

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