NFT Dealers

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

Listing Price Is Stored As `uint32`, Artificially Capping Sale Value And Risking Truncation

Author Revealed upon completion

Listing Price Is Stored As uint32, Artificially Capping Sale Value And Risking Truncation

Description

The protocol prices NFTs in USDC smallest units, so listing prices should support the full range of practical ERC20-denominated sale values.

In Listing, the price field is stored as uint32, and list() also accepts _price as uint32. This unnecessarily caps the maximum listing price to 2^32 - 1, which is only about 4,294.967295 USDC at 6 decimals. Any higher intended price cannot be represented safely. Using such a narrow integer type for token amounts is error-prone and can force unrealistic marketplace limits.

This type choice also breaks fee-tier behavior. The contract defines MID_FEE_THRESHOLD = 10_000e6, but uint32 can store at most 4_294_967_295 (~4,294.967295 USDC), so prices can never exceed the mid threshold. As a result, the high-fee branch in _calculateFees() is unreachable for all valid listings.

struct Listing {
address seller;
//@audit - Medium - price should be a uint256 since USDC already has 6 decimals
uint32 price;
address nft;
uint256 tokenId;
bool isActive;
}

Risk

Likelihood:

  • The issue appears whenever users need to list NFTs above the uint32 ceiling.

  • The risk increases over time as marketplace prices or collateral assumptions grow beyond this narrow range.

Impact:

  • Users cannot list NFTs above an unexpectedly low maximum price.

  • Price handling becomes fragile because token-denominated amounts are stored in an unnecessarily small type.

  • Fee logic is effectively altered: HIGH_FEE_BPS (5%) can never be applied to any listing price.

Proof of Concept

  1. list() accepts _price as uint32, so max storable value is 4_294_967_295.

  2. MID_FEE_THRESHOLD is 10_000e6 (10_000_000_000), which is greater than uint32 max.

  3. In _calculateFees(price):

    • price <= 1000e6 -> low fee branch.

    • price > 1000e6 will still satisfy price <= 10_000e6 because price cannot exceed ~4_294e6.

    • Therefore, the HIGH_FEE_BPS branch (price > 10_000e6) is unreachable.

Recommended Mitigation

Store listing prices as uint256, which is the standard type for ERC20-denominated token amounts.

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 {

Support

FAQs

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

Give us feedback!