Core Contracts

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

The liquidated RaacNFT will be locked in the StabilityPool contract forever

Summary

The StabilityPool contract is designed to manage a stability pool where users can deposit tokens and participate in liquidations. During the liquidation process, the finalizeLiquidation function in the LendingPool contract transfers NFTs from the liquidated user to the StabilityPool. However, the StabilityPool contract lacks functionality to manage or withdraw these NFTs, leading to potential loss of assets as the NFTs become permanently locked in the contract.

Vulnerability Details

The liquidateBorrower function in the StabilityPool contract calls finalizeLiquidation in the LendingPool contract:

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());
if (userDebt == 0) revert InvalidAmount();
uint256 crvUSDBalance = crvUSDToken.balanceOf(address(this));
if (crvUSDBalance < scaledUserDebt) revert InsufficientBalance();
// Approve the LendingPool to transfer the debt amount
bool approveSuccess = crvUSDToken.approve(address(lendingPool), scaledUserDebt);
if (!approveSuccess) revert ApprovalFailed();
// Update lending pool state before liquidation
lendingPool.updateState();
// Call finalizeLiquidation on LendingPool
lendingPool.finalizeLiquidation(userAddress);
emit BorrowerLiquidated(userAddress, scaledUserDebt);
}

The finalizeLiquidation function in the LendingPool contract transfers the NFTs from the liquidated user to the StabilityPool using the following code:

// 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;

However, the StabilityPool contract does not implement any methods to manage or withdraw these NFTs. As a result, the NFTs are permanently locked in the StabilityPool contract, and there is no way to retrieve or transfer them to another address.

Impact

NFTs transferred to the StabilityPool cannot be retrieved, leading to permanent loss of valuable assets. The impact is High, the likelihood is High, so the severity is High.

Tools Used

Manual Review

Recommendations

To address this issue, the StabilityPool contract should be updated to include functionality for managing and withdrawing NFTs.

Updates

Lead Judging Commences

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

Give us feedback!