Zcash’s Invisible Money Printer: Inside the Orchard Soundness Bug

Zcash’s Invisible Money Printer: Inside the Orchard Soundness Bug

A four-year-old flaw in Zcash’s flagship privacy circuit could have minted counterfeit ZEC that no one would ever be able to see or find out where the tokens are today, thanks to it privacy focused design. The technical story is narrower — and more instructive — than the headlines suggested.

On June 5, 2026, Zcash holders woke up to a disclosure that read like a cryptographer’s nightmare. Shielded Labs, a nonprofit that funds Zcash protocol development, revealed that a critical soundness vulnerability had been living inside Orchard — Zcash’s newest and largest shielded pool — since the pool went live in May 2022. For roughly four years, an attacker who understood the flaw could have forged counterfeit ZEC inside the shielded set, and because of the way Zcash hides transaction data, there would be no cryptographic way to prove afterward whether they had.

The market did what markets do with that sentence. ZEC, which had run above $585 earlier in the year on an institutional privacy bid, lost between a third and half of its value within 24 hours depending on the window, briefly trading near $262 before stabilizing in the mid-$300s. At least one prominent holder, Arthur Hayes, exited his position outright.

This piece walks through what Orchard is, what “soundness” means in a zero-knowledge system, the specific class of flaw at the heart of the bug, what an exploit would and wouldn’t have achieved, why the bug survived four years and four rounds of expert review, how the team responded, and — most usefully — the concrete engineering practices that make this category of failure less likely.

What Orchard Actually is?

Zcash supports two kinds of addresses: transparent ones, which behave like Bitcoin and expose sender, receiver, and amount on a public ledger, and shielded ones, which encrypt those details and prove their validity with zero-knowledge proofs. Over the years Zcash has shipped several generations of shielded pools — Sprout (2016), Sapling (2018), and Orchard (2022) — each a distinct cryptographic construction with its own circuit and parameters.

Orchard was the prestige upgrade. It was the first Zcash pool built on the Halo 2 proving system, and its headline achievement was eliminating the trusted setup that every earlier pool required. A trusted setup is a one-time ceremony that generates secret parameters; if the secrets aren’t destroyed, whoever holds them can forge proofs. Removing that requirement was a multi-year goal for the ecosystem, and Orchard delivered it. Halo 2 uses a recursive, transparent (no-trusted-setup) construction built on the Pasta curves — a cycle of two elliptic curves, Pallas and Vesta — and replaces the pairing-based polynomial commitments of older SNARKs with an inner-product argument.

The irony is hard to miss. Orchard was specifically engineered to remove the most notorious single point of failure in Zcash’s history — and it still shipped with a soundness bug. The trusted setup was gone; the implementation that replaced it had a gigantic hole. By 2026, Orchard held a substantial fraction of all circulating ZEC. That concentration is what turned an abstract circuit defect into a market event.

Soundness, completeness, and the meaning of “under-constrained”

To understand the bug you need two properties that every zero-knowledge proof system is supposed to have.

Completeness means an honest prover with a genuinely valid statement can always produce a proof the verifier accepts. If completeness breaks, legitimate users can’t transact — annoying, but not dangerous to the money supply.

Soundness means a dishonest prover cannot produce an accepted proof for a false statement. If soundness breaks, the system will accept transactions that are mathematically invalid. In a currency, that is the catastrophic direction: a soundness failure lets someone prove they own value they never had.

A zk-SNARK circuit is, mechanically, a system of polynomial constraints over a finite field. The prover supplies a witness — the private inputs — and the circuit checks that the witness satisfies every constraint. The art of circuit design is writing constraints that are satisfiable by exactly the valid witnesses and nothing else. When the constraints are too loose — when they fail to pin down some value the protocol depends on — the circuit is under-constrained. A malicious prover can then choose a witness that satisfies all the written constraints but does not correspond to any honest computation. The proof verifies. The statement is false. Soundness is gone.

Under-constrained circuits are not an exotic failure mode. They are, by a wide margin, the most common serious finding in zero-knowledge audits. A Kudelski Security analysis of the Halo2 ecosystem found that the overwhelming majority of audit findings trace to the circuit layer rather than the underlying proof math — precisely the layer where Orchard’s bug lived. Joe Andrews, CEO of the privacy-focused studio Aztec Labs, put it plainly to Decrypt: under-constrained elliptic-curve checks are among the most common weaknesses in production ZK circuits, and the pattern is not new to Zcash.

This matters for how you read the incident. The Orchard bug was not a break in Halo 2 the cryptography. The math behind the proof system is fine. The flaw was in Zcash’s implementation of a circuit on top of that math — a constraint that was supposed to enforce a check and quietly didn’t.

The Specific Flaw: A Base Point that was never tied down

The bug lived in the halo2_gadgets crate — the Rust library of reusable circuit components (“gadgets”) that the Orchard Action circuit is assembled from — inside the variable-base scalar-multiplication routine, ecc::chip::mul. To understand it you need one fact about how that routine is built.

Scalar multiplication — computing [k]·B for a scalar k and a base point B — is implemented as a double-and-add loop that runs over the bits of k across many rows of the circuit. For efficiency, halo2 uses cheap incomplete-addition formulas in that loop, and — critically — the same base point B must be present on every row. The circuit holds the base coordinates (x_p, y_p) constant from row to row using a selector called q_mul_2, which enforces “the base on this row equals the base on the previous row.”

Here is the defect. That constancy chain made every loop row agree with its neighbour — but nothing ever anchored the chain to the real input base. The per-row coordinates were written into the circuit with assign_advice, which simply places a value in an advice cell the prover is free to choose. They were never bound, via a copy/permutation-equality constraint, back to the actual base point the gadget was supposed to multiply; the constancy chain reached neither the doubling-row anchor nor the complete-addition base anchor at the ends. The loop proved it had used some constant point on every row, never that the constant point was the right one.

The consequence is the cleanest possible illustration of “under-constrained.” A malicious prover could feed the loop a free point B' ≠ B of their choosing. Because of how the high and low halves of the scalar are combined, the gadget would then compute roughly [a]·B + [b]·B' — a value the prover steers through B' — instead of the intended [k]·B. The proof still verifies. Every written constraint is satisfied. The output is simply wrong, in an attacker-chosen direction.

The One-token Mistake

Strip it down and the root cause is a single wrong API call: assign_advice where copy_advice was required. Both put a value in a cell. Only copy_advice also emits an equality constraint tying that cell to another — here, to the genuine base. They look nearly identical at the call site, and the gap between them is the gap between a sound circuit and a forgeable one. This is the same footgun that has produced a long tail of soundness bugs across the industry: Circom’s <-- (assign) versus <== (assign-and-constrain) is the identical trap in a different language. The “roughly two lines” the disclosure refers to are the missing copy-constraints — the fix is, almost literally, changing which function was called.

Counterfeit Money That is Undetectable

Why does a wrong multiplication output let you mint? Because that gadget sits on the path that derives an Orchard note’s nullifier. A nullifier is the unique, deterministic fingerprint a note reveals when it is spent; the consensus rules reject any block containing a nullifier that has already appeared, and that duplicate-rejection is the entire mechanism preventing double-spends in the shielded pool. Nullifier derivation runs through a variable-base multiplication — exactly the gadget that was broken.

So an attacker who can steer that multiplication’s output can produce a different but still-valid nullifier for the same note, as many times as they like. Each spend looks fresh to the network because each nullifier is new, even though the underlying note was already spent. Spend one real note a thousand times and you have manufactured value from nothing inside Orchard. That is the “unlimited counterfeit ZEC in a local regtest” Hornby demonstrated — not infinite global supply (the turnstile blocks that, as we’ll see), but unbounded forging within the pool.

The deployed fix has two visible layers, which is worth understanding precisely:

  1. A corrected circuit with a new verifying key. Because a verifier checks proofs against a pinned verifying key derived from the circuit, you cannot patch a circuit soundness bug with a node software update alone — every node would still be validating against the old, vulnerable key. Changing the key is a consensus change, which is why a hard fork was unavoidable. NU6.2 routes Orchard proofs through a per-circuit verifying key, labeled in Zebra’s code as InsecurePreNu6_2 for the old circuit and FixedPostNu6_2 for the corrected one.
  2. A belt-and-suspenders consensus rule. NU6.2 also added a network rule that rejects Orchard bundles whose proof has a non-canonical size. This is a narrow, encoding-level guard that blocks the malformed-proof shape the exploit relied on, independent of the deeper circuit fix.

The takeaway: the root cause was a constraint gap in the circuit; the remediation swapped in a corrected, re-keyed circuit and hardened proof acceptance at the network layer.

What an attacker could — and couldn’t — actually do

Here is where the headlines and the protocol reality diverge, and where a careful reading pays off.

Shielded Labs described the worst case as the ability to forge an unlimited number of counterfeit ZEC inside the Orchard pool, undetectably. The Zcash Foundation, describing the same bug, framed it as the ability to make Orchard accept invalid state transitions — potentially double-spending within Orchard — with no ability to inflate the total ZEC supply.

Both statements are true, and the reconciliation is the most important technical nuance of the episode: it lives in Zcash’s turnstile mechanism.

The turnstile is a cross-pool accounting invariant. Zcash tracks the total ZEC balance across all five value pools — Sprout, Sapling, Orchard, transparent, and the lockbox — and enforces a hard rule that no more value can leave a pool than has provably entered it. The turnstile doesn’t care about the contents of any individual shielded transaction; it watches the aggregate boundary of each pool.

So picture an attacker exploiting the bug at full tilt. Inside Orchard, they can conjure counterfeit value and shuffle it around invisibly. But the moment they try to withdraw it — to deshield into a transparent address, move it to Sapling, or otherwise exit Orchard — the turnstile checks the aggregate. If they attempt to pull out more than legitimately flowed into Orchard, the network rejects it. The counterfeit is trapped inside the pool.

This converts “unlimited, undetectable inflation of the 21-million ZEC supply” into something bounded and different in kind: the practical ceiling on theft is the total real value sitting in Orchard at the time, and the mechanism is effectively double-spending within the shielded set rather than minting new global supply. That is still a serious, confidence-destroying attack — an exploiter could in principle have drained honest Orchard depositors up to the size of the pool — but it is not the infinite-printing-press scenario, and the network-wide supply cap held throughout. The Foundation confirmed the turnstile showed no unauthorized value creation across the vulnerable window.

The turnstile is the unsung hero here, and it is not a coincidence. It was originally introduced to contain exactly this class of risk after Zcash’s earlier counterfeiting scare — more on that below.

The Residual Problem Privacy Can’t Escape

Even with the turnstile capping the damage, one uncomfortable fact remains, and it is the fact that actually moved the market: you cannot prove the bug was never exploited.

In a transparent chain like Bitcoin or Ethereum, a successful exploit leaves a permanent, public scar. Anyone can audit the ledger after the fact and see anomalous issuance. Privacy is the whole product in Zcash, and the same encryption that protects users from surveillance also erases the forensic trail. Within Orchard, there is no cryptographic method to retroactively distinguish a history that included counterfeit-and-double-spend activity from one that didn’t. The turnstile guarantees the total supply boundary was respected; it cannot reconstruct the internal honesty of the pool.

Shielded Labs was candid about this, stating there is no definitive way, using only cryptography, to determine whether exploitation occurred. The team’s judgment is that exploitation is unlikely — the bug was subtle enough to evade years of expert review, which argues against a random attacker having quietly found it first — but judgment is not proof.

Bitcoin advocates pounced on the structural point. AnchorWatch’s Rob Hamilton argued bluntly that this will happen again in Zcash and that you’ll never be able to prove it, because the supply isn’t auditable. Even sympathetic voices from the privacy world conceded the tradeoff is real. Cake Wallet’s COO, who goes by Seth for Privacy, declined to dunk on Zcash and called undetectability a natural downside of building privacy in as the default. Nic Carter of Castle Island Ventures framed the privacy-versus-auditability tension as “basically part of the deal” for anyone who’s followed the space.

That is the durable lesson of the Orchard bug, independent of this specific flaw: strong privacy and trustless supply-auditability are in tension, and a privacy chain has to buy back auditability deliberately through mechanisms like the turnstile — because the ledger won’t give it to you for free.

Why it survived four years — and the AI in the room

The most unsettling line in the disclosure is the timeline. The flaw was present from Orchard’s activation in May 2022, and it survived multiple rounds of review by some of the most experienced zero-knowledge cryptographers in the world. Orchard’s circuit was not a weekend project; it was scrutinized extensively and yet two lines of under-constraint code sat undisturbed for four years.

Why would a one-token error survive that scrutiny? The answer is structural, and it generalizes far beyond Zcash. Five properties of this bug class make it close to invisible to conventional review.

It is negative space, not a wrong line. Auditors are good at reading a constraint and asking “is this correct?” They are far worse at the inverse question, “is there a constraint that should be here and isn’t?” A missing copy_advice leaves nothing on the page to flag. To catch it you must independently re-derive the complete set of constraints the gadget needs and differentiate that mental model against what the code actually emits — a far harder task than reviewing what’s written, and one almost no one does exhaustively for every gadget.

Completeness hides it perfectly. The flaw is only reachable by a prover who deliberately witnesses a wrong base. Every honest prover — every wallet, every test vector, every integration test, every mainnet transaction for four years — supplies the correct base, so the gadget produces the correct output every single time in honest use. The bug emits zero symptoms under normal operation and cannot be caught by functional testing, because functional tests use honest inputs by definition. Soundness bugs are invisible to the entire discipline of “does it work?” testing; they only surface under “can it be made to lie?” testing.

It hid in the seam between library and application. halo2_gadgets is a general-purpose library; the Orchard circuit composes it. Engineers auditing Orchard could reasonably treat ecc::chip::mul as a vetted, widely-used primitive and look elsewhere. Engineers auditing the gadget library lacked the Orchard-specific context for why anchoring the base mattered so much. The defect lived precisely in the handoff — “the library is correct in general” and “the library is used correctly here” are different claims, and the gap between them is where this bug nested.

Removing the trusted setup moved the scrutiny away from the failure site. This is the subtle one. Sprout and Sapling had trusted-setup ceremonies, and everyone knew the setup was the scary part — so the field’s attention, and its most paranoid cryptographers, concentrated on the parameters. Orchard’s headline achievement was eliminating that ceremony. But “no trusted setup” quietly relocated 100% of the soundness risk into the circuit constraints — the exact layer that the trusted-setup era had trained everyone to worry about less. The marketing win and the security blind spot were the same design decision.

The trigger lives in a measure-zero set. Even fuzzing struggles here. Random inputs drawn from an honest prover’s distribution never exercise “substitute a different base point”; you only reach the bug by adversarially constructing a witness that violates an equality the circuit forgot to enforce. Conventional fuzzers explore the honest input space. They were never going to land on this.

That last property is exactly why the discovery method mattered as much as the discovery.

What found it, in the end, was a combination that did not exist a year earlier. Shielded Labs had engaged independent security researcher Taylor Hornby in April 2026 specifically to hunt for protocol-level vulnerabilities before attackers could. On May 28, 2026, Anthropic released Claude Opus 4.8. The next day, Hornby paired the new model with a custom AI auditing framework and ran a targeted review of the Orchard circuit. By the end of May 29, he had located the vulnerability, written a complete working exploit, and confirmed in a local test environment that it generated counterfeit ZEC. Shielded Labs verified the same exploit would have worked against mainnet before the patch.

This is the genuinely new variable, and the experts quoted in the coverage are split on what it means. Carlos Guzman of GSR called the implications “a little bit concerning,” noting that there aren’t many people who understand these circuits, which has historically made them hard to attack — but that AI is democratizing the ability to find bugs in them. Aztec’s Andrews observed that AI is accelerating the rate of such discoveries across the whole industry.

The double-edged nature is the point. The same capability that let a friendly researcher find this bug in a day is available, in principle, to an adversary. The asymmetry that historically protected obscure cryptographic code — “only a handful of people on earth can read this” — is eroding. For every protocol relying on the scarcity of circuit expertise as a de facto security control, that is a warning shot. The defensive implication is not “stop using AI”; it is “assume attackers have it too, and get to your own bugs first.”

The response: a textbook coordinated disclosure

If the bug is the cautionary half of the story, the response is the encouraging half. The remediation is close to a model of how a security-critical, consensus-level fix should be handled on a live network.

The sequence:

  • May 29 (evening): Hornby discloses to ZODL core engineers Daira-Emma Hopwood, Kris Nuttycombe, and Jack Grigg, who confirm the issue within hours.
  • May 31: Private coordination begins with miners and exchanges. Details are kept tightly held to avoid tipping off potential attackers before a fix is live.
  • June 2 (~02:00 UTC): An emergency soft fork (Zebra 4.5.3) activates at block height 3,363,426, with nodes rejecting all Orchard-containing transactions. Critically, the team did not ship the real fix first. A direct circuit patch would have revealed the flaw to anyone reading the diff; disabling Orchard wholesale bought time to finalize the corrected circuit without publishing a roadmap to the exploit.
  • June 3 (00:05 EDT): The NU6.2 hard fork (Zebra 5.0.0) activates at block height 3,364,600, re-enabling Orchard with the corrected, re-keyed circuit and the non-canonical-proof-size rule. Transparent and Sapling transactions ran normally throughout.
  • June 5: Public disclosure, after the network was already safe.

The full arc from private report to a fixed, re-enabled network took about five days. This was only the second security-driven protocol upgrade in Zcash’s history. The two-phase structure — disable first, fix second — is the part worth internalizing: when the patch itself is a map to the vulnerability, hiding the patch behind a feature kill-switch is the correct disclosure hygiene.

The one rough edge: during the transition some block explorers briefly showed no new blocks as miners and node operators scrambled to upgrade, which fueled momentary confusion that the chain had halted. It hadn’t, but it’s a reminder that emergency upgrades stress the whole operational supply chain, not just the core devs.

This has happened before — and the pattern is the lesson

Zcash has been here once already, and the comparison is illuminating.

In March 2018, cryptographer Ariel Gabizon — then at the Electric Coin Company — discovered a soundness flaw in BCTV14, the zk-SNARK construction underpinning the original Sprout pool (later catalogued as CVE-2019-7167). The trusted-setup parameter-generation procedure described in the BCTV14 paper inadvertently produced extra “bypass elements” that, if recovered from the setup transcript, let an attacker forge valid-looking proofs and counterfeit an unlimited amount of shielded ZEC — again, undetectably. The flaw had survived expert analysis for years; an earlier review had even caught a different mistake in the same paper while missing this one.

The fix was the Sapling upgrade of October 2018, which moved Sprout onto a new Groth16-based circuit with fresh parameters. And the containment mechanism introduced to ring-fence the still-vulnerable Sprout pool was — the turnstile. The 2026 turnstile that capped Orchard’s damage is the direct descendant of the control built to survive the 2018 scare. Zcash’s competitor Monero had its own analogous moment: a 2017 CryptoNote bug that allowed unlimited coin creation.

Put the two Zcash incidents side by side and the deeper pattern emerges:

Sprout (2018/19) Orchard (2026)
Layer of failure Protocol / trusted-setup parameters Implementation / circuit constraints
Proof system BCTV14 (trusted setup) Halo 2 (no trusted setup)
Root cause Setup produced soundness-breaking elements Unanchored base in EC multiplication (missing copy-constraint)
Detection Expert cryptographer, by hand Researcher + frontier AI model
Years undetected ~2 ~4
Containment Turnstile (introduced) Turnstile (inherited)
Inflation risk Capped to pool by turnstile Capped to pool by turnstile

The defining irony connects them: Orchard’s entire reason for existing was to eliminate the trusted setup that caused the first counterfeiting scare. It succeeded at that — and the soundness risk simply migrated one layer down, from the parameters to the circuit constraints. Removing one class of single point of failure doesn’t remove the category of soundness risk; it relocates it. That is the most important strategic lesson of the whole saga.

How Zcash’s architecture compares — and where the risk really lives

The Orchard bug is inseparable from a set of architectural choices Zcash made. Seeing those choices against the wider privacy and ZK landscape is what tells you whether your favorite system is exposed to the same class of failure, even though it will never have this exact bug.

There are two architectural axes that matter most. The first is where soundness ultimately rests: in a trusted-setup ceremony, or purely in the circuit. The second is whether the circuit is bespoke or general-purpose: hand-written for one application, or a reusable virtual machine that many applications share. The Orchard incident is what happens at one specific corner of that grid — transparent setup, bespoke hand-optimized circuit — and the corner you sit in determines your exposure.

Three Generations Inside Zcash Itself

Zcash is unusual in that it has shipped three fundamentally different proving architectures, and each moved the soundness risk somewhere new.

Sprout (2016) used the BCTV14 zk-SNARK over R1CS with a per-circuit trusted setup. Soundness depended on both the ceremony secrets being destroyed and the circuit being correct. Its 2018 counterfeiting flaw lived in the setup construction — the parameters themselves were unsound.

Sapling (2018) moved to Groth16 over BLS12-381, still a per-circuit trusted setup but with a far more robust multi-party ceremony. Proofs shrank to a famously compact 192 bytes. The soundness root was still setup-plus-circuit.

Orchard (2022) switched to Halo 2: PLONKish arithmetization, the Pallas/Vesta (“Pasta”) curve cycle, and an inner-product-argument commitment with no trusted setup at all. This was the prestige upgrade — and it is the crux. Eliminating the ceremony didn’t eliminate soundness risk; it concentrated 100% of it into the circuit constraints. Halo 2 also buys its flexibility with hand-written custom gates and hand-optimized gadgets like the variable-base multiplication that broke. More expressive power and no setup safety-net means a larger, subtler circuit surface — exactly where an unanchored base point can hide.

The throughline: each generation removed the previous era’s scariest single point of failure and relocated the risk one layer down. Orchard reached the bottom layer — the raw constraints — and that is where 2026’s bug was waiting.

Possibility of Bugs in Other Privacy Chains

Monero is the instructive opposite, because it doesn’t use a general proof circuit at all. Privacy comes from a fixed menu of specific primitives: CLSAG ring signatures for sender ambiguity, stealth addresses for the receiver, and Pedersen commitments with Bulletproofs+ range proofs for hidden amounts. There is no “Orchard circuit” equivalent that could be under-constrained, because there is no arbitrary arithmetization — each rule is a named, individually specified cryptographic protocol. That smaller, fixed surface is arguably easier to audit completely, and it is why Monero cannot have this bug. But it is not safer in general: Monero’s 2017 unlimited-creation flaw was a key-image double-spend bug in the CryptoNote protocol logic, and Bulletproofs themselves can harbor soundness defects. Monero trades circuit flexibility (and some per-transaction privacy strength, since ring sizes are bounded) for a narrower attack surface.

Tornado Cash and the typical Circom + Groth16 application sit in the trusted-setup, bespoke-circuit corner. Their circuits are tiny and single-purpose (deposit and withdraw a fixed denomination), so the surface is far smaller than Orchard’s full shielded-payment statement. But Circom is notorious for exactly this bug class: its <-- (assign) versus <== (assign-and-constrain) distinction is the identical footgun to halo2’s assign_advice/copy_advice, and a long list of real-world Circom exploits are missing-constraint bugs. Small circuit, same trap.

StarkNet / Cairo sits in the most structurally different corner: transparent setup, general-purpose VM. Cairo programs run on a single VM whose AIR (the STARK equivalent of the circuit) is written and audited once and reused by every application. FRI-based STARKs need no trusted setup and are plausibly post-quantum. The key contrast with Zcash is amortization: a zkVM concentrates the enormous cost of getting the constraints right onto one artifact that receives correspondingly enormous scrutiny, instead of asking every application to hand-roll — and independently get right — its own circuit. Aleo (snarkVM, with a universal/updatable setup) and general proving stacks like RISC Zero and SP1 follow the same zkVM philosophy.

Aztec occupies roughly Zcash’s neighborhood — application-specific privacy circuits — but writes them in the higher-level Noir language (over a PLONK-family backend). It is no accident that Aztec’s CEO is the one in the coverage advocating dual proving systems; living in the bespoke-circuit corner is what makes that defense feel necessary.

Mina is the most pointed comparison of all, because Kimchi — its PLONK variant — runs on the same Pasta curves as halo2, a shared lineage that traces back to Daira-Emma Hopwood (one of the engineers who confirmed the Orchard bug). Mina shares much of the gadget heritage Orchard’s broken multiplication came from. That does not mean Mina has this bug — it is a separate codebase — but it is precisely the kind of system whose maintainers should re-audit their variable-base multiplication for an analogous unanchored-base pattern. Shared cryptographic ancestry means shared classes of risk.

The Lesson for Developers and Examiners

Put plainly: the systems most exposed to an Orchard-style soundness bug are the ones in the bespoke-circuit corner — Zcash, Aztec apps, Circom/Tornado-style deployments — where humans hand-write and hand-optimize constraint systems for a specific statement. Transparent setup (Halo 2, STARKs) is a genuine improvement that removes the ceremony as an attack surface, but it raises the stakes on the circuit, because there is no longer any other place for soundness to come from. And the single biggest structural mitigation available — visible in the Cairo/Aleo/zkVM model — is to stop hand-writing one-off circuits and instead concentrate scrutiny on a single, heavily-verified, reusable one. Zcash chose bespoke for performance: a hand-tuned shielded-payment circuit is dramatically more efficient than the same logic on a general VM. The Orchard bug is, in a real sense, the bill for that performance.

The Orchard bug is not going to bite another chain directly — it was an implementation-specific defect in Zcash’s own code. But the class of bug is endemic to every system that secures money with hand-written ZK circuits, and the practices that would have caught it are general. Here is what meaningfully reduces the odds of a repeat, roughly in order of leverage.

1. Formally verify the circuit, not just audit it. Manual audits and expert eyes found neither this bug nor the 2018 one for years; human review is necessary but demonstrably insufficient for soundness. Formal verification flips the burden of proof: instead of searching for a counterexample, you mechanically prove that no witness satisfies the constraints unless the underlying statement is true. An under-constrained gadget cannot pass a verification obligation that asserts the constraints uniquely determine the output — the proof simply fails to discharge at build time, where the gap announces itself loudly instead of sitting silent for four years. The Rust ecosystem Zcash’s circuits are written in already has formal-methods tooling; the reason it isn’t used everywhere is cost and deadline pressure, not feasibility. The Zcash Foundation has since committed to formally verifying the Orchard circuit. For any pool guarding nine figures of value, formal verification of the soundness-critical gadgets should be table stakes, not a stretch goal.

2. Run two independent proof systems and require both to agree. Aztec’s Andrews pointed to the strongest structural defense: a second, independently implemented proof system checking the same statement, where a transaction is valid only if both systems accept it. For an attacker to forge a proof, they’d have to find correlated soundness bugs in two separately built circuits simultaneously — astronomically less likely than one. Ethereum is already planning this kind of multi-prover redundancy for its ZK roadmap. The cost is real (you maintain and prove against two systems), but for high-value settlement it converts a single point of cryptographic failure into a conjunction of independent ones.

3. Deploy automated under-constraint detection in CI. A growing class of specialized tools exists specifically to detect under-constrained signals in arithmetic circuits — static analyzers and SMT-backed checkers (in the Circom world, tools in the spirit of Picus, Ecne, and circomspect; analogous tooling is maturing for the halo2/PLONKish stack). These tools systematically ask “is every output value uniquely determined by the constraints?” — the exact question a human reviewer is bad at answering exhaustively. Wiring them into continuous integration means a newly introduced under-constraint fails the build, not the mainnet.

4. Fuzz and differentially test the circuit against a reference. Property-based fuzzing that feeds adversarial and exceptional inputs — points at infinity, equal points, boundary scalars — into circuit gadgets can surface incomplete-addition edge cases that ordinary unit tests, which exercise honest inputs, never reach. Pair this with differential testing: run the circuit’s logic against an independent, naïve, obviously-correct reference implementation and flag any divergence. Many circuit bugs are exactly the cases where the optimized path and the naïve path disagree.

5. Constrain the exceptional cases of every optimized formula explicitly. The proximate engineering lesson: incomplete/efficient elliptic-curve formulas carry an obligation to fence off their exceptional inputs, and that fence must be an enforced constraint, never an assumption, a comment, or a debug_assert that compiles out of release builds. A documented assumption that “this input is never the identity” is worthless to the verifier if nothing in the constraint system enforces it. Every place a circuit trades completeness for performance should have a corresponding, reviewed, test-covered guard constraint — and a checklist that maps each optimization to its guard.

6. Build supply-auditability in from day one — turnstiles and proof-of-supply. The turnstile is why this was a contained scare rather than an extinction event, and it is a design choice every privacy system should copy: enforce hard, publicly checkable invariants on value crossing pool boundaries so the worst case is bounded by pool size rather than infinite. Shielded Labs’ proposed follow-up goes further — a new shielded pool that routes all coins exiting Orchard through turnstile accounting, letting anyone independently verify that no counterfeit ZEC escapes. The frontier of this idea is proof-of-supply: cryptographic attestations that the shielded supply equals what was legitimately issued, ideally without forcing users to move funds. A privacy chain that can periodically prove “the books balance” buys back much of the auditability that encryption takes away.

7. Treat continuous adversarial review — including AI-assisted — as standing infrastructure. This bug was found because Shielded Labs paid someone to look for it before an attacker did, and equipped them with the newest tooling available. That posture should be permanent, not a one-off audit before launch. Standing security researchers, well-funded bug bounties scaled to the value at risk, and active use of frontier models for circuit review are now part of a serious privacy protocol’s baseline. The democratization of bug-finding cuts both ways; the only safe assumption is that adversaries have the same tools, so the defensive side has to run continuously and stay ahead.

8. Rehearse the emergency-upgrade path before you need it. Zcash’s response worked because the machinery already existed: responsible-disclosure channels, engineers with deep protocol context, and a network of miners, exchanges, and node operators who could coordinate a soft fork and hard fork in days. The two-stage “disable first, patch second” playbook — hiding the fix behind a feature kill-switch when the patch itself reveals the exploit — is worth codifying as a standard incident-response pattern. A protocol that has never tested whether it can push an emergency consensus change will discover the answer at the worst possible moment.

Strip away the price chart and the Federal-Reserve metaphors, and the Orchard incident resolves into something specific and teachable. A single under-constrained elliptic-curve gadget — the kind of bug that tops every ZK audit’s findings list — slipped into Zcash’s most advanced privacy circuit and survived four years of expert scrutiny. The damage was real in potential but bounded in practice, because a decade-old accounting invariant did exactly the job it was built for. The flaw was caught by a researcher with a new AI tool, fixed in five days through a disciplined coordinated disclosure, and left behind one genuinely unanswerable question: in a system designed to forget, you can patch the hole but you can never fully prove no one used it.

Zcash’s privacy didn’t fail. Its accounting circuit nearly did, and its safety net held. The work ahead — formal verification, dual proving, and trustless supply attestation — is the unglamorous engineering that turns “we believe it wasn’t exploited” into “we can prove the books balance.” For an asset whose entire value proposition is that you can’t see inside it, that proof is the thing worth building next.

Mahboob holds more than two decades of development exp: with 7 years of those being involved Blockchain and Web3. He has founded and lead multiple ventures and teams before the advent of AI.

20 Articles
Blockcritics Alerts / Sign-up to get alerts on hackathons, new products, apps, contracts, protocols and breakthroughs in web 3.0.