NFT Dealers

First Flight #58
Beginner FriendlyFoundry
100 EXP
Submission Details
Impact: high
Likelihood: high

Non-Whitelisted NFT Holders Are Locked Out Of The Secondary Market Contrary To Protocol Design

Author Revealed upon completion

Non-Whitelisted NFT Holders Are Locked Out Of The Secondary Market Contrary To Protocol Design

Description

The README and actor model state that non-whitelisted users can interact with the secondary market, including listing NFTs for sale. In particular, the documented behavior says non-whitelisted wallets can buy, update price, cancel listing, list NFT.

The implementation of list() contradicts that specification by gating the function with onlyWhitelisted. As a result, any NFT holder who is not currently whitelisted is prevented from listing their NFT on the marketplace, even though this is described as supported behavior. This creates a protocol-breaking denial of service for secondary-market participants and can strand purchased NFTs.

//@audit - High - The protocol state that normal user can list NFT for sale, but this function is only accessible by whitelisted users.
function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {
require(_price >= MIN_PRICE, "Price must be at least 1 USDC");
require(ownerOf(_tokenId) == msg.sender, "Not owner of NFT");
require(s_listings[_tokenId].isActive == false, "NFT is already listed");
require(_price > 0, "Price must be greater than 0");
listingsCounter++;
activeListingsCounter++;
s_listings[_tokenId] =
Listing({seller: msg.sender, price: _price, nft: address(this), tokenId: _tokenId, isActive: true});
emit NFT_Dealers_Listed(msg.sender, listingsCounter);
}

Risk

Likelihood:

  • The issue occurs whenever an NFT is owned by a user who is not whitelisted, including secondary buyers that were never added to the whitelist.

  • The owner can remove wallets from the whitelist at any time, so an existing holder can lose the ability to list after acquiring the NFT.

Impact:

  • Secondary-market users documented as supported by the protocol can be blocked from listing and exiting their position.

  • NFTs can become effectively illiquid for non-whitelisted holders, which breaks core marketplace functionality.

Proof of Concept

The following PoC can be put in test/NFTDealersTest.t.sol:

function testNonWhitelistedBuyerCannotListAgainstSpec() public revealed whitelisted {
//Whitelisted user mint and sell NFTs
vm.startPrank(userWithCash);
usdc.approve(address(nftDealers), 20e6);
nftDealers.mintNft();
nftDealers.list(1, 1000e6);
vm.stopPrank();
//Ordinary user buy NFTs
vm.startPrank(userWithEvenMoreCash);
usdc.approve(address(nftDealers), 1000e6);
nftDealers.buy(1);
vm.expectRevert("Only whitelisted users can call this function");
nftDealers.list(1, 2000e6);
vm.stopPrank();
}

Recommended Mitigation

If the intended design is to allow all NFT holders to participate in the secondary market, remove the whitelist restriction from list() and rely on ownership checks instead.

-function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {
+function list(uint256 _tokenId, uint32 _price) external {
require(_price >= MIN_PRICE, "Price must be at least 1 USDC");
require(ownerOf(_tokenId) == msg.sender, "Not owner of NFT");
require(s_listings[_tokenId].isActive == false, "NFT is already listed");
require(_price > 0, "Price must be greater than 0");

Support

FAQs

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

Give us feedback!