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 and test utilities that facilitate testing with Starknet Foundry.
| 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.9.4 (d3be9ebe1 2025-02-19)
cairo: 2.9.4 (https://crates.io/crates/cairo-lang-compiler/2.9.4)
sierra: 1.6.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 = "2.0.0-alpha.1"
The previous example would import the entire library. We can also add each package as a separate dependency to improve the building time by not including modules that won’t be used:
[dependencies]
openzeppelin_access = "2.0.0-alpha.1"
openzeppelin_token = "2.0.0-alpha.1"
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 {
// NOTE: If you added the entire library as a dependency,
// use `openzeppelin::token` instead.
use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl, DefaultConfig};
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