From the docs:

mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))


library GetCode {
    function at(address _addr) public view returns (bytes memory o_code) {
        assembly {
            // retrieve the size of the code, this needs assembly
            let size := extcodesize(_addr)
            // allocate output byte array - this could also be done without assembly
            // by using o_code = new bytes(size)
            o_code := mload(0x40)
            // new "memory end" including padding
            mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            // ...

I can follow the operators and parse the hexadecimal, however I'm not sure if I should be performing these on underlying values or the memory address values themselves (eg. 0x20 + 0x40 = 0x60).


It explained a little later in the same documentation:

Solidity manages memory in a very simple way: There is a “free memory pointer” at position 0x40 in memory. If you want to allocate memory, just use the memory starting from where this pointer points at and update it accordingly.

An array always use the first slot to store its length and it always aligned to 32 bytes (one slot).

In pseudo code it does something like this:

  • Read free memory pointer

    array_memory = memory[0x40]
  • Calculate array size in memory, add an extra 32 bytes for the array length and round it to 32 bytes. The mathematical formula is trunc((code_size + 32 + 32 - 1) / 32) * 32. And optimized to EVM assembly it is

    array_size = (code_size + 0x20 + 0x1f) & ~0x1f
  • Update free memory pointer

    memory[0x40] += array_size
  • Thank you. The formula you included is a very elegant means of explanation. My obstacles are conceptually mapping the logical bitwise operators to the formula. (Are the operands aligned, added, converted to binary and compared bit by bit to ~0x1f (binary)? Further, what is the role of ~0x1f.) May 20 '19 at 18:58
  • Search for bit mask, for example en.wikipedia.org/wiki/Mask_(computing). For example 3 has all "lower" bits set to 1 (00011), the negation ~3 will flip those bytes to 0 (11100). Now masking (x & ~3) will set the lower bits of x to 0.
    – Ismael
    May 20 '19 at 19:11
  • Now I've got it. Appreciate your time May 20 '19 at 19:16
  • Note that @Ismael's mathematical formula assumes that division rounds down to the nearest integer. This is the case in Solidity. E.g. 48 divided by 32 is 1, not 1.5 Aug 31 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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