Visualizing the Ethereum Virtual Machine
December 18, 2025
I like the vision of an open, verifiable, and censorship-resistant financial system. While the vision is still a heavy work in progress, I find the tech behind Ethereum to be interesting. So, I wanted to go through the exercise of building and visualizing an ethereum virtual machine, to understand how smart contracts actually run on Ethereum.
The actual implementation turned out to be pretty straightforward, although I ended up implementing a limited number of opcodes.
PC: 0 Gas: 21000 Status: RUNNING
Instructions
0: PUSH1 0x2a ← PC
2: PUSH1 0x00
4: MSTORE
5: PUSH1 0x00
7: MLOAD
8: PUSH1 0x00
10: SSTORE
11: PUSH1 0x00
13: SLOAD
14: PUSH1 0x00
16: MSTORE
17: PUSH1 0x20
19: PUSH1 0x00
21: RETURN
Stack (0/1024)
Empty
Memory
0x
Storage
Empty
Transient
Empty
Implemented Opcodes
| Opcode | Name | Minimum Gas | Description |
|---|---|---|---|
| 0x00 | STOP | 0 | Halt execution |
| 0x01 | ADD | 3 | Pop two values, push their sum |
| 0x02 | MUL | 5 | Pop two values, push their product |
| 0x03 | SUB | 3 | Pop two values, push their difference |
| 0x04 | DIV | 5 | Pop two values, push their quotient |
| 0x10 | LT | 3 | Less than comparison (a < b → 1, else 0) |
| 0x11 | GT | 3 | Greater than comparison (a > b → 1, else 0) |
| 0x14 | EQ | 3 | Equality check (a == b → 1, else 0) |
| 0x15 | ISZERO | 3 | Check if value is zero (0 → 1, else 0) |
| 0x16 | AND | 3 | Bitwise AND of two values |
| 0x17 | OR | 3 | Bitwise OR of two values |
| 0x18 | XOR | 3 | Bitwise XOR of two values |
| 0x19 | NOT | 3 | Bitwise NOT (256-bit inversion) |
| 0x50 | POP | 2 | Remove top stack item |
| 0x51 | MLOAD | 3 | Load 32 bytes from memory (+ expansion cost) |
| 0x52 | MSTORE | 3 | Store 32 bytes to memory (+ expansion cost) |
| 0x54 | SLOAD | 100 | Load value from storage |
| 0x55 | SSTORE | 100 | Store to storage (100-20000 depending on state) |
| 0x5C | TLOAD | 100 | Load from transient storage (EIP-1153) |
| 0x5D | TSTORE | 100 | Store to transient storage (EIP-1153) |
| 0x60 | PUSH1 | 3 | Push 1-byte value onto stack |
| 0x80 | DUP1 | 3 | Duplicate top stack item |
| 0x81 | DUP2 | 3 | Duplicate 2nd stack item |
| 0x90 | SWAP1 | 3 | Swap top two stack items |
| 0xF3 | RETURN | 0 | Return from execution |