NFT Dealers

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

uint32 listing price caps marketplace at 4294 USDC and makes the 5 percent fee tier permanently unreachable

Author Revealed upon completion

Root + Impact

Description

Listing.price is uint32. With 6-decimal USDC, type(uint32).max = 4,294,967,295 = ~4,294.97 USDC. The protocol defines MID_FEE_THRESHOLD = 10_000e6 (10,000,000,000) for the 5% fee tier, but this value exceeds uint32.max (4,294,967,295). The 5% fee tier in _calculateFees is dead code — mathematically unreachable through any listing flow. Additionally, the marketplace cannot support NFTs priced above ~4,295 USDC.

Risk

Likelihood:

  • This is a compile-time type constraint — every listing is affected, no special conditions needed

  • Any user attempting to list above ~4,295 USDC hits the type ceiling

Impact:

  • The 5% high-fee tier (HIGH_FEE_BPS = 500) is permanently dead code — the protocol's progressive fee model is broken by design

  • NFTs priced above ~4,295 USDC cannot be traded through this marketplace at all

  • At max listing price (~4,294 USDC), fee is 3% instead of intended 5% — 40% fee revenue shortfall for the protocol

Proof of Concept

forge test --match-test test_H03_Uint32PriceCap -vvv

The math:

  • uint32.max = 4,294,967,295

  • MID_FEE_THRESHOLD = 10,000,000,000

  • uint32.max < MID_FEE_THRESHOLD → the else branch (5% fee) is unreachable

function test_H03_Uint32PriceCap() public {
vm.startPrank(alice);
usdc.approve(address(nftDealers), type(uint256).max);
nftDealers.mintNft();
uint32 maxPrice = type(uint32).max; // 4,294,967,295 = ~4294.97 USDC
nftDealers.list(1, maxPrice);
vm.stopPrank();
(,uint32 storedPrice,,,) = nftDealers.s_listings(1);
// HIGH_FEE_THRESHOLD = 10_000e6 = 10,000,000,000 > uint32.max
assertTrue(uint256(storedPrice) < 10_000e6, "5% fee tier unreachable via uint32 price");
assertTrue(uint256(type(uint32).max) < 10_000e6, "uint32 max < MID_FEE_THRESHOLD");
}

Output: Max listing price (USDC): 4294 / HIGH_FEE_THRESHOLD needs (USDC): 10000 — proves the tier is unreachable.

Recommended Mitigation

Root cause — uint32 price field cannot reach fee thresholds defined as uint256:

struct Listing {
address seller;
@> uint32 price; // max value: 4,294,967,295 (~4,294.97 USDC)
address nft;
uint256 tokenId;
bool isActive;
}
@> uint256 private constant MID_FEE_THRESHOLD = 10_000e6; // 10,000,000,000 > uint32.max

Fix — use uint256 for all price fields:

struct Listing {
address seller;
- uint32 price;
+ uint256 price;
address nft;
uint256 tokenId;
bool isActive;
}
-function list(uint256 _tokenId, uint32 _price) external onlyWhitelisted {
+function list(uint256 _tokenId, uint256 _price) external onlyWhitelisted {
-function updatePrice(uint256 _listingId, uint32 _newPrice) external onlySeller(_listingId) {
+function updatePrice(uint256 _listingId, uint256 _newPrice) external onlySeller(_listingId) {

Support

FAQs

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

Give us feedback!