Tornado.Cash has become the largest privacy solution on Ethereum today. Tornado.Cash has been fully autonomous and decentralized, but it’s static — it has no way to evolve. This is a proposal to change that. If this proposal is adopted, then the governance of Tornado.Cash will be entrusted to its users, and Tornado.Cash will be allowed to evolve under the stewardship of its community. This way, the users of Ethereum will control their own privacy protocol.
Here is how a proposal for how the Tornado.Cash governance system could work:
TORN is an ERC20-compatible token with a fixed supply that governs Tornado.Cash. TORN holders can make proposals and vote to change the protocol via governance.
TORN is not a fundraising device or investment opportunity. It will remain non-transferable until the community decides that unlocking transfers via a governance vote, not earlier than 45 days following deployment, would comply with all applicable laws.
Here’s how the initial distribution of TORN would break down:
- 5% (500,000 TORN): Airdrop to early users of Tornado.Cash ETH pools
- 10% (1,000,000 TORN): Anonymity mining for Tornado.Cash ETH pools, distributed linearly over 1 year
- 55% (5,500,000 TORN): DAO treasury, will be unlocked linearly over 5 years with 3 month cliff
- 30% (3,000,000 TORN): Founding developers and early supporters, will be unlocked linearly over 3 years with 1 year cliff
Users who have believed in Tornado.Cash from early on should have a say in governing the protocol. For this reason, early adopters of the protocol will receive an airdrop of TORN.
TORN will be airdropped to all addresses that made deposits into Tornado.Cash ETH pools before block
11400000. TORN will be airdropped in the form of a non-transferable TORN voucher (vTORN) that can be redeemed 1:1 to TORN within 1 year. TORN that aren’t redeemed will be swept into the governance contract after 1 year and become part of the DAO Treasury. Redeemed TORN will be available immediately.
The airdropped amount depends on users’ deposit size and age — larger deposits and older deposits will receive more TORN. Multipliers for deposit size are logarithmic:
So a 100 ETH deposit will get twice as many tokens as a 1 ETH deposit. The multiplier allows large and small users of Tornado.Cash to both have a say in governance.
The exact curve for the time multiplier looks like this:
The exact airdrop formula is the following:
The fundamental principle behind Tornado.Cash is that privacy is a human right, and the more everyone adopts privacy measures, the more secure it is for all of us (much like how HTTPS becoming the default for web browsers made all of us more secure). To this end, users who add to the anonymity set of Tornado.Cash in the future should also receive TORN.
A natural option for distributing tokens is traditional DeFi liquidity mining. But any naive liquidity mining scheme would force users to reveal how much time their deposits spent in a Tornado.Cash pool. This conflicts with Tornado.Cash’s core value: preserving privacy.
That is the driving impetus behind the invention of Anonymity Mining. In Anonymity Mining, users will be able to receive TORN through a two-stage shielded liquidity mining system, which fully preserves user privacy.
After a user deposits into Tornado.Cash, a user will accrue private Anonymity Points (AP) into a shielded account — which shields your wallet address, your balance, and doesn’t leak any information about your deposits. Once the user accumulates enough AP on the user’s shielded account, the user can decide to convert the AP at any time into public TORN tokens via our custom-built Tornado.Cash AMM.
This system is a little complex. But it ensures that user privacy is always protected in the process of claiming TORN tokens.
Note: only notes that are deposited after the deployment ceremony are eligible for Anonymity Mining — earlier notes are distributed TORN via the airdrop.
Here’s how it works, step-by-step:
Claiming your AP
First, users must claim Anonymity Points (AP) for already spent Tornado.Cash notes (AP cannot be claimed until the user spends the notes). After the notes are spent, there is delay before it becomes claimable for AP.
To claim AP, the user’s browser generates a special zero knowledge proof that calculates the AP owed (based on how many blocks the user’s note was in an ETH Tornado.Cash pool) and then adds that to the user shielded balance. Below is a table of AP per block for different Tornado.Cash note sizes:
The only information other users will see on-chain is that someone claimed some AP batch of unknown size for some note for a certain Tornado.Cash pool. To further enhance privacy, the user can claim AP via a relayer (who will accept AP as compensation to cover their relaying costs).
Because AP is completely private, in order to store your shielded AP, the user needs to generate a secret key that stores the user’s AP balance. This key is randomly generated, and then encrypted with your Ethereum public key (using Metamask’s
eth_getEncryptionPublicKey) and stored on-chain. That way, if you lose it, it can be seamlessly recovered using the user’s Ethereum keys.
This secret key is used to encrypt and submit claim and withdrawal data without revealing the user’s identity.
Converting AP into TORN
To then convert your mined AP into publicly visible TORN, you can use the custom-built Tornado.Cash Automated Market Maker (AMM).
TORN is dripped continuously and evenly into this AMM (1M TORN tokens over 1 year). All the AP that is claimed at any point can bid on the TORN that has up to that point accumulated in the AMM.
This does mean that the timing to convert AP into TORN is somewhat strategic — if too many people withdraw at the same time, the rate for AP/TORN conversion ratio contracts, and if few people are withdrawing, the rate improves. However, for the first 45 days, TORN will not be transferable at all.
Here’s a rough analogy: you can imagine TORN tokens are being released by a drip into a bucket (the AMM) over one year. AP tokens let you bid on whatever amount of TORN is in the bucket so far. If there’s a lot of AP bidding at the same time, the bucket will drain really quickly and the rate per AP will be low. But if the AP holders are patient, it should level out over time and everyone should get a roughly equal number of TORN for AP.
That’s the entire process for claiming TORN. Unfortunately there’s some irreducible complexity. But, it’s impossible to know how much AP will get generated over the course of the Anonymity Mining program (since it’s private!), so this is the only way to ensure both that TORN has a fixed supply and that all AP remains shielded until it is converted into public TORN.
The exact AMM formula looks like this:
- T — TORN mining program allocation
- Tvirt — Virtual TORN balance
- Twithdrawn — Amount of TORN that users already withdrawn
- TORN — Amount of TORN that user will receive
- AP — Anonymity points to exchange
- W — AMM exchange weight constant
The Tornado.Cash Proxy
You might wonder how any of this is possible at all — isn’t Tornado.Cash immutable?
It is! The Tornado.Cash smart contracts cannot be changed or updated. They are decentralized and immutable.
But for Tornado.Cash to enable mining, it needs more metadata than is currently available: it needs to know the block number for each Tornado.Cash deposit and withdrawal. To that end, a proxy stands in front of the old Tornado.Cash that adds the current block number to each transaction. Thus, for Tornado.Cash users using the proxy, their notes can be used for Anonymity Mining, since the Merkle tree will contain data about when their deposits took place. (The version of Tornado.Cash without a proxy remains fully functional.)
Note: in order to aggregate deposits and withdrawal to the Merkle trees, someone needs to run a script called the
root-updater. So long as someone out there does this, the system works smoothly and trustlessly. Who handles this role and how it is handled is a decision for the community via governance. For more information on how this works, please check out this repo.
In order to participate in Tornado.Cash governance, users first need to lock tokens in the governance contract. If a user votes or creates a proposal, the tokens cannot be unlocked before the proposal execution period ends (8.25 days from proposal creation). The locked tokens can also be delegated to another address.
To create a proposal, a user needs to have at least 1,000 TORN. All proposals must be smart contracts with verified code that are executed from the governance contract (using
delegatecall). This way, it’s easy to audit and test any governance changes.
The voting period for a proposal is 3 days. A proposal will succeed if it receives a simple majority of votes and there are at least
25,000 TORN total votes (if turnout is too low, the proposal automatically fails).
After a proposal succeeds, it is subject for a timelock of 2 days. After the timelock, any user is able to execute the proposal (which initiates the changes). If proposal is not executed for 3 days after that, it is considered expired and can no longer be executed.
All of these initial parameters are relatively small, since there won’t be many TORN tokens in circulation early on. But as the circulating supply increases, governance may adjust these thresholds.
Governance proposals have the power to change any of Tornado.Cash’s internal parameters, including completely upgrading its implementation (via the proxy, of course).
This brings us to…
At the end of the day, this is just a proposal. We don’t control Tornado.Cash — its users do, so if the community adopts this proposal, then it will become the way forward for privacy on Ethereum.
We’ve written the code, and have published it to GitHub and IPFS.
The GitHub source code can be found at: torn-token, tornado-anonymity-mining, tornado-governance, tornado-initiation-ui. The proposed code is on IPFS with hash QmR3YK3z1okFmfWNhLjGSsdJgUJJRn2NEA7NpeQEAzAi1E, it can be accessed using a convenient shortcut initiation.tornado.cash. Any user can submit deploy transaction for any contract using their Metamask. It uses the CREATE2 and EIP-2470 deployer so all contract addresses are deterministic. The expected addresses of our proposed contracts are:
- deployer.contract.tornadocash.eth: 0xCEe71753C9820f063b38FDbE4cFDAf1d3D928A80
- torn.contract.tornadocash.eth: 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C
- governance-impl.contract.tornadocash.eth: 0xffbaC21a641Dcfe4552920138D90F3638B3c9fba
- governance.contract.tornadocash.eth: 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce
- reward-verifier.contract.tornadocash.eth: 0x88fd245fEdeC4A936e700f9173454D1931B4C307
- withdraw-verifier.contract.tornadocash.eth: 0x09193888b3f38C82dEdfda55259A82C0E7De875E
- tree-update-verifier.contract.tornadocash.eth: 0x653477c392c16b0765603074f157314Cc4f40c32
- reward-swap.contract.tornadocash.eth: 0x5cab7692D4E94096462119ab7bF57319726Eed2A
- poseidon2.contract.tornadocash.eth: 0x94C92F096437ab9958fC0A37F09348f30389Ae79
- poseidon3.contract.tornadocash.eth: 0xD82ed8786D7c69DC7e052F7A542AB047971E73d2
- tornado-proxy.contract.tornadocash.eth: 0x905b63Fff465B9fFBF41DeA908CEb12478ec7601
- tornado-trees.contract.tornadocash.eth: 0x43a3bE4Ae954d9869836702AFd10393D3a7Ea417
- mining-v2.contract.tornadocash.eth: 0x746Aebc06D2aE31B71ac51429A19D54E797878E9
- voucher.contract.tornadocash.eth: 0x3eFA30704D2b8BBAc821307230376556cF8CC39e
- team1.vesting.contract.tornadocash.eth: 0x5f48C2A71B2CC96e3F0CCae4E39318Ff0dc375b2
- team2.vesting.contract.tornadocash.eth: 0x00D5ec4CDF59374B2A47e842B799027356eAC02B
- team3.vesting.contract.tornadocash.eth: 0x77C08248c93Ab53Ff734AC555C932F8b9089D4C9
- team4.vesting.contract.tornadocash.eth: 0xc3877028655EbE90b9447DD33De391c955eAd267
- team5.vesting.contract.tornadocash.eth: 0xb43432eC23e228FB7cB0fA52968949458b509f4F
- governance.vesting.contract.tornadocash.eth: 0x179f48C78f57A3A78f0608cC9197B8972921d1D2
We thank everyone who helped us to ensure that the tornado.cash smart contracts are secure:
We also appreciate the help of Scott Bigelow and 1inch team for doing a security review of the smart contracts.