The RToken
contract, which models Aave's aToken
, incorrectly scales transfer amounts twice due to interactions between the transfer()
, transferFrom()
, and _update()
functions. This results in transferred amounts being lower than intended, leading to fund mismanagement and loss.
The vulnerability originates from how the contract handles token transfers. The RToken.sol::transfer()
and RToken.sol::transferFrom()
functions both manually scale the transfer amount before calling the respective ERC20 functions. However, the _update
function, which is called internally by these functions, also scales the amount.
Affected Code:
In the transfer()
function:
The amount
is scaled using rayDiv(getNormalizedIncome())
.
super.transfer(recipient, scaledAmount)
is called, which triggers _update()
.
_update()
again scales the amount, leading to double scaling.
In the transferFrom()
function:
amount
is pre-scaled using _liquidityIndex
.
super.transferFrom(sender, recipient, scaledAmount)
is called, which triggers _update()
.
_update()
scales the amount again, leading to double scaling.
In the _update()
function:
_update()
further scales the already pre-scaled amount from transfer()
and transferFrom()
.
This issue results in transferred amounts being significantly lower than intended, causing:
Loss of funds for users who expect to transfer full amounts.
Imbalance in the protocol’s internal accounting, affecting interest accrual and redemption calculations.
Potential economic attacks, where attackers could exploit the double scaling to reduce another user’s balances in certain interactions.
Manual review
I would recommend removing the manual scaling in transfer()
and transferFrom()
functions. Let _update()
handle all necessary scaling.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.