# Stack, Memory and Storage

By [Bytecode Tuesday](https://paragraph.com/@bytecodetuesday) · 2025-05-20

ethereum, bytecode, evm

---

We reject abstraction  
We believe in bytecode  
Bytecode is only true form  
Let’s code with bytes now

  
Welcome back to Bytecode Tuesday. [Last week](https://paragraph.com/@bytecodetuesday/3-the-ethereum-bytecode-lifecyle), we saw how your contract gets compiled, deployed, and executed on Ethereum. This week, we cover something even more fundamental: the three data regions of the EVM.

Let’s recall them from the last post:

*   Stack for last-in, first-out temporary values,
    
*   Memory for intra-transaction data (a byte array that resets every call), and
    
*   Storage slots for persistent state (a mapping of 32-byte keys to 32-byte values).
    

Now let’s break each one down

The Stack: Last-In, First-Out
-----------------------------

Think of the stack like a pile of plates. You can only work with the top one. It’s:

*   Last-In, First-Out (LIFO)
    
*   Can hold up to 1024 items (each 32 bytes)
    
*   Super fast and cheap to use
    

Some Relevant Instructions:
---------------------------

    PUSH1 VALUE → put VALUE on the stack
    Bytecode: 60VALUE // Replace VALUE with your desire value in hexadecimal (1 byte)
    PUSH32 VALUE → put VALUE on the stack
    Bytecode: 7FVALUE // Replace VALUE with your desired value in hexadecimal (32 bytes)
    ADD → pop the top two values, add them, and push the result
    Bytecode: 01

Example:

Which translates as

    PUSH1 0x02
    PUSH1 0x03
    ADD

Let’s now see how the stack is being manipulated in the following step by step animation.

![](https://storage.googleapis.com/papyrus_images/d30500066e305d26b6b6d35b2767f224.gif)

_Step by step animation of our Stack manipulation example_

Memory: The Scratchpad
----------------------

Memory is like RAM: it’s cleared after each transaction or call. You can use it to:

*   Store temporary values during execution
    
*   Return data to the caller (via RETURN)
    
*   Store arrays, strings, etc.
    

Some Relevant Instructions

    MSTORE → store 32 bytes at a memory offset
    Bytecode: 52
    MLOAD → read 32 bytes from memory
    Bytecode: 51

Example:

Which translates as:

    PUSH1 0x2A        // Value to store
    PUSH1 0x00        // Memory offset
    MSTORE             // Save 0x2A at offset 0x00, since MSTORE stores 32 bytes and we just push 1 byte (0x2A), the EVM left-pads the 1-byte value with 31 zero bytes to make it 32 bytes. This padded value is then stored at the specified memory offset (in this case 0x00).
    PUSH1 0x20        // Length to return
    PUSH1 0x00        // Start offset
    RETURN              // Return memory [0x000….2A]

In the following animation notice how the memory operates based on stack inputs.

![](https://storage.googleapis.com/papyrus_images/fb31e13dfed9cbfb5032540430a7387a.gif)

_Memory is byte-addressable, but MSTORE and MLOAD operate in 32-byte chunks._

Storage: The Blockchain's Hard Drive
------------------------------------

Each smart contract has its own storage, which is:

*   Persistent: Survives across transactions
    
*   Expensive: Writing to storage costs significant gas.
    
*   Private to the contract: One contract cannot directly access another’s storage.
    

The EVM storage maps data using 32-byte (256 bits) keys and values.

So, the storage can be visualized as a map like:

    0x0000000000000000000000000000000000000000000000000000000000000000 → 0x... (32 bytes)
    0x0000000000000000000000000000000000000000000000000000000000000001 → 0x... (32 bytes)

Why 32 Bytes?
-------------

Ethereum uses 32 bytes words as the native unit for storage and computation. This design aligns naturally with the Keccak-256 hashing, which produces 32 bytes outputs. Since Ethereum relies heavily on this algorithm, for addresses, storage keys, and more, structuring everything around 32-byte chunks makes contract development efficient.

However, this design isn’t without tradeoffs. Storing small values, like a boolean or a single digit, still consumes the full 32 bytes, which means wasted space and higher gas costs. Developers often have to pack and unpack multiple values manually to use storage efficiently, adding complexity on both smart contracts and dApps frontends.

The EVM's 32-byte word size made sense for early Ethereum, especially given its focus on DeFi, tokens, and ownership primitives. But as the platform evolves into a general purpose execution layer, the limitations of this native word size become more apparent. There’s growing interest, [including from Vitalik himself](https://ethereum-magicians.org/t/long-term-l1-execution-layer-proposal-replace-the-evm-with-risc-v/23617/33), in exploring a more flexible, byte oriented virtual machine that better supports new use cases and broader types of applications.

Some Relevant Instructions:

    SSTORE → write value to a storage slot
    Bytecode: 55
    SLOAD → read from a storage slot
    Bytecode: 54

Example:

Which translates as:

    PUSH1 0x2A       // value
    PUSH1 0x00       // storage key
    SSTORE             // storage[0x000…00] = 0x2A, since SSTORE uses a 32-byte key and value, the EVM left-pads the 1-byte value with 31 zero bytes to make it 32 bytes in the same way as 
    PUSH1 0x00       // key
    SLOAD               // load from storage[0x000...00], as SSTORE, it left-pads the 1-byte key with 31 zero bytes

As you can see, the memory and the state operate very similarly, the main difference is the memory is addressed by byte pointers while the state by 32 byte slots.

![](https://storage.googleapis.com/papyrus_images/f64888ecb297b5a62a6d1b7eb5a65439.gif)

_Unlike memory, storage persists after execution and is committed to Ethereum’s global state (in the Merkle Patricia Trie)._

Stack vs Memory vs Storage  

-----------------------------

Feature

Stack

Memory

Storage

Lifetime

One instruction

One transaction

Forever

Cost

Very cheap

Medium

Expensive

Access

Only top values

Offset-based

Key-value

Use cases

Math & logic

Return values

Contract state

Hands-on Assignment
-------------------

Write and check using this [EVM Disassembler](https://evmdisassembler-cooldev1337.pages.dev/) bytecode that:

1.  Stores the number 42 in memory
    
2.  Loads it back from memory
    
3.  Returns it
    

Bonus: Can you also store it in storage, then load and return it?

Bytecode isn’t magic. It’s just a sequence of stack gymnastics mixed with clever use of memory and storage.

Next week on Bytecode Tuesday, we’ll explore control flow, how to change the flow of execution inside a smart contract. Subscribe now for more weekly bytes and opcodes.

---

*Originally published on [Bytecode Tuesday](https://paragraph.com/@bytecodetuesday/4-stack-memory-and-storage)*
