What is the EVM?
Learn what the EVM is, why Ethereum needs it, how bytecode execution works, and how gas, state, storage, and contract creation fit together.

Introduction
**The EVM, or Ethereum Virtual Machine, is the execution engine that tells Ethereum how to interpret transactions and run smart contracts. ** That sounds straightforward until you ask the real question: how can thousands of independent computers execute untrusted code and still arrive at the same answer?
That is the problem the EVM solves. A blockchain cannot simply let programs run however the local machine happens to run them. It needs a runtime whose behavior is tightly specified, whose resource usage is bounded, and whose outputs are deterministic enough that every honest node can replay the same transaction and compute the same new state. The EVM is that runtime.
If you keep one idea in mind, the rest of the topic becomes easier: **the EVM is not mainly “a place where contracts live.” It is a state-transition machine. ** A transaction enters with some current world state, bytecode executes under fixed rules, gas limits how much work can happen, and the result is either a precise state update or a rollback of the attempted changes. In the Ethereum specification, this is expressed as a transaction-level state transition and then composed across all transactions in a block.
That framing also explains why the EVM became so influential beyond Ethereum itself. Many other chains chose to be EVM-compatible not because the EVM is the fastest possible virtual machine, but because it gives them a known execution model, established tooling, and a contract ecosystem that developers already understand.
How does the EVM turn a transaction into an agreed post‑state?
At the center of Ethereum is a shared data structure often called the world state. Conceptually, it is a mapping from 160-bit addresses to account states. Each account state contains four core fields: a [nonce](https://scribe-topic-id.invalid/foundations.transactions.nonce), a balance, a storageRoot, and a codeHash. The state is represented in a modified Merkle Patricia trie so that the chain can commit to the entire state with a compact root hash.
This matters because the EVM does not operate in a vacuum. Every opcode it executes is meaningful only relative to this world state. When a user sends ETH, calls a contract, or deploys new code, the EVM reads part of the current state, performs computation, and produces the next state. The formal specification writes this as a state transition of the form “old state plus transaction gives new state.” At the block level, the block transition is just these transaction transitions applied in sequence.
So the EVM is best understood as a machine that answers a narrow but strict question: *given this exact pre-state and this exact transaction, what is the exact post-state? * Consensus on Ethereum depends on every execution client answering that question the same way. Geth, Nethermind, and Besu are different software implementations, but they are all trying to implement the same execution rules.
That same logic carries to EVM-compatible systems. A rollup that advertises EVM equivalence is telling developers that contract bytecode should behave the same way under the same semantics. A chain like BNB Chain built around EVM compatibility did not merely copy Solidity syntax; it adopted the broader execution model that lets Ethereum-style contracts and tooling work with minimal change.
Why does Ethereum use a virtual machine instead of fixed transaction types?
You could ask why Ethereum needed a virtual machine instead of a small set of fixed transaction types. The answer is programmability. Bitcoin’s model is intentionally narrow: validate signatures, check spending conditions, update UTXOs. Ethereum’s ambition was broader. It wanted users to define custom stateful logic on-chain.
But arbitrary programmability creates a new problem. If contract code is arbitrary, then the network needs a common environment in which that code runs. It cannot depend on the node’s operating system, CPU architecture, or local libraries. The virtual machine is the abstraction layer that strips all that away.
The EVM therefore defines its own execution model: a stack-based machine with 256-bit words, byte-addressed code, word-oriented arithmetic, transient memory during execution, and persistent per-account storage across transactions. This is not an accident of implementation. It is a way of making contract execution portable and predictable.
The 256-bit word size often surprises newcomers. It is larger than the native word size on most hardware, so it is not chosen for raw machine efficiency. The design aligns more naturally with Ethereum’s cryptographic and hashing environment, where 256-bit values are common. That choice simplifies some parts of contract computation, though it also means EVM implementations do extra work that modern CPUs do not do natively.
This is one reason newer runtimes often prefer WebAssembly-style designs. WASM fits ordinary hardware and compiler pipelines better. The EVM persisted not because it is universally optimal, but because a virtual machine accumulates value through compatibility. Once a whole ecosystem of compilers, debuggers, auditors, standards, and deployed contracts forms around one execution model, that model becomes much more than its instruction set.
How do stack, memory, transient storage, and persistent storage work in EVM execution?
| Location | Lifetime | Visibility | Gas cost | Typical use |
|---|---|---|---|---|
| Stack | Single call frame | Execution-local only | Very cheap | Operands & arithmetic |
| Memory | Current execution | Call-local temporary | Low | Calldata and return buffers |
| Transient storage | Until transaction end | Visible within same tx | Medium-low | Transaction-local shared state |
| Storage | Persistent across txs | Global contract state | High | Durable contract state |
The simplest nontrivial way to picture EVM execution is to imagine a tiny machine evaluating bytecode step by step. It has a program counter telling it which instruction comes next, a stack for most immediate values, memory for temporary working data, and access to the contract’s persistent storage.
The stack is where arithmetic and many opcode arguments live. The EVM is stack-based, so instructions usually pop their inputs from the top of the stack and push their results back. The stack has a maximum depth of 1024 items. This style makes the bytecode compact, but it is also one reason raw EVM bytecode is hard for humans to read.
Memory is temporary. It exists only for the duration of the current execution context. A contract can write bytes into memory, read them back later in the same call, use them to build return values, or pass them into another call. But once execution ends, memory disappears. It is not part of the durable blockchain state.
Storage is the opposite. Each contract account has persistent storage, conceptually a key-value mapping of 256-bit words, committed into the account’s storage trie and therefore into global state. If a contract writes to storage and the execution completes successfully, later transactions will see the updated value. That persistence is what makes contracts stateful rather than mere pure functions.
There is also a newer middle ground called transient storage, accessible through [TSTORE](https://ethereum.org/developers/docs/evm) and TLOAD. It persists across internal calls within the same transaction but is cleared at the end of the transaction and is not committed to global state. The point is not to replace storage; it is to give contracts a cheaper place to keep transaction-local state that must survive nested calls but not survive beyond the transaction.
A common misunderstanding is to treat these as just three containers with different prices. The deeper distinction is about lifetime and consensus impact. Memory affects only the current execution. Transient storage affects the current transaction. Persistent storage affects the chain’s long-term shared state. Gas costs differ largely because these effects differ.
What happens on-chain when you send a transaction to an EVM contract?
Consider a user sending a transaction to a contract on Ethereum. The transaction includes fields such as the sender’s nonce, a gas limit, a destination address, possibly a value transfer, and input data. Since EIP-1559, the fee model also includes a maxFeePerGas and a maxPriorityFeePerGas, with the block’s base fee being burned and the priority fee going to the block beneficiary.
When a node executes that transaction, it first checks validity conditions and charges intrinsic costs. Then the EVM begins running the destination contract’s bytecode with a fresh machine state. The input data becomes the contract call data. The stack starts empty. Memory starts empty. The program counter starts at the first instruction.
Suppose the contract is a simple vault and the input data corresponds to withdraw(5 ether). The code might first check who the caller is, then load a balance from storage, compare it to the requested amount, and either continue or revert. If it continues, it may update storage to reduce the caller’s balance and then perform an external call to transfer ETH.
Each of those actions corresponds to concrete EVM behavior. Reading storage consumes gas. Writing storage consumes more gas because persistent state is changing. Preparing call data requires memory operations. Making the external call creates a new execution context with its own stack and memory, while still belonging to the same top-level transaction.
Now the critical part: if execution completes normally, the resulting state changes are committed. If execution hits an exceptional halt such as out-of-gas, invalid opcode, invalid jump, or stack underflow, the state changes from that execution are reverted. This rollback behavior is fundamental. The EVM is not “best effort.” It is atomic at the transaction or call-frame level according to the execution rules.
That atomicity is why patterns like reentrancy matter so much. In the DAO exploit, a recursive calling pattern let control flow return into vulnerable code before the intended invariant had been fully secured. The lesson was not that the EVM was broken in the sense of inconsistent execution. The lesson was that deterministic execution of exactly the programmed behavior can still produce disastrous results when contract logic is wrong.
How does gas meter execution and prevent non‑terminating or costly code on Ethereum?
A virtual machine that runs untrusted code on every node has an obvious failure mode: someone writes code that never stops, or that is cheap to send but expensive for the network to execute. **Gas is Ethereum’s answer to that problem. **
Every transaction specifies a gasLimit, and each EVM operation charges gas according to protocol rules. Computation, memory expansion, storage access, storage writes, contract creation, and many other actions all consume gas. Execution can continue only while gas remains.
This does two things at once. First, it meters resource use so that users pay for the burden they place on the network. Second, it guarantees termination in an economic sense: even if the code contains an infinite loop, the loop cannot run forever because gas will eventually run out.
This is the cleanest way to understand gas: it is not merely a fee market unit; it is a halting budget. The fee market sits on top of that mechanism. Under EIP-1559, each transaction pays a block base fee per gas consumed, and that base fee is burned. The user may also pay a priority fee to incentivize inclusion. But those pricing details only make sense because gas already measures execution work.
Gas accounting also reveals what the protocol considers expensive. Persistent state is costly because it creates long-lived burden for the network. Memory is cheaper because it vanishes after execution. Certain contract creation costs exist not because creation is philosophically special, but because validating and storing code imposes real work on clients.
Recent protocol changes make this clearer, not less. EIP-3860, for example, added a limit and metering for initcode, the code used during contract creation, because clients had to analyze it and that work scaled with size. The mechanism is very direct: if an operation causes measurable work or long-term state impact, protocol designers try to make that work explicit in gas.
Why is deploying a contract treated as running initcode (CREATE/CREATE2)?
| Method | Address derivation | Predictability | Initcode execution | Failure behavior |
|---|---|---|---|---|
| Create transaction | Sender address + nonce | Not precomputable | Runs initcode once | Atomic; no partial deployment |
| CREATE instruction | Creator address + nonce | Depends on creator nonce | Executes initcode then stores code | Atomic; aborted on failure |
| CREATE2 instruction | Creator+salt+initcode hash | Precomputable address | Executes initcode then stores code | Atomic; aborted on failure |
Deploying a contract is not just “uploading code.” In the EVM, contract creation itself is a computation. The transaction or CREATE/[CREATE2](https://ethereum.github.io/yellowpaper/paper.pdf) instruction provides initialization code, often called initcode. The EVM executes that initcode once. Whatever bytes it returns become the deployed runtime code.
This surprises many developers at first, but it explains a lot. Constructor arguments, library linking, initialization logic, and even factory patterns make sense because the deployment phase is a program that produces another program.
The address of the new contract is derived deterministically. For CREATE, it depends on the creator address and nonce. For CREATE2, it depends on the creator, a salt, and the hash of the initcode. That second form is useful when developers need predictable addresses before deployment.
Just as importantly, creation is atomic. If the initcode runs out of gas, throws an exceptional halt, or cannot afford the final code-deposit cost, then the creation has no effect and no runtime code is stored. This is not a partial deployment. Either a valid contract appears at the derived address, or nothing does.
The introduction of the EVM Object Format, or EOF, pushes this area further. EOF defines a versioned, extensible container format for EVM bytecode with validation at deploy time. The big idea is simple: if the protocol can validate structure once when code is deployed, execution and analysis later become cleaner and safer. Code and data are separated, versions can evolve more explicitly, and some classes of ambiguity become impossible by construction. That is a sign of the EVM ecosystem maturing from “just execute byte arrays” toward more structured executable objects.
Why do multiple EVM client implementations matter for consensus and reliability?
Ethereum does not have a single EVM program that everyone runs. It has a specification and many implementations. Geth is written in Go, Nethermind in . NET, Besu in Java, and there are standalone EVM engines such as evmone in C++. The EVM exists at the level of semantics, not at the level of one codebase.
This is important because consensus depends on cross-client agreement, not on trusting one implementation. If two major clients interpret an edge case differently, that is not a minor bug; it is a consensus risk. That is why the formal Yellow Paper, the execution-spec reference implementation, client test suites, and mechanized semantics such as KEVM all matter. They reduce the chance that “what everyone thought the EVM meant” diverges from “what nodes actually do.”
The execution-spec repository makes this practical by maintaining a readable Python specification of Ethereum’s execution layer and its fork-by-fork changes. The point is not that Python is how production nodes should execute blocks. The point is that readability helps humans inspect the rules they are all expected to implement.
This also explains why EIPs are central to EVM evolution. Opcode additions, gas repricing, transaction-format changes, and bytecode-format changes are not informal conventions. They are standardized through the EIP process and activated through network upgrades. The EVM is stable enough for compatibility to matter, but not frozen. It evolves by changing the consensus rules all clients must follow.
EVM trade‑offs: where compatibility helps and where performance or parallelism suffer
| Runtime | Compatibility | Parallelism | Performance fit | Best for |
|---|---|---|---|---|
| EVM | Large existing ecosystem | Sequential block-ordered | Suboptimal for modern CPUs | Compatibility and tooling |
| WASM-style runtimes | Smaller EVM ecosystem | Designed for parallelism | Better CPU/compiler fit | Performance-oriented runtimes |
The EVM’s biggest strength is not raw speed. It is the combination of deterministic execution, broad compatibility, and an enormous surrounding ecosystem. Solidity compilers, opcode explorers, auditors, formal verification tools, token standards, wallet integrations, rollup environments, and developer frameworks all fit together because they target the same execution model.
This ecosystem effect is strong enough that even systems not built on Ethereum often choose EVM compatibility. For developers, that means existing contracts can often be redeployed with little change. For users, it means familiar wallets and applications can interoperate more easily. For infrastructure providers, it means existing tooling can be reused.
But the same design brings tradeoffs. The EVM is fundamentally sequential in its execution model. Transactions in a block are applied as an ordered sequence of state transitions. That makes shared-state composability simple to reason about, but it does not naturally expose parallelism the way a runtime like Solana’s Sealevel does, where transactions declare state access up front.
The stack-based instruction set is also relatively awkward for high-performance compilation compared with more modern VM designs. And persistent state is expensive to manage at scale, which is why so much protocol engineering ends up focused on gas schedules, access patterns, and reducing unnecessary state growth.
So when people compare the EVM to WASM-based runtimes, the real question is not “which instruction set is prettier?” It is usually a deeper architectural tradeoff between ecosystem compatibility and runtime ergonomics or performance. Ethereum and many adjacent systems have repeatedly chosen compatibility because the value of a shared execution target is very high.
What real‑world applications and workflows run on the EVM?
People often say the EVM “runs smart contracts,” which is true but underspecified. What matters is that the EVM lets contracts act as shared state machines for many different applications. Tokens keep balances and allowances in storage. Exchanges update reserves and pricing invariants. Lending protocols track collateral and debt. Governance systems record voting power and proposal state. Account abstraction systems validate user operations through programmable logic. Rollups often replicate EVM semantics so that this same software model can run in a different settlement environment.
The EVM also matters in custody and settlement design, especially where multiple parties must jointly authorize on-chain actions. In threshold signing and MPC systems, the execution environment on-chain may still be an EVM-compatible contract even though the off-chain authorization mechanism is distributed. A concrete example is Cube Exchange’s decentralized settlement design, which uses a 2-of-3 threshold signature scheme: the user, Cube Exchange, and an independent Guardian Network each hold one key share; no full private key is ever assembled in one place, and any two shares are required to authorize a settlement. The threshold cryptography happens off-chain, but the settlement logic can still target EVM-style execution and account semantics.
That is a useful reminder that the EVM is often only one layer in a larger system. It defines what happens when transactions reach execution. It does not define every surrounding trust, signing, or coordination mechanism.
What is the minimal formal model of EVM execution and the state transition?
Once the intuition is clear, the formal picture becomes much less intimidating. Ethereum defines a transaction as an externally signed instruction. The world state maps addresses to accounts. The execution model runs code with a machine state that includes remaining gas, the program counter, memory, stack, and returndata. The transaction-level state transition produces either a new state and leftover gas information or an execution failure that reverts the attempted changes.
At the block level, the mechanism is just composition: apply the first transaction to the current state, then the second to that result, and so on through the block. After transaction execution, Ethereum also applies some block-level effects. In Shanghai and later, for example, consensus-layer withdrawals are processed after transactions as balance increases to recipients; they are not ordinary EVM transfers, they cannot fail, and they consume no gas.
That detail is worth noting because it shows the boundary of the EVM clearly. Not every balance change on Ethereum comes from ordinary contract execution. The EVM is the core execution engine, but the protocol also defines surrounding state changes at the block level.
Conclusion
The EVM is best understood as Ethereum’s metered, deterministic state-transition machine for running smart-contract bytecode. It exists because a programmable blockchain needs every node to execute the same untrusted code under the same rules and with bounded resource use.
If you remember one sentence tomorrow, make it this: **the EVM turns transactions into agreed state changes by executing bytecode against shared state, with gas enforcing a hard budget and rollback preserving atomicity when execution fails.
** Everything else is built on top of that idea.
- smart contracts
- tooling
- EVM-compatible chains
- much of Ethereum’s ecosystem
How does the EVM affect how I should fund, trade, or settle assets?
The EVM determines how transactions execute, how gas affects cost and finality, and what contract risks you face; so it matters before you fund, trade, or settle on an EVM chain. On Cube Exchange, you can fund and trade assets while applying a few concrete EVM checks to reduce execution, cost, and interoperability surprises.
- Check the network’s execution model and finality: read the chain’s docs or a block explorer to confirm it is EVM-compatible, learn its finality rule, and note any recommended confirmation count before you consider a deposit or withdrawal.
- Verify the asset and contract details: copy the token’s contract address from an official source, confirm token decimals and proxy patterns on a verified block explorer, and avoid deposits if the contract is unverified or nonstandard.
- Fund your Cube account with fiat or a supported crypto transfer, and estimate total settlement cost by adding the on‑chain gas estimate (including EIP‑1559 base fee burn) to any on‑exchange fees.
- Open the relevant market on Cube and choose execution: use a limit order for price control (and to reduce slippage/MEV exposure) or a market order for immediate fills; set max gas priority fee or slippage tolerances, review estimated fees, then submit.
Frequently Asked Questions
- How does gas actually stop an infinite loop or non-terminating contract? +
- Gas is a built-in execution budget: every EVM operation charges gas and execution stops when gas is exhausted, causing an exceptional halt that reverts the execution’s state changes; this economic metering therefore prevents infinite loops from running forever.
- If a nested contract call runs out of gas or reverts, do the outer contract's state changes get rolled back too? +
- If an internal call triggers an exceptional halt (out-of-gas, invalid opcode, etc.), the state changes from that execution are reverted; rollback is atomic at the transaction or call‑frame level, so whether the outer context continues depends on how the calling code handles the failed call.
- Can smart contracts read the large “blob” data added by EIP-4844 inside EVM execution? +
- No — blob contents introduced by EIP-4844 are not readable by EVM bytecode; only a commitment/versioned hash is exposed to the execution layer, so contracts cannot directly access blob bytes.
- What’s the practical difference between EVM memory, transient storage, and persistent storage? +
- Memory is ephemeral to the current execution context and disappears when execution ends; transient storage (TSTORE/TLOAD) persists across internal calls within the same transaction but is cleared at transaction end; persistent storage is the per-account storage trie committed into global state and survives across transactions.
- Why is deploying a contract treated as executing code (initcode) instead of just uploading bytecode? +
- Contract deployment runs the provided initcode as an EVM program; whatever bytes that initcode returns become the contract’s runtime code, the address is derived deterministically (CREATE by sender+nonce, CREATE2 by sender+salt+initcode hash), and if the initcode fails the creation is aborted with no code stored.
- Why does the EVM use 256‑bit words instead of a CPU-native word size like 64 bits? +
- The EVM uses 256‑bit words because that size aligns with Ethereum’s cryptographic and hashing primitives (256‑bit values are common), which simplifies contract-level computations even though it is not the most efficient native word size on typical CPUs.
- How are changes to EVM behavior introduced and how do clients stay in agreement? +
- EVM changes are proposed and standardized as EIPs and require coordinated network upgrades; execution-specs, client test suites, and mechanized semantics exist so multiple clients can implement the same new rules and avoid consensus divergence.
- What is the EVM Object Format (EOF) and why does it matter for deployed contracts? +
- EOF (EVM Object Format) is a versioned container and deploy‑time validation scheme for EVM bytecode that separates code and data, enables structured validation when code is deployed, and aims to make later execution and analysis safer and more predictable.
- What happens if different EVM implementations disagree about an edge‑case? +
- If two major clients interpret an edge case differently, that creates a consensus risk because Ethereum relies on cross‑client agreement; this is why the Yellow Paper, readable execution specifications, test suites, and formal semantics are maintained to minimize such divergences.