Previously in 20: Sending ETH we talked about sending ETH with call, in this tutorial we will dive into that.
Call
call is one of the address low-level functions which is used to interact with other contracts. It returns the success condition and the returned data: (bool, data).
- Officially recommended by
solidity,callis used to sendETHby triggeringfallbackorreceivefunctions. callis not recommended for interacting with other contracts, because you give away the control when calling a malicious contract. The recommended way is to create a contract reference and call its functions. See 21: Interact with other Contract- If the source code or
ABIis not available, we cannot create a contract variable; However, we can still interact with other contracts usingcallfunction.
Rules of using call
Rules of using call:
the binary code is generated by abi.encodeWithSignature:
function signature is "functionName(parameters separated by comma)". For example, abi.encodeWithSignature("f(uint256,address)", _x, _addr)。
In addition, we can specify the value of ETH and gas for the transaction when using call:
It looks a bit complicated, lets see how to use call in examples.
Target contract
Let's write and deploy a simple target contract OtherContract, the code is mostly the same as chapter 19, only with an extra fallback function。
This contract includes a state variable x, a Log event for receiving ETH, and three functions:
getBalance(): get the balance of the contractsetX():external payablefunction, can be used to set the value ofxand receiveETH.getX(): get the value ofx.
Contract interaction using call
1. Response Event
Let's write a Call contract to interact with the target functions in OtherContract. First, we declare the Response event, which takes success and data returned from call as parameters. So we can check the return values.
2. Call setX function
Now we declare the callSetX function to call the target function setX() in OtherContract. Meanwhile, we send msg.value of ETH, then emit the Response event, with success and data as parameters:
Now we call callSetX to change state variable _x to 5, pass the OtherContract address and 5 as parameters, since setX() does not have a return value, so data is 0x (i.e. Null) in Response event.

3. Call getX function
Next, we call getX() function, and it will return the value of _x in OtherContract, the type is uint256. We can decode the return value from call function, and get its value.
From the log of Response event, we see data is 0x0000000000000000000000000000000000000000000000000000000000000005. After decoding with abi.decode, the final return value is 5.

4. Call undeclared function
If we try to call functions that are not present in OtherContract with call, the fallback function will be executed.
In this example, we try to call foo which is not declared with call, the transaction will still succeed and return success, but the actual function executed was the fallback function.

Summary
In this tutorial, we talked about how to interact with other contracts using the low-level function call. For security reasons, call is not a recommended method, but it's useful when we don't know the source code and ABI of the target contract.