Contracts for Cairo

A library for secure smart contract development written in Cairo for Starknet. This library consists of a set of reusable components to build custom smart contracts, as well as ready-to-deploy presets. You can also find other utilities including interfaces and dispatchers.

This repo contains highly experimental code. Expect rapid iteration. Use at your own risk.
You can track our roadmap and future milestones in our Github Project.

Installation

The library is available as a Scarb package. Follow this guide for installing Cairo and Scarb on your machine before proceeding, and run the following command to check that the installation was successful:

$ scarb --version

scarb 2.6.3 (e6f921dfd 2024-03-13)
cairo: 2.6.3 (https://crates.io/crates/cairo-lang-compiler/2.6.3)
sierra: 1.5.0

Set up your project

Create an empty directory, and cd into it:

mkdir my_project/ && cd my_project/

Initialize a new Scarb project:

scarb init

The contents of my_project/ should now look like this:

$ ls

Scarb.toml src

Install the library

Install the library by declaring it as a dependency in the project’s Scarb.toml file:

[dependencies]
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.12.0" }
Make sure the tag matches the target release.

Basic usage

This is how it looks to build an ERC20 contract using the ERC20 component. Copy the code into src/lib.cairo.

#[starknet::contract]
mod MyERC20Token {
    use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
    use starknet::ContractAddress;

    component!(path: ERC20Component, storage: erc20, event: ERC20Event);

    // ERC20 Mixin
    #[abi(embed_v0)]
    impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
    impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;

    #[storage]
    struct Storage {
        #[substorage(v0)]
        erc20: ERC20Component::Storage
    }

    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
        #[flat]
        ERC20Event: ERC20Component::Event
    }

    #[constructor]
    fn constructor(
        ref self: ContractState,
        name: ByteArray,
        symbol: ByteArray,
        fixed_supply: u256,
        recipient: ContractAddress
    ) {
        self.erc20.initializer(name, symbol);
        self.erc20._mint(recipient, fixed_supply);
    }
}

You can now compile it:

scarb build