Core Contracts

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

User losses there interest earned after they withdraw

Overview

A user can withdraw there deposited assets if they call the withdraw function.

function withdraw(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
if (withdrawalsPaused) revert WithdrawalsArePaused();
// Update the reserve state before the withdrawal
ReserveLibrary.updateReserveState(reserve, rateData);
// Ensure sufficient liquidity is available
_ensureLiquidity(amount);
// Perform the withdrawal through ReserveLibrary
(uint256 amountWithdrawn, uint256 amountScaled, uint256 amountUnderlying) = ReserveLibrary.withdraw(
reserve, // ReserveData storage
rateData, // ReserveRateData storage
amount, // Amount to withdraw
msg.sender // Recipient
);
// Rebalance liquidity after withdrawal
_rebalanceLiquidity();
emit Withdraw(msg.sender, amountWithdrawn);
}

If a user calls the function above they get reserve assets and burn RTokens. our focus is in the burn operation

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);
return (amount, totalSupply(), amount);
}

The function does not add any checks to ensure that if the index in which the user is withdrawing has changed since the time they deposited user has definitely earned some interest. the function just proceeds and sets index to the correct one and burns tokens

POC

  • The burn function does not check whether the index has changed since the user’s last deposit.

  • The user has earned interest over time, but this interest is lost when withdrawing because the function simply updates _userState[from].index and burns tokens.

  • The user is effectively burning their original deposit without accounting for the accrued earnings, which reduces their total withdrawal amount.

  • Lets say User deposits 100 tokens at index 1.0
    Over time, index increases to 2.0, meaning the user’s balance should be More than 100 because of the interest earned during that period
    The user withdraws 100 tokens, expecting to retain their earned tokens
    Burn function resets index without recognizing the accrued interest → The extra tokens are lost

Impact

Loss of funds

Recommendation

The protocol should ensure that before burning tokens, the user’s interest is properly accounted for and included in their withdrawal amount.

Updates

Lead Judging Commences

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

RToken::burn transfers original deposit amount (amount) to users instead of amount plus interest (amountScaled), causing loss of all accrued interest on withdrawals

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

RToken::burn transfers original deposit amount (amount) to users instead of amount plus interest (amountScaled), causing loss of all accrued interest on withdrawals

Support

FAQs

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