Technical Breakdown of Night Watch
March 7th, 2023

Introduction

Night Watch is an experimental, unique, and deflationary on-chain art collection/game.

It consists of 455 unique, hand-made gifs, each with 15 frames and every frame being an NFT. It makes up the initial total supply of 6825.

Night Watch is deflationary because the same group of animals tends to merge and form an animation when they meet each other in the same wallet. In theory, the maximum supply may decrease by 1500%!

A Night Watch Token Structure
A Night Watch Token Structure

How It Works

Night Watch works with on-chain game logic and open-source, currently off-chain metadata controller. Every trio of animals has been randomly assigned a trio id and frame and is kept on-chain. This way, we can use an on-chain logic to compare the frame and trio ids of every token and merge if applicable. And then generate the metadata (images and attributes) off-chain.

Since Night Watch is completely determinate on-chain and has an open-source off-chain structure, all the logic can be reproduced by everyone and is sufficiently decentralized.

Fair Distribution

All Night Watch tokens were minted to a vault address at launch and then sold through the Vendor smart contract. This ensured that we didn't have to wait until sellout to start the game.

The distribution method for this project differs from others. Instead of directly minting tokens to their wallet, users buy them. The purchasing process involves two steps. First, users utilize the purchaseTokens function to pay and reserve their tokens. After one block of purchase, they can use the claimTokens function to claim their tokens and have them transferred to their wallet. The number of tokens to claim is determined by the hash of the next block, which serves as a randomness seed. This ensures that the randomness of the distribution can be verified by everyone.

Tracking of reserved tokens and creating the parameters for claimTokens are handled by Night Watch API.

Other Layers of Randomness

There are many layers of randomness in Night Watch.

First, we assign a random unique id to each trio using our mapping tool. We use the blockhash of the Night Watch contract deployment block as the seed for randomness.

Then, we randomly assign a trio id and a frame to each token via token-data-generator. This randomness is ensured by the same seed.

The randomness of the purchase events are ensured by the seed of the block following the purchase block. In this manner, Night Watch remains completely transparent at every level of distribution.

Metadata and Image Generation

Since the current blockchain technology doesn’t allow us to generate the entire metadata and the animations on-chain effectively, we are using an open-source metadata server to generate them. However, we made sure our metadata infrastructure is upgradeable in the smart contract. When we are certain an on-chain alternative is capable of doing the image processing Night Watch needs, we will move the metadata and animation generation to on-chain as well and make Night Watch a completely on-chain project.

Optimization

Night Watch needs more on-chain computation than other NFT projects. Thus, the gas usage is a little bit higher than the average NFT project. However, we applied many optimization techniques to make the game run smoothly and as cheaply as possible. Here are some of them:

Bitmapping

Bitmapping is a technique we use immensely to store the data as tiny as possible.

Every token needs to have these data:

  • Array of frames

  • Pointer id for the trios (full animation gifs)

We used bitmapping to store all this data as only 24-bit unsigned integers. Storing them without bitmapping would cost a lot more gas and would undermine the smoothness of the game.

Here is how an example token data works:

Token data breakdown
Token data breakdown

In the frames section, each 1 represents a frame existing, and 0 represents that it is not (right-to-left). For example, in the above example, frames 4 and 10 exist, and the others do not.

The set (trio) id is 69 in the decimal system. So basically, the token data tells us that this NFT should show the trio 69 with only the 4th and the 10th frames and skip the other frames. The metadata server uses this data to generate the animation and the attributes of the token.

Thanks to bitmapping, an on-chain merge of two sets of frames is as easy and optimized as a simple bitwise OR operator

ERC721A

Night Watch utilizes ERC721A for optimized batch minting.

Decentralization Measures

Every decentralized system needs a centralized head-start and needs to remove single points of failure gradually. We are aware of the single points of failure in our project and took some measures to remove them in time.

Centralized Metadata Server

We are using a centralized metadata server because of the technical inefficiencies in the Ethereum blockchain. However, we made sure to make our metadata functions upgradable in our smart contract; this way, we can upgrade to a decentralized/on-chain metadata generation (a rollup or an L2 solution).

Ironically, this creates another single point of failure; the owner of the smart contract can change the metadata smart contract anytime they want. To eliminate this, we added an option to lock changing the metadata contract in the main smart contract. When we make the switch to a decentralized metadata generation server, we will use the “lockState” function to disable the updating of the metadata contract forever.

Other Lockable States

Like metadata contract updating, we can disable manual updating of 3 more states.

  1. Token Data: After the reveal, we will disable the smart contract owner’s ability to update the token data manually. This way, we will have no control over the crew and frame ids of the tokens.

  2. Merge Pause: Before the reveal, merge functions are paused. After the reveal, we will start the merge and lock our ability to pause it.

  3. Transfer Pause: During the reveal, we will pause the token transfer events for a very short time to avoid issues with token data distribution and merge. After that, we will lock our ability to pause transfers.

  4. Vault Change: The vault address we keep Night Watch NFTs to sell, is the only exception to merge in the contract. This wallet doesn’t merge any NFTs, thus it’s a special one. After the project sells out, we’ll change this address to 0 address and lock changing it.

  5. Operator Filtering: The project currently includes an operator filterer to make sure the team receives royalties. If we can find a better option to receive royalties, we’ll disable this feature and lock opening it again.

Open Source Everything

Since we want full transparency, we made all our on-chain and off-chain software open-sourced. This way, you can run every piece of code, and reproduce every step we take to prove it yourself.

Finishing Thoughts

There are many more details we’d like to talk about like why did we choose the current randomness method, how did we optimize RPC usage, how do we keep track of all Purchase, Claim and Transfer events in order to provide correct tokens to users after purchase but leaving it here to keep the article short. We’ll give more insights with articles and tweets in the future.

Night Watch is a work of countless hours of thinking and building. It is highly experimental yet so subtle. It’s a living art project that will thrive over time with its loyal players.

If you have any questions or feedback, contact us on Twitter at @YigitDuman @Kaybidsteps @NightWatchNFT

Subscribe to Yiğit Duman
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from Yiğit Duman

Skeleton

Skeleton

Skeleton