The zkEVM types are a scale, introduced by Vitalik Buterin in an August 2022 post, for how closely a ZK rollup's execution matches Ethereum. Type 1 changes nothing and could prove Ethereum's own blocks. Type 4 only accepts the same source code, compiling Solidity or Vyper to a different VM. Types 2, 2.5 and 3 sit in between. The further a design moves from type 1, the cheaper and faster it has traditionally been to prove, and the more likely your contracts or tooling are to notice the difference.
Why the trade-off exists
Ethereum was never designed to be proven in zero knowledge. Its state lives in a Merkle-Patricia trie hashed with Keccak-256, data is RLP-encoded, and some opcodes and precompiles are very expensive to express inside a proof system. Each of those costs many times more to prove than a ZK-friendly alternative such as a Poseidon hash or a simpler state tree. A zkEVM team can pay that cost, or change parts of Ethereum to avoid it, and each change moves the design down the scale.
The five categories
Type 1: fully Ethereum-equivalent. Nothing is changed: same hashes, same state trie, same transaction and receipt structures, same precompiles and gas costs. A type 1 prover can prove an unmodified Ethereum L1 block, which is also what Ethereum itself would need to verify blocks with SNARKs. The cost was historically the slowest and most expensive proving.
Type 2: fully EVM-equivalent. Contract execution behaves exactly as on Ethereum, but data structures outside the EVM, such as the state tree or block hashing, are swapped for proof-friendly versions. Contracts, bytecode and dev tools work unchanged. Anything that inspects Ethereum's internal structures, such as verifying a storage proof from eth_getProof, may not.
Type 2.5: EVM-equivalent except for gas costs. The same as type 2, but opcodes and precompiles that are hard to prove get higher gas costs. That keeps a single transaction from overwhelming the prover. It breaks only code that depends on exact gas amounts.
Type 3: almost EVM-equivalent. Some features are dropped or changed, most commonly precompiles, and sometimes details of how code, memory or the stack are handled. Most applications work, but some need changes. Vitalik noted that type 3 is often a stage on the way to type 2, not a destination.
Type 4: high-level-language equivalent. The rollup compiles Solidity or Vyper, via its own compiler, to a VM designed for proving. Proving is much cheaper, but EVM bytecode doesn't run as-is, CREATE2 addresses can differ, hand-written assembly may break and bytecode-level debugging and tooling need replacing.
| Type | Matches Ethereum at | Typical changes | Proving cost | Developer impact |
|---|---|---|---|---|
| 1 | Whole protocol | None | Highest | None |
| 2 | EVM bytecode | State tree, block structure | High | Storage proofs and header formats differ |
| 2.5 | EVM bytecode except gas | Gas repricing | High, bounded per tx | Hard-coded gas assumptions break |
| 3 | Most bytecode | Missing or limited precompiles, edge cases | Lower | Some contracts need changes |
| 4 | Source code | Different VM and compiler | Lowest | New compiler, addresses, tooling |
Where projects sit
The labels are a snapshot. Teams move between them, and several describe themselves by the type they're aiming for rather than the one they meet today. Treat these as approximate as of mid-2026, and check each project's current compatibility docs.
- Scroll launched in 2023 with custom circuits that proved EVM bytecode directly, targeting type 2 but with type 3 gaps: its state tree was a Poseidon-based zkTrie, and several precompiles were unsupported or limited. Its Euclid upgrade in 2025 replaced both pieces. Proving moved to OpenVM, a RISC-V zkVM, which proves Scroll's execution logic written in ordinary Rust instead of hand-built EVM circuits, and the state commitment switched from zkTrie to Ethereum's Merkle-Patricia trie. That moved Scroll noticeably closer to Ethereum on both execution and state.
- Linea, built by Consensys, proves EVM bytecode with its own arithmetization and prover and has stated a goal of reaching type 1. For a long time it trailed Ethereum's hard forks, so contracts had to be compiled for an older EVM version; it has since been catching up.
- Polygon zkEVM targeted type 2 but was mostly type 3 in practice. Polygon has since announced it is winding the network down, so it is mainly of historical interest for new deployments.
- Taiko aims at type 1, reusing Ethereum's data structures, and has combined several proof types, including TEE-based and zkVM-based proofs.
- ZKsync Era is the standard type 4 example:
zksolccompiles Solidity to EraVM. ZKsync has added an EVM bytecode interpreter and is moving to a newer stack designed around EVM execution, so where it sits depends on which execution path your contract uses.
(Starknet sits outside the scale: Cairo is its own language, not an EVM.)
General-purpose zkVMs changed the economics
The 2022 classification assumed each team hand-wrote circuits for the EVM, which is why type 1 looked so expensive. Since then, RISC-V zkVMs such as OpenVM, SP1, RISC Zero and others have become fast enough to prove an existing EVM implementation written in Rust, like revm, compiled to RISC-V. That makes type 1 and type 2 designs much cheaper to build and maintain, and several teams have demonstrated proving full Ethereum L1 blocks within roughly a block time on large GPU clusters. The types remain a useful vocabulary for compatibility, but "closer to Ethereum" no longer automatically means "much slower to prove".
What this means when you deploy
Pick the right EVM version. Newer solc releases default to recent hard forks and emit opcodes like PUSH0 (Shanghai) and MCOPY (Cancun). On a chain that doesn't support them yet, deployment or execution fails with an invalid opcode. Set the target explicitly per chain:
# foundry.toml
[profile.default]
solc_version = "0.8.28"
evm_version = "cancun"
[profile.older_l2]
# for a chain that hasn't adopted Cancun yet
evm_version = "shanghai"
Check the precompile list. Precompiles are the most common type 3 gap. A missing precompile is dangerous because calling an address with no code succeeds and returns empty data, so an unchecked low-level call looks like it worked. Always check the return length:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
library Sha256Precompile {
function hash(bytes memory data) internal view returns (bytes32) {
(bool ok, bytes memory out) = address(0x02).staticcall(data);
require(ok && out.length == 32, "sha256 precompile unavailable");
return abi.decode(out, (bytes32));
}
}
You can probe a chain directly over JSON-RPC; the SHA-256 of empty input should come back as 0xe3b0c442...b855:
curl -s -X POST "$RPC_URL" -H 'Content-Type: application/json' --data '{
"jsonrpc": "2.0", "id": 1, "method": "eth_call",
"params": [{"to": "0x0000000000000000000000000000000000000002", "data": "0x"}, "latest"]
}'
Newer precompiles deserve the same check: the KZG point-evaluation precompile, the BLS12-381 precompiles added in Pectra, and the secp256r1 (P-256) verifier used for passkeys, which L2s adopted as RIP-7212 at 0x100.
Don't hard-code gas. Type 2.5 and type 3 chains reprice operations, and ZK rollups add data-publication costs. Estimate against the target chain, and avoid fixed gas stipends and gasleft() thresholds copied from Ethereum.
Expect different addresses on type 4. Factories and deterministic deployments that precompute CREATE2 addresses need the chain's own formula.
Watch block and state fields. PREVRANDAO is usually not a usable randomness source on a rollup, blob opcodes may return placeholder values, and storage proofs are only portable if the chain uses Ethereum's trie.
Test on the real chain. A local fork with anvil --fork-url runs the standard EVM against the chain's state, so it won't reproduce missing precompiles or repriced gas. Run your integration tests on the rollup's testnet.
Summary
| If the chain is | Expect |
|---|---|
| Type 1 | Ethereum behaviour everywhere, including storage proofs |
| Type 2 | Same contract behaviour; Ethereum-specific proofs and headers may differ |
| Type 2.5 | Same behaviour, different gas for some operations |
| Type 3 | Mostly the same; check precompiles and edge-case opcodes |
| Type 4 | Same Solidity, different compiler, bytecode, addresses and tools |
The type tells you where to look first. The chain's own list of differences from Ethereum tells you what actually applies today.
Get the weekly commit
New blockchain deep dives every week.