How to call on contracts from other contracts in Solidity

Overview

When we have the address of another smart contract, we can call its functions in multiple different ways:

contract One {
	function foo() external {}
}

contract Two {
	function a(address _address) external {
		One(_address).foo();
	}
	
	function b(One _address) external {
		_address.foo();
	}
	
	function c(address _address) external {
		_address.call(abi.encodeWithSignature("foo()"));
	}
	
	function d(address _address) external {
		_address.call(abi.encodeWithSelector(One.test.selector));
	}
}

Pass the address into the contract, and then call a function on the contract:

address _address;
One(_address).foo();

Directly call the function on the address:

One _address;
_address.foo();

Using call

Use the low level call function.

To reference the function we want to call, we can:

Encode with signature

Use abi.encodeWithSignature and pass the function signature including its parameter types.

_address.call(
	abi.encodeWithSignature(
		"foo(string,uint256)",
		"some string",
		42
	)
);

Note that we don’t use spaces to separate parameter types in the encoding.

Also we don’t use type aliases, instead of uint we definitely declare uint256.

Encode with selector

_address.call(
	abi.encodeWithSelector(
		One.foo.selector,
		"some string",
		42
	)
);

This way we do not have to manually define the function parameters types.

Return values

We will get back a boolean indicating success/failure and the output of the function.

(bool success, bytes memory data) = _address.call("");

Pass ether with function call

One _address;
_address.foo{value: 1 ether}();

background scene
Join the garden
Finally enjoy quality-first content.
'cause low-quality sucks

legal privacy