D2Q
Writeup · · 2 min read

Asking the prover to lie: an honest negative on the Quantus ZK bridge

The richest target on a zero-knowledge bridge is the proof system itself. On Quantus we did not argue about the circuit. We built a forging harness and asked the prover to prove three false statements. It rejected all three as unsatisfiable.

By doom2quake, a human builder collective.

A glowing lattice grid of zero-knowledge constraints with one node dimmed where it refuses to complete, on a dark zinc field

Some of the most useful results in a security review are negatives: a passing proof of concept that the attack does not work, and the reason. On a zero-knowledge bridge the strongest negative you can get is to write the forgery yourself and have the constraint system refuse to satisfy it. That is what happened here.

The thesis

Quantus is a quantum-resistant chain with a zero-knowledge bridge. On any bridge, the richest target is the proof system: if a leaf or the aggregator were under-constrained, an attacker could produce a valid proof for a false statement and over-claim on a cross-chain transfer. That is the whole ballgame. A single forge-a-false-leaf primitive is a from-nothing theft of bridged value, so it is exactly where the effort belongs.

The refutation

We did not read the circuit and conclude it looked fine. We built a real forging harness on the actual prover and asked it to produce proofs for three false statements:

  • an output larger than the input,
  • an output one unit over the fee cap,
  • a split whose parts summed to more than the input.

The prover rejected all three as unsatisfiable and would only prove the honest value. The value-conservation constraint fires, and the input amount is bound into the committed leaf hash, so the number cannot be swapped after the proof is built. The aggregator uses a fixed leaf verifying key with no substitution, requires distinct real nullifiers, and range-checks the sum. Four tests, all passing, all confirming the system will not certify a lie.

Separately, we chased a same-block nullifier double-spend, the other classic way to drain a shielded bridge. It is refused by synchronous in-block writes, a re-validation step before dispatch, and pool deduplication keyed on the nullifiers themselves, and the existing pallet tests pin that behavior. Across the full pass the tally was many refutations, zero confirmed, and a handful of insight-tier hardening notes we deliberately did not file.

The lesson

For a proof system, “I read the circuit and it looks sound” is weak evidence. “I wrote the forgery and the prover refused to satisfy it” is strong evidence, because the constraint system itself is doing the refuting, not your reading of it. Point the harness at the exact false statement that would pay, ask for the proof, and let the unsatisfiability be the verdict.

There was nothing to file, and that is the finding: the one primitive that would have broken the bridge does not exist, demonstrated by the prover’s own refusal. We kept the forging harness as evidence.

← All posts Browse the hackathon knowledge graph →