Core Contracts

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

The protocol calculates dust amount wrongly.

Summary

The protocol calculates dust amount wrongly.

Vulnerability Details

RToken.sol#calculateDustAmount() function is as follows.

function calculateDustAmount() public view returns (uint256) {
// Calculate the actual balance of the underlying asset held by this contract
319 uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this)).rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
// Calculate the total real obligations to the token holders
322 uint256 currentTotalSupply = totalSupply();
// Calculate the total real balance equivalent to the total supply
325 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;
}

On L322, totalSupply() returns value scaled up by liquidityIndex.
But L325 multiplies liquidityIndex recursively.
This is wrong. So totalRealBalance is bigger than normal.

And On L319, contractBalance is value which is scaled down by liquidityIndex from asset's balance.
This value is compared to totalRealBalance. This is error, too.

Impact

This vulnerability causes freezing of funds to RToken.

Tools Used

Manual review

Recommendations

Modify RToken.sol#calculateDustAmount() function as follows.

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());
++ uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this));
// 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;
++ return contractBalance <= currentTotalSupply ? 0 : contractBalance - currentTotalSupply;
}
Updates

Lead Judging Commences

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

Give us feedback!