Core Contracts

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

Double Scaling of Token Amounts in `transfer` and `transferFrom` Functions

Summary

The RToken contract scales token amounts in both the transfer and transferFrom functions and again within the internal _update function. This double scaling causes transferred amounts to be incorrectly calculated, allowing users to end up with more tokens than intended, potentially compromising the token’s economic integrity.

Vulnerability Details

  • transfer function:
    Scales the amount using getNormalizedIncome().

  • transferFrom function:
    Scales the amount using _liquidityIndex.

  • _update function:
    Scales the amount again regardless of prior scaling in the transfer functions.

Code Example

function transfer(address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome()); // First scaling
return super.transfer(recipient, scaledAmount);
}
function _update(address from, address to, uint256 amount) internal override {
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome()); // Second scaling
super._update(from, to, scaledAmount);
}

Issue

  • First scaling: Applied in transfer and transferFrom.

  • Second scaling: Reapplied in _update, leading to the amount being scaled twice.

  • Double scaling leads to token holders receiving disproportionately higher or lower token amounts depending on scaling factors.

Impact

  • Users can exploit this to inflate their token balances, draining protocol reserves.

Tools Used

Manual code review.

Recommendations

Ensure scaling is applied only once during transfers:

Solution 1: Remove Scaling from transfer and transferFrom

Let _update handle all scaling to maintain consistency:

function transfer(address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
return super.transfer(recipient, amount); // No pre-scaling
}

Solution 2: Remove Scaling from _update

If scaling should be handled in transfer functions, bypass scaling in _update:

function _update(address from, address to, uint256 amount) internal override {
super._update(from, to, amount); // No additional scaling
}

By adopting one consistent scaling approach, the protocol prevents unintended inflation or deflation of token balances.

Updates

Lead Judging Commences

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

RToken::transfer and transferFrom double-scale amounts by dividing in both external functions and _update, causing users to transfer significantly less than intended

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

RToken::transfer and transferFrom double-scale amounts by dividing in both external functions and _update, causing users to transfer significantly less than intended

Support

FAQs

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

Give us feedback!