Provably Fair NFT Launches — NFTGoblin’s Commit/Reveal Scheme

CryptoSec_Group
6 min readMay 13, 2022

--

If you read our previous post, then you’ll know that provably fair reveals can be more important than just protecting user’s from sniping.

One of our founders, NftDoyler, recently worked on the NFTGoblins smart contract, and we wanted to share the steps he took to ensure a provably fair reveal.

Introduction and Additional Resources

We can’t touch on EVERY possible solution or definition for provably fair reveals in this post, but hopefully, we can soon.

That said, in the meantime, here are a LOT of great resources if you’d like to learn more.

This post will serve more as a technical breakdown of the steps taken for NFTGoblins, but please reach out if you’d like to know or see more!

Prelude: The Collection

While having a collection organized isn’t necessary for a proper commit-reveal, it still helps.

In this case, the collection was 2222 pieces of generative art, using something along the lines of (but definitely not exactly) the Hashlips Art Engine.

After the art was generated (and re-generated 1500 times thanks to @Reed_Rawlings), the 1/1s were added and the entire collection was shuffled.

You can find a slightly older version of the NFT-Shuffler script here.

NFT-Shuffler — not pretty, but it works.

Once the collection was shuffled, the metadata and image files were uploaded to IPFS, to be kept hidden until the reveal.

Step 1: The Contract

The first part of a proper commit-reveal scheme should start with the contract.

That said, it IS possible to do this without any prior planning in your smart contract, it just takes a touch of funny business.

If you’d like ideas on that subject, check out this Twitter thread.

@NftDoyler dropping knowledge for commit-reveal schemes.

The first addition to the contract was the idea, and code for, the commit process.

As you can see, the commit method can only be called once, sets the contract’s provenance hash, and sets the futureBlockToUse variable.

A provenance hash (which you can see that I mistyped and just went with) is effectively a hash of all of the NFT images files, concatenated in order. This allows minters to verify that the order of the images was not changed once this process began.

Here are some more resources on provenance hashing, if you’d like to learn more:

Next, is the reveal process.

For the reveal, we take the futureBlockToUse set by commit, take it’s blockhash, convert this to a uint256, and then scale it.

This effectively gives us a pseudo-random number between 1 and MAX_SUPPLY, which we will use to shift the tokenID.

Quick side note, we add 1 to the tokenIdShift so that it cannot be zero in cases where the generated number is cleanly divisible by MAX_SUPPLY. This is so that we can use tokenIdShift > 0 as a check for future steps.

Note that we could STILL end up in a situation where nothing shifts, and this does not remove that scenario. If the tokenIdShift ends up being (MAX_SUPPLY - 1), then adding 1 will make it equal to MAX_SUPPLY. This comment is a reference to that, and a tongue-in-cheek joke about a previous job that Mouse Dev and myself had worked on.

Note: blockhash, even of a future block, is far from perfect randomness. That said, while it cannot be practically manipulated, a miner could throw away blocks that don’t match the values that they want. That said, this should only matter in cases where the expected value of doing this is at least 3e, if not 5e+.

Last, but not least, we have the actual tokenURI method.

Instead of taking a _tokenId and returning that metadata file, we use the shiftedTokenId to obtain the metadata file to return. This will loop to the end of the collection and back to the front, so 2223 would be tokenId 1 in this case, etc.

So, while the person who uploads these files to IPFS would know the ORDER in which the NFTs exist, it would be impossible for them to know where that order starts and ends.

Step 2: Putting it Into Action

With the code and logic in place, it was time to actually implement this process.

First, as mentioned before, the shuffled (but not shifted) images and metadata were uploaded to IPFS.

These links were also kept secret as long as possible, to prevent leaks in general.

Next, once the project was minted out, the provenance hash was generated. This was generated using the previously mentioned NFT-Shuffler tool.

The commit method was then called using this provenance hash.

https://etherscan.io/tx/0xca18e8d0393c654493a2a4233d4968b6194fdebaad2abfa2ffe0955c2a678fda

Note: reveal needs to be called within 256 blocks of commit, or things will break.

Before calling reveal, the baseURI was set on the rendering contract. This was done to prevent OpenSea from getting cranky but probably SHOULD have been called after the reveal.

https://etherscan.io/tx/0xa445998b9329765a18aa8ec17ff63728d5db4d3046e90f003d2e3f125a79c254

Finally, reveal was called, and the collection was revealed without anyone cheating or getting sniped!

https://etherscan.io/tx/0xc9d9adfbf40004cc69f3a5f61c90a021869858b5354eaeee993aa76187624b05

Step 3: The Cleanup

If you’ve been following along, or you are familiar with Tubby Cats, then you’ll know that there is one more slight issue with this solution.

As tokenId gets shifted, there will be a disconnect between the actual tokenId and what is displayed on OpenSea, etc.

Tubby Cats tokenId does not match the asset name.

While this isn’t a HUGE deal, it’s still a minor annoyance for some users and is easily fixable.

The script has not been added to the repository yet and still needs to be cleaned up, but this will fix that right up for you.

This script will take the shiftAmount (which, for NFTGoblins, was 625) and modify the existing metadata files to account for this.

Now, when tokenURI(1) is called, it will still reference 626.json, but this file will have a name and tokenId that references #1.

After this update was made, I updated the baseURI one more time, and users saw no change on their end except for the asset names.

https://etherscan.io/tx/0x2d43552e6c3b6b862223d546f76a75e51dfb854e321bc65b47d6a95a203bc612

Provably Fair NFT Reveals — Conclusion

Hopefully, this provided a straightforward example of a provably fair NFT reveal process, and helps you understand the commit-reveal scheme a bit more.

While this was “just” a free NFT launch during a bear market, hopefully, it will encourage you to expect more from even the most degen of collections.

If you’d like to read the contract in its entirety, you can find it here.

We know that it’s a bit rough out there, so hopefully, you can try to enjoy your stay in Goblin Town!

Let us know if you have any questions regarding this process or web3 security in general. Hopefully, this is accepted into the HonestNFT bounty program, but stay tuned for more content and exploits regardless!

--

--

CryptoSec_Group

Bringing security to the crypto and web3 masses. NFTs, education, tools, tutorials, and more!