Core Contracts

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

Stale Index in StabilityPool Liquidation Due to Missing Index Update

Summary

The liquidateBorrower function in StabilityPool retrieves user debt without first updating the lending pool's index, leading to incorrect debt calculations during liquidations.

Vulnerability Details

In StabilityPool.sol, liquidateBorrower() gets user debt from LendingPool:

function liquidateBorrower(address userAddress) external onlyManagerOrOwner nonReentrant whenNotPaused {
_update();
// Get the user's debt from the LendingPool.
@> uint256 userDebt = lendingPool.getUserDebt(userAddress);
uint256 scaledUserDebt = WadRayMath.rayMul(
userDebt,
@> lendingPool.getNormalizedDebt()
);
// ...
}

The issue is that both getUserDebt() and getNormalizedDebt() rely on the usage index which needs to be updated first via updateReserveState(). Without this update, the debt calculation uses stale indices.

In LendingPool.sol, we can see that getUserDebt() uses the potentially stale index:

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

Impact

  • Incorrect debt calculations during liquidations

  • Users may be liquidated for the wrong amounts

  • Protocol may suffer losses due to under-liquidation

  • Users may suffer losses due to over-liquidation

Tools Used

  • Manual review

Recommendations

Add index update before debt calculations:

function liquidateBorrower(address userAddress) external onlyManagerOrOwner nonReentrant whenNotPaused {
_update();
// Update indices first
+ lendingPool.updateState();
// Now get debt with updated indices
uint256 userDebt = lendingPool.getUserDebt(userAddress);
uint256 scaledUserDebt = WadRayMath.rayMul(
userDebt,
lendingPool.getNormalizedDebt()
);
// ...
}
Updates

Lead Judging Commences

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

StabilityPool: liquidateBorrower should call lendingPool.updateState earlier, to ensure the updated usageIndex is used in calculating the scaledUserDebt

Support

FAQs

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