The last article covered the world around a transaction: who answers for the codeless, who pays, how transactions travel, how blocks get made, where the risks moved. This article dives below, into the machine, answering one question at three scales: after you submit a transaction, who burns CPU for it, where, and at what price? The macro scale is the journey and the replay; the micro scale is the fictional machine doing the burning; the middle scale is the living testimony of contract practice.
Before setting off, drive in three nails, each pulling out a common illusion. First, there is no such thing as “submitting a block”; every submission path carries transactions. Second, the proposer does not verify other people’s blocks; it is the network’s one and only block maker for its slot, and verification is everyone else’s job. Third, “landing on chain” is not an action anyone performs; it is a process of gradual hardening.
The truth about submission: all three roads carry transactions
Redraw the submission paths accurately. Path one, via a node’s RPC: eth_sendRawTransaction aimed at your own node or a public RPC, carrying the signed transaction’s full bytes (type ‖ payload), landing in that node’s waiting room and then flooding into the public pool over gossip. Path two, the private channel: the same RPC call aimed at Flashbots Protect or a builder’s private endpoint, the same bytes, no gossip, straight into the builder’s private order flow. The oft-listed third path, “submitting to the public pool,” is not a submission method at all; it is path one’s second hop. So the accurate count is two and a half; and the difference between “your own node” and “someone else’s RPC” is trust, your own node does not censor you or front-run on what it sees, an operational matter, not a protocol one.
Transactions travel these roads and pool up, finally lying in some builder’s or node’s waiting room. Up to this point, no “block” exists anywhere. The network births exactly one block every 12 seconds, made by the one proposer drawn for the slot; a block is the next section’s artifact, not anything a user or ordinary node submits.
The proposer’s twelve seconds: the network’s only block maker
Set the role straight first: the proposer verifies nobody’s submissions; it makes the block, and verifying is everyone else’s job, covered two sections down. Its twelve seconds, segment by segment.
Before the slot begins, the RANDAO draw is deterministically derived from beacon-chain state, so a proposer knows about an epoch in advance that it has been picked; if it uses MEV-Boost, the validator registered with relays long ago, filing its fee recipient and preferences. At the slot’s start, pickup, one of two roads:
Local road (self-built block, via the Engine API, the in-machine interfacebetween consensus client CL and execution client EL): ① CL → EL: engine_forkchoiceUpdated(head, safe, finalized, payloadAttributes) once attributes arrive, the EL keeps building a candidate from waiting-room txs ② CL → EL: engine_getPayload(payloadId) → ExecutionPayload (full transaction list)
Outsourced road (MEV-Boost): ① to each relay: getHeader(slot, parentHash, pubkey) → (header, bid) pairs ② take the highest bid, wrap the header in a "blinded beacon block", sign with the validator's BLS key ③ submitBlindedBlock → the relay, after checking the signature, releases the full block body and broadcasts on the proposer's behalfOn the local road there is a second half of assembly: the CL wraps the ExecutionPayload into a larger container, the beacon block, filling in slot, proposer index, parent root, stuffing in the slot’s collected attestations, the randao_reveal that feeds the network’s randomness pool, deposits, exits, sync-committee aggregates, computing the consensus state root, then BLS-signing the whole. Then, around second zero to one of the slot, it drops the SignedBeaconBlock onto consensus-layer gossip. At that instant, the proposer’s entire power has been spent. Its “act of putting things on chain” is that one broadcast, and nothing else. It cannot declare the block valid or order anyone to accept it; from here on it watches the network’s face like everyone else. The second half of the script belongs to others: second 4 is the voting deadline for the slot’s attestation committees, second 8 the aggregators bundle the votes for the next proposer to carry.
Block anatomy: a two-layer nesting doll
A post-merge block is a consensus-layer container around an execution-layer payload:
SignedBeaconBlock ← the object on consensus gossip, SSZ-encoded├─ signature: the proposer's BLS signature└─ message: BeaconBlock ├─ slot / proposer_index / parent_root ├─ state_root ← consensus state root (validator set, balances, │ finality checkpoints) └─ body ├─ randao_reveal / attestations[] / slashings[] / deposits[] … ├─ blob_kzg_commitments[] ← blobs leave only commitments; bodies ride sidecars └─ execution_payload ← the "Ethereum block" you know lives here ├─ parent_hash / fee_recipient / block_number / timestamp ├─ prev_randao / gas_limit / gas_used / base_fee_per_gas ├─ state_root ← execution state root (the account world's MPT root) ├─ receipts_root / logs_bloom / block_hash / withdrawals[] └─ transactions[] ← a list of opaque byte strings, each = type ‖ payloadThree details must be called out. First, two state_roots: the beacon-block one roots the consensus state, validator set, balances, finality checkpoints; the ExecutionPayload one roots the execution state, accounts and storage; two ledgers, two trees, two roots, never conflate them. Second, transactions is just a list of byte strings; every transaction lies there in its canonical complete form, and the block does not understand transactions, it carries them. Third, serialization runs on two tracks, picking up part two’s passport: the consensus layer uses SSZ, which has built-in length framing, so opaque byte strings sit directly as list elements, no shell required; the execution layer’s interior, historical sync, RLP block bodies, the transaction trie, remains RLP country, where typed transactions need their b8/b9 passports. One principle, opaque atomic items inside containers, two framings, two implementations.
Verification = replay + checking commitments: the final meaning of gas
Who verifies? Every full node that receives the block, staked or not; stakers merely do one extra thing, vote, next section. What gets verified? Two checklists.
The consensus checklist runs in the CL: the BLS signature; the proposer’s identity, checkable because the RANDAO draw is a deterministic function of beacon state, so any node can recompute “whose slot is this” and spot an impostor at a glance; the slot and parent linkage; the randao_reveal’s validity; the legality of the block’s attestations; then the consensus layer’s own state transition, ending in a comparison against the consensus state root.
The execution checklist is the main event. The CL hands the payload to the EL through engine_newPayload, and the essence is one sentence: redo everything the builder did, then compare answers.
① Consistency: rebuild the execution block header from payload fields (transactionsRoot recomputed on the spot from the transaction list), keccak it, must equal the claimed block_hash② Replay every transaction: full state transition in order. Decode and dispatch, static checks, signature verification (that Falcon frame transaction's 2.1M-gas VERIFY frame is re-run here by every node: SIGPARAM copy, NTT, APPROVE), the frame loop, fee deduction, receipts③ Compare answers (commitment checks): state_root the replayed account world's root == claimed? one bit off, the whole block is invalid receipts_root all receipts (8141's per-frame status and payer live here) match? gas_used the per-transaction sum == claimed? base_fee the value derived from the parent by the 1559 formula == claimed? (fee rates are not free to invent) blob accounting usage and KZG commitments match one by one?See where the design’s center of gravity sits: the substance of verification is not “check a pile of signatures” but replay all execution, then compare cryptographic commitments; signature checking is one sub-step of the replay. The commitments, that row of roots, are the mechanism that makes cheating self-incriminating: let a builder skip one execution, print one extra unit, flip one storage slot, and state_root stops matching, the block dies, the bid was paid for nothing.
From this drops the final definition of gas: what you pay buys the CPU time for thousands of nodes to each re-perform your transaction once. The Falcon transaction is expensive because it makes every node run alongside it through two million gas of lattice arithmetic. Two corollaries go straight into the notebook: 8141’s per-frame receipts are committed into the block header via receipts_root, so every frame’s status and gas usage is consensus-grade data, not some node’s private log; and a mispriced precompile is wrong not once but once per node per replay, which is where the “worst-case CPU coverage” pricing principle and the DoS-weaponization worry in the coming sections are born.
“On chain” is hardening, not an action
What follows the proposer’s broadcast is a three-stage process. Stage one, voting, on the order of seconds: the slot’s attestation committees (all validators are split evenly across an epoch’s 32 slots, each voting once per epoch) independently run the full verification above, and if they approve, broadcast an attestation before second 4: “the head I see is this.” Stage two, fork choice, continuous: every node independently runs LMD-GHOST, weighing accumulated votes to pick the current head among possibly coexisting branches; the everyday meaning of a block being “on chain” is merely “fork choice currently counts it in the winning branch,” and that is revocable, shifts in votes, network partitions, or a late-arriving rival block can trigger a reorg. Stage three, finalization, about 12.8 minutes: Casper FFG runs at epoch granularity, a checkpoint gathering two-thirds of total stake becomes justified, and consecutive justifications finalize the previous one; undoing a finalized block means at least one-third of all stake gets slashed. Only here does “on chain” harden from “the network’s current majority opinion” into “economically irreversible history.” What large transfers wait for is exactly this line.
The verbs of the whole journey, each to its owner: users submit, and the object is always a transaction; the builder, or the proposer’s local EL, constructs the ExecutionPayload; the slot’s single proposer publishes, one gossip broadcast; all other full nodes verify; the slot’s committees vote; every node picks its chain by fork choice; and finalization is the collective act of two-thirds of stake.
The macro journey ends here. The replay section said every node runs your two million gas alongside you; now descend into the machine where the replaying happens, for a more fundamental question: precompiles and bytecode both burn node CPU, so why can the same piece of mathematics differ a hundredfold in price between the two roads? No magic in the answer: because the real CPU time burned differs by two to three orders of magnitude, and gas is an honest pricing of real CPU time. To see it, take the machine apart.
The EVM: a fictional CPU, and the interpretation tax on every instruction
The EVM is not the CPU in your computer. It is a paper specification defining a machine that does not exist: 256-bit words, a stack architecture, about 150 opcodes; every client simulates this imaginary machine in software, geth wrote the simulator in Go, reth in Rust. Contract bytecode is the program fed to the imaginary machine. Four non-negotiable reasons justify the trouble. Determinism: consensus demands that thousands of heterogeneous nodes compute bit-identical results for the same transaction; real hardware cannot promise that (floating-point rounding, undefined behavior, ISA differences), a paper machine can, every instruction’s semantics pinned to the bit. Sandboxing: contracts are strangers’ arbitrary code, and the imaginary machine is a room without doors or windows; bytecode can touch only the furniture the spec provides, stack, memory, storage, and physically cannot reach the host’s filesystem or network. Meterability and interruptibility: gas demands a price on every step and an out-of-fuel stop at exactly the right step; an interpreter does this naturally, native code cannot be cleanly halted at machine instruction 3891. Code as data: bytecode must live on chain as state and hash into codeHash, so it must be a platform-independent, compact representation. Four reasons buy safety and consensus; the price is the next section’s subject: simulation is expensive.
How expensive, the interpreter’s main loop shows. Every client’s EVM core is isomorphic to this pseudocode:
while True: op = code[pc] # ① fetch: read one byte from an array info = JUMP_TABLE[op] # ② decode: look up handler, price, stack needs if stack.depth < info.min_stack: # ③ stack safety check (every step) halt if gas_left < info.price: # ④ gas accounting (every step!) out_of_gas gas_left -= info.price info.execute(stack, mem, ...) # ⑤ the actual work pc += 1 # ⑥ stepCount what one ADD, priced at 3 gas, makes a real CPU do: one fetch, one table lookup plus a function call, two comparisons and a subtraction, then the “actual work,” which is itself watered down, because the EVM’s word is 256 bits while a real CPU has 64-bit registers, so the two operands are four-limb big-number structures in memory, and “one addition” means popping two big numbers off a stack that is a heap data structure rather than a register file, four carry-propagating 64-bit adds, and a push back, then the step. Total: one 3-gas ADD stands on tens to a hundred real machine instructions; native code does a 64-bit add in one instruction, about 0.3 nanoseconds. That is the interpretation tax: fetch, decode, checks, accounting, word-width simulation, stack traffic, six overheads wrapped around every opcode, with only step ⑤’s kernel being “the computation you wanted.” The tax rate is about two orders of magnitude.
Cryptography then pays tax on top of tax. A modern cryptographic library’s weapons are hand-written assembly field kernels, register-level scheduling of Montgomery multiplication, vector instructions computing four to eight lanes at once, precomputed tables; none of this is expressible in EVM bytecode, which has no notion of registers, no SIMD, no multiplier you control. You get one MULMOD at 8 gas, and inside the interpreter it is a software big-number routine at the hundred-nanosecond scale. Falcon takes one more cut: its reference implementation leans on floating-point FFT, and the EVM has no floating point, so on-chain implementations are forced into integer rewrites. Reconcile the books on one secp256k1 verification, whose mathematical core is a few thousand finite-field multiplications: on the bytecode road, each multiplication is one MULMOD plus an entourage of stack shuffling, and rolled up with modular inversion, hashing, and decompression it starts in the hundreds of thousands of gas, naive implementations passing a million; on the precompile road, a libsecp256k1-grade assembly implementation really takes tens of microseconds, priced at 3000 gas.
Gas is an honest meter
First reconcile the exchange rate. Gas pricing is anchored to “the real time of the slowest compliant client,” and historical calibration puts mainnet’s rate at roughly tens of nanoseconds per gas. Hold that ruler to both sides: the precompile road, 3000 gas times tens of nanoseconds, lands at tens to a hundred microseconds, which is exactly the native implementation’s real cost, the books balance; the bytecode road, hundreds of thousands of gas times tens of nanoseconds, lands at tens of milliseconds, and that is no gouging either, the interpreter genuinely burns that much CPU to act the same play out inside the imaginary machine. Both roads use one exchange rate; the price gap faithfully mirrors the CPU-time gap. Gas is an honest meter, and precompiles win on real cost, not on billing standards.
But honest metering is only half the riddle. The other half is a jump in the unit of account: for bytecode, the protocol can only price opcode by opcode, it cannot see your intent, whether you are running Falcon or computing Fibonacci, it sees only an instruction stream, so it assigns each instruction a conservative worst-case unit price and adds them up, freezing the interpretation tax into the bill line by line. What a precompile does, in essence, is register a semantic unit with the protocol: “address 0x01 means verifying one secp256k1 signature.” The protocol now knows what you are doing, and the unit of account jumps from “interpret one small step” to “complete one whole native task,” one flat price, set from the measured native worst case. Cheaper gas equals real cost reduction plus a promotion of the unit of account; neither alone suffices.
Why does client diversity not tear consensus apart? Because for precompiles, consensus requires bit-identical agreement on exactly two things: the input-to-output mapping, and the gas charged. Whether geth takes 40 microseconds and reth 25 is irrelevant; elapsed time is not a consensus object, results and prices are; and the deal holds because precompiles are stateless pure functions, consensus watches only the two ends of the black box. The bytecode side is far stricter by contrast: interpreters must agree at every step, including which instruction the fuel dies on, since the exact out-of-gas point determines the rollback point and is part of consensus. This explains two things at once: precompiles may be optimized to death, freedom inside the black box; and the price list is set by the slowest mainstream compliant implementation, one client speeding up its interpreter tenfold cannot and does not make MULMOD cheaper, so repricing is forever a governance event.
Load the machinery into the series’ cost model and three lanes line up. The bytecode lane interprets step by step inside the imaginary machine, β inflated two to three orders by the interpretation tax. The new-opcode lane (EVMMAX, EIP-6690, stalled) bolts special-purpose hardware onto the imaginary machine, modular-multiply instructions with preloaded Montgomery contexts, lowering β without leaving the VM, the middle lane. The precompile lane moves the whole function out of the imaginary machine, semantic registration plus native execution plus a flat price, swapping β for the native coefficient outright. One fine corner hides in this table: KECCAK256 is itself a subsidized opcode, from 30 gas, with a native implementation long built into every client; but it exposes only a fixed 256-bit-output hash interface, not SHAKE’s sponge-squeeze variable-length output. Implementing SHAKE as the standard writes it means hand-rolling the keccak permutation in bytecode and paying the full interpretation tax; hence a telling phenomenon, on-chain Falcon implementations swap SHAKE for a keccak256-chained pseudorandom generator, in essence abandoning the standard text to ride the subsidized opcode. In the cost model’s terms, the α term only gets cheap inside the EVM by deviating from the standard, and this is the mechanical root. It is also the hash-side mirror of part three’s line that encoding-and-implementation canonicity is a tax every generation of schemes pays again.
The subsidy roster: precompiles
The last sections explained “expensive”; now for where “cheap” comes from. A precompiled contract means: this function does not go through the EVM interpreter, it was compiled in advance into the client binary itself. There is no bytecode for it on chain; its code lives in every node’s executable. The name describes the execution site: not in the virtual machine, but in the virtual machine’s host.
Its origin story matters, because history is replaying. In the genesis era, contracts needed heavy cryptography, the canonical case being ECDSA verification inside a contract, and there were three options. Implement in EVM bytecode: elliptic-curve arithmetic inside a 256-bit interpreter, a million gas, economic death; note the déjà vu, this is exactly the situation of today’s on-chain Falcon and on-chain ML-DSA implementations, and the whole misery of the ARBITRARY lane fits in one sentence, living in a world without your own precompile. Add new opcodes: the instruction set is territory for general primitives, 256 slots cannot absorb domain functions. The winner was a hybrid: to the caller it presents as a contract, an ordinary CALL, arguments laid in memory, results read from memory; to the executor it presents as a native function, the EVM sees the target address in the precompile table, skips loading any bytecode, calls the client’s built-in implementation, and charges the spec’s fixed price. A contract’s coat, native code’s insides. The precise definition: a precompile equals a protocol-reserved low address, plus a specification (input format, output, gas formula), plus each client’s own native implementation; no bytecode (EXTCODESIZE on 0x01 returns 0, where naive “is it a contract” checks faceplant), no key, no deployment, existing the moment a fork activates. And with this, the series’ three families of protocol-anointed addresses close into one line: 0xaa is an identity constant, no code, no behavior, appearing only as caller; 0x8141 is a predeploy with real code, callable; a precompile has no bytecode, its behavior lives in client native code, reached through the CALL interface.
Read the roster as sedimentary rock laid down by “which cryptography Ethereum decided to subsidize.” 0x01 is ecrecover, 3000 gas, there from genesis, unlocking in-contract signature verification, on which multisig wallets, meta-transactions, and the whole off-chain-authorization paradigm grew. 0x05 is big-number modular exponentiation, added in Byzantium, repriced twice in its life. 0x06 through 0x08 are BN254 addition, multiplication, and pairing, Byzantium again; on-chain zkSNARK verification rests on them, no those three addresses, no zk-rollup industry, and they were priced too high at first, with the ZK application wave truly igniting only after EIP-1108 cut the price. 0x0a is KZG point evaluation, arriving with blob transactions. 0x0b through 0x11 are the full BLS12-381 suite, added in Pectra. 0x100 is P256VERIFY, piloted on L2s (RIP-7212), then brought to L1 (EIP-7951), wiring passkeys and phone secure elements onto the chain. Three readings fall out: every entry was once “too expensive to use inside the EVM”; every adoption unlocked an application class, the pairing precompiles begetting the ZK industry being the hard proof that one precompile can change an ecosystem; and the table is governance sediment, which cryptography gets subsidized, when, at what price, all hard-fork-grade decisions. The draft family of post-quantum verification precompiles (the EIP-8051 and 8052 line) is applying for the next row of this table: asking the protocol to do for lattice cryptography what it did for secp256k1 in 2015, for pairing curves in 2017, for P256 in 2025.
The mechanics, in full. Suppose an ML-DSA precompile exists at some address; calling it inside a VERIFY frame looks like:
① SIGPARAM copy: bring the 2420-byte signature from the ARBITRARY entry into memory② plating: lay out the input per the precompile spec [public key (SLOAD) ‖ message hash (TXPARAM 0x08) ‖ signature]③ STATICCALL(gas, precompile address, in, inSize, out, 32)④ the EVM checks the precompile table: hit → load no bytecode, call the client's native function⑤ native verification runs (vector instructions, microseconds), charging the spec's flat price, a price tag, not per-opcode metering⑥ returns 1 → require → APPROVE(0x3)Three takeaways. The call is an ordinary STATICCALL, no special instruction anywhere, which is what “a contract’s coat” means. Precompiles are stateless pure functions, so STATICCALL is legal, they run freely inside VERIFY frames, and 8141’s prefix trace rules whitelist them in so many words; thus “verification is too expensive” turns from a political question, whether to fork for it, into a pricing question, what to charge. And they are consensus-critical code: five or six clients implement one spec in different languages, and if any one of them differs by a single bit, the chain forks on that transaction; this is why adding a precompile equals a hard fork plus high-intensity review, the source of its governance cost.
Finally, pricing. One principle: the gas must cover the worst-case CPU time of the slowest implementation among all clients; priced too low, an attacker stuffs blocks with it and drags down every verifying node, the precompile itself becoming a DoS weapon, and as the replay section showed, a pricing error is amplified by every node times every replay. History proves repeatedly that prices get set wrong: modexp repriced twice, the BN254 pairing born too expensive and cut by EIP-1108 before the ZK wave could start; pricing errors are real, costly, and fixable only by better measurement. So every term of the old inequality lands. The precompile’s price X is a governance unknown. Its lower bound is the cost floor of covering worst-case CPU: native ML-DSA verification is an under-a-hundred-microseconds job on a modern CPU, and at tens of nanoseconds per gas that floor may sit as low as a few thousand gas. Its upper bound is the public pool’s remaining budget, one hundred thousand minus the signature’s structural fee and the other prefix frames’ share, roughly ninety thousand. The gap is far wider than intuition suggests, but the floor’s exact position, worst cases, no-SIMD fallback implementations, input-parsing overhead, DoS safety margin, is not a matter of gut feeling; it takes a measurement report that turns “what should this precompile charge” from intuition into an auditable formula. This also answers what part three left open: between the ARBITRARY lane and the scheme-table lane runs a middle lane, the precompile lane. Both run cryptography at native speed; they differ in call site and governance depth. A precompile is invoked by your EVM code, the signature stays an ARBITRARY entry, introspectable, hence never aggregatable, its cost lands inside the VERIFY frame under the hundred-thousand budget, and governance needs only one precompile EIP, the smallest decoupled piece. The scheme table is invoked by the protocol before any frame, bytes opaque, aggregation ticket in hand, and governance must touch the scheme table and define signer resolution, deep integration. One aside lights up the price difference: P256 is listed at 6700 in the 8141 scheme table, slightly below its precompile price, since in-table verification saves even the cost of that one CALL.
Practice as testimony: ecrecover, permit, and the P256 trilogy
Theory done; let the chain’s most widespread practice testify. The observation that “verifying ECDSA inside contracts is pretty common” hides no mystery, or rather, the mystery is the last two sections.
Solidity’s ecrecover(hash, v, r, s) looks like a built-in, but what the compiler emits is: lay 128 bytes of input in memory, STATICCALL precompile 0x01, read 32 bytes out, a zero-padded 20-byte address. The thousands of field operations of elliptic-curve arithmetic never enter the interpreter once; they all happen inside the client’s built-in native code, a fixed 3000 gas plus about a hundred gas of call overhead. Contracts orchestrate; precompiles do the math. A counterintuitive fact resolves in passing: the on-chain signature ecosystem grew almost entirely on secp256k1 not because the curve is superior, but because it alone was on the genesis roster.
What is the bytecode part doing, then? Hygiene, not mathematics. Library functions, OpenZeppelin’s ECDSA and kin, wrap: signature length checks; enforced low-s, part two’s EIP-2 malleability history given one more backstop at the library layer; recovery-bit normalization; and the zero-address guard, since ecrecover returns the zero address on failure rather than reverting, so comparing its return value against a possibly uninitialized storage slot, whose default value is exactly zero, would let a forged signature “pass,” and the library takes that bullet for you. A few hundred gas in total; a hygiene fee, not a math fee.
Spread out the bill of one permit (EIP-2612) and it gets more interesting. The owner signs a structured authorization off chain, anyone submits permit(...) with the signature, the contract verifies and writes the allowance directly, the owner paying zero gas throughout; this is the living mainstream heir of the relayer era from the last article. In the bill: calldata, one or two thousand gas; EIP-712 digest construction, a few hundred, riding the subsidized KECCAK256 again; hygiene, a few hundred; ecrecover, about 3100; then a nonce increment, one storage write around five thousand, and the allowance write, one cold storage write above twenty thousand. See the center of gravity: out of fifty to eighty thousand gas, verification is barely three thousand; the bulk is two storage writes. The intuition that “in-contract verification is expensive” is wrong in a world with precompiles: what is expensive is state, not subsidized cryptography. Run the counterfactual one step: if 0x01 did not exist, those thousands of field multiplications would fall into the interpreter at full price, a single verification costing hundreds of thousands to a million gas, and permit, meta-transactions, governance signatures, session keys, the entire “signature as authorization” contract ecosystem would simply never have been born.
The counterfactual needs no imagining; the chain just finished performing it. The P-256 curve that passkeys use was not on the genesis roster, 0x01 speaks only secp256k1. So the people who wanted passkeys really did write P-256 verification in pure Solidity and Yul (FCL, Daimo’s verifier and kin), and even optimized to the limit it costs on the order of two to three hundred thousand gas, the going rate of the no-precompile tax. Then RIP-7212 piloted on L2s at 3450; EIP-7951 brought it into L1 at about 6900. The same verification collapsed two orders of magnitude in price, and the passkey wallet wave followed. The P256 trilogy, bytecode grinding, L2 pilot, L1 adoption, is the previous full screening of the post-quantum precompile script; today’s million-gas on-chain Falcon and yesterday’s three-hundred-thousand-gas Daimo verifier are the same scene of the same film, shot on different curves.
One deeper difference hides in 0x01’s name. It is called ec-recover: what it does is not verification but public-key recovery, digest and signature in, signer out, leaning on curve structure peculiar to ECDSA. The underrated consequence: from genesis, Ethereum accounts never needed to publish a public key anywhere, the 65-byte signature carries it implicitly, and an address comparison completes verification. ML-DSA and Falcon have no recovery mode; lattice-signature mathematics does not support deriving the public key from a signature, so verification must be fed the key explicitly. In the post-quantum world, therefore, the public key must either travel, packed into calldata, 1312 bytes for ML-DSA-44, or settle, living in storage or a future key-alias mechanism. Part three’s account keeping its 897-byte Falcon key in a storage slot has its root here: it is not only that post-quantum keys are large, it is that post-quantum signatures lost the recovery property, and the public key must appear in person for the first time.
Finally, translate permit back into frame-transaction language, and the stakes come into focus. The owner’s off-chain signature is, in 8141 terms, a textbook explicit-msg credential: it signs another digest and imports the fact that “the owner authorized this allowance,” kin to part two’s session-key pair of entries. And a “post-quantum permit,” a Falcon-signed credential verified inside an arbitrary contract, today means full bytecode verification inside the target contract, an economic death sentence, viable only once a post-quantum precompile exists. That widens the bet on the precompile proposals from “account-layer verification” to the entire design space of “signature as authorization inside the EVM”: permit, ERC-1271, governance signatures, session keys, all staked on the roster’s next row.
Summary
Compress it into one paragraph. The world after you press send runs like this: all roads carry transactions, the network births one block per 12 seconds made by the one RANDAO-drawn proposer whose entire power is a single broadcast; the block is a consensus container nesting an execution payload, transactions lying innermost as opaque bytes; verification equals replay plus commitment checking, every full node redoing the builder’s work and comparing the row of roots, which makes gas’s final meaning the CPU time of thousands of nodes each re-performing your transaction; and “on chain” hardens by degrees through votes, fork choice, and finality, where undoing a finalized block burns a third of all stake. Inside the machine, the EVM is a CPU invented for determinism, sandboxing, meterability, and code-as-data, at the price of a two-order interpretation tax, with cryptography taxed again on top; gas is an honest meter, both roads priced by one exchange rate, and precompiles win on real cost plus a promoted unit of account, not on billing favoritism. The precompile roster is the protocol’s history of cryptographic subsidy, every entry once too expensive to use, every adoption unlocking an application class, prices set by worst-case CPU coverage, errors amplified by network-wide replay and fixed by better measurement. Practice testifies: in-contract verification is widespread precisely because the bytecode is not doing the verifying, hygiene to the interpreter, math to native code, the bulk of the bill to storage; P256 pre-screened the whole road in three acts; and post-quantum keys, having lost recovery, must travel or settle, while the precompile bet covers the entire signature-as-authorization design space. Every thread the series has laid, the two lanes, the byte floor, the aggregation ticket, the pricing argument, now converges on a single point: whether the roster’s next row gets written, and at what price, is a governance question that has to be answered with a measurement report.
The series will keep coming back: how the pricing arguments for the scheme table and the precompiles get fought, what the follow-up spec for aggregate proofs looks like, and where the compositional route (EIP-8202) takes signature agility.