This page covers the core execution concepts used throughout the opcode threat models.
What is the EVM?
The Ethereum Virtual Machine is a stack-based machine that runs contract bytecode. Essentials:
- Stack: Up to 1024 cells of 32-byte values. Most opcodes pop inputs and push outputs; only
PUSHreads from code. - Deterministic: Same code and inputs give the same result on every node.
- Execution: One instruction at a time. JUMP / JUMPI change where execution goes; STOP / RETURN end the call successfully; REVERT aborts and rolls back all state changes for the call. If an opcode cannot run (e.g. stack underflow, out of gas), execution reverts.
Execution context
Each call has a context with these regions. Threat models often refer to which region an opcode reads or writes.
| Region | Persistence | Access opcodes | Notes |
|---|---|---|---|
| Code | Permanent (on-chain) | CODESIZE, CODECOPY, EXTCODESIZE, EXTCODECOPY | Immutable bytecode of the contract (or target contract) |
| Stack | Per call | PUSH, POP, DUP, SWAP, … | LIFO; operands and results for opcodes |
| Memory | Per call | MLOAD, MSTORE, MSTORE8, MSIZE | Byte-addressable, zero-initialized, volatile |
| Storage | Permanent (on-chain) | SLOAD, SSTORE | 32-byte key → 32-byte value, per contract |
| Transient storage | Per transaction | TLOAD, TSTORE | Cleared after the transaction (EIP-1153) |
| Calldata | Per call | CALLDATALOAD, CALLDATASIZE, CALLDATACOPY | Immutable input to the call |
| Return data | Per call | RETURNDATASIZE, RETURNDATACOPY | Output of the last external call |
Program counter
The PC is the index of the next instruction in code. It normally steps one byte at a time. PUSHn skips its immediate bytes (the pushed constant). JUMP / JUMPI set the PC to a JUMPDEST; invalid jumps cause a revert. This is where control-flow and reentrancy show up in threat models.
Back to EVM Threat Models.