Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

Predictable Token IDs inside the `BidBeasts_NFT_ERC721::mint` function

Description

  • Token IDs should ideally be unpredictable to prevent front-running and gaming of rare traits or specific token numbers.

  • The contract uses sequential, predictable token IDs starting from 0, making it easy for attackers to predict and potentially front-run specific token mints.

function mint(address to) public onlyOwner returns (uint256) {
@> uint256 _tokenId = CurrenTokenID;
_safeMint(to, _tokenId);
emit BidBeastsMinted(to, _tokenId);
@> CurrenTokenID++;
return _tokenId;
}

Risk

Likelihood:

  • Token IDs are always sequential and predictable for every mint

  • Attackers can easily predict which token ID will be minted next

Impact:

  • Potential front-running if specific token IDs have special significance

  • Gaming of the system if certain token numbers are more valuable

Proof of Concept

function test_MEDIUM_PredictableTokenIds() public {
vm.startPrank(OWNER);
uint256 tokenId1 = nft.mint(ALICE);
uint256 tokenId2 = nft.mint(BOB);
uint256 tokenId3 = nft.mint(ALICE);
vm.stopPrank();
// Token IDs are sequential and predictable
assertEq(tokenId1, 0);
assertEq(tokenId2, 1);
assertEq(tokenId3, 2);
assertEq(nft.CurrenTokenID(), 3); // Next token will be ID 3
}

Recommended Mitigation

+ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
function mint(address to) public onlyOwner returns (uint256) {
- uint256 _tokenId = CurrenTokenID;
+ uint256 _tokenId = uint256(keccak256(abi.encodePacked(CurrenTokenID, block.timestamp, block.difficulty, to))) % 100000;
+ while (_exists(_tokenId)) {
+ _tokenId = (_tokenId + 1) % 100000;
+ }
_safeMint(to, _tokenId);
emit BidBeastsMinted(to, _tokenId);
CurrenTokenID++;
return _tokenId;
}
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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