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.
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.
#[starknet::interface]
trait ICallee<TContractState> {
fn set_value(ref self: TContractState, value: u128) -> u128;
}
#[starknet::contract]
mod Callee {
#[storage]
struct Storage {
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
}
}
}
Visit contract on Voyager or play with it in Remix.
use starknet::ContractAddress;
// We need to have the interface of the callee contract defined
// so that we can import the Dispatcher.
#[starknet::interface]
trait ICallee<TContractState> {
fn set_value(ref self: TContractState, value: u128) -> u128;
}
#[starknet::interface]
trait ICaller<TContractState> {
fn set_value_from_address(ref self: TContractState, addr: ContractAddress, value: u128);
}
#[starknet::contract]
mod Caller {
// We import the Dispatcher of the called contract
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);
}
}
}