Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Single Mapping per NFT Address (Ignoring `tokenId`)

Description

The mapping nftToErc20Info is defined as:

mapping(address nft => ERC20Info) nftToErc20Info;

It stores only one ERC20Info struct per NFT contract address, without considering the tokenId. In many NFT collections, there are multiple token IDs under the same contract. By using nftToErc20Info[nftAddress], the system supports only one fractioned NFT per contract address. Fractioning a second token (tokenId) on the same NFT contract overwrites the information from the first fractioned token.

Impact

  1. Collision Overwrites: Fractioning another tokenId from the same NFT contract overwrites the previous fraction data (erc20 address, balances, etc.).

  2. Loss of Ownership Records: Original fraction owners of tokenId = 1 may lose their claims if the fraction info for tokenId = 2 is written into the same slot.

  3. Inability to Claim: If tokenId mismatch occurs, no one can claim the originally fractioned NFT because that data is lost.

Attack Route

  1. Honest user fractionizes tokenId = 0. The contract stores that fraction info in nftToErc20Info[nftAddress].

  2. A second user calls divideNft(nftAddress, tokenId = 1, someAmount). The contract overwrites the same entry in nftToErc20Info[nftAddress], effectively destroying or hijacking the fraction records for tokenId = 0.

Recommendation

  • Change nftToErc20Info to a double-mapping that keys both the NFT contract address and the tokenId. For instance:

    mapping(address => mapping(uint256 => ERC20Info)) public nftToErc20Info;
  • Reflect this change throughout the contract (e.g., claimNft, sellErc20, transferErcTokens, etc.) so that each token ID has its own fraction data.

Updates

Lead Judging Commences

juan_pedro_ventu Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Wrong nft collection handling

Support

FAQs

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