Core Contracts

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

Missing withdrawalsPaused Check in withdrawNFT Function Allows NFT Withdrawals During Paused State

Summary

The LendingPool.sol contract includes a withdrawalsPaused variable intended to halt NFT withdrawals during emergencies or maintenance. However, the withdrawNFT function does not reference this variable, allowing withdrawals even when the withdrawal functionality is explicitly paused.

Vulnerability Details

Declared Pausing Mechanism Ignored:
The contract declares:

bool public withdrawalsPaused = false;

This variable is meant to control the ability of users to withdraw assets. However, the withdrawNFT function lacks a check for withdrawalsPaused.

Affected Function:

  • withdrawNFT

    // @audit-issue : Missing withdrawalsPaused check .
    function withdrawNFT(uint256 tokenId) external nonReentrant whenNotPaused {
    if (isUnderLiquidation[msg.sender]) revert CannotWithdrawUnderLiquidation();
    UserData storage user = userData[msg.sender];
    if (!user.depositedNFTs[tokenId]) revert NFTNotDeposited();
    // update state
    ReserveLibrary.updateReserveState(reserve, rateData);
    // Check if withdrawal would leave user undercollateralized
    uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
    uint256 collateralValue = getUserCollateralValue(msg.sender);
    uint256 nftValue = getNFTPrice(tokenId);
    if (collateralValue - nftValue < userDebt.percentMul(liquidationThreshold)) {
    revert WithdrawalWouldLeaveUserUnderCollateralized();
    }
    // Remove NFT from user's deposited NFTs
    for (uint256 i = 0; i < user.nftTokenIds.length; i++) {
    if (user.nftTokenIds[i] == tokenId) {
    user.nftTokenIds[i] = user.nftTokenIds[user.nftTokenIds.length - 1];
    user.nftTokenIds.pop();
    break;
    }
    }
    user.depositedNFTs[tokenId] = false;
    raacNFT.safeTransferFrom(address(this), msg.sender, tokenId);
    emit NFTWithdrawn(msg.sender, tokenId);
    }

Impact

In situations where withdrawals are paused to prevent potential exploits or maintain system stability, malicious actors or users could still withdraw NFTs, defeating the purpose of the emergency pause mechanism.

Tools Used

Manual Review

Recommendations

Integrate withdrawalsPaused **Check : **Add a conditional check at the start of the withdrawNFT function .

function withdrawNFT(uint256 tokenId) external nonReentrant whenNotPaused {
++ if (withdrawalsPaused) revert WithdrawalsArePaused();
if (isUnderLiquidation[msg.sender]) revert CannotWithdrawUnderLiquidation();
UserData storage user = userData[msg.sender];
if (!user.depositedNFTs[tokenId]) revert NFTNotDeposited();
// update state
ReserveLibrary.updateReserveState(reserve, rateData);
// Check if withdrawal would leave user undercollateralized
uint256 userDebt = user.scaledDebtBalance.rayMul(reserve.usageIndex);
uint256 collateralValue = getUserCollateralValue(msg.sender);
uint256 nftValue = getNFTPrice(tokenId);
if (collateralValue - nftValue < userDebt.percentMul(liquidationThreshold)) {
revert WithdrawalWouldLeaveUserUnderCollateralized();
}
// Remove NFT from user's deposited NFTs
for (uint256 i = 0; i < user.nftTokenIds.length; i++) {
if (user.nftTokenIds[i] == tokenId) {
user.nftTokenIds[i] = user.nftTokenIds[user.nftTokenIds.length - 1];
user.nftTokenIds.pop();
break;
}
}
user.depositedNFTs[tokenId] = false;
raacNFT.safeTransferFrom(address(this), msg.sender, tokenId);
emit NFTWithdrawn(msg.sender, tokenId);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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