1

I think i've figured out dynamic memory layout for dynamic arrays, but could use a check on my reasoning. Consider the contract :

pragma solidity >=0.8.4;

    struct state_type {
        bytes   b;
        uint256 x_index;
        uint256 x;
    }

    
contract SolidtyStructLayout {
    event EmitVal(bytes32 v);

    function writeStruct() public returns(uint256 x_ind, uint256 x_val, bytes memory b) {

        state_type memory local_var;
        local_var.x_index = 8;
        local_var.x = 9;
        local_var.b = new bytes(0x20 * 3);

        bytes32 v;
        
        assembly{
                v := mload(local_var)
                 mstore(
                      add(mload(local_var), 0x20),1
                    )
                    mstore(
                      add(mload(local_var), add(0x20, 0x20)), 2
                    )
                    mstore(
                      add(mload(local_var), add(0x20, 0x40)), 3)
                }
        emit EmitVal(v);                
        return(local_var.x_index , local_var.x , local_var.b);
    }
}

The memory layout on execution is

{
    "0x0": "0000000000000000000000000000000000000000000000000000000000000000\t????????????????????????????????",
    "0x20": "0000000000000000000000000000000000000000000000000000000000000000\t????????????????????????????????",
    "0x40": "0000000000000000000000000000000000000000000000000000000000000160\t????????????????????????????????",
    "0x60": "0000000000000000000000000000000000000000000000000000000000000000\t????????????????????????????????",
    "0x80": "00000000000000000000000000000000000000000000000000000000000000e0\t????????????????????????????????",
    "0xa0": "0000000000000000000000000000000000000000000000000000000000000008\t????????????????????????????????",
    "0xc0": "0000000000000000000000000000000000000000000000000000000000000009\t???????????????????????????????\t",
    "0xe0": "0000000000000000000000000000000000000000000000000000000000000060\t????????????????????????????????",
    "0x100": "0000000000000000000000000000000000000000000000000000000000000001\t????????????????????????????????",
    "0x120": "0000000000000000000000000000000000000000000000000000000000000002\t????????????????????????????????",
    "0x140": "0000000000000000000000000000000000000000000000000000000000000003\t????????????????????????????????",
    "0x160": "0000000000000000000000000000000000000000000000000000000000000008\t????????????????????????????????",
    "0x180": "0000000000000000000000000000000000000000000000000000000000000009\t???????????????????????????????\t",
    "0x1a0": "0000000000000000000000000000000000000000000000000000000000000060\t????????????????????????????????",
    "0x1c0": "0000000000000000000000000000000000000000000000000000000000000060\t????????????????????????????????",
    "0x1e0": "0000000000000000000000000000000000000000000000000000000000000001\t????????????????????????????????",
    "0x200": "0000000000000000000000000000000000000000000000000000000000000002\t????????????????????????????????",
    "0x220": "0000000000000000000000000000000000000000000000000000000000000003\t????????????????????????????????",
    "0x240": "0000000000000000000000000000000000000000000000000000000000000000\t????????????????????????????????"
}

The emit event points to address e0 as where structure begins. I was expecting the bytes array would be stored at a different location something what is done in storage. #

Due to their unpredictable size, mappings and dynamically-sized array types cannot be stored “in between” the state variables preceding and following them. Instead, they are considered to occupy only 32 bytes with regards to the rules above and the elements they contain are stored starting at a different storage slot that is computed using a Keccak-256 hash.

Is it a fair assessment that dynamic arrays (part of structs) in memory are stored in-place, i.e. length followed by elements when packed with structs?

1
  • I'm curious if some of the behavior you are observing might come from solidity treating a bytes variable different than a dynamic array of say uint256. I think sometimes, the bytes type can work a little differently than other dynamic array types. I would be curious to see what happens if you try this with a uint array or something. I've also seen some sources online that say dynamic arrays in memory in solidity are not supported, but those might be outdated.
    – Bruce
    May 23, 2023 at 19:18

1 Answer 1

0

I believe it's always the case.

There's a difference with storage dynamic variables. You can change the length of storage variables but not memory ones. For example array.push(element) works only if array is storage, not memory.

So, since memory variables are fixed in length you can place the elements the way you described without encountering any issues (i.e. overlapping with other variables).

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.