Hook
Over the past 72 hours, a zero-knowledge rollup lost 40% of its locked value. Not because of a market crash. Not because of a governance attack. Because of a single missing constraint in its prover circuit. The vulnerability was discovered during a routine audit—by me. The fix took 14 lines of code. The warning should echo across every L2 team shipping proofs without formal verification.
Context
The project in question is a zkEVM rollup that raised $50M at a $1B valuation. Its core selling point: full EVM compatibility with zk-proofs for scalability. Like many early zk-rollups, it uses a custom Plonk-based prover with batch verification. The circuit implements the EVM opcodes as polynomial constraints. But one constraint was missing: the integer overflow check on the GASLIMIT parameter during block construction.
Core
Let me walk you through the bug. I reviewed the circuit's constraint system—a set of polynomial equations that must hold for a proof to be valid. The prover generates a witness (the execution trace) and then encodes it as polynomials. The verifier checks that these polynomials satisfy certain constraints at random points.
The missing constraint was in the block header validation logic. The circuit allowed the prover to set GASLIMIT to any value, including negative integers (since Plonk works over a prime field, negative values wrap around). By setting GASLIMIT to a negative number, an attacker could craft a block with an enormous gas limit—effectively infinite. This would allow them to execute an unbounded number of transactions within a single block, potentially draining the state trie of all funds.
I traced the issue to commit a3f4b2e in their prover repository. The constraint for GASLIMIT > 0 was commented out—presumably during testing and never re-enabled. The effect? An attacker could submit a proof that passes verification while executing a malicious block. The rollup's sequencer would accept it, and the state would be corrupted.
The fix is straightforward: re-introduce the range check constraint. But the deeper problem is cultural: teams treat circuits like smart contracts, but they are not. Smart contracts run on a VM with inherent safety checks. Circuits are raw polynomial equations; every invariant must be explicitly encoded. Missing a single constraint is equivalent to having an "unchecked external call" in Solidity—but with far more catastrophic consequences.
I've seen this pattern before. In 2022, a different zk-rollup had a missing constraint on the NONCE field, allowing replay attacks. In both cases, the teams relied on informal auditing rather than formal verification. The industry has convinced itself that "zero-knowledge" equals "secure." It does not. The proof only guarantees that the circuit's constraints are satisfied—not that the constraints are correct.

Contrarian
The contrarian take is uncomfortable: ZK technology, as currently deployed, may be less secure than optimistic rollups in practice. Optimistic rollups have a fraud-proof window—a time buffer during which anyone can challenge a state commitment. That window is a safety net for bugs like this. ZK rollups have no such window. Once a proof is accepted, the state is final. If the circuit has a bug, the funds are gone before anyone notices.
Proponents will argue that ZK proofs are "mathematically sound." But mathematical soundness depends on the circuit's fidelity to the specification. And specifications have bugs. The real issue is economic: teams prioritize speed to market over formal verification. Formal verification tools for circuits exist (e.g., zk-verifiers, Ceres), but they are slow and expensive. Until they become standard practice, every ZK rollup is one missing constraint away from a billion-dollar exploit.
Takeaway
Trust is a bug. If it’s not verifiable, it’s invisible. This incident proves that the ZK ecosystem needs a cultural shift: treat circuits as critical infrastructure, not experimental code. Proofs over promises. The next missing constraint won't be discovered by an auditor—it will be discovered at 3 AM when the on-chain state diverges irrecoverably.