Skip to main content

What is Bytecode?

EVM bytecode is a sequence of hexadecimal bytes representing instructions (opcodes) and their data. Each opcode is 1 byte, and some opcodes are followed by additional data bytes.

Bytecode Structure

0x6003600201
  │  │  │ │└─ ADD (0x01)
  │  │  └─── PUSH1 0x02
  └──┴────── PUSH1 0x03
This bytecode:
  1. Pushes 0x03 onto the stack
  2. Pushes 0x02 onto the stack
  3. Adds the top two stack values

Reading Bytecode

Bytecode is read left to right, two characters at a time (one byte):
1

Parse in pairs

60 03 60 02 01 - Each pair is one byte
2

Identify opcodes

  • 60 = PUSH1 (followed by 1 data byte)
  • 01 = ADD (no data bytes)
3

Extract data

  • After PUSH1 (60), the next byte is data: 03
  • After the second PUSH1, the data is: 02

Opcode Format

Fixed-Length Opcodes

Most opcodes are just 1 byte with no additional data:
01 = ADD
02 = MUL  
03 = SUB
50 = POP

Variable-Length Opcodes (PUSH)

PUSH opcodes are followed by 1-32 bytes of data:
OpcodeHexData BytesExample
PUSH10x601 byte60 0a pushes 10
PUSH20x612 bytes61 01 2c pushes 300
PUSH30x623 bytes62 0f 42 40
PUSH320x7f32 bytesFull 256-bit value
PUSH0 (0x5f) pushes zero without any data bytes - it’s the only PUSH that doesn’t need data.

Examples from Tests

Simple Arithmetic

# 20 - 10 = 10 (0x0a)
cubipods -b 600a601403
Breakdown:
  • 60 0a - PUSH1 10
  • 60 14 - PUSH1 20
  • 03 - SUB

Memory Operations

# Store 0x20 at memory location 0x80
cubipods -b 6020608052
Breakdown:
  • 60 20 - PUSH1 32 (value to store)
  • 60 80 - PUSH1 128 (memory address)
  • 52 - MSTORE

Storage Operations

# Store "hello" (0x68656c6c6f) in slot 1
cubipods -b 6468656c6c6f600155
Breakdown:
  • 64 68656c6c6f - PUSH5 “hello” in hex
  • 60 01 - PUSH1 1 (storage slot)
  • 55 - SSTORE

Common Patterns

Pushing Small Numbers

For values 0-32, use PUSH1:
60 00  = PUSH1 0    (push zero)
60 01  = PUSH1 1    (push one)
60 20  = PUSH1 32   (push 32)

Pushing Zero

PUSH0 is more efficient:
5f = PUSH0  (equivalent to 60 00)

Multiple Operations

Chain operations together:
# (10 + 20) * 2 = 60
cubipods -b 6002601460140102
Breakdown:
  • 60 02 - PUSH1 2
  • 60 14 - PUSH1 20
  • 60 14 - PUSH1 20
  • 01 - ADD (20 + 20 = 40)
  • 02 - MUL (40 * 2 = 80… wait, this is wrong!)
Stack operations are LIFO (Last-In-First-Out). The order matters!
Correct version:
# (10 + 20) * 2 = 60
cubipods -b 6020600a0160020102
Stack trace:
  1. PUSH1 32 → [32]
  2. PUSH1 10 → [32, 10]
  3. ADD → [42] (32 + 10)
  4. PUSH1 2 → [42, 2]
  5. MUL → [84] (42 * 2)

Bytecode Validation

Cubipods validates bytecode when parsing:
// From src/lexer.rs:45-55
pub fn next_byte(&mut self) -> Result<String, Box<dyn Error>> {
    let first_nibble = self.ch;
    self.read_char();
    let second_nibble = self.ch;

    if first_nibble.is_whitespace() || second_nibble.is_whitespace() {
        return Err(Box::new(LexerError::HasWhitespace));
    }

    if !first_nibble.is_ascii_hexdigit() || !second_nibble.is_ascii_hexdigit() {
        return Err(Box::new(LexerError::InvalidNibble));
    }
    // ...
}

Valid Formats

# With 0x prefix (recommended)
cubipods -b 0x6003600201

# Without prefix
cubipods -b 6003600201

Invalid Formats

# Spaces
cubipods -b "60 03 60 02 01"  # ❌ Error: HasWhitespace

# Odd length
cubipods -b 0x600360020  # ❌ Error: EmptyChar

# Non-hex characters  
cubipods -b 0xZZZZ  # ❌ Error: InvalidNibble

Building Bytecode

Manual Construction

Calculate opcodes and data manually:
  1. Look up opcode hex values in Opcodes Overview
  2. Convert data to hex
  3. Concatenate bytes
Example - Push “Hi” (0x4869) and hash it:
62        # PUSH3 (need 3 bytes for padding)
004869    # "Hi" padded to 3 bytes
20        # KECCAK256
Result: 62004869620

Using Tests

The test suite shows many examples:
// From tests/integration_test.rs
#[test]
fn it_runs_add_opcode() -> Result<(), Box<dyn Error>> {
    // 10 + 20 = 30 (0x1e)
    let bytecode = "6014600a01";
    let mut vm = Vm::new(&bytecode, false)?;
    vm.run()?;
    assert_eq!(vm.stack.peek().unwrap(), "1e");
    Ok(())
}

Next Steps

Execution Model

See how bytecode is executed step by step

Opcodes Reference

Complete list of supported opcodes

CLI Examples

More bytecode examples to try

Try It Out

Execute bytecode yourself

Build docs developers (and LLMs) love