Flexible Tornado Cash Deposits

This potential proposal would allow depositors to combine and/or break apart their deposits.

Ex. A depositor deposits 100 ETH. Instead of withdrawing the full amount of ETH all at once, the depositor is able to withdraw ETH using any combination of the current anonymity set.
Deposited: 100 ETH
Withdraw Options:
1 100ETH
10 10ETH
100 1ETH
1000 0.1ETH

I believe that this should increase the anonymity of and convenience to a given depositor
What do you all think?

1 Like

I doubt this is possible.

Imagine that a whale that makes a deposit of 100 ETH begins to withdraw all deposits of 0.1 ETH. Then people who made deposits of 0.1 ETH simply won’t be able to take deposit, because 0.1 ETH bank is empty

Lol

I was skeptical too, but I think it might be possible actually:

Let’s first look at how I think it works currently on a very high level.

A pool contains some amount of ETH and two lists, a list deposits and a list withdrawals.

A user creates a secret note n. He then deposits 1 ETH and adds hash(0, n) to deposits. (With multiple arguments to hash I just mean the hash of the argument tuple.)

When a user wants to withdraw his ETH, he creates a ZKP, that he knows some index i and a note n, such that deposits[i] == hash(0, n). He also submits hash(1, n). The pool checks the proof, checks that hash(1, n) is not in the list of withdrawals (to avoid double spending) and lets him withdraw 1 ETH.

Now let’s see, how this can be extended to (in principle) allow arbitrary deposits and withdrawals. Be careful: In practice it should be carefully considered which deposits and withdrawals are actually allowed, to have good anonymity sets.

A pool again contains some amount of ETH and two lists, a list deposits and a list withdrawals.

A user creates a secret note n. He then deposits x ETH and adds hash(0, n, x) to deposits. He also must submit a ZKP, that he knows a note n, such that hash(0, n, x) matches the hash that he submitted and x matches the amount of ETH that he submitted.

When a user wants to withdraw y ETH, he creates a ZKP, that he knows some index i and a note n and an amount x (x >= y), such that deposits[i] == hash(0, n, x). (Note: He did not reveal the originally deposited amount x.) He also submits hash(1, n). The pool checks the proof, checks that hash(1, n) is not in the list of withdrawals and lets him withdraw y ETH. This would mean that x - y ETH is lost. To avoid that, the user must also create a new note n2 and submit hash(0, n2, x - y) to the list of deposits. Again he also must submit a ZKP, that he knows a note n2, such that hash(0, n2, x - y) matches the hash that he submitted. (This ZKP and the previous ZKP must be submitted as one ZKP, to ensure that they both use the same x.)

To summarize:

  • Deposit:
    • User sends ETH and the tuple (x, h, ZKP(h == hash(0, n, x))
    • Pool checks the ZKP
    • Pool checks that the sent ETH matches x
    • Pool adds h to deposits.
  • Withdrawal:
    • User sends (y, h1, h2, ZKP(hash(0, n, x) ∈ deposits && y <= x && h1 == hash(1, n) && h2 == hash(0, n2, x - y))
    • Pool checks the ZKP
    • Pool checks that h1 is not in withdrawals
    • Pool adds h1 to withdrawals
    • Pool sends y ETH
    • Pool adds h2 to deposits

This allows arbitrary deposits and withdrawals. It makes reasoning about anonymity sets somewhat interesting. If only deposits/withdrawals are allowed, that are currently allowed (all to the same pool), I think it at least does not make the anonymity set worse.

My reasoning could contain fatal errors.

1 Like

It is possible, yes, see this response on another thread

5 Likes

Glad this being worked on. Is there a timeline for when it may be done?

1 Like

What I describe in the following is maybe exactly what @poma referred to but I couldn’t find too much documentation so I post this anyway.

The deposit function that I described can be modified like so:

  • User sends ETH and the tuple (y, h1, h2, ZKP((hash(0, n, x) ∈ deposits || x == 0) && h1 == hash(1, n) && h2 == hash(0, n2, x + y))
  • Pool checks the ZKP
  • Pool checks that the sent ETH matches y
  • Pool checks that h1 is not in withdrawals
  • Pool adds h1 to withdrawals
  • Pool adds h2 to deposits

What this allows is to add new ETH to an existing deposit (without anyone knowing that it happened). This effectively creates the concept of an ‘anonymous wallet’. The note changes on every transaction but that can be easily worked around. Maybe in the contract itself or by creating them pseudo randomly from a seed.

I think the simplicity and usefulness of an anonymous wallet with a nice GUI (and hopefully the high gas fee problem solved in the future), could attract many users that don’t really need anonymity but simply prefer it. More users helps to increase anonymity, including for those that really need it.

If a user really wants to stay anonymous he should of course still be careful that the amounts he deposits/withdraws can not be correlated.

Super cool concept. Is anyone aware of a TORN calculator? Something like, assuming a user deposits 1 eth for 3 months, how much TORN is the user expected to earn

I don’t think there is a calculator out but check out this post. It may answer your question.