Skip to content

Latest commit

 

History

History
117 lines (90 loc) · 4.53 KB

readme_en.md

File metadata and controls

117 lines (90 loc) · 4.53 KB
title tags
27. Library Dispatcher
cairo
starknet
interface
abi
erc20
dispatcher
library

WTF Cairo Simple Tutorial: 27. Library Dispatcher

I've been learning cairo-lang recently, solidifying my understanding of the details, and creating a "WTF Cairo Simple Tutorial" for beginners. This tutorial is based on cairo 2.2.0 version.

Twitter: @0xAA_Science@WTFAcademy_

WTF Academy Community: DiscordWeChat GroupOfficial Website wtf.academy

All code and tutorials are open-source on GitHub: github.com/WTFAcademy/WTF-Cairo


In this chapter, we will introduce the Library Dispatcher in Cairo, which is automatically generated by interface contracts to help you call library contracts, similar to delegatecall in Solidity.

Library Dispatcher

Similar to the Contract Dispatcher, the Library Dispatcher is also automatically generated by interface contracts to assist you in calling library contracts. However, when using the Contract Dispatcher to call a target contract, the context is the target contract; whereas when using the Library Dispatcher to call a target contract, the context is the current contract. This is why it behaves like Solidity's delegatecall.

Additionally, unlike Ethereum, Starknet separates the code and storage of contracts. When you declare a contract, the contract's code is stored on the chain and can be queried via class_hash. Later, when you deploy the contract, it initializes and allocates storage. Since delegatecall only uses the target contract's code and does not require access to state variables, only the class_hash is needed for invocation. This means that every declare contract on Starknet can be used as a library contract.

Let's take the IMiniERC20 interface contract from our previous lesson as an example:

#[starknet::interface]
trait IMiniERC20<TContractState> {
    fn name(self: @TContractState) -> felt252;
    fn symbol(self: @TContractState) -> felt252;
}

The library dispatcher generated by the compiler looks like this:

#[derive(Copy, Drop, starknet::Store, Serde)]
struct IMiniERC20LibraryDispatcher {
    class_hash: starknet::ClassHash,
}

trait IMiniERC20DispatcherTrait<T> {
    fn name(self: T) -> felt252;
    fn symbol(self: T) -> felt252;
}

impl IMiniERC20LibraryDispatcherImpl of IMiniERC20DispatcherTrait<IMiniERC20LibraryDispatcher> {
    fn name(
        self: IMiniERC20Dispatcher
    ) -> felt252 {
        // Call the corresponding function using starknet::library_call_syscall
    }
    fn symbol(
        self: IMiniERC20Dispatcher
    ) {
        // Call the corresponding function using starknet::library_call_syscall
    }
}

Now, let's write a contract using the Library Dispatcher to call the mini_erc_20 library.

#[starknet::contract]
mod librarycall_mini_erc_20 {
    use starknet::ContractAddress;
    use super::IMiniERC20DispatcherTrait;
    use super::IMiniERC20LibraryDispatcher;

    #[storage]
    struct Storage {
        name: felt252,
        symbol: felt252,
    }

    #[constructor]
    fn constructor(
        ref self: ContractState,
        name_: felt252,
        symbol_: felt252,
    ) {
        self.name.write(name_);
        self.symbol.write(symbol_);
    }

    #[external(v0)]
    fn get_name(self: @ContractState, class_hash: starknet::ClassHash) -> felt252 {
        IMiniERC20LibraryDispatcher { class_hash }.name()
    }

    #[external(v0)]
    fn get_symbol(self: @ContractState, class_hash: starknet::ClassHash) -> felt252 {
        IMiniERC20LibraryDispatcher { class_hash }.symbol()
    }
}

A few points to note:

  • In the contract, you need to import DispatcherTrait and LibraryDispatcher.
  • Ensure that the layout of state variables in the contract matches that of the library contract, similar to Solidity's proxy contracts.
  • When calling, use IMiniERC20LibraryDispatcher and pass the target library's class_hash.

Conclusion

In this chapter, we introduced the Library Dispatcher in Cairo, which is automatically generated by interface contracts, making it convenient for you to call library contracts. Unlike the Contract Dispatcher, it uses the context of the current contract during invocation, similar to Solidity's delegatecall. Pay attention to this when using it.