Core Contracts

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

RToken.sol:: transferFrom() and transfer() use inconsistent liquidity index sources leading to incorrect token transfers"

Summary

The RToken.sol contract uses inconsistent methods to obtain the liquidity index between its transfer() and transferFrom() functions. While transfer() uses the current liquidity index from the LendingPool, transferFrom() uses a stored _liquidityIndex value that must be manually updated. This inconsistency can lead to incorrect token amounts being transferred if the stored index becomes stale.

Vulnerability Details

The RToken contract implements an interest-bearing token where token balances increase over time based on accrued interest, represented by a liquidity index. When transferring tokens, the actual transfer amount needs to be scaled by this index. However, the contract uses two different approaches to obtain this scaling factor:

  1. In transfer():

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

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

The _liquidityIndex is only updated when the LendingPool calls updateLiquidityIndex(). If this update is not called frequently enough, the stored index will become stale compared to the actual current index from getNormalizedIncome().

Impact

High

  • Users transferring the same amount of tokens through transfer() vs transferFrom() could end up transferring different underlying amounts due to the index discrepancy

  • If _liquidityIndex becomes stale and lower than the current index, transfer() will transfer less tokens than intended

Likelihood

Medium

  • The likelihood depends on how frequently updateLiquidityIndex() is called by the LendingPool

  • The issue exists in the code and requires no special conditions to manifest

  • Any period of time where the indices diverge creates an exploitable condition

Proof of Concept

N/A - Vulnerability is straight forward and sufficient information has been provided priorly.

Recommendations

Always use the current liquidity index from LendingPool for both functions:

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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 about 1 month 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.