Build an ERC721A NFT Whitelist Smart Contract (Solidity & Foundry)
ERC721a was developed to address previous high gas requirements in the ERC721 standard.

Build an ERC721A NFT Whitelist Smart Contract (Solidity & Foundry)

In this article you will learn how to write an NFT whitelist smart contract in Solidity utilizing a Merkle Binary Tree and Foundry for testing.

In 2017, I bought my first bitcoins (satoshi's) and then learned about rug pulls. In 2021, I found a literal rubbermaid tub of ASIC S9's on Facebook Marketplace which I bought, then installed 30 amp 240v power so I could mine bitcoin in my garage. In 2022, I left 100k oilfield, got a divorce, left my career and moved cross country to start IT - Programming at 34 years old. I am literally all in with zero backup plan. This IS the plan.

Hello and please enjoy this article. I am not an expert with anything in life but I did spend 10 days figuring out what I am about to tell you. So instead of gatekeeping my findings, I will put you on game for free.

As some of you may know, I will be graduating Nova Scotia Community College - NSCC next month in IT - Programming from the COGS campus in Nova Scotia, Canada.

My goal is to break into blockchain Web3 development as my first entrance into software development. I know that this is uncommon for new people to start with because you are dealing with sensitive financial information in a highly volatile and unregulated alternative finance industry.

But that sounds cool, so here I am.

What is the ERC721A?

ERC721A is an upgraded implementation of ERC721 which is the most common standard for writing NFT smart contracts.

ERC721A was created by a team that goes by AZUKI which you can read about here. https://www.azuki.com/en/erc721a

Essentially without making this article super long, ERC721A edits how the ERC721 mint function behaves by changing how the owner data is updated upon a successful mint.

Previously in ERC721 when Bob mints 10 NFT's, ERC721 would loop through each available 0x address and write Bob as the owner. This would create 10 writes to the contract which would be 10 writes worth of gas used to process the transaction.

ERC721A saves gas when minting multiple NFTs at once. ERC721A makes the cost of minting 10 virtually identical as the cost of minting 1.


Gas savings for ERC721A compared to ERC721.

ERC721A saves gas upon mint time by changing the way the owner is written to the smart contract. When Alice mints 3 NFTs the #100 address slot is written as Bob while slot #101 and #102 are not set. It isn't until Bob purchases #103 that the ERC721A decrements the current slot

Owners are set on the first of their batch.

Here you can see how the code works. The owner of the current index is found by decrementing current until the owner != 0. Through this, we have found the last previous owner and since we know the current owner is Bob at #103, we know the previous != 0 address was Alice at #100. So Alice must also own #101 and #102.

Just look at the curr-- to see how they find the previous owner.

How to set up a Whitelist?

Before this project I had no idea of any of this. I was given a task to build this project with a whitelist. But what is a whitelist?

A whitelist is a list of addresses that are allowed to mint our NFTs. Whitelists are often used in pre-sales to give community members first access to a drop.

So after some research of Elliptic Curve Digital Signature Algorithm (ECDSA) and Merkle Binary Trees.

I decided to go with the Merkle Tree solution.

A Merkle Tree is a binary tree structure where you take a list of addresses, hash them together using SHA-256 hashing algorithm to make a root hash.

Once you have one single root hash, you can store this in the smart contract which is an ideal solution because one root hash obviously uses less gas write costs than storing 100 individual addresses.

We then use this root to match the msg.sender address from whoever is trying to mint the NFT with "Proofs". Proofs are essentially the linking hashes of the leafs in the binary tree that are used to connect up to the root node. Which in turn would prove that your address is in fact inside this single root hash!

HL, HIK, HMNOP and HABCDEFGH are proofs of HK existing inside Root

HL, HIK, HMNOP and HABCDEFGH are proofs of HK existing inside Root. This is essentially what our NFT whitelist is. We will have a large number of addresses from users who want to participate in the presale or be the only addresses allowed to mint our new NFTs. They will sign up and give us their public address and we will take those addresses. Once our Presale ends, we will hash the addresses to gether into a root hash, which we will then use to deploy our contract.

When these users go to mint their NFT's since they are on our whitelist, they will be allowed access because we will provide them with our Merkle Tree Proofs that are algorithmically prove that their address they are minting to is in fact on our whitelist.

How to test with Foundry?

I used Foundry to write some basic tests for this contract.

The main thing that I wanted to test was the mint function. Since this was my first time using Foundry, I wasn't sure how Foundry uses msg.sender on the test side.

Initially I was trying to prank the msg.sender INSIDE the test function. But I was continually getting mint function errors where the address I was pranking as msg.sender was not being updated from the "DEFAULT_SENDER".

So I made a post on Stack Exchange (Ethereum). Waited... no replys. Then ended up figuring it out anyway.

The problem was that I needed to make a helper function over in the main contract that I was testing that returned "_msgSenderERC721A();". Then on the test side I made a variable _addr which equalled the return from my helper function, the actual MSG.SENDER.

This was my main problem in the tests that I was stuck on for 3 days.

This mint test loops through the whitelist addresses, pranks the msg.sender to the whitelist address, mints the NFT, then checks that supply changed by the number of mints.

My work is not perfect, but this project is a good beginner job that teaches you the basics of how to write a NFT whitelist smart contract.

//test for the msg.sender
    function test_MintingCoolios() public{
        for (uint256 i = 0; i < whitelistAddresses.length; i++) {
  
        vm.deal(whitelistAddresses[i], 5 ether);
        vm.startPrank(whitelistAddresses[i]);
        address _testAddr = coolios.getMsgSenderFromCoolios(); 
        //assert that the address is the same as the whitelist address
        emit log_address(_testAddr);
        assertEq(_testAddr, whitelistAddresses[i]);
        coolios.mint{value: 100000000000000000 }(proofs[i], 1);
        vm.stopPrank();
        }
        //after the loop of 4 white list addresses have minted,
        //supply should be 4
        uint256 supply = coolios.totalSupply();
        emit log_uint(supply);
        assertEq(supply, 4);
    }        
 //only used for testing the msg.sender in Coolios.t.sol
    function getMsgSenderFromCoolios() public view returns (address) {
        return _msgSenderERC721A();
    }        

Conclusion

I won't bore you with my code. But if you want to view the whole project on my GitHub, the link is below.

The important thing to understand is the general concept here of what ERC721A is and how it works as well as what a whitelist is and how to implement one within a Solidity smart contract.

Good luck to my fellow Nova Scotia Community College - NSCC peers as the year end approaches.

Thank you

Justin



https://github.com/turnwol7/Coolios-ERC721a-Whitelist-NFT-Project/tree/main

#blockchain #web3 #software #halifax #defi #solidity #software #solidity #nft

要查看或添加评论,请登录

Justin Bishop的更多文章

社区洞察

其他会员也浏览了