Core Contracts

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

`burn` function in RToken contract doesn't return the correct expected values, leading to wrong interest rates computation.

Summary

The burn function in RToken contract is defined as follows:

function burn(address from, address receiverOfUnderlying, uint256 amount, uint256 index)
external
override
onlyReservePool
returns (uint256, uint256, uint256)
{
if (amount == 0) {
return (0, totalSupply(), 0);
}
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if (amount > userBalance) {
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index);
_userState[from].index = index.toUint128();
_burn(from, amount.toUint128());
if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount);
}
emit Burn(from, receiverOfUnderlying, amount, index);
// @audit HIGH: third parameter should be amountScaled, leads to wrong interest rates update
return (amount, totalSupply(), amount);
}

We can see that amount is returned twice, but as explained in the function documentation, return values should be:

* @return A tuple containing:
* - uint256: The amount of scaled tokens burned
* - uint256: The new total supply after burning
* - uint256: The amount of underlying asset transferred
*/

This means the third return value should be amountScaled, not amount, as it should be the amount of underlying assets, i.e., the amount multiplied by the index.

The problem arises in ReserveLibrary that makes the call to the burn function:

function withdraw(ReserveData storage reserve, ReserveRateData storage rateData, uint256 amount, address recipient)
internal
returns (uint256 amountWithdrawn, uint256 amountScaled, uint256 amountUnderlying)
{
if (amount < 1) revert InvalidAmount();
// Update the reserve interests
updateReserveInterests(reserve, rateData);
// Burn RToken from the recipient - will send underlying asset to the recipient
(uint256 burnedScaledAmount, uint256 newTotalSupply, uint256 amountUnderlying) = IRToken(
reserve.reserveRTokenAddress
).burn(
recipient, // from
recipient, // receiverOfUnderlying
amount, // amount
reserve.liquidityIndex // index
);
amountWithdrawn = burnedScaledAmount;
updateInterestRatesAndLiquidity(reserve, rateData, 0, amountUnderlying);
emit Withdraw(recipient, amountUnderlying, burnedScaledAmount);
return (amountUnderlying, burnedScaledAmount, amountUnderlying);
}

Both burnedScaledAmount and amountUnderlying represent the amount of interest-bearing RToken that has been burned.

updateInterestRatesAndLiquidity uses amountUnderlying to update interests rates, but this is incorrect as amountUnderlying is not the amount of underlying assets being transferred back to the user.

Also, the Withdraw event is emitted with the same value twice for underlying assets and RToken burned amount, which is incorrect and might lead to front-end integration issues.

Impact

The impact of this vulnerability can be considered as high as it leads to incorrect interest rates computation.

Tools Used

Manual review.

Recommendations

Make sure to return the correct values in burn function so that interests rates are correctly computed in the lending pool after withdrawals. Note that amountScaled is not correctly computed but this is another issue.

function burn(address from, address receiverOfUnderlying, uint256 amount, uint256 index)
external
override
onlyReservePool
returns (uint256, uint256, uint256)
{
...
return (amount, totalSupply(), amountScaled);
}
Updates

Lead Judging Commences

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

RToken::burn returns incorrect underlying asset amount (amount instead of amountScaled), leading to wrong interest rate calculations

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

RToken::burn returns incorrect underlying asset amount (amount instead of amountScaled), leading to wrong interest rate calculations

Support

FAQs

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