This repo contains source files of a cross-chain voting protocol for ETHGlobal Istanbul 2023.
Many blockchain projects have governance tokens (such as UNI). Typically, the voting token and DAO smart contracts are deployed on the main Ethereum network. However, a significant portion of the governance tokens are transferred to L2 networks using bridges, stripping them of their governance functionality. Thus, to participate in DAO governance, tokens must be transferred back to the main Ethereum network, which is expensive, inconvenient, and not always fast.
There are numerous governance tokens initially deployed and used for governance on Ethereum L1, which have been partly bridged to various L2 networks. For example:
- Curve | CRV token - no less than 2.5% of the circulating supply is bridged to various L2s (based on Coingecko data - sum of bridged tokens' totalSupply).
- Lido V2 | LDO token - no less than 0.37% of the circulating supply is bridged to various L2s.
- Uniswap V3 | UNI token - no less than 0.23% of the circulating supply is bridged to various L2s.
Currently, the percentage of the circulating supply that is bridged to various L2s is not large. However, it will definitely increase with the growing popularity of L2 solutions and the emergence of the ability to vote with tokens located on L2s.
Since the architecture of L2 networks involves storing the state root on the main network, this state root can be used for storage proofs of governance token balances in the L2 network:
- A user wishing to vote using tokens on an L2 network visits the project's frontend: enters their voting decision (for/against, amount of tokens) and signs it with their private key. The project's backend generates a storage proof that a user with such a balance in L2 votes this way in the election.
- The project's backend aggregates all votes/proofs into a single recursive SNARKs proof and sends it to the L1 voting contract.
Let's consider the architecture and operation of the project step by step:
- When creating a proposal for voting on the main Ethereum network, the snapshot block numbers in each supported L2 are recorded. The governance token balances in each L2 network at the corresponding block can be used for this election.
- A user wishing to vote using tokens on an L2 network visits the project's frontend: enters their voting decision (for/against, amount of tokens) and signs it with their private key. The project's backend checks the user's balance in the L2 network and generates a storage proof (zk proof) that a user with such a balance in L2 votes this way in the election.
- The project's backend accumulates user votes in the form of zk proofs. At the end of the voting period, the project's backend aggregates all votes/proofs into a single recursive SNARKs proof and sends it to the L1 voting contract.
- The main voting contract checks and aggregates proofs from all networks, distributes corresponding votes among the voting options.
npm install
- Install all dependenciesnpm run build
- Build the projectnpm start
- Start the frontend server
npm install
- Install all dependenciesdocker-compose up
- Run Redis in Dockernpm start
- Start the backend server
npm install
- Install all dependencieshardhat compile
- Compile the smart contractshardhat migrate
- Deploy the smart contracts
npm install
- Install all dependenciesnode generate.js
- Generate the zero-knowledge proofs
https://6559b054b025a87e3173ea8c--zk-layer-vote.netlify.app
- VotesTokenL1 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
- GovernerL1 - 0xD7A1DC78F0E90Ab2645E1DbECf6135D17c7dA411
- StateRootL1 - 0xbb8c8E79c34C6420716A6937bF7E3B9226Cc81f5
- TokenL2 - 0xC007267DF5f0f7aEc5fb90CF03b56F051Bc6C89e
- DelegateL2 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
- TokenL2 - 0xbb8c8E79c34C6420716A6937bF7E3B9226Cc81f5
- DelegateL2 - 0x491A7D1A203980Fd5d2cdE093893FcdCf994291e
- TokenL2 - 0xC007267DF5f0f7aEc5fb90CF03b56F051Bc6C89e
- DelegateL2 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
- TokenL2 - 0xC007267DF5f0f7aEc5fb90CF03b56F051Bc6C89e
- DelegateL2 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
- TokenL2 - 0xbb8c8E79c34C6420716A6937bF7E3B9226Cc81f5
- DelegateL2 - 0x491A7D1A203980Fd5d2cdE093893FcdCf994291e
- TokenL2 - 0xC007267DF5f0f7aEc5fb90CF03b56F051Bc6C89e
- DelegateL2 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
- TokenL2 - 0x6c9373BaD4d213Ea0C796cCF039102B43341df24
- DelegateL2 - 0x507d16b08562Bc341775657C18eA2123EFc69FD1
- TokenL2 - 0xC007267DF5f0f7aEc5fb90CF03b56F051Bc6C89e
- DelegateL2 - 0x4d389dA3786036ee0b9aba8E4B99891a925d88D0
Our end goal is to develop an open-source cross-chain governance module that operates on recursive SNARKs and can be integrated with existing governance frameworks like Tally, Snapshot, and others.