Skip to content

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);
        }
    }
}
Powered By Nethermind