Core Contracts

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

RToken.sol calculateDustAmount() calculations are wrong, the function will always return 0.

Summary

The calculateDustAmount() is used to let the owner allocate accrued dust into some address in transferAccruedDust(). However the function wrongly calculates the dust amount, which causes the function to always return 0, effectively locking all dust amounts in the contract.

Vulnerability Details

In the function, it first calculate the RToken amount correpsonding to the underlying asset in the contract.

function calculateDustAmount() public view returns (uint256) {
uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this)).rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
uint256 currentTotalSupply = totalSupply();
....

Then it calls totalSupply(), which will return the deposits + interest owed to liquidity providers.

function totalSupply() public view override(ERC20, IERC20) returns (uint256) {
return super.totalSupply().rayMul(ILendingPool(_reservePool).getNormalizedIncome());
}

This is scaled again by the liquidityIndex which inflates the actual amount the protocol owes to the liquidity providers.

function calculateDustAmount() public view returns (uint256) {
....
uint256 totalRealBalance = currentTotalSupply.rayMul(ILendingPool(_reservePool).getNormalizedIncome());
return contractBalance <= totalRealBalance ? 0 : contractBalance - totalRealBalance;
}

The totalRealBalance will always be greater than the contractBalance, thus the function always returns 0.

Impact

Dust can never be collected

Tools Used

Manual Review

Recommendations

A potential solution is to use scaledBalanceOf which will return the total loaned out amount by the protocol, or rayDiv() the totalSupply of RToken with current liquidityIndex. However this wont still return the accurate dust amount since the underlying asset is meant to be loaned out. So comparing the current asset held by the contract in term of RToken and all asset loaned out by the protocol in term of RToken will make the function return 0 in most cases but not always. I think the developers should re-design the whole function.

Updates

Lead Judging Commences

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

RToken dust calculation structurally impossible with outstanding loans or funds deposited in the vault

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

RToken dust calculation structurally impossible with outstanding loans or funds deposited in the vault

Support

FAQs

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