| title |
Bad Guys NFT |
| description |
Claiming unlimited NFTs through unvalidated mint amounts |
| type |
Exploit |
| network |
|
| date |
2022-09-02 |
| returned_usd |
0 |
| tags |
|
| subcategory |
|
| vulnerable_contracts |
0xb84cbaf116eb90fd445dd5aeadfab3e807d2cbac |
|
| tokens_lost |
|
| attacker_addresses |
0xBD8A137E79C90063cd5C0DB3Dbabd5CA2eC7e83e |
|
| malicious_token |
|
| attack_block |
|
| reproduction_command |
forge test --match-contract Exploit_Bad_Guys_NFT -vvv |
| attack_txs |
0xb613c68b00c532fe9b28a50a91c021d61a98d907d0217ab9b44cd8d6ae441d9f |
|
| sources |
| title |
url |
RugDoctorApe Twitter Thread |
|
|
|
- Get whitelisted
- Call the whitelist mint function with a high number of
chosenAmount so you mint all available NFTs.
The attacker claimed 400 NFTs in a single transaction. The mistake is in the WhiteListMint function, where anyone whitelisted can pass an arbitrary chosenAmount. The _numberMinted_ map is only updated after calling the function, so the require passes for any number on the first try.
function WhiteListMint(bytes32[] calldata _merkleProof, uint256 chosenAmount)
public
{
require(_numberMinted(msg.sender)<1, "Already Claimed");
require(isPaused == false, "turn on minting");
require(
chosenAmount > 0,
"Number Of Tokens Can Not Be Less Than Or Equal To 0"
);
require(
totalSupply() + chosenAmount <= maxsupply - reserve,
"all tokens have been minted"
);
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
require(
MerkleProof.verify(_merkleProof, rootHash, leaf),
"Invalid Proof"
);
_safeMint(msg.sender, chosenAmount);
}
- The
chosenAmount parameter seems to be useless and would better be a constant of 1 if that was the intended usage.
- Otherwise, if it was intended to allow for more than one mint per accoutn, restrict the
chosenAmount parameter.