March 22, 2024

EVM Puzzle 1 & 2: Understanding Stack Operations

8 min readDifficulty: Beginner

Introduction

In this post, we'll tackle the first two EVM puzzles, which focus on understanding stack operations and basic program flow.

I highly recommend keeping evm.codes open in a separate tab as a reference while working through these puzzles. It provides detailed documentation for all EVM opcodes we'll be using.

Puzzle 1:

CALLVALUE and JUMP

Puzzle 1 introduces us to the CALLVALUE opcode and how it interacts with JUMP operations.

GOAL: The goal for each of these puzzles is to reach the JUMPDEST, or the DESTination you are JUMPing to.

Copy and Paste → 3456FDFDFDFDFDFD5B0 into the EVM Playground. Then click RUN.

# GOAL:
# Make the execution reach the "JUMPDEST" location (We want to JUMP to this DESTination).
# When the execution reaches JUMPDEST it will return from the contract successfully.
# If the execution reaches any other part with the REVERT or INVALID opcode ('fail' label),
# it will revert with an error.

00      34      CALLVALUE                    
01      56      JUMP
02      FD      REVERT
03      FD      REVERT
04      FD      REVERT
05      FD      REVERT
06      FD      REVERT
07      FD      REVERT
08      5B      JUMPDEST
09      00      STOP



# Bytecode: 0x3456FDFDFDFDFDFD5B0
Note: Notice the numbers in the middle column come straight from the bytecode starting from the bottom.

Understanding the Puzzle

LocationOpcodeMeaningOperationStack After
0CALLVALUEThis is where we "CALL" or give the value of the destination we want to get to. In this case the JUMPDEST is at location 06, so we're going to call a value of 6 (ETH).Add 8 to the stack[8]
1JUMPNow we are going to JUMP to the location we just called (8)Jump to location 8[]
2REVERTFAIL[]
3REVERTFAIL[]
4REVERTFAIL[]
5REVERTFAIL[]
6REVERTFAIL[]
7REVERTFAIL[]
8JUMPDESTLocation 8SUCCESS!!![]
9STOPHalts execution successfully-[]

Solution:

To solve this puzzle, we need to send exactly 8 wei with the transaction. This will make the JUMP instruction jump to position 8, where the JUMPDEST is located.

Puzzle 2:

CODESIZE

Puzzle 2 introduces us to the CODESIZE opcode and builds on our understanding of JUMP operations.

Copy and Paste → 34380356FDFD5B00FDFD into the EVM Playground. Then click RUN.

# Puzzle 2
# Goal: 
# JUMPDEST is at location 06 here, so we want to JUMP to location 6.
#
# The contract's code is:
#
# 00      34      CALLVALUE
# 01      38      CODESIZE
# 02      03      SUB
# 03      56      JUMP
# 04      FD      REVERT
# 05      FD      REVERT
# 06      5B      JUMPDEST
# 07      00      STOP
# 08      FD      REVERT
# 09      FD      REVERT
#
# Bytecode: 0x34380356FDFD5B00FDFD

Understanding the Puzzle

Solve for X

LocationOpcodeMeaningOperationStack After
0CALLVALUEPushes the amount of ETH sent with the transaction. We don't know this value yet so for now it's "x".Push X[X]
1CODESIZEPushes the size of the contract's code. Since there are 10 locations here (from 0-9), the CODESIZE is 10 bytesPush 10[10, X]
2SUBSubtracts the top two items on the stack10 - X[6]
3JUMPJumps to the position specified by the top stack value. Since we need this value to be 6, X must be 4 (10-4=6).Jump to 6[6]
4REVERTReverts the transaction if we jump hereFAIL[]
5REVERTReverts the transaction if we jump hereFAIL[]
6JUMPDESTValid jump destination markerSUCCESS!!![]
7STOPHalts execution successfully-[]
8REVERTReverts the transaction if we jump hereFAIL[]
9REVERTReverts the transaction if we jump hereFAIL[]

New Opcodes in Puzzle 2

  • CODESIZE (0x38): Pushes the size of the contract's code onto the stack
  • SUB (0x03): Subtracts the top two items on the stack

Solution:

To solve this puzzle, we needed to send 4 wei with the transaction. Here's why:

  1. The contract code is 10 bytes long (CODESIZE = 10)
  2. We need to jump to position 6 (the JUMPDEST)
  3. Therefore: 10 - CALLVALUE = 6
  4. Solving for CALLVALUE: CALLVALUE = 10 - 6 = 4