Skip to content

Commit

Permalink
feat: Cairo cheat sheet (#104)
Browse files Browse the repository at this point in the history
* implemented match and loop

* added array, felt and casting

* added events and struct

* updated felt syntax

* resolved all corrections

* chore: revisions

* Update type_casting.md

---------

Co-authored-by: julio4 <jules.doumeche@gmail.com>
  • Loading branch information
Nonnyjoe and julio4 authored Oct 31, 2023
1 parent 88f5545 commit 0d79abb
Show file tree
Hide file tree
Showing 19 changed files with 344 additions and 0 deletions.
1 change: 1 addition & 0 deletions listings/ch00-getting-started/cairo_cheatsheet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
6 changes: 6 additions & 0 deletions listings/ch00-getting-started/cairo_cheatsheet/Scarb.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Code generated by scarb DO NOT EDIT.
version = 1

[[package]]
name = "cairo_cheatsheet"
version = "0.1.0"
8 changes: 8 additions & 0 deletions listings/ch00-getting-started/cairo_cheatsheet/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "cairo_cheatsheet"
version = "0.1.0"

[dependencies]
starknet = ">=2.3.0"

[[target.starknet-contract]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[starknet::contract]
mod arrayExample {
#[storage]
struct Storage {}


#[external(v0)]
#[generate_trait]
impl external of externalTrait {
fn createArray(self: @ContractState, numOne: u32, numTwo: u32, numThree: u32) -> bool {
let mut Arr = ArrayTrait::<u32>::new();
Arr.append(numOne);
Arr.append(numTwo);
Arr.append(numThree);

let ArrLength: usize = Arr.len();
assert(ArrLength == 3, 'Array Length should be 3');

let first_value = Arr.pop_front().unwrap();
assert(first_value == numOne, 'Both values should match');

let second_value = *Arr.at(0);
assert(second_value == numTwo, 'Both values should match too');

//Returns true if an array is empty, then false if it isn't.
Arr.is_empty()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[starknet::contract]
mod feltExample {
use starknet::{ContractAddress, get_caller_address};

#[storage]
struct Storage {
userName: LegacyMap::<ContractAddress, felt252>,
}

#[external(v0)]
#[generate_trait]
impl external of externlalTrait {
fn storeName(ref self: ContractState, name: felt252) -> felt252 {
self.userName.write(get_caller_address(), name);

let welcomeMsg: felt252 = 'Welcome to StarknetByExample';
welcomeMsg
}

fn viewName(self: @ContractState, Add: ContractAddress) -> felt252 {
self.userName.read(Add)
}
}
}
7 changes: 7 additions & 0 deletions listings/ch00-getting-started/cairo_cheatsheet/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod array_example;
mod mapping_example;
mod felt_example;
mod loop_example;
mod match_example;
mod struct_example;
mod type_casting_example;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#[starknet::contract]
mod loopExample {
#[storage]
struct Storage {}

#[external(v0)]
#[generate_trait]
impl external of externlalTrait {
fn gatherEvens(ref self: ContractState, maxLimit: u32) -> Array<u32> {
let mut i: u32 = 0;
let mut Arr = ArrayTrait::new();
loop {
if i == maxLimit {
break;
};
if (i % 2 == 0) {
Arr.append(i);
}
i += 1;
};

return Arr;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#[starknet::contract]
mod mappingContract {
use starknet::ContractAddress;

#[storage]
struct Storage {
studentsName: LegacyMap::<ContractAddress, felt252>,
studentsResultRecord: LegacyMap::<(ContractAddress, felt252), u16>,
}

#[external(v0)]
#[generate_trait]
impl external of externalTrait {
fn registerUser(
ref self: ContractState, studentAdd: ContractAddress, studentName: felt252
) {
self.studentsName.write(studentAdd, studentName);
}

fn recordStudentScore(
ref self: ContractState, studentAdd: ContractAddress, Subject: felt252, score: u16
) {
self.studentsResultRecord.write((studentAdd, Subject), score);
}

fn viewStudentName(self: @ContractState, studentAdd: ContractAddress) -> felt252 {
self.studentsName.read(studentAdd)
}

fn viewStudentScore(
self: @ContractState, studentAdd: ContractAddress, Subject: felt252
) -> u16 {
// for a 2D mapping its important to take note of the amount of brackets being used.
self.studentsResultRecord.read((studentAdd, Subject))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#[starknet::contract]
mod matchExample {
#[storage]
struct Storage {}

#[derive(Drop, Serde)]
enum Colour {
Red,
Blue,
Green,
Orange,
Black
}

#[derive(Drop, Serde)]
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}

#[external(v0)]
#[generate_trait]
impl external of externlalTrait {
fn value_in_cents(self: @ContractState, coin: Coin) -> felt252 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}

fn specified_colour(self: @ContractState, colour: Colour) -> felt252 {
let mut response: felt252 = '';

match colour {
Colour::Red => { response = 'You passed in Red'; },
Colour::Blue => { response = 'You passed in Blue'; },
Colour::Green => { response = 'You passed in Green'; },
Colour::Orange => { response = 'You passed in Orange'; },
Colour::Black => { response = 'You passed in Black'; },
};

response
}

fn quiz(self: @ContractState, num: felt252) -> felt252 {
let mut response: felt252 = '';

match num {
0 => { response = 'You failed' },
_ => { response = 'You Passed' },
};

response
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#[starknet::contract]
mod StructExample {
use starknet::{ContractAddress, get_caller_address};

#[storage]
struct Storage {
userData: data
}

#[derive(Drop, starknet::Store)]
struct data {
Add: ContractAddress,
Age: u8
}

#[external(v0)]
#[generate_trait]
impl StoreStructImpl of IStoreStructContract {
fn store_struct(ref self: ContractState, age: u8) {
let newStruct = data { Add: get_caller_address(), Age: age };
self.userData.write(newStruct);
}

fn read_struct(self: @ContractState) -> (ContractAddress, u8) {
let lastUser = self.userData.read();
let add = lastUser.Add;
let age = lastUser.Age;
(add, age)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#[starknet::contract]
mod typecasting_Example {
#[storage]
struct Storage {}

#[external(v0)]
#[generate_trait]
impl external of externlalTrait {
fn typeCasting(self: @ContractState, randNumber: u32) {
let my_felt252 = 15;

// Since a u32 might not fit in a u8 and a u16, we need to use try_into,
// then unwrap the Option<T> type thats returned.
let new_u8: u8 = randNumber.try_into().unwrap();
let new_u16: u16 = randNumber.try_into().unwrap();

// since new_u32 is the of the same type (u32) as randNumber, we can directly assign them,
// or use the .into() method.
let new_u32: u32 = randNumber;

// When typecasting from a smaller size to an equal or larger size we use the .into() method.
// Note: u64 and u128 are larger than u32, so a u32 type will always fit into them.
let new_u64: u64 = randNumber.into();
let new_u128: u128 = randNumber.into();

// Since a felt252 is smaller than a u256, we can use the into() method
let new_u256: u256 = my_felt252.into();
let new_felt252: felt252 = new_u16.into();

//note a usize is smaller than a felt so we use the try_into
let new_usize: usize = my_felt252.try_into().unwrap();
}
}
}
8 changes: 8 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ Summary
<!-- ch00 -->
# Getting Started
<!-- - [Local environnement setup](./ch00/env_setup.md) -->
- [Cairo cheatsheet](./ch00/cairo_cheatsheet/)
- [Felt](./ch00/cairo_cheatsheet/felt.md)
- [Mapping](./ch00/cairo_cheatsheet/mapping.md)
- [Arrays](./ch00/cairo_cheatsheet/arrays.md)
- [Loop](./ch00/cairo_cheatsheet/loop.md)
- [Match](./ch00/cairo_cheatsheet/match.md)
- [Struct](./ch00/cairo_cheatsheet/struct.md)
- [Type casting](./ch00/cairo_cheatsheet/type_casting.md)
- [Basics of a Starknet contract](./ch00/basics/introduction.md)
- [Variables](./ch00/basics/variables.md)
- [Constructor](./ch00/basics/constructor.md)
Expand Down
24 changes: 24 additions & 0 deletions src/ch00/cairo_cheatsheet/arrays.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Arrays

Arrays are collections of elements of the same type.
The possible operations on arrays are defined with the `array::ArrayTrait` of the corelib:

```rust
trait ArrayTrait<T> {
fn new() -> Array<T>;
fn append(ref self: Array<T>, value: T);
fn pop_front(ref self: Array<T>) -> Option<T> nopanic;
fn pop_front_consume(self: Array<T>) -> Option<(Array<T>, T)> nopanic;
fn get(self: @Array<T>, index: usize) -> Option<Box<@T>>;
fn at(self: @Array<T>, index: usize) -> @T;
fn len(self: @Array<T>) -> usize;
fn is_empty(self: @Array<T>) -> bool;
fn span(self: @Array<T>) -> Span<T>;
}
```

For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo}}
```
10 changes: 10 additions & 0 deletions src/ch00/cairo_cheatsheet/felt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Felt252

Felt252 is a fundamental data type in Cairo from which all other data types are derived.
Felt252 can also be used to store short-string representations with a maximum length of 31 characters.

For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/felt_example.cairo}}
```
8 changes: 8 additions & 0 deletions src/ch00/cairo_cheatsheet/loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Loop

A loop specifies a block of code that will run repetitively until a halting condition is encountered.
For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/loop_example.cairo}}
```
7 changes: 7 additions & 0 deletions src/ch00/cairo_cheatsheet/mapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Mapping

The ```LegacyMap``` type can be used to represent a collection of key-value.

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/mapping_example.cairo}}
```
8 changes: 8 additions & 0 deletions src/ch00/cairo_cheatsheet/match.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Match

The "match" expression in Cairo allows us to control the flow of our code by comparing a felt data type or an enum against various patterns and then running specific code based on the pattern that matches.
For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/match_example.cairo}}
```
8 changes: 8 additions & 0 deletions src/ch00/cairo_cheatsheet/struct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Struct

A struct is a data type similar to tuple. Like tuples they can be used to hold data of different types.
For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/struct_example.cairo}}
```
9 changes: 9 additions & 0 deletions src/ch00/cairo_cheatsheet/type_casting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Type casting

Cairo supports the conversion from one scalar types to another by using the into and try_into methods.
`traits::Into` is used for conversion from a smaller data type to a larger data type, while `traits::TryInto` is used when converting from a larger to a smaller type that might not fit.
For example:

```rust
{{#include ../../../listings/ch00-getting-started/cairo_cheatsheet/src/type_casting_example.cairo}}
```

0 comments on commit 0d79abb

Please sign in to comment.