Is there any advantage of using inline assembly call over address.call?

For example

// address addr
// uint value
// bytes memory data

// using inline assembly
assembly {
    call(gas, addr, value, add(data, 0x20), mload(data), mload(0x40), 0)

// using address.call

I am looking at the code for Gnosis multisig wallet and wondered why they were using assembly call instead of address.call

1 Answer 1


Well, it's pretty obvious when looking into the set of input arguments passed in each case.

For the non-assembly call, you pass:

  • Destination address (addr)
  • Amount of ether (value)
  • Executable code (data)

For the assembly call, you pass:

  • Number of gas units
  • Destination address
  • Amount of ether
  • Executable code (data buffer + data length)
  • Output address (data buffer + data length)

So with the assembly call, you can also:

  1. Configure the gas
  2. Obtain the output

Edit(sea212): In this context, for solc == 0.4.x: By adding .gas(gas) you can also specify the number of gas units in non-assembly call. So the main advantage in using the assembly call is that you can obtain the output.

  • 1
    You can also obtain the output with the high-level call: <address>.call(bytes memory) returns (bool, bytes memory): issue low-level CALL with the given payload, returns success condition and return data, forwards all available gas, adjustable
    – sea212
    Commented Mar 3, 2020 at 11:47
  • @sea212: The question is about address.call.value, not address.call. Commented Mar 3, 2020 at 11:54
  • They are equivalent, except that you pass ether to a payable function. address.call.value(val)(data) is the Solidity <0.6.0 version of Solidity >=0.6.0 address.call{value: val}(data). In both cases they use the high level call I posted in the first comment and therefore in both cases they return a bool indicating the success of the execution and bytes containing the return data. You can test this in remix. What would be the point of a general call that does not offer the possibility to inspect the results?
    – sea212
    Commented Mar 3, 2020 at 12:21
  • 1
    @sea212: Of course, but the point of the question was to ask about any possible advantage in using assembly call over Solidity address.call.value, which is what I was trying to answer here. Also, please note that the contract in question was implemented in Solidity 0.4, so any extension of address.call.value in later versions is not really relevant in this context (i.e., should not be considered as part of the answer IMO). Commented Mar 3, 2020 at 12:32
  • 1
    I checked the solidity docs for Solidity 0.4.15 (which they used when they created the contract) and to my astonishment, it was indeed not possible to return the output data at that time. Nevertheless it was possible to configure the supplied gas by appending .gas(gas), e.g. address.call.value(value).gas(gas)(data). Quote: call returns a boolean indicating whether the invoked function terminated (true) or caused an EVM exception (false). It is not possible to access the actual data returned (for this we would need to know the encoding and size in advance).
    – sea212
    Commented Mar 3, 2020 at 12:40

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.