4

So function data input has a limit of 32 bytes. How exactly do the internals of the EVM work when you pass in a string arg that exceeds this limit? Does it pass a pointer to some value in memory instead? If so, how is it possible to retrospectively look at the value of that string for a previous transaction?

1 Answer 1

3

So function data input has a limit of 32 bytes.

That's not true, an EVM word has a length of 32 bytes, but you can use several words to fit more data if you are using a dynamic type that requires more than 32 bytes.

How exactly do the internals of the EVM work when you pass in a string arg that exceeds this limit?

Strings are dynamic-sized byte array so just a type of array. As every parameter they need to be abi encoded. So let's take an example string :

"This string is more than 32 bytes long" which is actually 38 bytes long.

If we abi encode it:

import Web3 from "web3";

const web3 = new Web3();

console.log(
  web3.eth.abi.encodeParameter(
    "string",
    "This string is more than 32 bytes long"
  )
);

We get : 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000265468697320737472696e67206973206d6f7265207468616e203332206279746573206c6f6e670000000000000000000000000000000000000000000000000000

The EVM works on 32 bytes words, so if we break it up :

  • word 1 [0x00]: 0x0000000000000000000000000000000000000000000000000000000000000020
  • word 2 [0x20]: 0x0000000000000000000000000000000000000000000000000000000000000026
  • word 3 [0x40]: 0x5468697320737472696e67206973206d6f7265207468616e2033322062797465
  • word 4 [0x60]: 0x73206c6f6e670000000000000000000000000000000000000000000000000000

Where word 1 is the offset of the array in the encoding (0x20 is the offset of word 2 which is the start of our data), Word 2 is the length of the array (0x26 is 38, the length of our string) and word 3 and 4 are our actual data.

Converting word 3 to ascii : "This string is more than 32 byte"

Converting word 4 to ascii : "s long"

So as you can see, if the array requires more than 1 word of data, another word is used. This repeats until all the data is contained. All starting offset and lengths are also encoded in the first words of the encoding (word 1 and 2 in this example).

Does it pass a pointer to some value in memory instead?

For calldata no, it's the encoding value. When you are inside your function if you specify "memory" for example, the calldata will be copied to memory and then yes dynamic types will be passed by reference since arrays are also a reference type.

how is it possible to retrospectively look at the value of that string for a previous transaction?

If you know that a string was received, for example with this contract :

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract LongString {

    function receivesLongString(string calldata longString) public {

    }
}

The parameter longString must have been passed by calldata (it doesn't matter that you use the calldata or memory specifier in your code, the parameters are encoded in the public transaction as you can read about in the doc).

This contract has been deployed here, and I made a call to it with the same string as before, you can see the tx here.

If you look at the input data you will see :

0x2830392a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000265468697320737472696e67206973206d6f7265207468616e203332206279746573206c6f6e670000000000000000000000000000000000000000000000000000

Where the first word is simply the first 4 bytes of keccak256("receivesLongString(string)") (function identifier) padded to 32 bytes and the rest is exactly the abi encoding of our string that we have seen earlier. So if you know what you are looking for, you can totally see the value from the tx calldata.

I hope that answers your questions.

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.