We reject abstraction
We believe in bytecode
Bytecode is the only true form
Let’s code with bytes now
Last week, we talked about EVM Bytecode, the raw machine level code that the Ethereum Virtual Machine (EVM) understands and executes. This week, we're going a level deeper: Opcodes.
An opcode (short for operation code) is a single instruction that tells the EVM what to do.
Think of it like a Lego block: each opcode does one very specific thing. When you put a bunch of them together, you build a working smart contract.
Each opcode is represented by 1 byte (2 hexadecimal characters), and each one corresponds to an operation like:
Storing data Loading data Adding two numbers Returning a result Jumping to a different part of the code
Some opcodes are followed by parameters or data, depending on what the operation needs.
Let’s take this snippet of bytecode:
7F00000000000000000000000000000000000000000000000000000000000000105F5260205FF3
In plain English:
It pushes the number 16 (at the end of the PUSH32) to memory position 0 Then, it returns 32 bytes of memory starting at position 0 This includes the number 16 we just stored, followed by 31 zero bytes
It's a simple program that always returns the same 32-byte value (number 16 in decimal), which is composed mostly of zeros, except for a 0x10 (16) at the end.
We’ll break this down into opcodes and understand what each one does.
We'll read it left to right, 1 byte at a time (2 hex characters = 1 byte)
Initial Stack: The stack is empty at the beginning.
Opcode 7F (PUSH32): Pushes the next 32 bytes onto the stack. These bytes represent the number 0x0000000000000000000000000000000000000000000000000000000000000010
, which is 16 in decimal.
Opcode 5F (PUSH0): Pushes the constant 0 onto the stack (Equivalent to PUSH1 0, but with gas savings).
Opcode 52 (MSTORE): Pops the top two values from the stack and stores the second value at the memory location specified by the first value. In this case, it stores 0x0000000000000000000000000000000000000000000000000000000000000010
at memory location 0.
Opcode 60 20 (PUSH1 0x20): Pushes the byte 0x20 (32 in decimal) onto the stack (length of the data we want to return).
Opcode 5F (PUSH0): Pushes the constant 0 onto the stack.
Opcode F3 (RETURN): Pops the top two values from the stack. The first value specifies the memory location to start returning data from, and the second value specifies the size of the data to return. It returns 32 bytes starting from memory location 0.
The returned data is 0x0000000000000000000000000000000000000000000000000000000000000010
, the number 16 in decimal notation.
Stack Operations: The stack operates on a Last In, First Out (LIFO) principle. Each opcode manipulates the stack by pushing or popping values, which are then used in subsequent operations.
Memory Storage: The MSTORE opcode stores data in memory, which is temporary and used during contract execution. In this example, the number 16 is stored at memory location 0.
Returning Data: The RETURN opcode allows the contract to return data to the caller. It specifies the memory location and size of the data to be returned.
Try using our online EVM Disassembler to break apart this bytecode yourself.
filosofiacodigo.eth and Cooldev1337