# SWITCH the way you use conditionals!

**URL:** <https://forum.openzeppelin.com/t/switch-the-way-you-use-conditionals/1651>\
**Category:** Guides and Tutorials\
**Tags:** tutorial, assembly-series\
**Created:** [October 29, 2019, 8:28pm UTC](https://forum.openzeppelin.com/t/switch-the-way-you-use-conditionals/1651 "2019-10-29T20:28:11Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![andresbach](https://avatars.discourse-cdn.com/v4/letter/a/839c29/32.png) [@andresbach](https://forum.openzeppelin.com/u/andresbach)\
**Post date:** [October 29, 2019, 8:28pm UTC](https://forum.openzeppelin.com/t/switch-the-way-you-use-conditionals/1651/1 "2019-10-29T20:28:11Z")

</div>

![cover_forum_assembly](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/2X/5/5544ac31fcb3f0ceba14db2ecb29ee724def376d.png)

> NOTE: This article is part of the [series of posts about coding in assembly](https://forum.openzeppelin.com/t/how-to-survive-in-the-assembly-world/1125). Please check out the entire series for more fun!

# Captain's log day 2

-- _You've been burned from the previous day, but your motivation stays intact._

Last time we saw [how to use the conditional `if` statement in `assembly`](https://forum.openzeppelin.com/t/how-would-your-life-be-if-you-start-learning-assembly/1126) and what the bytecode did behind the curtains, but you may have seen that [when we use an `if` statement in `assembly` there is a downside](https://solidity.readthedocs.io/en/v0.5.9/assembly.html#if): We don't have an `else` statement 😣

But don't worry, `Assembly` comes to the rescue with the **`switch`** statement! 🥁

In this article we will be discussing how to make use of the `switch` statement to cover multiple conditional cases that determine the flow of the code to be executed.

## Episode VI – Return of the _Code_

Let's use the example from day 1 and slightly change its desired functionality. If we wanted a different non-zero value in the output when the input is higher than 26 (0x1a), [we could make use of the `if`-`else` statement in Solidity](https://ethereum.stackexchange.com/questions/13952/control-structures-why-is-switch-and-goto-not-in-solidity) combined with the _less than_ operator `<`:

```javascript
function solidityIfElse(uint256 input) public pure returns (uint256 output) {
    if (input < 0x1a) {
        output = 0x1;
    } else {
        output = 0x2;
    }
}

```

But remember that we don't have the `else` statement in assembly, so instead we can use the `switch` statement:

```javascript
function assemblySwitch(uint256 input) public pure returns (uint256 output) {
    assembly {
        switch lt(input, 0x1a)
        case 0x1 {
            output := 0x1
        }
        default {
            output := 0x2
        }
    }
}

```

As you can see, we compare the `input` against the 0x1a value using the `lt(x,y)` instruction. This instruction outputs a one when `x` is strictly less than `y` and a zero in all other cases. We have split the results into two cases: when input is a one and when it's not. This last case would be the `default`.

Analogously, there is a `gt(x,y)` instruction, which is the reciprocal instruction that outputs a one when `x` is strictly greater than `y` and a zero in all other cases.

The `switch` statement reads the input and classifies it among the defined options. Although in this situation we only have a binary problem, the beauty of the `switch` statement is that we can define multiple cases above the default one - which handles all the situations that don't match with the other conditions - and perform operations based on each case.

For our purposes, the possible options are a one and a zero - the output from the `lt` instruction, but, for example, it’s possible that an integer variable goes from 0 to 9, and when the variable is a 2, 6, or 7 the code emits an event but stays quiet otherwise.

One thing to notice - contrary to the gas consumption of the [`assembly` code that we've seen in the past](https://forum.openzeppelin.com/t/how-would-your-life-be-if-you-start-learning-assembly/1126) - is that the `switch` function consumes more gas in the `assembly` case than when we used the Solidity version. So you shouldn't extrapolate the idea that writing the code in `assembly` will always be cheaper. I'll repeat it again: Focus on the code readability and not in the gas optimization.

If you didn't drink any coffee yet, now is the time. I'll wait...

## Episode V – The _Bytecode_ Strikes Back

Ready? Caffeinated? Great, because we are going to compare what the opcodes do in each scenario. This was extracted from the [Remix debug tool](https://remix.ethereum.org/), and as you've learned from [Ale's posts](https://blog.openzeppelin.com/deconstructing-a-solidity-contract-part-i-introduction-832efd2d7737/), the most important instructions of the Solidity `solidityIfElse` function are:

| # | Opcode | Value | Case |
| --- | --- | --- | --- |
| 182 | PUSH1 | 00 | |
| 184 | PUSH1 | 1A | |
| 186 | DUP3 | | |
| 187 | LT | | |
| 188 | ISZERO | | |
| 189 | PUSH1 | C7 | |
| 191 | JUMPI | | D---\> |
| 192 | PUSH1 | 01 | |
| 194 | SWAP1 | | |
| 195 | POP | | |
| 196 | PUSH1 | CC | |
| 198 | JUMP | | 1---\> |
| 199 | JUMPDEST | | \<---D |
| 200 | PUSH1 | 02 | |
| 202 | SWAP1 | | |
| 203 | POP | | |
| 204 | JUMPDEST | | \<---1 |
| 205 | SWAP2 | | |
| 206 | SWAP1 | | |
| 207 | POP | | |
| 208 | JUMP | | R---\> |

If you are sweating, believe in yourself. YOU CAN DO IT!

Again, ~~some magic has happened and~~ we start with our `input` right on top of the stack.

We start `PUSH`ing two values to the stack, a 0x0 and a 0x1A, and we duplicate the `input` value on top of the stack. After that, we use our known `LT` instruction with the first two elements in the stack which would be the `input` and the 0x1A. For those that are new here and don't know how the `LT` works, I recommend you [go to my previous post first](https://forum.openzeppelin.com/t/how-would-your-life-be-if-you-start-learning-assembly/1126) =)

`LT` would decide if the first element is _less than_ the second one, and leave the result on top of the stack. After that, the `ISZERO` instruction in 188 would mirror the result (0x0 -\> 0x1 or 0x1 -\> 0x0), and from here, we have another crossroads. If the `input` is less than 0x1A, `LT` would output a 0x1 in line 187, resulting in a 0x0 after line 188; however, if the `input` is greater than or equal to 0x1A, we would have a 0x0 after 187 but a 0x1 after 188.

– _Why the heck are you trying to make me dizzy?_ &nbsp; - You may ask, but all of this is the evil intention of the compiler, not mine!

Fasten your seatbelts, because after the `PUSH` in line 189, which defines the destination line 199 (0xC7), we are ready to `JUMP` through space and time!

 ![yep, that's a wormhole](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/1X/aee1834af5614659623fc05ec50cd529b797b0cd.jpeg)

... or not...

 ![wormhole_dis](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/2X/3/38cfcd84c67b43c0f82c8b36a7ca05669e2a4aa5.jpeg)

In line 191, we have a `JUMPI` instruction, and as you may recall, it's a conditional `JUMP` that will happen only if the second element in the stack is a one. So, now we REALLY REALLY have to divide the problem into two paths.

Let's assume that the `input` is less than 0x1A. In this case, we would have a zero as a second parameter for the `JUMPI`, so the `JUMP` wouldn't be made =(

Who wants to `JUMP` anyway? That's too mainstream...

Downstream, we are pushing a one into the stack, we `POP` an old zero, and we `JUMP` ~~weeee =D~~ to the line 204 (0xCC). There, we `SWAP` a couple of times in line 205 and 206 - to `POP` the `input` that we don't need anymore - and we `JUMP` again to the line 96 (0x60).

– _What happens there?_&nbsp; We find a place in memory that's free, we save the `output` there, and we `RETURN` it. ~~And when I say "we", it's actually the code, but it's too shy to go alone.~~

Easy peasy, right? Now, let's get into the other scenario.

We are back into line 191 just before the `JUMPI`, but this time, we have a one as a secondary parameter so... yes, you guessed it: hyperspace!

 ![yep, that's a wormhole](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/1X/aee1834af5614659623fc05ec50cd529b797b0cd.jpeg)

Nevertheless, this trip is short because it leaves us at line 199 (0xC7) where we `PUSH` a 2 onto the stack (200) and `POP` a zero from it. But after that, we continue with the same path as before: We `JUMP` to line 96, and we `RETURN` the `output`.

– _What's the difference then?_&nbsp; The `output`. In the first run, we were inside the body of the `if`, but in the second run, we went into the `else` body, the default one :o

– _Wooow, so what happens then with the `assemblySwitch` function?_&nbsp; Eeeasy now. We are getting into that. The instructions that are relevant for the `assemblySwitch` function are the following:

| # | Opcode | Value | Case |
| --- | --- | --- | --- |
| 210 | PUSH1 | 00 | |
| 212 | PUSH1 | 1A | |
| 214 | DUP3 | | |
| 215 | LT | | |
| 216 | PUSH1 | 01 | |
| 218 | DUP2 | | |
| 219 | EQ | | |
| 220 | PUSH1 | E6 | |
| 222 | JUMPI | | 1---\> |
| 223 | PUSH1 | 02 | |
| 225 | SWAP2 | | |
| 226 | POP | | |
| 227 | PUSH1 | EB | |
| 229 | JUMP | | D---\> |
| 230 | JUMPDEST | | \<---1 |
| 231 | PUSH1 | 01 | |
| 233 | SWAP2 | | |
| 234 | POP | | |
| 235 | JUMPDEST | | \<---D |
| 236 | POP | | |
| 237 | SWAP2 | | |
| 238 | SWAP1 | | |
| 239 | POP | | |
| 240 | JUMP | | R---\> |

Alrighty then, I reckon you have enough strength to continue with this last step, so no more coffee breaks.

As always, we start with the `input` in the stack and we `PUSH` a 0x0 and a 0x1A in lines 210-212 to compare our `input` with the 0x1A in line 215 using an `LT` instruction. That would give us a 0x1 or a 0x0 depending on the `input` (as before).

After that, a 0x1 is `PUSH`ed to compare with the result from the `LT` (216). _Why?_&nbsp; Because this is our first case in the `switch` statement. It checks if the value - in this case the result from the `LT` - corresponds with one of the defined cases. Amazing, right?

Let's imagine that we have a value that is less than 0x1A. In this case, `LT` would return a one and after the `EQ` in line 219 we would have a 0x1 as a second parameter for the `JUMPI` that is on line 222.

What does it mean? We are jumpiiiinng.  
Where? To the line 230 (0xE6).

 ![yep, that's a wormhole](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/1X/aee1834af5614659623fc05ec50cd529b797b0cd.jpeg)

There, we start `PUSH`ing a one into the stack (231), and we `POP` away some garbage in 234, 236, and 239.

After that, we have a final `JUMP` to the part of the code that `RETURN`s the `output`.

For the other case, when the `input` is at least 0x1A, we go down another road.

The result from the `LT` in line 215 is going to be 0x0 so when it's compared to 0x1 with the `EQ` (219), the result will be 0x0, too, which means no `JUMP` in line 222.

But because we completed the comparisons of all the possible cases - a list with only one case 😛 - we end up executing the `default` one. Here we `PUSH` a 0x2 as `output`, `JUMP` to the common garbage removal, and `RETURN` the value 0x2.

## Episode IV – A New _Conclusion_

This example is trivial because we only had 2 possibilities, but the `switch` statement would allow me to list all the possible outcomes - each one of them with their respective execution code - and define a `default` case that covers all other situations.

We've learned that this statement sequentially checks all the cases, so some gas will be wasted iterating all possibilities. When none of the cases matched with the condition, we also saw that the default body execution code is the one that comes first. Compared with the `if`-`else` alternative in Solidity, the gas consumption is greater this time. This means that you shouldn't go to _full `assembly` mode_ just to save some gas; use it only when it's needed =)

On a more global view, during these last 3 days, we've learned how certain instructions like `eq`, `not`, `iszero`, `lt`, and `gt` are used and also how we can make conditional statements in `assembly` using `if`s and `switch`es.

You should be proud of yourself, but remember that [there are plenty more opcodes](https://solidity.readthedocs.io/en/latest/assembly.html#opcodes) to have fun with, so stay tuned for the next chapter, or even better, why don't you write one? We'll be very happy to include it in the [index](https://forum.openzeppelin.com/t/how-to-survive-in-the-assembly-world/1125) 😃

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [October 30, 2019, 6:15am UTC](https://forum.openzeppelin.com/t/switch-the-way-you-use-conditionals/1651/2 "2019-10-30T06:15:48Z")

</div>

Hi @andresbach,  
Star Trek, Star Wars and potentially Stargate SG-1, plus assembly. 🚀

Will need to reread slowly with more caffeine to spot all the references and let the assembly sink in.

---

<div class="post-metadata">

**Author:** ![andresbach](https://avatars.discourse-cdn.com/v4/letter/a/839c29/32.png) [@andresbach](https://forum.openzeppelin.com/u/andresbach)\
**Post date:** [October 30, 2019, 1:55pm UTC](https://forum.openzeppelin.com/t/switch-the-way-you-use-conditionals/1651/3 "2019-10-30T13:55:37Z")

</div>

" … plus assembly." Haha 😂

Glad you liked it @abcoathup!  
Let’s see if you can find the theme of the next article 😆
