2

I'm passing some arguments to a function and abi.encode()-ing them. Then I pass this data to another function where I abi.decode() it, but Im not entirely sure how to do it:

Arguments I'm encoding:

uint256    quantity
uint8      addresses_array_length
address[]  addresses_array
address[]  addresses_array2
// addresses_array2.length = addresses_array.length - 1, always

I then pass this data and I'd like to decode it in exactly the same format (i.e. uint256, uint8, address[] and address[]).

How should I do this?

From what I read I should do something like:

assembly { //is it necessary to do all this within this assembly struct?
    quantity := mload(add(data, 32))
    addresses_array_length := mload(add(data, 1))
    // Now how should I do for the arrays?
  }

Thanks

Hiperfly
  • 459
  • 4
  • 11
  • I ran into a similar problem a while back trying to encode/decode dynamic arrays. I would suggest to only use fixed-size arrays for that. – Ahmed Ihsan Tawfeeq Jun 10 '21 at 06:13
  • Thanks for your input. I've been reading a bit more (https://docs.soliditylang.org/en/v0.5.4/assembly.html) and apparently it should be possible to pass dynamic arrays since the first 32bytes of data for the data regarding the array, represents the length, so I might not even need the variable addresses_array_length, but still not sure how to continue. – Hiperfly Jun 10 '21 at 07:56
  • @Hiperfly What if abi.decode isn t used for variable length array but is instead used as arguments for functions in someone s else implementation? https://ethereum.stackexchange.com/q/159866 – user2284570 Feb 16 '24 at 11:39

2 Answers2

6

I'm not sure what are you trying to achieve but if you are using abi.encode then you can use abi.decode.

// SPDX-License-Identifier: MIT

pragma solidity 0.8.4;

contract A {

function foo() public {
    uint256 a = 1;
    uint8 b = 2;
    address[] memory c = new address[](3);
    address[] memory d = new address[](2);

    c[0] = msg.sender;
    d[1] = msg.sender;

    bytes memory x = abi.encode(a, b, c, d);
    bar(x);
}


function bar(bytes memory data) public view {
    (uint256 x, uint8 y, address[] memory z, address[] memory w) = abi.decode(data, (uint256, uint8, address[], address[]));

    require(z[0] == msg.sender, "First array");
    require(w[1] == msg.sender, "Second array");

}

}

Ismael
  • 30,570
  • 21
  • 53
  • 96
2

I also got in trouble for this issue. After I followed Ismael's answer, it works. Thanks very much. I also tried to use js to encode array data and decode in solidity. It works.

const Web3 = require('web3')

const web3 = new Web3();

let array = ['0x50c439b6d602297252505a6799d84ea5928bcfb6', '0x8b9f9f4aa70b1b0d586be8adfb19c1ac38e05e9a', '0x6e11655d6ab3781c6613db8cb1bc3dee9a7e111f']; let userData = web3.eth.abi.encodeParameters( ['address[]'], [array] );

console.log(userData);

Gabriel
  • 21
  • 1