319981bf (main)
and
ae883e46 (PR)
+12 -7
+12 -7
{
"adversaries": {
"promise": {
"protects": "recipient",
"text": "Hides which account a receiving address belongs to. The payer knows the address it was given; sender, asset, amount and where the funds go next are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "A fresh receiving address has no public derivation linking it to the recipient account, but its funds can be followed through later sends and change outputs. Combining addresses exposes their joint use, and EIP-7702 delegation reveals the account implementation without proving who owns the address.",
"exposureShort": "A fresh receiving address has no public derivation linking it to the recipient account, but its funds can be followed through later sends and change outputs.",
"exposureContinued": "Combining addresses exposes their joint use, and EIP-7702 delegation reveals the account implementation without proving who owns the address.",
"advice": "Generate a fresh address for each receive, spend address-held balances separately with Advanced Control, and send to destinations with no public link to you.",
"sources": [
{
"title": "Address derivation from server-held ephemeral material",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/shared/genStealthAddress.ts#L17-L58"
},
{
"title": "Input selection, visible change and EIP-7702 execution",
"url": "https://clkd.xyz/docs/how-it-works#sending-funds"
},
{
"title": "Quote API: spendableAddresses and reusable singleAddress mode",
"url": "https://clkd.xyz/openapi.json"
}
],
"id": "publicObserver",
"value": "Recipient private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "Spending through shared execution infrastructure makes service use recognizable, which narrows the anonymity set to Cloaked users. No registry or announcement maps accounts to addresses, but timing, distinctive amounts, recurring counterparties and consolidation can identify or cluster recipients. A send draws from several addresses by default and leaves a change output that links them.",
"exposureShort": "Spending through shared execution infrastructure makes service use recognizable, which narrows the anonymity set to Cloaked users.",
"exposureContinued": "Timing, distinctive amounts, recurring counterparties and consolidation can identify or cluster recipients. A send draws from several addresses by default and leaves a change output that links them.",
"advice": "Space out related payments and check whether amounts or recurring patterns identify you. Follow your own change outputs to see what a counterparty can trace.",
"sources": [
{
"title": "Documented transaction links and change handling",
"url": "https://clkd.xyz/docs/how-it-works#what-is-visible-onchain"
},
{
"title": "Deterministic ephemeral keys stay offchain",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/shared/deriveDeterministicEphemeralKey.ts#L35-L68"
},
{
"title": "API permits repeated use; receive-once/spend-once is not enforced",
"url": "https://clkd.xyz/openapi.json"
}
],
"id": "chainAnalyst",
"value": "Recipient at risk",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "warning",
"exposure": "Every spend from the hosted client goes to a third-party relay, Porto, with the stealth address, destination and amount, which clusters your addresses per session even over Tor. The client is closed source, so what else reaches the RPC, hosting and analytics providers named in the privacy policy cannot be verified. Only the recovery tool runs without any server.",
"sentiment": "bad",
"exposureShort": "Every spend from the hosted client goes to a third-party relay, with the stealth address, destination and amount.",
"exposureContinued": "The client is closed source, so what else reaches the RPC, hosting and analytics providers named in the privacy policy cannot be verified.",
"advice": "Derive your address keys with the recovery tool, which makes no network calls, and spend them from a wallet on your own node over Tor. Fund gas for token transfers from a fresh wallet, since sponsored execution is only available through the hosted client.",
"sources": [
{
"title": "Client sends prepareCalls with address, recipient and amount to Porto RPC",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/README.md#architecture"
},
{
"contract": "OffchainResolver",
"title": "CCIP-Read forwards the ENS query and verifies the returned answer"
},
{
"title": "Disclosed metadata, relay data and external service providers",
"url": "https://clkd.xyz/docs/privacy"
},
{
"title": "Recovery derives address keys locally without API calls",
"url": "https://github.com/cloakedxyz/clkd-recovery/blob/b432a33873e2cfa4769807f8c95ed20a67234eed/src/lib/deriveKeys.ts#L31-L68"
},
{
"title": "Recovered keys are spent from any wallet; token sends need gas",
"url": "https://github.com/cloakedxyz/clkd-recovery/blob/b432a33873e2cfa4769807f8c95ed20a67234eed/src/components/PostRecoveryGuide.tsx#L81-L106"
}
],
"id": "networkObserver",
"value": "Recipient at risk",
"value": "Recipient exposed",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "Cloaked holds the viewing key, so it can regenerate every address and tie its activity to your account. Its Incognito relay states that it retains deposit-to-withdrawal associations, and the hosted wallet code handles your spending secrets.",
"exposureShort": "Cloaked holds the viewing key, so it can regenerate every address and tie its activity to your account.",
"exposureContinued": "Its Incognito relay states that it retains deposit-to-withdrawal associations, and the hosted wallet code handles your spending secrets.",
"advice": "Verify address derivations and transactions with an inspected local client. This protects your spending keys but does not remove Cloaked's view.",
"sources": [
{
"title": "Viewing key and public spending key shared with the server",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/client/deriveServerBoundKeys.ts#L16-L53"
},
{
"title": "Account-scoped addresses, quotes, submissions and pool state",
"url": "https://clkd.xyz/openapi.json"
},
{
"title": "Privacy policy: retained pool associations and account data",
"url": "https://clkd.xyz/docs/privacy"
},
{
"contract": "OffchainResolver",
"title": "Signature and expiry checks do not prove recipient control"
},
{
"section": "permissions",
"title": "Owner can replace gateway and signer"
},
{
"section": "upgrades-and-governance",
"title": "Hosted-client trust boundary"
}
],
"id": "privilegedInsider",
"value": "Recipient exposed",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "No announcement is published, so a quantum computer cannot replay address derivations from the chain alone. The viewing key held by Cloaked exposes the history regardless. Accounts created from a wallet signature reduce to that wallet's key plus a four-digit PIN. Passkey PRF secrets do not follow from breaking the passkey.",
"exposureShort": "No announcement is published, so a quantum computer cannot replay address derivations from the chain alone.",
"exposureContinued": "The viewing key held by Cloaked exposes the history regardless. Accounts created from a wallet signature reduce to that wallet's key plus a four-digit PIN. Passkey PRF secrets do not follow from breaking the passkey.",
"advice": "Create your account with the passkey PRF setup, not from a wallet signature. Treat the address history shared with Cloaked as permanently disclosed.",
"sources": [
{
"title": "Stealth signing keys mix the spending key with a hashed secret",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/client/genStealthPrivateKey.ts#L17-L34"
},
{
"title": "Four-digit PIN and wallet address determine the signed message",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/client/genCloakedMessage.ts#L15-L48"
},
{
"title": "Signature components are hashed into the account keys",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/client/genKeysFromSignature.ts#L23-L42"
},
{
"title": "Independent secrets, including two WebAuthn PRF outputs",
"url": "https://github.com/cloakedxyz/clkd-stealth/blob/9eb359efdd4ea31f5504bf81e57dcfe6f966dc14/src/client/genKeys.ts#L7-L67"
},
{
"title": "FIDO hmac-secret uses a separate random credential secret",
"url": "https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-hmac-secret-extension"
},
{
"title": "Operator data and retention",
"url": "https://clkd.xyz/docs/privacy"
}
],
"id": "futureAdversary",
"value": "Recipient at risk",
"alsoExposed": []
}
}
},
"anonymitySet": {
"type": "not-applicable",
"description": "Cloaked sends funds to one-time stealth addresses instead of mixing deposits in a shared pool."
},
"attributes": [
{
"id": "stealthAddresses",
"label": "Stealth addresses",
"description": "Uses fresh, one-time recipient addresses to obscure who controls the receiving address."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
}
],
"category": {
"id": "stealthAddress",
"label": "Stealth address",
"description": "Payments land on fresh one-time addresses. Hides which recipient a payment is for."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "Under the documented key model, existing stealth balances are held in user-controlled EOAs and can be recovered with the published client-side recovery tool. The hosted service cannot spend them without obtaining client-side key material.",
"walkawayTest": {
"passed": false,
"reason": "New payment-address generation, ENS resolution, address indexing, transaction construction, and relaying depend on the hosted Cloaked service."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The production web wallet is closed source and cannot be self-hosted. The published derivation code and API schema can nevertheless be used to build a local client that creates an account, derives keys, and signs and submits payments through the hosted API. The backend implementations of the API, ENS gateway, indexer, and relay service are not published, so the complete service cannot be reproduced."
},
"riskSummary": "## Funds can be stolen if\n1. a user relies on the hosted wallet and it is malicious or compromised and exfiltrates derived spending keys. The production wallet is closed source and has no published reproducible build, so users cannot inspect its source or verify the code being served.\n2. the accepted ENS signer returns an attacker-controlled payment address for a Cloaked name. The resolver authenticates the answer but does not prove that the intended recipient controls it.\n
\n## Funds can be lost if\n1. a user loses the passkey and encrypted backup, or the wallet and PIN, needed to re-derive their private spending keys.\n2. the service and client derive different address data and a payment is sent to an address for which the user cannot recreate the private key.\n
\n## Privacy can be lost if\n1. Cloaked, or an attacker who obtains its viewing data, uses the service's viewing capability and index to link an account's stealth addresses and onchain activity.\n2. spending from several stealth addresses together, reusing destinations, or recognizable timing and amounts links otherwise separate payments onchain.\n3. a user relies on the Incognito balance, because Cloaked's relay observes the association between Privacy Pools deposits and withdrawals even though it is hidden from public onchain observers.",
"tokens": [],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Cloaked has no public onchain governance process for its hosted wallet, API, indexer, ENS gateway, or relay. These components can change without an onchain notice period. The production wallet is closed source and has no published reproducible build, so users who rely on it cannot inspect its source, verify which client code is deployed, or determine whether an update preserves the client-side spending-key boundary. Users can bypass the hosted frontend with an inspected local client, but this does not reproduce the other hosted components or prevent them from changing.\n\nThe deployed ENS `OffchainResolver` code is immutable, but its owner can immediately replace the gateway URLs and accepted signer or transfer ownership. The accepted signer can authenticate any offchain ENS answer, including a payment address. The resolver callback verifies only the signature and expiry; it does not verify stealth-address derivation or recipient control. The resolver owner and signer are currently the same EOA.\n\nThese powers affect new address generation and ENS lookups. They do not let the owner or signer spend from an existing, correctly derived stealth address because its private spending key remains with the user. Existing balances can be recovered independently with the published recovery client, but the full Cloaked experience does not remain available if the hosted service disappears."
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "recipient",
"text": "Hides which account a receiving Safe belongs to. The payer knows the address it was given; sender, asset, amount and where the funds go next are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "A payment reaches a predicted Safe before it is deployed, with no onchain announcement linking it to the recipient account. Deployment later exposes the individual stealth owner and enabled modules, not the parent account.",
"exposureShort": "A payment reaches a predicted Safe before it is deployed, with no onchain data linking it to the recipient account.",
"exposureContinued": "Deployment later exposes the individual stealth signer (private signer controlling the safe) and enabled modules, not the parent account.",
"advice": "Generate a fresh address for each receive, keep unrelated funds separate with labels, and send to destinations with no public link to you.",
"sources": [
{
"title": "Counterfactual receiving Safe and individual stealth signer",
"url": "https://docs.fluidkey.com/technical-documentation/technical-walkthrough/#3-stealth-accounts"
},
{
"title": "Safe owner and initialization data determine the address",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/predictStealthSafeAddress.ts#L32-L104"
},
{
"contract": "FluidkeyEarnModule",
"title": "AutoEarnExecuted exposes Safe, token and deposited amount"
},
{
"title": "Labels restrict which balances fund a send",
"url": "https://docs.fluidkey.com/readme/labels/"
}
],
"id": "publicObserver",
"value": "Recipient private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "Safe deployment and auto-earn events make service use recognizable, which narrows the anonymity set to Fluidkey users. Nothing onchain maps Safes to accounts, but timing, amounts, common destinations and reuse across chains can identify or cluster recipients, and a send draws from several Safes by default, which links them. The optional Hide Trail routes through Houdini and two exchanges, a separate service with its own trust assumptions.",
"exposureShort": "Safe deployment and auto-earn events make service use recognizable, which narrows the anonymity set to Fluidkey users.",
"exposureContinued": "Nothing onchain maps Safes to accounts, but timing, amounts, common destinations and reuse across chains can identify or cluster recipients, and a send draws from several Safes by default, which links them. The optional Hide Trail routes through Houdini and two exchanges, a separate service with its own trust assumptions.",
"advice": "Label payments so a send draws from one Safe. Check related activity across chains and space out distinctive payments.",
"sources": [
{
"title": "onInstall records its caller; an event alone is not proof of a Fluidkey user",
"url": "https://github.com/fluidkey/fluidkey-earn-module/blob/122cde19940d06b94c0027f4cd2e22e7fa19129a/src/FluidkeyEarnModule.sol#L243-L260"
},
{
"title": "Different auto-earn versions use different initialization data",
"url": "https://docs.fluidkey.com/technical-documentation/stealth-account-initdata/"
},
{
"title": "Shared derivation path permits the same addresses across chains",
"url": "https://docs.fluidkey.com/technical-documentation/technical-walkthrough/#3a-stealth-signer-derivation"
},
{
"title": "Hide Trail integration",
"url": "https://docs.fluidkey.com/readme/advanced-privacy/"
}
],
"id": "chainAnalyst",
"value": "Recipient at risk",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "warning",
"exposure": "The hosted client is closed source, so which RPC and analytics providers see your Safe list cannot be verified. Paying to your fkey.id name hands the name and the fresh address to whoever resolves ENS for the payer, often the payer's RPC provider. Only the open kit and the recovery app can be pointed at your own node.",
"exposureShort": "The hosted client is closed source, so which RPC and analytics providers see your Safe list cannot be verified.",
"exposureContinued": "Paying to your fkey.id name hands the name and the fresh address to whoever resolves ENS for the payer, often the payer's RPC provider. Only the open kit and the recovery app can be pointed at your own node.",
"advice": "Derive addresses with the kit and hand them to payers directly instead of the ENS name. Read balances with the recovery app on your own RPC, and deploy and spend from a fresh gas wallet, since the recovery app deploys Safes from the connected wallet.",
"sources": [
{
"contract": "OffchainResolver",
"title": "Offchain ENS gateway"
},
{
"title": "Local CREATE2 prediction needs no RPC",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/predictStealthSafeAddress.ts#L120-L180"
},
{
"title": "Recovery app accepts a custom RPC",
"url": "https://github.com/fluidkey/sara/blob/6ab939e176cbae60a33214d292070d6a1dfe9b30/src/components/RecoverAddressesJourneyStep.tsx#L468"
},
{
"title": "Recovery app deploys the Safe from the connected wallet",
"url": "https://github.com/fluidkey/sara/blob/6ab939e176cbae60a33214d292070d6a1dfe9b30/src/hooks/useDeployStealthSafe.ts#L63-L99"
},
{
"title": "Disclosed service providers and transport encryption",
"url": "https://www.fluidkey.com/privacy"
}
],
"id": "networkObserver",
"value": "Recipient at risk",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "Fluidkey holds the viewing key, so it can regenerate every address and tie its activity to your account. Optional identity-verified services add identity attributes, and Hide Trail adds route knowledge at Houdini and each exchange.",
"exposureShort": "Fluidkey holds the viewing key, so it can regenerate every address and tie its activity to your account.",
"exposureContinued": "Optional identity-verified services add identity attributes, and Hide Trail adds route knowledge at Houdini and each exchange.",
"advice": "Verify address derivations and transactions with an inspected local client. This protects your spending keys but does not remove Fluidkey's view.",
"sources": [
{
"title": "Private viewing key shared with the service",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/extractViewingPrivateKeyNode.ts#L14-L30"
},
{
"title": "Ephemeral key plus public spending key generates each signer",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/generateStealthAddresses.ts#L14-L49"
},
{
"contract": "OffchainResolver",
"title": "ENS signature authenticates the service, not recipient control"
},
{
"section": "permissions"
},
{
"section": "upgrades-and-governance",
"title": "Hosted-client trust boundary"
},
{
"title": "Optional verification results and identity attributes",
"url": "https://www.fluidkey.com/privacy"
},
{
"title": "Hide Trail and its exchange intermediaries",
"url": "https://docs.fluidkey.com/readme/advanced-privacy/"
}
],
"id": "privilegedInsider",
"value": "Recipient exposed",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "No announcement is published, so a quantum computer cannot replay address derivations from the chain alone. The viewing key held by Fluidkey exposes the history regardless. Accounts created from a wallet signature reduce to that wallet's key plus a four-digit PIN.",
"exposureShort": "No announcement is published, so a quantum computer cannot replay address derivations from the chain alone.",
"exposureContinued": "The viewing key held by Fluidkey exposes the history regardless. Accounts created from a wallet signature reduce to that wallet's key plus a four-digit PIN.",
"advice": "Create your account with independently generated keys, not from a wallet signature. Treat the viewing key shared with Fluidkey as permanently disclosed.",
"sources": [
{
"title": "Stealth signer depends on a hashed shared secret",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/generateStealthPrivateKey.ts#L11-L21"
},
{
"title": "Signature halves generate the viewing and spending keys",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/generateKeysFromSignature.ts#L11-L36"
},
{
"title": "Wallet address and PIN determine the key-generation message",
"url": "https://github.com/fluidkey/fluidkey-stealth-account-kit/blob/2a4ccfafef127165c11ba16fc16235c919698ec2/src/utils/generateFluidkeyMessage.ts#L10-L32"
},
{
"title": "Recovery supports a four-digit PIN, defaulting to 0000",
"url": "https://github.com/fluidkey/sara/blob/6ab939e176cbae60a33214d292070d6a1dfe9b30/src/components/GenerateKeysJourneyStep.tsx#L28-L90"
},
{
"title": "Distinct web embedded-wallet and mobile device-key setups",
"url": "https://docs.fluidkey.com/readme/account-set-up/"
},
{
"title": "Operator data retention",
"url": "https://www.fluidkey.com/privacy"
}
],
"id": "futureAdversary",
"value": "Recipient at risk",
"alsoExposed": []
}
}
},
"anonymitySet": {
"type": "not-applicable",
"description": "Fluidkey sends funds to individual stealth Safes instead of mixing deposits in a shared pool."
},
"attributes": [
{
"id": "stealthAddresses",
"label": "Stealth addresses",
"description": "Uses fresh, one-time recipient addresses to obscure who controls the receiving address."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
},
{
"id": "defi",
"label": "DeFi",
"description": "Interop with DeFi vaults through stealth Safes."
}
],
"category": {
"id": "stealthAddress",
"label": "Stealth address",
"description": "Payments land on fresh one-time addresses. Hides which recipient a payment is for."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "Under the documented key model, existing stealth balances are held in user-controlled Safes and can be recovered with the published client-side recovery tool and original Safe initialization parameters. Auto-earn positions remain subject to the withdrawal conditions and risks of their underlying vaults.",
"walkawayTest": {
"passed": false,
"reason": "New payment-address generation through the app and ENS, address indexing, transaction construction, and relaying depend on the hosted Fluidkey service."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The production web wallet is closed source and cannot be self-hosted. The published derivation code and recovery client can nevertheless be used to derive keys, verify service-generated receiving addresses, and recover funds independently. A local client can also register and authenticate through the hosted API. The backend implementations of the API, ENS gateway, indexer, and relay service are not published, so the complete service cannot be reproduced."
},
"riskSummary": "## Funds can be stolen if\n1. a user relies on the hosted wallet and it is malicious or compromised and exfiltrates derived spending keys. The production wallet is closed source and has no published reproducible build, so users cannot inspect its source or verify the code being served.\n2. an accepted ENS signer returns an attacker-controlled payment address for a Fluidkey name. The resolver authenticates the answer but does not prove that the intended recipient controls it.\n3. the hosted service supplies malicious transaction data and the client signs it without independently checking the destination, amount, and calls being authorized.\n
\n## Funds can be lost if\n1. a user loses the wallet, PIN, login, or backup needed to recover their private spending keys.\n2. the service and client derive different address data or Safe initialization parameters and a payment is sent to an address that the user cannot recover.\n3. an auto-earn vault loses funds or cannot honor withdrawals, or a service used by Hide Trail fails to return the funds routed through it.\n
\n## Privacy can be lost if\n1. Fluidkey, or an attacker who obtains its viewing data, uses the service's viewing capability and index to link an account's stealth addresses and onchain activity.\n2. spending from several stealth addresses together, reusing destinations, or recognizable timing and amounts links otherwise separate payments onchain.\n3. a user relies on Hide Trail and the swap service or participating exchanges use their transfer records to link activity that is obscured from public onchain observers.",
"tokens": [],
"trackedOn": [
"ethereum",
"base",
"arbitrum",
"optimism",
"polygonpos",
"gnosis"
],
"upgradesAndGovernance": {
"content": "Fluidkey has no public onchain governance process for its hosted wallet, API, indexer, ENS gateway, or relay. These components can change without an onchain notice period. The production wallet is closed source and has no published reproducible build, so users who rely on it cannot inspect its source, verify which client code is deployed, or determine whether an update preserves the client-side spending-key boundary. Users can bypass the hosted frontend with an inspected local client, but this does not reproduce the other hosted components or prevent them from changing.\n\nThe deployed ENS `OffchainResolver` code is immutable, but its owner can immediately replace the gateway URL, add or remove accepted signers, or transfer ownership. An accepted signer can authenticate any offchain ENS answer, including a payment address. The resolver callback verifies only the signature and expiry. It does not verify stealth-address derivation or recipient control. The resolver is owned by a 3/5 Safe.\n\nThese powers affect new address generation and ENS lookups. They do not let the resolver owner or signers spend from an existing, correctly derived stealth Safe because its private owner key remains with the user. Existing balances can be recovered independently with the published recovery client and the original Safe initialization parameters, but the full Fluidkey experience does not remain available if the hosted service disappears.\n\nThe Fluidkey Earn module is separate from the resolver and has immutable code. Its owner is a 2/3 Safe on each tracked chain. Its owner can publish new vault configurations and manage authorized relayers. Relayers can initiate deposits into a Safe's selected configuration and add or remove relayers. Each configuration is identified by a hash of its contents, so adopting a different vault set requires a call from the Safe. Users can disable the module through their Safe. The governance and withdrawal conditions of the underlying vaults remain separate dependencies."
}
}
+8 -5
+8 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides which funds leaving Ethereum come back as which, by passing them through Monero between two custodial swaps. Both Ethereum legs are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Nothing public ties the deposit into a swap service to the later payout from a service hot wallet, because the Monero transactions in between hide sender, recipient and amount. Both Ethereum transfers show address, token and amount.",
"exposureShort": "Nothing public ties the deposit into a swap service to the later payout from a service hot wallet, because the Monero transactions in between hide sender, recipient and amount.",
"exposureContinued": "Both Ethereum transfers show address, token and amount.",
"advice": "Exit to a new in-app Ethereum wallet created from a fresh seed, never the wallet that deposited.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": {
"verdict": "exposed",
"note": "Only XMR exists inside. The source asset is public on Ethereum."
},
"linkage": {
"verdict": "atRisk",
"note": "An EVM wallet in Cake has one address, so exiting to the wallet that deposited pays the address that deposited."
}
},
"sources": [
{
"title": "The deposit is a plain transfer from the wallet to the address the service returned",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/lib/view_model/exchange/exchange_trade_view_model.dart#L200-L206"
},
{
"title": "An EVM wallet has a single address",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/cw_evm/lib/evm_chain_wallet_addresses.dart#L11-L38"
},
{
"title": "Every input names 16 ring members",
"url": "https://github.com/monero-project/monero/blob/v0.18.5.1/src/cryptonote_core/blockchain.cpp#L3268"
},
{
"title": "Amounts are encrypted to the recipient",
"url": "https://github.com/monero-project/monero/blob/v0.18.5.1/src/ringct/rctOps.cpp#L672-L720"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "Only amount and timing can pair the two Ethereum legs: a deposit into a swap service and a payout from a hot wallet that serves every asset the service trades.",
"exposureShort": "Only amount and timing can pair the two Ethereum legs: a deposit into a swap service and a payout from a hot wallet that serves every asset the service trades.",
"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": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "A round trip of similar amount and timing pairs the two Ethereum legs."
}
},
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "bad",
"exposure": "With Tor and own nodes, the two legs stay apart unless they run in the same app/tor session. Cake's Tor has one SOCKS port without isolation, so Moralis, which cannot be switched off, and Blink and Etherscan, if left on, can see both Ethereum wallets on one circuit.",
"exposureShort": "Cake's Tor config does not support isolation, so Moralis, which cannot be switched off, and Blink and Etherscan, if left on, can see both Ethereum wallets on one IP.",
"advice": "Turn on Tor, switch off Blink and Etherscan, set your own Monero node and Ethereum RPC, then restart the app, since the Ethereum client keeps its first connection. Wait and restart it again between the legs.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "Ethereum wallets opened in one session share a Tor circuit toward Moralis."
}
},
"sources": [
{
"title": "Built-in Tor is off unless the user enables it",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/lib/store/settings_store.dart#L1561"
},
{
"title": "Embedded Tor config: one SocksPort, no isolation flags, no control port",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/cw_core/lib/utils/tor/torch.dart#L65-L70"
},
{
"title": "The Ethereum client binds its proxy setting once",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/cw_evm/lib/clients/evm_chain_client.dart#L24"
},
{
"title": "Every wallet switch sends the address to Moralis, gated only by the API key",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/cw_evm/lib/clients/evm_chain_client.dart#L615-L640"
},
{
"title": "Blink and Etherscan toggles under Connections",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/lib/src/screens/settings/connection_sync_page.dart#L64-L79"
}
],
"id": "networkObserver",
"value": "Link exposed",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "The swap-in service that pays your XMR knows that output, and the service you exit with sees the rings of your Monero transaction. One party holding both finds its output in the rings behind the exit. Each service also holds the addresses, amounts, IP and Cake's API key of its leg, screens them and can hold the funds until KYC.",
"exposureShort": "The swap-in service that pays your XMR knows that Monero output, and the service you exit with sees the rings of your Monero transaction.",
"exposureContinued": "One party holding both finds its known output in the rings behind the exit. Each service also holds the addresses, amounts, IP and Cake's API key of its leg, screens them and can hold the funds until KYC.",
"advice": "Force different services for entry and exit. Self-transfer the XMR several times, hours to days apart, and never pay the exit service the whole amount.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Rings that reference the service's payout output point to the spend of your XMR."
},
"recipient": "private",
"amount": "private",
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "Private only if no party holds the records of both legs."
}
},
"sources": [
{
"title": "Breaking Monero: poisoned outputs, the attack by a counterparty on both sides",
"url": "https://www.monerooutreach.org/breaking-monero/poisoned-outputs.html"
},
{
"title": "The user can force a provider, otherwise the best rate wins",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/lib/view_model/exchange/exchange_view_model.dart#L596-L603"
},
{
"title": "Trocador is asked for partners of KYC grade C or better and both addresses are forwarded",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/lib/exchange/provider/trocador_exchange_provider.dart#L226-L240"
},
{
"title": "Cake ships its API key with the providers",
"url": "https://github.com/cake-tech/cake_wallet/blob/b7247dd0969d9004e49ce592b855cff2c7706fd6/tool/utils/secret_key.dart#L15-L106"
},
{
"title": "ChangeNOW: automated AML holds, KYC through SumSub, refund minus fees",
"url": "https://changenow.io/faq/kyc-aml"
},
{
"section": "upgrades-and-governance"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "A quantum computer recovers the key of every ring member from the chain alone, recomputes its key image and so finds the real spend of every ring, which turns the XMR's path from payout to exit into a public trail. The services' records of payout and deposit then join the Ethereum legs.",
"exposureShort": "A quantum computer recovers the key of every ring member from public chain data, recomputes its key image and can link every transaction.",
"exposureContinued": "The services' records of payout and deposit then join the Ethereum legs.",
"interior": {
"sender": "exposed",
"recipient": {
"verdict": "atRisk",
"note": "Readable for every output to an address the attacker knows, as the services know yours."
},
"amount": {
"verdict": "atRisk",
"note": "Readable for every output to an address the attacker knows."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "A key image is the output key hashed to a point times its private key",
"url": "https://github.com/monero-project/monero/blob/v0.18.5.1/src/crypto/crypto.cpp#L621-L628"
},
{
"title": "Zero to Monero: one-time addresses, amount encryption and key images (chapters 4 to 6)",
"url": "https://www.getmonero.org/library/Zero-to-Monero-2-0-0.pdf"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "recipient",
"exposure": "atRisk"
},
{
"field": "amount",
"exposure": "atRisk"
}
]
}
}
},
"anonymitySet": {
"type": "not-applicable",
"description": "Each Monero spend hides among 16 ring members, not among all outputs. A party that knows the entry output looks for it in the rings behind the exit, so against the swap services the set is small. Entry and exit amounts are public on Ethereum."
},
"attributes": [
{
"id": "bridged",
"label": "Bridged",
"description": "Funds leave Ethereum through a bridge and gain their privacy on another chain."
},
{
"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": "None",
"sentiment": "bad",
"orderHint": 0,
"description": "No contract and no delay. The swap service can hold funds in transit. Cake can change providers with an update.",
"walkawayTest": {
"passed": false,
"reason": "Deposit and payout both depend on the swap service. If it stops, funds in transit are lost or refunded at its discretion."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "Cake wallet and Monero are open source. Every service that swaps Monero is a closed exchange."
},
"riskSummary": "## Funds can be stolen if\n1. a swap service does not pay out.\n2. a service's hot wallet is compromised during the trade.\n
\n## Funds can be frozen if\n1. a service holds the deposit pending identity verification.\n2. a service refunds minus fees and blacklists the deposit address.\n
\n## Privacy can be lost if\n1. one party sees both legs: one service, Trocador or a vendor the services share. It finds its own payout output in the rings behind the exit transaction, and self-transfers in between only widen that search.\n2. the exit is paid to the same Ethereum wallet that deposited, since an EVM wallet in Cake has only one address.\n3. the XMR is swapped back in a matching amount and time.\n4. the same Monero payout address is reused on entry, the default for an in-app receiver.\n5. swap APIs, Blink, Etherscan, Moralis, RPC and Monero node see the same IP. Tor is off by default and not circuit-isolated.\n6. elliptic-curve cryptography is broken, which reveals the real spend in every ring.",
"tokens": [],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "No onchain governance, no contracts, instant change permissions. Three parties can change the swap routes.\n\n### Cake Labs LLC (the wallet)\n\nMIT-licensed and self-custodial. Cake runs no swap backend. Privacy defaults, all user-changeable: Tor off, swap mode \"Enabled\", Blink on, Etherscan on, Cake's price API on, Cake's Monero node, publicnode's Ethereum RPC. Moralis token discovery is always on.\n\n### The swap services (the custodians)\n\nFully centralized, custodial and intransparent.\n\n### Monero (the chain)\n\nRules change through scheduled hard forks. The mainnet table ends at version 16, active since block 2689608 (August 2022) with a ring size of 16."
}
}
+10 -6
+10 -6
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Promises private stablecoin transfers. Delivers hidden amounts and note owners over a public spend graph: which notes fund which, and every deposit and withdrawal, is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "bad",
"exposure": "Every transaction names the notes it spends and creates, so which notes fund which is public by design; only the amount and owner of a note are hidden. Empty padding notes have a zero commitment, so single-input and single-output transactions are recognizable. All blocks and proofs are served openly, and each deposit or withdrawal shows address and amount and points at one node of that graph. The per-transaction proofs use a flavor whose authors document that it is not zero-knowledge; how much of a note it leaks is not established.",
"exposureShort": "Every transaction names the notes it spends and creates, so which notes fund which is public by design; only the amount and owner of a note are hidden.",
"exposureContinued": "Empty padding notes have a zero commitment, so single-input and single-output transactions are recognizable. All blocks and proofs are served openly, and each deposit or withdrawal shows address and amount and points at one node of that graph. The per-transaction proofs use a flavor whose authors document that it is not zero-knowledge; how much of a note it leaks is not established.",
"advice": "Withdraw to an address that cannot be tied to you, and never an amount that matches a deposit.",
"interior": {
"sender": {
"verdict": "private",
"note": "The owner key is hidden; the spent note is a public graph node."
},
"recipient": {
"verdict": "private",
"note": "Recipient and change outputs are indistinguishable."
},
"amount": {
"verdict": "atRisk",
"note": "Protected by a proof flavor documented to leak witness data."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "RollupV1"
},
{
"title": "UTXO circuit: spent and created commitments are public, no nullifier",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/noir/utxo/src/main.nr#L9-L15"
},
{
"title": "Burn hash is the first consumed commitment",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/noir/utxo/src/main.nr#L66-L71"
},
{
"title": "Client proofs use the non-ZK Honk flavor",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/barretenberg-rs/src/binding.rs#L109-L118"
},
{
"title": "Honk docs: the base flavor leaks witness information",
"url": "https://github.com/AztecProtocol/aztec-packages/blob/58bf73a289f7da78c8920c9c73604a8e5d105025/barretenberg/cpp/src/barretenberg/ultra_honk/README.md#zero-knowledge"
},
{
"title": "Public transactions endpoint serves every proof",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/node/src/rpc/routes/configure.rs#L19-L25"
},
{
"title": "Docs describe nullifiers the deployed circuit does not have",
"url": "https://docs.payy.network/protocol/privacy-layer/nullifiers"
}
],
"id": "publicObserver",
"value": "Link exposed",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "bad",
"exposure": "Along a path without splits or merges the public deposit and withdrawal amounts fix every amount in between, and the graph shows who paid whom end to end. Each wallet has one fixed deposit address, so all its deposits link to each other and to whoever funded them.",
"exposureShort": "Along a path without splits or merges the public deposit and withdrawal amounts fix every amount in between, and the graph shows who paid whom end to end.",
"exposureContinued": "Each wallet has one fixed deposit address, so all its deposits link to each other and to whoever funded them.",
"advice": "Keep funds in the network across many transfers; only a split or merge stops amounts from being inferred. Fund the deposit address from a wallet that is not yours to keep.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Nodes are labelled by their terminal deposit and withdrawal addresses."
},
"recipient": "atRisk",
"amount": {
"verdict": "atRisk",
"note": "Inferable along a linear path from a deposit to a withdrawal."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Public block API",
"url": "https://validators.mainnet.payy.network/v0/blocks"
},
{
"title": "One deposit address stored per wallet",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/database/src/schema.rs#L464-L481"
},
{
"title": "Deposit relayed from the deposit address with a signed USDC authorization",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/guild-interface/src/mint.rs#L56-L90"
},
{
"title": "Wallet FAQ: the deposit address forwards to the bridge",
"url": "https://docs.payy.network/payy-wallet/payy-wallet-faq"
}
],
"id": "chainAnalyst",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"exposure": "atRisk"
}
]
},
"networkObserver": {
"sentiment": "bad",
"exposure": "Proofs are built on your device and the app talks only to the operator's servers. The payment-link website is different: it loads a third-party analytics script that records the page URL, which holds the redeem secret of the link, and reports a device fingerprint to the backend.",
"exposureShort": "The payment-link website loads a third-party analytics script that records the page URL, which holds the redeem secret of the link, and reports a device fingerprint to the backend.",
"exposureContinued": "On the other hand, proofs are built on your device and the app talks only to the operator's servers.",
"advice": "Redeem payment links in the app, not in a browser.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": {
"verdict": "atRisk",
"note": "A link opened in a browser hands its redeem secret to the analytics provider."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Analytics with default settings on the link website",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/app/packages/link/src/config/posthog.ts#L10-L18"
},
{
"title": "Send links carry the secret in the URL fragment",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/parse-link/src/lib.rs#L50-L56"
},
{
"title": "Device fingerprint and analytics id posted to the backend",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/app/packages/link/src/hooks/useStoreRedirect.ts#L30-L58"
},
{
"title": "Node logs every submitted proof",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/node/src/rpc/routes/txn.rs#L30-L34"
}
],
"id": "networkObserver",
"value": "Link exposed",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "One company runs the only validator and prover, the node, the note registry, the deposit relayer and the KYC checks. Its backend ties each session to a wallet address and keeps, per wallet, the deposit address, KYC record, country, IP country and the commitment and owner of every note the app reports; its diagnostics table has a field for the recovery phrase. For payment links and fiat ramps it holds the notes' private keys and can read and spend them. It can drop your withdrawals, and its owner can rewrite the state root with no delay.",
"exposureShort": "One company runs the only validator and prover, the node, the note registry, the deposit relayer and the KYC checks.",
"exposureContinued": "Its backend ties each session to a wallet address and keeps, per wallet, the deposit address, KYC record, country, IP country and the commitment and owner of every note the app reports. For payment links and fiat ramps it holds the notes' private keys and can read and spend them. It can drop your withdrawals, and its owner can rewrite the state root with no delay.",
"advice": "Use only ordinary transfers for anything you want to keep private. Links, ramps and the card hand the operator the note keys.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": {
"verdict": "atRisk",
"note": "Hidden for ordinary transfers; the backend holds the keys of link and ramp notes."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "RollupV1",
"title": "setRoot, provers, validators, burn substitutors"
},
{
"section": "permissions"
},
{
"title": "Session bound to a wallet address by signature",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/guild-interface/src/auth.rs#L1-L16"
},
{
"title": "Registry entries are keyed by recipient key and posted authenticated",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/guild-client-http/src/registry.rs#L45-L56"
},
{
"title": "Link and ramp notes are created with their private key on the backend",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/guild-interface/src/notes/create.rs#L36-L45"
},
{
"title": "Wallet table: deposit address, KYC, country, IP country",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/database/src/schema.rs#L464-L481"
},
{
"title": "Wallet notes table: commitment and owner per note",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/database/src/schema.rs#L452-L462"
},
{
"title": "Diagnostics table with a recovery phrase field",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/database/src/schema.rs#L36-L48"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "recipient",
"exposure": "exposed"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "Every per-transaction proof is public forever and not zero-knowledge, so whatever it leaks stays available to future compute, and a discrete-log break opens the commitments inside it. Registry ciphertexts use elliptic-curve key exchange; if the operator retains them, a quantum computer opens every note delivered through it.",
"advice": "Receive notes in person rather than through the registry where the app allows it.",
"exposureShort": "Every per-transaction proof is public forever and not zero-knowledge, so whatever it leaks stays available to future compute, and a discrete-log break opens the commitments inside it.",
"exposureContinued": "Registry ciphertexts use elliptic-curve key exchange. If the operator retains them, a quantum computer opens every note delivered through it.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "If the registry is retained; its ciphertexts are not on Ethereum."
},
"recipient": "atRisk",
"amount": {
"verdict": "atRisk",
"note": "Proofs are public and not zero-knowledge; registry ciphertexts open if retained."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Registry encryption (X25519-XSalsa20-Poly1305)",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/encrypt/src/asymmetric.rs#L80-L81"
},
{
"title": "Client proofs use the non-ZK Honk flavor",
"url": "https://github.com/polybase/payy/blob/2f95947f12981a838f6f0c9dddace825bf835502/pkg/barretenberg-rs/src/binding.rs#L109-L118"
},
{
"title": "Honk docs: ZK flavors add masking the base flavor lacks",
"url": "https://github.com/AztecProtocol/aztec-packages/blob/58bf73a289f7da78c8920c9c73604a8e5d105025/barretenberg/cpp/src/barretenberg/ultra_honk/README.md#zero-knowledge"
},
{
"contract": "HonkVerifier",
"title": "Onchain verifier (ZK flavor)"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"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": "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."
},
"detailedDescription": "Payy is a payments-focused ZK network, designed around private stablecoin transfers. Ethereum receives only state roots and the public deposit and withdrawal messages of each state update. Balances live offchain as UTXO-style notes whose commitments form a sparse Merkle tree maintained by the Payy validators. \n\n### Privacy considerations\n\nTo spend notes, the user's client generates a [Noir](https://noir-lang.org/) `utxo` proof that demonstrates ownership of the input notes and conservation of value; the public inputs of that proof are the commitments of the two notes consumed and the two notes created. Transfers therefore hide who paid whom and how much, but they do not hide which commitments were consumed: the deployed circuits do not use nullifiers, and a spend names its input commitments directly, which the node then marks as spent. Anyone with Payy block data can follow the resulting spend graph.\n\nBecause only commitments are stored in the tree, a recipient cannot reconstruct a received note from chain data alone: the sender must transmit the note contents out of band. In practice it is done by an encrypted registry operated by Payy, which stores the recipient's public key in the clear and serves each client the entries addressed to it. Thus it learns the delivery metadata even though it cannot read note contents. \n\n### Fees\n\nThe protocol charges no transfer or withdrawal fee.\n\n### Compliance\n\nThe deployed protocol enforces no compliance measures and contains no auditor key, view key or other mechanism that could retroactively decrypt past activity. Identity data is collected at the application layer: KYC is required for the Payy card and fiat ramps, but it is not necessary for using Payy L2.\n\n### Anonymity set\n\nPayy hides the contents of each note but not the links between notes, so its anonymity set should not be read as the set of all users. An observer of Payy block data sees a graph of opaque commitments; privacy rests on not knowing which address, asset or amount each node in that graph carries.",
"exitWindow": {
"value": "None",
"sentiment": "bad",
"orderHint": 0,
"description": "The PayyMultisig can instantly upgrade the Rollup contract, replace ZK verifiers and directly overwrite the state root, so users have no time to exit before a malicious change takes effect.",
"walkawayTest": {
"passed": false,
"reason": "Withdrawals must be included in a proven state update by the permissioned Payy operators. There is no mechanism for users to exit on Ethereum if the operators halt."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The sources for UI / wallet are not published, so users have to rely on Payy operated software. Also, DA is not posted to identifiable public source, so L2 state could not be independently reproduced.\n\nThe contracts, Noir circuits and node software are published in the Payy repository (without any license) and can be built and run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the proof system is broken and a malicious validator is registered, allowing forged spends or withdrawals.\n2. the PayyMultisig upgrades the Rollup contract or directly overwrites the state root to a malicious version.\n
\n## Funds can be lost if\n1. a user loses the note data or the keys required to spend their notes.\n2. the offchain transaction data becomes unavailable, as data availability is not verified on Ethereum.\n3. the operators stop including withdrawals in proven state updates, as there is no forced exit mechanism.\n
\n## Privacy can be lost if\n1. the Payy-operated note registry, note lookup or wallet backup services are compromised or their records are disclosed, revealing which addresses receive and hold which notes and who transacted with whom.",
"tokens": [],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "All privileged functions are ultimately controlled by the PayyMultisig (2/4). It owns the ProxyAdmin, which can instantly upgrade the Rollup proxy, and it is the owner of the Rollup contract, allowing it to manage provers, validators, ZK verifiers, supported tokens and burn substitutors, and to directly overwrite the state root via setRoot(). There is no timelock or exit window on any of these actions."
},
"zkCatalogId": "barretenberg"
}
+10 -6
+10 -6
{
"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",
"exposure": "Transfers inside publish only encrypted notes. 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.",
"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.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": {
"verdict": "private",
"note": "Leaked for gateway DeFi legs."
},
"asset": {
"verdict": "private",
"note": "Leaked for gateway DeFi legs."
},
"linkage": {
"verdict": "private",
"note": "Epoch calldata ties each exit to the nullifiers and shape of one transfer."
}
},
"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"
},
{
"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": "Gift claim and refund are indistinguishable",
"url": "https://github.com/sunnyside-io/privacy-boost-protocol/blob/23907eeebf0e50cd18da42a287671189e61ecb0f/contracts/src/interfaces/IPrivacyBoost.sol#L694-L707"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "bad",
"exposure": "The anonymity set is small, so most withdrawals can be linked to their funding deposits by amount and timing.",
"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.",
"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."
}
},
"sources": [
{
"title": "Operator heartbeat address",
"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",
"exposure": "All shielded actions go to the operator's server as an encrypted envelope, and note keys stay in a local vault. Only the operator's relay submits epochs onchain, so nothing of yours reaches a public node.",
"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.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
},
"sources": [
{
"title": "SDK package, closed Rust core",
"url": "https://www.npmjs.com/package/@sunnyside-io/privacy-boost"
},
{
"title": "Server info endpoint",
"url": "https://base.privacyboost.io/api/v1/info"
},
{
"contract": "PrivacyBoost",
"title": "Single permitted relay"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "The operator runs the enclave that holds every transfer in plaintext and the key to every onchain note. 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.",
"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.",
"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": "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"
}
],
"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",
"exposure": "Every note wraps its key to the enclave's long-lived elliptic-curve public key as well as the receiver's. A quantum computer, or a leak of that one key, decrypts the entire history.",
"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"
}
],
"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.",
"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."
}
},
"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."
},
"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.",
"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."
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides which deposit funds which withdrawal, for deposits approved by the permissioned ASP. Everything else is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Which approved deposit a withdrawal spends is hidden. Partial withdrawals leave a change note and look like full ones.",
"exposureShort": "Which approved deposit a withdrawal spends is hidden.",
"exposureContinued": "Partial withdrawals leave a change note and look like full ones.",
"advice": "Exit through a relayer, so no wallet of yours pays gas for the receiving address. Withdraw partially to fresh addresses, and ragequit only untouched deposits: ragequitting a change note reveals the withdrawal it came from.",
"sources": [
{
"contract": "PrivacyPoolsEntrypoint"
},
{
"title": "Withdrawal circuit",
"url": "https://github.com/0xbow-io/privacy-pools-core/blob/main/packages/circuits/circuits/withdraw.circom"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The approved set at any block is public, bounding the anonymity set. Any amount is allowed, so an unusual one pairs a deposit with its withdrawal. Paying gas from your own wallet instead of a relayer exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"exposureShort": "The approved set at any block is public, bounding the anonymity set.",
"exposureContinued": "Any amount is allowed, so an unusual one pairs a deposit with its withdrawal. Paying gas from your own wallet instead of a relayer exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"advice": "Use a pool with a large anonymity set. Withdraw common amounts rather than everything at once. Wait before exiting and pick a different time of day than the deposit. Exit to a fresh address every time and spend from it with a different wallet than the one that deposited.",
"sources": [
{
"title": "Blockchain Privacy and Regulatory Compliance (design paper)",
"url": "https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4563364"
},
{
"title": "Tutela (arXiv:2201.06811)",
"url": "https://arxiv.org/abs/2201.06811"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "good",
"exposure": "The official frontend allows you to set your own RPC endpoint per network, scans every pool whole and matches notes locally, so a node learns only which pools you looked at. 0xbow's servers still see that a session happened, through bulk feeds that carry nothing about the notes. A relayer receives amount and asset for a quote and the recipient once you confirm.",
"exposureShort": "The official frontend allows you to set your own RPC endpoint per network, scans every pool whole and matches notes locally, so a node learns only which pools you looked at.",
"exposureContinued": "0xbow's servers still see that a session happened, through bulk feeds that carry nothing about the notes. A relayer receives amount and asset for a quote and the recipient once you confirm.",
"advice": "Set an endpoint for every network before signing in, and sign in with a recovery phrase so no wallet address is queried. Without an endpoint, every read goes through 0xbow's proxy and Alchemy under 0xbow's key. Read the chain from your own node, send through a public RPC over Tor, and use a popular relayer. If you settle for a VPN instead of Tor, pick one you trust: it hides your IP from the relayer but sees it itself.",
"sources": [
{
"title": "RPC setting, one endpoint per network, offered before sign-in",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/containers/Header.tsx#L39"
},
{
"title": "Event sync and reads both move to the custom endpoint",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/config/chainData.ts#L667-L682"
},
{
"title": "Networks without an endpoint are skipped, not proxied",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/config/customRpc.ts#L638-L642"
},
{
"title": "Default reads through 0xbow's Hypersync proxy and Alchemy key",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/config/chainData.ts#L140-L141"
},
{
"title": "Pools scanned whole from deployment, dates from bulk logs",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/dataService.ts#L11-L25"
},
{
"title": "No block lookup per deposit",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/sdk.ts#L510-L516"
},
{
"title": "Relayed receipt read from bulk logs, hash never sent",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/relayedReceipt.ts#L3-L44"
},
{
"title": "Wallet balance read on a fixed cadence",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/providers/ChainProvider.tsx#L125-L147"
},
{
"title": "Recipient sent to the relayer on confirm only",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/quotePhases.ts#L4-L10"
},
{
"title": "Sign-in with a recovery phrase needs no wallet",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/providers/AuthProvider.tsx#L39-L47"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "warning",
"exposure": "The ASP postman sets a new approved list at any time with no delay, and the pool accepts only the latest one. It can deny you a private exit or publish a list with only your deposit, which is then your whole anonymity set. The website shows the anonymity set but does not block a tiny one.",
"exposureShort": "The ASP postman sets a new approved list at any time with no delay, and the pool accepts only the latest one.",
"exposureContinued": "It can deny you a private exit or publish a list with only your deposit, which is then your whole anonymity set. The website shows the anonymity set but does not block a tiny one.",
"advice": "Check the displayed anonymity set shown before withdrawing.",
"sources": [
{
"contract": "PrivacyPoolsEntrypoint",
"title": "updateRoot: the postman sets a new root with no delay"
},
{
"contract": "PrivacyPoolETH",
"title": "validWithdrawal: only the latest ASP root is accepted"
},
{
"section": "permissions",
"title": "Privacy Pools Multisig and ASP postman"
},
{
"title": "Anonymity set counted locally from the published list",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/containers/Modals/Withdraw/WithdrawForm.tsx#L175-L180"
},
{
"title": "Anonymity set shown, not enforced",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/containers/Modals/Withdraw/AmountInputSection.tsx#L94-L95"
}
],
"id": "privilegedInsider",
"value": "Link at risk",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "good",
"exposure": "Nothing encrypted is written onchain and commitments are plain hashes, so a quantum computer recovers nothing. Accounts created from a wallet signature reduce to that wallet's key.",
"exposureShort": "Nothing encrypted is written onchain and commitments are plain hashes, so a quantum computer recovers nothing.",
"exposureContinued": "Accounts created from a wallet signature reduce to that wallet's key.",
"advice": "Create your account from a seed phrase, not from a wallet signature.",
"sources": [
{
"title": "Commitment circuit (Poseidon)",
"url": "https://github.com/0xbow-io/privacy-pools-core/blob/main/packages/circuits/circuits/commitment.circom"
},
{
"title": "Wallet-signature seed derivation",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/walletSeed.ts#L40-L73"
},
{
"title": "Random seed phrase option",
"url": "https://github.com/0xbow-io/privacy-pools-website/blob/f34be7cb666b0607130c8a134973b3b30c33feb1/src/utils/seedPhrase.ts#L3-L7"
},
{
"section": "trusted-setups"
}
],
"id": "futureAdversary",
"value": "Link private",
"alsoExposed": []
}
}
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
}
],
"category": {
"id": "pool",
"label": "Pool",
"description": "Funds enter a shared pool and leave it later, with no actions inside. Hides which deposit funds which withdrawal."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "Even if the Entrypoint or ASP turns malicious, users can always ragequit (withdraw tokens) from the immutable pool contracts, at the cost of losing privacy.",
"walkawayTest": {
"passed": false,
"reason": "Association Set Providers must explicitly approve deposited funds before private withdrawals."
}
},
"relayerTracking": {
"type": "onchainEvents",
"sources": [
{
"address": "eth:0x6818809EefCe719E480a7526D76bD3e561526b46",
"sinceTimestamp": 1743265247,
"extractor": "privacyPoolsWithdrawalRelayed"
}
]
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The contracts, circuits, and supporting software needed to participate in Privacy Pools are publicly available and can be run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid withdrawals.\n2. the [trusted setup](#trusted-setups) is compromised or all ceremony participants collude, allowing invalid withdrawals.\n3. the Entrypoint owner deploys a malicious [upgrade](#upgrades-and-governance) that steals new deposits.\n
\n## Funds can be lost if\n1. a user loses the secret and nullifier required to spend their deposit.\n
\n## Privacy can be lost if\n1. no relayer is available and the withdrawal must be submitted from an address that can be linked to the user.\n2. the ASP manager refuses to whitelist a deposit, forcing the user to either wait or exit publicly through ragequit.",
"tokens": [
{
"token": {
"address": "0x6440f144b7e50D6a8439336510312d2F54beB01D",
"iconUrl": "https://coin-images.coingecko.com/coins/images/56069/large/BOLD_logo.png?1748265087",
"symbol": "BOLD",
"decimals": 18,
"priceId": "liquity-bold-2",
"sinceTimestamp": 1770806867
},
"buckets": [
{
"id": "privacy-pools-BOLD",
"type": "pool",
"label": "BOLD pool",
"address": "eth:0xb4b5Fd38Fd4788071d7287e3cB52948e0d10b23E",
"sinceTimestamp": 1770806867,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1752848471
},
"buckets": [
{
"id": "privacy-pools-DAI",
"type": "pool",
"label": "DAI pool",
"address": "eth:0x1c31C03B8CB2EE674D0F11De77135536db828257",
"sinceTimestamp": 1752848471,
"anonymitySet": {
"minimumAmounts": [
"200000000000000000000",
"20000000000000000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"iconUrl": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"symbol": "ETH",
"decimals": 18,
"priceId": "ethereum",
"sinceTimestamp": 1743265259
},
"buckets": [
{
"id": "privacy-pools-ETH",
"type": "pool",
"label": "ETH pool",
"address": "eth:0xF241d57C6DebAe225c0F2e6eA1529373C9A9C9fB",
"sinceTimestamp": 1743265259,
"anonymitySet": {
"minimumAmounts": [
"100000000000000000",
"10000000000000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29",
"iconUrl": "https://coin-images.coingecko.com/coins/images/53963/large/frxUSD.png?1737792154",
"symbol": "frxUSD",
"decimals": 18,
"priceId": "frax-usd",
"sinceTimestamp": 1754583623
},
"buckets": [
{
"id": "privacy-pools-frxUSD",
"type": "pool",
"label": "frxUSD pool",
"address": "eth:0xC6C769fac7AABEadd31a03fAe5Ca0Ec5B4C50f84",
"sinceTimestamp": 1754583623,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x085780639CC2cACd35E474e71f4d000e2405d8f6",
"iconUrl": "https://coin-images.coingecko.com/coins/images/36202/large/fxUSD.jpg?1710833113",
"symbol": "fxUSD",
"decimals": 18,
"priceId": "f-x-protocol-fxusd",
"sinceTimestamp": 1765446455
},
"buckets": [
{
"id": "privacy-pools-fxUSD",
"type": "pool",
"label": "fxUSD pool",
"address": "eth:0xD14F4B36E1D1D98c218db782c49149876042BC56",
"sinceTimestamp": 1765446455,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD",
"iconUrl": "https://coin-images.coingecko.com/coins/images/52721/large/sUSDS_Coin.png?1734086971",
"symbol": "sUSDS",
"decimals": 18,
"priceId": "susds",
"sinceTimestamp": 1752782999
},
"buckets": [
{
"id": "privacy-pools-sUSDS",
"type": "pool",
"label": "sUSDS pool",
"address": "eth:0xBBdA2173CDFEA1c3bD7F2908798F1265301d750c",
"sinceTimestamp": 1752782999,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
"iconUrl": "https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002",
"symbol": "USD1",
"decimals": 18,
"priceId": "usd1-wlfi",
"sinceTimestamp": 1754583179
},
"buckets": [
{
"id": "privacy-pools-USD1",
"type": "pool",
"label": "USD1 pool",
"address": "eth:0xc0A8Bc0F4F982b4d4f1fFae8F4FCCb58c9B29c98",
"sinceTimestamp": 1754583179,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1753353035
},
"buckets": [
{
"id": "privacy-pools-USDC",
"type": "pool",
"label": "USDC pool",
"address": "eth:0xb419c2867aB3CBc78921660cB95150d95A94ce86",
"sinceTimestamp": 1753353035,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3",
"iconUrl": "https://assets.coingecko.com/coins/images/33613/large/3466ef_3c088c66c7d941e8856339d0bddf33cc_mv2.png?1702514458",
"symbol": "USDe",
"decimals": 18,
"priceId": "ethena-usde",
"sinceTimestamp": 1754583083
},
"buckets": [
{
"id": "privacy-pools-USDe",
"type": "pool",
"label": "USDe pool",
"address": "eth:0xe6D36B33b00A7C0cB0C2a8d39D07e7dB0c526Abc",
"sinceTimestamp": 1754583083,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xdC035D45d973E3EC169d2276DDab16f1e407384F",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39926/large/usds.webp?1726666683",
"symbol": "USDS",
"decimals": 18,
"priceId": "usds",
"sinceTimestamp": 1752503003
},
"buckets": [
{
"id": "privacy-pools-USDS",
"type": "pool",
"label": "USDS pool",
"address": "eth:0x05e4DBD71B56861eeD2Aaa12d00A797F04B5D3c0",
"sinceTimestamp": 1752503003,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1753352915
},
"buckets": [
{
"id": "privacy-pools-USDT",
"type": "pool",
"label": "USDT pool",
"address": "eth:0xe859C0bD25f260BaEE534Fb52e307D3b64D24572",
"sinceTimestamp": 1753352915,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"iconUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857",
"symbol": "WBTC",
"decimals": 8,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1753975703
},
"buckets": [
{
"id": "privacy-pools-WBTC",
"type": "pool",
"label": "WBTC pool",
"address": "eth:0xF973f4B180A568157Cd7A0E6006449139E6Bfc32",
"sinceTimestamp": 1753975703,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0xDcEe70654261AF21C44c093C300eD3Bb97b78192",
"iconUrl": "https://coin-images.coingecko.com/coins/images/29734/large/woeth-200x200.png?1714796686",
"symbol": "wOETH",
"decimals": 18,
"priceId": "wrapped-oeth",
"sinceTimestamp": 1756377743
},
"buckets": [
{
"id": "privacy-pools-wOETH",
"type": "pool",
"label": "wOETH pool",
"address": "eth:0x7d2959bCFb936a84531518e8391DdBa844e03ebE",
"sinceTimestamp": 1756377743,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
},
{
"token": {
"address": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"iconUrl": "https://assets.coingecko.com/coins/images/18834/large/wstETH.png?1696518295",
"symbol": "wstETH",
"decimals": 18,
"priceId": "wrapped-steth",
"sinceTimestamp": 1753975583
},
"buckets": [
{
"id": "privacy-pools-wstETH",
"type": "pool",
"label": "wstETH pool",
"address": "eth:0x1A604E9DFa0EFDC7FFda378AF16Cb81243b61633",
"sinceTimestamp": 1753975583,
"deposit": {
"event": "0xe3b53cd1a44fbf11535e145d80b8ef1ed6d57a73bf5daa7e939b6b01657d6549",
"extractor": "privacyPoolsValue",
"params": {}
},
"withdrawal": {
"event": "0x75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21",
"extractor": "privacyPoolsValue",
"params": {}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "The 2/4 Privacy Pools Multisig can instantly change the system’s critical configs, including the Entrypoint implementation and ASP root used for private withdrawals. The ASP postman (EOA) can also remove any deposit from the whitelist at any time, forcing a public rage-quit if the affected party wishes to withdraw. The guaranteed immutable escape hatch is pool-level ragequit (public withdrawal) to the original depositor address, because that logic lives in the immutable pool contracts and does not depend on the Entrypoint registry and config. This means the system is permissioned in its deposit logic and deposit privacy, but non-custodial for deposited assets. Past, successful (non-ragequit) withdrawals can not be deanonymized by the protocol."
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides everything inside the pool, including which shield funds which unshield. Shields and unshields are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Everything inside the pool is hidden, including which shield funds which unshield. Shields and unshields show address, token and amount. DeFi bundles unshield to the adapter in cleartext.",
"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."
},
"asset": {
"verdict": "private",
"note": "Leaked for DeFi bundles."
},
"linkage": "private"
},
"sources": [
{
"contract": "RailgunSmartWallet"
},
{
"title": "Note ciphertext format",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/note/transact-note.ts"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The candidates for an unshield are the shields of the same token. In-pool transfers break the one-to-one match of a mixer, but timing and exact or round amounts narrow the set. Paying gas from your own wallet instead of a broadcaster exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"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.",
"advice": "Withdraw common amounts rather than everything at once. Wait before exiting and pick a different time of day than the deposit. Exit to a fresh address every time and spend from it with a different wallet than the one that deposited.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
},
"sources": [
{
"title": "A Tattered Cloak of Invisibility (arXiv:2606.25926)",
"url": "https://arxiv.org/abs/2606.25926"
},
{
"title": "The Anonymity Gap (arXiv:2608.22987)",
"url": "https://arxiv.org/abs/2608.22987"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "good",
"exposure": "The wallet finds its notes by trial-decrypting every note locally, so nodes learn nothing about which are yours. By default it sends the pending unshield to the configured node for a gas estimate, which reveals the destination early.",
"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.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": "private"
},
"sources": [
{
"title": "Gas estimation with dummy proof",
"url": "https://github.com/Railgun-Community/wallet/blob/main/src/services/transactions/tx-gas-details.ts"
},
{
"title": "Broadcaster decrypts request",
"url": "https://github.com/Railgun-Community/ppoi-safe-broadcaster-example/blob/main/src/server/waku-broadcaster/methods/transact-method.ts"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "good",
"exposure": "There is no view key, so nobody can read past activity. The DAO can upgrade the contracts after a seven-day delay. The proof-of-innocence list provider can refuse to list a shield, leaving only a self-broadcast exit.",
"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.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "private",
"linkage": {
"verdict": "atRisk",
"note": "POI nodes tie a session to a note cluster and its transaction ids."
}
},
"sources": [
{
"section": "permissions",
"title": "Governance roles"
},
{
"title": "POI required lists",
"url": "https://github.com/Railgun-Community/shared-models/blob/main/src/models/poi.ts"
},
{
"title": "POI node interface",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/poi/poi.ts"
}
],
"id": "privilegedInsider",
"value": "Link private",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "Notes are encrypted with elliptic-curve key exchange. A quantum computer decrypts every note sent to a 0zk address that was ever shared, including broadcaster fee notes: amounts, tokens and counterparties.",
"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.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Decrypts for notes touching any shared 0zk address."
},
"recipient": "atRisk",
"amount": "atRisk",
"asset": "atRisk",
"linkage": "atRisk"
},
"sources": [
{
"title": "Shared key derivation (Ed25519 ECDH)",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/keys-utils.ts"
},
{
"title": "AES-GCM note encryption",
"url": "https://github.com/Railgun-Community/engine/blob/main/src/utils/encryption/aes.ts"
}
],
"id": "futureAdversary",
"value": "Link at risk",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"exposure": "atRisk"
},
{
"field": "amount",
"exposure": "atRisk"
},
{
"field": "asset",
"exposure": "atRisk"
}
]
}
}
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "transfers",
"label": "Transfers",
"description": "Private transfers within the shielded pool."
},
{
"id": "defi",
"label": "DeFi",
"description": "Interop with DeFi (swaps, vaults) from within the shielded pool."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
}
],
"category": {
"id": "shieldedLedger",
"label": "Shielded ledger",
"description": "A pool with transfers or DeFi inside. Hides who pays whom and which deposit funds which withdrawal."
},
"exitWindow": {
"value": "7d",
"sentiment": "warning",
"orderHint": 604800,
"description": "DAO-approved upgrades wait 7d before they can execute, giving users time to unshield funds if they do not approve the change.",
"walkawayTest": {
"passed": true
}
},
"relayerTracking": {
"type": "railgunWaku",
"chainId": 1,
"sinceTimestamp": 1788134400
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The contracts, circuits, and supporting software needed to participate in the protocol are publicly available and can be run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid spends or withdrawals.\n2. the [trusted setup](#trusted-setups) is compromised or all ceremony participants collude, allowing invalid spends or withdrawals.\n3. the DAO passes a malicious [upgrade](#upgrades-and-governance) and users do not react before the 7-day execution delay expires.\n
\n## Funds can be lost if\n1. a user loses the private keys required to control their private balance.\n
\n## Privacy can be lost if\n1. no broadcaster is available and transactions must be sent from a public address that can be linked to the user.",
"tokens": [
{
"token": {
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"iconUrl": "https://assets.coingecko.com/coins/images/2518/large/weth.png?1696503332",
"symbol": "WETH",
"decimals": 18,
"priceId": "weth",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-WETH",
"type": "pool",
"label": "WETH",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"100000000000000000",
"10000000000000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-USDT",
"type": "pool",
"label": "USDT",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-USDC",
"type": "pool",
"label": "USDC",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000",
"20000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
}
}
]
},
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1574121600
},
"buckets": [
{
"id": "railgun-DAI",
"type": "pool",
"label": "DAI",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"anonymitySet": {
"minimumAmounts": [
"200000000000000000000",
"20000000000000000000000"
]
},
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
}
}
]
},
{
"token": {
"address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"iconUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857",
"symbol": "WBTC",
"decimals": 8,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1573689600
},
"buckets": [
{
"id": "railgun-WBTC",
"type": "pool",
"label": "WBTC",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
}
}
]
},
{
"token": {
"address": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4",
"iconUrl": "https://coin-images.coingecko.com/coins/images/71681/large/near.png?1768905174",
"symbol": "NEAR",
"decimals": 24,
"priceId": "rainbow-bridged-near-ethereum",
"sinceTimestamp": 1768867200
},
"buckets": [
{
"id": "railgun-NEAR",
"type": "pool",
"label": "NEAR",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1768867200,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x85F17Cf997934a597031b2E18a9aB6ebD4B9f6a4"
}
}
}
]
},
{
"token": {
"address": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb",
"iconUrl": "https://coin-images.coingecko.com/coins/images/14688/large/Logo_1_%28brighter%29.png?1734430693",
"symbol": "FLUID",
"decimals": 18,
"priceId": "instadapp",
"sinceTimestamp": 1623801600
},
"buckets": [
{
"id": "railgun-FLUID",
"type": "pool",
"label": "FLUID",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb"
}
}
}
]
},
{
"token": {
"address": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D",
"iconUrl": "https://coin-images.coingecko.com/coins/images/16840/large/railgun.jpeg?1696516407",
"symbol": "RAIL",
"decimals": 18,
"priceId": "railgun",
"sinceTimestamp": 1625270400
},
"buckets": [
{
"id": "railgun-RAIL",
"type": "pool",
"label": "RAIL",
"address": "eth:0xFA7093CDD9EE6932B4eb2c9e1cde7CE00B1FA4b9",
"sinceTimestamp": 1651422389,
"deposit": {
"event": "0x3a5b9dc26075a3801a6ddccf95fec485bb7500a91b44cec1add984c21ee6db3b",
"extractor": "railgunShield",
"params": {
"tokenAddress": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D"
}
},
"withdrawal": {
"event": "0xd93cf895c7d5b2cd7dc7a098b678b3089f37d91f48d9b83a0800a91cbdf05284",
"extractor": "railgunUnshield",
"params": {
"tokenAddress": "0xe76C6c83af64e4C60245D8C7dE953DF673a7A33D"
}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Railgun features an omnipotent DAO governed by the stakers of the RAIL token. The DAO has the authority to change ZK circuit logic on the core Railgun contract, which can arbitrarily change the rules for shielded tokens; as well as manage blacklisted tokens, mint RAIL tokens and manage governance rewards. See docs here: ",
"governanceInfo": {
"upgrades": {
"Normal upgrade path": "Create a proposal with an IPFS link and onchain calldata in the [Voting contract](https://etherscan.io/address/0xc480F68A3dcC3EdD82134FAB45C14A0FcF1dA3CC) → collect **500.00 K RAIL** sponsorship within 1mo → wait 2d → cast Yay votes within 5d and Nay votes within 6d → pass with a simple majority and **2.00 M RAIL** quorum → wait 7d → permissionless execution through the Delegator within 14d.",
"Exit window": "**7d** — a passed proposal must wait this long before it can be executed, giving users time to unshield funds."
},
"tokenGovernance": {
"Governance token": "`RAIL` 1 token = 1 vote, delegated. Total supply: **60.00 M RAIL**, DAO-owned treasury (unavailable for voting): **2.30 M RAIL**, staked for voting: **41.61 M RAIL**, the rest is circulating supply.",
"Stake lock": "Unstaking has **1mo** delay.",
"Voting venue": "[Voting contract](https://etherscan.io/address/0xc480F68A3dcC3EdD82134FAB45C14A0FcF1dA3CC) on Ethereum. Proposal text is distributed over IPFS, its CID is available as a parameter of `createPropsal()` call on the voting contract.",
"Proposal threshold": "**No threshold to create a proposal.** A proposal must receive sponsorship from **500.00 K RAIL** stake within 1mo.",
"Quorum": "**2.00 M RAIL**, with a simple majority required for acceptance.",
"Execution model": "**Onchain calldata · Permissionless execution through the Delegator.** A passed proposal waits 7d, after which anyone can execute it through the [Delegator contract](https://etherscan.io/address/0xB6d513f6222Ee92Fff975E901bd792E2513fB53B) within 14d."
}
}
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides amounts, senders and the link between deposit and withdrawal inside the pool. The first payment to each new contact is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "warning",
"exposure": "Transfers inside are encrypted, but the public part of every transaction lists the recipient address when you open a channel to a new contact, the token and amount of the fee you pay, and the target and calldata of any DeFi action. Deposits and withdrawals show address, token and amount. Submitting from your own wallet names you; a paymaster hides the submitter but shows the fee token and amount.",
"exposureShort": "Transfers inside are encrypted, but transactions to new contacts reveil the recipient.",
"exposureContinued": "The token and amount of the fee you pay, and the target and calldata of any DeFi action are public. Deposits and withdrawals show address, token and amount. Submitting from your own wallet names you. A paymaster hides the submitter but shows the fee token and amount.",
"advice": "Submit every pool action through a paymaster and pay its fee in the most common token. Treat the first payment to a new contact, and any DeFi action, as public.",
"interior": {
"sender": "private",
"recipient": {
"verdict": "exposed",
"note": "Opening a channel writes the recipient address in cleartext; later transfers do not."
},
"amount": "private",
"asset": {
"verdict": "atRisk",
"note": "The fee payment names the token; DeFi actions name the target contract."
},
"linkage": "private"
},
"sources": [
{
"title": "PrivacyPool contract on Voyager",
"url": "https://voyager.online/contract/0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
{
"title": "Channel opening carries the recipient address",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/actions.cairo#L329-L334"
},
{
"title": "DeFi actions carry target contract and calldata",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/actions.cairo#L360-L365"
},
{
"title": "Deposit and withdrawal events carry address, token and amount",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L17-L41"
},
{
"title": "Paymaster fee fixes the visible fee token",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/sdk/src/interfaces.ts#L160-L172"
},
{
"title": "Protocol fee is pulled in STRK from the submitter",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/privacy.cairo#L845-L856"
},
{
"title": "Without a paymaster the client submits from the user wallet",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/demo/src/hooks/useTransactionBuilder.ts#L247-L256"
}
],
"id": "publicObserver",
"value": "Link at risk",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "The set of registered users is small and split further by token and by fee token. A channel opened in the same transaction as a deposit ties the two together, and most withdrawal addresses have also deposited. Paying gas from your own wallet instead of a paymaster exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"exposureShort": "The set of registered users is small and split further by token and by fee token.",
"exposureContinued": "A channel opened in the same transaction as a deposit ties the two together, and most withdrawal addresses have also deposited. Paying gas from your own wallet instead of a paymaster exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"advice": "Open channels in a transaction without a deposit, pay fees in the most common token, and withdraw uneven amounts that match no deposit. 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": {
"verdict": "atRisk",
"note": "A channel opened in the same transaction as a deposit names the depositor."
},
"recipient": "exposed",
"amount": "private",
"asset": "atRisk",
"linkage": {
"verdict": "atRisk",
"note": "Most withdrawal addresses have also deposited, which pairs the two ends."
}
},
"sources": [
{
"title": "PrivacyPool contract on Voyager",
"url": "https://voyager.online/contract/0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
{
"title": "Deposit and withdrawal events carry address, token and amount",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L17-L41"
},
{
"title": "Fee is charged per action in a visible token",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/privacy.cairo#L845-L856"
}
],
"id": "chainAnalyst",
"value": "Link at risk",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
}
]
},
"networkObserver": {
"sentiment": "warning",
"exposure": "The paymaster and the sequencer receive the client proof with every action. Stwo proofs are not zero-knowledge by default, and how much of the private execution they reveal is not established. Traffic to the proving and note-discovery services is encrypted, and both support an oblivious relay that hides your address, but it is off unless the client turns it on.",
"exposureShort": "The paymaster and the sequencer receive the client proof with every action.",
"exposureContinued": "Stwo proofs are not zero-knowledge by default, and how much of the private execution they reveal is not established. Traffic to the proving and note-discovery services is encrypted, and both support an oblivious relay that hides your address, but it is off unless the client turns it on.",
"advice": "Turn on the oblivious relay for the proving and discovery services, or run both yourself.",
"interior": {
"sender": "unverifiable",
"recipient": "unverifiable",
"amount": "unverifiable",
"asset": "atRisk",
"linkage": "unverifiable"
},
"sources": [
{
"title": "Oblivious relay support is opt-in",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/sdk/src/internal/ohttp-client.ts#L24-L32"
},
{
"title": "Discovery service: per-request keys and oblivious relay",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/crates/discovery-service/README.md#L14-L32"
},
{
"title": "Proof and proof facts travel in the submitted transaction",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/demo/src/hooks/useTransactions.ts#L140-L160"
},
{
"title": "Stwo Cairo is not zero-knowledge by default",
"url": "https://github.com/starkware-libs/stwo-cairo/blob/2b1fb4ded5496fb2db4e8261cd5ee5ef6b710839/README.md#security-model"
}
],
"id": "networkObserver",
"value": "Link at risk",
"alsoExposed": [
{
"field": "sender",
"exposure": "unverifiable"
},
{
"field": "amount",
"exposure": "unverifiable"
}
]
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "Every user's viewing key is escrowed onchain, encrypted to one auditor key that a role holder can replace at any time with no delay; that key decrypts everything the protocol hides. The default proving service receives your address, viewing key and actions in the clear, the note-discovery service receives the viewing key on every sync, and deposits need a fresh attestation from a screening provider that sees and can block every depositor.",
"exposureShort": "Every user's viewing key is escrowed onchain, encrypted to one auditor key that a role holder can replace at any time with no delay.",
"exposureContinued": "That key decrypts everything the protocol hides. The default proving service receives your address, viewing key and actions in the clear, the note-discovery service receives the viewing key on every sync, and deposits need a fresh attestation from a screening provider that sees and can block every depositor.",
"advice": "Run the prover and note discovery yourself, or read the pool directly from chain. Nothing you do removes the auditor key.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Auditor and screener keys in pool storage",
"url": "https://voyager.online/contract/0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
{
"title": "Viewing key escrowed to the auditor key onchain",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L5-L13"
},
{
"title": "Auditor and screener keys are settable roles",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L43-L52"
},
{
"title": "Withdrawals carry the auditor-decryptable withdrawer address",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L17-L29"
},
{
"title": "Proving request carries the user address and viewing key",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/sdk/src/internal/proof-invocation-factory.ts#L128-L136"
},
{
"title": "Discovery request carries the viewing key",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/sdk/src/internal/indexer-discovery.ts#L158-L165"
},
{
"title": "Deposits require a signed screening attestation",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/privacy.cairo#L784-L800"
},
{
"title": "Screening sidecar forwards the depositor to an external provider",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/proof-interceptor/README.md#L37"
},
{
"section": "upgrades-and-governance"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
},
{
"field": "asset",
"exposure": "exposed"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "The proofs are post-quantum, the encryption is not. Channel keys, note contents and the auditor escrow use elliptic-curve key exchange, and the auditor public key sits onchain. A quantum computer recovers that one key and with it every escrowed viewing key, and so the whole history.",
"exposureShort": "The proofs are post-quantum, the encryption is not.",
"exposureContinued": "Channel keys, note contents and the auditor escrow use elliptic-curve key exchange, and the auditor public key sits onchain. A quantum computer recovers that one key and with it every escrowed viewing key, and so the whole history.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Stark-curve ECDH encryption of channel and note data",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/sdk/src/utils/encryptions.ts#L120-L136"
},
{
"title": "Viewing key escrowed under the onchain auditor public key",
"url": "https://github.com/starkware-libs/starknet-privacy/blob/cc0dc408dee41f5658cd528ae59ab0794be2e298/packages/privacy/src/events.cairo#L5-L13"
},
{
"title": "Auditor public key in pool storage",
"url": "https://voyager.online/contract/0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
},
{
"field": "asset",
"exposure": "exposed"
}
]
}
}
},
"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": "None",
"sentiment": "bad",
"orderHint": 0,
"description": "The pool implementation is immediately upgradeable, so users have no delay to withdraw before a malicious upgrade can take effect.",
"walkawayTest": {
"passed": false,
"reason": "Although the full software stack needed to generate proofs and exit is published and self-hostable, STRK-20 heavily relies on the permissioned Starknet sequencer: it alone verifies client proofs and must include pool transactions, so users cannot exit without its cooperation."
}
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The pool contract, TypeScript SDK, discovery service, and proving stack are publicly available and can be run locally, so users can audit what is actually proven and generate the required ZK proofs without revealing private data to a third-party prover."
},
"riskSummary": "## Funds can be stolen if\n1. the proof system or virtual Starknet execution model is broken or backdoored, allowing invalid server actions to be applied.\n2. the Starknet sequencer includes a transaction with fabricated proof facts.\n3. the escrow smart contract is maliciously upgraded (no delay).\n4. an external DeFi helper or target protocol invoked by the user mishandles assets.\n
\n## Funds can be lost if\n1. a user loses the Starknet account key or private viewing key required to spend their notes.\n2. the pool is paused or upgraded in a way that prevents users from applying valid actions.\n
\n## Privacy can be lost if\n1. the auditor private key holder decrypts registered users' viewing keys or withdrawal and metadata.\n2. a third-party-hosted prover or note discovery service leaks user secrets or metadata (both can be self-hosted).\n3. deposits, withdrawals, open-note fills, timing, unique amounts, or DeFi helper calldata make a user's activity linkable.",
"tokens": [
{
"token": {
"address": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
"iconUrl": "https://assets.coingecko.com/coins/images/26433/large/starknet.png?1696525507",
"symbol": "STRK",
"decimals": 18,
"priceId": "starknet",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-STRK",
"type": "pool",
"label": "STRK pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"
}
}
}
]
},
{
"token": {
"address": "0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696501661",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-USDC",
"type": "pool",
"label": "USDC pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb"
}
}
}
]
},
{
"token": {
"address": "0x0787150e306e6eae6e3f79dea881770e8bbff2c1b8eb490f969669ee945b3135",
"iconUrl": "https://coin-images.coingecko.com/coins/images/102173511/large/strkBTC_Logo.png?1779888214",
"symbol": "strkBTC",
"decimals": 8,
"priceId": "strkbtc",
"sinceTimestamp": 1777893725
},
"buckets": [
{
"id": "strk20-strkBTC",
"type": "pool",
"label": "strkBTC pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1777893725,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x0787150e306e6eae6e3f79dea881770e8bbff2c1b8eb490f969669ee945b3135"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x0787150e306e6eae6e3f79dea881770e8bbff2c1b8eb490f969669ee945b3135"
}
}
}
]
},
{
"token": {
"address": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac",
"iconUrl": "https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857",
"symbol": "WBTC",
"decimals": 8,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-WBTC",
"type": "pool",
"label": "WBTC pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac"
}
}
}
]
},
{
"token": {
"address": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
"iconUrl": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"symbol": "ETH",
"decimals": 18,
"priceId": "ethereum",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-ETH",
"type": "pool",
"label": "ETH pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"
}
}
}
]
},
{
"token": {
"address": "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a",
"iconUrl": "https://assets.coingecko.com/coins/images/54172/standard/logo200x200.png?1738561141",
"symbol": "XSTRK",
"decimals": 18,
"priceId": "endur-fi-staked-strk",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-XSTRK",
"type": "pool",
"label": "XSTRK pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
}
}
}
]
},
{
"token": {
"address": "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"decimals": 6,
"symbol": "USDT",
"priceId": "tether",
"sinceTimestamp": 1776679728
},
"buckets": [
{
"id": "strk20-USDT",
"type": "pool",
"label": "USDT pool",
"address": {
"chain": "starknet",
"address": "0x040337b1af3c663e86e333bab5a4b28da8d4652a15a69beee2b677776ffe812a"
},
"sinceTimestamp": 1776679728,
"deposit": {
"event": "0x9149d2123147c5f43d258257fef0b7b969db78269369ebcf5ebb9eef8592f2",
"extractor": "strk20Deposit",
"params": {
"tokenAddress": "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8"
}
},
"withdrawal": {
"event": "0x2eed7e29b3502a726faf503ac4316b7101f3da813654e8df02c13449e03da8",
"extractor": "strk20Withdrawal",
"params": {
"tokenAddress": "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8"
}
}
}
]
}
],
"trackedOn": [
"starknet"
],
"upgradesAndGovernance": {
"content": "The pool uses StarkWare-style role components and an instantly upgradeable smart contract implementation.\n\n- `APP_GOVERNOR` can set the fee amount, fee collector, and proof validity window.\n- `GOVERNANCE_ADMIN` can grant governance and upgrade-governor roles.\n- `SECURITY_ADMIN` can grant pause, unpause, and auditor-key administration roles.\n- `SECURITY_AGENT` can pause the pool, if granted.\n- `SECURITY_GOVERNOR` can unpause the pool and change the auditor public key, if granted.\n- `UPGRADE_GOVERNOR` can approve and execute upgrades, if granted.\n- `UPGRADE_AGENT` can execute approved upgrades, if granted.\n\nThe live role holders observed were:\n\n- `APP_GOVERNOR`: `0x2796da10aba2e1f445c38eba07e5a4393d6dab30d203d3432deb824e891619a` (2/4 Multisig)\n- `GOVERNANCE_ADMIN`: `0x3103066e6c7037ba947ea9a7b5b8d110ae7f3d631fa5849435d0dc1fc5ef785` (EOA)\n- `GOVERNANCE_ADMIN` and `SECURITY_ADMIN`: `0x663cc699d9c51b7d4d434e06f5982692167546ce525d9155edb476ac9a117d6` (7/12 Multisig)"
},
"zkCatalogId": "stwo"
}
+9 -5
+9 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides which deposit funds which withdrawal. Everything else is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Each pool has one fixed amount and no in-pool transfers, so every withdrawal spends exactly one deposit.",
"exposureShort": "Each pool has one fixed amount and no in-pool transfers, so every withdrawal spends exactly one deposit.",
"advice": "Exit through a relayer, so no wallet of yours pays gas for the receiving address.",
"sources": [
{
"contract": "Pool_1_ETH",
"title": "1 ETH pool"
},
{
"title": "Withdrawal circuit",
"url": "https://github.com/tornadocash/tornado-core/blob/master/circuits/withdraw.circom"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The candidates for a withdrawal are the unspent deposits of the same pool, the anonymity set, which differs sharply between pools. Timing, address reuse and relayer choice narrow it further. Paying gas from your own wallet instead of a relayer exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"exposureShort": "The candidates for a withdrawal are the unspent deposits of the same pool, the anonymity set, which differs sharply between pools.",
"exposureContinued": "Timing, address reuse and relayer choice narrow it further. Paying gas from your own wallet instead of a relayer exposes that wallet's fingerprint, its account implementation and fee habits, even from a fresh address.",
"advice": "Use a pool with a large anonymity set. Deposit a large sum as one note. Wait before exiting and pick a different time of day than the deposit. Exit to a fresh address every time and spend from it with a different wallet than the one that deposited.",
"sources": [
{
"title": "Tutela (arXiv:2201.06811)",
"url": "https://arxiv.org/abs/2201.06811"
},
{
"title": "Blockchain is Watching You (arXiv:2005.14051)",
"url": "https://arxiv.org/abs/2005.14051"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "good",
"exposure": "The app downloads all deposits and matches locally, so a node learns only which pool you looked at. The relayer receives only the finished withdrawal.",
"exposureShort": "The app downloads all deposits and matches locally, so a node learns only which pool you looked at.",
"exposureContinued": "The relayer receives only the finished withdrawal.",
"advice": "Read the chain from your own node, send through a public RPC over Tor, and use a popular relayer. If you settle for a VPN instead of Tor, pick one you trust: it hides your IP from the relayer but sees it itself.",
"sources": [
{
"title": "Event sync (classic UI)",
"url": "https://github.com/tornadocash/tornado-classic-ui/blob/master/services/events.js"
},
{
"title": "Relayer endpoint",
"url": "https://github.com/tornadocash/tornado-relayer/blob/master/src/contollers/controller.js"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "good",
"exposure": "The pools cannot be paused, upgraded or made to reveal anything. Governance controls only the website, the router and the relayer list.",
"exposureShort": "The pools cannot be paused, upgraded or made to reveal anything.",
"exposureContinued": "Governance controls only the website, the router and the relayer list.",
"advice": "Run an inspected local build of the client instead of the hosted frontend. Otherwise load it from its ENS name or IPFS hash.",
"sources": [
{
"contract": "Pool_0.1_ETH",
"title": "0.1 ETH pool (no operator)"
},
{
"contract": "InstanceRegistry"
},
{
"section": "permissions"
}
],
"id": "privilegedInsider",
"value": "Link private",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "Commitments use a Pedersen hash on an elliptic curve. A quantum computer could test whether a given deposit can fund a withdrawal, shrinking the candidate set without singling out one deposit. Notes backed up onchain are encrypted with elliptic-curve keys and become readable.",
"exposureShort": "Commitments use a Pedersen hash on an elliptic curve.",
"exposureContinued": "A quantum computer could test whether a given deposit can fund a withdrawal, shrinking the candidate set without singling out one deposit. Notes backed up onchain are encrypted with elliptic-curve keys and become readable.",
"advice": "Use a pool with a large anonymity set. Keep the note on your device and skip the onchain backup.",
"sources": [
{
"title": "Pedersen hash circuit (pinned circomlib fork)",
"url": "https://github.com/tornadocash/circomlib/blob/c372f14d324d57339c88451834bf2824e73bbdbc/circuits/pedersen.circom"
},
{
"title": "Commitment and nullifier hashing",
"url": "https://github.com/tornadocash/tornado-core/blob/v2.1/circuits/withdraw.circom"
},
{
"contract": "TornadoRouter",
"title": "Onchain note backups"
}
],
"id": "futureAdversary",
"value": "Link at risk",
"alsoExposed": []
}
}
},
"attributes": [
{
"id": "zk",
"label": "ZK",
"description": "Uses zero-knowledge proofs to prove private actions without revealing private data."
},
{
"id": "fixedAmounts",
"label": "Fixed amounts",
"description": "Pre-defined transfer amounts use distinct buckets (anonymity sets)."
}
],
"category": {
"id": "pool",
"label": "Pool",
"description": "Funds enter a shared pool and leave it later, with no actions inside. Hides which deposit funds which withdrawal."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "The core Tornado Cash contracts are immutable and have no admin upgrade path, so users can always withdraw with a valid note and proof.",
"walkawayTest": {
"passed": true
}
},
"relayerTracking": {
"type": "onchainEvents",
"sources": [
{
"address": "eth:0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc",
"sinceTimestamp": 1576523323,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936",
"sinceTimestamp": 1576534673,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF",
"sinceTimestamp": 1576536415,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xA160cdAB225685dA1d56aa342Ad8841c3b53f291",
"sinceTimestamp": 1577296976,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3",
"sinceTimestamp": 1576534688,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144",
"sinceTimestamp": 1577297383,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x07687e702b410Fa43f4cB4Af7FA097918ffD2730",
"sinceTimestamp": 1616114822,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x23773E65ed146A459791799d01336DB287f25334",
"sinceTimestamp": 1616115387,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x22aaA7720ddd5388A3c0A3333430953C68f1849b",
"sinceTimestamp": 1577297782,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x03893a7c7463AE47D46bc7f091665f1893656003",
"sinceTimestamp": 1616155055,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x2717c5e28cf931547B621a5dddb772Ab6A35B701",
"sinceTimestamp": 1616135923,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af",
"sinceTimestamp": 1616115450,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xd96f2B1c14Db8458374d9Aca76E26c3D18364307",
"sinceTimestamp": 1577298068,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D",
"sinceTimestamp": 1577298155,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x169AD27A470D064DEDE56a2D3ff727986b15D52B",
"sinceTimestamp": 1577298900,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f",
"sinceTimestamp": 1577298985,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x178169B423a011fff22B9e3F3abeA13414dDD0F1",
"sinceTimestamp": 1616134868,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0x610B717796ad172B316836AC95a2ffad065CeaB4",
"sinceTimestamp": 1616123193,
"extractor": "tornadoCashWithdrawal"
},
{
"address": "eth:0xbB93e510BbCD0B7beb5A853875f9eC60275CF498",
"sinceTimestamp": 1616135758,
"extractor": "tornadoCashWithdrawal"
}
]
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "There is at least one practical way to participate in Tornado Cash using published source code that can be audited and run locally."
},
"riskSummary": "## Funds can be stolen if\n1. the zk proof system is broken, allowing invalid withdrawals.\n2. the [trusted setup](#trusted-setups) is compromised or all ceremony participants collude, allowing invalid withdrawals.\n
\n## Funds can be lost if\n1. a user loses the note secrets required to withdraw. \n
\n## Privacy can be lost if\n1. no relayer is available and the withdrawal must be submitted from an address that can be linked to the user (see [best practice page](/publications/privacy-best-practices) for more info).",
"tokens": [
{
"token": {
"address": "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643",
"iconUrl": "https://assets.coingecko.com/coins/images/9281/large/cDAI.png?1696509390",
"symbol": "cDAI",
"decimals": 8,
"priceId": "cdai",
"sinceTimestamp": 1577297782
},
"buckets": [
{
"id": "tornado-cDAI-5000",
"type": "denomination",
"label": "cDAI 5000",
"address": "eth:0x22aaA7720ddd5388A3c0A3333430953C68f1849b",
"sinceTimestamp": 1577297782,
"denomination": "5000",
"anonymitySet": {
"minimumAmounts": [
"500000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "500000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "500000000000"
}
}
},
{
"id": "tornado-cDAI-50000",
"type": "denomination",
"label": "cDAI 50000",
"address": "eth:0x03893a7c7463AE47D46bc7f091665f1893656003",
"sinceTimestamp": 1616155055,
"denomination": "50000",
"anonymitySet": {
"minimumAmounts": [
"5000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "5000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "5000000000000"
}
}
},
{
"id": "tornado-cDAI-500000",
"type": "denomination",
"label": "cDAI 500000",
"address": "eth:0x2717c5e28cf931547B621a5dddb772Ab6A35B701",
"sinceTimestamp": 1616135923,
"denomination": "500000",
"anonymitySet": {
"minimumAmounts": [
"50000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "50000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "50000000000000"
}
}
},
{
"id": "tornado-cDAI-5000000",
"type": "denomination",
"label": "cDAI 5000000",
"address": "eth:0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af",
"sinceTimestamp": 1616115450,
"denomination": "5000000",
"anonymitySet": {
"minimumAmounts": [
"500000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "500000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "500000000000000"
}
}
}
]
},
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1576534688
},
"buckets": [
{
"id": "tornado-DAI-100",
"type": "denomination",
"label": "DAI 100",
"address": "eth:0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3",
"sinceTimestamp": 1576534688,
"denomination": "100",
"anonymitySet": {
"minimumAmounts": [
"100000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000"
}
}
},
{
"id": "tornado-DAI-1000",
"type": "denomination",
"label": "DAI 1000",
"address": "eth:0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144",
"sinceTimestamp": 1577297383,
"denomination": "1000",
"anonymitySet": {
"minimumAmounts": [
"1000000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000000000000000"
}
}
},
{
"id": "tornado-DAI-10000",
"type": "denomination",
"label": "DAI 10000",
"address": "eth:0x07687e702b410Fa43f4cB4Af7FA097918ffD2730",
"sinceTimestamp": 1616114822,
"denomination": "10000",
"anonymitySet": {
"minimumAmounts": [
"10000000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "10000000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "10000000000000000000000"
}
}
},
{
"id": "tornado-DAI-100000",
"type": "denomination",
"label": "DAI 100000",
"address": "eth:0x23773E65ed146A459791799d01336DB287f25334",
"sinceTimestamp": 1616115387,
"denomination": "100000",
"anonymitySet": {
"minimumAmounts": [
"100000000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000000"
}
}
}
]
},
{
"token": {
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"iconUrl": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"symbol": "ETH",
"decimals": 18,
"priceId": "ethereum",
"sinceTimestamp": 1576523323
},
"buckets": [
{
"id": "tornado-ETH-0.1",
"type": "denomination",
"label": "ETH 0.1",
"address": "eth:0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc",
"sinceTimestamp": 1576523323,
"denomination": "0.1",
"anonymitySet": {
"minimumAmounts": [
"100000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000"
}
}
},
{
"id": "tornado-ETH-1",
"type": "denomination",
"label": "ETH 1",
"address": "eth:0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936",
"sinceTimestamp": 1576534673,
"denomination": "1",
"anonymitySet": {
"minimumAmounts": [
"1000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000000000000"
}
}
},
{
"id": "tornado-ETH-10",
"type": "denomination",
"label": "ETH 10",
"address": "eth:0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF",
"sinceTimestamp": 1576536415,
"denomination": "10",
"anonymitySet": {
"minimumAmounts": [
"10000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "10000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "10000000000000000000"
}
}
},
{
"id": "tornado-ETH-100",
"type": "denomination",
"label": "ETH 100",
"address": "eth:0xA160cdAB225685dA1d56aa342Ad8841c3b53f291",
"sinceTimestamp": 1577296976,
"denomination": "100",
"anonymitySet": {
"minimumAmounts": [
"100000000000000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000000000000000"
}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1577298068
},
"buckets": [
{
"id": "tornado-USDC-100",
"type": "denomination",
"label": "USDC 100",
"address": "eth:0xd96f2B1c14Db8458374d9Aca76E26c3D18364307",
"sinceTimestamp": 1577298068,
"denomination": "100",
"anonymitySet": {
"minimumAmounts": [
"100000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
}
},
{
"id": "tornado-USDC-1000",
"type": "denomination",
"label": "USDC 1000",
"address": "eth:0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D",
"sinceTimestamp": 1577298155,
"denomination": "1000",
"anonymitySet": {
"minimumAmounts": [
"1000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1577298900
},
"buckets": [
{
"id": "tornado-USDT-100",
"type": "denomination",
"label": "USDT 100",
"address": "eth:0x169AD27A470D064DEDE56a2D3ff727986b15D52B",
"sinceTimestamp": 1577298900,
"denomination": "100",
"anonymitySet": {
"minimumAmounts": [
"100000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
}
},
{
"id": "tornado-USDT-1000",
"type": "denomination",
"label": "USDT 1000",
"address": "eth:0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f",
"sinceTimestamp": 1577298985,
"denomination": "1000",
"anonymitySet": {
"minimumAmounts": [
"1000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
}
}
]
},
{
"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": 1616123193
},
"buckets": [
{
"id": "tornado-WBTC-0.1",
"type": "denomination",
"label": "WBTC 0.1",
"address": "eth:0x178169B423a011fff22B9e3F3abeA13414dDD0F1",
"sinceTimestamp": 1616134868,
"denomination": "0.1",
"anonymitySet": {
"minimumAmounts": [
"10000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "10000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "10000000"
}
}
},
{
"id": "tornado-WBTC-1",
"type": "denomination",
"label": "WBTC 1",
"address": "eth:0x610B717796ad172B316836AC95a2ffad065CeaB4",
"sinceTimestamp": 1616123193,
"denomination": "1",
"anonymitySet": {
"minimumAmounts": [
"100000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "100000000"
}
}
},
{
"id": "tornado-WBTC-10",
"type": "denomination",
"label": "WBTC 10",
"address": "eth:0xbB93e510BbCD0B7beb5A853875f9eC60275CF498",
"sinceTimestamp": 1616135758,
"denomination": "10",
"anonymitySet": {
"minimumAmounts": [
"1000000000"
]
},
"deposit": {
"event": "0xa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
},
"withdrawal": {
"event": "0xe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c34931",
"extractor": "fixedAmount",
"params": {
"amount": "1000000000"
}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Tornado cash has a TORN DAO, which does not have the authority to upgrade or modify existing pools in any way. However it controls a significant portion of the Tornado cash protocol and periphery, including:\n\n1. **Default router for deposits and withdrawals and the official registry of supported pools**. Malicious upgrades of these components could lead to users losing deposited tokens. \n2. **Standard UI IPFS hash registered on ENS** ([link](https://app.ens.domains/tornadocash.eth)). Malicious upgrades of these components could lead to users losing deposited tokens. \n3. **TORN token itself**. Malicious upgrades of the token could lead to token transfers being frozen. \n4. **Registered relayers**. Malicious upgrades of these components could remove all registered relayers, disrupting user-relayer coordination and complicating private withdrawals.",
"governanceInfo": {
"upgrades": {
"Normal upgrade path": "Lock and optionally delegate TORN in the [Governance contract](https://etherscan.io/address/0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce) → submit a proposal with at least **1.00 K TORN** → wait 1m 15s → vote for 5d (extended by 6h if the outcome changes during the last 1h) → pass with a simple majority and **100.00 K TORN** quorum → wait 2d → permissionless execution within 3d. The DAO controls protocol and periphery components, but cannot upgrade or modify existing pools.",
"Exit window": "**2d** for DAO-controlled changes — an accepted proposal remains timelocked for this period before it can be executed. Existing Tornado Cash pools are immutable and cannot be upgraded by the DAO."
},
"tokenGovernance": {
"Governance token": "`TORN`, 1 token = 1 vote, delegated. Total supply: **9.99 M TORN**, DAO-owned TORN (unavailable for voting): **4.73 M TORN**, staked for voting: **2.57 M TORN**, the rest is circulating supply.",
"Stake lock": "After voting or proposing, staked tokens are locked for **5d 6h** after proposal ends, preventing governance hopping.",
"Voting venue": "[Governance contract](https://etherscan.io/address/0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce) on Ethereum. Proposals are viewable on the voting tab of the frontend, see the note on secure frontend above.",
"Proposal threshold": "**1.00 K TORN** locked in governance.",
"Quorum": "**100.00 K TORN**, with a simple majority required for acceptance.",
"Execution model": "**Permissionless execution after an onchain vote and timelock.** An accepted proposal waits 2d and can then be executed by anyone within 3d. Proposal executable payload is committed in the `propose()` transaction."
}
}
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "recipient",
"text": "Hides which registered recipient a stealth payment is for. The payer knows; sender, asset, amount and where the funds go next are public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Announcements mark each stealth payment but not the recipient whose keys were used. The registry publishes the candidate recipients and their key history.",
"exposureShort": "Announcements mark each stealth payment but not the recipient whose keys were used.",
"exposureContinued": "The registry publishes the candidate recipients and their key history.",
"advice": "Withdraw to a fresh address with no ENS name or prior activity, through the token relayer so your known wallet never funds the stealth address for gas. Keep funds from different stealth addresses apart.",
"sources": [
{
"contract": "Umbra",
"title": "Announcement, tokenPayments and TokenWithdrawal expose the fund path"
},
{
"contract": "StealthKeyRegistry",
"title": "StealthKeyChanged publishes recipients and key changes"
},
{
"title": "Recipient matching decrypts locally and checks the stealth address",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/umbra-js/src/classes/Umbra.ts#L704-L720"
}
],
"id": "publicObserver",
"value": "Recipient private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "Protocol use is public once a payment is announced, which narrows the anonymity set to registered recipients. Withdrawals to registered addresses, round trips back to the sender and a shared collecting address reveal or cluster recipients; membership alone does not identify them. The client withdraws one stealth address at a time and never merges them.",
"exposureShort": "Protocol use is public once a payment is announced, which narrows the anonymity set to registered recipients.",
"exposureContinued": "Withdrawals to registered addresses, round trips back to the sender and a shared collecting address reveal or cluster recipients; membership alone does not identify them. The client withdraws one stealth address at a time and never merges them.",
"advice": "Keep withdrawal destinations separate across payments and chains, and check that timing, amounts or recurring counterparties do not reconnect them to an identified account.",
"sources": [
{
"title": "Sections 6–7: reuse heuristics, false positives and historical evaluation",
"url": "https://arxiv.org/html/2308.01703v2#S6"
},
{
"title": "Table 2: denominator is withdrawn payments; section 7.4: no fee matches",
"url": "https://arxiv.org/html/2308.01703v2#S7"
},
{
"title": "Client warns on linked destinations, but allows proceeding",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/components/AccountReceiveTable.vue#L671-L715"
}
],
"id": "chainAnalyst",
"value": "Recipient at risk",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "warning",
"exposure": "On the payer's side the wallet RPC resolves the recipient, reads their registry entry and broadcasts the stealth payment seconds apart, so that provider can pair the payment with the recipient. On your side the wallet RPC receives the matched stealth-address balance batch, while a build-configured mainnet RPC looks up your connected wallet and the senders of matched payments, and withdrawal destinations are checked against ENS, POAP and Gitcoin APIs.",
"exposureShort": "On the payer's side the wallet RPC resolves the recipient, reads their registry entry and broadcasts the stealth payment seconds apart, so that provider can pair the payment with the recipient.",
"exposureContinued": "On your side the wallet RPC receives the matched stealth-address balance batch, while a build-configured mainnet RPC looks up your connected wallet and the senders of matched payments, and withdrawal destinations are checked against ENS, POAP and Gitcoin APIs.",
"advice": "Run an inspected local build with every RPC pointed at your own node and the external name and safety lookups disabled. Send broadcasts and relay requests over Tor.",
"sources": [
{
"title": "Payer flow: registry lookup and send through the wallet provider",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/pages/AccountSend.vue#L955-L1059"
},
{
"title": "The wallet provider wraps the connected wallet",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/store/wallet.ts#L262-L267"
},
{
"title": "Mainnet and Polygon RPCs are configured separately from the wallet",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/utils/constants.ts#L1-L17"
},
{
"title": "Connected-wallet name lookup uses MAINNET_PROVIDER",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/store/wallet.ts#L336-L358"
},
{
"title": "Matched senders go to mainnet name lookup; stealth balances to wallet RPC",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/components/AccountReceiveTable.vue#L584-L626"
},
{
"title": "Withdrawal checks send destination to ENS, POAP and Gitcoin lookups",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/utils/address.ts#L255-L319"
},
{
"title": "Signed relay request carries stealthAddr and acceptor",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/components/AccountReceiveTable.vue#L758-L768"
}
],
"id": "networkObserver",
"value": "Recipient at risk",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "good",
"exposure": "The contracts are immutable and give no administrator a viewing key or a way to replace registered keys without the registrant. The client matches announcements locally, so no indexer or relayer has a protocol-wide view.",
"exposureShort": "The contracts are immutable and give no administrator a viewing key or a way to replace registered keys without the registrant.",
"exposureContinued": "The client matches announcements locally, so no indexer or relayer has a protocol-wide view.",
"advice": "Run an inspected local build of the client instead of the hosted frontend.",
"sources": [
{
"contract": "Umbra",
"title": "Owner sets toll, tollCollector and tollReceiver; withdrawals require authorization"
},
{
"contract": "StealthKeyRegistry",
"title": "Direct registration or registrant-authorized signature, no admin override"
},
{
"title": "Viewing-key decryption is local to the client",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/umbra-js/src/classes/Umbra.ts#L704-L720"
},
{
"title": "Relay API receives signed withdrawal data, not a viewing key",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/frontend/src/utils/umbra-api.ts#L96-L111"
}
],
"id": "privilegedInsider",
"value": "Recipient private",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "Each announcement stores the ephemeral public key and the encrypted scalar. A quantum computer that breaks secp256k1 decrypts the scalar against every registered viewing key and checks which spending key yields the stealth address, identifying the recipient of every past payment.",
"exposureShort": "Each announcement stores the ephemeral public key and the encrypted scalar.",
"exposureContinued": "A quantum computer that breaks secp256k1 decrypts the scalar against every registered viewing key and checks which spending key yields the stealth address, identifying the recipient of every past payment.",
"sources": [
{
"contract": "Umbra",
"title": "Announcement archives pkx and ciphertext"
},
{
"contract": "StealthKeyRegistry",
"title": "Historical public viewing and spending keys"
},
{
"title": "ECDH-derived hash encrypts the scalar by XOR",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/umbra-js/src/classes/KeyPair.ts#L121-L157"
},
{
"title": "Recovered scalar is checked against the receiving address",
"url": "https://github.com/ScopeLift/umbra-protocol/blob/a81df24e76a0d6ab1ec79c6353e28c527b1b1a80/umbra-js/src/classes/Umbra.ts#L704-L720"
}
],
"id": "futureAdversary",
"value": "Recipient exposed",
"alsoExposed": []
}
}
},
"attributes": [
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
},
{
"id": "stealthAddresses",
"label": "Stealth addresses",
"description": "Uses fresh, one-time recipient addresses to obscure who controls the receiving address."
}
],
"category": {
"id": "stealthAddress",
"label": "Stealth address",
"description": "Payments land on fresh one-time addresses. Hides which recipient a payment is for."
},
"exitWindow": {
"value": "Infinite",
"sentiment": "good",
"orderHint": 9007199254740991,
"description": "The core contracts are immutable. The owner can change the toll for future payments, but cannot stop recipients from accessing payments that have already been sent.",
"walkawayTest": {
"passed": true
}
},
"reproducibility": {
"value": "Reproducible",
"sentiment": "good",
"description": "The immutable core contracts, cryptographic library, and frontend are published and can be built and run locally."
},
"riskSummary": "## Funds can be lost if\n1. an unsupported ERC-20, such as a fee-on-transfer or rebasing token, causes the Umbra contract's internal accounting to diverge from its token balance.\n
\n## Privacy can be lost if\n1. a recipient sends funds from a stealth address to a publicly linked address or consolidates payments in a recognizable way.\n2. public timing, amount, token, or ENS registration patterns let an observer narrow down the possible recipient.\n
\n## New payments can be stopped if\n1. the Umbra owner sets an arbitrarily high toll for contract-routed payments.",
"tokens": [
{
"token": {
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"iconUrl": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996",
"symbol": "DAI",
"decimals": 18,
"priceId": "dai",
"sinceTimestamp": 1619813937
},
"buckets": [
{
"id": "umbra-DAI",
"type": "pool",
"label": "DAI",
"address": "eth:0xFb2dc580Eed955B528407b4d36FfaFe3da685401",
"sinceTimestamp": 1619813937,
"deposit": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
},
"withdrawal": {
"event": "0x30eb3583ad09933b693a45452ab07512244cdbc5868701aa004c27b7b267c249",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
}
}
]
},
{
"token": {
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"iconUrl": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"symbol": "ETH",
"decimals": 18,
"priceId": "ethereum",
"sinceTimestamp": 1619813937
},
"buckets": [
{
"id": "umbra-ETH",
"type": "pool",
"label": "ETH",
"address": "eth:0xFb2dc580Eed955B528407b4d36FfaFe3da685401",
"sinceTimestamp": 1619813937,
"deposit": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
}
},
"withdrawal": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
}
}
}
]
},
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1619813937
},
"buckets": [
{
"id": "umbra-USDC",
"type": "pool",
"label": "USDC",
"address": "eth:0xFb2dc580Eed955B528407b4d36FfaFe3da685401",
"sinceTimestamp": 1619813937,
"deposit": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
},
"withdrawal": {
"event": "0x30eb3583ad09933b693a45452ab07512244cdbc5868701aa004c27b7b267c249",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1619813937
},
"buckets": [
{
"id": "umbra-USDT",
"type": "pool",
"label": "USDT",
"address": "eth:0xFb2dc580Eed955B528407b4d36FfaFe3da685401",
"sinceTimestamp": 1619813937,
"deposit": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
},
"withdrawal": {
"event": "0x30eb3583ad09933b693a45452ab07512244cdbc5868701aa004c27b7b267c249",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}
}
}
]
},
{
"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": 1619813937
},
"buckets": [
{
"id": "umbra-WBTC",
"type": "pool",
"label": "WBTC",
"address": "eth:0xFb2dc580Eed955B528407b4d36FfaFe3da685401",
"sinceTimestamp": 1619813937,
"deposit": {
"event": "0x29877766fa2bfe3b90008d6d92f965eca91cbc5757ed775740e460799fb92219",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
},
"withdrawal": {
"event": "0x30eb3583ad09933b693a45452ab07512244cdbc5868701aa004c27b7b267c249",
"extractor": "umbraAmount",
"params": {
"tokenAddress": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"
}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Umbra has no governance process or contract upgrade mechanism. The Umbra and StealthKeyRegistry contracts are immutable.\n\nThe Umbra contract has a permissioned owner that can immediately set the ETH toll charged on every contract-routed payment and change the addresses that collect and receive those tolls. Because the toll has no upper bound, the owner can effectively stop new payments through the Umbra contract at any time. The owner cannot change the payment or withdrawal logic and cannot prevent recipients from accessing payments already sent to them, so the exit window is infinite and the protocol passes the walkaway test."
}
}
+13 -7
+13 -7
{
"adversaries": {
"promise": {
"protects": "amount",
"text": "Hides transfer amounts. Who pays whom, and every wrap and unwrap amount, is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Only the amount of a confidential transfer is hidden. Sender, recipient, every wrap and unwrap amount and the ciphertext handles are public, and either party can later disclose a transfer amount onchain.",
"sentiment": "warning",
"exposureShort": "Only the amount of a confidential transfer is hidden.",
"exposureContinued": "Sender, recipient, every wrap and unwrap amount and the ciphertext handles are public, and either party can later disclose a transfer amount onchain.",
"advice": "Keep funds wrapped and transfer often, even zero amounts. Unwrap only after a while, and never an amount that matches a recent wrap or a known payment.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "private",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "ConfidentialUSDCWrapper"
},
{
"title": "Failed transfer moves an encrypted zero",
"url": "https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/blob/23ba15402346027f2416667acbb1e741179f8485/contracts/token/ERC7984/ERC7984.sol#L336-L352"
},
{
"title": "Unwrap makes the burned amount publicly decryptable",
"url": "https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/blob/23ba15402346027f2416667acbb1e741179f8485/contracts/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol#L262-L268"
},
{
"title": "Either party can request disclosure of a transfer amount",
"url": "https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/blob/23ba15402346027f2416667acbb1e741179f8485/contracts/token/ERC7984/ERC7984.sol#L202-L209"
}
],
"id": "publicObserver",
"value": "Amounts private",
"value": "Amounts at risk",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "All wraps and unwraps are public, so an account's balance is bounded by what went in and out, and exact for any account that never made a confidential transfer. Transfer partners and timing are public, so a wrap, a transfer and an unwrap in a row pair up by amount.",
"exposureShort": "All wraps and unwraps are public, so an account's balance is bounded by what went in and out, and exact for any account that never made a confidential transfer.",
"exposureContinued": "Transfer partners and timing are public, so a wrap, a transfer and an unwrap in a row pair up by amount.",
"advice": "Keep funds wrapped and transfer often, even zero amounts. Unwrap only after a while, and never an amount that matches a recent wrap or a known payment.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": {
"verdict": "atRisk",
"note": "Bounded by public wrap and unwrap totals; exact for accounts without confidential transfers."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "ConfidentialUSDCWrapper"
},
{
"title": "Wrap event carries the clear rounded amount",
"url": "https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/blob/23ba15402346027f2416667acbb1e741179f8485/contracts/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol#L256"
},
{
"title": "ERC-7984: public sender, recipient and handle per transfer",
"url": "https://eips.ethereum.org/EIPS/eip-7984"
}
],
"id": "chainAnalyst",
"value": "Amounts at risk",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "good",
"exposure": "Amounts are encrypted on your device and never leave it in clear. The default hosted relayer, which needs an operator API key, receives your address and the token contract with every encrypted input and balance view, so it learns who transacts and when, plus your IP.",
"exposureShort": "Amounts are encrypted on your device and never leave it in clear.",
"exposureContinued": "The default hosted relayer receives your address and the token contract with every encrypted input and balance view, so it learns who transacts and when, plus your IP.",
"advice": "Route relayer requests through Tor, or self-host the relayer.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": "private",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Hosted relayer URL",
"url": "https://github.com/zama-ai/relayer-sdk/blob/d06f1e585a78181135cb602109e5fa3da523b48d/src/configs.ts#L7"
},
{
"title": "Encrypted input bound to user and contract address",
"url": "https://github.com/zama-ai/relayer-sdk/blob/d06f1e585a78181135cb602109e5fa3da523b48d/src/relayer/sendEncryption.ts#L136-L145"
},
{
"title": "Balance view request carries user address and handles",
"url": "https://github.com/zama-ai/relayer-sdk/blob/d06f1e585a78181135cb602109e5fa3da523b48d/src/relayer/userDecrypt.ts#L288-L297"
},
{
"title": "Mainnet relayer needs an API key",
"url": "https://docs.zama.org/protocol/sdk/guides/relayer-api-keys"
},
{
"title": "Self-hosting a relayer",
"url": "https://github.com/zama-ai/fhevm/blob/94f1f3b35c71175dc68bb36887e0525f7c5d80c5/relayer/docs/SELF_HOSTING.md"
}
],
"id": "networkObserver",
"value": "Amounts private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "KMS operators share one FHE key under a threshold and can collude to decrypt every balance and transfer ever made. The token owner can appoint an observer with a never-expiring view of all balances and amounts, and can upgrade the token and the ACL, all with no delay.",
"exposureShort": "KMS operators share one FHE key under a threshold and can collude to decrypt every balance and transfer ever made.",
"exposureContinued": "The token owner can appoint an observer with a never-expiring view of all balances and amounts, and can upgrade the token and the ACL, all with no delay.",
"advice": "Watch for ObserverAdded events and upgrades on your token; there is no delay to react. Nothing you do prevents KMS collusion.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": {
"verdict": "exposed",
"note": "To colluding KMS operators, any owner-appointed observer, or the owner via upgrade."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"contract": "ConfidentialUSDCWrapper",
"title": "Wrapper (addObserver, blockUser, upgrade)"
},
{
"contract": "ProtocolConfig",
"title": "KMS signers and thresholds"
},
{
"contract": "ACL",
"title": "Access control the KMS honors"
},
{
"section": "permissions"
},
{
"title": "Observer gets a wildcard delegation without expiration",
"url": "https://github.com/zama-ai/protocol-apps/blob/85eef95c797da20875fe7eeae7f8d212d760486f/contracts/confidential-wrapper/contracts/ConfidentialWrapper.sol#L395-L403"
},
{
"title": "Wrapper upgrade authorized by the owner alone",
"url": "https://github.com/zama-ai/protocol-apps/blob/85eef95c797da20875fe7eeae7f8d212d760486f/contracts/confidential-wrapper/contracts/ConfidentialWrapper.sol#L497"
},
{
"title": "ACL upgrade authorized by the owner alone",
"url": "https://github.com/zama-ai/fhevm/blob/94f1f3b35c71175dc68bb36887e0525f7c5d80c5/host-contracts/contracts/ACL.sol#L654"
},
{
"title": "13 KMS parties with threshold t = 4",
"url": "https://github.com/zama-ai/kms/blob/b5cd5cf465dc488ff04ac8c19f3ef12877abffa0/ai-docs/ARCHITECTURE.md#L22-L23"
},
{
"title": "Shamir sharing with t < n/3 (TKMS announcement)",
"url": "https://www.zama.ai/post/introducing-zama-threshold-key-management-system-tkms"
}
],
"id": "privilegedInsider",
"value": "Amounts exposed",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "warning",
"exposure": "The encryption is lattice-based and survives quantum computers, but every ciphertext is publicly downloadable and one long-lived key protects them all. If enough key shares ever leak, the entire history is exposed.",
"exposureShort": "The encryption is lattice-based and survives quantum computers, but every ciphertext is publicly downloadable and one long-lived key protects them all.",
"exposureContinued": "If enough key shares ever leak, the entire history is exposed.",
"interior": {
"sender": "exposed",
"recipient": "exposed",
"amount": {
"verdict": "atRisk",
"note": "Lattice cryptography, but one long-lived key."
},
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Coprocessor ciphertext store (public listing)",
"url": "https://coprocessor-1.mainnet.zama.org/?max-keys=3"
},
{
"title": "ML-KEM hybrid encryption of decryption shares",
"url": "https://github.com/zama-ai/kms/blob/b5cd5cf465dc488ff04ac8c19f3ef12877abffa0/core/service/src/cryptography/hybrid_ml_kem.rs"
},
{
"title": "Key resharing and key switching in the KMS",
"url": "https://docs.zama.org/protocol/protocol/overview/kms"
}
],
"id": "futureAdversary",
"value": "Amounts at risk",
"alsoExposed": []
}
}
},
"anonymitySet": {
"type": "not-applicable",
"description": "Zama confidential tokens hide amounts, but sender and receiver addresses remain public and are not mixed in a shared anonymity set."
},
"attributes": [
{
"id": "fhe",
"label": "FHE",
"description": "Uses fully homomorphic encryption for private computation over encrypted values."
},
{
"id": "privateAmounts",
"label": "Private amounts",
"description": "Transfer amounts are private, while sender and recipient addresses remain public."
},
{
"id": "anyAmount",
"label": "Any amount",
"description": "Deposits and withdrawals can have any size."
},
{
"id": "defi",
"label": "DeFi",
"description": "Interop with DeFi (swaps, vaults) from within the confidential token."
}
],
"category": {
"id": "confidentialAmounts",
"label": "Confidential amounts",
"description": "Accounts and counterparties are public, balances and transfer amounts are encrypted."
},
"exitWindow": {
"value": "None",
"sentiment": "bad",
"orderHint": 0,
"description": "The confidential token contracts and system contracts are upgradeable without an onchain delay, so users do not get a guaranteed withdrawal window before changes take effect.",
"walkawayTest": {
"passed": false,
"reason": "Only KMS 7/13 multisig members can decrypt FHE ciphertext. Also, FHE coprocessor operator is currently essential for protocol liveness."
}
},
"quantumResistant": true,
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The smart contracts are source-available, but users also rely on offchain FHE execution and threshold decryption services whose outputs are accepted onchain through signature verification. The offchain data cannot currently be fully reproduced from Ethereum DA."
},
"riskSummary": "## Funds can be stolen if\n1. a malicious upgrade compromises the confidential token contracts or FHEVM contracts with their escrowed underlying tokens.\n2. the threshold of the current or any non-destroyed historical Ethereum KMS context attests an inflated unwrap amount, allowing pooled underlying deposited before or after that context existed to be released. Governance can also install a malicious context or lower the threshold of any live context in place; 7/13 describes only the current context.\n3. the 1/1 coprocessor input verification path accepts invalid encrypted inputs that bypass confidential balance checks.\n
\n## Funds can be lost if\n1. an underlying token admin blacklists a confidential token address or otherwise prevents transfers from the contract.\n2. a user is blocked by the confidential token owner or by a configured underlying-token denylist before finalization/withdrawal.\n3. a confidential token is paused by an owner-appointed pauser and not unpaused by the owner, halting confidential transfers, unwrap requests, and unwrap finalization (no pauser is currently set on any confidential token).\n4. offchain ciphertext data required by the coprocessor or KMS for encrypted handles becomes unavailable and cannot be reconstructed.\n
\n## Privacy can be lost if\n1. enough KMS operators with usable key shares collude or are compromised and decrypt private ciphertext handles. 7/13 describes only the current verifier context, while retained contexts can have different memberships and thresholds.\n2. the confidential token owner appoints an observer: observers receive a wildcard, non-expiring user-decryption delegation over all of that token's encrypted handles and can decrypt its balances and transfer amounts (no observers are currently configured on any confidential token).\n3. the offchain coprocessor, wallet, relayer, frontend, or RPC path records enough metadata to link a user to encrypted inputs or transactions.\n4. deposits and withdrawals are linked by clear boundary amounts, recipient graph, timing, or address reuse.",
"tokens": [
{
"token": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"iconUrl": "https://assets.coingecko.com/coins/images/6319/large/usdc.png?1696506694",
"symbol": "USDC",
"decimals": 6,
"priceId": "usd-coin",
"sinceTimestamp": 1766750819
},
"buckets": [
{
"id": "zama-cw-cUSDC",
"type": "pool",
"label": "cUSDC token",
"address": "eth:0xe978F22157048E5DB8E5d07971376e86671672B2",
"sinceTimestamp": 1766750819,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xe978F22157048E5DB8E5d07971376e86671672B2"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xe978F22157048E5DB8E5d07971376e86671672B2"
}
}
}
]
},
{
"token": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"iconUrl": "https://assets.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "USDT",
"decimals": 6,
"priceId": "tether",
"sinceTimestamp": 1766750831
},
"buckets": [
{
"id": "zama-cw-cUSDT",
"type": "pool",
"label": "cUSDT token",
"address": "eth:0xAe0207C757Aa2B4019Ad96edD0092ddc63EF0c50",
"sinceTimestamp": 1766750831,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xAe0207C757Aa2B4019Ad96edD0092ddc63EF0c50"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xAe0207C757Aa2B4019Ad96edD0092ddc63EF0c50"
}
}
}
]
},
{
"token": {
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"iconUrl": "https://assets.coingecko.com/coins/images/2518/large/weth.png?1696503332",
"symbol": "WETH",
"decimals": 18,
"priceId": "weth",
"sinceTimestamp": 1766750843
},
"buckets": [
{
"id": "zama-cw-cWETH",
"type": "pool",
"label": "cWETH token",
"address": "eth:0xda9396b82634Ea99243cE51258B6A5Ae512D4893",
"sinceTimestamp": 1766750843,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xda9396b82634Ea99243cE51258B6A5Ae512D4893"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xda9396b82634Ea99243cE51258B6A5Ae512D4893"
}
}
}
]
},
{
"token": {
"address": "0xA12CC123ba206d4031D1c7f6223D1C2Ec249f4f3",
"iconUrl": "https://coin-images.coingecko.com/coins/images/70921/large/zama.png?1764591992",
"symbol": "ZAMA",
"decimals": 18,
"priceId": "zama",
"sinceTimestamp": 1766750867
},
"buckets": [
{
"id": "zama-cw-cZAMA",
"type": "pool",
"label": "cZAMA token",
"address": "eth:0x80CB147Fd86dC6dEe3Eee7e4Cee33d1397d98071",
"sinceTimestamp": 1766750867,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x80CB147Fd86dC6dEe3Eee7e4Cee33d1397d98071"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x80CB147Fd86dC6dEe3Eee7e4Cee33d1397d98071"
}
}
}
]
},
{
"token": {
"address": "0x27f6c8289550fCE67f6B50BeD1F519966aFE5287",
"iconUrl": "https://coin-images.coingecko.com/coins/images/70647/large/tgbp-square.png?1762953800",
"symbol": "tGBP",
"decimals": 18,
"priceId": "tokenised-gbp",
"sinceTimestamp": 1767000887
},
"buckets": [
{
"id": "zama-cw-ctGBP",
"type": "pool",
"label": "ctGBP token",
"address": "eth:0xa873750ccBafD5ec7Dd13bfD5237d7129832eDD9",
"sinceTimestamp": 1767000887,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xa873750ccBafD5ec7Dd13bfD5237d7129832eDD9"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xa873750ccBafD5ec7Dd13bfD5237d7129832eDD9"
}
}
}
]
},
{
"token": {
"address": "0x68749665FF8D2d112Fa859AA293F07A622782F38",
"iconUrl": "https://assets.coingecko.com/coins/images/10481/large/Tether_Gold.png?1696510471",
"symbol": "XAUt",
"decimals": 6,
"priceId": "tether-gold",
"sinceTimestamp": 1772116091
},
"buckets": [
{
"id": "zama-cw-cXAUt",
"type": "pool",
"label": "cXAUt token",
"address": "eth:0x73cc9aF9d6BEFdb3c3fAf8a5E8c05Cb95FdaEEf1",
"sinceTimestamp": 1772116091,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x73cc9aF9d6BEFdb3c3fAf8a5E8c05Cb95FdaEEf1"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x73cc9aF9d6BEFdb3c3fAf8a5E8c05Cb95FdaEEf1"
}
}
}
]
},
{
"token": {
"address": "0xbeeffABcd0dB09589Dd21854aa760C52aB4bf04F",
"iconUrl": "https://coin-images.coingecko.com/coins/images/70647/large/tgbp-square.png?1762953800",
"symbol": "bbqTGBP",
"decimals": 18,
"priceId": "tokenised-gbp",
"sinceTimestamp": 1780585031
},
"buckets": [
{
"id": "zama-cw-cbbqTGBP",
"type": "pool",
"label": "cbbqTGBP token",
"address": "eth:0xBA4cFF6ED6F7Cb2A58776dECa4E984b498446762",
"sinceTimestamp": 1780585031,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xBA4cFF6ED6F7Cb2A58776dECa4E984b498446762"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xBA4cFF6ED6F7Cb2A58776dECa4E984b498446762"
}
}
}
]
},
{
"token": {
"address": "0xbEEF00A59B577423653A1526c7009bdE103F542B",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "steakcUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1781877707
},
"buckets": [
{
"id": "zama-cw-csteakcUSDC",
"type": "pool",
"label": "csteakcUSDC token",
"address": "eth:0x66Bf74E96900D1a19c7070D939D124f2F565C458",
"sinceTimestamp": 1781877707,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x66Bf74E96900D1a19c7070D939D124f2F565C458"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x66Bf74E96900D1a19c7070D939D124f2F565C458"
}
}
}
]
},
{
"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": 1789148087
},
"buckets": [
{
"id": "zama-cw-cWBTC",
"type": "pool",
"label": "cWBTC token",
"address": "eth:0xd86aE89C089B380f064Fe01899B4071F1eb6Bb3d",
"sinceTimestamp": 1789148087,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xd86aE89C089B380f064Fe01899B4071F1eb6Bb3d"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xd86aE89C089B380f064Fe01899B4071F1eb6Bb3d"
}
}
}
]
},
{
"token": {
"address": "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39284/large/AUSD_1024px.png?1764684132",
"symbol": "AUSD",
"decimals": 6,
"priceId": "agora-dollar",
"sinceTimestamp": 1789146719
},
"buckets": [
{
"id": "zama-cw-cAUSD",
"type": "pool",
"label": "cAUSD token",
"address": "eth:0xEa9A15A29DD180c40442142CaeEfC491d37bfDB2",
"sinceTimestamp": 1789146719,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xEa9A15A29DD180c40442142CaeEfC491d37bfDB2"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xEa9A15A29DD180c40442142CaeEfC491d37bfDB2"
}
}
}
]
},
{
"token": {
"address": "0x808507121B80c02388fAd14726482e061B8da827",
"iconUrl": "https://assets.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728",
"symbol": "PENDLE",
"decimals": 18,
"priceId": "pendle",
"sinceTimestamp": 1789150991
},
"buckets": [
{
"id": "zama-cw-cPENDLE",
"type": "pool",
"label": "cPENDLE token",
"address": "eth:0x8900123F7e17709C1D80eda1E611A9503Cf1B3df",
"sinceTimestamp": 1789150991,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x8900123F7e17709C1D80eda1E611A9503Cf1B3df"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x8900123F7e17709C1D80eda1E611A9503Cf1B3df"
}
}
}
]
},
{
"token": {
"address": "0xbeef003C68896c7D2c3c60d363e8d71a49Ab2bf9",
"iconUrl": "https://coin-images.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "steakUSDT",
"decimals": 18,
"priceId": "tether",
"sinceTimestamp": 1789152239
},
"buckets": [
{
"id": "zama-cw-csteakUSDT",
"type": "pool",
"label": "csteakUSDT token",
"address": "eth:0x1F6A937119c0c34Db0a2c4F000386a3BfD4A9e73",
"sinceTimestamp": 1789152239,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x1F6A937119c0c34Db0a2c4F000386a3BfD4A9e73"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x1F6A937119c0c34Db0a2c4F000386a3BfD4A9e73"
}
}
}
]
},
{
"token": {
"address": "0xbeeff07d991C04CD640DE9F15C08ba59c4FEDEb7",
"iconUrl": "https://coin-images.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "bbqUSDT",
"decimals": 18,
"priceId": "tether",
"sinceTimestamp": 1789152695
},
"buckets": [
{
"id": "zama-cw-cbbqUSDT",
"type": "pool",
"label": "cbbqUSDT token",
"address": "eth:0x80Ae7dbCe3c1696d3eeD04Ec8348c3C432322273",
"sinceTimestamp": 1789152695,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x80Ae7dbCe3c1696d3eeD04Ec8348c3C432322273"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x80Ae7dbCe3c1696d3eeD04Ec8348c3C432322273"
}
}
}
]
},
{
"token": {
"address": "0xbeeff2C5bF38f90e3482a8b19F12E5a6D2FCa757",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "bbqUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789153067
},
"buckets": [
{
"id": "zama-cw-cbbqUSDC",
"type": "pool",
"label": "cbbqUSDC token",
"address": "eth:0x501b014f86a73A7199E00cB31C0e9565Ac51e51B",
"sinceTimestamp": 1789153067,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x501b014f86a73A7199E00cB31C0e9565Ac51e51B"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x501b014f86a73A7199E00cB31C0e9565Ac51e51B"
}
}
}
]
},
{
"token": {
"address": "0x3d5EcCb62974178236A768A7ef14D3ce468Fbe91",
"iconUrl": "https://coin-images.coingecko.com/coins/images/7598/large/WBTCLOGO.png?1764496367",
"symbol": "armcWBTC",
"decimals": 18,
"priceId": "wrapped-bitcoin",
"sinceTimestamp": 1789148987
},
"buckets": [
{
"id": "zama-cw-carmcWBTC",
"type": "pool",
"label": "carmcWBTC token",
"address": "eth:0xF921A5B0634f4236B21A4e948317abf9a2E86B6f",
"sinceTimestamp": 1789148987,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xF921A5B0634f4236B21A4e948317abf9a2E86B6f"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xF921A5B0634f4236B21A4e948317abf9a2E86B6f"
}
}
}
]
},
{
"token": {
"address": "0x500aE64100D7DbDb640531085C2F5d40cDC8930D",
"iconUrl": "https://coin-images.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "armUSDTs",
"decimals": 18,
"priceId": "tether",
"sinceTimestamp": 1789150187
},
"buckets": [
{
"id": "zama-cw-carmUSDTs",
"type": "pool",
"label": "carmUSDTs token",
"address": "eth:0xbaC6DeDf2C10D6D381F9DBd9EFd69D93FfCef50B",
"sinceTimestamp": 1789150187,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xbaC6DeDf2C10D6D381F9DBd9EFd69D93FfCef50B"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xbaC6DeDf2C10D6D381F9DBd9EFd69D93FfCef50B"
}
}
}
]
},
{
"token": {
"address": "0xA2EAaD0D586cF9FD73bb2c09cF6A7E3e187D68cd",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "armUSDCs",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789151411
},
"buckets": [
{
"id": "zama-cw-carmUSDCs",
"type": "pool",
"label": "carmUSDCs token",
"address": "eth:0x77F8207ee451441336538bA07a2F425780dED8DB",
"sinceTimestamp": 1789151411,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x77F8207ee451441336538bA07a2F425780dED8DB"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x77F8207ee451441336538bA07a2F425780dED8DB"
}
}
}
]
},
{
"token": {
"address": "0xBf29043164660C60A2a72Cd15FFe2304e87B6838",
"iconUrl": "https://coin-images.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "armUSDTp",
"decimals": 18,
"priceId": "tether",
"sinceTimestamp": 1789153331
},
"buckets": [
{
"id": "zama-cw-carmUSDTp",
"type": "pool",
"label": "carmUSDTp token",
"address": "eth:0x63a60aCC304b84eF829b263f28e7b636Bf77d45A",
"sinceTimestamp": 1789153331,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x63a60aCC304b84eF829b263f28e7b636Bf77d45A"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x63a60aCC304b84eF829b263f28e7b636Bf77d45A"
}
}
}
]
},
{
"token": {
"address": "0x5dc53a23AdC9f2Bed98de6F59F7F309a7c71FF2B",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "armUSDCp",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789150751
},
"buckets": [
{
"id": "zama-cw-carmUSDCp",
"type": "pool",
"label": "carmUSDCp token",
"address": "eth:0x2ebBd099f66b0ca94DD82B4c06fe3eEf6AFf853c",
"sinceTimestamp": 1789150751,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x2ebBd099f66b0ca94DD82B4c06fe3eEf6AFf853c"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x2ebBd099f66b0ca94DD82B4c06fe3eEf6AFf853c"
}
}
}
]
},
{
"token": {
"address": "0x55C1B6e461a6334B567bAF0FEb5D728715446f05",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "pendleUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789150499
},
"buckets": [
{
"id": "zama-cw-cpendleUSDC",
"type": "pool",
"label": "cpendleUSDC token",
"address": "eth:0xb6e5299fc56053DD5440104Fd6Fd2A3CD064edbC",
"sinceTimestamp": 1789150499,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xb6e5299fc56053DD5440104Fd6Fd2A3CD064edbC"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xb6e5299fc56053DD5440104Fd6Fd2A3CD064edbC"
}
}
}
]
},
{
"token": {
"address": "0x32401B9fb79065Bc15949DE0BD43927492f02F0C",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39284/large/AUSD_1024px.png?1764684132",
"symbol": "fAUSDe",
"decimals": 18,
"priceId": "agora-dollar",
"sinceTimestamp": 1789148387
},
"buckets": [
{
"id": "zama-cw-cfAUSDe",
"type": "pool",
"label": "cfAUSDe token",
"address": "eth:0x76A3f985315aAc9789Cb5BF8A5bb83BFF55FD5a6",
"sinceTimestamp": 1789148387,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x76A3f985315aAc9789Cb5BF8A5bb83BFF55FD5a6"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x76A3f985315aAc9789Cb5BF8A5bb83BFF55FD5a6"
}
}
}
]
},
{
"token": {
"address": "0xb48C056C5608bA2Ee4cD94AF2bF4b1F25295Bd7e",
"iconUrl": "https://coin-images.coingecko.com/coins/images/325/large/Tether.png?1696501661",
"symbol": "fcUSDT",
"decimals": 18,
"priceId": "tether",
"sinceTimestamp": 1789388567
},
"buckets": [
{
"id": "zama-cw-cfcUSDT",
"type": "pool",
"label": "cfcUSDT token",
"address": "eth:0xA28A369Df348ac232E4DAF7B0Ef90280d8707D7F",
"sinceTimestamp": 1789388567,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xA28A369Df348ac232E4DAF7B0Ef90280d8707D7F"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xA28A369Df348ac232E4DAF7B0Ef90280d8707D7F"
}
}
}
]
},
{
"token": {
"address": "0xc207d3f66537D7F66456808379A0E560cF20Da36",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "roxcUSDC",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789153955
},
"buckets": [
{
"id": "zama-cw-croxcUSDC",
"type": "pool",
"label": "croxcUSDC token",
"address": "eth:0xB1B18Ad1F16D744c470cb6B09Cb826AfFcc9EB30",
"sinceTimestamp": 1789153955,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0xB1B18Ad1F16D744c470cb6B09Cb826AfFcc9EB30"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0xB1B18Ad1F16D744c470cb6B09Cb826AfFcc9EB30"
}
}
}
]
},
{
"token": {
"address": "0xE0181090c22579B6A217f1522cbf8c9f1F0C1965",
"iconUrl": "https://coin-images.coingecko.com/coins/images/6319/large/USDC.png?1769615602",
"symbol": "roxUSDCy",
"decimals": 18,
"priceId": "usd-coin",
"sinceTimestamp": 1789154375
},
"buckets": [
{
"id": "zama-cw-croxUSDCy",
"type": "pool",
"label": "croxUSDCy token",
"address": "eth:0x4FCCF8046FB7FB7AB76321BD39C27453e396B88f",
"sinceTimestamp": 1789154375,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x4FCCF8046FB7FB7AB76321BD39C27453e396B88f"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x4FCCF8046FB7FB7AB76321BD39C27453e396B88f"
}
}
}
]
},
{
"token": {
"address": "0xB344e331A3cDa61D329fb3Cca2Be5942da87c418",
"iconUrl": "https://coin-images.coingecko.com/coins/images/39284/large/AUSD_1024px.png?1764684132",
"symbol": "PAPY",
"decimals": 18,
"priceId": "agora-dollar",
"sinceTimestamp": 1789151975
},
"buckets": [
{
"id": "zama-cw-cPAPY",
"type": "pool",
"label": "cPAPY token",
"address": "eth:0x9ABb8f3dC2863B1F108DeD7ea41902fEF6732A8c",
"sinceTimestamp": 1789151975,
"deposit": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"to": "0x9ABb8f3dC2863B1F108DeD7ea41902fEF6732A8c"
}
},
"withdrawal": {
"event": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"extractor": "erc20Transfer",
"params": {
"from": "0x9ABb8f3dC2863B1F108DeD7ea41902fEF6732A8c"
}
}
}
]
}
],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "Zama Confidential Tokens governance is implemented through an Aragon 'DAO' deployment controlled by two multisigs: ZamaGovMultisigA with a 9/17 threshold and ZamaGovMultisigB with a 3/6 threshold. The Gateway contracts are controlled separately by the SafeL2 multisig listed in the permissions section. These accounts can upgrade contracts or change critical configuration without a timelock. On the Gateway, the owner multisig can create and destroy KMS contexts, change the thresholds of any live context, and disable or remove registered host chains, halting Gateway workflows for those chains.\n\nConfidential token owners and underlying token owners can freeze users. Confidential token owners can further appoint a pauser that halts all confidential transfers, wrapping, and unwrapping of their token (only the owner can unpause), change or disable the underlying-token denylist hook, and appoint observers that gain wildcard decryption access to all balances and transfer amounts of their token. Currently, no pausers or observers are configured. The Ethereum ACL owner can manage ACL-level account blocking, unpause the ACL, change HCU limits, and — through the ProtocolConfig contract — create KMS contexts with arbitrary signer sets and thresholds, retune the thresholds of any live context (including the current one) in place, and trigger or abort FHE key- and CRS-generation in the KMSGeneration contract. A new context immediately becomes the default verifier authority and can attest unwrap amounts for assets deposited before it existed. Superseded contexts remain equally authoritative for all past and future ciphertext handles until the ACL owner explicitly destroys them; the current context cannot be destroyed. Changing an onchain KMS context changes only the accepted ECDSA credentials and does not trigger or verify resharing or destruction of the underlying FHE key shares.\n\nOffchain components like the coprocessor and KMS are trusted for liveness, privacy and security and are currently not decentralized."
}
}
+10 -5
+10 -5
{
"adversaries": {
"promise": {
"protects": "linkage",
"text": "Hides which funds leaving Ethereum come back as which, by passing through Zcash's shielded pool. Everything on Ethereum and NEAR is public."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Nothing ties the ZEC that enters the shielded pool to the ZEC that leaves it. Everything up to the pool edge is public: the Ethereum deposit, the NEAR ledger entries that credit, swap and withdraw it, and the Zcash address and amount of every payout, which the bridge encrypts so that anyone can decrypt them.",
"exposureShort": "Nothing ties the ZEC that enters the shielded pool to the ZEC that leaves it.",
"exposureContinued": "Everything up to the pool edge is public: the Ethereum deposit, the NEAR ledger entries that credit, swap and withdraw it, and the Zcash address and amount of every payout, which the bridge encrypts so that anyone can decrypt them.",
"advice": "Receive the ZEC straight into a fresh shielded address, as Zodl does per swap, and pay the return leg from the pool. The web app pays transparent addresses only, which adds a public shielding step.",
"interior": {
"sender": "private",
"recipient": {
"verdict": "atRisk",
"note": "Payout notes are decryptable by anyone, so a reused address ties payouts together."
},
"amount": "private",
"asset": {
"verdict": "exposed",
"note": "Only ZEC exists inside the pool; the assets swapped from and to are public on NEAR."
},
"linkage": "private"
},
"sources": [
{
"title": "Custodial bridge mint carries the Ethereum transaction hash in its memo",
"url": "https://nearblocks.io/address/eth.omft.near"
},
{
"title": "Withdrawal message names the target Zcash address",
"url": "https://github.com/Near-One/btc-bridge/blob/4711c2f1d035a208464b9729bb24e45ed9ab7831/contracts/satoshi-bridge/src/api/token_receiver.rs#L8-L16"
},
{
"title": "Payouts are encrypted to an all-zero outgoing viewing key",
"url": "https://github.com/Near-One/btc-bridge/blob/4711c2f1d035a208464b9729bb24e45ed9ab7831/contracts/satoshi-bridge/src/zcash_utils/orchard_policy.rs#L13-L63"
},
{
"title": "Zodl requests a fresh shielded address per swap",
"url": "https://github.com/zodl-inc/zodl-ios/blob/15f1eed4024d2c996b0d38c746d5aed235704a01/secant/Sources/Features/SwapAndPayForm/SwapAndPayStore.swift#L943"
},
{
"title": "Web app accepts transparent and TEX addresses only",
"url": "https://github.com/defuse-protocol/defuse-frontend/blob/752a7838d1e73b00e6965a9cb6a08af68b447e41/src/components/DefuseSDK/utils/validateAddress.ts#L131-L145"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "good",
"exposure": "The amount paid into the pool and the amount later sent to a bridge deposit address are both public with their timing, so a round trip of similar size within hours pairs them. Deposit addresses are fresh per quote but spent together with the bridge change address, so every exit is attributable to NEAR Intents.",
"exposureShort": "The amount paid into the pool and the amount later sent to a bridge deposit address are both public with their timing, so a round trip of similar size within hours pairs them.",
"exposureContinued": "Deposit addresses are fresh per quote but spent together with the bridge change address, so every exit is attributable to NEAR Intents.",
"advice": "Hold the ZEC in the pool for days, split or merge it with other shielded funds, and swap back amounts that match no payout.",
"interior": {
"sender": "private",
"recipient": "atRisk",
"amount": "private",
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "Round-trip amount and timing across the pool edge pair a payout with a later deposit."
}
},
"sources": [
{
"title": "Kappos et al., An Empirical Analysis of Anonymity in Zcash (USENIX 2018)",
"url": "https://arxiv.org/abs/1805.03180"
},
{
"title": "Deposit address derived per quote from the deposit message",
"url": "https://github.com/Near-One/btc-bridge/blob/4711c2f1d035a208464b9729bb24e45ed9ab7831/contracts/satoshi-bridge/src/deposit_msg.rs#L49-L52"
},
{
"title": "Bridge change address and UTXO set",
"url": "https://nearblocks.io/address/zcash-connector.bridge.near"
}
],
"id": "chainAnalyst",
"value": "Link private",
"alsoExposed": []
},
"networkObserver": {
"sentiment": "warning",
"exposure": "Zodl syncs through public lightwalletd servers, which see which transactions the wallet fetches and broadcasts, and so the payout and the later exit of the same wallet. Tor covers these calls and the swap requests including session isolation but is opt-in and does not cover block sync.",
"exposureShort": "Zodl syncs through public lightwalletd servers, which see which transactions the wallet fetches and broadcasts, and so the payout and the later exit of the same wallet.",
"exposureContinued": "Tor covers these calls and the swap requests including session isolation but is opt-in and does not cover block sync.",
"advice": "Turn on Tor in Zodl before the first swap.",
"interior": {
"sender": "private",
"recipient": "atRisk",
"amount": "private",
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "The lightwalletd server sees the wallet fetch the payout and later broadcast the exit."
}
},
"sources": [
{
"title": "Tor is off unless the user enables it",
"url": "https://github.com/zodl-inc/zodl-ios/blob/15f1eed4024d2c996b0d38c746d5aed235704a01/secant/Sources/Dependencies/SDKSynchronizer/SDKSynchronizerLive.swift#L28"
},
{
"title": "Default lightwalletd endpoint",
"url": "https://github.com/zodl-inc/zodl-ios/blob/15f1eed4024d2c996b0d38c746d5aed235704a01/secant/Sources/Dependencies/ZcashSDKEnvironment/ZcashSDKEnvironmentInterface.swift#L21"
},
{
"title": "Zashi 2.1: which calls Tor covers",
"url": "https://electriccoin.co/blog/zashi-2-1-enhanced-privacy-with-tor-beta/"
},
{
"title": "Hornby, Fixing Privacy Problems in the Zcash Light Wallet Protocol",
"url": "https://defuse.ca/downloads/Fixing%20Privacy%20Problems%20in%20the%20Zcash%20Light%20Wallet%20Protocol.pdf"
}
],
"id": "networkObserver",
"value": "Link at risk",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "The Operator runs the 1Click bridge API, the Ethereum custody and the screening, so both legs sit in its logs with the IP address and wallet identifiers of each request, plus the fresh Zcash refund address Zodl attaches to every swap out of ZEC. It has no key into the shielded pool, so joining the legs still needs IP or timing. It screens every address with KYT vendors, can lock any account and can hold bridged funds.",
"exposureShort": "The Operator runs the 1Click bridge API, the Ethereum custody and the screening, so both legs sit in its logs with the IP address and wallet identifiers of each request, plus the fresh Zcash refund address Zodl attaches to every swap out of ZEC.",
"exposureContinued": "It has no key into the shielded pool, so joining the legs still needs IP or timing. It screens every address with KYT vendors, can lock any account and can hold bridged funds.",
"advice": "Always use the Zodl Tor feature, wait some time in the shielded pool and use amounts that do not match.",
"interior": {
"sender": "private",
"recipient": "private",
"amount": "private",
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "IP address, partner key and timing of both legs sit in one operator's logs."
}
},
"sources": [
{
"title": "1Click terms: IP and wallet data, screening, freezes",
"url": "https://docs.near-intents.org/security-compliance/terms-of-service"
},
{
"title": "Screening providers",
"url": "https://docs.near-intents.org/security-compliance/risk-and-compliance"
},
{
"title": "Any account can be locked by DAO or locker role",
"url": "https://github.com/near/intents/blob/fa44ede9e874931c39a6c4246de82bc40f4f8d99/defuse/src/contract/accounts/force.rs#L21-L33"
},
{
"title": "Owner-only mint of the wrapped Ethereum assets",
"url": "https://github.com/near/intents/blob/fa44ede9e874931c39a6c4246de82bc40f4f8d99/poa-token/src/contract.rs#L79-L81"
},
{
"title": "Zodl sends its partner key and refund address with each quote",
"url": "https://github.com/zodl-inc/zodl-ios/blob/15f1eed4024d2c996b0d38c746d5aed235704a01/secant/Sources/Dependencies/SwapAndPay/sources/Near1Click.swift#L313-L344"
},
{
"section": "upgrades-and-governance"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": []
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "All of an account's rotated addresses share one incoming viewing key on the Pallas curve, and every payout address is public on NEAR. A quantum computer recovers that key from any one address and decrypts every note the account ever received, including the change notes of its exits, which joins both legs of every round trip. Ironwood's quantum-recoverable notes protect funds, not privacy.",
"exposureShort": "All of an account's rotated addresses share one incoming viewing key on the Pallas curve, and every payout address is public on NEAR.",
"exposureContinued": "A quantum computer recovers that key from any one address and decrypts every note the account ever received, including the change notes of its exits, which joins both legs of every round trip. Ironwood's quantum-recoverable notes protect funds, not privacy.",
"advice": "Use a separate Zodl account per round trip, so one recovered key exposes only that trip.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Spends are found through the change notes they pay back to the same account."
},
"recipient": "exposed",
"amount": "exposed",
"asset": "exposed",
"linkage": "exposed"
},
"sources": [
{
"title": "Orchard key agreement on the Pallas curve",
"url": "https://zips.z.cash/protocol/protocol.pdf#concreteorchardkeyagreement"
},
{
"title": "ZIP 2005: quantum recoverability, not quantum privacy",
"url": "https://zips.z.cash/zip-2005"
},
{
"title": "Payouts are encrypted to an all-zero outgoing viewing key",
"url": "https://github.com/Near-One/btc-bridge/blob/4711c2f1d035a208464b9729bb24e45ed9ab7831/contracts/satoshi-bridge/src/zcash_utils/orchard_policy.rs#L13-L63"
}
],
"id": "futureAdversary",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "atRisk"
},
{
"field": "recipient",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
}
]
}
}
},
"anonymitySet": {
"type": "not-applicable",
"description": "The anonymity set is Zcash's Ironwood shielded pool, which lives outside the chains L2BEAT indexes. Payout and deposit amounts are public at the pool edge, so the effective set behind an exit is the pool entries (public on NEAR) that could match it in amount and time."
},
"attributes": [
{
"id": "bridged",
"label": "Bridged",
"description": "Funds leave Ethereum through a bridge and gain their privacy on another chain."
},
{
"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": "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 Verifier can be upgraded at once by 4/5 NEAR Intents DAO members, the Zcash bridge by 3/5 Rainbow Bridge DAO members with no verified delay, and the Ethereum-side funds sit in an operator-controlled EOA, so there is no window to leave before a change takes effect.",
"walkawayTest": {
"passed": false,
"reason": "Ethereum deposits and withdrawals are executed off-chain by the custodial bridge operator, and Zcash withdrawals need a whitelisted relayer to trigger the MPC signature. Without the operators, only Zcash deposits that were never credited can be refunded, after a two-day timelock."
}
},
"reproducibility": {
"value": "Partially reproducible",
"sentiment": "warning",
"description": "The Verifier, the custodial bridge token, the Zcash bridge and the Zodl wallet are open source, but the bridge back end, the 1Click API and the solver relay are closed services that every Ethereum leg depends on."
},
"riskSummary": "## Funds can be stolen if\n1. the custodial bridge operator's single mint key or its Ethereum treasury key is compromised.\n2. 4/5 NEAR Intents DAO council members upgrade the Verifier maliciously.\n3. 3/5 Rainbow Bridge DAO council members upgrade the Zcash connector, its token or the light client maliciously.\n4. 11/17 NEAR MPC nodes collude to sign Zcash transactions from bridge addresses.\n
\n## Funds can be frozen if\n1. the DAO or one of the two single-key account lockers freezes the user's account in the Verifier.\n2. the custodial bridge operator freezes a deposit or withdrawal for a compliance review.\n3. the whitelisted relayers stop proving Zcash deposits or triggering Zcash withdrawals.\n
\n## Privacy can be lost if\n1. the ZEC is swapped back in an amount and at a time that matches the payout; both are public at the edge of the shielded pool.\n2. the same Zcash address receives more than one payout, since every payout note is decryptable by anyone.\n3. the operator or its screening vendors join the two legs through IP address, session or partner key. Tor is off by default in Zodl.\n4. the lightwalletd server links the wallet's fetch of the payout transaction with its later broadcast of the exit.\n5. elliptic-curve cryptography is broken: all of an account's addresses share one incoming viewing key, and the addresses are public.",
"tokens": [],
"trackedOn": [
"ethereum"
],
"upgradesAndGovernance": {
"content": "The route touches three governed systems. None of them has an onchain delay that a user could rely on, and the Ethereum side has no contracts at all.\n\n### NEAR Intents Verifier (`intents.near`)\n\nThe Verifier is a NEAR contract with `near-plugins` roles. `intents.sputnik-dao.near`, a Sputnik DAO with five council members and a 4/5 threshold, holds the `DAO` role and is super admin, so it can grant every other role. Upgrades go through `ctl-intents.near`, a controller contract whose only admin is the same DAO. A passed proposal deploys the new code at once. Six accounts hold `PauseManager` and can halt all swaps and withdrawals. Nobody holds `UnpauseManager`, so only the DAO can resume. Two EOAs each hold `UnrestrictedAccountLocker` and can lock any user account, which stops its intents and withdrawals while deposits keep arriving, only the DAO can unlock.\n\n### Custodial \"PoA\" bridge (`omft.near`, `eth.omft.near`)\n\nDespite the name, nothing here is a proof-of-authority consensus or a multisig. The `poa-factory` contract `omft.near` deploys one token per bridged asset and mints on the permission of `TokenDepositer`: `bridge-mng.near`, an EOA, and `int-mnt-dao.sputnik-dao.near`, a three-member DAO whose members can each execute a call alone. The same DAO as above is super admin. Nothing on NEAR verifies that a mint is backed. On Ethereum the funds sit in the escrow [`0x2CfF…2680`](https://etherscan.io/address/0x2CfF890f0378a11913B6129B2E97417a2c302680) and in per-quote deposit accounts, all plain EOAs.\n\n### Zcash connector (`zcash-connector.bridge.near`, `zec.omft.near`, `zcash-client.bridge.near`)\n\nThe connector, the token's controller and the light client are all governed by `rainbowbridge.sputnik-dao.near`, a Sputnik DAO with five council members and a 3/5 threshold. `bridge-ops.near` (five EOAs) can stage code, pause the connector and run migrations; `pm.bridge.near` can pause. Deposits are credited only after `omni-relayer.bridge.near` or `intents-relayer.near` submit an inclusion proof against the light client, whose headers are relayed by `zcash-relayer.near`. Withdrawals are signed by the NEAR MPC network `v1.signer` (11/17, see the [MPC operators page](https://mpc-operators.nearone.org/)) on request of a whitelisted relayer. A user cannot trigger the signature alone. The one permissionless path is a refund of a deposit that was never credited, executable by anyone after a two-day timelock (fourteen days when the relayer has flagged the request). Bridge fees are 0.0001 ZEC minimum per deposit and withdrawal, adjustable by the DAO."
},
"zkCatalogId": "zcash"
}
+10 -5
+10 -5
{
"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."
},
"adversaries": [
{
"id": "publicObserver",
"label": "Public observer",
"description": "Everyone with a block explorer and some basic tools. Sees every public onchain event, but does no correlation beyond following links.",
"examples": "A curious counterparty, an employer, a journalist."
},
{
"id": "chainAnalyst",
"label": "Chain analyst",
"description": "Scrapes all public data and correlates it: timing, amounts, gas and wallet fingerprints, address clusters.",
"examples": "Chain analytics firms, ZachXBT, data brokers."
},
{
"id": "networkObserver",
"label": "Network observer",
"description": "Sits between the user and the chain and sees web2 traffic only: RPC providers, relayers and broadcasters, indexers, ISPs. Learns IP addresses, timing, browser fingerprints, ciphertext and what becomes public. Assumes Tor to send transactions and, where the client has an RPC setting, an own node to read the blockchain.",
"examples": "Infura or Alchemy, a Tornado relayer, a wallet vendor selling telemetry, Google captcha or analytics in the dapp frontend."
},
{
"id": "privilegedInsider",
"label": "Privileged insider",
"description": "Holds a protocol operator role or receives keys or plaintext by design: upgrade admin, sequencer, decryption or view key holder, TEE vendor, association set provider, hosted prover, note registry.",
"examples": "A compliance backdoor key, a DAO with an upgrade key, a KMS committee, an ASP operator."
},
{
"id": "futureAdversary",
"label": "Future adversary",
"description": "Harvest now, decrypt later. Holds every byte ever written onchain plus any retained logs, and future cryptanalysis such as a large quantum computer that breaks elliptic-curve key exchange and pairings, but not hashes, symmetric ciphers or lattices.",
"examples": "First well-funded insiders, then everyone in a potential post-quantum future."
}
],
"fields": [
{
"id": "sender",
"label": "Sender",
"subject": "Sender",
"promiseLabel": "Sender privacy",
"description": "The Ethereum address that funds entered from, or that initiated a transfer."
},
{
"id": "recipient",
"label": "Recipient",
"subject": "Recipient",
"promiseLabel": "Recipient privacy",
"description": "The Ethereum address that funds exit to, or that receives a transfer."
},
{
"id": "amount",
"label": "Amount",
"subject": "Amounts",
"promiseLabel": "Amount privacy",
"description": "The value moved."
},
{
"id": "asset",
"label": "Asset",
"subject": "Asset",
"promiseLabel": "Asset privacy",
"description": "Which token is moved."
},
{
"id": "linkage",
"label": "Link",
"subject": "Link",
"promiseLabel": "Link privacy",
"description": "Whether the entry and exit of the same funds, or sender and recipient of the same transfer, can be tied together."
}
],
"cells": {
"publicObserver": {
"sentiment": "good",
"exposure": "Private payments publish encrypted notes. 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.",
"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.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Your first sponsored transaction after registration is publicly tied to your account."
},
"recipient": {
"verdict": "exposed",
"note": "The first payment to a new contact reveals the recipient's Aztec address."
},
"amount": "private",
"asset": {
"verdict": "exposed",
"note": "zk.money only holds DAI."
},
"linkage": {
"verdict": "atRisk",
"note": "If your first sponsored transaction after registration is a payment to a new contact, it shows both ends."
}
},
"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": "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"
},
{
"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"
},
{
"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"
}
],
"id": "publicObserver",
"value": "Link private",
"alsoExposed": []
},
"chainAnalyst": {
"sentiment": "warning",
"exposure": "The anonymity set is limited to zk.money users. 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.",
"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.",
"interior": {
"sender": "atRisk",
"recipient": "exposed",
"amount": {
"verdict": "atRisk",
"note": "Inferable when a payment sits between a matching public deposit and withdrawal."
},
"asset": "exposed",
"linkage": {
"verdict": "atRisk",
"note": "Registration deposits are publicly tied to their tag."
}
},
"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"
},
{
"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"
},
{
"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",
"exposure": "Keys and proving stay on your device. 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.",
"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.",
"interior": {
"sender": {
"verdict": "atRisk",
"note": "Payment requests over XMTP show who asks whom."
},
"recipient": "exposed",
"amount": "private",
"asset": "exposed",
"linkage": "atRisk"
},
"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": "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"
}
],
"id": "networkObserver",
"value": "Link private",
"alsoExposed": []
},
"privilegedInsider": {
"sentiment": "bad",
"exposure": "Wallets encrypt payments, withdrawals and deposit claims to an enclave key registered in the portal. 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.",
"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.",
"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 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": "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": "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"
}
],
"id": "privilegedInsider",
"value": "Link exposed",
"alsoExposed": [
{
"field": "sender",
"exposure": "exposed"
},
{
"field": "amount",
"exposure": "exposed"
}
]
},
"futureAdversary": {
"sentiment": "bad",
"exposure": "A quantum computer that breaks elliptic-curve key exchange can decrypt historical notes and payment events published to Ethereum. Registered Aztec addresses identify the accounts. Deposit address secrets and enclave communication use the same class of cryptography.",
"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"
},
{
"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"
}
],
"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.",
"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."
}
},
"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."
},
"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.",
"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."
},
"zkCatalogId": "barretenberg"
}