Core Contracts

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

`RAACNFT` which gets transferred to `StabilityPool` when liquidation happened will be lost

Summary

The StabilityPool has a function to allow manager role to finalize liquidation process by calling liquidateBorrower, in LendingPool, all borrower's collateral (RAACNFTs) will be transferred to StabilityPool, but StabilityPool does not offer a way to use those NFTs, which cause them to be locked in contract.

Vulnerability Details

In LendingPool::finalizeLiquidation:

function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
if (!isUnderLiquidation[userAddress]) revert NotUnderLiquidation();
// update state
ReserveLibrary.updateReserveState(reserve, rateData);
if (block.timestamp <= liquidationStartTime[userAddress] + liquidationGracePeriod) {
revert GracePeriodNotExpired();
}
UserData storage user = userData[userAddress];
uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
isUnderLiquidation[userAddress] = false;
liquidationStartTime[userAddress] = 0;
// Transfer NFTs to Stability Pool
for (uint256 i = 0; i < user.nftTokenIds.length; i++) {
uint256 tokenId = user.nftTokenIds[i];
user.depositedNFTs[tokenId] = false;
raacNFT.transferFrom(address(this), stabilityPool, tokenId); // <=@
}
delete user.nftTokenIds;
// Burn DebtTokens from the user
(uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) = IDebtToken(reserve.reserveDebtTokenAddress).burn(userAddress, userDebt, reserve.usageIndex);
// Transfer reserve assets from Stability Pool to cover the debt
IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);
// Update user's scaled debt balance
user.scaledDebtBalance -= amountBurned;
reserve.totalUsage = newTotalSupply;
// Update liquidity and interest rates
ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, amountScaled, 0);
emit LiquidationFinalized(stabilityPool, userAddress, userDebt, getUserCollateralValue(userAddress));
}

We see upon liquidation, all collateralized NFTs will be transferred to StabilityPool, but this contract does not provide any interface which handles the operation on RAACNFTs, and those NFTs which get transferred will be lost.

Impact

All transferred RAACNFTs will be stuck in StabilityPool

Tools Used

Manual review

Recommendations

Consider allowing managers or trusted roles to transfer out RAACNFTs for further usage.

Updates

Lead Judging Commences

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

Liquidated RAACNFTs are sent to the StabilityPool by LendingPool::finalizeLiquidation where they get stuck

Support

FAQs

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