17
address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
nameReg.call("register", "MyName"); //1
nameReg.call(bytes4(sha3("fun(uint256)")), a); //2
if(!nameReg.call.value(10)){throw;} //3

Here it says,

Furthermore, to interface with contracts that do not adhere to the ABI, the function call is provided which takes an arbitrary number of arguments of any type. These arguments are padded to 32 bytes and concatenated. One exception is the case where the first argument is encoded to exactly four bytes. In this case, it is not padded to allow the use of function signatures here.

  • Are 1 and 2 legal?
  • Does it mean that 2 is illegal?
  • What does the 3 mean?

1 Answer 1

23

Solidity's call is a low-level interface for sending a message to a contract. It returns false if the subcall encounters an exception, otherwise it returns true. There is no notion of a legal call, if it compiles, it's valid Solidity.

  1. nameReg.call("register", "MyName") is a message that passes certain bytes to nameReg. For the bytes, see: Understanding nameReg.call("register", "MyName") style call between contracts

  2. nameReg.call(bytes4(sha3("fun(uint256)")), a) is a message that would invoke a function named fun (if nameReg adheres to the ABI) and pass it the raw, unpadded data a (you need to correctly pad a to 32 bytes first if you want behavior to match the ABI. For uint256 use left-padding.).

For 3, contract.call.value(...)(...) is a way to add Ether when invoking a contract. if(!nameReg.call.value(10)()){throw;} is an example of handling the failure case of the subcall. Note the extra parentheses value(10)() which invokes the fallback function.

call is a low-level interface, and it is simpler to invoke a function directly, nameReg.fun(a) instead of the second example. The direct invocation is also type-safe, and allows the return value of fun to be used.

5
  • 2
    Note that in the case of 1, "register" and "MyName" are padded to 32 bytes, whereas in 2, a is concatenated directly onto the 4-byte bytes4(sha3("fun(uint256)")) Sep 23, 2016 at 17:09
  • @eth so do you mean it ignores returned value by the contract? Feb 17, 2021 at 15:56
  • @user2284570 Yes, Solidity's call does not return a contract function's return value: it only returns did the function encounter an exception or not.
    – eth
    Mar 7, 2021 at 21:38
  • 2
    As I understand it, (bool success, bool returnBytes) = addr.call{...}(abi.encodeWithSignature(...), ...) is the new recommended way to (1) call functions without throwing if the function cannot be called, and (2) send payment to payable functions. So I'm pretty sure chriseth's comment about call only applies to the older versions. Dec 14, 2021 at 10:48
  • 1
    @LukeHutchison Think you're right, upvoted, and removed the chriseth comment. Not sure how much to edit the rest of this answer; feel free to write a 2nd answer that is much more current :)
    – eth
    Dec 15, 2021 at 21:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.