|=[ RESEARCH :: FILE 01C ]=
HOW PRIVATE IS PRIVACY POOLS?
PRIVACY POOLS · V1 MAINNET · ~14,000 TRANSACTIONSPrivacy Pools v1 lets users deposit specific tokens, prove they are not associated with illicit funds, and withdraw them to a fresh address without revealing which deposit is yours. Since inception there have been ~14,000 transactions on Privacy Pools' Ethereum Mainnet instance, and I applied statistical methods and heuristics across all of them to see how users are using the protocol, and how private the compliant mixer is.
DATA — 31.03.2025 → 09.08.2026 · ETHEREUM MAINNET
EVERY V1 MAINNET EVENT, RE-INDEXED FROM THE CONTRACTS
WHAT IS A MIXER DOING WITH AN APPROVAL LIST?
Blockchains are transparent by design, but many users want to have onchain privacy, and there are many mixers that help users obfuscate funds. Your funds are deposited into a shared pool, you wait, and then later withdraw to a fresh address. As your funds are pooled with others, an onlooker cannot tell which withdrawal belongs to which deposit, and the larger the pool is, the better the anonymity.
Tornado Cash is the most famous mixer. The US government sanctioned it in 2022 after stolen funds, including hundreds of millions taken by North Korean hackers, were washed through the same pot as everyone else's. The sanctions were ruled unlawful and lifted in 2025, but the message had already been sent.
Privacy Pools was built by 0xbow and has been live on Ethereum since March 2025, designed with compliance in mind. You deposit publicly into the pool, and wait for it to be approved and accepted into the Association Set, which screens out illicit funds. To withdraw your funds, you need to prove you own the funds, and that it was accepted by the Association Set Provider (ASP). This is the pitch: privacy for you, a compliance story for the regulator.
WHAT I ACTUALLY DID
Every action on Privacy Pools v1 emits a public event from the smart contracts, which can be [re]-indexed and investigated for links between deposits and withdrawals. Between the launch and 9th August 2026, there were 6,333 deposits and 7,944 withdrawals in the Ethereum pools.
Given this public record, I asked the question: "How often can you work out which deposit paid for which withdrawal?" If you're watching a cloakroom from across the street, you can't see what happens inside, but you can see which coat goes in, which coat comes out, and when they do it. This allows you to infer quite a lot.
A steady hum of activity
6,333 deposits and 7,944 withdrawals, weekly, March 2025 – August 2026
USDT pool dominates
gross deposited vs withdrawn volume per pool, in USD (ETH converted at $1,920, avg price 10 Aug 2026)
SEVEN METHODS
I applied seven different ways an observer might be able to connect a withdrawal back to its deposit, ranking them by most deanonymising first. The rank is a product of:
- Coverage - the size of the population a chosen heuristic can touch
- Certainty - the strength of the deanonymisation for users in that population
There are some methods that can directly deanonymise users with ease, and some methods that are completely useless. I measured some of these leaks in bits, which measure the amount of unpredictability in the dataset, with each bit halving the crowd you can hide in. For example, 10 bits halves the crowd 10 times.
#1 Reusing the same address.14.4% (1,145) of Ethereum withdrawals are users withdrawing to the same address they deposited from.
The whole point of using Privacy Pools is you can withdraw your funds to a new address, that has no history. Yet, one in seven withdrawals go to the exact same address, and 50.4% of those users withdrew the same amount, less fees, as they deposited. This heuristic is ranked number one as we can put a full certainty that these users deposited and withdrew to the same address, and threw away their potential anonymity in doing so.
This is not a failure of the protocol design, but a user-hygiene failure, and something that can be solved in v2 of the project.
One withdrawal in seven reuses a deposit address
1,145 of 7,944 withdrawals (14.4%) go back to an address that had already deposited into the same pool
9.8% (777) of Ethereum withdrawals can be identified due to the use of weird, unique amounts for deposits and withdrawals.
Mixers like Tornado Cash force users to deposit in fixed sizes: 0.1 ETH, 1 ETH, 10 ETH, precisely so that amounts couldn't identify you. Privacy Pools v1 dropped that feature for user convenience. This means that depositing an amount of 0.48732951 ETH and then withdrawing a similar amount minus the relayer fee, combined with the odds that two unrelated people choose the same eleven digit number are effectively zero, and you can be easily identified. There is a near-certainty for this method, with a median of 11.6 bits.
The instinct is that a random number blends in. It does the opposite. Privacy Pools anonymity comes from how many people share your set, and a majority of users deposit round numbers, where thousands of deposits look identical on withdrawal. The careful majority is untouched by this leak.
One in four deposits is exactly 0.1 ETH — the rest name themselves
4,215 real ETH-pool deposits; 9.8% of all withdrawals (777) have a near-certain 1:1 link from the amount alone
Fresh wallets aren't fresh: 31% of direct ETH deposits come from fresh, single-use wallets.
Instead of funding a fresh wallet from a Privacy Pools withdrawal, 36% of fresh wallets have exactly one inbound transaction, a certain link to who is depositing. One in eight of these wallets were funded by labeled hot wallets of major exchanges, meaning the exchange knows you've deposited into Privacy Pools and can apply any of these heuristics to track your withdrawal. ~10% of the ETH deposits were withdrawals re-depositing into fresh wallets. The median gap between funding the wallet and depositing is seven minutes.
Fresh wallets aren't fresh: who funds a first-time depositor?
All 1,250 fresh single-use wallets that deposited into the ETH pool, by what their funding history shows. Every funding transfer is public.
8.3% (656) of withdrawals occur within 5 minutes of the root updating, and shrink the crowd to ~9 with a confidence of 0.82.
One of the trade-offs of Privacy Pools is waiting to be accepted by the ASP, with the median wait time ~1 hour. Privacy Pools v1 requires your withdrawals to be against the latest approved set. So an impatient user who deposited several days ago, the moment the list is updated and their deposit is accepted, they withdraw the funds immediately.
8.3% of all withdrawals land within five minutes of the latest approved set, and each update accepts ~9 new deposits. Of these 656 withdrawals, 78% matched a deposit from the four days before that update. This collapses an analyst's problem: instead of searching through hundreds of deposits, they only need to go through ~9. Being in a rush costs you ~7-9 bits of entropy; your anonymity set becomes ~300 times smaller. I also ran the same test against a control week, and only matched 8% of those 656 withdrawals. This gives us ~3 bits of confidence that our hypothesis (withdrawals spike after list updates because those users were just approved) is correct.
Clever users can also run this trick in reverse. If your deposit has been sitting in the pool for weeks and you see a fresh 1 ETH deposit get approved, withdraw 1 ETH immediately, in the same minute as the rush. To an observer you look like one of the newly approved deposits, but you are not in that batch, so anyone intersecting with the update's nine new names excludes you.
Withdrawals pounce the moment deposits get approved
7,944 withdrawals timed against 2,242 approval-list updates — the spike at zero is impatient users grabbing freshly-approved money
Withdrawing your deposit to a fresh address that is empty means you cannot pay Ethereum's gas fees without doxxing that wallet by funding it from elsewhere. Privacy Pools uses a relayer service that submits the withdrawal onchain for you, pays the gas fees, and takes a cut of your withdrawal. 73% of relayed withdrawals have come from one single relayer. This risk is entirely offchain. We are trusting the relayer to not store information like IP addresses, timing, destination addresses. We are hoping that if they do log things, they will not answer subpoenas.
One company carries three-quarters of all private withdrawals
29 relayers have ever operated; the top three carry 91.6% of relayed traffic — and 94.1% of all withdrawals are relayed
Timing links ~3% of withdrawals, but folded into other heuristics lets us discard fifteen of every sixteen candidate deposits.
The most standard mixer advice is to wait a long, random amount of time, so you cannot be linked through timing. Most people don't really adhere to this advice. 20% of deposits are withdrawn within 6 hours, with a peak coming at around 2 weeks, and ~10% hold for more than 3 months. In Privacy Pools v1, timing is inevitable but it is rarely linkable, with only 3% of deposits being identifiable. The power of timing comes when combining it with other heuristics that delivers ~4 bits of entropy, letting us discard fifteen of every sixteen candidate deposits.
Some rinse in hours, some wait months — few do anything between
1,144 withdrawals linked to their own deposit by address reuse; median wait 10.9 days
Transacting at the same time leaks some information about you, but not enough to reveal who you are.
No one can be unmasked by their timezone alone, but transacting at the same time for each withdrawal leaks about 1 bit per withdrawal (0.66 on average, 1.27 for repeat users), shrinking the pool of candidate deposits an analyst needs to consider by roughly half.
The crowd never sleeps — but each person does
the hour you withdraw in is worth 0.66 bits of identity on average; 1.27 bits for repeat users
50.4 ETH IS A LONELY NUMBER
Mixers are meant to be simple: when you withdraw, you could be any of the deposits that came before you, and the bigger the number, the more likely you will be anonymous. In the case of Privacy Pools v1, a withdrawal can only have come from a deposit that was:
- a) vetted and approved by the ASP
- b) worth at least as much as the withdrawal
- c) actually published on the approved list at that moment
These three things mean that your cover is smaller and more transparent than advertised. The actual size of the crowd is smaller than the count of deposits before you by a median factor of 1.26. This gets progressively worse for larger deposits:
- 1 in 10 withdrawals have a crowd 8.9x smaller
- 1 in 100 withdrawals have a crowd 42x smaller
- the worst case has a crowd 375x smaller: a withdrawal of 50.4 ETH that, after the 3 filters, could have only six possible deposits in the pool's entire history.
Privacy is always better when you have friends.
The crowd you're told about vs the crowd you're actually in
Deposits that could possibly fund your withdrawal (approved, rich enough) vs all prior deposits, for 7,551 mainnet withdrawals
PRIVACY POOLS V2 FIXES IT ALL (OR DOES IT?)
Privacy Pools v2 will be released soon™ which brings:
- No more deposit fees
- Private transfers in the shielded pool
- Better UX with no more seed phrases to manage
- Private payment requests
- In-pool yield
- Multi-asset pools
Based on the above, Privacy Pools v2 improves and fixes a lot of the leaks that occur in v1. A multi-asset pool means that small pools and large deposits stop being so lonely, and each withdrawal is hidden in a larger pool.
In-pool yield is also a great obfuscation method. If you deposit and withdraw the same, unique amount you have your name written all over the transaction. If your deposit is earning variable yield whilst it sits in the pool, the number that goes in doesn't have to be the number that comes out, and your fingerprint has been smudged.
Onchain privacy is important for everyone, but it has a UX problem the average user cannot comprehend. Most of the leaks in this essay were not cryptography failing; they were product and habit. People reuse addresses, hit send max, and withdraw the second their deposit clears, and no contract upgrade can stop them.
Privacy Pools v2 seems to be at the forefront of fixing that, by making the careful thing the default and actually fixing the UX problem onchain privacy has.
A last word on Tornado Cash, because it deserves one: it did nothing wrong. It was code that did exactly what it promised, for everyone, without asking any questions. It was sanctioned, and developers jailed, for what other people did with it. Roman Storm and Alexey Pertsev are still fighting for their freedom. This essay exists because privacy is a human right, and rights need measuring.
HOW TO ACTUALLY USE IT
Everything above measured, distilled into habits:
- Deposit round amounts. 0.1, 0.5, 1 ETH. A weird amount is a name tag (#2).
- Never withdraw where you deposited. Fresh address, every time (#1). In v2, payment requests do this for you.
- Wait, and wait randomly. Days, not minutes. And whatever you do, don't withdraw in the five minutes after your deposit gets approved; that is exactly when everyone is watching the door (#4).
- Fund your fresh wallet carefully. Don't hit "send max". Send a round amount with a little extra for gas, and know that if the money comes straight from an exchange, the exchange knows (#3).
- Use a VPN or Tor when you withdraw. The relayer can't see your wallet history, but it can see your IP address (#5).
- Don't always transact at the same hour. Your bedtime is a signal (#7).
- Split large withdrawals. 50.4 ETH had six possible funders in the pool's history. Ten withdrawals of 5 ETH would have had thousands (#crowd).
- Check the crowd before you use it. More deposits before yours, more places to hide.
IMPORTANT NOTES
With the exception of address reuse and funding analysis, everything else is a probability. It is overwhelmingly likely that a deposit matches a withdrawal, but I cannot say that it is 100% true. I also used aggregated data so that no one is directly doxxed; the goal of this research is to measure the system and understand how we can do better.
Evaluating Privacy Pools but not sure if it fits your product? Talk to Ben.
TALK TO BEN →