6b16956e (main)
and
dd50032a (PR)
+18 -0
+18 -0
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides which deposit funds which withdrawal, for deposits approved by the permissioned association set provider. Everything else is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Which approved deposit a withdrawal spends is hidden. Partial withdrawals leave a change note and look like full ones.",
"advice": "Exit through a relayer, so no wallet of yours pays gas for the receiving address. Withdraw partially to fresh addresses, and ragequit only untouched deposits: ragequitting a change note reveals the withdrawal it came from.",
"sources": [
{
"contract": "PrivacyPoolsEntrypoint"
},
{
"title": "Withdrawal circuit",
"url": "https://github.com/0xbow-io/privacy-pools-core/blob/main/packages/circuits/circuits/withdraw.circom"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The approved set at any block is public, so the candidates for a withdrawal are known exactly and matched by amount and timing. Any amount is allowed, so an unusual one pairs a deposit with its withdrawal. Paying gas from your own wallet instead of a relayer exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"advice": "Use a pool with a large anonymity set. Withdraw common amounts rather than everything at once. Wait before exiting and pick a different time of day than the deposit. Exit to a fresh address every time and spend from it with a different wallet than the one that deposited.",
"sources": [
{
"title": "Blockchain Privacy and Regulatory Compliance (design paper)",
"url": "https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4563364"
},
{
"title": "Tutela (arXiv:2201.06811)",
"url": "https://arxiv.org/abs/2201.06811"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "bad",
"exposure": "Event sync is forced through 0xbow's own proxy with no option for a public node. On login the app looks up the block of each of your deposits, then polls your wallet balance and the withdrawal receipt from the same session. Relayers receive amount and recipient for a quote.",
"advice": "Use a client with an RPC setting, such as the raw SDK, pointed at your own node. The official frontend cannot avoid the lookups.",
"sources": [
{
"title": "Reads go to Alchemy under 0xbow's key, no RPC setting",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/config/wagmiConfig.ts#L46-L58"
},
{
"title": "Event sync through 0xbow's Hypersync proxy",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/config/chainData.ts#L135-L140"
},
{
"title": "Block lookup for every deposit on login",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/utils/sdk.ts#L439-L442"
},
{
"title": "Wallet balance polled every 10 seconds",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/providers/ChainProvider.tsx#L126-L133"
},
{
"title": "Withdrawal receipt polled after relay",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/hooks/useWithdraw.ts#L414-L416"
},
{
"title": "Login requires a connected wallet",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/providers/AuthProvider.tsx#L33-L36"
},
{
"title": "Relayer quote carries amount and recipient",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/utils/relayerClient.ts#L45-L58"
}
],
"id": "networkObserver",
"value": "Link exposed",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "warning",
"exposure": "The ASP postman sets a new approved list at any time with no delay, and the pool accepts only the latest one. It can deny you a private exit or publish a list with only your deposit, which is then your whole anonymity set. The website shows the anonymity set but does not block a tiny one.",
"advice": "Check the anonymity set shown before withdrawing, or count the approved list yourself with a client that fetches it whole, such as the raw SDK.",
"sources": [
{
"contract": "PrivacyPoolsEntrypoint",
"title": "updateRoot: the postman sets a new root with no delay"
},
{
"contract": "PrivacyPoolETH",
"title": "validWithdrawal: only the latest ASP root is accepted"
},
{
"section": "permissions",
"title": "Privacy Pools Multisig and ASP postman"
},
{
"title": "Anonymity set shown, not enforced",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/62a962f68def3cbeb801c4259e743fd3d4762928/src/containers/Modals/Withdraw/WithdrawForm.tsx#L204-L213"
},
{
"title": "Kohaku fetches the approved list whole",
"url": "https://github.com/ethereum/kohaku/blob/master/packages/privacy-pools/src/data/0xbowAsp.service.ts"
}
],
"id": "privilegedInsider",
"value": "Link at risk",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "good",
"exposure": "Nothing encrypted is written onchain and commitments are plain hashes, so a quantum computer recovers nothing. Accounts created from a wallet signature reduce to that wallet's key.",
"advice": "Create your account from a seed phrase, not from a wallet signature.",
"sources": [
{
"title": "Commitment circuit (Poseidon)",
"url": "https://github.com/0xbow-io/privacy-pools-core/blob/main/packages/circuits/circuits/commitment.circom"
},
{
"title": "Wallet-signature seed derivation",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/main/src/utils/walletSeed.ts"
},
{
"section": "trusted-setups"
}
],
"id": "futureAdversary",
"value": "Link private",
"alsoExposed": []
}
}
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
}
],
"category": {
"id": "pool",
"label": "Pool",
"description": "Funds enter a shared pool and leave it later, with no transfers inside. Hides which deposit funds which withdrawal."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "Even if the Entrypoint or ASP turns malicious, users can always ragequit (withdraw tokens) from the immutable pool contracts, at the cost of losing privacy.",
"walkawayTest": {
"passed": false,
"reason": "Association Set Providers must explicitly approve deposited funds before private withdrawals."
}
},
"relayerTracking": {
"type": "onchainEvents",
"sources": [
{
"address": "eth:0x6818809EefCe719E480a7526D76bD3e561526b46",
"sinceTimestamp": 1743265247,
"extractor": "privacyPoolsWithdrawalRelayed"
}
]
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The contracts, circuits, and supporting software needed to participate in Privacy Pools are publicly available and can be run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid withdrawals.\n2. the [trusted setup](#trusted-setups) is compromised or all ceremony participants collude, allowing invalid withdrawals.\n3. the Entrypoint owner deploys a malicious [upgrade](#upgrades-and-governance) that steals new deposits.\n
\n## Funds can be lost if\n1. a user loses the secret and nullifier required to spend their deposit.\n
\n## Privacy can be lost if\n1. no relayer is available and the withdrawal must be submitted from an address that can be linked to the user.\n2. the ASP manager refuses to whitelist a deposit, forcing the user to either wait or exit publicly through ragequit.",
"tokens": [
{
"token": {
"address": "0x6440f144b7e50D6a8439336510312d2F54beB01D",
"iconUrl": "https://coin-images.coingecko.com/coins/images/56069/large/BOLD_logo.png?1748265087",
"symbol": "BOLD",
"decimals": 18,
"priceId": "liquity-bold-2",
"sinceTimestamp": 1770806867
},
"buckets": [
{
"id": "privacy-pools-BOLD",
"type": "pool",
"label": "BOLD pool",
"address": "eth:0xb4b5Fd38Fd4788071d7287e3cB52948e0d10b23E",
"sinceTimestamp": 1770806867,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1752848471
},
"buckets": [
{
"id": "privacy-pools-DAI",
"type": "pool",
"label": "DAI pool",
"address": "eth:0x1c31C03B8CB2EE674D0F11De77135536db828257",
"sinceTimestamp": 1752848471,
"anonymitySet": {
"minimumAmounts": [
"200000000000000000000",
"20000000000000000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"iconUrl": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"symbol": "ETH",
"decimals": 18,
"priceId": "ethereum",
"sinceTimestamp": 1743265259
},
"buckets": [
{
"id": "privacy-pools-ETH",
"type": "pool",
"label": "ETH pool",
"address": "eth:0xF241d57C6DebAe225c0F2e6eA1529373C9A9C9fB",
"sinceTimestamp": 1743265259,
"anonymitySet": {
"minimumAmounts": [
"100000000000000000",
"10000000000000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29",
"iconUrl": "https://coin-images.coingecko.com/coins/images/53963/large/frxUSD.png?1737792154",
"symbol": "frxUSD",
"decimals": 18,
"priceId": "frax-usd",
"sinceTimestamp": 1754583623
},
"buckets": [
{
"id": "privacy-pools-frxUSD",
"type": "pool",
"label": "frxUSD pool",
"address": "eth:0xC6C769fac7AABEadd31a03fAe5Ca0Ec5B4C50f84",
"sinceTimestamp": 1754583623,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x085780639CC2cACd35E474e71f4d000e2405d8f6",
"iconUrl": "https://coin-images.coingecko.com/coins/images/36202/large/fxUSD.jpg?1710833113",
"symbol": "fxUSD",
"decimals": 18,
"priceId": "f-x-protocol-fxusd",
"sinceTimestamp": 1765446455
},
"buckets": [
{
"id": "privacy-pools-fxUSD",
"type": "pool",
"label": "fxUSD pool",
"address": "eth:0xD14F4B36E1D1D98c218db782c49149876042BC56",
"sinceTimestamp": 1765446455,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD",
"iconUrl": "https://coin-images.coingecko.com/coins/images/52721/large/sUSDS_Coin.png?1734086971",
"symbol": "sUSDS",
"decimals": 18,
"priceId": "susds",
"sinceTimestamp": 1752782999
},
"buckets": [
{
"id": "privacy-pools-sUSDS",
"type": "pool",
"label": "sUSDS pool",
"address": "eth:0xBBdA2173CDFEA1c3bD7F2908798F1265301d750c",
"sinceTimestamp": 1752782999,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
"iconUrl": "https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002",
"symbol": "USD1",
"decimals": 18,
"priceId": "usd1-wlfi",
"sinceTimestamp": 1754583179
},
"buckets": [
{
"id": "privacy-pools-USD1",
"type": "pool",
"label": "USD1 pool",
"address": "eth:0xc0A8Bc0F4F982b4d4f1fFae8F4FCCb58c9B29c98",
"sinceTimestamp": 1754583179,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1753353035
},
"buckets": [
{
"id": "privacy-pools-USDC",
"type": "pool",
"label": "USDC pool",
"address": "eth:0xb419c2867aB3CBc78921660cB95150d95A94ce86",
"sinceTimestamp": 1753353035,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3",
"iconUrl": "https://assets.coingecko.com/coins/images/33613/large/3466ef_3c088c66c7d941e8856339d0bddf33cc_mv2.png?1702514458",
"symbol": "USDe",
"decimals": 18,
"priceId": "ethena-usde",
"sinceTimestamp": 1754583083
},
"buckets": [
{
"id": "privacy-pools-USDe",
"type": "pool",
"label": "USDe pool",
"address": "eth:0xe6D36B33b00A7C0cB0C2a8d39D07e7dB0c526Abc",
"sinceTimestamp": 1754583083,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xdC035D45d973E3EC169d2276DDab16f1e407384F",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39926/large/usds.webp?1726666683",
"symbol": "USDS",
"decimals": 18,
"priceId": "usds",
"sinceTimestamp": 1752503003
},
"buckets": [
{
"id": "privacy-pools-USDS",
"type": "pool",
"label": "USDS pool",
"address": "eth:0x05e4DBD71B56861eeD2Aaa12d00A797F04B5D3c0",
"sinceTimestamp": 1752503003,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1753352915
},
"buckets": [
{
"id": "privacy-pools-USDT",
"type": "pool",
"label": "USDT pool",
"address": "eth:0xe859C0bD25f260BaEE534Fb52e307D3b64D24572",
"sinceTimestamp": 1753352915,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"iconUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857",
"symbol": "WBTC",
"decimals": 8,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1753975703
},
"buckets": [
{
"id": "privacy-pools-WBTC",
"type": "pool",
"label": "WBTC pool",
"address": "eth:0xF973f4B180A568157Cd7A0E6006449139E6Bfc32",
"sinceTimestamp": 1753975703,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xDcEe70654261AF21C44c093C300eD3Bb97b78192",
"iconUrl": "https://coin-images.coingecko.com/coins/images/29734/large/woeth-200x200.png?1714796686",
"symbol": "wOETH",
"decimals": 18,
"priceId": "wrapped-oeth",
"sinceTimestamp": 1756377743
},
"buckets": [
{
"id": "privacy-pools-wOETH",
"type": "pool",
"label": "wOETH pool",
"address": "eth:0x7d2959bCFb936a84531518e8391DdBa844e03ebE",
"sinceTimestamp": 1756377743,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"iconUrl": "https://assets.coingecko.com/coins/images/18834/large/wstETH.png?1696518295",
"symbol": "wstETH",
"decimals": 18,
"priceId": "wrapped-steth",
"sinceTimestamp": 1753975583
},
"buckets": [
{
"id": "privacy-pools-wstETH",
"type": "pool",
"label": "wstETH pool",
"address": "eth:0x1A604E9DFa0EFDC7FFda378AF16Cb81243b61633",
"sinceTimestamp": 1753975583,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "The 2/4 Privacy Pools Multisig can instantly change the system’s critical configs, including the Entrypoint implementation and ASP root used for private withdrawals. The ASP postman (EOA) can also remove any deposit from the whitelist at any time, forcing a public rage-quit if the affected party wishes to withdraw. The guaranteed immutable escape hatch is pool-level ragequit (public withdrawal) to the original depositor address, because that logic lives in the immutable pool contracts and does not depend on the Entrypoint registry and config. This means the system is permissioned in its deposit logic and deposit privacy, but non-custodial for deposited assets. Past, successful (non-ragequit) withdrawals can not be deanonymized by the protocol."
}
}
+18 -0
+18 -0
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides everything inside the pool, including which shield funds which unshield. Shields and unshields are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Everything inside the pool is hidden, including which shield funds which unshield. Shields and unshields show address, token and amount. DeFi bundles unshield to the adapter in cleartext.",
"advice": "Exit through a broadcaster, so no wallet of yours pays gas for the receiving address.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": {
"verdict": "private",
"note": "Leaked for DeFi bundles, which unshield to the adapter in cleartext."
},
"asset": {
"verdict": "private",
"note": "Leaked for DeFi bundles."
},
"linkage": "private"
},
"sources": [
{
"contract": "RailgunSmartWallet"
},
{
"title": "Note ciphertext format",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/note/transact-note.ts"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The candidates for an unshield are the shields of the same token. In-pool transfers break the one-to-one match of a mixer, but timing and exact or round amounts narrow the set. Paying gas from your own wallet instead of a broadcaster exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"advice": "Withdraw common amounts rather than everything at once. Wait before exiting and pick a different time of day than the deposit. Exit to a fresh address every time and spend from it with a different wallet than the one that deposited.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
},
"sources": [
{
"title": "A Tattered Cloak of Invisibility (arXiv:2606.25926)",
"url": "https://arxiv.org/abs/2606.25926"
},
{
"title": "The Anonymity Gap (arXiv:2608.22987)",
"url": "https://arxiv.org/abs/2608.22987"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "good",
"exposure": "The wallet finds its notes by trial-decrypting every note locally, so nodes learn nothing about which are yours. By default it sends the pending unshield to the configured node for a gas estimate, which reveals the destination early.",
"advice": "Read the chain from your own node, send through a public RPC over Tor, and use a popular broadcaster. If you settle for a VPN instead of Tor, pick one you trust: it hides your IP from the broadcaster but sees it itself.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
},
"sources": [
{
"title": "Gas estimation with dummy proof",
"url": "https://github.com/Railgun-Community/wallet/blob/main/src/services/transactions/tx-gas-details.ts"
},
{
"title": "Broadcaster decrypts request",
"url": "https://github.com/Railgun-Community/ppoi-safe-broadcaster-example/blob/main/src/server/waku-broadcaster/methods/transact-method.ts"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "good",
"exposure": "There is no view key, so nobody can read past activity. The DAO can upgrade the contracts after a seven-day delay. The proof-of-innocence list provider can refuse to list a shield, leaving only a self-broadcast exit.",
"advice": "Watch governance proposals; you have seven days to unshield before an upgrade takes effect. Be ready to self-broadcast if the list provider censors you.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": {
"verdict": "atRisk",
"note": "POI nodes tie a session to a note cluster and its transaction ids."
}
},
"sources": [
{
"section": "permissions",
"title": "Governance roles"
},
{
"title": "POI required lists",
"url": "https://github.com/Railgun-Community/shared-models/blob/main/src/models/poi.ts"
},
{
"title": "POI node interface",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/poi/poi.ts"
}
],
"id": "privilegedInsider",
"value": "Link private",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "Notes are encrypted with elliptic-curve key exchange. A quantum computer decrypts every note sent to a 0zk address that was ever shared, including broadcaster fee notes: amounts, tokens and counterparties.",
"advice": "Treat your 0zk address as a secret: share it privately, and use a fresh one per counterparty where you can.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Decrypts for notes touching any shared 0zk address."
},
"recipient": "atRisk",
"amount": "atRisk",
"asset": "atRisk",
"linkage": "atRisk"
},
"sources": [
{
"title": "Shared key derivation (Ed25519 ECDH)",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/keys-utils.ts"
},
{
"title": "AES-GCM note encryption",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/encryption/aes.ts"
}
],
"id": "futureAdversary",
"value": "Link at risk",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"exposure": "atRisk"
},
{
"field": "amount",
"exposure": "atRisk"
},
{
"field": "asset",
"exposure": "atRisk"
}
]
}
}
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "transfers",
"label": "Transfers",
"description": "Private transfers within the shielded pool."
},
{
"id": "defi",
"label": "DeFi",
"description": "Interop with DeFi (swaps, vaults) from within the shielded pool."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
}
],
"category": {
"id": "shieldedLedger",
"label": "Shielded ledger",
"description": "A pool with transfers or DeFi inside. Hides who pays whom and which deposit funds which withdrawal."
},
"exitWindow": {
"value": "7d",
"sentiment": "warning",
"orderHint": 604800,
"description": "DAO-approved upgrades wait 7d before they can execute, giving users time to unshield funds if they do not approve the change.",
"walkawayTest": {
"passed": true
}
},
"relayerTracking": {
"type": "railgunWaku",
"chainId": 1,
"sinceTimestamp": 1788134400
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The contracts, circuits, and supporting software needed to participate in the protocol are publicly available and can be run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid spends or withdrawals.\n2. the [trusted setup](#trusted-setups) is compromised or all ceremony participants collude, allowing invalid spends or withdrawals.\n3. the DAO passes a malicious [upgrade](#upgrades-and-governance) and users do not react before the 7-day execution delay expires.\n
\n## Funds can be lost if\n1. a user loses the private keys required to control their private balance.\n
\n## Privacy can be lost if\n1. no broadcaster is available and transactions must be sent from a public address that can be linked to the user.",
"tokens": [
{
"token": {
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"iconUrl": "https://assets.coingecko.com/coins/images/2518/large/weth.png?1696503332",
"symbol": "WETH",
"decimals": 18,
"priceId": "weth",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-WETH",
"type": "pool",
"label": "WETH",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"100000000000000000",
"10000000000000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-USDT",
"type": "pool",
"label": "USDT",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-USDC",
"type": "pool",
"label": "USDC",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
}
}
]
},
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1574121600
},
"buckets": [
{
"id": "railgun-DAI",
"type": "pool",
"label": "DAI",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000000000000000",
"20000000000000000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
}
}
]
},
{
"token": {
"address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"iconUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857",
"symbol": "WBTC",
"decimals": 8,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-WBTC",
"type": "pool",
"label": "WBTC",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
}
}
]
},
{
"token": {
"address": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4",
"iconUrl": "https://coin-images.coingecko.com/coins/images/71681/large/near.png?1768905174",
"symbol": "NEAR",
"decimals": 24,
"priceId": "rainbow-bridged-near-ethereum",
"sinceTimestamp": 1768867200
},
"buckets": [
{
"id": "railgun-NEAR",
"type": "pool",
"label": "NEAR",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1768867200,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4"
}
}
}
]
},
{
"token": {
"address": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb",
"iconUrl": "https://coin-images.coingecko.com/coins/images/14688/large/Logo_1_%28brighter%29.png?1734430693",
"symbol": "FLUID",
"decimals": 18,
"priceId": "instadapp",
"sinceTimestamp": 1623801600
},
"buckets": [
{
"id": "railgun-FLUID",
"type": "pool",
"label": "FLUID",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb"
}
}
}
]
},
{
"token": {
"address": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D",
"iconUrl": "https://coin-images.coingecko.com/coins/images/16840/large/railgun.jpeg?1696516407",
"symbol": "RAIL",
"decimals": 18,
"priceId": "railgun",
"sinceTimestamp": 1625270400
},
"buckets": [
{
"id": "railgun-RAIL",
"type": "pool",
"label": "RAIL",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D"
}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Railgun features an omnipotent DAO governed by the stakers of the RAIL token. The DAO has the authority to change ZK circuit logic on the core Railgun contract, which can arbitrarily change the rules for shielded tokens; as well as manage blacklisted tokens, mint RAIL tokens and manage governance rewards. See docs here: ",
"governanceInfo": {
"upgrades": {
"Normal upgrade path": "Create a proposal with an IPFS link and onchain calldata in the [Voting contract](https://etherscan.io/address/0xc480F68A3dcC3EdD82134FAB45C14A0FcF1dA3CC) → collect **500.00 K RAIL** sponsorship within 1mo → wait 2d → cast Yay votes within 5d and Nay votes within 6d → pass with a simple majority and **2.00 M RAIL** quorum → wait 7d → permissionless execution through the Delegator within 14d.",
"Exit window": "**7d** — a passed proposal must wait this long before it can be executed, giving users time to unshield funds."
},
"tokenGovernance": {
"Governance token": "`RAIL` 1 token = 1 vote, delegated. Total supply: **60.00 M RAIL**, DAO-owned treasury (unavailable for voting): **2.30 M RAIL**, staked for voting: **41.61 M RAIL**, the rest is circulating supply.",
"Stake lock": "Unstaking has **1mo** delay.",
"Voting venue": "[Voting contract](https://etherscan.io/address/0xc480F68A3dcC3EdD82134FAB45C14A0FcF1dA3CC) on Ethereum. Proposal text is distributed over IPFS, its CID is available as a parameter of `createPropsal()` call on the voting contract.",
"Proposal threshold": "**No threshold to create a proposal.** A proposal must receive sponsorship from **500.00 K RAIL** stake within 1mo.",
"Quorum": "**2.00 M RAIL**, with a simple majority required for acceptance.",
"Execution model": "**Onchain calldata · Permissionless execution through the Delegator.** A passed proposal waits 7d, after which anyone can execute it through the [Delegator contract](https://etherscan.io/address/0xB6d513f6222Ee92Fff975E901bd792E2513fB53B) within 14d."
}
}
}
}