Core Contracts

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

dos via double for-loop: unlimited nft ownership

Summary

first of all the number of nfts a user can obtain is unspecified in raacnft. if a user owns a large number of nfts, then when the withdrawNFT() function is called, two for-loops are executed, potentially consuming more gas than the block limit allows. in this case, the transaction will fail and not be added to the blockchain.

Vulnerability Details

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++) { // @audit if a user owns an enormous number of nfts?
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);
}
function getUserCollateralValue(address userAddress) public view returns (uint256) {
UserData storage user = userData[userAddress];
uint256 totalValue = 0;
for (uint256 i = 0; i < user.nftTokenIds.length; i++) { // @audit if a user owns an enormous number of nfts?
uint256 tokenId = user.nftTokenIds[i];
uint256 price = getNFTPrice(tokenId);
totalValue += price;
}
return totalValue;
}

inside the withdrawNFT() function, the getUserCollateralValue() function is called, which iterates a for-loop equal to the number of nfts the user owns and in the later part of withdrawNFT() the same operation is performed. in this case, if the loops consume more gas than the block limit allows, the transaction may be reverted.

Impact

if the loops consume more gas than the block limit allows, the transaction may be reverted

Tools Used

code review

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

LendingPool: Unbounded NFT array iteration in collateral valuation functions creates DoS risk, potentially blocking liquidations and critical operations

LightChaser L-36 and M-02 covers it.

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

LendingPool: Unbounded NFT array iteration in collateral valuation functions creates DoS risk, potentially blocking liquidations and critical operations

LightChaser L-36 and M-02 covers it.

Support

FAQs

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