2

enter image description here

Hi I am new but I want to learn, I have just forked a project in Solidity and deployed it. I would like to know how to use calldata in order to call an external function. For instance:

function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

Can you provide any example? I deployed and I would like to call the function from https://remix.ethereum.org/

Thanks

1 Answers1

4

The CALLDATA field in Remix allows you to manually input any value of the data field in Ethereum transaction.

The data field always starts with 0x, then contains 4 bytes (8 hex characters) of the function signature, and the rest of data is the function arguments.


Function signature is calculated as first 4 bytes of keccak-256 hash of a string containing the function name and argument types.

Example:

  • transferOwnership(address) - this is the string that is going to be hashed
  • f2fde38b092330466c661fc723d5289b90272a3e580e3187d1d7ef788506c557 is the keccak-256 hash of this string
  • f2fde38b is the first 4 bytes, which is the function signature

The arguments are then ordered in the same way as in the function (in your case, there's only one argument). The length of each value depends on its datatype (some are fixed, some dynamic). In case of address type, the length is 256bit (64 hex characters).

So if you have an address 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, the actual value passed as an argument is going to be 000000000000000000000000ffffffffffffffffffffffffffffffffffffffff (left-padded zeros to the length of 256bit).


All combined together:

0xf2fde38b000000000000000000000000ffffffffffffffffffffffffffffffffffffffff

calls the function transferOwnership(address) and passes address 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF as an argument

Note: You can find another example in my answer to a similar question.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • How does it determine the function name from the first 4 bytes of the hash of the name? – Alireza Zojaji Feb 12 '22 at 13:43
  • 1
    @AlirezaZojaji The 4byte selector is a result of a one-way hash function. So unless you have a dictionary of selectors to their respective function names, there's no way to get the function name just from the selector. – Petr Hejda Feb 12 '22 at 13:45
  • How can we include a string in arguments? (Since its length is not known) – Alireza Zojaji Feb 12 '22 at 13:46
  • 1
    @AlirezaZojaji String is effectively a dynamic-length array of bytes. And Solidity allows for dynamic-length array without predefined size. Example: `function foo(string memory _myString) external`. Its selector `0xf31a6969` is then calculated from the function name and types (without the `memory` data location): `foo(string)` – Petr Hejda Feb 12 '22 at 13:47
  • Ok, Suppose we need to call a function with 2 string arguments. How does it determine the length of each arguement? – Alireza Zojaji Feb 12 '22 at 13:49
  • And where is the dictionary of selectors stored? – Alireza Zojaji Feb 12 '22 at 13:51
  • 1
    @AlirezaZojaji If a param is a dynamic-sized array, its value consists of 2 parts: 1) pointer to the location of the actual value, and 2) the actual value. Example: When you call`foo(string,string)`, you pass at least four 32-byte slots of data. 1st slot value is a pointer to the 3rd slot where the actual string value is stored. 2nd slot value is a pointer to the 4th slot where the actual string value is stored. If the first string was longer than one slot - for example 3 slots - the second string starts in (and the second pointer points to) a slot after these three. – Petr Hejda Feb 12 '22 at 13:56
  • 1
    @AlirezaZojaji There is no official "the dictionary". There are several collections by, for example, blockchain explorer sites, some of them might be opensource, ... But generally, the selector is really just a result of a one-way hashing function. – Petr Hejda Feb 12 '22 at 13:58
  • Please introduce a reference about calling external functions. – Alireza Zojaji Feb 12 '22 at 14:48