Part III · Chapter 12 of 43 · Byzantium

EIP-196/197: putting zero-knowledge proofs on-chain

Verifying a zk-SNARK means doing elliptic-curve pairing math — thousands of field operations that, written as EVM bytecode, would cost more gas than an entire block holds. EIP-196 and 197 add that math as native precompiles, so a contract can check a proof in a few cheap calls. It's the quiet enabler of on-chain privacy and every validity rollup.

Updated Jun 24, 2026 · 10 min
Assumed
  • contracts & the EVM
  • precompiles (the idea)

Byzantium, October 2017. The REVERT chapter is the change from that fork you feel every day; this is the one that reshaped Ethereum’s future. It sounds narrow — two opcodes’ worth of elliptic-curve arithmetic — but it’s what first made verifying a zero-knowledge proof on-chain affordable, and from that one capability came private transactions and every validity (zk) rollup. The problem it solves is a brutal cost wall, and the tool it uses — the precompile — is one of Ethereum’s most important escape hatches. Let’s derive it.

1 step The math is too expensive

The problem: pairings don’t fit in a block

A zk-SNARK A zero-knowledge proof that a statement is true (e.g. 'this batch of transactions is valid') which is tiny and fast to check, revealing nothing else. Verifying one requires elliptic-curve operations — in particular a pairing check. is wonderful because it’s small and fast to verify — but “fast” is relative to the operation it needs: an elliptic-curve pairing, plus curve additions and scalar multiplications. Those are heavy number-theory computations over large fields. Written as ordinary EVM bytecode — looping over field arithmetic opcode by opcode — a single verification would run to hundreds of millions of gas, far more than an entire block’s gas limit. On-chain proof verification simply doesn’t fit.

verifying a zk proof needs elliptic-curve pairings zk proof valid? verify it pairing in bytecode thousands of ops block gas limit hundreds of millions of gas — on-chain verification is a non-starter
Verifying a zk proof needs elliptic-curve pairings — thousands of field operations. Implemented as EVM bytecode, one verification costs hundreds of millions of gas, blowing past the entire block gas limit. So checking a proof on-chain is a non-starter.

→ Step 2: let the protocol run the hard part.

2 step Ship it natively

Precompiles: native crypto at reserved addresses

The escape hatch is a precompile A built-in operation exposed at a reserved low address (0x01, 0x02, …). It's called exactly like a contract, but instead of running EVM bytecode the client executes an optimized native implementation, priced at a fixed gas cost reflecting its real work. . Instead of forcing the pairing through the EVM, the protocol provides an optimized native (C/Go) implementation at a reserved address, callable like any contract. EIP-196 adds addition and scalar multiplication on the alt_bn128 curve The elliptic curve (also called BN254) whose operations Byzantium made available: ecAdd at 0x06, ecMul at 0x07, and the ecPairing check at 0x08. Chosen because efficient SNARK systems target it. (ecAdd at 0x06, ecMul at 0x07), and EIP-197 adds the crucial pairing check (ecPairing at 0x08). Each is billed a fixed, modest gas cost matching what the operation actually takes a node — not what it would cost as bytecode.

give the EVM native math at reserved addresses verifier contract CALL 0x08 a CALL precompile · 0x08 alt_bn128 pairing native C/Go · fixed cheap gas 0x06 · ecAdd0x07 · ecMul0x08 · ecPairing the protocol ships the hard crypto natively — priced at its real, low cost now a contract verifies a SNARK in a handful of cheap calls
A verifier contract CALLs a precompile (e.g. 0x08 for the alt_bn128 pairing) just like calling a contract, but the client runs a fast native implementation and charges a fixed low gas cost. EIP-196 adds ecAdd/ecMul (0x06/0x07); EIP-197 adds the ecPairing check (0x08).

→ Step 3: verify anything, reveal nothing.

3 step Proofs on-chain

The payoff: privacy and validity rollups

With the pairing check affordable, a contract can verify a SNARK in a handful of calls — and a SNARK can attest to almost anything while revealing nothing beyond “it’s true.” Two enormous applications grew directly from this. Privacy: a mixer contract can accept a proof that “I own a deposit in this set and haven’t withdrawn it” without revealing which deposit, enabling private transfers (the design behind Tornado Cash and Zcash-style schemes). And scaling: a validity rollup A layer-2 that executes transactions off-chain and posts a single succinct proof to L1 that the whole batch was valid. The L1 contract verifies the proof — cheaply, thanks to the pairing precompile — instead of re-executing every transaction. (zk-rollup) can prove that an entire batch of thousands of L2 transactions was executed correctly, and the L1 contract verifies that one proof instead of re-running the batch.

on-chain proof verification, cheap enough to use verify SNARK private transactions prove validity, hide details validity (zk) rollups one proof = a whole batch the pairing precompile seeded on-chain privacy and zk-rollup scaling
Once a contract can verify a SNARK cheaply, it can accept a proof that something is true while learning nothing else — powering private transactions (prove validity, hide the details) and validity rollups (one proof stands in for a whole batch of L2 transactions).
04 Go Deeper Where to take it from here