
Cairo
- 5 installs
- 4 repo stars
- Updated February 25, 2026
- hairyf/blockchain-master
Write and compile Cairo programs and Starknet contracts, using the Rust-like syntax, Sierra/CASM pipeline, and linear-type semantics.
About
A reference for the Cairo language and compiler covering modules, types, traits, and the Sierra-to-CASM compilation pipeline for provable programs. A developer uses it when building Starknet contracts or general provable computation.
- Rust-like syntax compiling via Sierra IR to CASM
- Modules/crates, linear types, and Starknet contract structure
Cairo by the numbers
- 5 all-time installs (skills.sh)
- Ranked #338 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Jul 13, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hairyf/blockchain-master --skill cairoAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 4 |
| Last updated | February 25, 2026 |
| Repository | hairyf/blockchain-master ↗ |
What it does
Write and compile Cairo programs and Starknet contracts, using the Rust-like syntax, Sierra/CASM pipeline, and linear-type semantics.
Files
Skill based on Cairo (starkware-libs/cairo), generated fromsources/cairo. Doc path:sources/cairo/docs/reference/src/components/cairo/modules/.
Cairo is a Turing-complete language for provable programs (Starknet, general computation). It uses a Rust-like syntax, Sierra as an intermediate representation, and compiles to CASM. Use this skill for writing and compiling Cairo programs and Starknet contracts, and for understanding types, traits, and linear semantics.
Core References
| Topic | Description | Reference |
|---|---|---|
| Modules and crates | Crates, modules, use, super, file layout | core-modules-and-crates |
| Functions | Signatures, mut/ref, methods, implicits, nopanic, local compilability | core-functions |
| Structs and enums | Definitions, instantiation, destructuring, match | core-structs-and-enums |
| Traits and impls | Traits, named impls (of), impl generics, dispatch | core-traits-and-impls |
| Types and generics | Type system, generics, Array, Felt252Dict, fixed arrays | core-types-and-generics |
| Linear types | Move, Copy, Drop, Destruct, Clone, snapshot (@) | core-linear-types |
| Derive and prelude | Derive macro, common traits, prelude | core-derive-and-prelude |
Features
Starknet
| Topic | Description | Reference |
|---|---|---|
| Starknet contracts | Storage, entry points, events, ABI, dispatchers, syscalls | features-starknet-contracts |
Tooling
| Topic | Description | Reference |
|---|---|---|
| CLI and compilation | cairo-compile, sierra-compile, cairo-run, starknet-compile | features-cli-and-compilation |
| Match and panic | Match (enum/felt252), panic, nopanic, panic_with | features-match-and-panic |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Naming and memory | Conventions, struct copy semantics, array/dict patterns | best-practices-naming-and-memory |
Naming and Memory Practices
Follow Cairo naming conventions for consistency and tooling. Be aware of immutable memory and struct copy semantics when writing performance-sensitive code.
Naming
| Item | Convention |
|---|---|
| Modules | snake_case |
| Types, traits | PascalCase |
| Enum variants | PascalCase |
| Struct fields | snake_case |
| Functions, methods, variables | snake_case |
| Constants | UPPER_CASE |
| Type parameters | PascalCase (often single letter e.g. T) |
- Acronyms:
L1HandlernotL1_Handler;rpc_callnotRPC_call. - Avoid single-letter words except as last word or digit:
contract_classnotc_class. - Unused variables must be prefixed with
_(e.g._or_unused).
Memory and structs
- Struct mutation: Assigning to a member with
.copies the whole struct. For multiple field updates, prefer one full struct literal assignment to avoid repeated copies. - Arrays: No in-place element mutation; use
.append()and.pop_front(). Iterate with.span()to avoid consuming the array. - Dictionaries: Use
entry(key)+finalize(value)for read-modify-write; types containingFelt252Dictmust deriveDestruct.
Key Points
- Consistent naming improves readability and allows linter warnings.
- Minimize struct copies in hot paths; use snapshots
@when only reading. - Prefer
Spanandentry/finalizepatterns over repeated indexing or redundant copies.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/naming-conventions.adoc
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/structs.adoc
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/array-types.adoc
-->
Derive Macro and Prelude
The #[derive(...)] attribute generates implementations of common traits for structs and enums. The prelude brings standard items into scope.
Derive
#[derive(Copy, Drop, PartialEq)]
struct Foo { x: i32, y: i32 }
#[derive(Copy)]
struct FeltAndT<T, impl TCopy: Copy<T>> { f: felt252, t: T }Common derived traits: Copy, Clone, Drop, Destruct, Default, Debug, Hash, PanicDestruct, PartialEq, Serde. All members must implement the same trait (or for Default on enums, only the #[default] variant’s members).
Key Points
- Use
Dropfor types that can be discarded at scope exit;Destructfor types that need explicit teardown (e.g. containingFelt252Dict). PanicDestructallows safe destruction during panic; required for destructors in panic paths.- Prelude is automatically applied; no need to import basic types/traits for standard code.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/derive-macro.adoc
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/prelude.adoc
-->
Linear Types
Cairo uses move semantics by default: values are used exactly once. Copying and dropping are forbidden unless the type implements the appropriate trait.
Usage
Move: After a value is passed or used, it cannot be used again unless it implements Copy or is used via snapshot @.
struct A {}
fn main() {
let a = A {};
foo(a);
foo(a); // error: value was previously moved
}Copy: Allow multiple uses by copying.
#[derive(Copy)]
struct A {}Drop: Allow values to go out of scope without being moved.
#[derive(Drop)]
struct A {}
fn main() { A {}; } // okDestruct: For types that cannot be dropped (e.g. contain Felt252Dict), provide custom teardown.
#[derive(Destruct)]
struct A { d: Felt252Dict<u32> }Clone: Explicit copy when Copy is not appropriate (e.g. types containing Array).
Snapshot `@T`: Immutable view; does not move the value. Always copyable and droppable.
Pitfalls and solutions
| Problem | Solution |
|---|---|
| "Value was previously moved" | Use @ snapshot, ref parameter, derive Copy/Clone, or add impl generic Copy<T>/Clone<T>. |
| "Value was not dropped" | Derive Drop or Destruct, deconstruct with let A { .. } = a or match, or call a function that consumes the value. |
Restrictions: Copy cannot be implemented if any field is non-copyable (e.g. Array). Drop cannot be implemented if any field is non-droppable (e.g. Dict). Destructors must be nopanic.
Key Points
- Default: move only, no implicit copy or drop.
- Snapshot
@does not move; use for read-only sharing. - Use
Destructfor types holding dictionaries; implement manually asnopanicif needed.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_semantics/pages/linear-types.adoc
-->
Modules and Crates
Crates are single compilation units with a root directory and root module in lib.cairo. Modules are named containers for items (structs, enums, functions, constants, traits).
Usage
Define a module inline or in a separate file. File path follows the module hierarchy: crate_name::a::b::c → <crate_root>/a/b/c.cairo.
// a.cairo
mod foo {
// items
}
mod bar; // defined in a/bar.cairoScope: Items in outer modules are not visible in inner modules. Use full paths or use to refer to them. Use super for the parent module.
struct A {}
struct B {}
mod foo {
use super::B;
fn bar() {
super::A {}; // allowed
B {}; // allowed (imported)
// A {}; // error: not in scope
}
}Key Points
- One crate = one compilation unit; root =
lib.cairo. - Module hierarchy is defined by
moddefinitions; submodules use their name, parent usessuper. - Import with
use path::to::Itemoruse path::to::Item as Alias.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/modules-and-source-files.adoc
-->
Match and Panic
Match expressions select code by pattern; panic aborts execution unrecoverably. Functions can be marked nopanic or use panic_with for Option/Result.
Match
On enums: One arm per variant; bind variant data. Arms that don’t return or panic must have the same type.
match enum_var {
Variant0(a, b, c) => { ... }
Variant1(_) => { ... }
}On felt252: Literal 0 and wildcard _ only.
match felt_var {
0 => { ... }
_ => { ... }
}Panic
Basics: panic(data: Array<felt252>) -> never. Panic runs destructors (Drop/Destruct) for live values so execution stays provable.
nopanic: Only nopanic functions can be called from a nopanic function. Trait functions marked nopanic require all impls to be nopanic (e.g. Destruct::destruct).
panic_with: For functions returning Option or Result; on None/Err call panic with given data and optionally create a wrapper (e.g. unwrap).
#[panic_with('got none value', unwrap)]
fn identity(value: Option<u128>) -> Option<u128> { value }Key Points
- Match is exhaustive; use
_for catch-all on felt252. - Destructors must be nopanic because they run during panic.
- Use
panic_withto get consistent panic messages and wrapper helpers.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/match-expressions.adoc
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/panic.adoc
-->
Starknet Contracts
Starknet contracts are Cairo modules annotated with #[starknet::contract]. They have persistent storage, entry points (external, constructor, L1 handler), and can emit events and call other contracts.
Usage
Contract and storage: Define a Storage struct; use ::read() and ::write(value) for simple storage, ::read(key) / ::write(key, value) for maps. Prefer starknet::storage::Map over deprecated LegacyMap.
#[starknet::contract]
mod my_contract {
struct Storage {
x: felt252,
m: LegacyMap::<felt252, u128>,
}
#[external(v0)]
fn foo(value: felt252) -> felt252 {
let y = x::read() + value;
m::write(y, 3_u128);
y
}
}Entry points: #[external(v0)] for public/contract calls (first parameter ref self: ContractState or self: @ContractState for views); #[constructor] (single, must be named constructor); #[l1_handler] for L1 messages. Unannotated functions are private.
Events: Define #[event] enum with variants deriving starknet::Event; emit with self.emit(Event::Variant(...)). Use #[flat] to merge nested event enums.
Calling other contracts: Use the generated interface and dispatchers. Contract dispatcher runs in callee context; library dispatcher runs in caller context. Use IMyContractDispatcher { contract_address } or IMyContractLibraryDispatcher { class_hash }. For low-level control use starknet::syscalls::call_contract_syscall (selector = starknet_keccak of function name).
Key Points
- Storage types must implement
starknet::Store; map keys must implementHash. - Deployment default-initializes storage (zeroes). Constructor is optional.
- ABI describes entry points, types, and events; use
<contract>::__abifor the generated trait.
<!-- Source references:
- https://github.com/starkware-libs/cairo
- sources/cairo/docs/reference/src/components/cairo/modules/language_constructs/pages/contracts.adoc
-->