Core Contracts

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

`RToken::calculateDustAmount()` does incorrect scaling calculations

Summary

The RToken minting and burning dynamics are forked from AAVE, and allow these tokens to automatically calculate deposit interests. This is done by scaling and normalizing the amounts to mint and burn based on deposit indexes. The RToken is combined with the DebtToken to allow dynamic calculations of borrowing and deposit rates, however, deposit rates are calculated based on linear interest, whereas borrowings are calculated with compounding interest. Because of this when depositing, borrowing, and repaying, there are scenarios where repayments will be higher than what depositors will take in as interest, which allows for extra RTokens to accumulate in the contract. This is why the protocol has added the transferAccruedDust function to prevent stuck funds. However, this function does not properly carry out scaling and normalization leading to invalid returns.

Vulnerability Details

Let's look at what the calculateDustAmount() function is doing:

function calculateDustAmount() public view returns (uint256) {
// Calculate the actual balance of the underlying asset held by this contract
uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this)).rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
// Calculate the total real obligations to the token holders
uint256 currentTotalSupply = totalSupply();
// Calculate the total real balance equivalent to the total supply
uint256 totalRealBalance = currentTotalSupply.rayMul(ILendingPool(_reservePool).getNormalizedIncome());
// All balance, that is not tied to rToken are dust (can be donated or is the rest of exponential vs linear)
return contractBalance <= totalRealBalance ? 0 : contractBalance - totalRealBalance;
}

First, we take the contract balance, excluding any accrued deposit interests, and then we take the totalSupply, which returns the normalized total supply of RTokens. Scaling the contractBalance and doing the second rayMul on the already normalized amount is incorrect, as it over-inflates the amount. Because of this, the function will never transfer the full dust amount and there will always be leftovers.

Impact

Broken dust withdrawal functionality.

Tools Used

Manual review

Recommendations

Do not double scale the RToken total supply and the curvUSD balance.

Updates

Lead Judging Commences

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

RToken::calculateDustAmount incorrectly applies liquidity index, severely under-reporting dust amounts and permanently trapping crvUSD in contract

Support

FAQs

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