Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encodeData doesn't support array types #4

Open
rmw2 opened this issue Feb 4, 2019 · 4 comments
Open

encodeData doesn't support array types #4

rmw2 opened this issue Feb 4, 2019 · 4 comments

Comments

@rmw2
Copy link
Contributor

rmw2 commented Feb 4, 2019

Currently a placeholder error is thrown when abi encoding an array type. This should be replaced with a genuine implementation of the ABI encoding for arrays

@alko89
Copy link

alko89 commented Mar 22, 2019

I'm just trying to figure this out. In EIP712 specification it is stated: The array values are encoded as the keccak256 hash of the concatenated encodeData of their contents (i.e. the encoding of SomeType[5] is identical to that of a struct containing five members of type SomeType). From this I figure it should be something like:

  if (field.type == 'array') {
    for (let v of value) {
      encTypes.push('bytes32');
      value = ethUtil.keccak256(encodeData(field.items.type, v))
      encValues.push(value);
    }
  }

@BrendanChou
Copy link

@alko89 That only applies for fixed-length arrays, not for arrays of arbitrary length.

In that case, the encoded hash of the array would be a single bytes32 that is just the keccak256 of: the encoded values of each element in the array in 32-byte chunks

@dstarke
Copy link

dstarke commented Mar 31, 2020

I have created a pull request where you can see an implementation that addresses this issue. To answer the question above, I will point out that:

  • encodeData(), which in this library always operates in the context of a struct, encodes each of the fields in the struct and returns the concatenation of the results.
  • The encoding for a field that is a struct is the hash of the encodeData() for the struct.
  • The encoding for a field that is an array is the hash of the concatenation of the field encodings of each element of the array.

So: encodeData() for a field in a struct does the same thing as the field encoding for an array: take the hash of the concatenation of the field encodings of each sub-element.

Some examples:

  • For an array of atomic types, the array encoding will be the hash of the concatenation of the raw encoding of each element.
  • For an array of structs, the array encoding will be the hash of the concatenation of the encoding of each element, and since the elements are structs, the encoding of each element is a hash of the concatenation of the encodings of each of the members of the struct.

Since there are no good Solidity examples of this out there either, I'll point out that implementing this in Solidity is pretty straightforward: construct an array arr of all of the encodings of the elements, and then the struct hash of the array is keccak256(abi.encodePacked(arr)).

@dstarke
Copy link

dstarke commented Mar 31, 2020

One other note, since the spec is worded somewhat confusingly and is structured slightly differently than the code here. The encodeData() for a struct, as implemented here, includes the type hash. The encoding for an array field does not include a type hash.

In the spec, the inclusion of the type hash is part of the definition of hashStruct() rather than encodeData(). The end result is the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants