The address that exists before anyone deploys it

You query an Ethereum address nobody has ever touched. Empty bytes, zero balance, completely inert. Fine. Now query `0x0000000000000000000000000000000000000009`, the BLAKE2b compression precompile that shipped in Istanbul. Still empty bytes. No bytecode. No constructor ever ran. Call it from a smart contract anyway, and it executes complex cryptographic logic and hands back a result like nothing unusual just happened.

Nothing was deployed. It just works.

That gap between "no bytecode" and "fully functional" is the entire story of why adding a precompile is a consensus change, not a deployment.

What a precompile actually is under the hood

The EVM (Ethereum Virtual Machine, the sandboxed runtime that executes contract code) processes a CALL opcode by checking the destination address. If that address falls outside the reserved precompile range (currently `0x01` through `0x09` on mainnet), the EVM looks up bytecode stored in state and executes it. Normal contract logic.

But if the destination sits inside the precompile range, the EVM short-circuits entirely. It skips the bytecode lookup. It dispatches to a native Go function compiled directly into the client software. The computation happens in the execution client's host language, not in EVM bytecode at all, and the result gets returned to the caller as if a contract had run.

The precompile's logic lives in Geth, Nethermind, Besu, Erigon, and every other execution client as compiled native code. The address is just a routing key, like a switchboard extension that rings a room with no phone on the wall. There is no deployment transaction because there is nothing to deploy.

Why that design forces a hard fork

Imagine Ethereum without consensus rules governing which addresses trigger precompile dispatch. Two nodes, same block, same CALL to address `0x0a`. One node runs software that treats `0x0a` as the point-evaluation precompile added in Cancun. The other runs older software, sees an empty account, charges 25,000 gas for calling a nonexistent contract, and returns empty data.

Those two nodes now disagree on post-transaction state. Gas consumed differs. Return data differs. If the calling contract checks the return value, its subsequent execution path may differ entirely. State roots diverge. The nodes are on separate chains.

This is a consensus split, full stop. It happens the instant any single client starts treating a new address differently from the rest of the network. There is no gradual rollout. No feature flag. No canary deployment. Either every validating node agrees, at the same block height, that `0x0a` now routes to new logic, or you have a fork.

Contrast this with deploying a regular smart contract. One party sends a transaction, pays gas, bytecode lands in state. Every node processes that transaction identically because they all follow the same existing rule: store the bytecode at the new address. No client software changes required. The change lives entirely within the state machine's existing rules.

Precompiles change the rules themselves. That is a categorically different operation, and I think it's undersold how clean that distinction actually is.

The EIP process isn't bureaucracy, it's physics

When developers want to add a new precompile, the path runs through an Ethereum Improvement Proposal, then through the All Core Devs call process, then into a hard fork specification, then into coordinated client releases, then into a network upgrade activated at a specific block number (or, post-Merge, at a specific epoch). This looks like bureaucracy. It isn't.

It's the minimum coordination surface for a change that must be simultaneously true across thousands of independent nodes.

Consider the BLS12-381 precompiles (EIP-2537, a long-running proposal). The cryptographic operations they expose, pairing checks, G1/G2 additions, scalar multiplications, are used in proof systems and validator aggregation. Gas costs for each operation had to be benchmarked across multiple hardware profiles and all major clients before activation, because underpricing creates a denial-of-service vector. Too cheap, and an attacker constructs a block that takes minutes to verify. The question of what to charge for a single BLS pairing required months of cross-client benchmarking.

That's the real work inside an EIP. Not the cryptographic implementation, which is hard enough on its own, but the safety analysis that only makes sense at network scale.

A concrete scenario: two validators, one upgrade, one missed

A network upgrade activates at block 20,000,000. Validator Alice upgraded her Geth node two weeks prior. Validator Bob runs a custom setup and missed the announcement. Still on the previous version.

At block 20,000,001, a transaction calls the newly activated precompile at `0x0a`. Alice's node dispatches to the native function, consumes 50,000 gas, returns 96 bytes of output. Bob's node sees an empty account at `0x0a`, consumes 25,000 gas, returns empty data. The contracts depending on that return value execute differently on each node. State roots diverge.

Bob is now on a minority fork. Every block he proposes gets rejected by the upgraded majority. His attestations reference a different state. He earns no rewards and risks inactivity penalties depending on network conditions. The fix isn't a patch he applies mid-flight. He stops, upgrades, and resyncs from a checkpoint before the divergence point.

This isn't a hypothetical failure mode. It's exactly what the activation block mechanism is designed to prevent by making the transition atomic across the network.

The deeper constraint: state and gas coherence

The part most explanations skip: precompiles don't just add new functionality. They participate in the full EVM execution environment: gas metering, call depth limits, revert semantics, return data handling.

A precompile whose gas schedule is slightly off creates exploitable asymmetries between what a user pays and what the network actually spends computing the result. The MODEXP precompile (EIP-198, Byzantium fork) had its gas formula repriced in EIP-2565 during Berlin, precisely because the original formula was discovered to be significantly more expensive to compute than the gas charged. Both fixes required consensus upgrades, years apart.

So adding a precompile isn't a one-time event. The gas schedule is a living commitment the protocol makes to every smart contract that will ever call that address. If the economics turn out wrong, fixing them requires another consensus change. You're not deploying code. You're making a promise to every contract ever written that calls that address, about how much it will cost and what it will return, and that promise runs forward indefinitely.

That's a much heavier obligation than deploying a contract. Anyone who treats these two operations as roughly equivalent hasn't thought it through.

What this means for EVM-compatible chains

Chains that market themselves as EVM-compatible face an interesting version of this problem. Add a precompile Ethereum mainnet doesn't have, and smart contracts written for that chain become non-portable. A Solidity contract calling address `0x0a` expecting BLS operations will behave completely differently, or break entirely, if deployed on a chain where `0x0a` is empty or mapped to something else.

So if you're auditing a cross-chain protocol and it calls low-numbered addresses directly: check each chain's precompile table. The precompile address space functions as a shared namespace across the EVM ecosystem even though no formal registry governs it. Chains that deviate from Ethereum's precompile set are making a quiet compatibility bet. Most developers don't notice until a contract that tested fine on one network fails silently on another, returning empty data instead of the expected cryptographic output.

The divergences are small in number and enormous in consequence.

The precompile mechanism is elegant precisely because it's invisible. But invisibility has a cost: you cannot change the rules of a machine that ten thousand strangers are running simultaneously without getting every single one of them to flip the switch at the same moment. The protocol doesn't ask nicely. It just forks.