Emanuele RicciEmanuele Ricci

Emanuele Ricci

3 min read

EVM Puzzle 3 solution

This is Part 3 of the “Let’s play EVM Puzzles” series, where I will explain how to solve each puzzle challenge.

EVM Puzzles is a project developed by Franco Victorio (@fvictorio_nan) that a perfect fit if you are in the process of learning how the Ethereum EVM works and you want to apply some of the knowledge you have just acquired.

EVM Puzzle 3

00      36      CALLDATASIZE
01      56      JUMP
02      FD      REVERT
03      FD      REVERT
04      5B      JUMPDEST
05      00      STOP

The problem is similar to the [[Puzzle 1]] and [[Puzzle 2]] challenges where we need to find a way to have in the EVM Stack the correct value when the JUMP opcode is executed. We need to have into the stack the value 4 in order to land in a valid JUMPDEST opcode.

In this puzzle we have only one opcode before the JUMP

To solve this challenge it's important to understand what the calldata is.

From Chapter 13 - The Ethereum Virtual Machine

The call data region is the data that is sent with a transaction. In the case of contract creation, it would be the constructor code. This region is immutable and can be read with the instructions CALLDATALOADCALLDATASIZE, and CALLDATACOPY.

Instead from OpenZeppelin blog post "Deconstructing a Solidity Contract — Part III: The Function Selector" the calldata is explained like:

As explained in Solidity’s documentation ABI specification, the calldata is an encoded chunk of hexadecimal numbers that contains information about what function of the contract we want to call, and it’s arguments or data. Simply put, it consists of a “function id”, which is generated by hashing the function’s signature (truncated to the first leading four bytes) followed by the packed arguments data.

If for example we want to interact with a Contract to withdraw 10 WETH we would call the contract's function that have this signature: withdraw(uint256). The calldata value for that call would be 0x2e1a7d4d0000000000000000000000000000000000000000000000008ac7230489e80000 which the 4 first bytes represents the function signature, the other 32 would represent the uint256 parameter value passed to it.

Just try to print this in your Solidity contract to reproduce it: abi.encodeWithSignature("withdraw(uint256)", 10 ether);

Solution

The solution in this challenge is pretty easy, we just need to pass 4 bytes input value in order to make the JUMP op to jump to the JUMPDEST destination.

For example we could pass the 4 bytes that represent the signature of the function we have used in the example above. In this case we would pass 0x2e1a7d4d to solve the challenge.

Here's the link to the solution of Puzzle 3 on EVM Codes website to simulate it.