Pieces Protocol

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

Unrestricted minting in ERC20ToGenerateNftFraccion allows creation of unlimited NFT fractions

Unrestricted minting in ERC20ToGenerateNftFraccion allows creation of unlimited NFT fractions

Summary

The ERC20ToGenerateNftFraccion contract allows any address to mint unlimited tokens through an unprotected mint function. This critical vulnerability undermines the entire NFT fractionalization system.

Vulnerability Details

In ERC20ToGenerateNftFraccion, the mint function lacks access controls:

function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}

An attacker can:

  • Call divideNft() to legitimately divide their NFT into, say, 100 tokens.

  • Directly call mint() to create any additional amount of tokens.

  • Trade these tokens using regular ERC20 transfers.

  • Keep enough tokens to claim back the NFT through claimNft().

While TokenDivider includes protected trading functions (sellOrder and buyOrder), these don't prevent the exploit because malicious trading can occur entirely through standard ERC20 transfers, completely bypassing the TokenDivider contract.

Impact

This vulnerability allows attackers to:

  • Create unlimited unauthorized NFT fractions.

  • Sell these fractions to unsuspecting buyers.

  • Maintain enough tokens to reclaim the original NFT.

  • Profit while retaining control of the underlying NFT.

Tools Used

  • Manual review

Recommendations

Add access control to the ERC20ToGenerateNftFraccion contract:

contract ERC20ToGenerateNftFraccion is ERC20, ERC20Burnable {
address public immutable tokenDivider;
constructor(string memory _name, string memory _symbol, address _tokenDivider) ERC20(_name, _symbol) {
require(_tokenDivider != address(0), "Invalid TokenDivider address");
tokenDivider = _tokenDivider;
}
modifier onlyTokenDivider() {
require(msg.sender == tokenDivider, "Only TokenDivider can mint");
_;
}
function mint(address _to, uint256 _amount) public onlyTokenDivider {
_mint(_to, _amount);
}
}

Update TokenDivider's divideNft function to pass its address:

ERC20ToGenerateNftFraccion erc20Contract = new ERC20ToGenerateNftFraccion(
string(abi.encodePacked(ERC721(nftAddress).name(), "Fraccion")),
string(abi.encodePacked("F", ERC721(nftAddress).symbol())),
address(this)
);
Updates

Lead Judging Commences

fishy Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Lack of token access control chekcs

Any person can mint the ERC20 token generated in representation of the NFT

Support

FAQs

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