NFT Dealers

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

updatePrice Bypasses MIN_PRICE Enforcement

Author Revealed upon completion

updatePrice allows price to be set below MIN_PRICE, undermining the protocol's minimum listing invariant

list() enforces a minimum price of 1 USDC (MIN_PRICE = 1e6). However, updatePrice() only checks > 0, allowing an active listing's price to be set to any value from 1 wei upward — effectively making NFTs free or near-free to buy while bypassing the intended minimum.

function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {
require(_price >= MIN_PRICE, "Price must be at least 1 USDC"); // @> enforced at listing
}
function updatePrice(uint256 _listingId, uint32 _newPrice) external onlySeller(_listingId) {
...
require(_newPrice > 0, "Price must be greater than 0"); // @> MIN_PRICE check missing
}

Risk

Risk

Likelihood:

  • A whitelisted seller can exploit this immediately after listing by calling updatePrice(listingId, 1) to drop the price to 1 wei

  • A colluding buyer and seller can use this to transfer NFTs for near-zero cost, circumventing the fee tiers entirely (fees on 1 wei = 0)

Impact:

  • Protocol fee revenue is bypassed entirely — _calculateFees(1) rounds to 0

  • The MIN_PRICE invariant assumed by the rest of the contract is violated, potentially breaking fee calculation assumptions downstream

Proof of Concept

nftDealers.list(tokenId, 1e6); // lists at MIN_PRICE = 1 USDC
nftDealers.updatePrice(tokenId, 1); // drops to 1 wei — no revert
// Colluding buyer calls:
nftDealers.buy(tokenId); // buys for 1 wei, pays 0 fees

Recommended Mitigation

- function updatePrice(uint256 _listingId, uint256 _newPrice) external onlySeller(_listingId) {
- require(_newPrice > 0, "Price must be greater than 0");
+ require(_newPrice >= MIN_PRICE, "Price must be at least 1 USDC");
}
+

Support

FAQs

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

Give us feedback!