The Shortcut Hiding Inside the EVM

You're staring at a deployment failure. Your zero-knowledge proof verifier compiles clean, the tests pass locally, and then you run the gas estimate and watch the number climb past two million, past five million, past the block limit entirely. The contract is mathematically correct and practically undeployable, which is a specific kind of misery that will make you question your career choices.

And yet zkSNARK verifiers run on Ethereum mainnet every day. So what's actually happening?

Precompiles. A small set of contracts baked directly into the Ethereum client software, running native machine code instead of EVM bytecode. They look like ordinary smart contracts to the caller. They aren't.

What a Precompile Actually Is

In the EVM's execution model, every opcode costs gas because every opcode does real work: the network prices computation to prevent abuse. A simple ADD costs 3 gas. A KECCAK256 hash costs 30 gas plus 6 per word. The pricing reflects actual CPU cycles, loosely.

Now imagine verifying an ECDSA signature in a smart contract. The naive approach is implementing the elliptic-curve arithmetic yourself in Solidity. Hundreds of opcodes, thousands of gas, code that's both expensive and slow. The alternative: a precompile at address `0x01` called `ecrecover`. You send it a hash and a signature, it returns the signer's address. Fixed gas cost of 3,000. Done in a single CALL.

The mechanism is simple but worth being precise about. Precompiles live at reserved addresses, currently `0x01` through `0x0a` on mainnet. When the EVM encounters a CALL to one of these addresses, it doesn't look up bytecode in the state trie. The client software routes that call to a native Go (or Rust, or C++) function compiled directly into the node. The function runs, returns output to the EVM call stack, and charges a fixed gas amount defined in the relevant EIP. No custom opcode required, no changes to the instruction set, just a special address the client knows to handle differently.

This is the part most guides skip. Precompiles are not EVM features in the bytecode sense. They're client-level implementations dressed up as contracts, like a bouncer who looks like a regular patron but answers to a completely different set of rules. The EVM's opcode table is unchanged. The abstraction holds.

The Roster and the Reasoning

Ethereum mainnet currently ships ten precompiles. Each one exists because the math it performs is either prohibitively expensive to implement in raw bytecode, or cryptographically foundational enough that a single canonical implementation matters for security.

`ecrecover` (0x01): recovers an Ethereum address from a secp256k1 signature. Every ECDSA-based wallet interaction depends on this somewhere.

`SHA2-256` (0x02) and `RIPEMD-160` (0x03): hash functions needed for Bitcoin-compatible operations, added largely so cross-chain bridges and SPV proofs could work.

`identity` (0x04): just copies its input. Sounds trivial. It's a cheap way to copy memory in certain contexts and saves gas versus doing it manually.

`modexp` (0x05): big-integer modular exponentiation, the engine behind RSA verification and various commitment schemes. Doing this in EVM bytecode for a 2048-bit modulus would cost astronomically more gas than the precompile's variable formula.

Then the pairing-based cryptography precompiles: `ecAdd` (0x06) and `ecMul` (0x07) for BN254 elliptic-curve point operations, and `ecPairing` (0x08) for the bilinear pairing check itself. These three, added via EIP-196 and EIP-197, are what made zkSNARK verification economically viable on Ethereum. A single pairing check on BN254 costs 45,000 gas via the precompile. The same operation in pure EVM arithmetic runs into the millions.

`blake2f` (0x09) followed: the BLAKE2 compression function, useful for Zcash compatibility and certain hash constructions.

`point evaluation` (0x0a): added with EIP-4844 to verify KZG polynomial commitments, the cryptographic primitive underneath blob transactions and the data availability layer feeding rollups.

Every addition solves a concrete bottleneck that showed up in real contract development, not a theoretical one. The list is short because the bar is high.

A Worked Scenario: Two Developers, Same Proof

Consider two developers, Priya and Tomás, both building zkSNARK-based private voting systems. Priya's team, working before EIP-196 shipped, tried to implement BN254 pairing verification entirely in Solidity. Their benchmarks showed roughly 8 million gas per proof verification, far above the block gas limit of the era. The contract couldn't be used. They shelved it.

Tomás's team built the same verifier after EIP-196 and EIP-197 landed. Their contract calls `ecPairing` at `0x08` with the proof data. The verification runs for around 260,000 gas total, well within a single transaction.

Same cryptographic security guarantee. The difference isn't cleverness; it's the precompile.

The cryptographic security of the operation is identical in both cases. The precompile doesn't change what is being computed. It changes where: from interpreted EVM bytecode to optimized native code, with a fixed gas price negotiated by the community through an EIP.

What People Get Wrong About Precompiles

The common misconception is that precompiles are a form of trust or centralization, special contracts the Ethereum Foundation controls. That folk wisdom needs to die.

Precompiles are consensus-layer features. Every client (Geth, Nethermind, Besu, Erigon) implements the same precompile logic, specified precisely in the Yellow Paper and in the relevant EIPs. If a client's implementation of `ecrecover` returns a different result than the spec, that client forks off the network. The correctness guarantee comes from multi-client implementation and the spec, not from any single party.

The second misconception is about gas pricing. Precompile gas costs are not arbitrary; they're benchmarked on reference hardware and calibrated through EIPs. EIP-2565, for instance, repriced `modexp` after analysis showed the original formula from EIP-198 was underpricing large-exponent operations and overpricing small ones. Gas repricing of precompiles has happened multiple times. If you're building a contract that calls a precompile millions of times in simulation, check that your gas estimates use current pricing, not a figure from an older deployment guide. This is the kind of mistake that costs real money and feels completely avoidable in retrospect.

The third misconception: precompiles cannot be called with arbitrary logic layered on top at the EVM level. You can't override them, proxy them in interesting ways, or extend their behavior from Solidity. What they do is fixed. If you need slightly different elliptic-curve arithmetic for a different curve, you either wait for a new precompile to be proposed and accepted, or you implement it in bytecode and pay the full gas cost. No middle ground.

The Cost of Adding a New One

Precompiles aren't free to add. Each one requires every client team to write, audit, and maintain a native implementation. A bug in a precompile is a consensus bug: if Geth and Nethermind return different outputs for the same input, the network splits. The bar for inclusion is high, and it should be.

This is why proposals like EVM-MAX are exploring whether future cryptographic primitives should be handled differently, possibly through new opcode families rather than more precompile addresses. The precompile model solved a real problem brilliantly. It also has limits, and the people building Ethereum's roadmap are not pretending otherwise.

The ten addresses from `0x01` to `0x0a` are doing an enormous amount of quiet work right now: every signature check, every zkSNARK verifier, every KZG commitment. Native code, fixed price, invisible to the caller. Which, frankly, is the most Ethereum thing imaginable: the most powerful feature in the stack is the one that technically isn't part of the stack at all.