Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Huff implementation cant mint more than one NFT

Summary

The contract fails to increment the total supply of NFTs with each mint, leading to repeated attempts to mint the same NFT identifier and consequently causing the transaction to revert.

Vulnerability Details

The issue is located in the minting function MINT_HORSE() within the Huff code. The function, designed to mint a new NFT, references the TOTAL_SUPPLY but does not increment it after minting an NFT. This oversight results in the TOTAL_SUPPLY remaining constant, causing every minting attempt after the first to try to mint an NFT with an already existing identifier.

The relevant code from the HorseStore.huff file is as follows:

#define macro MINT_HORSE() = takes (0) returns (0) {
[TOTAL_SUPPLY] // [TOTAL_SUPPLY]
caller // [msg.sender, TOTAL_SUPPLY]
_MINT() // []
stop // []
}

Impact

This bug effectively renders the contract incapable of minting more than one unique NFT, severely limiting the functionality and utility of the NFT contract. It directly contradicts the expected behavior of an NFT minting process, where each minted token should have a unique identifier.

Tools Used

Manual review

Recommendations

To rectify this problem, the following changes are recommended:

  1. Modify the MINT_HORSE() function to increment the TOTAL_SUPPLY each time an NFT is successfully minted. This can be achieved by adding a line of code within the macro to increment the TOTAL_SUPPLY storage variable.

  2. Ensure that the incrementation logic correctly handles potential overflows to maintain contract security.

  3. After implementing the changes, thoroughly test the updated contract to verify that each minting operation results in a unique NFT identifier and that the TOTAL_SUPPLY reflects the correct number of minted NFTs.

Sample fix:

#define macro MINT_HORSE() = takes (0) returns (0) {
[TOTAL_SUPPLY] // [TOTAL_SUPPLY]
sload // [totalSupply]
dup1 // [totalSupply, totalSupply]
caller // [msg.sender, totalSupply, totalSupply]
_MINT() // [totalSupply]
0x01 add // [totalSupply]
[TOTAL_SUPPLY] sstore
stop // []
}

POC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import {Test, console2} from "forge-std/Test.sol";
import {HuffDeployer} from "foundry-huff/HuffDeployer.sol";
import {HorseStore} from "../src/HorseStore.sol";
import {IERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
contract MixedHuffTest is Test {
string public constant NFT_NAME = "HorseStore";
string public constant NFT_SYMBOL = "HS";
string public constant horseStoreLocation = "HorseStore";
HorseStore horseStoreHuff;
HorseStore horseStoreSol;
function setUp() public {
horseStoreSol = new HorseStore();
horseStoreHuff = HorseStore(
HuffDeployer.config().with_args(bytes.concat(abi.encode(NFT_NAME), abi.encode(NFT_SYMBOL))).deploy(
horseStoreLocation
)
);
}
function testMintTwo() public {
address user = makeAddr("user");
deal(user, 1 ether);
vm.warp(10);
vm.roll(10);
vm.startPrank(user);
horseStoreSol.mintHorse();
horseStoreSol.mintHorse();
assertEq(horseStoreSol.totalSupply(), 2);
assertEq(horseStoreSol.balanceOf(user), 2);
// lets try the same with huff version
horseStoreHuff.mintHorse();
// this will revert with message ALREADY_MINTED
horseStoreHuff.mintHorse();
assertEq(horseStoreHuff.totalSupply(), 2);
assertEq(horseStoreHuff.balanceOf(user), 2);
vm.stopPrank();
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Failure to increment total supply on mint

Failure to properly load the totalSupply in Huff

Support

FAQs

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