2

For example, given the following cases:

uint[3] memory arr;
uint[] memory arr = new uint[](3);

Suppose I try to access arr from within an assembly block (using mload, for example).

Where (relatively to arr) is the value of arr.length located, and where are the entries located?

Thank you!

2 Answers 2

4

OK, I ran a simple test and found out that in a dynamic array, the length of the array is located at the first 32 bytes relatively to the beginning of the array:

Smart Contract:

pragma solidity 0.4.25;

contract MyContract {
    function read1() external pure returns (uint a, uint b, uint c) {
        uint[3] memory arr;
        arr[0] = 111;
        arr[1] = 222;
        arr[2] = 333;
        assembly {
            a := mload(add(arr,  0))
            b := mload(add(arr, 32))
            c := mload(add(arr, 64))
        }
    }

    function read2() external pure returns (uint a, uint b, uint c) {
        uint[] memory arr = new uint[](3);
        arr[0] = 444;
        arr[1] = 555;
        arr[2] = 666;
        assembly {
            a := mload(add(arr,  0))
            b := mload(add(arr, 32))
            c := mload(add(arr, 64))
        }
    }
}

Truffle Test:

contract("MyContract", function(accounts) {
    it("test", async function() {
        const myContract = await artifacts.require("MyContract").new();
        await test(myContract.read1);
        await test(myContract.read2);
    });
    async function test(func) {
        const [a, b, c] = await func();
        console.log(a.toFixed(), b.toFixed(), c.toFixed());
    }
});

Printout:

111 222 333 (this is for the `uint[3] memory arr`)
3 444 555   (this is for the `uint[] memory arr = new uint[](3)`)
2
  • Yup. I've never found this documented anywhere, but this has been my experience too.
    – user19510
    Jun 25, 2019 at 19:29
  • 2
    Documented at for example solidity.readthedocs.io/en/v0.5.3/… "For dynamic arrays, this slot stores the number of elements in the array" EDIT: ok the link is about variables in storage and this question is about memory... Anyone can "Edit on Github" to improve the docs
    – eth
    Jun 25, 2019 at 23:14
0

Dynamically-Sized Arrays

Dynamically-sized array arr is at slot 0, and here is stored the size of arr. Values are stored starting at the hash of the slot (0 in this case).

Fixed-Sized Arrays

Fixed-sized array arr2 is stored at slots 1 and 2, because the length of the array is 2 (predefined). One slot for each element.

Fixed-sized array arr3 is located in memory, works similar to arr2.

Fixed-sized array arr4 is located in memory but the behaviour is similar to arr. If you pass 0 as a parameter of the function getFixMemoryArrayElement_2() you will get the length or arr4.

You can use the following code to test in Remix:

pragma solidity ^0.5.0;

contract Array {

    uint[] arr;   // Storage at slot 0
    uint[2] arr2; // Storage at slot 1 and 2

// Dynamic Array Storage

    // Dynamic Array Storage
    function setDynArrayElement() public {
        arr.push(2);
        arr.push(3);
        arr.push(4);
    }

    // Dynamic Array Length
    function getDynArrayLength() public view returns (uint _l) {
        assembly {
            _l := sload(0)
        }
    }

    // Dynamic Array Element
    function getDynElement(uint i) public view returns (uint _x) {
        assembly {
            _x := sload(add(keccak256(sload(0), 32),i))
        }
    }

// Fixed Array Storage

    // Fixed Array Storage
    function setFixnArrayElement() public {
        arr2[0]= 5;
        arr2[1]= 6;
    }

    // Fixed Array Element
    function getFixElement() public view returns (uint _value1, uint _value2) {
        assembly {
            _value1 := sload(1)
            _value2 := sload(2)
        }
    }

// Fixed Array Memory

    // Fixed Array Memory
    function getFixMemoryArrayElement(uint i) public pure returns (uint _l) {
        uint[2] memory arr3;
        arr3[0] = 7;
        arr3[1] = 8;
        assembly {
            _l := mload(add(arr3,mul(i,0x20)))
        }
    }

    function getFixMemoryArrayLen() public pure returns (uint _l) {
        uint[] memory arr4 = new uint[](10);
        assembly {
            _l := mload(arr4)
        }
    }
    function getFixMemoryArrayElement_2(uint i) public pure returns (uint _l) {
        uint[] memory arr4 = new uint[](5);
        arr4[0] = 9;
        arr4[1] = 10;
        assembly {
            _l := mload(add(arr4,mul(i,0x20)))
        }
    }
}
6
  • I think you're answering as though the arrays are in storage, but they're in memory.
    – user19510
    Jun 25, 2019 at 19:28
  • @smarx Are you saying for arrand arr2? They are not located in storage?
    – alberto
    Jun 25, 2019 at 20:21
  • Yes, in your code, arr and arr2 are located in storage. But the original question was about memory.
    – user19510
    Jun 25, 2019 at 20:50
  • @smarx Oh yes, that's because the question was edited while I was sending the answer.
    – alberto
    Jun 25, 2019 at 20:51
  • Ah! That explains it. :-)
    – user19510
    Jun 25, 2019 at 20:54

Your Answer

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

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