Core Contracts

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

`liquidateBorrower` scales user's debt twice

Summary

The method incorrectly multiplies scaledDebtBalance by the usageIndex twice.

Details

Let's observe liquidateBorrower function

function liquidateBorrower(address userAddress) external onlyManagerOrOwner nonReentrant whenNotPaused {
_update();
@> uint256 userDebt = lendingPool.getUserDebt(userAddress);
@> uint256 scaledUserDebt = WadRayMath.rayMul(userDebt, lendingPool.getNormalizedDebt());
if (userDebt == 0) revert InvalidAmount();
uint256 crvUSDBalance = crvUSDToken.balanceOf(address(this));
if (crvUSDBalance < scaledUserDebt) revert InsufficientBalance();
bool approveSuccess = crvUSDToken.approve(address(lendingPool), scaledUserDebt);
if (!approveSuccess) revert ApprovalFailed();
lendingPool.updateState();
lendingPool.finalizeLiquidation(userAddress);
}

User debt is fetched through lendingPool.getUserDebt, which calculates it by multiplying their scaled debt balance by the usage index

function getUserDebt(address userAddress) public view returns (uint256) {
UserData storage user = userData[userAddress];
return user.scaledDebtBalance.rayMul(reserve.usageIndex);
}

Afterwards, the output is multiplied by the output of getNormalizedDebt from LendingPool.sol. However, that method also returns the usage index

function getNormalizedDebt() external view returns (uint256) {
return reserve.usageIndex;
}

In the end, scaledDebtBalance is multiplied by the index twice. This inflated value is then checked against the current contract balance and reverts if it's insufficient

uint256 crvUSDBalance = crvUSDToken.balanceOf(address(this));
if (crvUSDBalance < scaledUserDebt) revert InsufficientBalance();

Managers who finalized the liquidation will face cases where the contract would have sufficient balance to cover the liquidation, yet still revert.

Impact

Logic error, inadvertent reverts

Mitigation

Skip the second multiplication

Updates

Lead Judging Commences

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

StabilityPool::liquidateBorrower double-scales debt by multiplying already-scaled userDebt with usage index again, causing liquidations to fail

Support

FAQs

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

Give us feedback!