7
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?
17

EDIT: Solidity's author, chriseth, recommends to avoid using Solidity's call

https://github.com/ethereum/solidity/issues/2884#issuecomment-329169020

The thing is: a.call() is an ancient beast that should not be used. I would recommend using inline assembly for such tasks, since it provides the same security guarantees but does not do any invisible magic.


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.

  • 1
    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)")) – Tjaden Hess Sep 23 '16 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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