dabo
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
      • No invitee
    • Publish Note

      Publish Note

      Everyone on the web can find and read all notes of this public team.
      Once published, notes can be searched and viewed by anyone online.
      See published notes
      Please check the box to agree to the Community Guidelines.
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
No invitee
Publish Note

Publish Note

Everyone on the web can find and read all notes of this public team.
Once published, notes can be searched and viewed by anyone online.
See published notes
Please check the box to agree to the Community Guidelines.
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
1
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
--- Title: How to Build a Private DAO on Ethereum breaks: false --- $$ \def\Zq{\mathbb{Z}_q} \def\EE{\mathbb{E}} \def\deq{\mathrel{\mathop:}=} \def\range#1{[{#1}]} \def\PK{\textit{pk}} \def\SK{\textit{sk}} \def\ct{\textit{ct}} $$ # How to Build a Private DAO on Ethereum ### Griffin Dunaif and Dan Boneh --- A [DAO is a form of partnership](https://en.wikipedia.org/wiki/Decentralized_autonomous_organization) where a group of people come together to achieve a shared goal. Recently, a DAO called [ConstitutionDAO](https://en.wikipedia.org/wiki/ConstitutionDAO) formed with the mission of purchasing one of the last remaining physical copies of the Constitution. The DAO raised an astonishing $40 million in under a week to place a bid. However, the DAO was promptly outbid by an individual investor who placed a bid at $43.17 million, just slightly above the assets of ConsutitutionDAO, thereby ensuring that the investor won the auction. Herein lies the problem with the current state of DAOs: their treasuries are public. When ConstitutionDAO was raising money, its entire balance sheet was visible to the public. This property can be detrimental to DAOs and impairs their ability to participate in certain types of auctions. In particular, DAOs cannot participate in sealed bid auctions precisely because their treasuries are public. In the case of ConstitutionDAO, having a public treasury enabled other bidders to know its maximal bid and outbid it. If DAOs are to become widely adopted, particularly by businesses, it is essential that the assets of the DAOs remain private. In particular, only the DAO managers should know the total assets managed by the DAO. There are ample use cases where a private treasury is necessary: an investment DAO may want the size of the fund to remain private, a business may want to keep its current sales numbers private, and of course, a fund participating in auctions needs its treasury to remain private. To solve this issue, we propose a simple treasury design that enables DAOs to utilize private treasuries. This short post explains the inner workings of a private DAO that runs on the Ethereum network. Our protocol is somewhat related to a protocol used by an anonymity mixer called [Tornado.cash Classic](https://tornado.cash/), however the privacy properties of the two protocols are quite different. Most notably, in Tornado.cash the sender and receiver are the same person: a client deposits funds into the Tornado contract and that same client later withdraws the funds. In our settings the sender and receiver are different: anyone can send funds to the DAO, but only the DAO manager can withdraw the funds. We note that a more advanced version of Tornado.cash, called Nova, provides all the features we need. However, Nova is designed to solve a much harder problem. Our Private DAO protocol is much simpler than Nova, but offers a different privacy properties. ## Privacy Goals and high level design The plan is to deploy a single *master contract* on the Ethereum chain, and this one contract will manage many DAOs, similar to the design of [juicebox](https://juicebox.money/#/). This single contract acts as a platform that makes it easy to create and manage DAOs. Every DAO created on this platform has a designated *DAO manager*, or a designated group of managers. Anyone can send funds to a DAO on the platform. However, only the DAO manager can withdraw funds from the DAO it is managing. We aim to provide the following privacy properties: * **Balanace privacy**: When someone sends funds to a DAO managed by the master contract, an observer cannot tell which DAO the funds are for. Clearly, an observer can tell the aggregate amount submitted to all DAOs on the platform by reading the master contract's balance. However, an observer learns nothing about the balance of each DAO, other than this upper bound. * **The DAO manager**: The DAO manager can calculate the current balance of funds sent to its DAO. Moreover, the DAO manager should be able to prove to a 3rd party that the DAO's balance is greater than a certain amount. * **Withdrawal privacy**: When the DAO manager withdraws funds from its DAO, the amount withdrawn is public, but the remaining balance of the DAO remains hidden. * **Non goal:** We stress that we do not aim to provide privacy for end users who contributed funds to the DAO. In particular, an observer may eventually learn the Ethereum addresses who sent funds to the DAO. While we do not aim to provide privacy for contributors, our protocol does provide some privacy. We will come back to this when describing the withdrawal protocol. The last bullet needs more discussion. There are protocols that provide privacy for contributors, such as Tornado.cash Nova, where even the DAO manager does not know the source of the funds to its DAO. However, these designs may be difficult to use in the context of a DAO platform. First, privacy for contributors may complicate KYC requirements. Second, privacy for contributors may complicate the process of issuing refunds to contributors, in case the DAO needs to refund all or some of the contributions. Both issues are solvable, but they complicate the user experience. As such, we believe that our set of privacy goals outlined above is an interesting point in the design space, and one that enables a simple and efficient protocol. <!-- **Privacy for contributors**: The system should not reveal the source of the funds. An observer can see that a specific Ethereum address sent funds to the master contract. However, the observer should not know which DAO received the funds. Moreover, privacy for contributors should be maintained even after that DAO manager withdraws funds from the DAO. --> If the master contract manages sufficiently many DAOs of comparable size, then our privacy goals make it possible for DAOs on the platform to participate in a sealed bid auction. While an observer knows an upper bound on the assets of a particular DAO, it does not know the amount that belongs to that DAO. Moreover, the DAO manager can prove to the auction house that it has sufficient funds to participate in the auction, and can withdraw the funds when it comes time to bid. ## PDAO: A Private DAO Protocol The life cycle of a DAO managed on the platform has three key steps: * **DAO creation**: the DAO manager creates the DAO. This step require no on-chain transations. * **Deposit**: used by an end-user who wants to contrbute funds to the DAO. * **Withdrawal**: used by the DAO manager to withdraw funds from the DAO. We describe these steps in detail in the next three subsections. **Contract initialization**: When the master contract is first deployed it is initialized with an empty Merkle tree $T$ of depth $d$ (say $d = 32$). An empty tree is a tree where all the leaves are zero. The contract stores (i) the root hash of this Merkle tree, and (ii) a counter called *next* that is initially set to zero. This counter indicates the location of the next empty leaf in the tree, counting from left to right. When *next* reaches to $2^{d}-1$, the tree is full and a new contract must be initialized. ### Step 1: Creating a DAO Our protocol uses a finite cyclic group $\EE$ of prime order $q$ with generator $G \in \EE$. For efficiency, we take $\EE$ to be the group of points on the [Grumpkin elliptic curve](https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations) that are defined over the base field. This curve is designed for efficient SNARK proof generation on the Ethereum network. The curve is defined over a prime field $\mathbb{F}_r$, where $r$ is the size of the curve *alt_bn128* used by the [Ethereum pairing precompile](https://eips.ethereum.org/EIPS/eip-197). As such, arithmetic over $\mathbb{F}_r$ can be efficiently implemented by a SNARK prover. Now, to create a DAO, the DAO manager posts a Schnorr public key to the DAO web site. In more detail, the DAO manager samples a random $\alpha$ from $\Zq$, computes $\PK \gets \alpha \cdot G \in \EE$, and posts $\PK$ to the DAO’s website. The manager keeps the secret key $\alpha$ to itself. That’s it. There is no on-chain activity and no gas fees. ### Step 2: A member sends funds to the DAO A client wants to send ETH to the DAO, say a total of $v$ ETH. The client obtains the DAO’s public key $\PK \in \EE$ from the DAO's web site and does the following: 1. Sample a random $\rho$ in $\Zq$; 1. Compute what we call a leaf, which is a pair: $\ \ L = \bigl( \rho \cdot G,\ \ \rho \cdot \PK \bigr) \in \EE^2$; 1. Call the master contract’s *deposit()* function with the argument $L$, sending $v$ ether in the transaction; 1. The master contract accepts the funds and records the expanded leaf $$L’ = \bigl( \rho \cdot G,\ \ \rho \cdot \PK,\ \ v, \ \ n \bigr)$$ in the next unoccupied leaf, from left to right, of the Merkle tree $T$. Here $n$ is the leaf number that is designated for $L'$ in $T$. Specifically, the contract sets $n \gets \textit{next}$ and inserts $L'$ into leaf number *next*. The contract increments the value of *next* by one, and computes the Merkle root of the tree $T$ obtained by adding this new leaf $L'$ to the existing tree $T$ at position $n$. If the tree has depth $d$, then computing the updated Merkle root can be done by storing only $d$ hash values in the contract's storage. Since the leaf $L$ is posted on-chain, and is public for the entire world to see, it is imperative that $L$ reveal nothing about the identity of the DAO that received the funds. In particular, nothing about $\PK$ should be revealed. This easily follows from the hardness of the Decision Diffie-Hellman assumption in the group $\EE$. ### Step 3: the DAO manager withdraws funds When the DAO manager wants to withdraw $w$ ETH from the DAO, it must do so by proving that the DAO was the intended recipient of at least that much ETH. Moreover, those funds should only be withdrawn once. All this must be done without revealing the balance of the DAO to the contract. We will accomplish this by utilizing a SNARK. First, how does the DAO manager even know the balance of the funds sent to the DAO? To do so, the DAO manager will monitor all the deposits sent to the master contract. For every observed leaf $L' = \bigl(P,\ Q,\ v,\ n \bigr)$ the DAO manager uses its secret key $\alpha$ to test if $$\alpha \cdot P = Q.$$ If so, the DAO manager learns that this deposit is intended for its DAO and records that $v$ ETH were added to the DAO balance. Otherwise, this deposit is meant for some other DAO. *A word of caution:* When the DAO manager finds a deposit meant for its DAO it will do a little more work to add the balance to the DAO balanace. It is important that this does not introduce a timing side channel on the DAO manager's machine, otherwise an observer will learn that the current deposit is meant for this DAO. [This paper](https://floriantramer.com/publications/sidechannels20/) discusses this problem in detail. **The withdrawal protocol.** Next, suppose the DAO manager wants to withdraw $w$ ETH from the DAO. We require that there is a subset of leaves $\bigl\{L_i' = (P_i, Q_i, v_i, n_i) \bigr\}_{i=1}^\ell$ that belong to the DAO such that $v_1 + \cdots + v_\ell = w$. A simple withdrawal protocol is for the DAO manager to call the *withdraw()* function on the master contract giving it the argument $$ \begin{align} \label{eq:one} (L_1', \ldots, L_\ell',\ \pi_m,\ \pi_s), \tag{1} \end{align} $$ where * $\pi_m$ is a batch-Merkle proof that proves that $L_1', \ldots, L_\ell'$ are leaves in the Merkle tree $T$ (recall that the master contract stores the Merkle root for $T$), * $\pi_s$ is a batch-Schnorr proof that proves that the DAO manager knows $\alpha \in \Zq$ such that $Q_i = \alpha P_i$ for all $i=1,\ldots,\ell$. Note that batch-Merkle and batch-Schnorr proofs are more efficient than simply repeating a single-instance Merkle or Schnorr proof $\ell$ times. The master contract verifies that 1. the proofs $\pi_m$ and $\pi_s$ are valid with respect to its stored Merkle root, 2. $v_1 + \cdots + v_\ell = w$, and 3. the leaves $n_1, \ldots, n_\ell \in [2^d]$ have not yet been spent. If so, the master contract sends $w$ ETH to the DAO manager, which is the originator of the withdrawal request. It also adds $n_1, \ldots, n_\ell$ to its list of spent leaves so that these leaves cannot be spent again. Note that by revealing which leaves are spent on withdrawal, an observer learns the Ethereum address of the contributor who sent the funds to the DAO. As such, a contributor Alice is anonymous until the point in time when the DAO manager withdraws Alice's contribution from the master contract. Prior to that moment, an observer will know that Alice contributed to the platform, but will not know which DAO received the contribution. **A more efficient withdrawal protocol.** The difficulty with the simple withdrawal protocol above is that the call data $(L_1', \ldots, L_\ell', \pi_m, \pi_s)$ in $\eqref{eq:one}$ can be quite large. Moreover, verifying the Merkle and Schnorr multi-proofs on chain can be quite costly. Both these factors can result in high transaction fees for withdrawing funds from the master contract. We can reduce the withdrawal transaction fees by using a SNARK. Here the DAO manager calls the *withdraw()* function on the master contract giving it the much shorter argument $$(n_1, \ldots, n_\ell, \pi),$$ where $\pi$ is a SNARK proof that the DAO manager knows a witness $$(\alpha, P_1, Q_1, v_1, \ldots, P_\ell, Q_\ell, v_\ell)$$ such that 1. for $i=1,\ldots,\ell$ the leaf $(P_i, Q_i, v_i, n_i)$ is in the merkle tree $T$, 2. for $i=1,\ldots,\ell$ we have $Q_i = \alpha \cdot P_i$, and 3. $v_1 + \cdots + v_\ell = w$. The master contract verifies the SNARK proof $\pi$ and checks that the leaves $n_1, \ldots, n_\ell \in [2^d]$ have not yet been spent. If so, the master contract sends $w$ ETH to the DAO manager, the originator of the withdrawal request. It then adds $n_1, \ldots, n_\ell$ to its list of spent leaves so that these leaves cannot be spent again. Since a SNARK requires a fixed size input, we can set $\ell = 100$, so that the DAO manager can withdraw a batch of up to a hundred leaves at a time. ## Implementation <!-- Our implementation of the system is available here: https://github.com/securitylab/privDAO --> The current implementation features a JavaScript CLI and package, which can be plugged into a graphical user interface. The JavaScript module consists of two functions: *deposit()* and *withdraw()*. The *withdraw()* function runs on the DAO manager's machine and computes a SNARK proof. This is done using the Groth16 SNARK system implemented in *snarkjs*. The PrivateTreasury smart contract is 145 lines of Solidity. It includes a SNARK verifier. In addition, it features the MerkleTreeWithHistory contract from TornadoCash, and the MiMC hash from circomlib.

Import from clipboard

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template is not available.
Upgrade
All
  • All
  • Team
No template found.

Create custom template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

How to use Slide mode

API Docs

Edit in VSCode

Install browser extension

Get in Touch

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Upgrade to Prime Plan

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

No updates to save
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Upgrade

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Upgrade

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully