NFT Dealers

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

### [M-2] `list()` has incorrect modifiers: `onlyWhitelisted` blocks non-whitelisted users, and missing `onlyWhenRevealed` allows listing before reveal

Author Revealed upon completion

Description: The README states that both whitelisted and non-whitelisted users can list NFTs. However, list() is gated by onlyWhitelisted, blocking non-whitelisted users from a function they are entitled to use. Additionally, list() is missing the onlyWhenRevealed modifier, allowing listings to be created before the collection is revealed, which contradicts the two-phase design.

@> function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {

README: "Non whitelisted user/wallet [...] buy, update price, cancel listing, list NFT"
README: "The protocol is revealed [...] users that are whitelisted can now list NFTs for secondary sell"

Impact: Non-whitelisted users cannot access a core feature they are entitled to. Listings can also be created prematurely before the reveal phase.

Proof of Concept:

A non-whitelisted user who legitimately owns an NFT (e.g. bought it or received it) is blocked from listing it, despite the README explicitly granting them this right.

Run forge test --match-test test_poc_M2 -vvv to see the following output:

[PASS] test_poc_M2_listModifierErrors() (gas: 212812)
PoC Test Code
function test_poc_M2_listModifierErrors() public {
vm.startPrank(owner);
nftDealers.revealCollection();
nftDealers.whitelistWallet(userWithCash);
vm.stopPrank();
// Mint NFT with whitelisted user, then transfer to non-whitelisted user
vm.startPrank(userWithCash);
usdc.approve(address(nftDealers), 20e6);
nftDealers.mintNft();
nftDealers.transferFrom(userWithCash, userWithEvenMoreCash, 1);
vm.stopPrank();
// Non-whitelisted user owns the NFT but cannot list it — should be allowed per README
vm.prank(userWithEvenMoreCash);
vm.expectRevert("Only whitelisted users can call this function");
nftDealers.list(1, uint32(100e6));
}

Recommended Mitigation: Remove onlyWhitelisted and add onlyWhenRevealed to list().

-function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {
+function list(uint256 _tokenId, uint32 _price) external onlyWhenRevealed {

Support

FAQs

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

Give us feedback!