Core Contracts

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

User may be charged with less interests if borrowed multiple times.

Summary

The RAAC protocol employs a interest accruing system similar as AAVE and Compound, which the index is a variable keeps increasing with time, user's accrued interests are determined by the index difference. When user repays, the increased amount is supposedly to be added to the principles and act as interests accrued. However, there are a few issues here, which makes user to manipulate index to pay less, or in other scenario, user can get charged with less interests than expected.

Vulnerability Details

When user borrow, they need to deposit RAACNFTs as collateral, once collateral ratio is sufficient, they are eligible for borrowing. When they borrow, they are issued DebtTokens to keep track of their borrowed amounts, and when they repay, those DebtTokens are burnt. Here in DebtToken::burn:

uint256 userBalance = balanceOf(from);
uint256 balanceIncrease = 0;
if (_userState[from].index != 0 && _userState[from].index < index) {
uint256 borrowIndex = ILendingPool(_reservePool).getNormalizedDebt(); // usageIndex
balanceIncrease = userBalance.rayMul(borrowIndex) - userBalance.rayMul(_userState[from].index);
amount = amount;
}
_userState[from].index = index.toUint128();

We see the balanceIncreasehere should be the interests accrued, while in the current code it's not used anywhere. Also we notice, _userState.indexis updated to the latest one. If this borrower immediately repay another amount of loan, potentially really amount (1 wei or so), then he may potentially be repaying less, as the difference between indexes is less.

Similarily, we suppose borrower borrows 1000 RWA at timestamp T1, and later at T2, he borrows 500 RWA again. Lastly, at T3, when this borrower is repaying back all the borrowed amount, he will be charged based on T2's index, as it's the last time his index gets updated. But since out of this 1500 RWA, 1000 of them is borrowed at T1, so less interests will be charged because of this. Out of this 1500 RWA, the 1000 RWA and the rest 500 RWA should be considered and calculated separately, as they were borrowed at different times, but in reality, they are grouped together and calculated together as well.

Impact

Interest is charged incorrectly, and it's also possible for an user to manipulate user state's index to pay less interests.

Tools Used

Manual review

Recommendations

Keep track of borrow offer independently, as well as the interests accrued.

Updates

Lead Judging Commences

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

DebtToken::burn calculates balanceIncrease (interest) but never applies it, allowing borrowers to repay loans without paying accrued interest

Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.

DebtToken compound interest only applies between borrows due to mint-based compounding mechanism, causing final borrow period to receive simple interest instead of proper compound interest

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

DebtToken::burn calculates balanceIncrease (interest) but never applies it, allowing borrowers to repay loans without paying accrued interest

Interest IS applied through the balanceOf() mechanism. The separate balanceIncrease calculation is redundant/wrong. Users pay full debt including interest via userBalance capping.

DebtToken compound interest only applies between borrows due to mint-based compounding mechanism, causing final borrow period to receive simple interest instead of proper compound interest

Support

FAQs

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