WTF Solidity: 21. Interact with other Contract
Twitter: @0xAA_Science | @WTFAcademy_
Community: Discord|Wechat|Website wtf.academy
Codes and tutorials are open source on GitHub: github.com/AmazingAng/WTFSolidity
Interact with deployed contract
Interactions between contracts not only make the programs re-usable on the blockchain, also enrich the Ethereum ecosystem. Many web3 Dapps rely on other contract to work, for example yield farming. In this tutorial, we will talk about how to interact with contract that source code (or ABI) and address are available.
Target Contract
Lets write a simple contract OtherContract to work with.
contract OtherContract {
uint256 private _x = 0; // state variable x
// Receiving ETH event, log the amount and gas
event Log(uint amount, uint gas);
// get the balance of the contract
function getBalance() view public returns(uint) {
return address(this).balance;
}
// set the value of x, as well as receiving ETH (payable)
function setX(uint256 x) external payable{
_x = x;
// emit Log event when receiving ETH
if(msg.value > 0){
emit Log(msg.value, gasleft());
}
}
// read the value of x
function getX() external view returns(uint x){
x = _x;
}
}
This contract includes a state variable _x, a Log event which will emit when receiving ETH, and three functions:
getBalance(): return the balance of the contract.setX():external payablefunction, set the value of_x, as well as receivingETH.getX(): read the value of_x
Interact with OtherContract
We can create a reference to the contract with the contract address and source code (or ABI): _Name(_Address), _Name is the contract name which should be consistent with the contract source code (or ABI), _Address is the contract address. Then we can call the functions in the contract like this: _Name(_Address).f(), f() is the function you want to call.
Here are four examples of interacting with contracts, compile and deploy these two contracts: OtherContract and CallContract:
1. Pass the contract address
We can pass the contract address as parameter and create a reference of OtherContract, then call the function of OtherContract. For example, here we create a callSetX function which will call setX from OtherContract, pass the deployed contract address _Address and the x value as parameter:
function callSetX(address _Address, uint256 x) external{
OtherContract(_Address).setX(x);
}
Copy the address of OtherContract, and pass it as the first parameter of callSetX, after the transaction succeeded, we can call getX from OtherContract and the value of x is 123.
2. Pass the contract variable
We can also pass the reference of the contract as parameter, just change the type from address to the contract name, i.e. OtherContract. The following example shows how to call getX() from OtherContract.
Note: The parameter OtherContract _Address is still address type behind the scene. You will find it's address type in the generated ABI and when passing the parameter to callGetX.
function callGetX(OtherContract _Address) external view returns(uint x){
x = _Address.getX();
}
Copy the address of OtherContract, and pass it as the parameter of callGetX, after the transaction succeeded, we can get the value of x.
3. Create contract variable
We can create a contract variable and call its functions. The following example shows how to create a reference of OtherContract and save to oc:
function callGetX2(address _Address) external view returns(uint x){
OtherContract oc = OtherContract(_Address);
x = oc.getX();
}
Copy the address of OtherContract, and pass it as the parameter of callGetX2 , after the transaction succeeded, we can get the value of x.
4. Interact with contract and send ETH
If the target function is payable, then we can also send ETH to that contract: _Name(_Address).f{value: _Value}(), _Nameis the contract name, _Address is the contract address, f is the function to call, and _Value is the value of ETH to send (in wei).
OtherContract has a payable function setX, in the following example we will send ETH to the contract by calling setX.
function setXTransferETH(address otherContract, uint256 x) payable external{
OtherContract(otherContract).setX{value: msg.value}(x);
}
Copy the address of OtherContract, and pass it as the parameter of setXTransferETH , in addition we send 10ETH.
After the transaction is confirmed, we can check the balance of the contract by reading the Log event or by calling getBalance().
Summary
In this tutorial, we talked about how to create contract reference with its source code (or ABI) and address, then call its functions.