We can launch NFTs in the fairest and funniest ways by combining whitelists with community events and gamification. In this video we will explore an implementation of whitelists in an NFTs contract and other ideas that Vitalik proposed in his blog to offer a better experience to the participants.
Before we start
For this tutorial you will need Metamask or another compatible wallet with Goerli funds that you can get from a faucet.
The Smart Contract
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
contract MyWhitelistNFT is ERC721Enumerable, Ownable {
uint256 public price = 0.01 ether;
uint256 public constant MAX_SUPPLY = 10000;
string public baseTokenURI = "https://baseurl.com/";
bool public saleActive = false;
mapping (address => uint256) public whitelistReserved;
constructor () ERC721 ("My MNFT", "MNFT") {
}
// Overide functions
function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI;
}
// Public functions
function mintToken(uint256 _amount) public payable {
uint256 supply = totalSupply();
require( supply + _amount <= MAX_SUPPLY, "Can't mint more than max supply" );
require( msg.value == price * _amount, "Wrong amount of ETH sent" );
if(!saleActive)
{
uint256 reservedAmt = whitelistReserved[msg.sender];
require(reservedAmt > 0 && _amount <= reservedAmt, "Sale isn't active and you are not whitelisted" );
whitelistReserved[msg.sender] = reservedAmt - _amount;
}
for(uint256 i; i < _amount; i++){
_safeMint( msg.sender, supply + i );
}
}
// Admin functions
function editWhitelistReserved(address[] memory _a, uint256[] memory _amount) public onlyOwner {
for(uint256 i; i < _a.length; i++){
whitelistReserved[_a[i]] = _amount[i];
}
}
function setSaleActive(bool val) public onlyOwner {
saleActive = val;
}
function setBaseURI(string memory baseURI) public onlyOwner {
baseTokenURI = baseURI;
}
function withdraw() public payable onlyOwner {
(bool sent, bytes memory data) = owner().call{value: address(this).balance}("");
data;
require(sent, "Failed to send Ether");
}
}
Thanks for watching this video!
Follows us on dev.to and in Youtube for everything related to Blockchain development.