zkDrop: A Private Lottery Airdrop System


To motivate this construction, we must map out the current landscape of public crypto airdrops. To encourage participation in their protocol, blockchain-based projects typically send out free ERC-20 tokens to early adopters and active participants in their community. This system of distributing ERC-20 tokens for governance purposes (i.e. token-voting mechanism) is flawed. Participating in these airdrop events requires revealing your public wallet address (i.e. public key), and thereby doxxing your financial history associated with your public identity. Linking your public metamask address to a web3 platform reveals everything about yourself, since your public address is a gateway to publicly available transaction history on the blockchain. Consider, for example, if a protocol decides to blacklist your address from being eligible for an airdrop based on your DAO voting history? This warranted a system enabling users to claim airdrops completely anonymously, without revealing their public keys. Additionally, the private airdrop system incorperates a lottery system on top as another layer, allowing for verifiable randomness and fairness mechanisms for drawing lottery winners. This lottery system would allow an airdroper to specify the percentage of users who would be eligible for an airdrop.

The zero knowledge aspect comes from the fact that proof verification happens without associating the collectors address to the commitment they provided. The collector can prove to the contract that they know the key/secret pair corresponding to a commitment without revealing which commitment they’re associated with.

Application Type


Proposal Overview

Within the scope of this proposal, the goal is to implement the following components:

  1. Frontend for users to set up their own private lotteries using their own funds and parameters. Currently, the service is centralized and implements a single lottery. The lottery is broken up into an official lottery and sample demo lottery.

  2. Expand the functionality and documentation of the frontend that instructs users how to set up their own lotteries. Documentation will be hosted on GitBook.

  3. Expand system to incorporate a simple reputation service meeting certain on-chain requirements (i.e. checking whether users have more than 10 ONE in their wallet). This requires a combination of semaphores and/or some external oracle service (trusted third-party entity) verifying the validity of the on-chain information before creating the proof. This system would replace the current mechanism for collecting commitments, which is submitted through a centralized provider like Github Gist.

Use Case

Conduct a private airdrop system with a lottery service where users can retrieve ERC-20/ERC-721 airdrops privately without revealing their identity. Private lotteries are essential for applications that reward users on their participation while keeping their identities anonymous.

Competitive Landscape

My application modifies the A16Z core repo (GitHub - a16z/zkp-merkle-airdrop-lib) by modifying and incorporating proxy patterns to the smart contracts and adding a lottery system, implementing ERC-721 (in addition to ERC-20) private airdrops, and interactive NextJS UI. Another competing project includes a more complicated infrastructure that requires two-wallets and ECDSA signature schemes: GitHub - nalinbhardwaj/stealthdrop: Anonymous Airdrops using ZK-SNARKs. Additionally, they both lack reputation service for collecting commitments, which is in the product roadmap.

Proposal Ask

zkDrop is built to be community-driven and self-funded by the DAO. In order to get this up and running, we will be requesting the $15k/year stable basic income to take care of initial development, welfare, and operations costs.

This ask will be in line with the laid down milestones as detailed below

  1. Launching a feature-complete product on our testnet
  2. Forming a DAO with 5-out-of-9 multisig with our DAOs
  3. Launching on our mainnet with audit
  4. Attracting 1k daily active users (with launch video, full PR promotion)
  5. Attracting 10k daily active users (with a detailed roadmap, governance process)

Road Map

Objective Date Status
Testnet launch April 26th Done
Beta Testing and Fixes May 15th Done
Mainnet Launch May 23rd Done
Smart Contract Audit June 31st Pending

External links

Source Code: GitHub - TalDerei/ZKDrop: zkDrop: A Private lottery airdrop system using zero-knowledge proofs to preserve privacy and anonymity
Production Link: https://zk-drop.vercel.app/
Demo Video: Private Airdrops - YouTube
Github Gist: ZKDrop_Claim_Gist.md · GitHub

Mainnet Smart Contracts:
ERC-20 Contract Address: 0xc1D0A7DD443A621BF533Ff58ad9B9B29A1663D0A
NFT Contract Address: 0x317712AD0EEaa0314F2e4C65843E6E16c1B0566F
Lottery Verifier Contract Address: 0x2010b60eF4B67AeA8A7D89839f7F7f4739FB63f8
Private Lottery Clone Contract Address: 0xd7f4315f0ad69858e54e1336b56383efEE2b8e56
Private Lottery Factory Contract Address: 0x1d55C4e6be13250Fe4Ad8E0Fa4CC41D3246768F3
Private Lottery Proxy Contract Address: 0x8a2A73572866383859d9dce07b7A8877C8Ca01fF

Screenshots of the dApp

I’m a pretty reasonably okay Dev and I can honestly say that github is like reading Eskimo Chinese. Especially the zk merkle section.

1 Like

A couple of improvements are needed before we can approve this proposal:

  • “Calculate Proof” prompts an alert to wait but an alert will actually pause all browser processes and block the proof generation process unless the user clicks OK
  • I think an on-chain submission of the commitment, i.e. the process of entering the lottery, would be needed to make this feature-complete product - the idea is that you can enter the lottery by inserting your commitment with one wallet, but then you can withdraw from another - the current process of pasting your commitment off-chain is simply not a satisfactory solution
  • The sample lottery can either make use of the above insertion process or generate more sample commitments so that more users can test the product
  • [trivial] Is there a reason why the sample lottery airdrop amount is so small? I almost thought I didn’t receive anything. Since it’s a sample token anyways, might as well make the airdrop amount larger?
  • [optional] you can also use Harmony’s VRF for random number generation instead of a random function that is based on block properties (which is known to validators)
1 Like

Thanks for the feedback, here’s some of my own thoughts regarding the aforementioned:

  • I agree, UI refactoring is necessary to make the proof generation process more intuitive and interactive. I’ll start by changing the alert to be non-blocking and avoid pausing all browser processes. I’ll be adding more informative error handling as well. I’m currently working on an instructions page describing how to interact with the sample lottery, as well as how the broader proof generation and verification process functions.

  • The original idea regarding off-chain commitments was two-fold:
    [1] It creates a mechanism for bridging off-chain credentials to on-chain identity in a privacy preserving manner.
    [2] Eliminates on-chain gas fees for entering the lottery. There’s a centralization trade-off there by requiring a centralized provider like Github Gist / MongoDB Database to collect the commitments off-chain. Implementing an on-chain solution for collecting commitments requires modifying the existing smart contracts. Currently, a operator deploying the private lottery airdrop contracts (myself) has to pay the gas costs for publishing the root hash and array of commitments (as calldata for reconstructing state on-chain) for setting up the lottery. On-chain commitments would essentially transfer the gas costs to the end-user by having them store the commitments on-chain rather than the private lottery operator. But, since the gas costs on the Harmony chain are trivial, I think on-chain commitments make sense as well. But, there’s one major problem that’s prevented me from implementing on-chain commitments…what’s to stop users from entering the lottery multiple times and potentially exploiting the max number of commitments supported by the smart contract. There either needs to be a mechanism in place for verifying one user = one commitment (like an on-chain reputation service), or maybe constraining a single lottery entry per wallet. Thoughts?

  • I was running into gas limit constraints on both the testnet/mainnet when publishing the array of commitments on-chain as calldata, thereby limiting the number of sample commitments to 2^7 (128) commitments originally. Implementing the aforementioned on-chain commitments would alleviate this bottleneck and allow me to increase the number of sample commitments. The circuits are also currently configured to support 2^10 (1024) users, but this number can be increased by modifying the circuit. The only concern is that the underlying proving system is PLONK, and increasing the number of supported users means increasing the number of constraints and size of the zkey file. The current zkey file is 60 MB, and pushing 60 MB through the browser is already non-trivial for some machines. Any ideas in that regard?

  • I’ll definitely increase the airdrop amount. The contracts support both ERC-20 and ERC-721 private transfer functionality. Currently, the sample demo lottery only transfers ERC-20 tokens, and the official lottery will be configured to transfer ERC-721 tokens by setting the URI and metadata.

  • Implementing Harmony’s VRF is in the pipeline, reading up on the implementation details.

Glad that you are considering my suggestions! I think you are absolutely right that a decentralized solution will make more sense for a low gas fee chain like Harmony.

As for the size of the tree and hence the zkey file - I think you can keep it as 2^10 right now. I think if this product eventually gains traction, you can consider then switching back to groth16 and do a setup ceremony.

The on chain commitment and tree insertion is probably top priority right now. Once that is done, we can approve your proposal and you can continue with the rest of the changes before mainnet launch!