1

I am digging into memory and the free memory pointer in solidity.

I have been wondering what the maximum size of memory in a single execution of a function in solidity?

As I know, when memory is used, the free memory pointer address is automatically updated at 0x40. I am very curious of what the end of the free memory pointer address will be ?

I tried to figure it out on the remix ide, just like below, but I often got out of gas.

  assembly {
        mstore(0x40, 0xFFFFFF)
    }

It seems I can set the memory pointer onto the maximum number of 32bytes

like this
mstore(0x40, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

So does it mean by that the maximum size of memory is 32 bytes??

If anybody knows, please let me know it and the reason why?

2 Answers 2

3

I just want to extend the answer about theoretical memory size (32-byte address, 2^256 bytes because it's byte-addressable). In reality, if you look at the entire blockchain, it has several limits:

  1. it's bounded by the implementation of the client.
  2. it's bounded by the block gas limit.

For 1., the official Go Ethereum implementation uses Uint64 for memory size, so the memory size is bounded by 2^64 bytes: Go Ethereum Mstore implementation For 2., it's the real limit that you will hit much sooner before the 1. comes, and it's blockchain-dependent and function-type dependent.

For example, the Ethereum blockchain now has ~30M gas (Jan 2023). In practice, the transaction can only spend less than that. So with the approximate equation (X/32)^2/512 + 3X/32 = 30M you found X is approximately a bit higher 0x3C0000. It's the real limit for the current Ethereum blockchain. For BSC, it's higher (~140M Block gas limit).

Function to test gas limit :

contract Test{
    function test()public {
        assembly {
            mstore(0x40, 0x3C0000)
        }
        // The above mstore doesn't cost much gas but it affects the subsequent mstore and mem alloc (the free mem pointer)
        string memory dummy = "test";
        // MSTORE for dummy will extend mem and spend nearly 30M gas.
    }
}

Another concern is the view function when using eth_call directly, as far as I know there is no official upper limit gas spent by eth_call and hence your function may hit the client gas limit in 1.. Unofficially the client or RPC provider will have their own limit on that (e.g. 550M on alchemy). Different clients may have different implementations on this.

2

Yes, memory is 32 bytes in size.

However you didn't prove anything by doing mstore(0x40, 0xFF..FF), because you're just storing a number (0xFF..FF) into memory at position 0x40.

What's important is what happens the next time solidity will try writing to memory (2 steps):

  1. it will read the value from 0x40 (so it will read 0xFF..FF);
  2. it will do mstore(0xFF..FF, new_number).

(there's also a third step where it will update the value at 0x40)

It's this last mstore that, during execution, will trigger the EVM to expand the memory to 0xFF..FF, causing a very high gas cost (docs for math).

So, theoretically max size is 32 bytes, but practically much lower.

The special meaning of 0x40 is something specific of solidity and not the EVM, so it doesn't matter what you write there as long as solidity doesn't try to use it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.