What if… Anonymous on-chain savings accounts
TLDR: We introduce Hush Hush, a non-custodial privacy extension that provides a Tornado.cash like pool for aTokens which supports arbitrary withdrawal amounts.
A great thanks to Tornado.cash for inspiration and Roman Semenov for helpful clarifications.
With the rise of DeFi lending and borrowing protocols, on-chain savings accounts have become a reality on Ethereum. Nevertheless, the public nature of the Ethereum blockchain means that transaction history and balances are publicly on display for anyone to watch. This means that anybody with an internet connection and knowledge of your address can look at your savings and expenditures, something we would never accept in the world of banks, so why do we accept it in Ethereum?
While Tornado.cash is amazing for mixing Ether such that you can withdraw anonymously, there is no widely used equivalent within the area of interest-bearing tokens. Further, the Tornado.cash structure forces a user to withdraw the deposit in its entirety which is not ideal for long-term savings accounts.
To combat these issues, we present Hush Hush, a tool that allow users to deposit interest-bearing tokens into a dark-pool, from which they can later withdraw fractions of their balance — instead of all at once. Using the same underlying building block as Tornado.cash and zCash, the zk-snark, links between deposits and withdrawals are broken. This means that whenever a withdraw is made, an observer will simply learn that someone in the pool withdrew funds, but not who. Because an observer can see who deposit into the pool, but not who withdraws, he can compute an upper limit of the depositors balance, e.g., a user deposited twice and will at most have 2*deposit + interest in the pool.
Depositing into the pool
To deposit, the user generates a secret note and transfer some aTokens along with a commitment of the note (a hash of the note) to the smart contract on Ethereum. The contract will then append the commitment to its state, ensuring that it can be withdrawn later. Anyone who knows the secret inside the commitment can withdraw from the deposit, so don’t give the secret to anyone! An analogy to these commitments and notes is the Bitcoin UTXO set, a UTXO can be spend by the private-key that owns it, exactly as the commitment can be spend by the holder of the note.
Withdrawing from the pool
To withdraw from the pool, the user will prove that he knows the note for an unspent commitment inside the contract. He will do so inside a zk-snark, proving that he indeed has such knowledge without revealing the specific commitment nor its secrets. Along with the note to spend, he will use a change-note, holding the change after his withdraw, e.g., with 1000$ deposits and a 200$ withdraw the change is 800$. The commitment to this change-note is then appended to the contract’s state, ensuring that it can later be spent. Because the zk-snark is not revealing which note is spend, an observer won’t even know if the withdraw is from another change-note. This is what allows users to keep amount that do not match the deposit amount inside the pool.
To ensure that publishing the withdraw proof is not leaking the spender, the proof can be published through a relayer who is paid a fee for his services.
Implications of partial withdraws
Because the system allows a depositor to withdraw a fraction of his funds, the “change” will stay hidden inside the pool. This is great for convenience as the alternative is to make a fresh deposit which have strict requirements to amounts which we often cannot satisfy after a partial withdraw. However, it is not a dance on roses, as this means that we lose some privacy at the cost of convenience. Nevertheless, the privacy is still greatly increased in comparison to plain token transfers on Ethereum.
To get an idea of the implications on privacy, let us take some examples: Say that we have 1000 depositers which all have deposited 1000$ into the pool. For each of the deposits, we know who deposited into the pool. Then say someone withdraws 500$. This withdraw could have been made from any of the deposits, meaning that an observer would have a 1 in 1000 chance of picking the matching commitment, thereby guessing who withdrew.
After that withdraw, there is now 1001 commitments in the state of the contract, 1000 to 1000$ and 1 to 500$ (the change). As only the spender knows which commitment he used, an observer cannot remove anything from the set of suspects. We now have 2 cases:
- The next withdraw >500$
- The next withdraw ≤500$
Say we have another withdraw of 600$, an observer knows that it cannot be from the 500$ change commitment. However, it could still be any of the original deposits. Even though there are 1001 commitments in the pool, he has a 1 in 1000'th chance of correctly guessing the spender.
If we instead have a withdraw of 400$, the withdraw could be from the change commitment as well, meaning that an observer have a 1 in 1001 chance of guessing correct.
This means that we are pretty well hidden. Still, Tornado.cash with a similar number of commitments will provide better anonymity as all commitments are fresh deposits.
However, Hush Hush gives us the ability to stay inside the pool with change, which is not possible in Tornado.
The current Hush Hush implementation were build for the EthGlobal MarketMake hackathon, and showcase that more private on-chain savings accounts are a possibility, however, it was a bit rushed, and requires updates to mature before primetime.
Furthermore, the current version utilises an on-chain incremental merkle-tree to keep track of commitments which in the current gas-environment is very expensive to append to (~1 million gas * 200gwei = 😬).
To combat the excessive gas cost, we are exploring to move merkle-tree inserts into a zk-snark, proving that the insert is done correctly and then updating the merkle-root on-chain, which has some similarities to a rollup. While this would greatly cut down gas-cost it brings other issues, which we will elaborate on in a later post.
Hush Hush is a non-custodial privacy extension to interest-bearing tokens that gives users the ability to anonymously spend from an on-chain savings account.
It uses fixed deposit-sizes and variable withdraws, providing users with flexibility to stay in the pool after a partial spending.
As a withdraw could be spending funds from any of the deposits but only some of the change (change-amounts ≥ withdraw) the anonymity set will at most be equal to the number of commitments. For pure privacy, Tornado.cash will be hiding better due to its more restrictive nature.
Currently in development, exploring ideas for reducing gascost to levels that are managable for non-whales.
To stay updated on the progress of Hush Hush, you can follow us on twitter: @HushHushEth