Zero Knowledge-based NFT Private Airdrop. ๐ finalist EthDenver 22
Zero Knowledge Proof NFT Airdrop
This library contains the tools (Zero Knowledge Proof circuits + smart contracts) needed to run a Zero Knowledge Based NFT Airdrop. DAOs or any other entity can collect commitments from their contributors via web2 platforms in a public way and deploy a private airdrop smart contract that allows these same contributors to use their wallet to redeem their airdrop.
By leveraging Zero Knowledge proof, there is no association between the web2 identity that made the initial commitment and the web3 wallet used to redeem the NFT based on that same commitment
Project finalist at EthDenver 2022 ๐
Miro board to understand how it works
Related Work and Credits
Credit to A16Z (https://github.com/a16z/zkp-merkle-airdrop-contracts). This application modifies the purpose of the core A16Z repo allowing NFT (ERC721) private airdrops as well.
Purpose
Distribute an NFT airdrop without having to collect users address beforehand. Today is very common to see DAOs and other NFT projects asking for the public addresses of their contributors via Google Forms or Airtables in order to run aidrops. This it is a privacy threat for users.
Usage
Setup
npm ito install all the support node packages- Circom setup in order to generate circuits: Circom 2.0 install + snarkjs
- Hardhat configuration
Compile circom circuits and solidity verifier smart contract
- Compile the circuit.circom file. Note: the input in the last line must match the height of the merkle tree. The number of leaves is the amount of commitments you are gonna collect from the users
circom circuits/circuit.circom --sym --wasm --r1cs -o ./build - generate zkey =>
snarkjs plonk setup build/circuit.r1cs build/pot16final.ptau build/circuitfinal.zkey - generate MerkVerifier.sol =>
snarkjs zkey export solidityverifier build/circuit_final.zkey contracts/compiled/MerkVerifier.sol
Deploy smart contracts
npx hardhat run ./scripts/4_deployContracts.ts --network localhost
- ZekoGenerativeNFT.sol, an ERC721 generative NFT contract.
- PrivateAirdrop.sol, used to manage the airdrop.
- MerkVerifier.sol, contract automatically generated by circom as a result of the input circuit. It is used to run the zero knowledge proof verification on-chain.
Mint NFTs
npx hardhat run ./scripts/5_mint721.ts --network localhost
An extra functionality added on ZekoGenerativeNFT.sol (function mintRoleToAirdrop) allows to mint a generative NFT that include a DaoName and a role as on-chain metadata.
Note: this function is not strictly required to the execution of the private airdrop.
Collect Commitments
npx hardhat run ./scripts/6_collectCommitments.ts --network localhost
A commitment is generated from the uses by hashing two private values (a secret and a nullifier). The commitments are collected by the airdrop issuer entity and assembled in a merkle tree. The root of the commitments merkle tree is then stored as state variable in the private airdrop contract.
The commitments are stored (and dynamically updated) into ./public/publicCommitments.txt
Generate Zero Knowledge Proof Call Data
npx hardhat run ./scripts/7_GenerateProofCallData.ts --network localhost
- his/her secret and private nullifier used to creates the commitment (private)
- the public verification key (circuit_final.zkey) - (public)
- the public zero knowledge circuit (circuit.wasm) - (public)
Note: this operation doesn't involve any on-chain transaction and can be privately by the user or in any browser facing app.
Note: the nullifier hash is generated to avoid the double spending starting from the same (valid) proof
Collect the airdrop
npx hardhat run ./scripts/8_collect721.ts --network localhost
Again, the verification process performed by the MerkVerifier contract is able to tell if the inputs passed by the users are associated to any of the commitments used to assemble the merkle tree without revealing which specific commitment is associated with the user that makes the call. The privacy of the user is protected
Check the contracts deployed on Mumbai (Polygon testned)
- ZekoGenerativeNFT.sol
- MerkVerifier.sol
- [PrivateAirdrop.sol]()
Use-cases
- Collect users' commitments via off-chain public channels and distribute airdrop preserving their privacy
- Create identity-based NFT badges that bridge off-chain credentials to on-chain identity in a privacy preserving way(Zero Knowledge based badges created according to someone's role on Discord or Github contribution). This would further then unlock:
To test the contract
- Start your localhost
npx hardhat node - Run the test
npx hardhat test ./test/smartContractTest.js --network localhost