Payment Rails CROPS Dashboard
Unaudited, unvetted, experimental. Do not use as a reference. AI-researched ratings that may be wrong; not advice or a statement of fact about any provider. Full disclaimer
Pending review. 1150 of 1150 ratings not yet checked by a human. Do not rely on unreviewed ratings.

Tornado Cash (Classic pools)

transferEthereum Assessed on Ethereum (chain 1)github.com

Ratings apply to this deployment only. Treat them as unverified for other chains. Why this deployment: The classic UI's networkConfig.js (tornado-classic-ui@a83fae07 L11-L60) lists Ethereum mainnet first (netId1, deployedBlock 9116966), and the onchain InstanceRegistry 0xB20c…A911 lists 19 enabled mainnet instances. Unit: the 4 ETH pools (0.1/1/10/100) and the 8 stablecoin pools (DAI 100-100k, USDC 100/1k, USDT 100/1k). Excluded: cDAI and WBTC pools, other chains (BSC, Polygon, Gnosis, Arbitrum, Optimism, Avalanche), Nova, and governance-only contracts (staking, vesting).

At a glance

Category
Protocols for privacy-preserving transfers
Chain
EthereumEthereum
CROPS tally
17 of 23 hold up · 1 no evidence
Security audits
3 published
Offered
Everywhere
Last edited
2026-10-13 · History
  1. Censorship Resistance No evidenceWeakest: Token and chain freeze risks disclosed
  2. Open1 WeakWeakest: Contracts verified onchain; Whole stack published; Can be self-hosted
  3. Free2 PartialWeakest: Open-source licences; Protection against relicensing; No proprietary dependencies
  4. Privacy2 PartialWeakest: Tracking and analytics; Third parties in the payment flow; Endpoints can be changed
  5. Security1 WeakWeakest: Token approval scope; Audits and bug bounty

Where it is offered

Offered everywhere, per the provider's code or documents. Checked 2026-10-09. Not scored.

The pools are immutable contracts with no live operator and no address or country check, so deposit and withdraw are callable from anywhere. The archived official classic UI has no country or IP geolocation gate in its source (grep for country, geolocation, ipapi, jurisdiction finds nothing); it screens the connecting wallet address against the Chainalysis sanctions oracle and redirects listed addresses to a 451 page. That is an address filter, not a country list. We found no first-party terms page listing countries; the GitHub org is archived and the classic UI source contains no terms text naming countries. Judgment call: we did not inspect the UI build currently served at tornadocash.eth, which could differ from the archived source. Legality of use differs by jurisdiction (see `context`); that is not an availability restriction by the provider.

Evidence (2)2 verified
  1. Verified

    deposit() and withdraw() in the deployed v2.0 source check only the commitment, nullifier, Merkle root and zkSNARK proof; there is no caller, address or country restriction.

    tornadocash/tornado-core · contracts/Tornado.sol

    commit 7033f34434 · checked 2026-10-09

  2. Verified

    The classic UI's only access check is isSanctioned(address) on the Chainalysis oracle at wallet connect; a grep of the source at this commit for country, geolocation, ipapi, ip-api and jurisdiction finds no country gate.

    tornadocash/tornado-classic-ui · store/metamask.js

    commit a83fae0772 · checked 2026-10-09 · source unchanged at weekly re-read 2026-10-19

Censorship Resistance

Who can block valid use, and can users route around them?

No evidencePillar rating: weakest of 5
4 of 5 Partial or better · 1 no evidence

What would raise this pillar

Admin pause or freeze powers

Can any privileged role stop, freeze, or block payments through the settlement contracts, and how is that role constrained? C1

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The pool contracts that hold and release funds have no pause, freeze, blacklist or allowlist. Their one admin role, operator, could only swap the verifier, and it reads as the zero address onchain on every pool that has it; the two newer DAI pools have no operator at all. The verifier has no admin. TORN governance does control a gate one step out: the optional TornadoRouter checks an upgradeable InstanceRegistry and RelayerRegistry, so governance could disable an instance on the router path. Judgment call: we score the pools as the settlement contracts and give 3, because a payer and payee can call the pools directly (C2) and the router gate does not reach that path.

Evidence (4)4 verified
  1. Verified

    The only privileged role in the pool source (tag v2.0, solc 0.5.11, the build deployed in Dec 2019) is operator, which can call updateVerifier and changeOperator (L116-L123); there is no pause, freeze, blacklist or allowlist. The Tornado and MerkleTreeWithHistory contracts in the Sourcify source of 0x47CE…2936 are identical to this file apart from line endings.

    tornadocash/tornado-core · contracts/Tornado.sol

    commit 7033f34434 · checked 2026-10-07

  2. Verified

    operator() of the ETH 1 pool returns the zero address at block 26141552; operator() also returns zero on the 0.1, 10, 100 ETH, DAI 100/1000, USDC and USDT pools at block 26141280, and reverts (no such function) on the DAI 10k/100k pools, whose 0.7.6 source has no operator.

    0x47CE…2936 on sourcify.dev

    0x47CE…2936 explorer · Sourcify · block 26141552 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  3. Verified

    The ETH 0.1 pool's source adds operator-only migrateState, initializeTreeForMigration and finishMigration; operator() returns zero, so none can be called.

    0x12D6…B8Fc on sourcify.dev

    0x12D6…B8Fc explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  4. Verified

    The optional TornadoRouter refuses deposits and withdrawals for instances the InstanceRegistry marks DISABLED and calls RelayerRegistry.burn on withdraw; its governance() is the TORN governance proxy 0x5efd…A1Ce. All 19 registry instances read state 1 (enabled) at block 26140925.

    0xd90e…F31b on sourcify.dev

    0xd90e…F31b explorer · Sourcify · block 26141552 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Settle without the provider

Can a payer or payee complete settlement by calling the public contracts directly, without the provider's API, signer, or relayer? C2

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

A payer can deposit and a payee holding the note can withdraw by calling the pool contracts directly, with no relayer, router, API or signature from anyone else. Addresses and ABI are committed in the public UI repo, and the reference client calls the pool directly. We did not run a transaction. The payment is completed by handing the note to the payee off-chain; the protocol has no on-chain payee field at deposit time.

Evidence (4)4 verified
  1. Verified

    deposit(commitment) and withdraw(proof, root, nullifierHash, recipient, relayer, fee, refund) are external with no caller check; the relayer is only a fee recipient bound into the proof, and fee may be zero (ETHTornado.sol L29-L40 pays recipient directly).

    tornadocash/tornado-core · contracts/Tornado.sol

    commit 7033f34434 · checked 2026-10-07

  2. Verified

    Mainnet pool addresses per denomination are committed in the UI config, and abis/Instance.abi.json holds the pool ABI.

    tornadocash/tornado-classic-ui · networkConfig.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  3. Verified

    The reference client sends withdraw directly to the pool from the user's own account when no relayer URL is given (L236).

    tornadocash/tornado-core · src/cli.js

    commit 1ef6a263ac · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  4. Verified

    The deployed ETH 100 pool is a Sourcify match to this source and has no proxy (EIP-1967 implementation slot zero).

    0xA160…f291 on sourcify.dev

    0xA160…f291 explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Reliance on hosted services

Does the payment flow require a relayer, paymaster, bundler, or API that only the provider runs? C3

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Settlement needs only the pools, a proof client and an Ethereum RPC. A relayer is optional: it exists so a withdrawer can pay gas from the withdrawn amount instead of from a funded account, which matters for privacy but not for settlement. The indexer is optional too, as the UI falls back to RPC event reads. Judgment call: we score 3 although withdrawing to a fresh address without a relayer needs gas from elsewhere, which can reduce privacy (see P3); the cell measures whether settlement depends on a hosted intermediary, and it does not.

Evidence (3)3 verified
  1. Verified

    Withdrawal pays denomination minus fee to the recipient and pays a relayer only if fee > 0; any account may submit the transaction.

    tornadocash/tornado-core · contracts/ETHTornado.sol

    commit 7033f34434 · checked 2026-10-07

  2. Verified

    The UI reads deposit events from The Graph and then from the RPC, so the indexer is optional; the proving key is a static GitHub release asset (tornado-core v2.1).

    tornadocash/tornado-classic-ui · services/events.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  3. Verified

    Relayers are optional; the RelayerRegistry lets anyone owning an ENS subdomain register with minStakeAmount 5000 TORN; relayer code is public (tornado-relayer, archived).

    0x58E8…3dF2 on sourcify.dev

    0x58E8…3dF2 explorer · Sourcify · block 26141552 · checked 2026-10-07

Neutral settlement, disclosed filtering

Is the settlement layer free of address or geographic filtering, and is any filtering at the edge disclosed and avoidable? C4

2 Partial

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The pools are neutral: no address or country filtering. The archived classic UI screens the connecting wallet against the Chainalysis sanctions oracle and sends listed addresses away. The check is visible in public code, the list source is identified by its oracle address, and the direct pool path bypasses it. tornado-core's cli.js has no screening. Judgment call: this fits anchor 3 in substance, but 3 needs a distributed package or trace for the client, and we also did not inspect the build currently served at tornadocash.eth, so we take 2.

Evidence (3)3 verified
  1. Verified

    On wallet connect (L427) the UI calls isSanctioned(address) on the Chainalysis sanctions oracle 0x40C57923924B5c5c5455c48D93317139ADDaC8fb and, if true, redirects the page away; pages/451.vue shows "Unavailable For Legal Reasons".

    tornadocash/tornado-classic-ui · store/metamask.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    The pool contracts check only the commitment, nullifier, Merkle root and proof; there is no address or country check.

    tornadocash/tornado-core · contracts/Tornado.sol

    commit 7033f34434 · checked 2026-10-07

  3. Verified

    The deployed ETH 10 pool matches that source on Sourcify, so a wallet screened out by the UI can still call it directly (C2).

    0x910C…9DbF on sourcify.dev

    0x910C…9DbF explorer · Sourcify · block 26141280 · checked 2026-10-07

Token and chain freeze risks disclosed

Are the tokens and chains the rail depends on enumerated, with their issuers' freeze powers and sequencer assumptions stated to payees? C5

Under review

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 todayDrift

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The weekly re-check found that a recorded fact changed. This rating counts as unknown until a reviewer re-checks it.

Tokens and pools are enumerated onchain and in the UI config. Neither the repos nor the UI tell users that USDC and USDT can blacklist a pool address, which would lock every note in that pool; the pools were not blacklisted at our block. ETH and DAI pools carry no issuer freeze. Ethereum L1 has no sequencer. Scored 2: enumerated in code, assumptions not stated.

Evidence (2)2 verified
  1. VerifiedDrift

    InstanceRegistry lists each instance with its token (DAI 0x6B17…1d0F, USDC 0xA0b8…eB48, USDT 0xdAC1…1ec7, cDAI, WBTC, or ETH) and state; networkConfig.js in the UI enumerates the same per network.

    0xB20c…A911 on sourcify.dev

    0xB20c…A911 explorer · Sourcify · block 26140925 · checked 2026-10-07

  2. Verified

    USDC isBlacklisted() returns false for both USDC pools, and USDT isBlackListed() returns false for both USDT pools, at block 26141584; both issuers retain the power to blacklist.

    0xA0b8…eB48 on etherscan.io

    0xA0b8…eB48 explorer · Sourcify · block 26141584 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Open

Is the whole stack visible?

1 WeakPillar rating: weakest of 4
1 of 4 Partial or better

What would raise this pillar

Contracts verified onchain

Does the deployed bytecode match public source, and can a third party rebuild it? O1

1 Weak

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-07 12 days ago

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The pools and verifier are partial matches on Sourcify, the governance-era contracts are full matches, and the hasher, which every deposit calls, has no Sourcify verification (it is generated bytecode; we could not load Etherscan). No rebuild was attempted. Judgment call: partial matches would support 2, but one settlement-path contract is unverified, so we take anchor 1.

Evidence (2)2 verified
  1. Verified

    Sourcify returns match (partial, metadata differs) for all 12 pools and the verifier 0xce17…557A, exact_match for the router, registries and FeeManager, and no record for the MiMC hasher 0x8358…28fe.

    0x47CE…2936 on sourcify.dev

    0x47CE…2936 explorer · Sourcify · block 26141280 · checked 2026-10-07

  2. Verified

    Tag v2.0 pins solc 0.5.11 with optimizer runs 200, matching the deployed compiler; Verifier.sol is generated from the trusted-setup key and the hasher bytecode by scripts/compileHasher.js, neither committed as source.

    tornadocash/tornado-core · truffle-config.js

    commit 7033f34434 · checked 2026-10-07

Whole stack published

Are the SDK, frontend, backend or API, indexer, and deploy scripts all public? O2

1 Weak

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-07 12 days ago

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Every layer has public source on GitHub, but all of it is archived since 2022. For the immutable pools and the proof client the archive is still the running code. The governance-era router and registries are public only as Sourcify source, and the frontend now served via tornadocash.eth and current relayer builds were not traced to any public repository in this review. Judgment call: between 2 and 1 we take 1, because we could not show the live frontend and relayer builds are public.

Evidence (1)1 verified
  1. Verified

    All 47 repos in github.com/tornadocash are archived, last pushed between 2019 and 2022-08-22; they include contracts, circuits, CLI, classic UI, relayer, subgraphs and deploy scripts.

    tornadocash/tornado-core · contracts

    commit 1ef6a263ac · checked 2026-10-07

Can be self-hosted

Can a stranger reach a working deployment from the README? O3

1 Weak

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Build and run documentation exists for the UI and the core client. Reproduction not attempted, so the score is capped at 1.

Evidence (1)1 verified
  1. Verified

    The README gives build steps (Node 14, yarn, .env, yarn generate) and an IPFS deploy script; tornado-core README L42-L78 covers build and the CLI.

    tornadocash/tornado-classic-ui · README.md

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Interfaces and data export

Are ABIs, event schemas, an API schema, and a payee data export in a non-proprietary format all in the repo? O4

2 Partial

Best evidence: VerifiedChecked 2026-10-07 12 days ago

UnreviewedAssessed by AI research agent (seed), 2026-10-07

ABIs and event schemas are in the repo. There is no protocol API to document, as no backend is required. There is no payee export function; the note string is the only record a payee holds. Judgment call: we treat the absence of any required API as satisfying the API part, giving 2; no export, so not 3.

Evidence (1)1 verified
  1. Verified

    ABIs for the pool instance, router (TornadoProxy), RelayerRegistry and governance are committed; Deposit and Withdrawal events are defined in Tornado.sol L36-L37.

    tornadocash/tornado-classic-ui · abis

    commit a83fae0772 · checked 2026-10-07

Free

Does the license actually let a third party fork, modify, and run it?

2 PartialPillar rating: weakest of 3
3 of 3 Partial or better

What would raise this pillar

Open-source licences

Does every repository needed to run the product carry an OSI-approved license? F1

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Every required component carries an OSI licence: GPL-3.0 for the pools, circuits and proof client, and MIT for the classic UI. The circomlib fork used in proof generation states GPL-3.0 only in package.json, with no LICENSE file; its upstream is GPL-3.0. The optional tornado-cli, relayer and subgraph repos have no LICENSE file. Judgment call: we count the package.json declaration on circomlib as a licence, and we take 2 rather than 3 because of the unlicensed optional repos.

Evidence (2)2 verified
  1. Verified

    tornado-core (pools, circuits, verifier generation, cli.js) is GPL-3.0 at the deployed tag; the websnark and snarkjs forks are GPL-3.0 (GitHub license API).

    tornadocash/tornado-core · LICENSE

    commit 7033f34434 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    The circomlib fork pinned by tornado-core has no LICENSE file; its package.json declares GPL-3.0. tornado-cli has no LICENSE file (package.json says ISC); tornado-relayer and tornado-subgraph have none.

    tornadocash/circomlib · package.json

    commit c372f14d32 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Protection against relicensing

Can the provider unilaterally relicense future versions, and has it committed not to? F2

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

There is no CLA and no relicensing event, and the GitHub repos are archived. No written licence-stability commitment exists.

Evidence (1)1 verified
  1. Verified

    The UI's contributing guide asks for focused PRs and has no CLA. tornado-core has no CONTRIBUTING file, and its LICENSE has a single commit, 21a9545b (2019-07-17).

    tornadocash/tornado-classic-ui · .github/CONTRIBUTING.md

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

No proprietary dependencies

Does a production deployment need a proprietary plugin or hosted-only service? F3

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

No proprietary plugin or hosted-only service is needed. The pools, proving key and client are public, and any Ethereum RPC works. The UI's default Infura and Alchemy RPCs, The Graph, and the Chainalysis oracle are all optional. Judgment call: the code supports 3, but with no O3 reproduction we take 2.

Evidence (1)1 verified
  1. Verified

    The circuit and proving key come from tornado-core GitHub release assets (v2.1); the client needs only a user-supplied RPC.

    tornadocash/tornado-core · scripts/downloadKeys.js

    commit 1ef6a263ac · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Privacy

What can an observer learn, and did the user knowingly choose it?

2 PartialPillar rating: weakest of 5
5 of 5 Partial or better

What would raise this pillar

Tracking and analytics

Do the SDK, widget, or frontend ship analytics, telemetry, error reporting, or fingerprinting? P1

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The archived UI and the core client ship no analytics or telemetry. When a remote RPC is used, tornado-cli calls ip.tornado.cash to show the user's IP; that call is counted under P4. We ran no trace and did not inspect the live IPFS build. Judgment call: absence shown only in code is capped at 2.

Evidence (1)1 verified
  1. Verified

    None of the UI dependencies is an analytics, telemetry, error-reporting or fingerprinting package; nuxt.config.js L53 sets a CSP with script-src 'self'.

    tornadocash/tornado-classic-ui · package.json

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Data collected beyond payment

Does the flow collect anything beyond addresses, amounts, token, and chain? P2

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The protocol collects only what settlement needs: a commitment at deposit, and recipient, relayer and fee at withdrawal. No required component holds account, identity or contact data. An optional relayer sees the recipient and the proof it relays.

Evidence (1)1 verified
  1. Verified

    The public inputs are root, nullifierHash, recipient, relayer, fee and refund. The private inputs (nullifier, secret, Merkle path) stay in the user's client. Deposit takes only a commitment.

    tornadocash/tornado-core · circuits/withdraw.circom

    commit 7033f34434 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Payments linkable onchain

What do calldata and events reveal about who paid whom for what? P3

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Onchain data shows who deposited and who received, but not which deposit paid which withdrawal. Amounts are fixed denominations, and there is no memo or invoice field. Linkage can still come from timing, distinctive gas or funding patterns, low pool activity, reused addresses, or the optional router EncryptedNote event, which ties the depositor's address to an encrypted note backup. Judgment call: anonymity-set size depends on user behaviour and is not scored; we score what the code and chain reveal, which is anchor 3.

Evidence (2)2 verified
  1. Verified

    Deposit emits commitment, leafIndex and timestamp, and the depositor is the tx sender. Withdrawal emits recipient, nullifierHash, relayer and fee. The proof hides which commitment a nullifier spends.

    tornadocash/tornado-core · contracts/Tornado.sol

    commit 7033f34434 · checked 2026-10-07

  2. Verified

    verifier() on each of the 12 pools returns the Groth16 verifier 0xce17…557A (read at block 26141280). Amounts are fixed per pool by denomination().

    0x47CE…2936 on sourcify.dev

    0x47CE…2936 explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Third parties in the payment flow

Which third parties see a request during a payment, and can they be swapped out? P4

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

On the minimal required path (core client plus RPC), only the RPC the user chooses sees the request. The optional UI adds The Graph (hardcoded) and default Infura and Alchemy RPCs (swappable in Settings). An optional relayer, when used, sees the recipient and the user's IP unless Tor is used. tornado-cli adds an IP-echo call. All of these are named in code. Judgment call: we score 2 because the hardcoded Graph endpoint cannot be swapped by config, although a user avoids it by not using the UI.

Evidence (2)2 verified
  1. Verified

    The UI queries The Graph hosted-service subgraphs at hardcoded URLs. Its RPC defaults are Infura and Alchemy with build-time keys (networkConfig.js L30-L39), replaceable in Settings. The Chainalysis oracle is read through the RPC.

    tornadocash/tornado-classic-ui · services/graph.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    tornado-cli calls https://ip.tornado.cash when the RPC is not local, unless the private-RPC flag is set.

    tornadocash/tornado-cli · cli.js

    commit 378ddf8b8b · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Endpoints can be changed

Can RPC and indexer URLs be changed, and is the indexer code public? P5

2 Partial

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The RPC can be set in the UI, and with --rpc in the CLI. The indexer URL can be changed only in code, though the UI falls back to RPC reads. Scored 2: the indexer is configurable via code only.

Evidence (1)1 verified
  1. Verified

    The UI settings offer an RPC dropdown and a custom RPC URL field. The indexer URL is fixed in services/graph.js; the indexer code is public (tornado-subgraph).

    tornadocash/tornado-classic-ui · components/Settings.vue

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Security

Who can cause loss, lock users in, or change the rules?

1 WeakPillar rating: weakest of 6
4 of 6 Partial or better

What would raise this pillar

  • Token approval scope reaching Partial: A bounded allowance by default (capped or refilling, limited to one receiver), or exact-amount with an unbounded opt-in clearly labelled in code.
  • Audits and bug bounty reaching Partial: Audit pinned to a commit, resolutions not individually linked.

Who holds funds in transit

Who holds funds between payer and payee, and can the provider redirect them? S1

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The pools are non-upgradeable escrows that release funds only to whoever holds the note's secret, who chooses the recipient in the proof. No operator, governance or relayer can redirect funds. A relayer cannot change the recipient or fee because both are bound into the proof. Whoever holds the note controls the funds, so a payer who keeps a copy of a note handed to a payee can still withdraw first.

Evidence (2)2 verified
  1. Verified

    Funds sit in the pool between deposit and withdrawal and leave only to the recipient (and an optional relayer fee) bound into a valid proof for an unspent nullifier; no function lets any role move pool funds.

    tornadocash/tornado-core · contracts/ERC20Tornado.sol

    commit 7033f34434 · checked 2026-10-07

  2. Verified

    The DAI 100k pool (0.7.6 build) has no operator function, and its EIP-1967 implementation slot is zero; the 0.5.11 pools have operator() = 0x0 (see C1).

    0x2377…5334 on sourcify.dev

    0x2377…5334 explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Who can upgrade the code

Who can change the contract code, and with how much notice? S2

3 Strong

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

No one can change the pool, verifier or router code: none is a proxy, and the one pool role that could swap the verifier is set to zero. TORN governance (5-day vote, 2-day execution delay, delegatecall execution) can upgrade the InstanceRegistry, RelayerRegistry and FeeManager, which only the optional router path consults, and it owns the tornadocash.eth name that serves the UI. Proposal 20's target was created after its vote closed and carries a selfdestruct, which shows that code executed by governance need not be the code voters saw. Judgment call: we score the settlement contracts at 3; the governance risk is in the router path and the frontend, both of which a user can avoid.

Evidence (4)4 verified
  1. Verified

    The EIP-1967 implementation slot reads zero on all 12 pools and on the verifier and router; pools have no upgrade function, and operator() (which could swap the verifier) is 0x0.

    0x47CE…2936 on sourcify.dev

    0x47CE…2936 explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    RelayerRegistry, InstanceRegistry and FeeManager are proxies whose admin slot is the governance proxy 0x5efd…A1Ce; governance is its own admin (LoopbackProxy).

    0x58E8…3dF2 on sourcify.dev

    0x58E8…3dF2 explorer · Sourcify · block 26141280 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  3. Verified

    EXECUTION_DELAY is 172800 s (2 days) after a 432000 s (5 day) voting period; execute() delegatecalls the proposal contract (tornado-governance Governance.sol L184-L200), so a passed proposal can do anything governance can.

    0x5efd…A1Ce on sourcify.dev

    0x5efd…A1Ce explorer · Sourcify · block 26141584 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  4. Verified

    proposals(20) has target 0xC503…752D, endTime 1684394654 (2023-05-18) and executed = true; the verified code at the target includes an owner-only selfdestruct (emergencyStop), and Sourcify records its creation in tx 0x4eeffe76…042b at block 17299150 (2023-05-20), after voting closed.

    0xC503…752D on sourcify.dev

    0xC503…752D explorer · Sourcify · block 26141584 · checked 2026-10-07

Token approval scope

How large an allowance does the SDK ask users to grant, and for how long? S3

1 Weak

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The UI asks by default for an unlimited allowance to TornadoRouter and shows the choice in its approval dialog. The router is not upgradeable, and deposit pulls only the denomination from msg.sender, but any allowance left over remains exposed to the router's fixed code. The core client approves exactly the deposit amount, which would score higher. Judgment call: we score the UI default because it is the published frontend, and take 1 (unbounded by default, disclosed).

Evidence (2)2 verified
  1. Verified

    approvalAmount defaults to 'unlimited' (L13), which approves 2^256-1 to the router; components/ApproveModalBox.vue offers the user a choice between the deposit amount and unlimited.

    tornadocash/tornado-classic-ui · store/token.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    The core client approves exactly the deposit amount to the pool.

    tornadocash/tornado-core · src/cli.js

    commit 1ef6a263ac · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Funds safe if provider disappears Derived

If the provider disappears tomorrow, do payees keep their funds and the ability to keep settling? S4

2 Partial

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

Derived from S1=3, C2=3, C3=3 and O3=1. Funds sit in immutable pools that no one can redirect (S1). A note holder can withdraw by calling the pool directly with the public client and proving key (C2), and no relayer or indexer is required (C3). Settlement can continue the same way. A public frontend build exists in the archived classic UI, but we did not reproduce it (O3=1). Judgment call: 2, not 3, for that reason.

Evidence (2)2 verified
  1. Verified

    The pools are immutable with operator 0x0, and withdraw is callable by anyone holding a valid proof (C2).

    0x910C…9DbF on sourcify.dev

    0x910C…9DbF explorer · Sourcify · block 26141280 · checked 2026-10-07

  2. Verified

    The proving key and circuit needed to withdraw are public GitHub release assets.

    tornadocash/tornado-core · scripts/downloadKeys.js

    commit 1ef6a263ac · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Secrets and webhook handling

Are secrets kept out of client bundles and are webhooks signed and verified? S5

2 Partial

Best evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

The user secret is the note (nullifier and secret), generated and kept client-side. The protocol has no API keys or webhooks. The UI embeds RPC provider keys in its bundle, a minor issue since they grant only RPC quota. Integrity of the served frontend depends on whoever controls tornadocash.eth (TORN governance, see S2). Judgment call: 2 for the bundled RPC keys.

Evidence (1)1 verified
  1. Verified

    The UI builds INFURA_KEY and ALCHEMY_*_KEY from env into client-side RPC URLs, so those keys ship in the browser bundle; they authorise RPC usage only. There are no webhooks or merchant API keys.

    tornadocash/tornado-classic-ui · networkConfig.js

    commit a83fae0772 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

Audits and bug bounty

Has the code been audited at a pinned commit, were findings fixed traceably, and is there a live bounty? S6

1 Weak

Sets the pillar ratingBest evidence: VerifiedChecked 2026-10-19 today

UnreviewedAssessed by AI research agent (seed), 2026-10-07

ABDK audited the contracts and circuits at a pinned commit, and the report links fix commits. The deployed code was built from tag v2.0, 107 commits later, and we could not confirm every change after the audit was reviewed. There is no live bug bounty. The router, registries and governance upgrades were not reviewed here. Judgment call: 1 rather than 2, because the audited commit is not the deployed commit.

Evidence (2)2 verified
  1. Verified

    ABDK's Solidity audit pins peppersec/tornado-mixer commit 0484408e (2019-10-17) and links fix commits such as d0e312eb (merge of PR 24, "audit-6"); circuit and cryptographic reviews sit in the same folder.

    abdk-consulting/audits · tornado/Tornado_solidity_audit.pdf

    commit 57af593b14 · checked 2026-10-07 · source unchanged at weekly re-read 2026-10-19

  2. Verified

    The README links the ABDK reports at tornado.cash URLs, which no longer resolve. The deployed tag v2.0 (7033f344) is 107 commits after the audited commit, with contract changes; no bug bounty or SECURITY file exists in the repos.

    tornadocash/tornado-core · README.md

    commit 7033f34434 · checked 2026-10-07

Security audits 3

Published audits and similar reviews of this provider's code, newest first. Context for the Audits and bug bounty rating, which scores them; this list does not change any rating, and an audit of older code says little about what is deployed now.

DateAuditorTypeScopeCovers deployed codeFindings
2019-11-29ABDK ConsultingSecurity reviewCryptographic review of the mixer protocol (Pedersen and MiMC hashing, nullifier and commitment design) and its implementation.
Reviews the protocol design used by the deployed pools; the implementation it read was the then-current master of peppersec/tornado-mixer (now tornadocash/tornado-core), not a pinned commit.
Partly
2019-11-25ABDK ConsultingAuditWithdraw circuit, Merkle tree checker and hash templates (circom) in tornado-mixer. at 0484408e82
The repository was then named peppersec/tornado-mixer. The deployed proving key comes from the tornado-core v2.1 release assets; we did not compare the deployed circuit with the audited commit.
PartlyNo major issues; minor issues, many fixed in linked commits, one left open
2019-11-19ABDK ConsultingAuditPool contracts (Mixer, ETH and ERC20 mixers, Merkle tree) in tornado-mixer. at 0484408e82
The deployed pools were built from tag v2.0 (7033f344), 107 commits after the audited commit, with contract changes (see S6).
PartlyNo critical issues; major and moderate flaws marked fixed (last fix commit d0e312eb); some minor issues deferred or declined

Compiled from: The tornado-core README audit section (its tornado.cash/audits links no longer resolve), the classic UI README (links a Decurity dApp audit at tornado.cash, which no longer resolves and is not in Decurity's public audits repo), the ABDK portfolio at github.com/abdk-consulting/audits (tornado folder), all archived github.com/tornadocash repos, and the Trail of Bits publications list. ABDK's 2020 audit of the Tornado Farm anonymity-mining contracts is in the same folder but is not in the payment path, so it is not listed. No published audit of the router, registries or governance contracts was found. Checked 2026-10-13. Only published reports are listed; private audits a provider mentions without a report are not.

Operational and procurement

Facts an institution's procurement, finance and security functions ask for. Separate from the CROPS ratings and never scored.

Group A: operational facts. Group B: 45 due-diligence controls derived from a UN agency's vendor requirements: 10 evidenced, 0 attested, 4 absent, 31 not applicable, 0 unknown. "Not applicable" means there is no operator to hold the control: it falls to whoever deploys the rail. How to read this.

Group A: operational facts

Fees

Evidenced
ComponentPaid byAmountBasis
providernonenone in the pool contractswithdraw sends the denomination minus the proof-bound fee to the recipient and the fee to the relayer; the pools take nothing and have no admin to add a fee.
providerpayeeoptional relayer fee, set by the chosen relayerDeducted from the withdrawn denomination when a relayer submits the withdrawal; fee and relayer are bound into the proof. Zero when the withdrawer submits it.
networkpayerdeposit sample 2026-10-09, 0.00287 ETH (919,444 gas at 3.12 gwei)Router deposit into the ETH 1 pool, tx 0xb25e…d1cc, block 26153431; varies with Ethereum gas price.
networkpayeewithdrawal sample 2026-10-09, 0.00109 ETH (349,079 gas at 3.12 gwei)Self-submitted withdrawal from the ETH 1 pool via the router with fee 0, tx 0x7678…48e3, block 26153424.
limitnonefixed denominations per pool (ETH 0.1/1/10/100, DAI 100 to 100k, USDC and USDT 100/1k)Each pool's denomination is set at construction and cannot change; one deposit equals one denomination (pools enumerated per token in the InstanceRegistry, see refs).

On the optional router path, relayers registered in the RelayerRegistry have TORN burned from their stake per withdrawal (FeeManager sets the rate); that cost falls on relayers and reaches users only through their fee. No FX.

Evidence shared with CROPS: C5 item 1

  1. Verified

    _processWithdraw sends denomination - fee to the recipient and fee to the relayer if fee > 0; there is no protocol fee.

    tornadocash/tornado-core · contracts/ETHTornado.sol

    commit 7033f34434 · checked 2026-10-09

  2. Verified

    Deposit receipt read 2026-10-09: gasUsed 919444, effectiveGasPrice 3.119 gwei, cost 0.002868 ETH; Deposit log from the ETH 1 pool 0x47CE…2936.

    etherscan.io/tx/0xb25ecc750f4854305239ccef3fa4af9b8ecb81d59e833e1ae2a85c5d12d7d1cc

    block 26153431 · checked 2026-10-09

  3. Verified

    Withdrawal receipt read 2026-10-09: gasUsed 349079, effectiveGasPrice 3.125 gwei, cost 0.001091 ETH; Withdrawal log from the ETH 1 pool with relayer 0x0 and fee 0.

    etherscan.io/tx/0x7678bb5e5132c430f767d15d076096119b9f23d651630964dd1bab96616248e3

    block 26153424 · checked 2026-10-09

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Custody model

Evidenced

Self-custody

Agrees with S1 (score 3). Funds sit in immutable pools between deposit and withdrawal and leave only to whoever holds the note; no operator, governance or relayer can move them. Holding the note is holding the funds, so a payer who keeps a copy can withdraw first.

Evidence shared with CROPS: S1 item 1, S1 item 2

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Licences and registrations

N/A: falls to the institution

An institution using the pools carries its own licensing and sanctions analysis; see the provider file's `context` for the 2022 OFAC designation and its 2025 removal.

No legal entity operates the pools and no party takes custody or provides a service on the required path; there is nobody to hold a licence. Relayers and frontends are optional and independent.

  1. Verified

    The GitHub organisation profile names no company (company null; name "Tornado Cash"; blog tornado.cash).

    api.github.com/orgs/tornadocash

    checked 2026-10-09

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Cash-out options

N/A: falls to the institution

The note holder withdraws the token to an address it chooses; converting it to local currency is outside the protocol.

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

First deployment

Evidenced

2019-12-16 (block 9116966): ETH 0.1 pool 0x12D6…B8Fc, the first Ethereum mainnet pool (also the UI config's deployedBlock); the ETH 1 pool followed at block 9117609.

  1. Verified

    Sourcify creation data gives tx 0xeed4367a9b4c066b9fbf0a44869f36b93d2f06e5a63a9464ddfd0597a8a45935, block 9116966, deployer 0x8589…DA16; the receipt's contractAddress is this pool and the block time is 2019-12-16 19:08 UTC.

    0x12D6…B8Fc on sourcify.dev

    0x12D6…B8Fc explorer · Sourcify · block 9116966 · checked 2026-10-09

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Operating entity

Absent

Searched: the GitHub org profile, tornado-core and classic-UI READMEs and the classic UI source (no terms or legal entity), and https://tornado.cash (no response to curl). No contracting entity is disclosed. OFAC's 2022 designation treated "Tornado Cash" as an entity without naming a legal form, and the US and Dutch prosecutions named individuals; neither is a company record.

  1. Verified

    The organisation profile names no company or legal entity.

    api.github.com/orgs/tornadocash

    checked 2026-10-09

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Security incidents

Evidenced
  • 2023-05-20: TORN governance proposal 20 was executed although its target contract was created after the vote closed and carries an owner-only selfdestruct, so the code executed was not the code voters saw. It reached governance, the registries and the router path, not the pools. Wider effects were not reconstructed here. funds lost: unknown source

Absence of a found incident is not evidence that none occurred.

Primary sources only. A 2024 report of a backdoor in the IPFS-served frontend was not evidenced from a primary source and is not listed. No pool contract incident was found: the pools are immutable and their operator is zero (CROPS C1, S2).

Evidence shared with CROPS: S2 item 4

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Product changes affecting users

Evidenced
  • 2022-08-08: US Treasury (OFAC) designated Tornado Cash and its smart contract addresses. source
  • 2022-08-22: Last push to the github.com/tornadocash repositories; all 47 are now archived. source
  • 2025-03-21: US Treasury announced removal of the Tornado Cash sanctions. source

The pool contracts themselves have not changed since deployment. Governance changes to the optional registries and router are not itemised (72 proposals at the seed read).

Evidence shared with CROPS: O2 item 1

  1. Documented

    Treasury press release announcing the designation.

    home.treasury.gov/news/press-releases/jy0916

    checked 2026-10-09 · source unchanged at weekly re-read 2026-10-19

  2. Documented

    Treasury press release dated March 21, 2025 announcing the delisting.

    home.treasury.gov/news/press-releases/sb0057

    checked 2026-10-09 · source unchanged at weekly re-read 2026-10-19

UnreviewedAssessed by AI research agent (operational), 2026-10-09Checked 2026-10-09

Volume transacted (verified only)

Unknown

not computed on 2026-10-19: eth_getLogs: Request blocked

Settlement is observable but the event shape does not fit a single amount spec. 347 events (deposits and withdrawals) appeared on the four ETH pools in the 5000 blocks to 26153707, so the pools are in use. Not computed; the maintainer runs scripts/volumes.mjs.

UnreviewedAssessed by AI research agent (operational), 2026-10-09

Group B: institutional due diligence

ControlStateWhat was found
Assurance and certifications
B1.1 ISO 27001, developer organisation
Is the organisation that develops the product ISO 27001 certified, and does the certificate name that entity?
N/A: falls to the institution
implied from the component list
B1.2 ISO 27001, hosting and support organisation
Is the organisation that hosts and supports the service ISO 27001 certified in its own name, with a scope covering the service?
N/A: falls to the institution
implied from the component list
B1.3 SOC 2 Type II or ISAE 3000/3402 reports
Does the provider undergo periodic SOC 2 Type II or ISAE 3402 Type II assessments and make reports available?
N/A: falls to the institution
implied from the component list
B1.4 Independent source-code security review before go-live
Was the application reviewed by an independent party before launch, and is the report linked?
N/A: falls to the institution
implied from the component list
B1.5 Penetration testing
Is the service penetration-tested before go-live and at least every three years, with results available?
N/A: falls to the institution
implied from the component list
B1.6 Vulnerability scanning cadence
Are the platform and the application scanned for vulnerabilities at least every six months?
N/A: falls to the institution
implied from the component list
Vulnerability and patch management
B2.1 Security contact and disclosure policy
Is there a published way to report a vulnerability (SECURITY.md, security.txt, or a disclosure page)?
Absentnone of 9 repo(s): tornadocash/tornado-core (archived) ✗ no security policy file; tornadocash/tornado-classic-ui (archived) ✗ no security policy file; tornadocash/tornado-cli (archived) ✗ no security policy file; tornadocash/tornado-relayer (archived) ✗ no security policy file; tornadocash/tornado-governance (archived) ✗ no security policy file; tornadocash/tornado-subgraph (archived) ✗ no security policy file; tornadocash/websnark (archived) ✗ no security policy file; tornadocash/snarkjs (archived) ✗ no security policy file; tornadocash/circomlib (archived) ✗ no security policy file
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B2.2 Patch service levels
Does the provider commit to patch timelines for known vulnerabilities (the partner expects 30 days critical, 40 high, 90 medium)?
N/A: falls to the institution
implied from the component list
B2.3 Dependency and vulnerability scanning in CI
Do the public repositories run dependency or code scanning automatically?
Absentnone of 9 repo(s): tornadocash/tornado-core (archived) ✗ no scanning config or workflow step found; tornadocash/tornado-classic-ui (archived) ✗ no scanning config or workflow step found; tornadocash/tornado-cli (archived) ✗ no scanning config or workflow step found; tornadocash/tornado-relayer (archived) ✗ no scanning config or workflow step found; tornadocash/tornado-governance (archived) ✗ no scanning config or workflow step found; tornadocash/tornado-subgraph (archived) ✗ no scanning config or workflow step found; tornadocash/websnark (archived) ✗ no scanning config or workflow step found; tornadocash/snarkjs (archived) ✗ no scanning config or workflow step found; tornadocash/circomlib (archived) ✗ no scanning config or workflow step found
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
Incident reporting and continuity
B3.1 Incident reporting commitment
Does the provider commit to notify customers of security or data incidents within a stated time (the partner expects 24 hours)?
N/A: falls to the institution
implied from the component list
B3.2 Backups and restore testing
Are customer records backed up daily and restores tested on a schedule?
N/A: no such service
implied from the component list
B3.3 Recovery plan
Is there an approved and tested recovery plan for the service?
N/A: no such service
implied from the component list
B3.4 Status page and post-mortems
Does the provider publish service status and post-mortems for incidents?
N/A: falls to the institution
implied from the component list
Identity and access (operator side)
B4.1 MFA for end users
Can or must end users protect accounts with multi-factor authentication?
N/A: no such service
implied from the component list
B4.2 MFA and separate accounts for privileged access
Is privileged access protected by MFA and kept on separate accounts?
N/A: falls to the institution
implied from the component list
B4.3 Periodic access reviews
Are user access rights reviewed at least annually and privileged accounts at least six-monthly?
N/A: falls to the institution
implied from the component list
B4.4 Segregation of duties and joiner-mover-leaver controls
Is there a documented segregation-of-duties model and a joiner-mover-leaver process?
N/A: falls to the institution
implied from the component list
B4.5 Session timeout
Are idle interactive sessions terminated after a defined period (the partner expects 60 minutes)?
N/A: no such service
implied from the component list
API and integration
B5.1 API authentication, browser to server
Which standard (OAuth 2.0, OpenID Connect, SAML, JWT) protects browser-to-server API calls?
N/A: falls to the institution
implied from the component list
B5.2 API authentication, server to server
Are server-to-server calls authenticated with keys or PKI certificates, and are keys scoped and rotatable?
N/A: falls to the institution
implied from the component list
B5.3 Token expiry
Do API tokens expire, and within what period (the partner caps it at 120 minutes for public data, 30 otherwise)?
N/A: falls to the institution
implied from the component list
B5.4 Export controls
If an API exports data, does it limit volumes and log exports?
N/A: falls to the institution
implied from the component list
Data protection and privacy governance
B6.1 Data classification and encryption
Does the provider state a data classification and enforce encryption at rest and TLS 1.2 or better in transit?
N/A: falls to the institution
implied from the component list
B6.2 Production data kept out of test environments
Does the provider state that production or real personal data is not used in development and testing?
N/A: falls to the institution
implied from the component list
B6.3 Data retention and deletion on termination
What is retained, for how long, and is customer data removed on termination?
N/A: falls to the institution
implied from the component list
B6.4 Data protection impact assessment and roles
For systems holding personal data, has a DPIA been completed and are controller and processor defined?
N/A: falls to the institution
implied from the component list
B6.5 Data processing or sharing agreement available
Can a customer obtain a data processing agreement or equivalent?
N/A: falls to the institution
implied from the component list
Logging and monitoring
B7.1 Audit logging
Are account changes, logins and activity on important records logged and retained?
N/A: falls to the institution
implied from the component list
B7.2 Central monitoring and endpoint detection
Are logs sent to a managed SIEM and is endpoint detection running on all platforms?
N/A: falls to the institution
implied from the component list
Hosting and network
B8.1 Hardened hosting
Are hosts hardened to a recognised benchmark, with only essential ports open, IDS/IPS, a WAF for internet-facing applications and tenant isolation?
N/A: falls to the institution
implied from the component list
B8.2 Deployment configuration and infrastructure as code
Does the repository ship reproducible deployment configuration (containers, IaC, Helm) that a self-hoster can harden?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✗ no deployment configuration; tornadocash/tornado-classic-ui (archived) ✓ deployment configuration: Dockerfile; tornadocash/tornado-cli (archived) ✗ no deployment configuration; tornadocash/tornado-relayer (archived) ✓ deployment configuration: Dockerfile; tornadocash/tornado-governance (archived) ✗ no deployment configuration; tornadocash/tornado-subgraph (archived) ✗ no deployment configuration; tornadocash/websnark (archived) ✗ no deployment configuration; tornadocash/snarkjs (archived) ✗ no deployment configuration; tornadocash/circomlib (archived) ✗ no deployment configuration
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
Engineering practice in public repositories
B9.1 Default branch protected
Does the default branch require reviews and passing checks, with no direct pushes?
Absentnone of 9 repo(s): tornadocash/tornado-core (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/tornado-classic-ui (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/tornado-cli (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/tornado-relayer (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/tornado-governance (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/tornado-subgraph (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/websnark (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/snarkjs (archived) ✗ no branch rules visible (classic branch protection is not readable without push access); tornadocash/circomlib (archived) ✗ no branch rules visible (classic branch protection is not readable without push access)
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.2 CI runs on pull requests
Does every pull request trigger automated checks?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✓ 1 workflow file(s); tornadocash/tornado-classic-ui (archived) ✗ 1 workflow file(s); tornadocash/tornado-cli (archived) ✗ no .github/workflows; tornadocash/tornado-relayer (archived) ✓ 1 workflow file(s); tornadocash/tornado-governance (archived) ✓ 1 workflow file(s); tornadocash/tornado-subgraph (archived) ✓ 1 workflow file(s); tornadocash/websnark (archived) ✗ no .github/workflows; tornadocash/snarkjs (archived) ✗ no .github/workflows; tornadocash/circomlib (archived) ✗ no .github/workflows
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.3 Tests run in CI
Do the CI workflows run the test suite?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✓ test command in a workflow; tornadocash/tornado-classic-ui (archived) ✗ test command in a workflow; tornadocash/tornado-cli (archived) ✗ test command in a workflow; tornadocash/tornado-relayer (archived) ✓ test command in a workflow; tornadocash/tornado-governance (archived) ✓ test command in a workflow; tornadocash/tornado-subgraph (archived) ✗ test command in a workflow; tornadocash/websnark (archived) ✗ test command in a workflow; tornadocash/snarkjs (archived) ✗ test command in a workflow; tornadocash/circomlib (archived) ✗ test command in a workflow
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.4 Coverage reported
Is test coverage measured and reported (the partner expects 85%)?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✓ coverage tooling referenced; tornadocash/tornado-classic-ui (archived) ✗ coverage tooling referenced; tornadocash/tornado-cli (archived) ✗ coverage tooling referenced; tornadocash/tornado-relayer (archived) ✗ coverage tooling referenced; tornadocash/tornado-governance (archived) ✓ coverage tooling referenced; tornadocash/tornado-subgraph (archived) ✗ coverage tooling referenced; tornadocash/websnark (archived) ✗ coverage tooling referenced; tornadocash/snarkjs (archived) ✗ coverage tooling referenced; tornadocash/circomlib (archived) ✗ coverage tooling referenced
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.5 Versioned releases
Are releases tagged with immutable semantic versions?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✗ latest tags: v2.1, v2.0, 1.0; tornadocash/tornado-classic-ui (archived) ✗ no tags; tornadocash/tornado-cli (archived) ✗ no tags; tornadocash/tornado-relayer (archived) ✓ latest tags: v5.0.0-beta.12, v5.0.0-beta.11, v5.0.0-beta.10; tornadocash/tornado-governance (archived) ✓ latest tags: v3.0.0, v2.0.0, v1.0.3; tornadocash/tornado-subgraph (archived) ✗ no tags; tornadocash/websnark (archived) ✓ latest tags: v0.0.10, v0.0.9, v0.0.8; tornadocash/snarkjs (archived) ✓ latest tags: v0.1.20, v0.1.19, v0.1.18; tornadocash/circomlib (archived) ✓ latest tags: v0.2.4, v0.2.3, v0.2.2
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.6 Signed tags or commits
Are release tags or recent commits cryptographically signed?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✓ 7 of 10 recent commits signed; tornadocash/tornado-classic-ui (archived) ✓ 10 of 10 recent commits signed; tornadocash/tornado-cli (archived) ✗ 3 of 10 recent commits signed; tornadocash/tornado-relayer (archived) ✗ 0 of 10 recent commits signed; tornadocash/tornado-governance (archived) ✗ 1 of 10 recent commits signed; tornadocash/tornado-subgraph (archived) ✗ 3 of 10 recent commits signed; tornadocash/websnark (archived) ✗ 0 of 10 recent commits signed; tornadocash/snarkjs (archived) ✓ 8 of 10 recent commits signed; tornadocash/circomlib (archived) ✓ 8 of 10 recent commits signed
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.7 Changelog
Is a changelog maintained with the code?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✓ 3 release(s) with notes; tornadocash/tornado-classic-ui (archived) ✗ no changelog or release notes; tornadocash/tornado-cli (archived) ✗ no changelog or release notes; tornadocash/tornado-relayer (archived) ✓ 9 release(s) with notes; tornadocash/tornado-governance (archived) ✗ no changelog or release notes; tornadocash/tornado-subgraph (archived) ✗ no changelog or release notes; tornadocash/websnark (archived) ✗ no changelog or release notes; tornadocash/snarkjs (archived) ✗ no changelog or release notes; tornadocash/circomlib (archived) ✗ no changelog or release notes
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
B9.8 Contribution and branching model documented
Does the README or contribution guide state how changes are proposed, reviewed and released?
Evidencedsome of 9 repo(s): tornadocash/tornado-core (archived) ✗ none found; tornadocash/tornado-classic-ui (archived) ✓ CONTRIBUTING file; tornadocash/tornado-cli (archived) ✗ none found; tornadocash/tornado-relayer (archived) ✗ none found; tornadocash/tornado-governance (archived) ✗ none found; tornadocash/tornado-subgraph (archived) ✗ none found; tornadocash/websnark (archived) ✗ none found; tornadocash/snarkjs (archived) ✗ none found; tornadocash/circomlib (archived) ✗ none found
source 1 · source 2 · source 3 · source 4 · source 5 · source 6 · source 7 · source 8 · source 9
Architecture documentation
B10.1 Architecture documentation
Is there a public architecture document covering logical, infrastructure and integration architecture and the components used?
EvidencedLogical view only. The tornado-core README describes the deposit, commitment, proof and withdrawal design with a diagram and gas and circuit specs; there is no infrastructure or integration architecture document (the linked whitepaper URL on tornado.cash does not resolve).
source 1
Commercial and financial
B11.1 Contracting entity
Which legal entity would an institution contract with, and in which jurisdiction?
N/A: falls to the institution
implied from the component list
B11.2 Funding of ongoing operation
How is ongoing operation and maintenance funded (revenue, foundation, grants, fee switch), per a primary source?
EvidencedNo operator to fund. The pools need no maintenance; relayers fund themselves from withdrawal fees; TORN governance can fund changes to the optional registries, router and frontend by proposal. Public development stopped in 2022.
CROPS S2 · CROPS S2 · CROPS C3 · CROPS O2
B11.3 Termination terms
What happens to customer funds and data on termination by either side?
N/A: falls to the institution
implied from the component list
AI components
B12.1 AI in the payment path
Does an AI system take part in payment processing or compliance decisions (for example automated transaction screening)?
Absent
Searched: the pool contracts and the core client (no screening of any kind) and the archived classic UI, whose only check is a lookup of the connecting address in the Chainalysis sanctions oracle, a list lookup rather than an AI decision. The build served at tornadocash.eth was not inspected.
CROPS C4 · CROPS C4
B12.2 AI controls documented
If AI is used, are monitoring, validation, override, decommissioning and bias evaluation documented?
N/A: no such service
No AI component was found in the payment path (B12.1 absent).

Scope of assessment

Components in the payment path

ComponentRolePublicLicenceOperatorRequired
Tornado pool instances (4 ETH, 4 DAI, 2 USDC, 2 USDT)contractsYesGPL-3.0none (operator set to zero address; no proxy)Yes
Withdraw verifier and MiMC hashercontractsYesGPL-3.0none (no admin functions)Yes
Withdraw circuit and proving key (tornado-core v2.1 release assets)otherYesGPL-3.0none (static files from the 2020 trusted setup)Yes
Proof-generation client (tornado-core cli.js with websnark, snarkjs, circomlib)sdkYesGPL-3.0userYes
Ethereum mainnet and a JSON-RPC endpoint of the user's choiceledgerYesLGPL-3.0Ethereum validators; RPC chosen by the userYes
tornado-cli (mainnet CLI recommended by the tornado-core README)sdkYesnoneuserNo
TornadoRouter (deposit and relayed-withdraw entry used by the UI)contractsYesMITTORN governance (rescueTokens only; not upgradeable)No
InstanceRegistry and FeeManager (upgradeable proxies)contractsYesMITTORN governanceNo
RelayerRegistry (upgradeable proxy) and registered relayersrelayerYesnoneindependent relayers staking TORN; registry admin is TORN governanceNo
TORN governance (LoopbackProxy, TORN token voting)otherYesMITTORN holdersNo
Classic UI (archived GitHub source; live build on IPFS via tornadocash.eth)frontendYesMITTORN governance controls the tornadocash.eth nameNo
The Graph hosted subgraphs (UI default, hardcoded)indexerYesnoneThe Graph hosted serviceNo
Chainalysis sanctions oracle lookup in the UI (0x40C5…C8fb)otherNoproprietaryChainalysisNo
ip.tornado.cash IP-echo service called by tornado-cliotherNoproprietaryunknownNo

Repositories

Contracts

RoleAddressSource verified
ETH 0.1 pool0x12D6…B8Fc explorer · Sourcifysourcify
ETH 1 pool0x47CE…2936 explorer · Sourcifysourcify
ETH 10 pool0x910C…9DbF explorer · Sourcifysourcify
ETH 100 pool0xA160…f291 explorer · Sourcifysourcify
DAI 100 pool0xD4B8…Cfa3 explorer · Sourcifysourcify
DAI 1000 pool0xFD86…7144 explorer · Sourcifysourcify
DAI 10000 pool (0.7.6 build, no operator)0x0768…2730 explorer · Sourcifysourcify
DAI 100000 pool (0.7.6 build, no operator)0x2377…5334 explorer · Sourcifysourcify
USDC 100 pool0xd96f…4307 explorer · Sourcifysourcify
USDC 1000 pool0x4736…Ba9D explorer · Sourcifysourcify
USDT 100 pool0x169A…D52B explorer · Sourcifysourcify
USDT 1000 pool0x0836…872f explorer · Sourcifysourcify
Groth16 withdraw verifier (all pools)0xce17…557A explorer · Sourcifysourcify
MiMC hasher (generated bytecode)0x8358…28fe explorer · Sourcifynone
TornadoRouter (optional UI path)0xd90e…F31b explorer · Sourcifysourcify
InstanceRegistry proxy (governance admin)0xB20c…A911 explorer · Sourcifysourcify
RelayerRegistry proxy (governance admin)0x58E8…3dF2 explorer · Sourcifysourcify
TORN Governance (LoopbackProxy)0x5efd…A1Ce explorer · Sourcifysourcify

Assessor notes

Unit: 12 Ethereum mainnet pools (ETH 0.1/1/10/100, DAI 100/1k/10k/100k, USDC 100/1k, USDT 100/1k), the shared verifier 0xce17…557A and the hasher 0x8358…28fe. Pool and slot reads are pinned at blocks 26141280 and 26141552, governance and token reads at 26141584, and registry state at 26140925 (publicnode serves only recent blocks, so the reads span several blocks). The github.com/tornadocash org is archived (all 47 repos, last push 2022-08-22). We cite it for the immutable pools and the clients; later community source was not reviewed. Governance: TORN-weighted LoopbackProxy with 72 proposals at our read. Proposal 20 (May 2023) is recorded in S2 from onchain state only. The reported 2024 frontend backdoor was not evidenced from a primary source here and is not scored. The hasher is generated bytecode with no Sourcify record; Etherscan could not be loaded. No transactions, UI runs, traces, or self-host attempts were made.