Mint your Kanji NFTs here! (Rinkeby)
The solidity source code can be found here.
It is common for NFT projects to rely on a “Whitelist” to control who can mint their NFTs. There are different ways to implement a whitelist. In this post I will go over the ECDSA signature method and how to use it without associating a list of wallet addresses.
Table of Contents
Whitelisting
Whitelisting introduce several major advantages for a NFT project:
- avoiding gas wars amongst users
- more fair launches (spots on the whitelist can be given in the most appropriate and fair way possible before the mint event)
A common implementation approach is to store the merkle root of all the whitelisted addresses on the contract, so that any address can be verified against the merkle tree by submitting a merkle proof that their address is on the whitelist. However this gets tedious when addresses are frequently added or removed from the whitelist (which happens a lot IRL). As a new merkle tree is needed when even just 1 address (merkle leaf) changes.
Another approach is to use ECDSA signatures.
ECDSA Signatures
ECDSA signatures is a type of asymmetric encryption algorithm.
General Idea:
Signing:
Hash(Data) + Signer’s Private Key -> Signature
Public Key Recovery:
Hash(Data) + Signature -> Signer’s Public Key
Data
can be anything. However, anything we put in here will need to be reproduced exactly during the Public Key Recovery, otherwise the public key recovered will not match the Signer’s public key. It is this particular property that allows us to verify the authenticity of the Data
.
Our Approach:
This project implements the ECDSA signtures approach with random alphanumeric strings (Secrets) that are given to users who are allowed to mint. Compare to the common approach of using wallet addresses, using secrets allow the users to use any wallets they wish. Users can also decide on the wallet at the time of minting.
Signing:
Hash(Prefix + User Address + NFT Amount + Contract Address + ChainId + Secret) + Private Key -> Signature
-
Prefix - State the purpose of this message (referencing Ethereum’s
"\x19Ethereum Signed Message:\n"
) - User Address - User wallet that is invoking the transaction
- NFT Amount - Number of NFT to mint (usually 1 for NFT, more useful for ERC20)
- Contract Address - Address of the deployed NFT contract to prevent reply attacke between different deployments
- ChinaId - Chain to execute transaction on to prevent replay attack between different networks (e.g. testnet and mainnet)
- Secret - Secret that is used for minting to prevent same secret from being used again (usually called a nonce)
- Private Key - Signer’s private key
Public Key Recovery:
Hash(Prefix + Sender Address + NFT Amount + Contract Address + ChainId + Secret) + Signature -> Public Key
It is important that the server does its own hashing of the data:
- allows the server to independently get the values of
Sender Address
,Contract Address
andChainId
- prevent the case where data is not actually hashed and the signature is crafted such that an arbitrary address can be recovered
Architecture
There are 3 components to this project:
- React for frontend
- Cloudflare for server
- Solidity for smart contract
The flow of the minting process is illustrated in the diagram below.
Minting AI Generated Kanjis
The NFTs that you’ll be minting are AI generated Kanjis that were produced with sketch-rnn. You can see the collection that has been minted so far in this OpenSea Collection.
Secrets
The secrets are 80 of the most common pinyins for Kanji. Here’s a hint