Core Contracts

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

Inconsistent scaling in `transferFrom` function leading to incorrect token transfers

Summary

The transferFrom function in the RToken contract uses an outdated liquidity index for scaling token amounts, while other transfer-related functions use the current normalized income from the lending pool. This can lead to incorrect token transfer amounts.

Vulnerability Details

In the RToken contract, the transferFrom function scales amounts using the stored _liquidityIndex:

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);
}

However, other similar functions like transfer and _update use the current normalized income from the lending pool:

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

The _liquidityIndex value may be outdated compared to the current normalized income, as it's only updated when updateLiquidityIndex is called by the reserve pool.

Impact

  1. Incorrect token transfer amounts when using transferFrom

  2. Users receiving more or fewer tokens than intended, depending on the difference between indices

Tools Used

  • Manual code review

Recommendations

Update the transferFrom function to use the current normalized income:

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);
}
Updates

Lead Judging Commences

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