Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: medium
Invalid

Missing Holding Period Enables NFT Fraction Front-Running

Summary

The TokenDivider protocol allows NFT fractionalization but lacks protection against metadata-based sniping attacks as specified in ERC-7631's security considerations. The protocol's immediate fractionalization mechanism allows attackers to identify and target rare NFT fractions before they enter the market, potentially leading to unfair market manipulation.

Vulnerability Details

Source Code Reference

According to the ERC-7631 Documentation, which is under the ERC-721,:

"For dual nature collections that offer ERC-721 tokens with differing rarity levels, the ERC-721 metadata should be revealed in a way that is not easily gameable with metadata scraping and ERC-20 token transfers. A recommendation is to require that an ERC-721 token is held by the same account for some time before revealing its metadata."

The TokenDivider contract implements a dual-nature token system where ERC-721 tokens can be fractionalized into ERC-20 tokens. However, it fails to adhere to the security recommendations in ERC-7631, specifically regarding the requirement to hold an ERC-721 token for some time before its metadata is revealed.

The vulnerability exists in the divideNft function

function divideNft(address nftAddress, uint256 tokenId, uint256 amount) onlyNftOwner(nftAddress, tokenId) onlyNftOwner(nftAddress ,tokenId) external {
if(nftAddress == address(0)) { revert TokenDivider__NftAddressIsZero(); }
if(amount == 0) { revert TokenDivider__AmountCantBeZero(); }
ERC20ToGenerateNftFraccion erc20Contract = new ERC20ToGenerateNftFraccion(
string(abi.encodePacked(ERC721(nftAddress).name(), "Fraccion")),
string(abi.encodePacked("F", ERC721(nftAddress).symbol())));
erc20Contract.mint(address(this), amount);
address erc20 = address(erc20Contract);

Example Scenario

The attack begins before any fractionalization occurs. Since the NFT metadata is publicly available and there's no holding period requirement, attackers can monitor valuable NFTs. Looking at the divideNft function:

function divideNft(address nftAddress, uint256 tokenId, uint256 amount)
onlyNftOwner(nftAddress, tokenId) onlyNftOwner(nftAddress ,tokenId) external {
// No holding period check
// No metadata protection
ERC20ToGenerateNftFraccion erc20Contract = new ERC20ToGenerateNftFraccion(...);
}

When a valuable NFT owner decides to fractionalize their NFT, they must call the divideNft function. This transaction will appear in the memepool. The attacker watches for transactions to the TokenDivider contract's divideNft function.

Once fractionalization occurs, the attacker knows the owner will likely list fractions for sale using the sellErc20 function:

function sellErc20(address nftPegged, uint256 price,uint256 amount) external {
if(nftPegged == address(0)) {
revert TokenDivider__NftAddressIsZero();
}
if( amount == 0) {
revert TokenDivider__AmountCantBeZero();
}
ERC20Info memory tokenInfo = nftToErc20Info[nftPegged];
if(balances[msg.sender][tokenInfo.erc20Address] < amount) {
revert TokenDivider__InsuficientBalance();
}
balances[msg.sender][tokenInfo.erc20Address] -= amount;
s_userToSellOrders[msg.sender].push(
SellOrder({
seller: msg.sender,
erc20Address: tokenInfo.erc20Address,
price: price,
amount: amount
})
);

The attacker prepares their buying transaction in advance, knowing the fraction's value based on the already-visible NFT metadata.

As soon as fractions are listed through sellErc20, the attacker can immediately purchase them using the buyOrder function

The attack succeeds because:

  1. The TokenDivider contract never implements the ERC-7631 recommended holding period:

    • NFT owners can fractionalize immediately after acquiring an NFT

    • No require statement checks for any time-based conditions

  2. The metadata is always accessible:

    • No mechanism exists to hide or gradually reveal NFT metadata

Impact

The vulnerability allows attackers to scrape metadata and identify rare NFTs instantly, giving them an unfair advantage. Regular users cannot compete, disrupting the protocol’s fairness. Additionally, the contract does not comply with ERC-7631, which recommends implementing a holding period before revealing metadata for dual-nature token systems. This vulnerability makes it easy for attackers to target rare fractions and undermines the integrity of the fractional NFT market.

Tools Used

Manual Review

Recommendations

  1. To address this vulnerability, add a holding period before revealing metadata as it prevents attackers from knowing which NFTs are rare until after a sufficient time has passed.

  2. Implement a phased metadata reveal system

  • Initially hide NFT metadata when tokens are first acquired

  • Reveal metadata only after the holding period expires

    These changes would bring the protocol into compliance with ERC-7631's security considerations while maintaining its core functionality and improving market fairness.

Updates

Lead Judging Commences

fishy Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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