Platform: Code4rena
Start Date: 11/08/2022
Pot Size: $40,000 USDC
Total HM: 8
Participants: 108
Period: 4 days
Judge: hickuphh3
Total Solo HM: 2
Id: 152
League: ETH
Rank: 23/108
Findings: 3
Award: $97.21
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: itsmeSTYJ
Also found by: 0x1f8b, 0x52, 0xDjango, Ch_301, Chom, KIntern_NA, PwnedNoMore, Treasure-Seeker, auditor0517, byndooa, cccz, csanuragjain, ladboy233, nine9, shenwilly, thank_you, yixxas, zkhorse
42.8343 USDC - $42.83
In the NFTDropMarketFixedPriceSale
contract, there is a configuration called limitPerAccount
which is defined as "The limit of tokens an account can purchase".
The current code checks the balance of msg.sender
in the mintFromFixedPriceSale
function. This check can be easily bypassed by minting the amount, then transferring to another wallet and then re-minting.
if (IERC721(nftContract).balanceOf(msg.sender) + count > saleConfig.limitPerAccount) { if (saleConfig.limitPerAccount == 0) { // Provide a more targeted error if the collection has not been listed. revert NFTDropMarketFixedPriceSale_Must_Have_Sale_In_Progress(); } revert NFTDropMarketFixedPriceSale_Cannot_Buy_More_Than_Limit(saleConfig.limitPerAccount); }
This code incorrectly checks the balance of msg.sender
instead of internally accounting for how many the wallet has minted.
Easy POC to check is - make the limit 10, then mint 10, transfer 10, mint 10 again.
VS Code
The NFT industry practice is to save the number of mints for msg.sender
in storage. As an example, you can check how Azuki internally accounts for numberMinted
using a storage variable.
#0 - HardlyDifficult
2022-08-17T20:58:38Z
🌟 Selected for report: rbserver
Also found by: 0xc0ffEE, CodingNameKiki, Deivitto, Diraco, IllIllI, KIntern_NA, Lambda, Noah3o6, Treasure-Seeker, ignacio, oyc_109, zeesaw
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L182 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTCollection.sol#L271
The NFTCollection
and NFTDropCollection
contracts use the OZ _mint
instead of _safeMint
.
So, if a contract cannot hold ERC721 tokens and attempts to mint, it does not revert. Instead, the ETH is lost and so are the NFT tokens.
Easy POC is as follows:
onERC721Received
functionVS Code
The NFT industry practice is to use _safeMint
instead of _mint
. Blue chip NFTs such as BAYC, Azuki, Doodles, etc. use _safeMint
.
Note that when we implement _safeMint
, we will also need to add ReentrancyGuard to the mint function to avoid reentrancy attacks to mint over the max supply.
#0 - HardlyDifficult
2022-08-18T12:18:22Z
🌟 Selected for report: Saw-mon_and_Natalie
Also found by: 0x1f8b, 0x52, 0xDjango, 0xNazgul, 0xSmartContract, 0xSolus, 0xackermann, 0xmatt, 0xsolstars, Aymen0909, Bnke0x0, Chom, Deivitto, DevABDee, Dravee, ElKu, IllIllI, JC, Kumpa, Lambda, LeoS, MiloTruck, PwnedNoMore, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Treasure-Seeker, Vexjon, Waze, Yiko, __141345__, apostle0x01, auditor0517, berndartmueller, bin2chen, bobirichman, brgltd, bulej93, c3phas, carlitox477, cccz, cryptphi, csanuragjain, d3e4, danb, delfin454000, durianSausage, erictee, fatherOfBlocks, gogo, iamwhitelights, joestakey, jonatascm, ladboy233, mics, oyc_109, rbserver, ret2basic, robee, rokinot, rvierdiiev, shenwilly, sikorico, simon135, thank_you, wagmi, yash90, zeesaw, zkhorse
41.2059 USDC - $41.21
Botting NFT mints is very common for hyped projects. People create bot contracts to immediately mint as much as they can and then sell in the secondary market for a premium.
Genuine buyers miss out minting the project and there is a lot of negative publicity after that happens.
For some context on botted mints, you can check out how the Adidas mint and the Sevens mint were botted and the aftermath that happened.
There is no bot protection for mints currently in the Foundation contracts.
There is a limitPerAccount
configuration but that is meant to prevent humans from minting more than needed. Even though this check can currently be bypassed (by transferring to another wallet and I've created a separate issue for that), even if it is fixed - it will not stop bot attacks (refer the Adidas' bot attack linked above - people can create subcontracts to mint, transfer to a single owner after minting and self destruct all sub contracts).
VS Code
One effective way to prevent bot attacks is to use ECDSA signatures. Cool Pets implemented the protection very well and that is a contract you may refer to.
#0 - Chomtana
2022-08-16T03:52:20Z
Dup #20 not sure about risk but it's great if it can be upgraded into high risk :)
#1 - HardlyDifficult
2022-08-17T21:20:29Z
Dupe #20
#2 - HickupHH3
2022-08-27T01:59:03Z
warden's primary QA