New to blockchain software development? Read my beginners guide here

How to call another smart contract

Created on August 2022 • Tags: ethereumsolidityguides

A guide to calling a smart contract within another contract


Table of Contents for How to call another smart contract


If you have 2 smart contracts. One has a public function, and you want to call that function from another.

Let’s say you have this contract, deployed already:


contract FirstDeployedContract {
uint public counter = 1;

function setCounter(uint _newValue) public {
counter = _newValue;
}
}

And you have a new contract where you want to call setCount(123).

There are a few ways you could do this…

If you know the other (deployed) contract you can cast an address to that contract type, which means you can then call the function setCounter(uint) on it.

The following example shows this - there is a function setAddress which takes a new address, you can pass in the deployed FirstDeployedContract address.

Note: there is no check that _addr really is a FirstDeployedContract. It just trusts you.

// not shown here, but make sure FirstDeployedContract was imported in.
contract SecondContract {

FirstDeployedContract deployedContract;

function setAddress(address _addr) public {
deployedContract = FirstDeployedContract(_addr);
}

function setCounter(uint _val) public {
// assumes you called setAddress() with a valid FirstDeployedContract address
deployedContract.setCounter(_val); // << calls setCounter on the _addr
}

}

Calling a function in another contract by using its keccak256 signature

Maybe you don’t have the full contract details (or ABI). Maybe you just know there is a function called setCounter(uint) on a smart contract deployed at an address.

A function is called by calculating the start of a keccak256 hash. There is a mapping in smart contracts that maps from that 4 bytes of keccak256 hash to a function call.

// ...
// 'deployedContract' is set up the same as previous code above.

function setCounterWithSignature(uint _newCounterVal) public {
deployedContract.call(bytes4(keccak256("setA(uint256)")),_newCounterVal);
}
// ...

Calling another contract, using assembly code (Yul)

As well as calling other contracts in normal Solidity code, it is of course also possible to call another contract using assembly code in Solidity (Yul)

You have to get the 4 bytes function selector, then call it with staticcall().

You can also use call() but only for non view/pure functions.

You pass in how much gas to use on the call. If we just pass in gas(), then all remaining gas possible will be sent as the max amount.


assembly {
mstore(0x00, theFunctionSelector); // theFunctionSelector should be 32 bytes here)

// 32-28 = 4 bytes.
// the selector will be the final 4 bytes (of the full 32 bytes)
let wasSuccessful := staticcall(gas(), theOtherContractAddress, 28, 32, 0x00, 0x20)
if(iszero(wasSuccessful) {
revert(0, 0)
}
// success!
}

This post is incomplete and a work-in-progress
I'll update it soon and flesh it out with more info!

Spotted a typo or have a suggestion to make this crypto dev article better? Please let me know!

See all posts (70+ more)

See all posts (70+ more)

Was this post helpful? 📧

If you liked this content and want to receive emails about future posts like this, enter your email. I'll never spam you.

Or follow me on @CryptoGuide_Dev on twitter

By using this site, you agree that you have read and understand its Privacy Policy and Terms of Use.
Use any information on this site at your own risk, I take no responsibility for the accuracy of safety of the information on this site.