3

In this doc :

https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

Given this representation of the contract

contract Foo {
  function bar(fixed[2] xy) {}
  function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; }
  function sam(bytes name, bool z, uint[] data) {}
}

it is said that If we wanted to call the method sam with the arguments "dave", true and [1,2,3] it would be broken down into :

0x0000000000000000000000000000000000000000000000000000000000000060: the location of the data part of the first parameter (dynamic type), measured in bytes from the start of the arguments block. In this case, 0x60.

What does that mean ?

I can't wrap my head around this concept nor the way it's ordered (methodid,datalocationparam1,hexparm2,datalocationparam3,hexparam3,hexparam1,datalocationparam3,entry1,entry2,entry3),or what an "entry" is.

3
  • I struggled mightily with this exact issue. I don't know if there's a better solution, but I can tell you that if you pick apart the page you've referenced above, what you're looking for is in there. It took me a couple of days, but I was able to ultimately figure it out using what's there. It's not at all clearly written, though. Dec 8, 2016 at 19:49
  • did you ever figured out to ordering ? (methodid,datalocationparam1,hexparm2,datalocationparam3,hexparam3,hexparam1,datalocationparam3,hex3-1,hex3-2,hex3-3)
    – solinooby
    Dec 11, 2016 at 23:01
  • I did. There's a GitHub repository called "ethslurp" that does this, but it's kind of hacky. In a file called transaction.cpp. In a function called parseParams. The function takes the input string and a list of parameter types and returns and returns the parameters in a pipe separated string. It's hacky, but it works. Dec 11, 2016 at 23:33

2 Answers 2

0

Very late to the party here, but my understanding is this:

First part of the data:

  1. MethodID (4 bytes / 8 hex characters)
  2. location_of_dynamic_parameter_1 (32 bytes / 64 character)
  3. binary_parameter (32 bytes / 64 characters)
  4. location_of_dynamic_parameter_3 (32 bytes / 64 characters)

The location of dynamic parameters is the hex value of the number of bytes after the method id.

In this case the first dynamic parameter is immediately after the data above. So 32 bytes + 32 bytes + 32 bytes = 96 bytes which when we convert to hex is 0x60

The dynamic parameters start with 32 bytes to describe the length. This is 4 for bytes because there are 4 bytes in "dave".

After this is the actual content of the first dynamic parameter. For "dave" this turns into the UTF-8/ASCII encoding padded right to 32 bytes.

Next is the start of the 3rd dynamic parameter. The location of this is: 32 Bytes (P1 location) + 32 Bytes (Bool) + 32 Bytes (P3 location) + 32 Bytes (P1 Length) + 32 Bytes (P1 Content) = 160 Bytes (A0 in hex).

Again for the dynamic parameters they start with the length, for a uint256[] this is how many items are in the array. In this case they are saying 3 items in the array.

And finally is 3x 32 bytes for each of the items in that array

0

Here's a much more simpler example to understand it:

Note: A single hex digit equals 4 bits and so a single byte equals 2 hex characters.

0xF = 1111 = Half a byte

0xFF = 11111111 = A single byte

32 bytes = 64 characters long in hexadecimal.

function bbfn(bytes memory xx) public view {
        console.logBytes(msg.data);
}

Calling bbfn() with 0xFFFFFFFF as input.

Output:

0x9e95799300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004ffffffff00000000000000000000000000000000000000000000000000000000


Splitting the output:

0x9e957993 - Method ID

0000000000000000000000000000000000000000000000000000000000000020 - Data location of first para
0000000000000000000000000000000000000000000000000000000000000004 - Size of first para
FFFFFFFf00000000000000000000000000000000000000000000000000000000 - First para

0x20 is 32.

Consider the end of 0x20 as the starting offset and from there 32 bytes gives use the value 0xFFFFFFFF.

See the second example and you'll understand more.


Same but with two para:

function bbfn(bytes memory xx, bytes memory yy) public view {
        console.logBytes(msg.data);
}

Input: 0xffffffff, 0xffffffff

Output:

0xd04dec87000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004ffffffff00000000000000000000000000000000000000000000000000000000

Splitting:

0xd04dec87 - Method ID
0000000000000000000000000000000000000000000000000000000000000040 - Data location of first para
0000000000000000000000000000000000000000000000000000000000000080 - Data location of second para
0000000000000000000000000000000000000000000000000000000000000004 - Size of first para
ffffffff00000000000000000000000000000000000000000000000000000000 - First para
0000000000000000000000000000000000000000000000000000000000000004 - Size of second para
ffffffff00000000000000000000000000000000000000000000000000000000 - Second para

0x40 is 64 0x80 is 128

From the end of 0x40 as the starting offset jumpping 64 bytes gives use the value 0xFFFFFFFF

0000000000000000000000000000000000000000000000000000000000000040 - Start from this end and jump 64 bytes.
0000000000000000000000000000000000000000000000000000000000000080 - 32 bytes
0000000000000000000000000000000000000000000000000000000000000004 - 32 bytes
ffffffff00000000000000000000000000000000000000000000000000000000

Which now equals 64 bytes and we are at the first para value.

Now let's go with the second value.

The second value is stored at 0x80 meaning 128 bytes from this offset.

0000000000000000000000000000000000000000000000000000000000000080 - 128 bytes from here.
0000000000000000000000000000000000000000000000000000000000000004 - 32 bytes
ffffffff00000000000000000000000000000000000000000000000000000000 - 32 bytes
0000000000000000000000000000000000000000000000000000000000000004 - 32 bytes
ffffffff00000000000000000000000000000000000000000000000000000000

Which equals 32+32+32 128 bytes and we get our second para value.

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.