Calling other contracts
There are two different ways to call other contracts in Cairo.
The easiest way to call other contracts is by using the dispatcher of the contract you want to call. You can read more about Dispatchers in the Cairo Book.
The other way is to use the starknet::call_contract_syscall
syscall yourself. However, this method is not recommended and will not be covered in this chapter.
In order to call other contracts using dispatchers, you will need to define the called contract's interface as a trait annotated with the #[starknet::interface]
attribute, and then import the IContractDispatcher
and IContractDispatcherTrait
items in your contract.
Here's the Callee
contract interface and implementation:
// This will automatically generate ICalleeDispatcher and ICalleeDispatcherTrait
#[starknet::interface]
pub trait ICallee<TContractState> {
fn set_value(ref self: TContractState, value: u128) -> u128;
}
#[starknet::contract]
pub mod Callee {
use starknet::storage::StoragePointerWriteAccess;
#[storage]
struct Storage {
pub value: u128,
}
#[abi(embed_v0)]
impl ICalleeImpl of super::ICallee<ContractState> {
fn set_value(ref self: ContractState, value: u128) -> u128 {
self.value.write(value);
value
}
}
}
The following Caller
contract uses the Callee
dispatcher to call the Callee
contract:
#[starknet::contract]
pub mod Caller {
// We need to import the dispatcher of the callee contract
// If you don't have a proper import, you can redefine the interface by yourself
use super::{ICalleeDispatcher, ICalleeDispatcherTrait};
use starknet::ContractAddress;
#[storage]
struct Storage {}
#[abi(embed_v0)]
impl ICallerImpl of super::ICaller<ContractState> {
fn set_value_from_address(ref self: ContractState, addr: ContractAddress, value: u128) {
ICalleeDispatcher { contract_address: addr }.set_value(value);
}
}
}