c1cbf427 (main)
and
ab2934d0 (PR)
+52 -66
+2 -2
{
"badges": [],
"description": "A shielded pool for ERC-20 tokens on Base, designed for institutional users. Provides TEE-backed privacy, balancing better UX with worse privacy trust assumptions.",
"detailedDescription": "Privacy Boost is a shielded pool for registered ERC-20 tokens on Base, aimed at institutional users. The operator's TEE setup has to be trusted for privacy and liveness, while ZKPs ensure validity and an exit path against a malicious or faulty operator.\n\n### Architecture\n\nDeposited tokens are represented as notes whose Poseidon2 commitments are appended to an onchain Merkle tree, and spending a note publishes its nullifier. Users can privately transfer deposited tokens to other users. The TEE collects user-approved transfers and withdrawals, batches them into epochs, and a permissioned relay submits each epoch onchain with a Groth16 proof that checks correctness.\n\nAccounts can authorize spending with registered approval keys or with explicit onchain spend approvals, including batches and approval-only smart-wallet accounts. Epoch proofs use current auth roots or roots superseded no more than 10 minutes ago.\n\nUsers can locally prove a forced withdrawal of up to 13 notes. The contract checks that the referenced auth key or spend approval is live and unexpired when the request is submitted, and records the authorized withdrawal and fee. Anyone can execute it 3 days later if the notes remain unspent, without cooperation from the TEE or relays. The account owner can cancel a pending request.\n\nUsers can locally generate and deploy portal deposit EIP-7702 addresses. Anyone can send ERC-20 to such a portal address, the tokens are regularly swept into Privacy Boost escrow for the hidden recipient.\nGift notes can be claimed by recipients or refunded by senders after a bound deadline, either privately through a relay or through a permissionless public gift exit. Proof-authorized withdrawals can also call approved external gateways for DeFi operations.\n\nIf the operator disappears, no new deposits or private transfers can be processed and the pool effectively enters this exit-only mode, in which the zero-knowledge guarantees alone are sufficient to recover funds.\n\n### Privacy considerations\n\nAll private data exists in plaintext inside the operator's TEE. This privacy depends on the hardware security of the TEE against actors with physical access (side-channel and microarchitectural attacks could expose the full plaintext ledger), as well as vendor vulnerabilities. The source code running within the TEE is not published.\n\nA permissionless forced withdrawal publishes the commitments of the spent notes and the registered account ID, publicly linking the exit of specific notes with the EOA that registered auth keys. It is a fallback mechanism that reclaims the user's tokens but strips the privacy.\n\nPractical privacy also depends on the timing and amounts of deposits and withdrawals, as well as on the frontend used to interact with the pool. Normal withdrawals and transfers within the private pool are not submitted as onchain transactions via RPC nodes, but directly to the TEE, thus not leaking anything to the RPC. Users are advised to research [OPSEC best practice](/publications/privacy-best-practices).\n\n### Fees\n\nStandard deposits are free of protocol fees. Portal deposits can charge a separate sweeper fee, capped at 10% and currently set to 0%, and have token-specific minimum sweep amounts. Withdrawals, including forced withdrawals and public gift exits, pay a 0.4% fee forwarded to the treasury; a forced withdrawal records the fee at request time.\n\n### Deposit and withdrawal statistics\n\nThe pool's own events do not carry per-transfer amounts, so L2BEAT counts every ERC-20 transfer into the pool as a deposit and every transfer out of it as a withdrawal. Besides regular deposits, portal sweeps and withdrawals, this includes refunds of cancelled deposit requests, withdrawal fees forwarded to the treasury, and both legs of DeFi operations executed through approved gateways.\n\n### Compliance\n\nRegistered auditors can query the Audit API of the TEE to fetch the balance and transaction history of any address. The TEE serves such requests without user consent, but is supposed to emit a record of every access on the AuditGateway smart contract, so that users can publicly verify whether and when their private data was disclosed.\n\nThe source code running within the TEE is not published, so it is impossible to verify the onchain audit attestation mechanism.",
"description": "A shielded ledger for ERC-20 tokens on Base, aimed at institutional users, whose privacy rests on the operator's TEE.",
"detailedDescription": "Privacy Boost is a shielded ledger for ERC-20 tokens on Base, aimed at institutional users. Privacy and liveness depend on the operator's TEE, while zero-knowledge proofs secure funds and a forced exit.\n\n### Architecture\n\nDeposits become notes whose Poseidon2 commitments enter an onchain Merkle tree, and spending a note publishes its nullifier. The TEE collects the transfers and withdrawals users approve and batches them into epochs. A permissioned relay submits each epoch with a Groth16 validity proof.\n\nAccounts approve spends with registered keys or with onchain spend approvals, which also serve smart-wallet accounts. Both are leaves of an auth Merkle tree in the AuthRegistry. Epoch proofs may use a tree root up to 10 minutes old, so a revoked key or approval stays usable that long.\n\n### Forced withdrawals\n\nA user can prove a forced withdrawal of up to 13 notes locally. The contract checks the authorization at request time, and anyone can execute the withdrawal 3 days later if the notes are still unspent. The account owner can cancel it. This is the exit when the operator stops, and it publishes the spent notes and the linked account.\n\n### Portal deposits, gifts and DeFi\n\nPortal deposits use EIP-7702 addresses that users generate locally. Anyone can send ERC-20 tokens there, and sweeps move them into the pool for the hidden recipient. Gift notes go to the recipient or back to the sender after a deadline, privately through the relay or through a public gift exit. Withdrawals can call approved gateways for DeFi.\n\n### Compliance\n\nAuditors appointed by the admin multisig can query the TEE's Audit API for the balance and history of any address, without the user's consent. The AuditGateway lists 0 auditors today. The TEE is meant to record each access on that contract, but with its code unpublished this is unverifiable.\n\n### Privacy considerations\n\nEvery private transaction exists in plaintext inside the operator's TEE, whose source code is unpublished. Privacy therefore also rests on the hardware vendor and on resistance to attacks by anyone with physical access. Practical privacy also depends on the timing and amounts of deposits and withdrawals, see [OPSEC best practice](/publications/privacy-best-practices).\n\n### Fees\n\nStandard deposits pay no protocol fee. Portal deposits pay a sweeper fee of 0%, capped at 10%, and have token-specific minimum sweep amounts. Withdrawals, forced withdrawals and public gift exits pay 0.4% to the treasury. A forced withdrawal fixes its fee at request time.\n\n### Deposit and withdrawal statistics\n\nThe statistics count every ERC-20 transfer into the pool as a deposit and every transfer out as a withdrawal, since pool events omit per-transfer amounts. This includes portal sweeps, refunds of cancelled deposit requests, withdrawal fees sent to the treasury and both legs of gateway DeFi calls.",
"links": {
"websites": [
"https://www.privacyboost.io/"
],
"documentation": [
"https://docs.privacyboost.io/"
],
"repositories": [
"https://github.com/sunnyside-io/privacy-boost-protocol",
"https://github.com/sunnyside-io/privacy-boost-ceremony"
]
}
}
+50 -64
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides everything inside the ledger, including which deposits fund a withdrawal. Deposits and withdrawals 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",
"exposureShort": "Transfers inside publish only encrypted notes.",
"exposureContinued": "Deposits and withdrawals show address, token and amount. Each epoch's calldata pairs every exit with the nullifiers and the input/output shape of the transfer that funded it.",
"advice": "Exit through the operator's relay. A forced exit reveals your account and the notes you spend. A public gift exit names the destination.",
"exposureContinued": "Deposits and withdrawals show address, token and amount. Each epoch pairs every exit with the nullifiers and note shape of the transfer that funded it. Forced withdrawals publish the spent notes and the account, public gift exits the destination.",
"advice": "Exit through the operator's relay.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": {
"verdict": "private",
"note": "Leaked for gateway DeFi legs."
"verdict": "atRisk",
"note": "Public in gateway DeFi legs."
},
"asset": {
"verdict": "private",
"note": "Leaked for gateway DeFi legs."
"verdict": "atRisk",
"note": "Public in gateway DeFi legs."
},
"linkage": {
"verdict": "private",
"note": "Epoch calldata ties each exit to the nullifiers and shape of one transfer."
}
"linkage": "private"
},
"sources": [
{
"contract": "PrivacyBoost"
},
{
"title": "Epoch calldata: withdrawals, nullifiers and transfer shapes",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IPrivacyBoost.sol#L828-L852"
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/5792c139b9529ed80643262d75b5489055be11b0/contracts/src/interfaces/IPrivacyBoost.sol#L828-L852"
},
{
"title": "Forced withdrawal publishes account, destination and notes",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IPrivacyBoost.sol#L582-L592"
"title": "Forced withdrawal publishes account and notes",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/5792c139b9529ed80643262d75b5489055be11b0/contracts/src/interfaces/IPrivacyBoost.sol#L582-L591"
},
{
"title": "Gift claim and refund are indistinguishable",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IPrivacyBoost.sol#L694-L707"
"title": "Public gift exit names the destination",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/5792c139b9529ed80643262d75b5489055be11b0/contracts/src/interfaces/IPrivacyBoost.sol#L707"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "bad",
"exposureShort": "The anonymity set is small, so most withdrawals can be linked to their funding deposits by amount and timing.",
"advice": "There is currently no crowd to hide in. Keep funds inside and transfer often, withdraw amounts that match no deposit, and never exit to an address that has deposited.",
"exposureShort": "The anonymity set is very small.",
"exposureContinued": "Most pool activity is one address that keeps depositing and withdrawing 0.001 WETH, which an analyst can filter out.",
"interior": {
"sender": "atRisk",
"recipient": "atRisk",
"amount": {
"verdict": "atRisk",
"note": "Bounded by the public deposit and exit amounts."
},
"asset": "atRisk",
"linkage": {
"verdict": "atRisk",
"note": "The anonymity set is too small for care to hide the link."
"verdict": "exposed",
"note": "The set is too small to hide in."
}
},
"sources": [
{
"title": "Operator heartbeat address",
"title": "Address with 0.001 WETH round trips",
"url": "https://basescan.org/address/0xf977237b7d978dde922ee4909619740c73d8a49b"
},
{
"contract": "PrivacyBoost",
"title": "Withdrawal fee in basis points"
}
],
"id": "chainAnalyst",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"exposure": "atRisk"
},
{
"field": "amount",
"exposure": "atRisk"
},
{
"field": "asset",
"exposure": "atRisk"
}
]
},
"networkObserver": {
"sentiment": "good",
"exposureShort": "All shielded actions go to the operator's server as an encrypted envelope, and note keys stay in a local vault.",
"exposureContinued": "Only the operator's relay submits epochs onchain, so nothing of yours reaches a public node.",
"sentiment": "warning",
"exposureShort": "Anyone on your network path sees when your wallet deposits and when the app contacts the operator, and can match both to the chain.",
"exposureContinued": "The SDK has no Tor or proxy setting.",
"advice": "Route the app through Tor with system-wide tools.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
"amount": {
"verdict": "atRisk",
"note": "Public in gateway DeFi legs."
},
"asset": {
"verdict": "atRisk",
"note": "Public in gateway DeFi legs."
},
"linkage": {
"verdict": "atRisk",
"note": "Private only over Tor, which the SDK lacks."
}
},
"sources": [
{
"title": "SDK package, closed Rust core",
"url": "https://www.npmjs.com/package/@sunnyside-io/privacy-boost"
},
{
"title": "Server info endpoint",
"title": "Operator endpoint",
"url": "https://base.privacyboost.io/api/v1/info"
},
{
"contract": "PrivacyBoost",
"title": "Single permitted relay"
"title": "SDK 1.2.5, configured with one server URL",
"url": "https://www.npmjs.com/package/@sunnyside-io/privacy-boost/v/1.2.5"
}
],
"id": "networkObserver",
"value": "Link private",
"value": "Link at risk",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposureShort": "The operator runs the enclave that holds every transfer in plaintext and the key to every onchain note.",
"exposureContinued": "The client fetches that key from the operator's web endpoint and the published SDK checks no enclave attestation, so a substituted key would read every note unnoticed. Appointed auditors can pull any account's history without consent, and the audit log is written by the operator's own unpublished code.",
"advice": "Treat everything in the pool as visible to the operator. A forced exit is the only path that does not need it, and it is public.",
"exposureShort": "The operator's enclave holds every transfer in plaintext and a key to every note.",
"exposureContinued": "The SDK trusts the enclave key it fetches from the operator's endpoint. Auditors appointed by the admin can pull any account's history without consent.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "AuditGateway"
},
{
"section": "permissions",
"title": "Admin and operator multisigs"
},
{
"title": "TEE key is fetched from the operator endpoint",
"url": "https://www.npmjs.com/package/@sunnyside-io/privacy-boost"
"title": "SDK fetches the enclave key from the endpoint",
"url": "https://www.npmjs.com/package/@sunnyside-io/privacy-boost/v/1.2.5"
},
{
"title": "Notes wrap an ephemeral key for the TEE alongside the receiver",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IStructs.sol#L36-L56"
"title": "Notes wrap a key for the enclave beside the receiver",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/5792c139b9529ed80643262d75b5489055be11b0/contracts/src/interfaces/IStructs.sol#L36-L56"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "recipient",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
},
{
"field": "asset",
"exposure": "exposed"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposureShort": "Every note wraps its key to the enclave's long-lived elliptic-curve public key as well as the receiver's.",
"exposureContinued": "A quantum computer, or a leak of that one key, decrypts the entire history.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "PrivacyBoost",
"title": "Ciphertext layout"
},
{
"title": "Every output and deposit ciphertext carries a TEE-wrapped key",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IStructs.sol#L36-L125"
"title": "Every output and deposit ciphertext carries an enclave key",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/5792c139b9529ed80643262d75b5489055be11b0/contracts/src/interfaces/IStructs.sol#L36-L125"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "recipient",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
},
{
"field": "asset",
"exposure": "exposed"
}
]
}
}
},
"anonymitySet": {
"type": "too-small"
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "tee",
"label": "TEE",
"description": "Privacy assumptions of this project are secured by trusted hardware."
},
{
"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": "None",
"sentiment": "bad",
"orderHint": 0,
"description": "The pool and both registries sit behind transparent proxies whose ProxyAdmins are owned by the admin multisig, which can upgrade them with no delay. Users get no window to exit before a change takes effect.",
"description": "The admin multisig upgrades the pool and both registries instantly through their ProxyAdmins.",
"walkawayTest": {
"passed": false,
"reason": "If the TEE operators disappear, no new deposits or private transfers can be processed and the system enters exit-only mode."
"reason": "Without the TEE operator, deposits and private transfers stop and only forced withdrawals remain."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "ZK circuits guaranteeing user fund security are published, but the epoch, forced withdrawal and gift claim verification keys deployed in September 2026 have not yet been reproduced by L2BEAT. The TEE sources guaranteeing privacy are not yet published. TEE logic could not be verified for correctness."
"description": "The circuits are published. The epoch, forced withdrawal and gift claim verification keys deployed in September 2026 remain unreproduced, and the TEE source code is unpublished."
},
"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 admin multisig deploys a malicious [upgrade](#upgrades-and-governance) or registers a malicious verifying key.\n
\n## Funds can be lost if\n1. a user loses their note secrets, or loses access to both the account-owner wallet and any usable authorization keys.\n
\n## Privacy can be lost if\n1. the TEE is compromised.\n2. a registered auditor fetches the user's balance and transaction history through the Audit API.\n3. a user exits through a forced withdrawal, which publicly links the spent notes and the withdrawal address to the account that registered the approval key.",
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid spends or withdrawals.\n2. all [trusted setup](#trusted-setups) participants collude or leak their secrets, allowing forged proofs.\n3. the admin multisig deploys a malicious [upgrade](#upgrades-and-governance) or registers a malicious verifying key.\n
\n## Funds can be lost if\n1. a user loses their note secrets, or both the account-owner wallet and every usable authorization key.\n
\n## Privacy can be lost if\n1. the TEE or its hardware vendor is compromised (see privileged insider).\n2. an appointed auditor fetches the user's history through the Audit API.\n3. a user exits through a forced withdrawal (see public observer).\n4. a user relies on today's anonymity set, which is too small to hide in (see chain analyst).",
"tokens": [
{
"token": {
"address": "0x4200000000000000000000000000000000000006",
"iconUrl": "https://coin-images.coingecko.com/coins/images/2518/large/weth.png?1696503332",
"symbol": "WETH",
"decimals": 18,
"priceId": "weth",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-WETH",
"type": "pool",
"label": "WETH",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-USDC",
"type": "pool",
"label": "USDC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
"iconUrl": "https://coin-images.coingecko.com/coins/images/40143/large/cbbtc.webp?1726136727",
"symbol": "cbBTC",
"decimals": 8,
"priceId": "coinbase-wrapped-btc",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-cbBTC",
"type": "pool",
"label": "cbBTC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42",
"iconUrl": "https://coin-images.coingecko.com/coins/images/26045/large/euro.png?1696525125",
"symbol": "EURC",
"decimals": 6,
"priceId": "euro-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-EURC",
"type": "pool",
"label": "EURC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x311935Cd80B76769bF2ecC9D8Ab7635b2139cf82",
"iconUrl": "https://coin-images.coingecko.com/coins/images/4128/large/solana.png?1718769756",
"symbol": "SOL",
"decimals": 9,
"priceId": "solana",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-SOL",
"type": "pool",
"label": "SOL",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39963/large/usdt.png?1724952731",
"symbol": "USDT",
"decimals": 6,
"priceId": "l2-standard-bridged-usdt-base",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-USDT",
"type": "pool",
"label": "USDT",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x940181a94A35A4569E4529A3CDfB74e38FD98631",
"iconUrl": "https://assets.coingecko.com/coins/images/31745/large/token.png?1696530564",
"symbol": "AERO",
"decimals": 18,
"priceId": "aerodrome-finance",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-AERO",
"type": "pool",
"label": "AERO",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xB2000000000000000000004c27f6523082f41D01",
"iconUrl": "https://coin-images.coingecko.com/coins/images/102175780/large/zi54rndmdx59nblfgry3d1pyckch.?1787558766",
"symbol": "Basecat",
"decimals": 18,
"priceId": "basecat",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-Basecat",
"type": "pool",
"label": "Basecat",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
"iconUrl": "https://coin-images.coingecko.com/coins/images/18834/large/wstETH.png?1696518295",
"symbol": "wstETH",
"decimals": 18,
"priceId": "wrapped-steth",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-wstETH",
"type": "pool",
"label": "wstETH",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xb200000000000000000000C2e324d24d7eEcd1fb",
"iconUrl": "https://coin-images.coingecko.com/coins/images/102175597/large/aapl_200x200.png?1787068801",
"symbol": "AAPLc",
"decimals": 8,
"priceId": "apple-coinbase-tokenized-stock",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-AAPLc",
"type": "pool",
"label": "AAPLc",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xcb585250f852C6c6bf90434AB21A00f02833a4af",
"iconUrl": "https://coin-images.coingecko.com/coins/images/66267/large/Coinbase_Wrapped_XPR_%28cbXRP%29.png?1749023398",
"symbol": "cbXRP",
"decimals": 6,
"priceId": "coinbase-wrapped-xrp",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-cbXRP",
"type": "pool",
"label": "cbXRP",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4",
"iconUrl": "https://assets.coingecko.com/coins/images/31126/large/2023-08-11_13.21.24.png?1697025145",
"symbol": "TOSHI",
"decimals": 18,
"priceId": "toshi",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-TOSHI",
"type": "pool",
"label": "TOSHI",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x532f27101965dd16442E59d40670FaF5eBB142E4",
"iconUrl": "https://assets.coingecko.com/coins/images/35529/large/1000050750.png?1709031995",
"symbol": "BRETT",
"decimals": 18,
"priceId": "based-brett",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-BRETT",
"type": "pool",
"label": "BRETT",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xbeeff7aE5E00Aae3Db302e4B0d8C883810a58100",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "bbqUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-bbqUSDC",
"type": "pool",
"label": "bbqUSDC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x1deEfABEe758AAbdC29a542B24ca3b75aFD56765",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "gtusdcf",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-gtusdcf",
"type": "pool",
"label": "gtusdcf",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0xFeFeC33668E22677c4762d0853d56245a800ff08",
"iconUrl": "https://coin-images.coingecko.com/coins/images/2518/large/weth.png?1696503332",
"symbol": "gtwethb",
"decimals": 18,
"priceId": "weth",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-gtwethb",
"type": "pool",
"label": "gtwethb",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x1D3b1Cd0a0f242d598834b3F2d126dC6bd774657",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "CSUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-CSUSDC",
"type": "pool",
"label": "CSUSDC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
},
{
"token": {
"address": "0x5435BC53f2C61298167cdB11Cdf0Db2BFa259ca0",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "edgeUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1788377831
},
"buckets": [
{
"id": "privacy-boost-edgeUSDC",
"type": "pool",
"label": "edgeUSDC",
"address": "base:0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40",
"sinceTimestamp": 1788377831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x71A0fD3C76E3E937d8275A3cb6a467b70123bD40"
}
}
}
]
}
],
"trackedOn": [
"base"
],
"upgradesAndGovernance": {
"content": "Privacy Boost is controlled by the 3/4 admin multisig, which can upgrade the pool, registries and AuditGateway without delay. It can replace all five proof verifiers and register or replace their verification keys, set withdrawal and portal sweep fees up to 10% each, configure portal minimum sweeps, and change the treasury, operator and gateway route manager.\n\nThe external-call gateway owner manages target/selector policies, selects its guardian, and can pause or unpause execution. The guardian can pause and remove policies. Stranded gateway tokens can only be swept back to the pool while paused."
"content": "The 3/4 admin multisig upgrades the pool, registries and AuditGateway instantly. It can replace all five verifiers and their keys, set withdrawal and portal fees up to 10% each, configure portal minimum sweeps, appoint auditors, and change the treasury, operator and gateway route manager.\n\nThe gateway owner manages target and selector policies, picks the guardian and can pause execution. The guardian can pause and remove policies. Stranded gateway tokens return to the pool only while paused."
}
}
+63 -55
+1 -1
{
"badges": [],
"description": "An onchain privacy system for Ethereum based on encrypted UTXO-style private balances and zk-proven DeFi interactions.",
"detailedDescription": "Railgun is a non-custodial privacy protocol on Ethereum built around encrypted UTXO-style private balances rather than fixed-denomination pools. This design enables in-protocol transfers of shielded tokens and interactions with DeFi smart contracts on L1.\n\nA shield transaction moves assets from a public address on Ethereum into the Railgun contract and creates encrypted commitments in a Merkle-tree state. Later private transfers or unshields use zk-SNARK proofs to spend those commitments without revealing the sender, recipient, token type, or amount. Notes created by deposits and private transactions represents ownership of tokens in Railgun, users must keep them secret and make sure the notes are not lost.\n\nRailgun supports private transfers and cross-contract interactions without fragmenting liquidity across denominations. DeFi calls can be executed through the RelayAdapt contract, which temporarily unshields tokens to Ethereum L1, performs a sequence of contract calls, and shields the resulting assets back into Railgun in a single transaction (facilitated by a relayer).\n\nRailgun has a DAO governed by holders of the RAIL token. The DAO has the authority to arbitrarily change the logic of the protocol and its shielded tokens.\n\n### Privacy considerations\n\nRailgun protocol supports [relayed withdrawals](https://docs.railgun.org/developer-guide/wallet/transactions/unshielding), in which a relayer (called a broadcaster in Railgun ecosystem) processes withdrawals on the user's behalf for a fee, which enables sending funds to fresh addresses. Transactions from private addresses can be sent through relayers over the [Waku network](https://blog.waku.org/2024-04-26-railgun-case-study/), which increases network-level privacy. Railgun allows interactions between shielded tokens and DeFi, which allows depositing and withdrawing different tokens.\n\nPractical privacy also depends on the timing and amounts of deposits and withdrawals. Users are advised to research [OPSEC best practice](/publications/privacy-best-practices).\n\n### Fees\n\nThere are mandatory onchain protocol fees of 0.25% for shields and 0.25% for unshields. The NFT fee field is currently set to 0. Shield and unshield fees are sent to the Railgun Treasury.\n\nRelayers can charge additional offchain fees for submitting transactions on a user's behalf. These relayer fees are not set by the core protocol contracts.\n\n### Compliance\n\nRailgun protocol does not enforce any compliance measures. However it allows using [Private Proof of Innocence](https://docs.railgun.org/wiki/assurance/private-proofs-of-innocence)(PPoI), which can attest to the origin and history of shielded tokens. Relayers and some wallets require a valid PPoI for their services, but they are not generally enforced.\n\nAdditionally, Railgun users can share a read-only viewing key to expose all sent and received private transactions, if required by a regulator or enforcer. \n### Anonymity set\n\nBecause Railgun allows private transfers, optional PPoIs that can be enforced by relayers, and interactions with DeFi, its anonymity set depends on many details. A withdrawal from Railgun could be connected with a deposit of another token, or could not correspond to any deposit if a user received a private transfer from another user. The anonymity set, in the best case, corresponds to the set of all Railgun users.",
"detailedDescription": "Railgun is a shielded ledger on Ethereum. Users shield tokens into encrypted notes, transfer them privately and unshield them to any address. zk-SNARK proofs keep sender, recipient, token and amount hidden. DeFi calls go through the RelayAdapt contract, which unshields tokens, runs the calls and shields the results back in one transaction.\n\n### Privacy considerations\n\n[Broadcasters](https://docs.railgun.org/developer-guide/wallet/transactions/unshielding) submit private transactions and pay their gas. Wallets reach them over the [Waku network](https://blog.waku.org/2024-04-26-railgun-case-study/). Practical privacy also depends on the timing and amounts of shields and unshields, see [OPSEC best practice](/publications/privacy-best-practices).\n\nRailgun names no reference wallet, so the privacy ratings on this page assume [RailOxide](https://github.com/triamazikamno/railoxide). It routes all traffic through built-in Tor and builds Private Proofs of Innocence (PPoI) from a local copy of the lists. Other wallets likely leak significantly more.\n\n### Fees\n\nShields pay a protocol fee of 0.25% and unshields 0.25%, both to the Railgun Treasury. The NFT fee is 0. Broadcasters charge their own fee per transaction.\n\n### Compliance\n\nScreening happens offchain. A [PPoI](https://docs.railgun.org/wiki/assurance/private-proofs-of-innocence) proves that a note descends only from shields a list provider accepted. The default list screens shields with Chainalysis's sanctions API. Broadcasters on Ethereum require a PPoI, self-broadcasting skips the check. Users can also share a read-only viewing key that discloses all their private transactions.\n\n### Anonymity set\n\nEach token has its own anonymity set. Private transfers between users mix their notes within it.",
"links": {
"websites": [
"https://railgun.org"
]
}
}
+62 -54
{
"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",
"exposureShort": "Everything inside the pool is hidden, including which shield funds which unshield.",
"exposureContinued": "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."
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"asset": {
"verdict": "private",
"note": "Leaked for DeFi bundles."
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"linkage": "private"
},
"sources": [
{
"contract": "RailgunSmartWallet"
"contract": "RailgunSmartWallet",
"title": "Shield and unshield"
},
{
"title": "Note ciphertext format",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/note/transact-note.ts"
"contract": "RelayAdapt",
"title": "DeFi bundles"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposureShort": "The candidates for an unshield are the shields of the same token.",
"exposureContinued": "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.",
"exposureContinued": "In-pool transfers break a one-to-one match, while timing and exact amounts narrow it.",
"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",
"amount": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"asset": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"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",
"exposureShort": "The wallet finds its notes by trial-decrypting every note locally, so nodes learn nothing about which are yours.",
"exposureContinued": "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.",
"exposureShort": "RailOxide sends all traffic over built-in Tor, broadcaster messages included, and finds your notes by decrypting every note locally.",
"advice": "Use RailOxide, the wallet these ratings assume, and read the chain from your own node.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
"amount": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"asset": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"linkage": {
"verdict": "atRisk",
"note": "Private only over Tor, which RailOxide uses by default."
}
},
"sources": [
{
"title": "Gas estimation with dummy proof",
"url": "https://github.com/Railgun-Community/wallet/blob/main/src/services/transactions/tx-gas-details.ts"
"title": "RailOxide privacy model",
"url": "https://github.com/triamazikamno/railoxide/blob/8773f4ecb00c6ac7cf164ba1f989eb77dd4b0ec5/docs/privacy-model.md"
},
{
"title": "Broadcaster decrypts request",
"url": "https://github.com/Railgun-Community/ppoi-safe-broadcaster-example/blob/main/src/server/waku-broadcaster/methods/transact-method.ts"
"title": "Built-in Tor is the default",
"url": "https://github.com/triamazikamno/railoxide/blob/8773f4ecb00c6ac7cf164ba1f989eb77dd4b0ec5/crates/wallet-ops/src/settings/network_chains.rs#L10-L15"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "good",
"exposureShort": "There is no view key, so nobody can read past activity.",
"exposureContinued": "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.",
"exposureShort": "Only the user holds viewing keys, and DAO upgrades wait 7 days.",
"exposureContinued": "PPoI list providers can refuse a shield, which leaves a self-broadcast exit. RailOxide builds PPoIs from a local copy of the lists, so the notes you spend stay on your device.",
"advice": "Watch governance proposals and unshield before an upgrade you reject executes.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"amount": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"asset": {
"verdict": "atRisk",
"note": "Public in DeFi bundles."
},
"linkage": {
"verdict": "atRisk",
"note": "POI nodes tie a session to a note cluster and its transaction ids."
"note": "Private only with a wallet that builds PPoIs locally, like RailOxide."
}
},
"sources": [
{
"section": "permissions",
"title": "Governance roles"
"section": "upgrades-and-governance"
},
{
"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"
"title": "RailOxide builds PPoIs locally",
"url": "https://github.com/triamazikamno/railoxide/blob/8773f4ecb00c6ac7cf164ba1f989eb77dd4b0ec5/crates/wallet-ops/src/poi_contexts.rs#L116-L150"
}
],
"id": "privilegedInsider",
"value": "Link private",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposureShort": "Notes are encrypted with elliptic-curve key exchange.",
"exposureContinued": "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.",
"exposureContinued": "A quantum computer decrypts every note sent to a 0zk address that was ever shared, broadcaster fee notes included.",
"advice": "Share your 0zk address privately, with a fresh one per counterparty where you can.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Decrypts for notes touching any shared 0zk address."
},
"sender": "atRisk",
"recipient": "atRisk",
"amount": "atRisk",
"asset": "atRisk",
"linkage": "atRisk"
"linkage": {
"verdict": "atRisk",
"note": "Private only while your 0zk address stays unshared."
}
},
"sources": [
{
"title": "Shared key derivation (Ed25519 ECDH)",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/keys-utils.ts"
"url": "https://github.com/Railgun-Community/engine/blob/6e2614d53a106dd62abad91e7ce03ee4a3956138/src/utils/keys-utils.ts#L186-L224"
},
{
"title": "AES-GCM note encryption",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/encryption/aes.ts"
"url": "https://github.com/Railgun-Community/engine/blob/6e2614d53a106dd62abad91e7ce03ee4a3956138/src/utils/encryption/aes.ts#L24-L40"
}
],
"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.",
"description": "DAO-approved upgrades wait 7d before execution, so users can unshield before a change they reject.",
"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.",
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid spends or withdrawals.\n2. all [trusted setup](#trusted-setups) participants collude or leak their secrets, allowing forged proofs.\n3. the DAO passes a malicious [upgrade](#upgrades-and-governance) and users stay in the pool past its 7 days execution delay.\n
\n## Funds can be lost if\n1. a user loses the keys of their private balance.\n
\n## Privacy can be lost if\n1. a user sends transactions from their own public address (see public observer).",
"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: ",
"content": "RAIL stakers govern Railgun through a DAO. It can upgrade the core contract and its circuits, which changes the rules for every shielded token. It can also block tokens from new shields, mint RAIL and manage governance rewards. [Governance docs](https://docs.railgun.org/wiki/rail-token/protocol-governance).",
"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."
}
}
}
}
+69 -110
+1 -1
{
"badges": [],
"description": "A private DAI wallet on Aztec Network, with funds escrowed on Ethereum.",
"detailedDescription": "Internal payments are hidden, but names, deposits and withdrawals are public. The first payment to a new contact reveals the recipient. The first sponsored transaction after registration reveals the sender's account.\n\nEvery withdrawal and refund needs a proof and a live AWS Nitro enclave. Operations are encrypted to the enclave (TEE), which decrypts and reads them. Its approved binary has not been reproduced from the published source. Aztec Labs controls zk.money names and the released wallets' contract configuration.\n\n### Multiproofs and exits\nThe portal releases funds only after Aztec proves the withdrawal message (zk proof of validity) and any one registered enclave signer co-signs it (TEE signature). Stealing escrowed funds requires both layers to fail while privacy leaks depend on either. Anyone can register an enclave running the approved image with a fresh AWS attestation.\n\nIf Aztec governance changes its canonical rollup, anyone can freeze the portal. Deposits stop and refundable ownership is fixed at the last proven checkpoint. Later L2 transfers do not change it. Withdrawals and refunds still need an enclave. Refunds expose note or deposit amounts on Ethereum and use proofs without zero knowledge.\n\n### Wallet\n- **Hosted:** loads code from zk.money on every visit. Whoever controls deployment can read viewing keys and request harmful passkey signatures. Passkey prompts do not show the operation.\n- **Desktop:** runs local code but fetches contract addresses from two unsigned Aztec Labs lists. Substituting them can redirect future deposits and payments.\n- **Independent operation:** requires modifying the desktop build to pin verified addresses, remove screening and serve it under auth.zk.money. Users can submit Ethereum transactions themselves and run the approved enclave on AWS. New names still require Aztec Labs' signature. L2BEAT has not run this setup.\n\nBoth released wallets allow custom Aztec, Ethereum and enclave endpoints. Their passkeys belong to auth.zk.money, which must authorize wallet.zk.money on every use. Onchain contracts do not check the signature's origin. A modified wallet served under auth.zk.money would bypass this dependency.\n\nWallets use XMTP, an end-to-end encrypted messaging network, to confirm contacts added by QR code or link and to send payment requests. Messages are encrypted, but each inbox is publicly tied to a name, so XMTP's servers can see which names talk to each other.\n\nThe browser stores the master key unencrypted until sign-out, and viewing keys and decrypted notes until local data is cleared. All keys except the spending key derive from the master key (privacy is lost if the master key is leaked).\n\n### Deposits and fees\nUsers fund deposit addresses called SIPAs. Anyone can sweep them into the Ethereum portal. USDC and USDT are swapped to DAI through Curve. After fees, DAI stays in escrow and an Inbox message credits private notes on Aztec L2. SIPAs can be reused, at the expense of user privacy.\n\nA sweep pays 0.25 DAI, or 0.5 DAI when claiming a name. Registration costs 5 DAI by default, including its sweep fee. The domain owner (onchain role in NameRegistry) can sign custom prices and add fee beneficiaries. Users select a beneficiary in their registration intent.\n\nThe portal takes 0.1 DAI from each deposit and ordinary withdrawal to sponsor Aztec fees. Sponsorship requires a registered name or a voucher from a registered account. An empty fee-paying contract or fees above its allowance stall the released wallet. Modified code can pay with the account's own Fee Juice (potential privacy implications). Deposits share a 50,000 DAI capacity, refilling over 1 day. Deposit, payment and withdrawal transaction amounts are capped at 2,583 DAI each.\n\n### Names and Compliance\nNames (tags) publicly map to Aztec addresses and keys on Ethereum. Claims require the domain owner's signature from a closed-source server with a name blocklist. The released wallet requires a registered name to access an account on a new device.\n\nExternal name payments use a resolver operator to derive and announce deposit addresses. Internal payments skip it (reading from the onchain contract), but wallet-created deposit addresses still derive from Aztec Labs' operator key. The onchain Resolver checks a zk proof on every lookup, binding each address to the recipient's registered keys, Aztec address and L1 account, so the operator cannot redirect payments. It can still re-derive every deposit address of its users. Users can choose another operator for name payments. The only registered operator is Aztec Labs, and its service is unpublished.\n\nThe wallet sends Ethereum addresses to Predicate through zk.money for screening, which can be bypassed by funding a deposit SIPA directly. The relayer also screens token movements against OFAC and optionally Predicate. Self-submitting sweeps and proven withdrawals bypasses relayer screening.\n\nThe name resolver screens deposit addresses and funders against OFAC before notifying the recipient on L2. A blocked payment leaves funds at an address the wallet never learns. Recovery requires the recipient's own tooling to re-derive it and authorization from their L1 account. Onchain contracts and the enclave do not check compliance lists.\n\n### Source verification\nThe [token verification steps](https://github.com/l2beat/l2beat/blob/main/packages/config/src/projects/zkmoney/verificationSteps-token.md) compare a fresh source build with the Aztec instance (L2 contract) pinned by the Ethereum portal. The [verifier steps](/zk-catalog/barretenberg#verifiers) regenerate the keys and Solidity verifiers of the refund and resolver circuits and compare them with the deployed contracts.",
"detailedDescription": "zk.money is a private DAI wallet on Aztec, with funds escrowed in an Ethereum portal. Payments inside are hidden, while names, deposits and withdrawals are public.\n\nEvery withdrawal and refund needs a zk proof and a signature from a live AWS Nitro enclave (TEE). The enclave decrypts and reads the operations it handles. Aztec Labs controls zk.money names and the contract lists the released wallets use.\n\n### Multiproof system\nThe portal releases funds only after Aztec proves the withdrawal message and one registered enclave signer co-signs it. Stealing escrowed funds requires both layers to fail, while a failure of either breaks privacy.\n\nIf Aztec Network governance changes its canonical rollup, anyone can freeze the zk.money portal, see [upgrades and governance](#upgrades-and-governance). Refunds then publish note or deposit amounts on Ethereum and use proofs without zero knowledge.\n\n### Wallets\nThe privacy ratings assume [zk.money Desktop v0.1.0](https://github.com/aztec-labs-eng/zkmoney-public/releases/tag/desktop-v0.1.0). There also is a hosted wallet without published source and the potential to build your independent wallet:\n- **Desktop:** runs local code but fetches contract addresses from two unsigned Aztec Labs lists. The wallet checks the [profile](https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/config-client/src/toContractServiceConfig.ts#L41-L68) against the [manifest](https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/core/src/oxide/index.ts#L108-L170), and both come from Aztec Labs. Substituting them can redirect future deposits and payments.\n- **Hosted:** loads code from zk.money on every visit, which makes its owner an insider. It can read viewing keys and request harmful passkey signatures behind prompts that hide the operation.\n- **Independent operation:** would allow a desktop build modified to pin verified addresses, remove screening and serve it under auth.zk.money. Users could submit Ethereum transactions themselves and run the approved enclave on AWS. New names still require Aztec Labs' signature. This setup is untested.\n\n### Deposits\nUsers fund L1 deposit addresses called SIPAs, and anyone can sweep them into the Ethereum portal. USDC and USDT are swapped to DAI through Curve. After fees, DAI stays in escrow and an Inbox message credits private notes on Aztec L2. Reusing a SIPA links its deposits.\n\n### Names\nTags like l2beat.zk.money publicly map to Aztec addresses and keys on Ethereum. They have two uses:\n- **L1 deposits:** any Ethereum wallet with ENS offchain lookups can pay l2beat.zk.money. The lookup returns a deposit address from the recipient's chosen resolver operator.\n- **L2 transfers:** zk.money users add a tag as a contact, and the wallet reads its Aztec address from the onchain registry to send private transfers.\n\nClaims require the domain owner's signature from a closed-source server with a name blocklist. The released wallet requires a registered name to access an account on a new device. Wallets use XMTP, an end-to-end encrypted messaging network, to confirm contacts added by QR code or link and to send payment requests.\n\n### Resolver\nFor ENS lookups, the resolver operator derives each deposit address from a secret shared with the recipient and announces it to them on L2. The wallets derive their own deposit addresses from the same shared secret, so the operator can link them. The onchain Resolver checks a zk proof on every lookup, which stops the operator from redirecting payments. Users can choose a custom operator for name payments.\n\n### Compliance\nThe wallet sends Ethereum addresses to Predicate through zk.money for screening, which funding a deposit SIPA directly avoids. The relayer screens token movements against OFAC and optionally Predicate, and self-submitted sweeps and withdrawals skip it.\n\nThe name resolver screens deposit addresses and funders against OFAC before notifying the recipient on L2. A blocked payment leaves funds at an address unknown to the wallet. Recovery requires the recipient's own tooling to re-derive it and authorization from their L1 account. Screening happens only in these offchain services.\n\n### Fees and limits\nA sweep pays 0.25 DAI, or 0.5 DAI when claiming a name. Registration costs 5 DAI by default, including its sweep fee.\n\nThe portal takes 0.1 DAI from each deposit and ordinary withdrawal to sponsor Aztec fees. Sponsorship requires a registered name or a voucher from a registered account. An empty fee-paying contract, or fees above its allowance, stall the released wallet. Modified code can pay with the account's own Fee Juice. Deposits share a 50,000 DAI capacity, refilling over 1 day. Deposit, payment and withdrawal amounts are capped at 2,583 DAI each.\n\n### Source verification\nThe [token verification steps](https://github.com/l2beat/l2beat/blob/main/packages/config/src/projects/zkmoney/verificationSteps-token.md) compare a fresh source build with the Aztec instance (L2 contract) pinned by the Ethereum portal. The [verifier steps](/zk-catalog/barretenberg#verifiers) regenerate the keys and Solidity verifiers of the refund and resolver circuits.",
"links": {
"websites": [
"https://zk.money"
],
"documentation": [
"https://docs.zk.money/docs"
],
"repositories": [
"https://github.com/aztec-labs-eng/zkmoney-public"
],
"explorers": [
"https://aztecscan.xyz/contracts/instances/0x015ca4a43f83d08a038c36c06ca92527f120dc1f9176ea85d1ea347decaf444d"
]
}
}
+68 -109
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides senders, amounts and links between deposits and withdrawals within the ledger. Tags, deposits and withdrawals are public. The first payment to a new contact reveals the recipient, and the first sponsored transaction after registration reveals the sender’s account."
"text": "Hides senders, amounts and the link between deposits and withdrawals inside the ledger. Names, deposits and withdrawals 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",
"exposureShort": "Private payments publish encrypted notes.",
"exposureContinued": "Fixed log tags identify zk.money transactions on Aztec, and the first payment to a new contact reveals the recipient's Aztec address through a handshake. The Ethereum registry maps that address to a tag. The first sponsored transaction after registration also identifies the sender's account. Deposits and withdrawals show address, token and amount. Claiming a tag links it and the Aztec address to the funding L1 wallet.",
"advice": "Claim your tag from a wallet with no public link to you and fund each deposit address once. Wait for deposits to be swept. Recovering them reveals the link to your account.",
"exposureContinued": "Claiming a name ties it and its Aztec address to the wallet that funds the registration. The first payment to a new contact reveals the recipient through a handshake, and L2 logs mark every transaction of the shared token smart contract. Your first sponsored transaction after registration is tied to your account, with the payment, deposit address or withdrawal it carries.",
"advice": "Claim your name from a wallet with no public link to you, and make your first transaction after registration a deposit from that wallet. Fund each deposit address once and let it be swept/relayed.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Your first sponsored transaction after registration is publicly tied to your account."
"note": "Public for your first sponsored transaction after registration."
},
"recipient": {
"verdict": "exposed",
"note": "The first payment to a new contact reveals the recipient's Aztec address."
"note": "Revealed by the first payment to each new contact."
},
"amount": "private",
"asset": {
"verdict": "exposed",
"note": "zk.money only holds DAI."
"note": "Only DAI."
},
"linkage": {
"verdict": "atRisk",
"note": "If your first sponsored transaction after registration is a payment to a new contact, it shows both ends."
"note": "Exposed when your first sponsored transaction after registration withdraws or pays a new contact."
}
},
"sources": [
{
"title": "Fixed log tags on every zk.money transaction",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/noir-projects/oxide_lib/src/constants.nr#L77-L81"
"title": "Fixed log tags on every token transaction",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/vendor/oxide/noir-projects/oxide_lib/src/constants.nr#L77-L81"
},
{
"title": "First delivery to a new contact opens a handshake",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/sdk/src/feePaymentMethod/claimFpcGasModel.ts#L232-L237"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/sdk/src/feePaymentMethod/claimFpcGasModel.ts#L232-L237"
},
{
"title": "First sponsored transaction nullifies the L1 account",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/contracts/contracts/fee_paying/claim_fpc/src/main.nr#L205-L217"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/contracts/contracts/fee_paying/claim_fpc/src/main.nr#L205-L217"
},
{
"title": "Withdrawals publish their L1 payload",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/noir-projects/oxide_token_contract/src/withdrawal.nr#L32-L42"
},
{
"contract": "RegistrationController"
},
{
"contract": "AccountMetadataRegistry"
},
{
"contract": "DepositSIPA"
"contract": "AccountMetadataRegistry",
"title": "Names map to Aztec addresses"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposureShort": "The anonymity set is limited to zk.money users.",
"exposureContinued": "The first payment to a tag from outside zk.money is publicly tied to that tag. Anyone who records Aztec transactions can also tie the first deposit address your wallet creates after registration to your account.",
"advice": "Watch the anonymity set in this early stage. Give outside payers a deposit address your wallet created instead of your tag. Fund your first deposit address after registration from the wallet that claimed your tag. 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.",
"exposureShort": "In practice the anonymity set is zk.money's users on Aztec, although the L2 contract is permissionless.",
"exposureContinued": "The first payment to a name from outside zk.money is publicly tied to that name.",
"advice": "Give outside payers a deposit address your wallet created. 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": "atRisk",
"recipient": "exposed",
"sender": {
"verdict": "atRisk",
"note": "Public for your first sponsored transaction after registration."
},
"recipient": {
"verdict": "exposed",
"note": "Revealed by the first payment to each new contact."
},
"amount": {
"verdict": "atRisk",
"note": "Inferable when a payment sits between a matching public deposit and withdrawal."
},
"asset": "exposed",
"asset": {
"verdict": "exposed",
"note": "Only DAI."
},
"linkage": {
"verdict": "atRisk",
"note": "Registration deposits are publicly tied to their tag."
"note": "Registration deposits are publicly tied to their name."
}
},
"sources": [
{
"contract": "ZkMoneyPortal"
},
{
"contract": "RegistrationSIPA"
},
{
"contract": "PlainWithdrawalExecutor"
},
{
"title": "Private transfers credit the recipient with new notes",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/noir-projects/oxide_token_contract/src/main.nr#L133-L167"
},
{
"title": "Resolver notifies the recipient of each deposit address",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/noir-projects/oxide_token_contract/src/main.nr#L236-L251"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/vendor/oxide/noir-projects/oxide_token_contract/src/main.nr#L236-L251"
},
{
"title": "The notification and the sweep request share one Aztec transaction",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/sdk/src/services/sipaIntents.ts#L171-L186"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/sdk/src/services/sipaIntents.ts#L171-L186"
},
{
"title": "Handshake announcements are tagged with the recipient address",
"url": "https://github.com/AztecProtocol/aztec-packages/blob/v5.2.0/noir-projects/noir-contracts/contracts/standard/handshake_registry_contract/src/main.nr#L82-L96"
}
],
"id": "chainAnalyst",
"value": "Link at risk",
"alsoExposed": [
{
"field": "amount",
"exposure": "atRisk"
}
]
},
"networkObserver": {
"sentiment": "good",
"exposureShort": "Keys and proving stay on your device.",
"exposureContinued": "Note discovery reveals your account address to the Aztec node. Ethereum RPC requests reveal funding wallets, deposit addresses and L1 transaction senders. XMTP carries payment requests and contact links under public account addresses, exposing who asks whom for money. Both wallets support custom Aztec, Ethereum and enclave endpoints.",
"advice": "Use zk.money Desktop with your own Aztec and Ethereum nodes. Send L1 transactions from your Ethereum wallet over a public RPC. Route all computer traffic through a VPN or Tor. Avoid payment requests and contact links with counterparties that must stay private.",
"sentiment": "warning",
"exposureShort": "Anyone on your network path sees when you send Aztec transactions and can match your deposit and withdrawal to the blocks they land in.",
"exposureContinued": "Desktop has no Tor or proxy setting.",
"advice": "Route zk.money Desktop through Tor with system-wide tools.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Payment requests over XMTP show who asks whom."
"note": "XMTP shows who asks whom for payment."
},
"recipient": "exposed",
"recipient": {
"verdict": "exposed",
"note": "Revealed by the first payment to each new contact."
},
"amount": "private",
"asset": "exposed",
"linkage": "atRisk"
"asset": {
"verdict": "exposed",
"note": "Only DAI."
},
"linkage": {
"verdict": "atRisk",
"note": "Private only over Tor, which Desktop lacks."
}
},
"sources": [
{
"title": "Desktop endpoint overrides",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/web-wallet-desktop/src/config.js#L36-L47"
"title": "Desktop settings: endpoints only, no proxy",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/web-wallet-desktop/src/config.js#L36-L47"
},
{
"title": "Handshakes are found by a tag derived from your address",
"url": "https://github.com/AztecProtocol/aztec-packages/blob/v5.2.0/noir-projects/noir-contracts/contracts/standard/handshake_registry_contract/src/main.nr#L82-L96"
},
{
"title": "L1 gas estimates over the wallet RPC carry your address",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/web-wallet/src/features/deposit/sipaRecovery.ts#L166-L193"
},
{
"title": "Desktop sends screening to zk.money from its own process",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/web-wallet-desktop/scripts/compose-config.js#L15-L20"
},
{
"title": "XMTP identity is the account bootstrap address",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/web-wallet/src/platform/xmtp/WebXmtpClient.ts#L95-L109"
},
{
"title": "Pointing the wallet at a different service",
"url": "https://docs.zk.money/docs/desktop"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/web-wallet/src/platform/xmtp/WebXmtpClient.ts#L95-L109"
}
],
"id": "networkObserver",
"value": "Link private",
"value": "Link at risk",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposureShort": "Wallets encrypt payments, withdrawals and deposit claims to an enclave key registered in the portal.",
"exposureContinued": "The approved code decrypts them inside the enclave. Privacy against the operator depends on AWS Nitro and that code, whose binary has not been reproduced. The resolver operator can re-derive all deposit addresses, including those created by your wallet, linking L1 deposits to L2 recipients.",
"advice": "Run your own enclave, which is permissionless onchain but still depends on AWS. Running your own resolver operator is also permissionless, but its service is unpublished and the released wallets only use Aztec Labs' operator.",
"exposureShort": "The wallets derive their own deposit addresses from an ECDH secret shared with the resolver operator, Aztec Labs today.",
"exposureContinued": "Matching the derived commitments against public portal deposits lets the operator link L1 deposits to L2 recipients. Payments, withdrawals and deposit claims are encrypted to an enclave admitted with an AWS Nitro attestation, which reads them inside.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Enclave requests carry notes and the nullifier hiding key",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/yarn-project/oxide-lib/src/types.ts#L336-L392"
"title": "Wallets derive deposit addresses against the resolver key",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/web-wallet/src/features/deposit/sipaGateway.ts#L857-L871"
},
{
"title": "Wallets encrypt to the enclave key registered in the portal",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/yarn-project/oxide-client/src/fleet_signer.ts#L172-L202"
"title": "Their nonces count down a predictable range",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/sdk/src/services/sipaSelfResolve.ts#L49-L58"
},
{
"title": "Deposit address secrets derive from the resolver key",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/sdk/src/services/sipaStealth.ts#L80-L100"
"title": "Wallets encrypt to the enclave key registered in the portal",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/vendor/oxide/yarn-project/oxide-client/src/fleet_signer.ts#L172-L202"
},
{
"title": "The resolver circuit derives each secret from the operator key",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/68425f9cf408ac803eade04d10318fcf345444a0/vendor/oxide/noir-projects/resolver_circuit/src/main.nr#L23-L79"
},
{
"title": "Self-made deposit addresses use predictable nonces",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/sdk/src/services/sipaSelfResolve.ts#L47-L53"
},
{
"title": "Addresses are sent to Predicate for screening",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/front-core/src/core/services/screening/PredicateScreeningService.ts#L86-L97"
},
{
"contract": "ZkMoneyPortal",
"title": "Registered TEE signers"
},
{
"contract": "Resolver"
},
{
"contract": "AccountMetadataRegistry",
"title": "Resolver operators"
},
{
"section": "permissions"
"title": "Deposits publish the recipient commitment"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposureShort": "A quantum computer that breaks elliptic-curve key exchange can decrypt historical notes and payment events published to Ethereum.",
"exposureContinued": "Registered Aztec addresses identify the accounts. Deposit address secrets and enclave communication use the same class of cryptography.",
"advice": "Treat every payment and every deposit link as permanently disclosed.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "AccountMetadataRegistry",
"title": "Registered Aztec addresses"
},
{
"title": "Deposit address secrets use secp256k1 key exchange",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/sdk/src/services/sipaStealth.ts#L80-L100"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/packages/sdk/src/services/sipaStealth.ts#L80-L100"
},
{
"title": "Enclave channel uses P-256 HPKE",
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/vendor/oxide/yarn-project/oxide-lib/src/encryption.ts#L1-L5"
"url": "https://github.com/aztec-labs-eng/zkmoney-public/blob/f04743f5d57d1b89f9190cad0f6affd28b0793f2/vendor/oxide/yarn-project/oxide-lib/src/encryption.ts#L1-L5"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
}
]
}
}
},
"anonymitySet": {
"type": "partially-attributed"
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "tee",
"label": "TEE",
"description": "Privacy assumptions of this project are secured by trusted hardware."
},
{
"id": "transfers",
"label": "Transfers",
"description": "Private transfers 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": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "The escrow and approved enclave image cannot be upgraded. Every withdrawal and refund still needs a proof and a live approved enclave. If Aztec changes its canonical rollup, anyone can freeze deposits and fix refundable ownership at the last proven checkpoint. Later L2 transfers do not change it.",
"description": "The escrow and the approved enclave image are immutable.",
"walkawayTest": {
"passed": false,
"reason": "Withdrawals and refunds require a live enclave running the approved image published by Aztec Labs. Running one requires AWS Nitro infrastructure. Both released wallets also depend on zk.money services, so independent operation requires a modified desktop build."
"reason": "Withdrawals and refunds need a live enclave running the approved image on AWS Nitro. The released wallets also depend on zk.money services, so independent operation needs a modified desktop build."
}
},
"relayerTracking": {
"type": "onchainEvents",
"sources": [
{
"address": "eth:0xdf410ad448A0f7165181FBdB32f8896f4a0d9449",
"sinceTimestamp": 1790298635,
"extractor": "zkMoneyWithdrawalRelayer",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"executorAddress": "0xC2363b7155EE8391C5395B72C46a6d22BF49151c",
"operationExecutor": "0xe883686d9EC4E0430f2233A6BF12B2D226a39e19"
}
}
]
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The contract, desktop wallet, enclave and circuit sources are public. The deployed refund and resolver verifiers match the published circuits. The approved enclave binary has not been reproduced. The resolver service, frozen-chain snapshot service and hosted wallet release source are unpublished. Verification instructions cover the refund and resolver circuits and the Aztec token pinned by the Ethereum portal."
"description": "The contract, desktop wallet, enclave and circuit sources are public. The deployed refund and resolver verifiers match the published circuits. The approved enclave binary remains unreproduced. The resolver service, frozen-chain snapshot service and hosted wallet release source are unpublished. Verification instructions cover the refund and resolver circuits and the Aztec token pinned by the Ethereum portal."
},
"riskSummary": "## Funds can be stolen if\n\n1. Aztec's private execution or refund proof is unsound and the enclave layer also fails.\n2. malicious wallet code obtains a harmful signature, or substituted unsigned contract lists redirect future deposits and payments.\n3. the NameRegistry owner or owner of zk.money in ENS redirects future payments to names.\n\n
\n\n## Funds can be lost if\n\n1. a user loses their passkey.\n2. no AWS-attested enclave is running.\n3. resolver screening blocks an external payment. Funds remain recoverable, but the recipient needs their own tooling to re-derive the unannounced deposit address.\n\n
\n\n## Privacy can be lost if\n\n1. a user pays a new contact. The handshake reveals the recipient's Aztec address, publicly linked to their name. The first sponsored transaction after registration also reveals the sender's account.\n2. an enclave or AWS Nitro attestation is compromised.\n3. the resolver operator re-derives deposit addresses and links deposits to recipients.\n4. public deposits, withdrawals, registration and deposit-address reuse allow amount or timing correlation.\n5. an external Aztec RPC learns the account from note requests, or zk.money and Predicate correlate screened addresses by IP.\n6. someone reads keys and decrypted notes stored unencrypted on the device.\n7. a freeze forces refunds, which expose note and deposit amounts on Ethereum and use proofs without zero knowledge.\n8. a quantum computer breaks the elliptic-curve encryption of notes published to Ethereum.",
"riskSummary": "## Funds can be stolen if\n\n1. Aztec's private execution or refund proof is unsound and the enclave layer also fails.\n2. malicious wallet code obtains a harmful signature, or substituted unsigned contract lists redirect future deposits and payments.\n3. the NameRegistry owner or owner of zk.money in ENS redirects future payments to names.\n\n
\n\n## Funds can be lost if\n\n1. a user loses their passkey.\n2. every AWS-attested enclave stops running.\n3. resolver screening blocks an external payment and the recipient lacks the tooling to re-derive its deposit address.\n\n
\n\n## Privacy can be lost if\n\n1. a user pays a new contact, which reveals the recipient, or makes their first sponsored transaction after registration, which is tied to their account (see public observer).\n2. the resolver operator derives the wallets' deposit addresses and links L1 deposits to L2 recipients (see privileged insider).\n3. an enclave or AWS Nitro is compromised (see privileged insider).\n4. the portal freezes and users exit through refunds, which publish note or deposit amounts on Ethereum.\n5. a quantum computer breaks the elliptic-curve encryption of data published to Ethereum (see future adversary).",
"tokens": [
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1790298635
},
"buckets": [
{
"id": "zkmoney-DAI",
"type": "pool",
"label": "DAI",
"address": "eth:0xdf410ad448A0f7165181FBdB32f8896f4a0d9449",
"sinceTimestamp": 1790298635,
"anonymitySet": {
"minimumAmounts": [
"200000000000000000000"
]
},
"deposit": {
"event": "0x8154af7b1b360f500640de68c82af19c52c4ad4189d7a7c7a41506e19a1fdd6c",
"extractor": "zkMoneyDeposit",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"fundingCut": "100000000000000000",
"factoryAddress": "0xc357E34D4C7520a83C9Ec0a242Ba52b4ecABa1Fc",
"depositImplementation": "0xF714D8Cf287F4A410b018514074A9371BC45461b",
"registrationImplementation": "0x0934F010d59b552949DBe44AcBE5AFf0e32C8C34",
"fundingTokens": [
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"0xdAC17F958D2ee523a2206206994597C13D831ec7"
],
"exchangeAddress": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
"historyFromBlock": 26051085
}
},
"withdrawal": {
"event": "0x0ef2e2e9f18042ca214d1bee833209f28326ffa8f4a6b0dc92172caf71bc5433",
"extractor": "zkMoneyWithdrawal",
"params": {}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "### Immutable escrow and accounts\n\nThe portal, Aztec token, fee-paying contract, verifiers, withdrawal executors and current SIPA implementations cannot be upgraded.\n\nThe approved enclave image is fixed. Anyone can permanently register a signer with an AWS Nitro attestation at most 1 hour old. 2 signers are registered. A withdrawal or refund needs only one of them, alongside its proof. Registrations do not expire and cannot be revoked.\n\nIf Aztec governance changes the canonical rollup, anyone can permanently freeze the portal. Deposits stop and refundable ownership is fixed at the last proven checkpoint. Later L2 transfers do not change it. Withdrawals and refunds still require a live enclave.\n\n### Name administration\n\nTwo Aztec Labs EOAs control *.zk.money names:\n\n- The deployer owns the NameRegistry and can replace its RegistrationController, AccountMetadataRegistry and Resolver, allowing it to reassign names, rewrite records and redirect future payments. It also owns zk.money in ENS, which the DNS domain holder can reclaim.\n- The domain owner can refuse name claims, sign custom registration fees and add fee beneficiaries. Users select a beneficiary from the allowlist in their signed registration intent. Existing beneficiaries cannot be removed.\n\n### Wallet and services\n\nAztec Labs controls hosted wallet code, desktop releases and two unsigned contract lists consumed by both wallets. These are security dependencies: wallet code handles keys and signatures, and the lists determine where future funds go. The wallet checks the [profile](https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/config-client/src/toContractServiceConfig.ts#L41-L68) and [manifest](https://github.com/aztec-labs-eng/zkmoney-public/blob/fc37a3e25440bc4bd7a9de81a7f4830ec753a4d4/packages/core/src/oxide/index.ts#L108-L170) for consistency, but both come from Aztec Labs. A local build with custom nodes still trusts those lists until their addresses are independently verified and pinned.\n\nThe relayer, resolver, claim server, enclave hosts and passkey domain also control availability and censorship. Self-submission bypasses the relayer, but exits still need an enclave and the released wallets still depend on zk.money services."
"content": "The core smart contracts of Aztec Network and zk.money are immutable.\n\n### Enclave signers and freeze\n\nAnyone can permanently register an enclave signer with an AWS Nitro attestation up to 1 hour old, and 2 are registered. If Aztec governance changes its canonical rollup, anyone can freeze the portal for good, which stops deposits and enables refunds at the last proven checkpoint.\n\n### Names and services\n\nTwo Aztec Labs EOAs control *.zk.money names. The deployer owns the NameRegistry and can replace its registration, metadata and resolver contracts, which lets it reassign names and redirect future payments. It also owns zk.money in ENS, which the DNS holder can reclaim. The domain owner can refuse claims, sign custom fees and add permanent fee beneficiaries, which users pick from in their registration intent. Aztec Labs also controls the hosted wallet, the desktop releases and the two unsigned contract lists both wallets currently use."
},
"zkCatalogId": "barretenberg"
}