Core Contracts

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

Inconsistent Scaling in Token Transfer Functions

Summary

The RToken contract implements token transfers using two different scaling formulas: the transfer function uses the reserve pool’s normalized income while the transferFrom function uses the contract’s stored liquidity index. This inconsistency can lead to incorrect token transfers and misrepresentation of user balances.

Vulnerability Details

In the RToken contract, the two functions that override the standard ERC20 transfer behavior scale the transfer amount differently:

  • transfer Function:

    function transfer(address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
    uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
    return super.transfer(recipient, scaledAmount);
    }

    This function scales the transfer amount by dividing it with the current normalized income obtained from the Reserve Pool via:

    ILendingPool(_reservePool).getNormalizedIncome()
  • transferFrom` Function:

    function transferFrom(address sender, address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
    uint256 scaledAmount = amount.rayDiv(_liquidityIndex);
    return super.transferFrom(sender, recipient, scaledAmount);
    }

    Here, the scaling is performed using the contract’s stored _liquidityIndex.

The inconsistency arises because the two functions rely on different sources for the scaling factor. The normalized income from the Reserve Pool (getNormalizedIncome()) may not always be equal to the stored _liquidityIndex (which is updated via the updateLiquidityIndex function). As a result, transfers initiated via transfer and transferFrom might behave differently, causing discrepancies in user balances and overall token accounting.

Impact

  • Token Accounting Errors:
    If the two scaling factors differ, users may receive or lose an incorrect amount of tokens during transfers, undermining the protocol’s financial accuracy.

  • User Balance Inconsistency:
    Inconsistent scaling can lead to unexpected user balances, potentially causing confusion and disputes among token holders.

Tools Used

  • Manual code review

Recommended Mitigation

  • Standardize Scaling Method:
    Ensure that both transfer and transferFrom use the same scaling factor. Ideally, choose either the normalized income from the Reserve Pool or the stored liquidity index, and apply it uniformly across all transfer operations. For example, if the intended scaling factor is the normalized income from the Reserve Pool, modify transferFrom as follows:

    function transferFrom(address sender, address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
    uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
    return super.transferFrom(sender, recipient, scaledAmount);
    }
  • Review Update Mechanism:
    Alternatively, if the stored _liquidityIndex is preferred for performance or consistency reasons, ensure that the Reserve Pool’s normalized income is regularly synchronized with _liquidityIndex and update the transfer function accordingly.

Updates

Lead Judging Commences

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

RToken::transfer uses getNormalizedIncome() while transferFrom uses _liquidityIndex, creating inconsistent transfer amounts depending on function used

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

RToken::transfer uses getNormalizedIncome() while transferFrom uses _liquidityIndex, creating inconsistent transfer amounts depending on function used

Support

FAQs

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

Give us feedback!