✅Memory

Layout in Memory - Solidity doc

Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows:

  • 0x00 - 0x3f (64 bytes): scratch space for hashing methods

  • 0x40 - 0x5f (32 bytes): currently allocated memory size (aka. free memory pointer)

  • 0x60 - 0x7f (32 bytes): zero slot

I made a diagram for easier memorization:

memory layout

Scratch space can be used between statements (i.e. within inline assembly). The zero slot is used as initial value for dynamic memory arrays and should never be written to (the free memory pointer points to 0x80 initially).

Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future).

bytes/string is made of two parts:

  1. The first 32 bytes is the length of that bytes/string

  2. The actual value starts from the 33th byte

This fact was used in Ethernaut MagicNumber:

contract MagicNumberHack {
    constructor(MagicNum challenge) {
        // len(bytecode) = 19 = 0x13
        bytes memory bytecode = hex"69602a60005260206000f3600052600a6016f3";
        
        address addr;
        assembly {
            // create(value, offset, size)
            addr := create(0, add(bytecode, 0x20), 0x13)
        }
        
        // Verify if the contract was successfully deployed
        require(addr != address(0));

        // Interact with the challenge contract
        challenge.setSolver(addr);
    }
}

Here we used add(bytecode, 0x20) to get the actual value of bytecode since the first slot is its length and its actual value is in the second slot.

Last updated

Was this helpful?