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

The total supply value used as the token ID is not loaded properly in the mint process, causing every subsequent mint to fail after the first successful one

Summary

Implementation of the HorseStore.huff::MINT_HORSE() function does not load properly the total supply value used to determine the token ID, causing Denial-of-Service (DoS) as it allows only one NFT ever to be minted.

Vulnerability Details

When minting a horse NFT, assigning a unique token ID to each minted NFT is crucial. In the case of the HorseStore.huff::MINT_HORSE() function, the total supply value is used to determine the token ID. However, there is an issue with the function that causes it not to load the total supply value correctly. As a result, the function assigns the same token ID of 0 to every minted NFT, which causes the transaction to fail with the error message ALREADY_MINTED. This issue prevents the successful minting of subsequent NFTs after the first one.

Impact

Only one NFT can ever be minted.

Proof of Concept (PoC)

Add the next test in HorseStoreHuff.t.sol.

function test_MintingHorseRevertsAfterFirstSuccessfulMint(address randomOwner) public {
vm.assume(randomOwner != address(0));
vm.assume(!_isContract(randomOwner));
uint256 horseId = horseStore.totalSupply();
vm.prank(randomOwner);
horseStore.mintHorse(); // first successful mint
assertEq(horseStore.ownerOf(horseId), randomOwner);
vm.expectRevert("ALREADY_MINTED"); // any mint transactions made after the first mint will be reverted
vm.prank(randomOwner);
horseStore.mintHorse();
}

Run a test with forge test --mt test_MintingHorseRevertsAfterFirstSuccessfulMint.

Tools Used

  • Foundry

Recommendations

The value stored at the TOTAL_SUPPLY storage slot must be loaded properly.

Recommended changes to HorseStore.huff::MINT_HORSE() function:

#define macro MINT_HORSE() = takes (0) returns (0) {
[TOTAL_SUPPLY] // [TOTAL_SUPPLY]
+ sload // [totalSupply] retrieve the value stored in the `TOTAL_SUPPLY` slot and push it onto the stack
- caller // [msg.sender, TOTAL_SUPPLY]
+ caller // [msg.sender, totalSupply] update comment with new stack item
_MINT() // []
stop // []
}

Add the next test in HorseStoreHuff.t.sol.

function test_MintMultipleHorses(uint256 amount) public {
amount = bound(amount, 2, 20);
for (uint256 i = 0; i < amount; ++i) {
uint256 horseId = horseStore.totalSupply();
vm.prank(user);
horseStore.mintHorse();
assertEq(horseStore.ownerOf(horseId), user);
}
uint256 totalSupply = horseStore.totalSupply();
assertEq(totalSupply, amount);
}

Run a test with forge test --mt test_MintMultipleHorses.

Updates

Lead Judging Commences

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

Failure to properly load the totalSupply in Huff

Support

FAQs

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