Confidential DAO Voting Using Homomorphic Encryption
In this blog post, you will discover how homomorphic encryption can enable the creation of confidential Decentralized Autonomous Organizations (DAOs). You will get a practical guide on implementing a confidential DAO with Zama's fhEVM.
What’s a DAO and why do it confidential?
A DAO is a self-governing entity on a blockchain that leverages a governance token to enable token holders to propose and vote on decisions related to the organization. Typically, a DAO consists of two primary smart contracts: the Governor contract, which manages vote proposals and voting processes, and a Token contract that maintains a registry of token holders.
Various voting models exist, such as quorum voting or quadratic voting but regardless of the voting paradigm, the ability to cast a vote depends on token ownership, representing a stake in the project.
In a traditional DAO, voting records are publicly accessible, revealing each user's token holdings and voting choices. In contrast, a confidential DAO employs a confidential token, maintaining the secrecy of both the token quantities and individual votes.
For the purpose of this article, let’s focus on the Compound Protocol as the point of reference.
In the context of this article, you will transform the COMP token contract into a confidential token contract.
The fhEVM introduces new encrypted data types like [.c-inline-code]ebool[.c-inline-code] and [.c-inline-code]euint32[.c-inline-code]. You'll proceed to update properties, including [.c-inline-code]totalSupply[.c-inline-code], [.c-inline-code]balances[.c-inline-code] and others, to use the [.c-inline-code]euint32[.c-inline-code] data type.
A token used within a DAO is close to a traditional ERC-20 token with some distinctions. Rather than solely monitoring a user's token balance at a specific moment, it maintains a historical record of the number of tokens held by each user over time. In the context of a proposal introduced at block N, users are eligible to vote on it using the token holdings they had at that particular block.
The token contract incorporates two methods for managing this historical data: [.c-inline-code]moveDelegates[.c-inline-code] and [.c-inline-code]writeCheckpoint[.c-inline-code].
Whenever a mint, transfer, or delegate takes place, the contract triggers the [.c-inline-code]moveDelegates[.c-inline-code] function to create a checkpoint reflecting the user's token holdings at the current block number.
Transitioning this function to use encrypted integers is relatively straightforward, as illustrated. The primary distinction lies in replacing the default [.c-inline-code]0[.c-inline-code] with [.c-inline-code]TFHE.asEuint(0)[.c-inline-code] to obtain an encryption of zero.
Apart from the function signature, there's no need to make any changes to the [.c-inline-code]writeCheckpoint[.c-inline-code] function: [.c-inline-code]writeCheckpoint[.c-inline-code] will store the encrypted number of votes for a specific block.
Aside from changes in methods like [.c-inline-code]balanceOf[.c-inline-code] or [.c-inline-code]transfer[.c-inline-code] that were already discussed in the ERC-20 article and changes in function signatures, the token contract is good to go.
The Governor contract is responsible for managing proposals and votes. When the token amount is encrypted, you’ll want to keep the vote choice secret as well. To ensure vote confidentiality, we'll make changes to the ciphertext for both the total "for" and "against" votes.
The fhEVM provides a method which acts as a ternary operator on encrypted integers. This method is called cmux. When using [.c-inline-code]TFHE.cmux[.c-inline-code] to assign a value, the result changes, even if the plaintext value remains unchanged. This is useful because each time a vote is cast, both ciphertexts will be updated on the chain.
In our confidential Governor version, there exists a proposal threshold. Essentially, individuals with fewer than a specific number of tokens are ineligible to propose or cancel a vote. Since the amount of votes is encrypted, you must make adjustments to this verification process.
We are doing a homomorphic comparison between the proposal threshold and the number of votes using [.c-inline-code]TFHE.lt[.c-inline-code] which returns an encrypted boolean value. Once decrypted, you can use it with [.c-inline-code]require()[.c-inline-code] function to revert the transaction if needed.
Transitioning a DAO contract from an unencrypted state to an encrypted one has proven to be a straightforward process. fhEVM offers a user-friendly solution for writing smart contracts with encrypted data and performing homomorphic computations.
You can find Governor contract, Comp contract and more examples on the fhEVM repository. If you want to try fhEVM and write your own contract, we have a documentation, community support and even a bounty program.