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 7 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 7 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!