NFT Dealers

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

`uint32` price type caps listings at ~4,294 USDC — 5% fee tier unreachable

Author Revealed upon completion

Root + Impact

Description

  • The protocol defines three progressive fee tiers: 1% (up to 1,000 USDC), 3% (up to 10,000 USDC), and 5% (above 10,000 USDC).

  • Listing.price is uint32 (max 4,294,967,295). With 6 decimals, max price is ~4,294 USDC. HIGH_FEE_THRESHOLD is 10,000e6 = 10,000,000,000 which exceeds uint32 max, making the 5% tier dead code. Listings above ~4,294 USDC are impossible.

struct Listing {
address seller;
uint32 price; // @> max ~4,294 USDC with 6 decimals
// ...
}
uint256 private constant MID_FEE_THRESHOLD = 10_000e6; // @> 10B > uint32 max (4.29B)

Risk

Likelihood:

  • Every listing above ~4,294 USDC is impossible — the uint32 parameter rejects it at the ABI level

Impact:

  • Protocol loses fee revenue (3% instead of 5% on high-value sales) and sellers cannot list above ~4,294 USDC

Proof of Concept

function testUint32PriceCap() public {
// type(uint32).max = 4,294,967,295 = ~4,294.97 USDC
// HIGH_FEE_THRESHOLD = 10,000e6 = 10,000,000,000 > uint32 max
// So _calculateFees always hits the <= MID_FEE_THRESHOLD branch
uint256 fee = nftDealers.calculateFees(type(uint32).max);
assertEq(fee, (uint256(type(uint32).max) * 300) / 10_000); // always 3%, never 5%
}

The fee at max uint32 price (~4,294 USDC) returns 3% (MID_FEE_BPS). The 5% tier requires price > 10,000e6 which exceeds uint32 range, so HIGH_FEE_BPS is dead code.

Recommended Mitigation

Change price to uint256 so the full fee schedule works as designed. This also prevents silent truncation for high-value NFTs.

struct Listing {
address seller;
- uint32 price;
+ uint256 price;
// ...
}
- 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!