# Poseidon vs. MiMC

TONado Cash uses Poseidon as its core hash function. Tornado-EVM used MiMC. This page explains why.

## What is a "SNARK-friendly" hash?

A hash inside a SNARK circuit needs to be **cheap to express as arithmetic constraints**. SHA-256, the everyday cryptographic hash, has bit-manipulation operations (rotations, AND, XOR) that are extremely expensive in a SNARK; encoding one SHA-256 block can cost tens of thousands of constraints.

SNARK-friendly hashes do the opposite: they're designed to be **field-native**, expressing rounds as polynomial operations over the SNARK's scalar field. The result is hash functions that are dramatically cheaper inside a circuit, at the cost of being more expensive when run outside a circuit on conventional hardware.

The two most-deployed SNARK-friendly hashes are:

* **MiMC**, published in 2016. Used by Tornado-EVM, Iden3, and others.
* **Poseidon**, published in 2019. Used by Zcash Sapling, Aztec, Filecoin, and many newer protocols.

## Why Tornado-EVM used MiMC

MiMC was the natural choice for an Ethereum-era Groth16 application:

* The `circomlib` MiMC implementation existed and was reviewed.
* MiMC's round constants over BN254 (Ethereum's curve) were well-studied.
* The Tornado team wasn't ZK-research-driven; they used the standard tools.

It worked. Tornado-EVM ran for years.

## Why TONado Cash switched to Poseidon

Three reasons.

### 1. Field-parameter flexibility

MiMC's specification was originally tuned for BN254. Poseidon, by contrast, is **explicitly defined over an arbitrary prime field**. The spec gives you a recipe for deriving round constants for any field that meets certain conditions (essentially: large enough prime, well-distributed structure).

Since TONado Cash uses BLS12-381, not BN254, every constant in the hash function has to be regenerated. Poseidon makes this straightforward: pick the prime, run the constant-generation procedure, done. MiMC requires more careful re-analysis to confirm the new constants don't open up algebraic attacks.

### 2. Ecosystem standardization

The TON ZK ecosystem (such as it is in 2026) standardizes on Poseidon. So do almost all post-2020 ZK projects. Picking Poseidon means:

* The on-chain Tolk Poseidon implementation can reuse community-vetted constants.
* Future cross-protocol composability. For example, if TON eventually has a generalized ZK rollup, it almost certainly speaks Poseidon.
* The off-chain prover code uses the same `circomlib/circuits/poseidon.circom` module that hundreds of other projects do.

MiMC, by contrast, is increasingly considered legacy. Tornado-EVM is the largest active deployment.

### 3. Better understood algebraic security

The hash function security argument boils down to: *no efficient algorithm finds a collision or pre-image in fewer round-trips than brute force.* Both MiMC and Poseidon have been studied. As of 2026, Poseidon has had more recent analysis (including specific looks at Poseidon-over-BLS12-381) and the consensus is that its 8-full-rounds + N-partial-rounds parameter family resists known algebraic attacks (Gröbner basis, interpolation, statistical).

This isn't a knock on MiMC. It's a reflection of where research attention has gone.

## What we kept from circomlib

TONado Cash imports `circomlib/circuits/poseidon.circom` directly inside the withdraw circuit. The circomlib Poseidon was originally designed for BN254, but the *parameters* it picks (round counts, MDS matrix structure) are field-independent. Only the **constants** have to be regenerated for BLS12-381, and that's a mechanical operation.

A detail worth being aware of: the circomlib Poseidon constants are derived deterministically from a "domain separator" string. Reducing those constants modulo BLS12-381's scalar field doesn't introduce known weaknesses, but a cryptographer sign-off on this specific reduction is on the [mainnet launch plan](/operations/mainnet-launch-plan.md) before we ship to mainnet.

## What "Poseidon-3" and "Poseidon-2" mean

In TONado Cash you'll see references to two Poseidon variants:

* **Poseidon-2**: 2 input field elements → 1 output. Used for the commitment: `commitment = Poseidon(nullifier, secret)`.
* **Poseidon-3**: 3 input field elements → 1 output. Used for Merkle tree internal nodes: `parent = Poseidon(left, right, level_marker)`. (The Merkle implementation can also use Poseidon-2; circomlib supports both, the exact arity is a constant of the implementation.)

Each arity has its own round-constant table. Both are imported from circomlib.

## Parity is critical

There are three places Poseidon is evaluated:

1. **The off-chain prover** ([`packages/core/src/poseidon.ts`](https://github.com/tonadocash/monorepo/blob/main/packages/core/src/poseidon.ts)): uses the circom-compiled WASM, so it's the same code as the circuit.
2. **The circuit**: runs inside the SNARK at proving time.
3. **The on-chain Tolk verifier**: verifies a Groth16 proof; doesn't itself execute Poseidon. (In the current design, the pool delegates *all* Poseidon evaluation to off-chain provers + proofs.)

These have to agree byte-for-byte on any input or proofs won't verify. The build has a parity-check script ([`apps/contracts/scripts/check-poseidon-parity.ts`](https://github.com/tonadocash/monorepo/blob/main/apps/contracts/scripts/check-poseidon-parity.ts)) that runs in CI to catch any drift.

## What changes if Poseidon is broken

If a researcher finds an efficient collision attack on Poseidon-over-BLS12-381:

* An attacker can construct two distinct `(nullifier, secret)` pairs with the same commitment, allowing them to "withdraw" your deposit by producing a proof keyed to their own preimage.
* The fix is to migrate to a new hash function (perhaps a different parameterization of Poseidon, or a switch to another SNARK-friendly hash like Anemoi or Reinforced Concrete), and to deploy v2 pools with the new circuit.

This is a generic risk for any SNARK-using protocol, no different from "what happens if SHA-256 is broken" for general cryptography. The protocol's modular design (separate `verifier.tolk` per pool) lets us migrate without rewriting the contracts from scratch.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tonadocash.com/how-it-works/poseidon-vs-mimc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
