# Control Flow in Bytecode **Published by:** [Bytecode Tuesday](https://paragraph.com/@bytecodetuesday/) **Published on:** 2025-05-27 **URL:** https://paragraph.com/@bytecodetuesday/5-control-flow-in-bytecode ## Content We reject abstraction We believe in bytecode Bytecode is only true form Let’s code with bytes now Last week, we talked about Stack, Memory, and Storage, the three data regions of the EVM. Today, we’re going to explore how smart contracts make decisions and change execution paths using control flow.What is control flow?Control flow is the logic that determines what happens next in a program. In Solidity, you use if, else, for, while, or function calls. In bytecode, those high-level keywords are translated into jump instructions. The EVM is a very simple machine, it executes bytecode one instruction at a time, moving forward by default. But with control flow instructions, we can tell it to jump to a different part of the code, or conditionally jump based on a value.The Core Control Flow Opcodes OpcodeNameDescription56JUMPJump to a specific position in the code (unconditional)57JUMPIJump to a position only if a condition is met (conditional)5BJUMPDESTMarks a valid place to jump to. You must jump only to a location with this opcodeExample: Conditional return based on inputLet’s say you want to write a smart contract that:Returns 0x02 if the input is greater than 10Otherwise, returns 0x01This is what our example looks like in pseudocode: 10) { return 0x02; } else { return 0x01; }">if (input > 10) { return 0x02; } else { return 0x01; }And here’s what the EVM bytecode can be implemented:OffsetBytecodeDescription0060 0APUSH1 0x0A Push the number 10 to the stack0260 00PUSH1 0x00 We are going to load the first 32 bytes of calldata (the program input)0435CALLDATALOAD Load the number sent as parameter0511GT Check if input > 100660 0EPUSH1 0x0E Destination if TRUE0857JUMPI Jump to label if GT was TRUEFalse branch (default: input <= 10)0960 01PUSH1 0x01 Push value 10B60 12PUSH1 0x12 Destination to branch merge point0D56JUMP to merge pointTrue branch (input > 10) starts at 0x120E5BJUMPDEST Safe jump target0F60 02PUSH1 0x02 Push value 2Branch merge point, true and false branches converge here125BJUMPDEST Safe jump target1360 00PUSH1 0x00 Memory offset 01552MSTORE Store the result (either the number 1 or 2) from the stack to memory location 01660 20PUSH1 0x20 Return length set to 32 bytes1860 00PUSH1 0x00 Return offset set to 01AF3RETURN 32 bytes and end execution Step-by-step execution when passed 15 (0x00..0E) as calldata parameter. This number is greater than 10 to 0x02 will be returned.5 is lesser than 10 so 0x01 is returnedDo we need JUMPDEST?The EVM doesn’t allow jumping to just any byte, it has to be a JUMPDEST. This design prevents jumping into the middle of data or invalid instruction segments. Think of JUMPDEST as a checkpoint you can land on. While marking safe spots for jump instructions is considered a sound and secure virtual machine design choice, the EVM has been rightfully criticized for requiring full 32-byte absolute offsets for every jump. This approach is unnecessarily heavy. A more ergonomic and lightweight alternative would be to use relative jumps based on the current execution point (known as the program counter). In most cases, such as typical if or while logic, the jump distances are small and could easily be expressed in a single byte. The inefficiency of absolute jumps is well-known, and there is ongoing discussion in the Ethereum ecosystem about adopting relative jumps in future virtual machine designs.What’s Happening?Input is loaded from calldata.Compared with 10 using the GT (greater than) opcode.If true, we JUMPI to a labeled part of the code where we return 0x01.If false, the EVM continues forward and returns 0x00 and jumps to the merge pointThe merge point is where both true and false branches reunite and returns the resultBoth branches store the result at the stack, then on the merge point a 32-byte value padded with zeros is returned.Try It YourselfModify it and check it using this EVM Disassembler to:Return 0xAA if the input is less than 5Return 0xBB if the input is between 5 and 20Return 0xCC otherwiseSo far, we've explored bytecode piece by piece, but what does a real smart contract look like in raw bytecode? Next Tuesday, we’ll take a full contract and break it down section by section. Subscribe now and see you next Tuesday for more bytecode. ## Publication Information - [Bytecode Tuesday](https://paragraph.com/@bytecodetuesday/): Publication homepage - [All Posts](https://paragraph.com/@bytecodetuesday/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@bytecodetuesday): Subscribe to updates ## Optional - [Collect as NFT](https://paragraph.com/@bytecodetuesday/5-control-flow-in-bytecode): Support the author by collecting this post - [View Collectors](https://paragraph.com/@bytecodetuesday/5-control-flow-in-bytecode/collectors): See who has collected this post