4

For Example:

I am trying a sample contract where i want to pass nested array values.

But i cant able to find the suitable solution ?

Is it possible or do i have to change the way to send the data ?

Thanks

  • In the Solidity world there should not be any issue with making a nested dynamic array. – Daniel Sep 13 '18 at 1:19
6

TL;DR

You will have to find an alternative for now if you're making the calls externally as they haven't implemented nested arrays interactions with the call data yet, but it is available in memory/storage implementations.

Internal Nested Uses

What this basically means is you can use nested array when they either:

Have a storage implementation

pragma solidity ^0.4.0;

contract NestedArrays {
    uint[][] private nested;
    function test() public {}
}

Or a memory implementation

pragma solidity ^0.4.0;

contract NestedArrays {
    function test() public {
        uint[][] memory nested;
    }
}

External Failed Nested Uses

If you try to use it as part of the call data such as:

As function params

pragma solidity ^0.4.0;

contract NestedArrays {
    function test(uint[][] nested) public {
    }
}

Will result in the error:

UnimplementedFeatureError: Nested arrays not yet implemented.

Or as a return statement

pragma solidity ^0.4.0;

contract NestedArrays {
    function test() public returns (uint[][] nested) {
    }
}

Will result in the error:

UnimplementedFeatureError: Nested dynamic arrays not implemented here.

Alternative Nested Implementation

This feature may come in later iterations of Solidity, but for now it's not directly possible. What you can do is pass the data as bytes and extract the array data e.g.

pragma solidity ^0.4.0;

contract AssemblyArray {

    function getFirstArray(bytes _array) 
        public
        returns (uint[]) {
        assembly {
            // First available block of memory
            let ptr := msize()
            // Size of the first array
            let size := mload(add(_array, 0x40)) 
            // Initial offset (3 bytes)
            let offset := 0x60
            // Iterator index
            let idx := 0

            // Data Size of uint which is 32 bytes
            mstore(ptr, 0x20)
             // Array Size
            mstore(add(ptr,0x20), size)

            // Skip to the end if the array is empty
            jumpi(_ret, eq(0, size))

            _add:
            // Add the value from the bytes array to our new array
            mstore(add(ptr,add(0x40,mul(0x20,idx))), mload(add(offset, mul(0x20, idx))) )

            // Increment the index
            idx := add(idx, 1)
            // Jump back to add if we still have more elements
            jumpi(_add, lt(idx, size))

            _ret:
            return(ptr, mul(add(size, 2), 0x20))
        }    
    }
}

The example above is more pseudo code which extracts the first array from a nested array and probably needs correcting. This example only works for 32 byte values.

This would simply extract an array from a nested array which is stored in bytes and you would need to loop the mstore to get all the values though.

Here's a rough overview of how the arrays are stored in our bytes:

--------------------------------------------------------------------------------------
|   Length of    |    Data Type   |   Length of    |     Element    |     Element    |
|  total bytes   |      Size      |  first array   |       n1       |        n2      |
--------------------------------------------------------------------------------------
|    32 bytes    |     32 bytes   |    32 bytes    |    32 bytes    |    32 bytes    | 
--------------------------------------------------------------------------------------
|      0x80      |       0x20     |       0x40     |       0x01     |      0x02      |
--------------------------------------------------------------------------------------

In simple if this is too complicated I would consider trying alternatives or ask do you really need to pass nested arrays.

Internal Nested Continued

I forgot to mention that you can pass nested arrays internally as they don't involve the calldata e.g.

pragma solidity ^0.4.0;

contract NestedArrays {

    function passNested(uint[][] nested) internal {
        // ...
    }

    function returnNested() internal returns (uint[][]) {
        // ...
    }
}

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.