{"id":18357205,"url":"https://github.com/nethermindeth/cairo-workshop","last_synced_at":"2025-04-10T01:53:44.557Z","repository":{"id":255461236,"uuid":"851295520","full_name":"NethermindEth/cairo-workshop","owner":"NethermindEth","description":"Cairo smart contract development workshop content","archived":false,"fork":false,"pushed_at":"2024-10-01T21:46:43.000Z","size":35,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-05T09:45:44.908Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Cairo","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NethermindEth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-02T20:18:44.000Z","updated_at":"2024-11-04T10:58:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"b281c1a8-e73a-45eb-b26f-618d0afc1efe","html_url":"https://github.com/NethermindEth/cairo-workshop","commit_stats":null,"previous_names":["nethermindeth/cairo-workshop"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fcairo-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fcairo-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fcairo-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NethermindEth%2Fcairo-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NethermindEth","download_url":"https://codeload.github.com/NethermindEth/cairo-workshop/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248142939,"owners_count":21054671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T22:13:13.041Z","updated_at":"2025-04-10T01:53:44.529Z","avatar_url":"https://github.com/NethermindEth.png","language":"Cairo","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intro to Cairo Smart Contract Development\n\n## Slidedeck\n\nhttps://docs.google.com/presentation/d/11atBf9fmFT1ZPeCEqFQiifylQUFhTk8dR6W6T0-NlXk\n\n## Prerequisites\n\nThe following components are recommended to be installed for full experience of the workshop. \nNOTE: CLI commands listed below are for a Linux shell (for Windows-based systems it is recommended to use WSL for efficiency)\n\n- Install Rust \u0026 Cargo:\n  - `curl https://sh.rustup.rs -sSf | sh -s`\n    or\n  - `rustup update` (make sure you are at Rust 1.80.1)\n\n- Install scarb (https://docs.swmansion.com/scarb/download.html):\n  - `curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh`\n\n- Download and build starklings\n  - `git clone https://github.com/shramee/starklings-cairo1.git \u0026\u0026 cd starklings-cairo1`\n  - `cargo update`\n  - `cargo run -r --bin starklings`\n\n- Install starkli *(recommended for CLI-heavy development)*\n  - `curl https://get.starkli.sh | sh`\n  - `starkliup`\n\n- Install Starknet wallet *(recommended for in-browser development)*\n  - https://braavos.app/\n    \n    or\n  - https://www.argent.xyz/\n\n## Starknet fundamentals\n\n### STARK\n\n- Succinct Non-Interactive Argument of Knowledge - one of fields of research of zk proofs\n- Proof of 'integrity'\n- For example - I computed program P over input I which resulted in O\n\n### Logical concept of Starknet\n\n```\n\n\n                                             ┌───────────┐\n                                  ┌─────────►│           │ Proof\n                                  │          │   SHARP   ├────────┐\n                              ┌───┴───┐      │           │        │\n┌─────┐      ┌──────────┐     │ Block │      └───────────┘  ┌─────▼───────┐\n│ tx1 │      │          │     │  ---  │                     │             │\n│     ├─────►│ Starknet ├────►│  tx1  │                     │   Ethereum  │\n│ tx2 │      │          │     │       │                     │             │\n│     │      └──────────┘     │  tx2  │                     └─────────────┘\n│ tx3 │                       │       │                           ▲\n│     │                       │  tx3  ├───────────────────────────┘\n│  .  │                       │       │\n│  .  │                       │   .   │\n│  .  │                       │   .   │\n│     │                       │   .   │\n└─────┘                       └───────┘\n\n```\n---\n\n### Cairo\n\n- `Cairo` is a high level language which compiles to `Sierra` (The `S`afe `I`nt`e`rmediate `R`ep`r`esent`a`tion) - prevents writing unprovable code\n- `Sierra` compiles to `Cairo Assembly` (`CASM`)\n- `CASM` is a provable computation language\n  - i.e. execution of CASM can be proven by SHARP (and proof stored on L1).\n\n```\n\n     ┌─────────┐\n     │         │\n     │  Cairo  │\n     │         │\n     └────┬────┘                             ┌───────────────────────┐\n          │                                  │                       │\n          ▼                                  │                       │\n   ┌────────────┐                            │                       │\n   │            │                            │                       │\n   │   Sierra   │     ──────────────────►    │   Starknet network    │\n   │            │                            │                       │\n   └──────┬─────┘                            │                       │\n          │                                  │                       │\n          ▼                                  └────────┬──────────────┘\n ┌─────────────────┐                                  │\n │                 │                                  │\n │      CASM       │                                  │\n │(Cairo Assembly) │                                  │\n │                 ├──────────────────────────────────┤\n └─────────────────┘                                  │\n                                                      ▼\n                                              ┌─┬─────┬───┬─┐\n                                              │ ├─────────┤ │\n                                              │ │         │ │\n                                              │ │  SHARP  │ │\n                                              │ │         │ │\n                                              │ ├─────────┤ │\n                                              └─┴────┼────┴─┘\n```\n\n---\n\n### Cairo program example\n```rust\nuse debug::PrintTrait;\n\nfn fib(a: felt252, b: felt252, n: felt252) -\u003e felt252 {\n    if n == 0 {\n        a\n    } else {\n        fib(b, a+b, n-1)\n    }\n}\n\nfn main() {\n    let x = fib(1,1,3);\n    x.print();\n}\n```\n\n---\n\n### Mutability\n\n```rust\nuse debug::PrintTrait;\nfn main() {\n    let x = 5;\n    x.print();\n    x = 6;  // compile error\n    x.print();\n}\n```\n\n```rust\nuse debug::PrintTrait;\nfn main() {\n    let mut x = 5;\n    x.print();\n    x = 6;  // OK\n    x.print();\n}\n```\n\n---\n\n### Types\n\nScalar types\n\n- Felt type : `felt252`\n- Integer type : `u8`, `u16`, `u32`, `u64`, `u128`, `u256`, `usize`\n- Boolean : `bool`\n- 'strings' : `felt252`\n- unit: `()`\n---\n\n### Casting\n\n```rust\nuse traits::TryInto;\nuse option::OptionTrait;\nfn main() {\n    let x: felt252 = 3;\n    let y: u32 = x.try_into().unwrap();\n}\n```\n---\n\n### Functions\n\n```rust\nuse debug::PrintTrait;\n\nfn another_function() {\n    'Another function.'.print();\n}\n\nfn main() {\n    'Hello, world!'.print();\n    another_function();\n}\n```\n\n---\n#### Named parameters\n\n```rust\nfn foo(x: u8, y: u8) {}\n\nfn main() {\n    let first_arg = 3;\n    let second_arg = 4;\n    foo(x: first_arg, y: second_arg);\n    let x = 1;\n    let y = 2;\n    foo(:x, :y)\n}\n```\n\n---\n#### Return values\n\nA function 'is an expression'\n\n```rust\nuse debug::PrintTrait;\n\nfn main() {\n    let x = plus_one(5);\n\n    x.print();\n}\n\nfn plus_one(x: u32) -\u003e u32 {\n    x + 1\n}\n```\n\n---\n### Control flow\n#### if else\n\n```rust\nuse debug::PrintTrait;\n\nfn main() {\n    let number = 3;\n\n    if number == 12 {\n        'number is 12'.print();\n    } else if number == 3 {\n        'number is 3'.print();\n    } else if number - 2 == 1 {\n        'number minus 2 is 1'.print();\n    } else {\n        'number not found'.print();\n    }\n}\n```\n\n\nNote: 'if' is an expression!\n\n```rust\nif true { 42 } else { 0 } == 42\n```\n\n---\n#### Loops\n\n```rust\nuse debug::PrintTrait;\nfn main() {\n    let mut i: usize = 0;\n    loop {\n        if i \u003e 10 {\n            break;\n        }\n        if i == 5 {\n            i += 1;\n            continue;\n        }\n        i.print();\n        i += 1;\n    }\n}\n```\n\n---\n\n### Structs\n\n```rust\nstruct User {\n    active: bool,\n    username: felt252,\n    email: felt252,\n    sign_in_count: u64,\n}\n```\n---\n\n### Arrays\n\n```rust\nuse array::ArrayTrait;\n\nfn main() {\n    let mut a = ArrayTrait::new();\n    a.append(0);\n    a.append(1);\n    a.append(2);\n}\n```\n```rust\nlet first_value = a.pop_front().unwrap();\n```\n\n\n```rust\nuse array::ArrayTrait;\nfn main() {\n    let mut a = ArrayTrait::new();\n    a.append(0);\n    a.append(1);\n\n    let first = *a.at(0);\n    let second = *a.at(1);\n}\n```\n```rust\nuse array::ArrayTrait;\nuse box::BoxTrait;\nfn main() -\u003e u128 {\n    let mut arr = ArrayTrait::\u003cu128\u003e::new();\n    arr.append(100);\n    let index_to_access =\n        1; // Change this value to see different results, what would happen if the index doesn't exist?\n    match arr.get(index_to_access) {\n        Option::Some(x) =\u003e {\n            *x.unbox()\n        // Don't worry about * for now, if you are curious see Chapter 3.2 #desnap operator\n        // It basically means \"transform what get(idx) returned into a real value\"\n        },\n        Option::None(_) =\u003e {\n            let mut data = ArrayTrait::new();\n            data.append('out of bounds');\n            panic(data)\n        }\n    }\n}\n```\n---\n\n### Dictionaries\n\n```rust\nuse dict::Felt252DictTrait;\n\nfn main() {\n    let mut balances: Felt252Dict\u003cu64\u003e = Default::default();\n\n    balances.insert('Alex', 100);\n\n    let alex_balance = balances.get('Alex');\n    assert(alex_balance == 100, 'Balance is not 100');\n}\n```\n\n---\n\n### Ownership\n\n```\n{\n  let s = ...;\n}\n```\n\n- `s` is always 'owned'\n- When `s` comes into scope, it is valid.\n- It remains valid until it goes out of scope.\n\n\nIf `s` is passed to a function it is moved.\nHowever, if `s` implements `Copy` it is copied.\n\n---\n\n### Snapshot\n\nA snapshot is an immutable instance of a variable.\n```\nlet v = ...;\nlet snapshot_v = @v;\n\nlet modifiablevalue = *snapshot_v;\n```\n\nA function must explicitely specify the snapshot type to accept snapshots.\n\n```\nfn mod(arg: @ArgType) {\n}\n```\n\n---\n\n\n\n\n## Toolchain characteristics\n\n### Scarb\n\n- Build tool, package manager\n- Includes Cairo compiler\n\n### Starkli\n\n- Starknet CLI utility - contract declaration \u0026 deployment\n\n### VSCode Extension\n\n- Syntax highlighting\n- Scarb integration\n- Code formatter\n- Dev productivity aids\n\n### Starknet Foundry\n\n- Dev, build \u0026 test toolpack\n\n### Devnet\n\n- Emulated Starknet \"instance\"\n\n### Remix (with Starknet plugin)\n\n- Online IDE with Cairo syntax highlighting\n- Online compilation\n- Contract declaration, deployment \u0026 interaction\n- Devnet \u0026 Wallet integration\n\n## Learning resources\n\n  - Cairo book (https://book.cairo-lang.org/)\n  - Starklings (https://github.com/shramee/starklings-cairo1.git)\n  - Starknet by Example (https://starknet-by-example.voyager.online/)\n  - Cairo by Example (https://cairo-by-example.com/)\n  - Exercism (https://exercism.org/tracks/cairo)\n  - Node Guardians (https://nodeguardians.io/) - WIP\n\n## Starklings\n\nJust follow Starklings exercises.\n\n## Let's play! (with Remix IDE)\n\n1. Open Remix with Starknet and GitHub repo\n    \n    https://remix.ethereum.org/?#activate=Starknet\u0026call=Starknet//loadFolderFromGithub//NethermindEth/cairo-workshop//\n\n2. Select a smart contract code file\n3. Go to Starknet plugin panel, run Compile \n4. Go to Environments panel at the top (one with \"Remote Devnet\" selected) - press to drop down and select one random account from the list\n5. Go back to Starknet plugin panel, in Deploy section run Declare\n6. Once declare step completes, fill in the constructor parameters and run Deploy\n7. Go to Interact section, call/invoke contract methods\n\n## Go to testnet\n\n### Create testnet account using a wallet\n1. Open a Starknet wallet (eg. Braavos)\n2. Select \"Add account\" and create a new account record in wallet - note the new account address\n3. Switch the wallet to Testnet (Sepolia) network\n4. Fund the account (eg. from wallet via testnet faucet - https://starknet-faucet.vercel.app/)\n5. Deploy the account to the network\n6. View the account in block explorer (eg. Voyager, https://sepolia.voyager.online/contract/\u003ccontact_address\u003e)\n\n### Put contract on testnet\n\n1. In Remix Starknet plugin, in the Environments panel, select Wallet \n2. Connect to preferred wallet\n3. Go to plugin Deploy section, run Declare for selected Wallet account\n4. Fill in contract constructor parameters if required\n5. Run Deploy\n6. Go to Interact section, call/invoke contract methods\n\n## Unit testing\n\n1. In command line, in cairo-workshop folder, run `scarb build` to build all contracts in project\n2. Run `scarb test` to see unit tests run\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnethermindeth%2Fcairo-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnethermindeth%2Fcairo-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnethermindeth%2Fcairo-workshop/lists"}