From badf4dbdf5fbb669b3786925ebea25a667ecf2d6 Mon Sep 17 00:00:00 2001 From: Julio <30329843+julio4@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:37:59 +0700 Subject: [PATCH 01/13] Prepare release 2.8.2 (#257) * dep: fix patch to latest shikijs for cairo hl * fix(app): correct sidebar placement * fix(app): responsive content centering * fix(app): responsive content centering * doc: branch guidelines * fix(app): top section nav links --- CONTRIBUTING.md | 6 + package.json | 8 + patches/vocs.patch | 1416 ++------------------------------------------ pnpm-lock.yaml | 135 +++-- routes.ts | 4 - styles.css | 95 +-- 6 files changed, 183 insertions(+), 1481 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ac94b34..0543b466 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,12 @@ When contributing to this repository, please first discuss the change you wish t Join the telegram channel: https://t.me/StarknetByExample +The release branch is `main`. The development branch is `dev` and is considered stable (but not released yet). +When you want to contribute, please create a new branch from `dev` and open a pull request to merge your changes back into `dev`. +You should never open a pull request to merge your changes directly into `main`. + +The `dev` branch is deployed at https://starknet-by-example-dev.voyager.online/ + Please note we have a code of conduct, please follow it in all your interactions with the project. ## Table of Contents diff --git a/package.json b/package.json index 032ce81a..4d683183 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,14 @@ "pnpm": { "patchedDependencies": { "vocs": "patches/vocs.patch" + }, + "overrides": { + "vocs>shiki": "^1.23.0", + "vocs>@shikijs/core": "^1.23.0", + "vocs>@shikijs/types": "^1.23.0", + "vocs>@shikijs/rehype": "^1.23.0", + "vocs>@shikijs/twoslash": "^1.23.0", + "vocs>@shikijs/transformers": "^1.23.0" } } } diff --git a/patches/vocs.patch b/patches/vocs.patch index 0bd0899a..db1208c9 100644 --- a/patches/vocs.patch +++ b/patches/vocs.patch @@ -1,1394 +1,46 @@ -diff --git a/_lib/vite/plugins/cairo.json b/_lib/vite/plugins/cairo.json -new file mode 100644 -index 0000000000000000000000000000000000000000..9078642c2c1dc8b472469c269619b1898734459c ---- /dev/null -+++ b/_lib/vite/plugins/cairo.json -@@ -0,0 +1,996 @@ -+{ -+ "credits": "Pulled from: https://raw.githubusercontent.com/starkware-libs/cairo/main/vscode-cairo/syntaxes/cairo.tmLanguage.json. This grammar is heavily modified Rust grammar from VSCode repository: https://github.com/microsoft/vscode/blob/11f415d4d77f7739c202905ccd02e27774146b75/extensions/rust/syntaxes/rust.tmLanguage.json", -+ "name": "Cairo", -+ "scopeName": "source.cairo", -+ "patterns": [ -+ { -+ "comment": "boxed slice literal", -+ "begin": "(<)(\\[)", -+ "beginCaptures": { -+ "1": { -+ "name": "punctuation.brackets.angle.cairo" -+ }, -+ "2": { -+ "name": "punctuation.brackets.square.cairo" -+ } -+ }, -+ "end": ">", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.angle.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#types" -+ } -+ ] -+ }, -+ { -+ "comment": "modules", -+ "match": "(mod)\\s+([a-z][A-Za-z0-9_]*)", -+ "captures": { -+ "1": { -+ "name": "storage.type.cairo" -+ }, -+ "2": { -+ "name": "entity.name.module.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "use statements", -+ "name": "meta.use.cairo", -+ "begin": "\\b(use)\\s", -+ "beginCaptures": { -+ "1": { -+ "name": "keyword.other.cairo" -+ } -+ }, -+ "end": ";", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.semi.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#namespaces" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#lvariables" -+ } -+ ] -+ }, -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#attributes" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#constants" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#functions" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#macros" -+ }, -+ { -+ "include": "#namespaces" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#strings" -+ }, -+ { -+ "include": "#variables" -+ } -+ ], -+ "repository": { -+ "comments": { -+ "patterns": [ -+ { -+ "comment": "documentation comments", -+ "name": "comment.line.documentation.cairo", -+ "match": "(///).*$", -+ "captures": { -+ "1": { -+ "name": "punctuation.definition.comment.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "line comments", -+ "name": "comment.line.double-slash.cairo", -+ "match": "(//).*$", -+ "captures": { -+ "1": { -+ "name": "punctuation.definition.comment.cairo" -+ } -+ } -+ } -+ ] -+ }, -+ "block-comments": { -+ "patterns": [ -+ { -+ "comment": "empty block comments", -+ "name": "comment.block.cairo", -+ "match": "/\\*\\*/" -+ }, -+ { -+ "comment": "block documentation comments", -+ "name": "comment.block.documentation.cairo", -+ "begin": "/\\*\\*", -+ "end": "\\*/", -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ } -+ ] -+ }, -+ { -+ "comment": "block comments", -+ "name": "comment.block.cairo", -+ "begin": "/\\*(?!\\*)", -+ "end": "\\*/", -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ } -+ ] -+ } -+ ] -+ }, -+ "constants": { -+ "patterns": [ -+ { -+ "comment": "ALL CAPS constants", -+ "name": "constant.other.caps.cairo", -+ "match": "\\b[A-Z]{2}[A-Z0-9_]*\\b" -+ }, -+ { -+ "comment": "constant declarations", -+ "match": "\\b(const)\\s+([A-Z][A-Za-z0-9_]*)\\b", -+ "captures": { -+ "1": { -+ "name": "storage.type.cairo" -+ }, -+ "2": { -+ "name": "constant.other.caps.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "decimal integers and floats", -+ "name": "constant.numeric.decimal.cairo", -+ "match": "\\b\\d[\\d_]*(\\.?)[\\d_]*(?:(E|e)([+-]?)([\\d_]+))?(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b", -+ "captures": { -+ "1": { -+ "name": "punctuation.separator.dot.decimal.cairo" -+ }, -+ "2": { -+ "name": "keyword.operator.exponent.cairo" -+ }, -+ "3": { -+ "name": "keyword.operator.exponent.sign.cairo" -+ }, -+ "4": { -+ "name": "constant.numeric.decimal.exponent.mantissa.cairo" -+ }, -+ "5": { -+ "name": "entity.name.type.numeric.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "hexadecimal integers", -+ "name": "constant.numeric.hex.cairo", -+ "match": "\\b0x[\\da-fA-F_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b", -+ "captures": { -+ "1": { -+ "name": "entity.name.type.numeric.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "octal integers", -+ "name": "constant.numeric.oct.cairo", -+ "match": "\\b0o[0-7_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b", -+ "captures": { -+ "1": { -+ "name": "entity.name.type.numeric.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "binary integers", -+ "name": "constant.numeric.bin.cairo", -+ "match": "\\b0b[01_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b", -+ "captures": { -+ "1": { -+ "name": "entity.name.type.numeric.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "booleans", -+ "name": "constant.language.bool.cairo", -+ "match": "\\b(true|false)\\b" -+ } -+ ] -+ }, -+ "escapes": { -+ "comment": "escapes: ASCII, byte, Unicode, quote, regex", -+ "name": "constant.character.escape.cairo", -+ "match": "(\\\\)(?:(?:(x[0-7][\\da-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))", -+ "captures": { -+ "1": { -+ "name": "constant.character.escape.backslash.cairo" -+ }, -+ "2": { -+ "name": "constant.character.escape.bit.cairo" -+ }, -+ "3": { -+ "name": "constant.character.escape.unicode.cairo" -+ }, -+ "4": { -+ "name": "constant.character.escape.unicode.punctuation.cairo" -+ }, -+ "5": { -+ "name": "constant.character.escape.unicode.punctuation.cairo" -+ } -+ } -+ }, -+ "attributes": { -+ "comment": "attributes", -+ "name": "meta.attribute.cairo", -+ "begin": "(#)(\\!?)(\\[)", -+ "beginCaptures": { -+ "1": { -+ "name": "punctuation.definition.attribute.cairo" -+ }, -+ "3": { -+ "name": "punctuation.brackets.attribute.cairo" -+ } -+ }, -+ "end": "\\]", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.attribute.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#strings" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#types" -+ } -+ ] -+ }, -+ "functions": { -+ "patterns": [ -+ { -+ "comment": "pub as a function", -+ "match": "\\b(pub)(\\()", -+ "captures": { -+ "1": { -+ "name": "keyword.other.cairo" -+ }, -+ "2": { -+ "name": "punctuation.brackets.round.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "function definition", -+ "name": "meta.function.definition.cairo", -+ "begin": "\\b(fn)\\s+([A-Za-z0-9_]+)((\\()|(<))", -+ "beginCaptures": { -+ "1": { -+ "name": "keyword.other.fn.cairo" -+ }, -+ "2": { -+ "name": "entity.name.function.cairo" -+ }, -+ "4": { -+ "name": "punctuation.brackets.round.cairo" -+ }, -+ "5": { -+ "name": "punctuation.brackets.angle.cairo" -+ } -+ }, -+ "end": "\\{|;", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.curly.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#constants" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#functions" -+ }, -+ { -+ "include": "#macros" -+ }, -+ { -+ "include": "#namespaces" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#strings" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#variables" -+ } -+ ] -+ }, -+ { -+ "comment": "function/method calls, chaining", -+ "name": "meta.function.call.cairo", -+ "begin": "([A-Za-z0-9_]+)(\\()", -+ "beginCaptures": { -+ "1": { -+ "name": "entity.name.function.cairo" -+ }, -+ "2": { -+ "name": "punctuation.brackets.round.cairo" -+ } -+ }, -+ "end": "\\)", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.round.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#attributes" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#constants" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#functions" -+ }, -+ { -+ "include": "#macros" -+ }, -+ { -+ "include": "#namespaces" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#strings" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#variables" -+ } -+ ] -+ }, -+ { -+ "comment": "function/method calls with turbofish", -+ "name": "meta.function.call.cairo", -+ "begin": "([A-Za-z0-9_]+)(?=::<.*>\\()", -+ "beginCaptures": { -+ "1": { -+ "name": "entity.name.function.cairo" -+ } -+ }, -+ "end": "\\)", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.round.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#attributes" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#constants" -+ }, -+ { -+ "include": "#gtypes" -+ }, -+ { -+ "include": "#functions" -+ }, -+ { -+ "include": "#lifetimes" -+ }, -+ { -+ "include": "#macros" -+ }, -+ { -+ "include": "#namespaces" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#strings" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#variables" -+ } -+ ] -+ } -+ ] -+ }, -+ "keywords": { -+ "patterns": [ -+ { -+ "comment": "control flow keywords", -+ "name": "keyword.control.cairo", -+ "match": "\\b(break|continue|do|else|for|if|loop|match|return|try|while|yield)\\b" -+ }, -+ { -+ "comment": "storage keywords", -+ "name": "keyword.other.cairo storage.type.cairo", -+ "match": "\\b(extern|let|macro|mod)\\b" -+ }, -+ { -+ "comment": "const keyword", -+ "name": "storage.modifier.cairo", -+ "match": "\\b(const)\\b" -+ }, -+ { -+ "comment": "type keyword", -+ "name": "keyword.declaration.type.cairo storage.type.cairo", -+ "match": "\\b(type)\\b" -+ }, -+ { -+ "comment": "enum keyword", -+ "name": "keyword.declaration.enum.cairo storage.type.cairo", -+ "match": "\\b(enum)\\b" -+ }, -+ { -+ "comment": "trait keyword", -+ "name": "keyword.declaration.trait.cairo storage.type.cairo", -+ "match": "\\b(trait)\\b" -+ }, -+ { -+ "comment": "struct keyword", -+ "name": "keyword.declaration.struct.cairo storage.type.cairo", -+ "match": "\\b(struct)\\b" -+ }, -+ { -+ "comment": "storage modifiers", -+ "name": "storage.modifier.cairo", -+ "match": "\\b(ref|static)\\b" -+ }, -+ { -+ "comment": "other keywords", -+ "name": "keyword.other.cairo", -+ "match": "\\b(as|dyn|move|impl|implicits|in|nopanic|of|priv|pub|static_assert|typeof|unsafe|use|where|with)\\b" -+ }, -+ { -+ "comment": "fn", -+ "name": "keyword.other.fn.cairo", -+ "match": "\\bfn\\b" -+ }, -+ { -+ "comment": "crate", -+ "name": "keyword.other.crate.cairo", -+ "match": "\\bcrate\\b" -+ }, -+ { -+ "comment": "mut", -+ "name": "storage.modifier.mut.cairo", -+ "match": "\\bmut\\b" -+ }, -+ { -+ "comment": "logical operators", -+ "name": "keyword.operator.logical.cairo", -+ "match": "(\\^|\\||\\|\\||&&|<<|>>|!)(?!=)" -+ }, -+ { -+ "comment": "logical AND, borrow references", -+ "name": "keyword.operator.borrow.and.cairo", -+ "match": "&(?![&=])" -+ }, -+ { -+ "comment": "assignment operators", -+ "name": "keyword.operator.assignment.cairo", -+ "match": "(\\+=|-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)" -+ }, -+ { -+ "comment": "single equal", -+ "name": "keyword.operator.assignment.equal.cairo", -+ "match": "(?])=(?!=|>)" -+ }, -+ { -+ "comment": "comparison operators", -+ "name": "keyword.operator.comparison.cairo", -+ "match": "(=(=)?(?!>)|!=|<=|(?=)" -+ }, -+ { -+ "comment": "math operators", -+ "name": "keyword.operator.math.cairo", -+ "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))" -+ }, -+ { -+ "comment": "less than, greater than (special case)", -+ "match": "(?:\\b|(?:(\\))|(\\])|(\\})))[ \\t]+([<>])[ \\t]+(?:\\b|(?:(\\()|(\\[)|(\\{)))", -+ "captures": { -+ "1": { -+ "name": "punctuation.brackets.round.cairo" -+ }, -+ "2": { -+ "name": "punctuation.brackets.square.cairo" -+ }, -+ "3": { -+ "name": "punctuation.brackets.curly.cairo" -+ }, -+ "4": { -+ "name": "keyword.operator.comparison.cairo" -+ }, -+ "5": { -+ "name": "punctuation.brackets.round.cairo" -+ }, -+ "6": { -+ "name": "punctuation.brackets.square.cairo" -+ }, -+ "7": { -+ "name": "punctuation.brackets.curly.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "namespace operator", -+ "name": "keyword.operator.namespace.cairo", -+ "match": "::" -+ }, -+ { -+ "comment": "desnap", -+ "match": "(\\*)(?=\\w+)", -+ "captures": { -+ "1": { -+ "name": "keyword.operator.desnap.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "snap", -+ "name": "keyword.operator.snap.cairo", -+ "match": "@" -+ }, -+ { -+ "comment": "dot access", -+ "name": "keyword.operator.access.dot.cairo", -+ "match": "\\.(?!\\.)" -+ }, -+ { -+ "comment": "ranges, range patterns", -+ "name": "keyword.operator.range.cairo", -+ "match": "\\.{2}(=|\\.)?" -+ }, -+ { -+ "comment": "colon", -+ "name": "keyword.operator.key-value.cairo", -+ "match": ":(?!:)" -+ }, -+ { -+ "comment": "dashrocket, skinny arrow", -+ "name": "keyword.operator.arrow.skinny.cairo", -+ "match": "->" -+ }, -+ { -+ "comment": "hashrocket, fat arrow", -+ "name": "keyword.operator.arrow.fat.cairo", -+ "match": "=>" -+ }, -+ { -+ "comment": "dollar macros", -+ "name": "keyword.operator.macro.dollar.cairo", -+ "match": "\\$" -+ }, -+ { -+ "comment": "question mark operator, questionably sized, macro kleene matcher", -+ "name": "keyword.operator.question.cairo", -+ "match": "\\?" -+ } -+ ] -+ }, -+ "interpolations": { -+ "comment": "curly brace interpolations", -+ "name": "meta.interpolation.cairo", -+ "match": "({)[^\"{}]*(})", -+ "captures": { -+ "1": { -+ "name": "punctuation.definition.interpolation.cairo" -+ }, -+ "2": { -+ "name": "punctuation.definition.interpolation.cairo" -+ } -+ } -+ }, -+ "macros": { -+ "patterns": [ -+ { -+ "comment": "macros", -+ "name": "meta.macro.cairo", -+ "match": "(([a-z_][A-Za-z0-9_]*!)|([A-Z_][A-Za-z0-9_]*!))", -+ "captures": { -+ "2": { -+ "name": "entity.name.function.macro.cairo" -+ }, -+ "3": { -+ "name": "entity.name.type.macro.cairo" -+ } -+ } -+ } -+ ] -+ }, -+ "namespaces": { -+ "patterns": [ -+ { -+ "comment": "namespace (non-type, non-function path segment)", -+ "match": "(?", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.brackets.angle.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#block-comments" -+ }, -+ { -+ "include": "#comments" -+ }, -+ { -+ "include": "#keywords" -+ }, -+ { -+ "include": "#lvariables" -+ }, -+ { -+ "include": "#punctuation" -+ }, -+ { -+ "include": "#types" -+ }, -+ { -+ "include": "#variables" -+ } -+ ] -+ }, -+ { -+ "comment": "primitive types", -+ "name": "entity.name.type.primitive.cairo", -+ "match": "\\b(bool|never)\\b" -+ }, -+ { -+ "comment": "trait declarations", -+ "match": "\\b(trait)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", -+ "captures": { -+ "1": { -+ "name": "keyword.declaration.trait.cairo storage.type.cairo" -+ }, -+ "2": { -+ "name": "entity.name.type.trait.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "struct declarations", -+ "match": "\\b(struct)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", -+ "captures": { -+ "1": { -+ "name": "keyword.declaration.struct.cairo storage.type.cairo" -+ }, -+ "2": { -+ "name": "entity.name.type.struct.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "enum declarations", -+ "match": "\\b(enum)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", -+ "captures": { -+ "1": { -+ "name": "keyword.declaration.enum.cairo storage.type.cairo" -+ }, -+ "2": { -+ "name": "entity.name.type.enum.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "type declarations", -+ "match": "\\b(type)\\s+(_?[A-Z][A-Za-z0-9_]*)\\b", -+ "captures": { -+ "1": { -+ "name": "keyword.declaration.type.cairo storage.type.cairo" -+ }, -+ "2": { -+ "name": "entity.name.type.declaration.cairo" -+ } -+ } -+ }, -+ { -+ "comment": "types", -+ "name": "entity.name.type.cairo", -+ "match": "\\b_?[A-Z][A-Za-z0-9_]*\\b(?!!)" -+ } -+ ] -+ }, -+ "gtypes": { -+ "patterns": [ -+ { -+ "comment": "option types", -+ "name": "entity.name.type.option.cairo", -+ "match": "\\b(Some|None)\\b" -+ }, -+ { -+ "comment": "result types", -+ "name": "entity.name.type.result.cairo", -+ "match": "\\b(Ok|Err)\\b" -+ } -+ ] -+ }, -+ "punctuation": { -+ "patterns": [ -+ { -+ "comment": "comma", -+ "name": "punctuation.comma.cairo", -+ "match": "," -+ }, -+ { -+ "comment": "curly braces", -+ "name": "punctuation.brackets.curly.cairo", -+ "match": "[{}]" -+ }, -+ { -+ "comment": "parentheses, round brackets", -+ "name": "punctuation.brackets.round.cairo", -+ "match": "[()]" -+ }, -+ { -+ "comment": "semicolon", -+ "name": "punctuation.semi.cairo", -+ "match": ";" -+ }, -+ { -+ "comment": "square brackets", -+ "name": "punctuation.brackets.square.cairo", -+ "match": "[\\[\\]]" -+ }, -+ { -+ "comment": "angle brackets", -+ "name": "punctuation.brackets.angle.cairo", -+ "match": "(?]" -+ } -+ ] -+ }, -+ "strings": { -+ "patterns": [ -+ { -+ "comment": "double-quoted byte array strings", -+ "name": "string.quoted.double.cairo", -+ "begin": "(\")", -+ "beginCaptures": { -+ "1": { -+ "name": "punctuation.definition.string.bytearray.cairo" -+ } -+ }, -+ "end": "\"", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.definition.string.bytearray.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#escapes" -+ }, -+ { -+ "include": "#interpolations" -+ } -+ ] -+ }, -+ { -+ "comment": "single-quoted short strings", -+ "name": "string.quoted.single.cairo", -+ "begin": "(')", -+ "beginCaptures": { -+ "1": { -+ "name": "punctuation.definition.string.short.cairo" -+ } -+ }, -+ "end": "'", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.definition.string.short.cairo" -+ } -+ }, -+ "patterns": [ -+ { -+ "include": "#escapes" -+ }, -+ { -+ "include": "#interpolations" -+ } -+ ] -+ } -+ ] -+ }, -+ "lvariables": { -+ "patterns": [ -+ { -+ "comment": "super", -+ "name": "variable.language.super.cairo", -+ "match": "\\bsuper\\b" -+ } -+ ] -+ }, -+ "variables": { -+ "patterns": [ -+ { -+ "comment": "variables", -+ "name": "variable.other.cairo", -+ "match": "\\b(? [ -- remarkDirective, -- remarkInferFrontmatter, -- remarkFrontmatter, -- remarkMdxFrontmatter, -- remarkGfm, -- remarkLinks, -- remarkBlogPosts, -- remarkCallout, -- remarkCode, -- remarkCodeGroup, -- remarkDetails, -- remarkFilename, -- remarkSponsors, -- remarkSteps, -- remarkStrongBlock, -- remarkSubheading, -- remarkTwoslash, -- remarkAuthors, -- ...(markdown?.remarkPlugins || []), -+ remarkDirective, -+ remarkInferFrontmatter, -+ remarkFrontmatter, -+ remarkMdxFrontmatter, -+ remarkGfm, -+ remarkLinks, -+ remarkBlogPosts, -+ remarkCallout, -+ remarkCode, -+ remarkCodeGroup, -+ remarkDetails, -+ remarkFilename, -+ remarkSponsors, -+ remarkSteps, -+ remarkStrongBlock, -+ remarkSubheading, -+ remarkTwoslash, -+ remarkAuthors, -+ ...(markdown?.remarkPlugins || []), - ]; - const defaultThemes = { -- dark: 'github-dark-dimmed', -- light: 'github-light', -+ dark: "github-dark-dimmed", -+ light: "github-light", - }; --export const getRehypePlugins = ({ markdown, rootDir = '', twoslash = {}, } = {}) => [ -- rehypeSlug, -- [ -- rehypeShiki, -- { -- transformers: [ -- transformerLineNumbers(), -- transformerNotationDiff(), -- transformerNotationFocus(), -- transformerNotationHighlight(), -- transformerNotationWordHighlight(), -- transformerNotationInclude({ rootDir }), -- transformerEmptyLine(), -- transformerTagLine(), -- transformerTitle(), -- twoslash !== false -- ? transformerTwoslash({ -- explicitTrigger: true, -- renderer: twoslashRenderer(), -- twoslasher, -- twoslashOptions: { -- ...twoslash, -- customTags: [ -- 'allowErrors', -- ...(defaultTwoslashOptions.customTags ?? []), -- ...(twoslash.customTags ?? []), -- ], -- compilerOptions: { -- ...(twoslash.compilerOptions ?? {}), -- ...defaultTwoslashOptions.compilerOptions, -- }, -- }, -- }) -- : null, -- transformerSplitIdentifiers(), -- ].filter(Boolean), -- themes: defaultThemes, -- ...markdown?.code, -- }, -- ], -- [ -- rehypeInlineShiki, -- { -- themes: defaultThemes, -- ...markdown?.code, -- }, -- ], -- rehypeShikiDisplayNotation, -- [ -- rehypeAutolinkHeadings, -- { -- behavior: 'append', -- content() { -- return [h('div', { dataAutolinkIcon: true })]; -- }, -- }, -- ], -- ...(markdown?.rehypePlugins || []), -+export const getRehypePlugins = ({ -+ markdown, -+ rootDir = "", -+ twoslash = {}, -+} = {}) => [ -+ rehypeSlug, -+ [ -+ // Patch -+ rehypeShikiFromHighlighter, -+ highlighter, -+ // Patch end -+ { -+ transformers: [ -+ transformerLineNumbers(), -+ transformerNotationDiff(), -+ transformerNotationFocus(), -+ transformerNotationHighlight(), -+ transformerNotationWordHighlight(), -+ transformerNotationInclude({ rootDir }), -+ transformerEmptyLine(), -+ transformerTagLine(), -+ transformerTitle(), -+ twoslash !== false -+ ? transformerTwoslash({ -+ explicitTrigger: true, -+ renderer: twoslashRenderer(), -+ twoslasher, -+ twoslashOptions: { -+ ...twoslash, -+ customTags: [ -+ "allowErrors", -+ ...(defaultTwoslashOptions.customTags ?? []), -+ ...(twoslash.customTags ?? []), -+ ], -+ compilerOptions: { -+ ...(twoslash.compilerOptions ?? {}), -+ ...defaultTwoslashOptions.compilerOptions, -+ }, -+ }, -+ }) -+ : null, -+ transformerSplitIdentifiers(), -+ ].filter(Boolean), -+ themes: defaultThemes, -+ ...markdown?.code, -+ }, -+ ], -+ [ -+ rehypeInlineShiki, -+ { -+ langs, -+ themes: defaultThemes, -+ ...markdown?.code, -+ }, -+ ], -+ rehypeShikiDisplayNotation, -+ [ -+ rehypeAutolinkHeadings, -+ { -+ behavior: "append", -+ content() { -+ return [h("div", { dataAutolinkIcon: true })]; -+ }, -+ }, -+ ], -+ ...(markdown?.rehypePlugins || []), - ]; - export async function mdx() { -- const { config } = await resolveVocsConfig(); -- const { markdown, rootDir, twoslash } = config; -- const remarkPlugins = getRemarkPlugins({ markdown }); -- const rehypePlugins = getRehypePlugins({ markdown, rootDir, twoslash }); -- return [ -- mdxPlugin({ -- providerImportSource: 'vocs/mdx-react', -- remarkPlugins, -- rehypePlugins, -- }), -- ]; -+ const { config } = await resolveVocsConfig(); -+ const { markdown, rootDir, twoslash } = config; -+ const remarkPlugins = getRemarkPlugins({ markdown }); -+ const rehypePlugins = getRehypePlugins({ markdown, rootDir, twoslash }); -+ return [ -+ mdxPlugin({ -+ providerImportSource: "vocs/mdx-react", -+ remarkPlugins, -+ rehypePlugins, -+ }), -+ ]; - } - //# sourceMappingURL=mdx.js.map diff --git a/_lib/vite/plugins/rehype/inline-shiki.js b/_lib/vite/plugins/rehype/inline-shiki.js -index 1e2a7426a5a80afa1bdff24388a8849b49e04f2e..20332be7836e5ca932f59747c3de697430b1d711 100644 +index 1e2a7426a5a80afa1bdff24388a8849b49e04f2e..a8394cddd3968f6c153eed58481a80fb5a8e1b09 100644 --- a/_lib/vite/plugins/rehype/inline-shiki.js +++ b/_lib/vite/plugins/rehype/inline-shiki.js -@@ -1,30 +1,51 @@ --import { bundledLanguages, getSingletonHighlighter } from 'shiki'; --import { visit } from 'unist-util-visit'; -+import { bundledLanguages, getSingletonHighlighter } from "shiki"; -+import { visit } from "unist-util-visit"; - const inlineShikiRegex = /(.*){:(.*)}$/; - let promise; - export const rehypeInlineShiki = function (options = {}) { -- const themeNames = ('themes' in options ? Object.values(options.themes) : [options.theme]).filter(Boolean); -- const langs = options.langs || Object.keys(bundledLanguages); -- return async function (tree) { -- if (!promise) -- promise = getSingletonHighlighter({ -- themes: themeNames, -- langs, -- }); -- const highlighter = await promise; -- return visit(tree, 'element', (node, index, parent) => { +@@ -13,16 +13,33 @@ export const rehypeInlineShiki = function (options = {}) { + }); + const highlighter = await promise; + return visit(tree, 'element', (node, index, parent) => { - if (node.tagName !== 'code') - return; -- const match = node.children[0]?.value?.match(inlineShikiRegex); ++ if (node.tagName !== "code") return; ++ // ignore math ++ const classes = Array.isArray(node.properties.className) ++ ? node.properties.className ++ : []; ++ const languageMath = classes.includes("language-math"); ++ const mathDisplay = classes.includes("math-display"); ++ const mathInline = classes.includes("math-inline"); ++ if (languageMath || mathDisplay || mathInline) { ++ return; ++ } ++ + const match = node.children[0]?.value?.match(inlineShikiRegex); - if (!match) - return; - const [, code, lang] = match; - const hast = highlighter.codeToHast(code, { ...options, lang }); -- const inlineCode = hast.children[0].children[0]; ++ let hast; ++ if (match) { ++ const [, code, lang] = match; ++ hast = highlighter.codeToHast(code, { ...options, lang }); ++ } else { ++ if (!node.children[0] || node.children[0].type !== "text") return; ++ const code = node.children[0].value; ++ hast = highlighter.codeToHast(code, { ++ ...options, ++ lang: "cairo", ++ }); ++ } + const inlineCode = hast.children[0].children[0]; - if (!inlineCode) - return; -- parent?.children.splice(index ?? 0, 1, inlineCode); -+ const themeNames = ( -+ "themes" in options ? Object.values(options.themes) : [options.theme] -+ ).filter(Boolean); -+ const langs = options.langs || Object.keys(bundledLanguages); -+ return async function (tree) { -+ if (!promise) -+ promise = getSingletonHighlighter({ -+ themes: themeNames, -+ langs, -+ }); -+ const highlighter = await promise; -+ return visit(tree, "element", (node, index, parent) => { -+ if (node.tagName !== "code") return; -+ // ignore math -+ const classes = Array.isArray(node.properties.className) -+ ? node.properties.className -+ : []; -+ const languageMath = classes.includes("language-math"); -+ const mathDisplay = classes.includes("math-display"); -+ const mathInline = classes.includes("math-inline"); -+ if (languageMath || mathDisplay || mathInline) { -+ return; -+ } -+ -+ const match = node.children[0]?.value?.match(inlineShikiRegex); -+ if (match) { -+ const [, code, lang] = match; -+ const hast = highlighter.codeToHast(code, { ...options, lang }); -+ const inlineCode = hast.children[0].children[0]; -+ if (!inlineCode) return; -+ parent?.children.splice(index ?? 0, 1, inlineCode); -+ } else { -+ if (!node.children[0] || node.children[0].type !== "text") return; -+ const code = node.children[0].value; -+ const hast = highlighter.codeToHast(code, { -+ ...options, -+ lang: "Cairo", ++ if (!inlineCode) return; + parent?.children.splice(index ?? 0, 1, inlineCode); }); -- }; -+ const inlineCode = hast.children[0].children[0]; -+ if (!inlineCode) return; -+ parent?.children.splice(index ?? 0, 1, inlineCode); -+ } -+ }); -+ }; - }; - //# sourceMappingURL=inline-shiki.js.map + }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c6d19f9..575a437a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,9 +4,17 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + vocs>shiki: ^1.23.0 + vocs>@shikijs/core: ^1.23.0 + vocs>@shikijs/types: ^1.23.0 + vocs>@shikijs/rehype: ^1.23.0 + vocs>@shikijs/twoslash: ^1.23.0 + vocs>@shikijs/transformers: ^1.23.0 + patchedDependencies: vocs: - hash: p6z7kxjkom4q2uemolyyrxbtiy + hash: 7wumpnts656yvepr4seo2mjn34 path: patches/vocs.patch importers: @@ -33,7 +41,7 @@ importers: version: 5.6.3 vocs: specifier: 1.0.0-alpha.62 - version: 1.0.0-alpha.62(patch_hash=p6z7kxjkom4q2uemolyyrxbtiy)(@types/node@22.8.6)(@types/react-dom@18.3.1)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.24.3)(typescript@5.6.3) + version: 1.0.0-alpha.62(patch_hash=7wumpnts656yvepr4seo2mjn34)(@types/node@22.8.6)(@types/react-dom@18.3.1)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.24.3)(typescript@5.6.3) devDependencies: '@types/react-dom': specifier: ^18.3.1 @@ -981,26 +989,26 @@ packages: cpu: [x64] os: [win32] - '@shikijs/core@1.22.2': - resolution: {integrity: sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==} + '@shikijs/core@1.23.1': + resolution: {integrity: sha512-NuOVgwcHgVC6jBVH5V7iblziw6iQbWWHrj5IlZI3Fqu2yx9awH7OIQkXIcsHsUmY19ckwSgUMgrqExEyP5A0TA==} - '@shikijs/engine-javascript@1.22.2': - resolution: {integrity: sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==} + '@shikijs/engine-javascript@1.23.1': + resolution: {integrity: sha512-i/LdEwT5k3FVu07SiApRFwRcSJs5QM9+tod5vYCPig1Ywi8GR30zcujbxGQFJHwYD7A5BUqagi8o5KS+LEVgBg==} - '@shikijs/engine-oniguruma@1.22.2': - resolution: {integrity: sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==} + '@shikijs/engine-oniguruma@1.23.1': + resolution: {integrity: sha512-KQ+lgeJJ5m2ISbUZudLR1qHeH3MnSs2mjFg7bnencgs5jDVPeJ2NVDJ3N5ZHbcTsOIh0qIueyAJnwg7lg7kwXQ==} - '@shikijs/rehype@1.22.2': - resolution: {integrity: sha512-A0RHgiYR5uiHvddwHehBN9j8PhOvfT6/GebSTWrapur6M+fD/4i3mlfUv7aFK4b+4GQ1R42L8fC5N98whZjNcg==} + '@shikijs/rehype@1.23.1': + resolution: {integrity: sha512-PH5bpMDEc4nBP62Ci3lUqkxBWRTm8cdE+eY9er5QD50jAWQxhXcc1Aeax1AlyrASrtjTwCkI22M6N9iSn5p+bQ==} - '@shikijs/transformers@1.22.2': - resolution: {integrity: sha512-8f78OiBa6pZDoZ53lYTmuvpFPlWtevn23bzG+azpPVvZg7ITax57o/K3TC91eYL3OMJOO0onPbgnQyZjRos8XQ==} + '@shikijs/transformers@1.23.1': + resolution: {integrity: sha512-yQ2Cn0M9i46p30KwbyIzLvKDk+dQNU+lj88RGO0XEj54Hn4Cof1bZoDb9xBRWxFE4R8nmK63w7oHnJwvOtt0NQ==} - '@shikijs/twoslash@1.22.2': - resolution: {integrity: sha512-4R3A7aH/toZgtlveXHKk01nIsvn8hjAfPJ1aT550zcV4qK6vK/tfaEyYtaljOaY1wig2l5+8sKjNSEz3PcSiEw==} + '@shikijs/twoslash@1.23.1': + resolution: {integrity: sha512-Qj/+CGAF6TdcRjPDQn1bxyKD8ejnV7VJLqCHzob1uCbwQlJTI5z0gUVAgpqS55z4vdV1Mrx2IpCTl9glhC0l3A==} - '@shikijs/types@1.22.2': - resolution: {integrity: sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==} + '@shikijs/types@1.23.1': + resolution: {integrity: sha512-98A5hGyEhzzAgQh2dAeHKrWW4HfCMeoFER2z16p5eJ+vmPeF6lZ/elEne6/UCU551F/WqkopqRsr1l2Yu6+A0g==} '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} @@ -1375,6 +1383,9 @@ packages: electron-to-chromium@1.5.50: resolution: {integrity: sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==} + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -2042,8 +2053,8 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - oniguruma-to-js@0.4.3: - resolution: {integrity: sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==} + oniguruma-to-es@0.4.1: + resolution: {integrity: sha512-rNcEohFz095QKGRovP/yqPIKc+nP+Sjs4YTHMv33nMePGKrq/r2eu9Yh4646M5XluGJsUnmwoXuiXE69KDs+fQ==} ora@7.0.1: resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} @@ -2282,8 +2293,14 @@ packages: regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regex@4.4.0: - resolution: {integrity: sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==} + regex-recursion@4.2.1: + resolution: {integrity: sha512-QHNZyZAeKdndD1G3bKAbBEKOSSK4KOHQrAJ01N1LJeb0SoH4DJIeFhp0uUpETgONifS4+P3sOgoA1dhzgrQvhA==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@5.0.2: + resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==} rehype-autolink-headings@7.1.0: resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} @@ -2379,8 +2396,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@1.22.2: - resolution: {integrity: sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==} + shiki@1.23.1: + resolution: {integrity: sha512-8kxV9TH4pXgdKGxNOkrSMydn1Xf6It8lsle0fiqxf7a1149K1WGtdOu3Zb91T5r1JpvRPxqxU3C2XdZZXQnrig==} signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -3489,49 +3506,49 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.24.3': optional: true - '@shikijs/core@1.22.2': + '@shikijs/core@1.23.1': dependencies: - '@shikijs/engine-javascript': 1.22.2 - '@shikijs/engine-oniguruma': 1.22.2 - '@shikijs/types': 1.22.2 + '@shikijs/engine-javascript': 1.23.1 + '@shikijs/engine-oniguruma': 1.23.1 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 - '@shikijs/engine-javascript@1.22.2': + '@shikijs/engine-javascript@1.23.1': dependencies: - '@shikijs/types': 1.22.2 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 - oniguruma-to-js: 0.4.3 + oniguruma-to-es: 0.4.1 - '@shikijs/engine-oniguruma@1.22.2': + '@shikijs/engine-oniguruma@1.23.1': dependencies: - '@shikijs/types': 1.22.2 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 - '@shikijs/rehype@1.22.2': + '@shikijs/rehype@1.23.1': dependencies: - '@shikijs/types': 1.22.2 + '@shikijs/types': 1.23.1 '@types/hast': 3.0.4 hast-util-to-string: 3.0.1 - shiki: 1.22.2 + shiki: 1.23.1 unified: 11.0.5 unist-util-visit: 5.0.0 - '@shikijs/transformers@1.22.2': + '@shikijs/transformers@1.23.1': dependencies: - shiki: 1.22.2 + shiki: 1.23.1 - '@shikijs/twoslash@1.22.2(typescript@5.6.3)': + '@shikijs/twoslash@1.23.1(typescript@5.6.3)': dependencies: - '@shikijs/core': 1.22.2 - '@shikijs/types': 1.22.2 + '@shikijs/core': 1.23.1 + '@shikijs/types': 1.23.1 twoslash: 0.2.12(typescript@5.6.3) transitivePeerDependencies: - supports-color - typescript - '@shikijs/types@1.22.2': + '@shikijs/types@1.23.1': dependencies: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 @@ -3929,6 +3946,8 @@ snapshots: electron-to-chromium@1.5.50: {} + emoji-regex-xs@1.0.0: {} + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -5011,9 +5030,11 @@ snapshots: dependencies: mimic-fn: 2.1.0 - oniguruma-to-js@0.4.3: + oniguruma-to-es@0.4.1: dependencies: - regex: 4.4.0 + emoji-regex-xs: 1.0.0 + regex: 5.0.2 + regex-recursion: 4.2.1 ora@7.0.1: dependencies: @@ -5260,7 +5281,15 @@ snapshots: regenerator-runtime@0.14.1: {} - regex@4.4.0: {} + regex-recursion@4.2.1: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@5.0.2: + dependencies: + regex-utilities: 2.3.0 rehype-autolink-headings@7.1.0: dependencies: @@ -5467,12 +5496,12 @@ snapshots: shebang-regex@3.0.0: {} - shiki@1.22.2: + shiki@1.23.1: dependencies: - '@shikijs/core': 1.22.2 - '@shikijs/engine-javascript': 1.22.2 - '@shikijs/engine-oniguruma': 1.22.2 - '@shikijs/types': 1.22.2 + '@shikijs/core': 1.23.1 + '@shikijs/engine-javascript': 1.23.1 + '@shikijs/engine-oniguruma': 1.23.1 + '@shikijs/types': 1.23.1 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 @@ -5766,7 +5795,7 @@ snapshots: '@types/node': 22.8.6 fsevents: 2.3.3 - vocs@1.0.0-alpha.62(patch_hash=p6z7kxjkom4q2uemolyyrxbtiy)(@types/node@22.8.6)(@types/react-dom@18.3.1)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.24.3)(typescript@5.6.3): + vocs@1.0.0-alpha.62(patch_hash=7wumpnts656yvepr4seo2mjn34)(@types/node@22.8.6)(@types/react-dom@18.3.1)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.24.3)(typescript@5.6.3): dependencies: '@floating-ui/react': 0.26.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@hono/node-server': 1.13.4(hono@3.12.12) @@ -5781,9 +5810,9 @@ snapshots: '@radix-ui/react-navigation-menu': 1.2.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@shikijs/rehype': 1.22.2 - '@shikijs/transformers': 1.22.2 - '@shikijs/twoslash': 1.22.2(typescript@5.6.3) + '@shikijs/rehype': 1.23.1 + '@shikijs/transformers': 1.23.1 + '@shikijs/twoslash': 1.23.1(typescript@5.6.3) '@vanilla-extract/css': 1.16.0 '@vanilla-extract/dynamic': 2.1.2 '@vanilla-extract/vite-plugin': 3.9.5(@types/node@22.8.6)(vite@5.4.10(@types/node@22.8.6)) @@ -5823,7 +5852,7 @@ snapshots: remark-mdx-frontmatter: 4.0.0 remark-parse: 11.0.0 serve-static: 1.16.2 - shiki: 1.22.2 + shiki: 1.23.1 tailwindcss: 3.4.14 toml: 3.0.0 twoslash: 0.2.12(typescript@5.6.3) diff --git a/routes.ts b/routes.ts index 1969da23..d8348c7f 100644 --- a/routes.ts +++ b/routes.ts @@ -7,7 +7,6 @@ const config: Sidebar = [ }, { text: "Getting Started", - link: "/getting-started/basics/storage", items: [ // { // text: "Local environment setup" @@ -98,7 +97,6 @@ const config: Sidebar = [ }, { text: "Components", - link: "/components/how_to", items: [ { text: "Components How-To", @@ -120,7 +118,6 @@ const config: Sidebar = [ }, { text: "Applications", - link: "/applications/upgradeable_contract", items: [ { text: " Upgradeable Contract", @@ -174,7 +171,6 @@ const config: Sidebar = [ }, { text: "Advanced concepts", - link: "/advanced-concepts/write_to_any_slot", items: [ { text: "Writing to any storage slot", diff --git a/styles.css b/styles.css index 2ba7b331..4aeb1128 100644 --- a/styles.css +++ b/styles.css @@ -60,48 +60,47 @@ section.vocs_Sidebar_level } /* Make sidebar collapsible */ -.vocs_DocsLayout_gutterLeft { - top: 0; - left: 0; - bottom: 0; -} -.vocs_DocsLayout_gutterLeft { - margin-left: 0; - transition: margin 0.3s ease; -} -.sidebar_hidden .vocs_DocsLayout_gutterLeft { - margin-left: calc(var(--vocs_DocsLayout_leftGutterWidth) * -1); -}; - -.vocs_DocsLayout_content_withSidebar { - margin-left: var(--vocs_DocsLayout_leftGutterWidth) -} -.sidebar_hidden .vocs_DocsLayout_content_withSidebar { - margin-left: 0 !important; -} -.vocs_DocsLayout_content_withSidebar { - transition: margin 300ms ease !important; - max-width: unset; -} - -.vocs_DesktopTopNav_logo a { - margin-top: 2px !important; -} - -.vocs_Sidebar_logo { - padding-top: 0px !important; -} - -.sidebar_toggle { - position: absolute; - top: 0; - right: calc(var(--vocs-topNav_height) * -1); - height: var(--vocs-topNav_height); - width: var(--vocs-topNav_height); -} - -.sidebar_toggle button { - padding: var(--vocs-space_8); +@media screen and (min-width: 1080px) { + .vocs_DocsLayout_gutterLeft { + margin-left: 0; + transition: margin 0.3s ease; + width: var(--vocs-sidebar_width); + } + .sidebar_hidden .vocs_DocsLayout_gutterLeft { + margin-left: calc(var(--vocs-sidebar_width) * -1); + } + + .vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); + } + .sidebar_hidden .vocs_DocsLayout_content_withSidebar { + margin-left: 0 !important; + } + .vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); + transition: margin 300ms ease !important; + max-width: unset; + } + + .vocs_DesktopTopNav_logo a { + margin-top: 2px !important; + } + + .vocs_Sidebar_logo { + padding-top: 0px !important; + } + + .sidebar_toggle { + position: absolute; + top: 0; + right: calc(var(--vocs-topNav_height) * -1); + height: var(--vocs-topNav_height); + width: var(--vocs-topNav_height); + } + + .sidebar_toggle button { + padding: var(--vocs-space_8); + } } /* END sidebar */ @@ -120,3 +119,15 @@ section.vocs_Sidebar_level font-size: var(--vocs-fontSize_20); padding-bottom: 0.875em; } + +.vocs_DesktopTopNav_logoWrapper { + left: 22px; + justify-content: start; +} + +/* Force show theme switcher */ +@media screen and (max-width: 1280px) { + .vocs_DesktopTopNav_hideCompact { + display: block; + } +} From b7d405f9adca16936fd2263db74a8f41f3733e63 Mon Sep 17 00:00:00 2001 From: Julio <30329843+julio4@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:13:48 +0100 Subject: [PATCH 02/13] Prepare release `2.9.2` (#282) * fix(app): correct sidebar placement * fix(app): responsive content centering * fix(app): responsive content centering * Update issue templates, Close #273 close #273 * Feat: add logos (#278) * fix #276 * feat: updated logo * Feat: upgrade to `2.9.2` (#280) * chore: update 2.9.2 * chore: apply fmt * fix: hide AA for upcoming fixes * fix: github edit link * fix: starknet book deadlink * fix #279 * small improvement: increase footer bottom padding * fix #275 * fix: minor * fix: remove print from cairo_cheatsheet * Update verify_cairo_programs.yml --- .github/ISSUE_TEMPLATE/bug_report.md | 23 ++++ .github/ISSUE_TEMPLATE/feature-request.md | 16 +++ .github/workflows/verify_cairo_programs.yml | 2 +- .tool-versions | 4 +- Scarb.lock | 79 +++++++++----- Scarb.toml | 12 +-- components/ThemeImage.tsx | 27 +++++ components/useTheme.tsx | 32 ++++++ footer.tsx | 2 +- .../commit_reveal/src/commit_reveal.cairo | 7 +- .../src/ecdsa_verification.cairo | 14 +-- .../hash_trait/src/hash_trait.cairo | 13 ++- .../library_calls/src/tests.cairo | 7 +- .../simple_account/src/simple_account.cairo | 12 +-- .../store_using_packing/src/contract.cairo | 4 +- .../store_using_packing/src/tests.cairo | 5 +- .../struct_as_mapping_key/src/test.cairo | 5 +- .../write_to_any_slot/src/contract.cairo | 9 +- .../write_to_any_slot/src/tests.cairo | 2 +- .../advanced_factory/src/contract.cairo | 18 ++-- .../advanced_factory/src/tests.cairo | 42 ++++---- .../applications/coin_flip/src/contract.cairo | 18 ++-- .../coin_flip/src/mock_randomness.cairo | 22 ++-- .../applications/coin_flip/src/tests.cairo | 70 ++++++------ .../components/src/countable.cairo | 9 +- .../src/others/switch_collision.cairo | 8 +- .../applications/components/src/ownable.cairo | 30 +++--- .../components/src/switchable.cairo | 11 +- .../src/contract_countable.cairo | 9 +- .../src/contract_countable_switchable.cairo | 9 +- ...ntract_countable_switchable_internal.cairo | 9 +- .../src/countable_dep_switch.cairo | 7 +- .../src/countable_internal_dep_switch.cairo | 8 +- .../constant_product_amm/src/contracts.cairo | 16 +-- .../constant_product_amm/src/tests.cairo | 6 +- .../crowdfunding/src/campaign.cairo | 10 +- .../src/campaign/pledgeable.cairo | 6 +- .../crowdfunding/src/mock_upgrade.cairo | 10 +- .../applications/crowdfunding/src/tests.cairo | 100 +++++++++--------- listings/applications/erc20/src/token.cairo | 100 +++++++++--------- .../merkle_tree/src/contract.cairo | 10 +- .../applications/merkle_tree/src/tests.cairo | 18 ++-- .../nft_dutch_auction/src/erc721.cairo | 28 ++--- .../src/nft_dutch_auction.cairo | 30 +++--- .../src/storage.cairo | 2 +- listings/applications/simple_vault/Scarb.toml | 1 + .../applications/simple_vault/src/lib.cairo | 3 - .../simple_vault/src/simple_vault.cairo | 31 +++--- .../applications/simple_vault/src/tests.cairo | 2 - .../applications/staking/src/contract.cairo | 8 +- .../staking/src/tests/staking_tests.cairo | 59 ++++++----- .../staking/src/tests/tokens.cairo | 4 +- .../applications/timelock/src/erc721.cairo | 2 +- .../timelock/src/tests/timelock.cairo | 54 +++++----- .../timelock/src/tests/utils.cairo | 2 +- .../applications/timelock/src/timelock.cairo | 14 +-- .../upgradeable_contract/src/tests.cairo | 21 ++-- .../src/upgradeable_contract_v0.cairo | 5 +- .../src/upgradeable_contract_v1.cairo | 7 +- listings/cairo_cheatsheet/Scarb.toml | 1 - .../cairo_cheatsheet/src/enum_example.cairo | 18 ++-- .../cairo_cheatsheet/src/if_let_example.cairo | 12 +-- .../src/mapping_example.cairo | 10 +- .../cairo_cheatsheet/src/match_example.cairo | 2 +- .../cairo_cheatsheet/src/struct_example.cairo | 2 +- .../src/while_let_example.cairo | 2 - .../bytearray/src/bytearray.cairo | 2 +- .../calling_other_contracts/src/caller.cairo | 14 +-- .../constructor/src/constructor.cairo | 6 +- .../getting-started/counter/src/counter.cairo | 6 +- .../custom_type_serde/src/contract.cairo | 10 +- .../errors/src/custom_errors.cairo | 8 +- .../errors/src/simple_errors.cairo | 6 +- .../errors/src/vault_errors.cairo | 8 +- .../getting-started/events/src/counter.cairo | 24 ++--- .../factory/src/simple_factory.cairo | 16 +-- .../interfaces_traits/src/explicit.cairo | 10 +- .../interfaces_traits/src/implicit.cairo | 8 +- .../src/implicit_internal.cairo | 13 ++- .../mappings/src/mappings.cairo | 6 +- .../storage/src/contract.cairo | 8 +- .../storage/src/minimal_contract.cairo | 6 +- .../storing_custom_types/src/contract.cairo | 6 +- .../testing_how_to/src/contract.cairo | 14 +-- .../variables/src/global_variables.cairo | 6 +- .../variables/src/local_variables.cairo | 8 +- .../variables/src/storage_variables.cairo | 10 +- .../visibility/src/visibility.cairo | 8 +- pages/components/collisions.md | 2 +- pages/getting-started/basics/storage.md | 2 +- pages/getting-started/basics/syscalls.md | 2 +- .../testing/contract-testing.md | 3 - pages/index.mdx | 11 +- public/svg/Horizontal_Dark.svg | 29 +++++ public/svg/Horizontal_Light.svg | 29 +++++ public/svg/Icon_Dark.svg | 12 +++ public/svg/Icon_Light.svg | 12 +++ public/svg/Vertical_Dark.svg | 29 +++++ public/svg/Vertical_Light.svg | 29 +++++ routes.ts | 28 ++--- vocs.config.ts | 15 ++- 101 files changed, 904 insertions(+), 643 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature-request.md create mode 100644 components/ThemeImage.tsx create mode 100644 components/useTheme.tsx delete mode 100644 listings/applications/simple_vault/src/tests.cairo create mode 100644 public/svg/Horizontal_Dark.svg create mode 100644 public/svg/Horizontal_Light.svg create mode 100644 public/svg/Icon_Dark.svg create mode 100644 public/svg/Icon_Light.svg create mode 100644 public/svg/Vertical_Dark.svg create mode 100644 public/svg/Vertical_Light.svg diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..7c8cc313 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Checklist:** +- Using the correct tooling versions, from https://github.com/NethermindEth/StarknetByExample/blob/dev/.tool-versions diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 00000000..36b7339b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,16 @@ +--- +name: Feature request +about: Suggest an idea of example or concept to showcase +title: '' +labels: enhancement +assignees: '' + +--- + +**Describe the concept/idea you would like to see** + +**Is it a new example or a modification/extension of a current one** +If you consider editing some content, explain exactly why and what. + +**Additional context** +Add any other context or screenshots about the request here. diff --git a/.github/workflows/verify_cairo_programs.yml b/.github/workflows/verify_cairo_programs.yml index 518a91f8..151ceee2 100644 --- a/.github/workflows/verify_cairo_programs.yml +++ b/.github/workflows/verify_cairo_programs.yml @@ -3,7 +3,7 @@ name: Verify Cairo programs compilation on: pull_request: branches: - - main + - dev workflow_dispatch: jobs: diff --git a/.tool-versions b/.tool-versions index aac540e2..c69b5af8 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -scarb 2.8.2 -starknet-foundry 0.30.0 +scarb 2.9.2 +starknet-foundry 0.35.0 diff --git a/Scarb.lock b/Scarb.lock index 6cd8c91c..a7c69be7 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -128,105 +128,126 @@ dependencies = [ [[package]] name = "openzeppelin" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:5dc87a71f0f5d045e02e5bc5ea7a9b0360bbbc3f388b846006280d266feac192" +checksum = "sha256:05fd9365be85a4a3e878135d5c52229f760b3861ce4ed314cb1e75b178b553da" dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_finance", + "openzeppelin_governance", + "openzeppelin_introspection", "openzeppelin_merkle_tree", "openzeppelin_presets", "openzeppelin_security", "openzeppelin_token", "openzeppelin_upgrades", + "openzeppelin_utils", ] [[package]] name = "openzeppelin_access" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:b9139449e53d715992b2d9e887c0c723d886419bee7ceb5561648c70bd6d3174" +checksum = "sha256:7734901a0ca7a7065e69416fea615dd1dc586c8dc9e76c032f25ee62e8b2a06c" dependencies = [ "openzeppelin_introspection", - "openzeppelin_utils", ] [[package]] name = "openzeppelin_account" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:841bb881adbe98b64fee1dc1329f6e3fbabdfbd9fa65c66ffb54c55f13764bce" +checksum = "sha256:1aa3a71e2f40f66f98d96aa9bf9f361f53db0fd20fa83ef7df04426a3c3a926a" dependencies = [ "openzeppelin_introspection", "openzeppelin_utils", ] +[[package]] +name = "openzeppelin_finance" +version = "0.20.0" +source = "registry+https://scarbs.xyz/" +checksum = "sha256:f0c507fbff955e4180ea3fa17949c0ff85518c40101f4948948d9d9a74143d6c" +dependencies = [ + "openzeppelin_access", + "openzeppelin_token", +] + [[package]] name = "openzeppelin_governance" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:a9d9c983cfd4369e7bbb69433fb264edf376805ed873b1f70a287825a6bd1eaf" +checksum = "sha256:c0fb60fad716413d537fabd5fcbb2c499ca6beb95af5f0d1699955ecec4c6f63" dependencies = [ "openzeppelin_access", + "openzeppelin_account", "openzeppelin_introspection", + "openzeppelin_token", + "openzeppelin_utils", ] [[package]] name = "openzeppelin_introspection" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:312bc2e531f036480ad7392dbb31042c38d875ef9dbb5578ea8de5c05e35b7d8" +checksum = "sha256:13e04a2190684e6804229a77a6c56de7d033db8b9ef519e5e8dee400a70d8a3d" [[package]] name = "openzeppelin_merkle_tree" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:8e264c8d5f0591262a235a445b8ca78dd5580c251707b218b829b6b4d6f84a34" +checksum = "sha256:039608900e92f3dcf479bf53a49a1fd76452acd97eb86e390d1eb92cacdaf3af" [[package]] name = "openzeppelin_presets" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:7bc9db7563e434535ebd06c7598ba0f8494e791c5f80401389b356a3ebd65a08" +checksum = "sha256:5c07a8de32e5d9abe33988c7927eaa8b5f83bc29dc77302d9c8c44c898611042" dependencies = [ "openzeppelin_access", "openzeppelin_account", + "openzeppelin_finance", "openzeppelin_introspection", "openzeppelin_token", "openzeppelin_upgrades", + "openzeppelin_utils", ] [[package]] name = "openzeppelin_security" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:b7497f5e55c6d9f1d7606ad0d12719e3c04765e266fb91fb72740e0af41d03f3" +checksum = "sha256:27155597019ecf971c48d7bfb07fa58cdc146d5297745570071732abca17f19f" [[package]] name = "openzeppelin_token" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:7074c23fbc300b3cccff1037264dfdbe976fb11ae42ce687f4a8ce469adc552a" +checksum = "sha256:4452f449dc6c1ea97cf69d1d9182749abd40e85bd826cd79652c06a627eafd91" dependencies = [ + "openzeppelin_access", "openzeppelin_account", - "openzeppelin_governance", "openzeppelin_introspection", + "openzeppelin_utils", ] [[package]] name = "openzeppelin_upgrades" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:4de95a7fb8955e63711f34bb954676f6cef127b44b570c0535d7781297821b44" +checksum = "sha256:15fdd63f6b50a0fda7b3f8f434120aaf7637bcdfe6fd8d275ad57343d5ede5e1" [[package]] name = "openzeppelin_utils" -version = "0.16.0" +version = "0.20.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:a494aeb5f1371db7f22e922196aa41d1d1698877a766a838350c0b6ffe49fda2" +checksum = "sha256:44f32d242af1e43982decc49c563e613a9b67ade552f5c3d5cde504e92f74607" [[package]] name = "pragma_lib" version = "1.0.0" -source = "git+https://github.com/astraly-labs/pragma-lib#86d7ccdc15b349b8b48d9796fc8464c947bea6e1" +source = "git+https://github.com/astraly-labs/pragma-lib?tag=2.9.1#ee1f3f7e9276cf64e19e267832de380d84c04d28" [[package]] name = "simple_account" @@ -248,15 +269,15 @@ dependencies = [ [[package]] name = "snforge_scarb_plugin" -version = "0.2.0" +version = "0.35.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:2e4ce3ebe3f49548bd26908391b5d78537a765d827df0d96c32aeb88941d0d67" +checksum = "sha256:20bd6a488fda7201ce2a5fd680d8e715b10e3545147b276747ad079c96c3d5d2" [[package]] name = "snforge_std" -version = "0.30.0" +version = "0.35.0" source = "registry+https://scarbs.xyz/" -checksum = "sha256:2f3c4846881813ac0f5d1460981249c9f5e2a6831e752beedf9b70975495b4ec" +checksum = "sha256:fe4e1b1526c815441183baed7f93e73bc76a6393d23e1f9c34fbe227bfaedfd6" dependencies = [ "snforge_scarb_plugin", ] diff --git a/Scarb.toml b/Scarb.toml index eca997b2..37e6b8f1 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -12,13 +12,13 @@ test = "$(git rev-parse --show-toplevel)/scripts/test_resolver.sh" [workspace.tool.snforge] [workspace.dependencies] -starknet = "2.8.2" -cairo_test = "2.8.2" -assert_macros = "2.8.2" -snforge_std = "0.30.0" -openzeppelin = "0.16.0" +starknet = "2.9.2" +cairo_test = "2.9.2" +assert_macros = "2.9.2" +snforge_std = "0.35.0" +openzeppelin = "0.20.0" components = { path = "listings/applications/components" } -pragma_lib = { git = "https://github.com/astraly-labs/pragma-lib" } +pragma_lib = { git = "https://github.com/astraly-labs/pragma-lib", tag = "2.9.1" } [workspace.package] description = "Collection of examples of how to use the Cairo programming language to create smart contracts on Starknet." diff --git a/components/ThemeImage.tsx b/components/ThemeImage.tsx new file mode 100644 index 00000000..d8e57e06 --- /dev/null +++ b/components/ThemeImage.tsx @@ -0,0 +1,27 @@ +import { useEffect, useState } from "react"; +import { useTheme } from "./useTheme"; + +export const ThemeImage = ({ + light, + dark, + alt, + ...props +}: { + light: string; + dark: string; + alt: string; + [key: string]: any; +}) => { + const [mounted, setMounted] = useState(false); + const theme = useTheme(); + + useEffect(() => { + setMounted(true); + }, []); + if (!mounted) { + return {alt}; + } + + // Client-side rendering after hydrating + return {alt}; +}; diff --git a/components/useTheme.tsx b/components/useTheme.tsx new file mode 100644 index 00000000..a2aa12d2 --- /dev/null +++ b/components/useTheme.tsx @@ -0,0 +1,32 @@ +import { useEffect, useState } from "react"; + +export function useTheme() { + const [theme, setTheme] = useState<"dark" | "light">(() => { + if (typeof window === "undefined") return "light"; + return document.documentElement.classList.contains("dark") + ? "dark" + : "light"; + }); + + useEffect(() => { + const handleThemeChange = () => { + const newTheme = document.documentElement.classList.contains("dark") + ? "dark" + : "light"; + setTheme(newTheme); + }; + + // Watch for class changes on documentElement + const observer = new MutationObserver(handleThemeChange); + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["class"], + }); + + return () => { + observer.disconnect(); + }; + }, []); + + return theme; +} diff --git a/footer.tsx b/footer.tsx index 41212213..70d07b30 100644 --- a/footer.tsx +++ b/footer.tsx @@ -1,6 +1,6 @@ export default function Footer() { return ( -
+
ICommitmentRevealTraitDispatcher { let (contract_address, _) = deploy_syscall( - CommitmentRevealTraits::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CommitmentRevealTraits::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ICommitmentRevealTraitDispatcher { contract_address } } diff --git a/listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo b/listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo index 5321a85e..c6f601ad 100644 --- a/listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo +++ b/listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo @@ -9,12 +9,12 @@ use starknet::secp256_trait::{Signature}; // 3. Sign the hash (off chain, keep your private key secret) #[starknet::interface] trait IVerifySignature { - fn get_signature(self: @TContractState, r: u256, s: u256, v: u32,) -> Signature; + fn get_signature(self: @TContractState, r: u256, s: u256, v: u32) -> Signature; fn verify_eth_signature( self: @TContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32, ); fn recover_public_key( - self: @TContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 + self: @TContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32, ); } @@ -23,7 +23,7 @@ mod verifySignature { use super::IVerifySignature; use core::starknet::eth_address::EthAddress; use starknet::secp256k1::Secp256k1Point; - use starknet::secp256_trait::{Signature, signature_from_vrs, recover_public_key,}; + use starknet::secp256_trait::{Signature, signature_from_vrs, recover_public_key}; use starknet::eth_signature::{verify_eth_signature, public_key_point_to_eth_address}; #[storage] @@ -46,7 +46,7 @@ mod verifySignature { /// # Returns /// /// * `Signature` - The signature struct. - fn get_signature(self: @ContractState, r: u256, s: u256, v: u32,) -> Signature { + fn get_signature(self: @ContractState, r: u256, s: u256, v: u32) -> Signature { // Create a Signature object from the given v, r, and s values. let signature: Signature = signature_from_vrs(v, r, s); signature @@ -62,7 +62,7 @@ mod verifySignature { /// * `s` - The S component of the signature. /// * `v` - The V component of the signature. fn verify_eth_signature( - self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 + self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32, ) { let signature = self.get_signature(r, s, v); verify_eth_signature(:msg_hash, :signature, :eth_address); @@ -79,7 +79,7 @@ mod verifySignature { /// * `s` - The S component of the signature. /// * `v` - The V component of the signature. fn recover_public_key( - self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 + self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32, ) { let signature = self.get_signature(r, s, v); let public_key_point = recover_public_key::(msg_hash, signature) @@ -93,7 +93,7 @@ mod verifySignature { #[cfg(test)] mod tests { - use starknet::secp256_trait::{Signature, signature_from_vrs, recover_public_key,}; + use starknet::secp256_trait::{Signature, signature_from_vrs, recover_public_key}; use starknet::EthAddress; use starknet::secp256k1::{Secp256k1Point}; use starknet::eth_signature::{verify_eth_signature, public_key_point_to_eth_address}; diff --git a/listings/advanced-concepts/hash_trait/src/hash_trait.cairo b/listings/advanced-concepts/hash_trait/src/hash_trait.cairo index 88fde919..ee8b9fb6 100644 --- a/listings/advanced-concepts/hash_trait/src/hash_trait.cairo +++ b/listings/advanced-concepts/hash_trait/src/hash_trait.cairo @@ -1,10 +1,10 @@ #[starknet::interface] pub trait IHashTrait { fn save_user_with_poseidon( - ref self: T, id: felt252, username: felt252, password: felt252 + ref self: T, id: felt252, username: felt252, password: felt252, ) -> felt252; fn save_user_with_pedersen( - ref self: T, id: felt252, username: felt252, password: felt252 + ref self: T, id: felt252, username: felt252, password: felt252, ) -> felt252; } @@ -36,7 +36,7 @@ pub mod HashTraits { #[abi(embed_v0)] impl HashTrait of super::IHashTrait { fn save_user_with_poseidon( - ref self: ContractState, id: felt252, username: felt252, password: felt252 + ref self: ContractState, id: felt252, username: felt252, password: felt252, ) -> felt252 { let login = LoginDetails { username, password }; let user = UserDetails { id, login }; @@ -48,7 +48,7 @@ pub mod HashTraits { } fn save_user_with_pedersen( - ref self: ContractState, id: felt252, username: felt252, password: felt252 + ref self: ContractState, id: felt252, username: felt252, password: felt252, ) -> felt252 { let login = LoginDetails { username, password }; let user = UserDetails { id, login }; @@ -64,16 +64,15 @@ pub mod HashTraits { #[cfg(test)] mod tests { - use starknet::SyscallResultTrait; use super::{HashTraits, IHashTraitDispatcher, IHashTraitDispatcherTrait}; use starknet::syscalls::deploy_syscall; fn deploy() -> IHashTraitDispatcher { let mut calldata = array![]; let (address, _) = deploy_syscall( - HashTraits::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + HashTraits::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); IHashTraitDispatcher { contract_address: address } } diff --git a/listings/advanced-concepts/library_calls/src/tests.cairo b/listings/advanced-concepts/library_calls/src/tests.cairo index 6458ef4d..90c2707e 100644 --- a/listings/advanced-concepts/library_calls/src/tests.cairo +++ b/listings/advanced-concepts/library_calls/src/tests.cairo @@ -1,8 +1,7 @@ mod tests { use starknet::syscalls::deploy_syscall; - use starknet::SyscallResultTrait; use library_calls::library_call::{ - MathUtils, MathUtilsLibraryCall, IMathUtilsDispatcher, IMathUtilsDispatcherTrait + MathUtils, MathUtilsLibraryCall, IMathUtilsDispatcher, IMathUtilsDispatcherTrait, }; #[test] @@ -12,9 +11,9 @@ mod tests { .unwrap(); let mut calldata: Array = array![]; let (address, _) = deploy_syscall( - MathUtilsLibraryCall::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + MathUtilsLibraryCall::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IMathUtilsDispatcher { contract_address: address }; contract.set_class_hash(math_utils_class_hash); diff --git a/listings/advanced-concepts/simple_account/src/simple_account.cairo b/listings/advanced-concepts/simple_account/src/simple_account.cairo index 6de72c81..f1e1386b 100644 --- a/listings/advanced-concepts/simple_account/src/simple_account.cairo +++ b/listings/advanced-concepts/simple_account/src/simple_account.cairo @@ -5,7 +5,7 @@ trait ISRC6 { fn execute_calls(self: @TContractState, calls: Array) -> Array>; fn validate_calls(self: @TContractState, calls: Array) -> felt252; fn is_valid_signature( - self: @TContractState, hash: felt252, signature: Array + self: @TContractState, hash: felt252, signature: Array, ) -> felt252; } @@ -30,7 +30,7 @@ mod simpleAccount { struct Storage { #[substorage(v0)] src5: SRC5Component::Storage, - public_key: felt252 + public_key: felt252, } #[constructor] @@ -43,7 +43,7 @@ mod simpleAccount { #[derive(Drop, starknet::Event)] enum Event { #[flat] - SRC5Event: SRC5Component::Event + SRC5Event: SRC5Component::Event, } #[abi(embed_v0)] @@ -68,7 +68,7 @@ mod simpleAccount { } fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array + self: @ContractState, hash: felt252, signature: Array, ) -> felt252 { if self._is_valid_signature(hash, signature.span()) { starknet::VALIDATED @@ -81,10 +81,10 @@ mod simpleAccount { #[generate_trait] impl SignatureVerificationImpl of SignatureVerification { fn _is_valid_signature( - self: @ContractState, hash: felt252, signature: Span + self: @ContractState, hash: felt252, signature: Span, ) -> bool { check_ecdsa_signature( - hash, self.public_key.read(), *signature.at(0_u32), *signature.at(1_u32) + hash, self.public_key.read(), *signature.at(0_u32), *signature.at(1_u32), ) } } diff --git a/listings/advanced-concepts/store_using_packing/src/contract.cairo b/listings/advanced-concepts/store_using_packing/src/contract.cairo index 8ef6b2db..e1611a22 100644 --- a/listings/advanced-concepts/store_using_packing/src/contract.cairo +++ b/listings/advanced-concepts/store_using_packing/src/contract.cairo @@ -1,7 +1,7 @@ #[derive(Copy, Serde, Drop)] pub struct Time { pub hour: u8, - pub minute: u8 + pub minute: u8, } #[starknet::interface] @@ -18,7 +18,7 @@ pub mod TimeContract { #[storage] struct Storage { - time: Time + time: Time, } impl TimePackable of StorePacking { diff --git a/listings/advanced-concepts/store_using_packing/src/tests.cairo b/listings/advanced-concepts/store_using_packing/src/tests.cairo index eb888025..3bb290d4 100644 --- a/listings/advanced-concepts/store_using_packing/src/tests.cairo +++ b/listings/advanced-concepts/store_using_packing/src/tests.cairo @@ -1,5 +1,4 @@ mod tests { - use starknet::SyscallResultTrait; use store_using_packing::contract::{TimeContract, Time, ITimeDispatcher, ITimeDispatcherTrait}; use starknet::syscalls::deploy_syscall; @@ -9,9 +8,9 @@ mod tests { // Set up. let mut calldata: Array = array![]; let (address0, _) = deploy_syscall( - TimeContract::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + TimeContract::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = ITimeDispatcher { contract_address: address0 }; // Store a Time struct. diff --git a/listings/advanced-concepts/struct_as_mapping_key/src/test.cairo b/listings/advanced-concepts/struct_as_mapping_key/src/test.cairo index 34ebdf26..7fef6c87 100644 --- a/listings/advanced-concepts/struct_as_mapping_key/src/test.cairo +++ b/listings/advanced-concepts/struct_as_mapping_key/src/test.cairo @@ -1,5 +1,4 @@ mod tests { - use starknet::SyscallResultTrait; use struct_as_mapping_key::contract::{PetRegistry, Pet}; use starknet::syscalls::deploy_syscall; @@ -14,9 +13,9 @@ mod tests { // Set up. let mut calldata: Array = array![]; let (address0, _) = deploy_syscall( - PetRegistry::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + PetRegistry::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IPetRegistryDispatcher { contract_address: address0 }; let pet = Pet { name: 'Cute Labrador', age: 5, owner: 'Louis' }; diff --git a/listings/advanced-concepts/write_to_any_slot/src/contract.cairo b/listings/advanced-concepts/write_to_any_slot/src/contract.cairo index 1e7d4922..e5673412 100644 --- a/listings/advanced-concepts/write_to_any_slot/src/contract.cairo +++ b/listings/advanced-concepts/write_to_any_slot/src/contract.cairo @@ -7,7 +7,6 @@ pub trait IWriteToAnySlots { #[starknet::contract] pub mod WriteToAnySlot { use starknet::syscalls::{storage_read_syscall, storage_write_syscall}; - use starknet::SyscallResultTrait; use core::poseidon::poseidon_hash_span; use starknet::StorageAddress; @@ -19,15 +18,11 @@ pub mod WriteToAnySlot { #[abi(embed_v0)] impl WriteToAnySlot of super::IWriteToAnySlots { fn write_slot(ref self: ContractState, value: u32) { - storage_write_syscall(0, get_address_from_name(SLOT_NAME), value.into()) - .unwrap_syscall(); + storage_write_syscall(0, get_address_from_name(SLOT_NAME), value.into()).unwrap(); } fn read_slot(self: @ContractState) -> u32 { - storage_read_syscall(0, get_address_from_name(SLOT_NAME)) - .unwrap_syscall() - .try_into() - .unwrap() + storage_read_syscall(0, get_address_from_name(SLOT_NAME)).unwrap().try_into().unwrap() } } pub fn get_address_from_name(variable_name: felt252) -> StorageAddress { diff --git a/listings/advanced-concepts/write_to_any_slot/src/tests.cairo b/listings/advanced-concepts/write_to_any_slot/src/tests.cairo index 6428a6eb..42c6528d 100644 --- a/listings/advanced-concepts/write_to_any_slot/src/tests.cairo +++ b/listings/advanced-concepts/write_to_any_slot/src/tests.cairo @@ -16,7 +16,7 @@ mod tests { // Set up. let mut calldata: Array = array![]; let (address0, _) = deploy_syscall( - WriteToAnySlot::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + WriteToAnySlot::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false, ) .unwrap(); let mut contract = IWriteToAnySlotDispatcher { contract_address: address0 }; diff --git a/listings/applications/advanced_factory/src/contract.cairo b/listings/applications/advanced_factory/src/contract.cairo index ff81f715..f8436ead 100644 --- a/listings/applications/advanced_factory/src/contract.cairo +++ b/listings/applications/advanced_factory/src/contract.cairo @@ -10,26 +10,24 @@ pub trait ICampaignFactory { goal: u256, start_time: u64, end_time: u64, - token_address: ContractAddress + token_address: ContractAddress, ) -> ContractAddress; fn get_campaign_class_hash(self: @TContractState) -> ClassHash; fn update_campaign_class_hash(ref self: TContractState, new_class_hash: ClassHash); fn upgrade_campaign( - ref self: TContractState, campaign_address: ContractAddress, new_end_time: Option + ref self: TContractState, campaign_address: ContractAddress, new_end_time: Option, ); } #[starknet::contract] pub mod CampaignFactory { use core::num::traits::Zero; - use starknet::{ - ContractAddress, ClassHash, SyscallResultTrait, syscalls::deploy_syscall, get_caller_address - }; + use starknet::{ContractAddress, ClassHash, syscalls::deploy_syscall, get_caller_address}; use crowdfunding::campaign::{ICampaignDispatcher, ICampaignDispatcherTrait}; use components::ownable::ownable_component; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; component!(path: ownable_component, storage: ownable, event: OwnableEvent); @@ -71,7 +69,7 @@ pub mod CampaignFactory { #[derive(Drop, starknet::Event)] pub struct CampaignCreated { pub creator: ContractAddress, - pub contract_address: ContractAddress + pub contract_address: ContractAddress, } pub mod Errors { @@ -109,9 +107,9 @@ pub mod CampaignFactory { // Contract deployment let (contract_address, _) = deploy_syscall( - self.campaign_class_hash.read(), 0, constructor_calldata.span(), false + self.campaign_class_hash.read(), 0, constructor_calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); // track new campaign instance self.campaigns.write((creator, contract_address), self.campaign_class_hash.read()); @@ -135,7 +133,7 @@ pub mod CampaignFactory { } fn upgrade_campaign( - ref self: ContractState, campaign_address: ContractAddress, new_end_time: Option + ref self: ContractState, campaign_address: ContractAddress, new_end_time: Option, ) { assert(campaign_address.is_non_zero(), Errors::ZERO_ADDRESS); diff --git a/listings/applications/advanced_factory/src/tests.cairo b/listings/applications/advanced_factory/src/tests.cairo index 4b2b3bf5..31352aaa 100644 --- a/listings/applications/advanced_factory/src/tests.cairo +++ b/listings/applications/advanced_factory/src/tests.cairo @@ -1,11 +1,11 @@ use advanced_factory::contract::{ - CampaignFactory, ICampaignFactoryDispatcher, ICampaignFactoryDispatcherTrait + CampaignFactory, ICampaignFactoryDispatcher, ICampaignFactoryDispatcherTrait, }; use crowdfunding::campaign::Campaign; use starknet::{ClassHash, get_block_timestamp, contract_address_const}; use snforge_std::{ declare, start_cheat_caller_address, stop_cheat_caller_address, spy_events, DeclareResultTrait, - ContractClassTrait, get_class_hash, EventSpyAssertionsTrait + ContractClassTrait, get_class_hash, EventSpyAssertionsTrait, }; // Define a goal contract to deploy @@ -88,11 +88,11 @@ fn test_create_campaign() { factory.contract_address, CampaignFactory::Event::CampaignCreated( CampaignFactory::CampaignCreated { - creator: campaign_creator, contract_address: campaign_address - } - ) - ) - ] + creator: campaign_creator, contract_address: campaign_address, + }, + ), + ), + ], ); } @@ -111,7 +111,7 @@ fn test_upgrade_campaign_class_hash() { start_cheat_caller_address(factory.contract_address, pending_campaign_creator); let pending_campaign = factory .create_campaign( - "title 1", "description 1", 10000, start_time_pending, end_time_pending, token + "title 1", "description 1", 10000, start_time_pending, end_time_pending, token, ); assert_eq!(old_class_hash, get_class_hash(pending_campaign)); @@ -123,7 +123,7 @@ fn test_upgrade_campaign_class_hash() { start_cheat_caller_address(factory.contract_address, active_campaign_creator); let active_campaign = factory .create_campaign( - "title 2", "description 2", 20000, start_time_active, end_time_active, token + "title 2", "description 2", 20000, start_time_active, end_time_active, token, ); assert_eq!(old_class_hash, get_class_hash(active_campaign)); @@ -145,10 +145,10 @@ fn test_upgrade_campaign_class_hash() { ( factory.contract_address, CampaignFactory::Event::ClassHashUpdated( - CampaignFactory::ClassHashUpdated { new_class_hash } - ) - ) - ] + CampaignFactory::ClassHashUpdated { new_class_hash }, + ), + ), + ], ); // upgrade pending campaign @@ -163,9 +163,11 @@ fn test_upgrade_campaign_class_hash() { @array![ ( pending_campaign, - Campaign::Event::Upgraded(Campaign::Upgraded { implementation: new_class_hash }) - ) - ] + Campaign::Event::Upgraded( + Campaign::Upgraded { implementation: new_class_hash }, + ), + ), + ], ); // upgrade active campaign @@ -180,8 +182,10 @@ fn test_upgrade_campaign_class_hash() { @array![ ( active_campaign, - Campaign::Event::Upgraded(Campaign::Upgraded { implementation: new_class_hash }) - ) - ] + Campaign::Event::Upgraded( + Campaign::Upgraded { implementation: new_class_hash }, + ), + ), + ], ); } diff --git a/listings/applications/coin_flip/src/contract.cairo b/listings/applications/coin_flip/src/contract.cairo index cefe052e..74fec7b3 100644 --- a/listings/applications/coin_flip/src/contract.cairo +++ b/listings/applications/coin_flip/src/contract.cairo @@ -13,16 +13,16 @@ pub trait IPragmaVRF { requestor_address: ContractAddress, request_id: u64, random_words: Span, - calldata: Array + calldata: Array, ); } #[starknet::contract] pub mod CoinFlip { use core::num::traits::zero::Zero; - use starknet::{ContractAddress, get_caller_address, get_contract_address,}; + use starknet::{ContractAddress, get_caller_address, get_contract_address}; use starknet::storage::{ - Map, StoragePointerReadAccess, StoragePathEntry, StoragePointerWriteAccess + Map, StoragePointerReadAccess, StoragePathEntry, StoragePointerWriteAccess, }; use pragma_lib::abi::{IRandomnessDispatcher, IRandomnessDispatcherTrait}; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; @@ -52,7 +52,7 @@ pub mod CoinFlip { pub struct Landed { pub flip_id: u64, pub flipper: ContractAddress, - pub side: Side + pub side: Side, } #[derive(Drop, Debug, PartialEq, Serde)] @@ -79,7 +79,7 @@ pub mod CoinFlip { fn constructor( ref self: ContractState, randomness_contract_address: ContractAddress, - eth_address: ContractAddress + eth_address: ContractAddress, ) { assert(randomness_contract_address.is_non_zero(), Errors::INVALID_ADDRESS); assert(eth_address.is_non_zero(), Errors::INVALID_ADDRESS); @@ -106,11 +106,11 @@ pub mod CoinFlip { requestor_address: ContractAddress, request_id: u64, random_words: Span, - calldata: Array + calldata: Array, ) { let caller = get_caller_address(); assert( - caller == self.randomness_contract_address.read(), Errors::CALLER_NOT_RANDOMNESS + caller == self.randomness_contract_address.read(), Errors::CALLER_NOT_RANDOMNESS, ); let this = get_contract_address(); @@ -125,7 +125,7 @@ pub mod CoinFlip { fn _request_my_randomness(ref self: ContractState) -> u64 { let randomness_contract_address = self.randomness_contract_address.read(); let randomness_dispatcher = IRandomnessDispatcher { - contract_address: randomness_contract_address + contract_address: randomness_contract_address, }; let this = get_contract_address(); @@ -139,7 +139,7 @@ pub mod CoinFlip { // Request the randomness to be used to construct the winning combination let request_id = randomness_dispatcher .request_random( - nonce, this, CALLBACK_FEE_LIMIT, PUBLISH_DELAY, NUM_OF_WORDS, array![] + nonce, this, CALLBACK_FEE_LIMIT, PUBLISH_DELAY, NUM_OF_WORDS, array![], ); self.nonce.write(nonce + 1); diff --git a/listings/applications/coin_flip/src/mock_randomness.cairo b/listings/applications/coin_flip/src/mock_randomness.cairo index 54f2f327..493be34a 100644 --- a/listings/applications/coin_flip/src/mock_randomness.cairo +++ b/listings/applications/coin_flip/src/mock_randomness.cairo @@ -4,7 +4,7 @@ pub mod MockRandomness { use pragma_lib::types::RequestStatus; use starknet::{ContractAddress, ClassHash, get_caller_address, get_contract_address}; use starknet::storage::{ - Map, StoragePointerReadAccess, StoragePathEntry, StoragePointerWriteAccess + Map, StoragePointerReadAccess, StoragePathEntry, StoragePointerWriteAccess, }; use core::num::traits::zero::Zero; use coin_flip::contract::{IPragmaVRFDispatcher, IPragmaVRFDispatcherTrait}; @@ -41,7 +41,7 @@ pub mod MockRandomness { callback_fee_limit: u128, publish_delay: u64, num_words: u64, - calldata: Array + calldata: Array, ) -> u64 { let caller = get_caller_address(); let this = get_contract_address(); @@ -70,7 +70,7 @@ pub mod MockRandomness { callback_fee: u128, random_words: Span, proof: Span, - calldata: Array + calldata: Array, ) { let requestor = IPragmaVRFDispatcher { contract_address: callback_address }; requestor.receive_random_words(requestor_address, request_id, random_words, calldata); @@ -81,7 +81,7 @@ pub mod MockRandomness { } fn get_total_fees( - self: @ContractState, caller_address: ContractAddress, request_id: u64 + self: @ContractState, caller_address: ContractAddress, request_id: u64, ) -> u256 { self.total_fees.entry((caller_address, request_id)).read() } @@ -94,7 +94,7 @@ pub mod MockRandomness { ref self: ContractState, requestor_address: ContractAddress, request_id: u64, - new_status: RequestStatus + new_status: RequestStatus, ) { panic!("unimplemented") } @@ -107,24 +107,24 @@ pub mod MockRandomness { minimum_block_number: u64, callback_address: ContractAddress, callback_fee_limit: u128, - num_words: u64 + num_words: u64, ) { panic!("unimplemented") } fn get_pending_requests( - self: @ContractState, requestor_address: ContractAddress, offset: u64, max_len: u64 + self: @ContractState, requestor_address: ContractAddress, offset: u64, max_len: u64, ) -> Span { panic!("unimplemented") } fn get_request_status( - self: @ContractState, requestor_address: ContractAddress, request_id: u64 + self: @ContractState, requestor_address: ContractAddress, request_id: u64, ) -> RequestStatus { panic!("unimplemented") } fn requestor_current_index( - self: @ContractState, requestor_address: ContractAddress + self: @ContractState, requestor_address: ContractAddress, ) -> u64 { panic!("unimplemented") } @@ -141,7 +141,7 @@ pub mod MockRandomness { panic!("unimplemented") } fn refund_operation( - ref self: ContractState, caller_address: ContractAddress, request_id: u64 + ref self: ContractState, caller_address: ContractAddress, request_id: u64, ) { panic!("unimplemented") } @@ -156,7 +156,7 @@ pub mod MockRandomness { fn get_contract_balance(self: @ContractState) -> u256 { panic!("unimplemented") } - fn get_admin_address(self: @ContractState,) -> ContractAddress { + fn get_admin_address(self: @ContractState) -> ContractAddress { panic!("unimplemented") } fn set_admin_address(ref self: ContractState, new_admin_address: ContractAddress) { diff --git a/listings/applications/coin_flip/src/tests.cairo b/listings/applications/coin_flip/src/tests.cairo index bdaa0466..74bb63e9 100644 --- a/listings/applications/coin_flip/src/tests.cairo +++ b/listings/applications/coin_flip/src/tests.cairo @@ -4,7 +4,7 @@ use coin_flip::contract::{ use starknet::{ContractAddress, contract_address_const}; use snforge_std::{ declare, start_cheat_caller_address, stop_cheat_caller_address, spy_events, - EventSpyAssertionsTrait, DeclareResultTrait, ContractClassTrait + EventSpyAssertionsTrait, DeclareResultTrait, ContractClassTrait, }; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use pragma_lib::abi::{IRandomnessDispatcher, IRandomnessDispatcherTrait}; @@ -63,9 +63,7 @@ fn test_all_relevant_random_words() { (1001, Side::Tails, 8), (12345654321, Side::Tails, 9), ]; - for ( - random_word, expected_side, expected_request_id - ) in random_words { + for (random_word, expected_side, expected_request_id) in random_words { _flip_request( coin_flip, randomness, @@ -74,7 +72,7 @@ fn test_all_relevant_random_words() { expected_request_id, CALLBACK_FEE_LIMIT / 5 * 3, random_word, - expected_side + expected_side, ); } } @@ -89,7 +87,7 @@ fn test_multiple_flips() { stop_cheat_caller_address(eth.contract_address); _flip_request( - coin_flip, randomness, eth, deployer, 0, CALLBACK_FEE_LIMIT / 5 * 3, 123456789, Side::Tails + coin_flip, randomness, eth, deployer, 0, CALLBACK_FEE_LIMIT / 5 * 3, 123456789, Side::Tails, ); _flip_request( coin_flip, @@ -99,7 +97,7 @@ fn test_multiple_flips() { 1, CALLBACK_FEE_LIMIT / 4 * 3, 12345654321, - Side::Tails + Side::Tails, ); _flip_request(coin_flip, randomness, eth, deployer, 2, CALLBACK_FEE_LIMIT, 3, Side::Tails); } @@ -112,7 +110,7 @@ fn _flip_request( expected_request_id: u64, expected_callback_fee: u128, random_word: felt252, - expected_side: Side + expected_side: Side, ) { let original_balance = eth.balance_of(coin_flip.contract_address); @@ -128,17 +126,17 @@ fn _flip_request( ( coin_flip.contract_address, CoinFlip::Event::Flipped( - CoinFlip::Flipped { flip_id: expected_request_id, flipper: deployer } - ) - ) - ] + CoinFlip::Flipped { flip_id: expected_request_id, flipper: deployer }, + ), + ), + ], ); let post_flip_balance = eth.balance_of(coin_flip.contract_address); assert_eq!( post_flip_balance, original_balance - - randomness.get_total_fees(coin_flip.contract_address, expected_request_id) + - randomness.get_total_fees(coin_flip.contract_address, expected_request_id), ); randomness @@ -152,7 +150,7 @@ fn _flip_request( expected_callback_fee, array![random_word].span(), array![].span(), - array![] + array![], ); spy @@ -162,16 +160,16 @@ fn _flip_request( coin_flip.contract_address, CoinFlip::Event::Landed( CoinFlip::Landed { - flip_id: expected_request_id, flipper: deployer, side: expected_side - } - ) - ) - ] + flip_id: expected_request_id, flipper: deployer, side: expected_side, + }, + ), + ), + ], ); assert_eq!( eth.balance_of(coin_flip.contract_address), - post_flip_balance + (CALLBACK_FEE_LIMIT - expected_callback_fee).into() + post_flip_balance + (CALLBACK_FEE_LIMIT - expected_callback_fee).into(), ); } @@ -201,15 +199,15 @@ fn test_two_consecutive_flips() { @array![ ( coin_flip.contract_address, - CoinFlip::Event::Flipped(CoinFlip::Flipped { flip_id: 0, flipper: deployer }) + CoinFlip::Event::Flipped(CoinFlip::Flipped { flip_id: 0, flipper: deployer }), ), ( coin_flip.contract_address, CoinFlip::Event::Flipped( - CoinFlip::Flipped { flip_id: 1, flipper: other_flipper } - ) - ) - ] + CoinFlip::Flipped { flip_id: 1, flipper: other_flipper }, + ), + ), + ], ); let post_flip_balance = eth.balance_of(coin_flip.contract_address); @@ -234,7 +232,7 @@ fn test_two_consecutive_flips() { expected_callback_fee, array![random_word_deployer].span(), array![].span(), - array![] + array![], ); randomness .submit_random( @@ -247,7 +245,7 @@ fn test_two_consecutive_flips() { expected_callback_fee, array![random_word_other_flipper].span(), array![].span(), - array![] + array![], ); spy @@ -257,24 +255,24 @@ fn test_two_consecutive_flips() { coin_flip.contract_address, CoinFlip::Event::Landed( CoinFlip::Landed { - flip_id: 0, flipper: deployer, side: expected_side_deployer - } - ) + flip_id: 0, flipper: deployer, side: expected_side_deployer, + }, + ), ), ( coin_flip.contract_address, CoinFlip::Event::Landed( CoinFlip::Landed { - flip_id: 1, flipper: other_flipper, side: expected_side_other_flipper - } - ) - ) - ] + flip_id: 1, flipper: other_flipper, side: expected_side_other_flipper, + }, + ), + ), + ], ); assert_eq!( eth.balance_of(coin_flip.contract_address), - post_flip_balance + (CALLBACK_FEE_LIMIT - expected_callback_fee).into() * 2 + post_flip_balance + (CALLBACK_FEE_LIMIT - expected_callback_fee).into() * 2, ); } diff --git a/listings/applications/components/src/countable.cairo b/listings/applications/components/src/countable.cairo index 7a470909..36e905f8 100644 --- a/listings/applications/components/src/countable.cairo +++ b/listings/applications/components/src/countable.cairo @@ -16,7 +16,7 @@ pub mod countable_component { #[embeddable_as(Countable)] impl CountableImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of super::ICountable> { fn get(self: @ComponentState) -> u32 { self.countable_value.read() @@ -44,7 +44,7 @@ mod CountableContract { #[event] #[derive(Drop, starknet::Event)] enum Event { - CountableEvent: countable_component::Event + CountableEvent: countable_component::Event, } #[abi(embed_v0)] @@ -57,13 +57,12 @@ mod test { use super::CountableContract; use super::{ICountableDispatcher, ICountableDispatcherTrait}; use starknet::syscalls::deploy_syscall; - use starknet::SyscallResultTrait; fn deploy_countable() -> ICountableDispatcher { let (address, _) = deploy_syscall( - CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ICountableDispatcher { contract_address: address } } diff --git a/listings/applications/components/src/others/switch_collision.cairo b/listings/applications/components/src/others/switch_collision.cairo index fbb554a1..8db6e2a9 100644 --- a/listings/applications/components/src/others/switch_collision.cairo +++ b/listings/applications/components/src/others/switch_collision.cairo @@ -19,6 +19,7 @@ pub mod SwitchCollisionContract { // [!region storage] #[storage] + #[allow(starknet::colliding_storage_paths)] struct Storage { switchable_value: bool, #[substorage(v0)] @@ -53,16 +54,15 @@ pub mod SwitchCollisionContract { mod switch_collision_tests { use components::switchable::{ISwitchableDispatcher, ISwitchableDispatcherTrait}; use super::{ - SwitchCollisionContract, ISwitchCollisionDispatcher, ISwitchCollisionDispatcherTrait + SwitchCollisionContract, ISwitchCollisionDispatcher, ISwitchCollisionDispatcherTrait, }; - use starknet::SyscallResultTrait; use starknet::syscalls::deploy_syscall; fn deploy() -> (ISwitchCollisionDispatcher, ISwitchableDispatcher) { let (contract_address, _) = deploy_syscall( - SwitchCollisionContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + SwitchCollisionContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ( ISwitchCollisionDispatcher { contract_address }, diff --git a/listings/applications/components/src/ownable.cairo b/listings/applications/components/src/ownable.cairo index cd3698d9..accb3e19 100644 --- a/listings/applications/components/src/ownable.cairo +++ b/listings/applications/components/src/ownable.cairo @@ -29,24 +29,24 @@ pub mod ownable_component { #[derive(Drop, Debug, PartialEq, starknet::Event)] pub struct OwnershipTransferredEvent { pub previous: ContractAddress, - pub new: ContractAddress + pub new: ContractAddress, } #[derive(Drop, Debug, PartialEq, starknet::Event)] pub struct OwnershipRenouncedEvent { - pub previous: ContractAddress + pub previous: ContractAddress, } #[event] #[derive(Drop, Debug, PartialEq, starknet::Event)] pub enum Event { OwnershipTransferredEvent: OwnershipTransferredEvent, - OwnershipRenouncedEvent: OwnershipRenouncedEvent + OwnershipRenouncedEvent: OwnershipRenouncedEvent, } #[embeddable_as(Ownable)] pub impl OwnableImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of super::IOwnable> { fn owner(self: @ComponentState) -> ContractAddress { self.ownable_owner.read() @@ -65,7 +65,7 @@ pub mod ownable_component { #[generate_trait] pub impl OwnableInternalImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of OwnableInternalTrait { fn _assert_only_owner(self: @ComponentState) { let caller = get_caller_address(); @@ -84,7 +84,7 @@ pub mod ownable_component { self.ownable_owner.write(new); self .emit( - Event::OwnershipTransferredEvent(OwnershipTransferredEvent { previous, new }) + Event::OwnershipTransferredEvent(OwnershipTransferredEvent { previous, new }), ); } @@ -132,15 +132,15 @@ mod test { use super::ownable_component::{OwnershipRenouncedEvent, OwnershipTransferredEvent}; use super::{IOwnableDispatcher, IOwnableDispatcherTrait}; use starknet::ContractAddress; - use starknet::{syscalls::deploy_syscall, SyscallResultTrait, contract_address_const}; + use starknet::{syscalls::deploy_syscall, contract_address_const}; use starknet::testing::{set_contract_address}; use core::num::traits::Zero; fn deploy() -> (IOwnableDispatcher, ContractAddress) { let (contract_address, _) = deploy_syscall( - OwnedContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + OwnedContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); (IOwnableDispatcher { contract_address }, contract_address) } @@ -167,9 +167,9 @@ mod test { starknet::testing::pop_log(address), Option::Some( OwnedContract::Event::OwnableEvent( - OwnershipTransferredEvent { previous: contract_address, new: new_owner }.into() - ) - ) + OwnershipTransferredEvent { previous: contract_address, new: new_owner }.into(), + ), + ), ); } @@ -204,9 +204,9 @@ mod test { starknet::testing::pop_log(address), Option::Some( OwnedContract::Event::OwnableEvent( - OwnershipRenouncedEvent { previous: contract_address }.into() - ) - ) + OwnershipRenouncedEvent { previous: contract_address }.into(), + ), + ), ); } diff --git a/listings/applications/components/src/switchable.cairo b/listings/applications/components/src/switchable.cairo index a6dcd4fd..71f89f5b 100644 --- a/listings/applications/components/src/switchable.cairo +++ b/listings/applications/components/src/switchable.cairo @@ -27,7 +27,7 @@ pub mod switchable_component { #[embeddable_as(Switchable)] impl SwitchableImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of super::ISwitchable> { fn is_on(self: @ComponentState) -> bool { self.switchable_value.read() @@ -41,7 +41,7 @@ pub mod switchable_component { #[generate_trait] pub impl SwitchableInternalImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of SwitchableInternalTrait { fn _off(ref self: ComponentState) { self.switchable_value.write(false); @@ -90,13 +90,12 @@ mod test { use super::switchable_component::SwitchEvent; use super::{ISwitchableDispatcher, ISwitchableDispatcherTrait}; use starknet::{syscalls::deploy_syscall, ContractAddress}; - use starknet::SyscallResultTrait; fn deploy() -> (ISwitchableDispatcher, ContractAddress) { let (address, _) = deploy_syscall( - SwitchContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + SwitchContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); (ISwitchableDispatcher { contract_address: address }, address) } @@ -113,7 +112,7 @@ mod test { assert_eq!(switchable.is_on(), true); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(SwitchContract::Event::SwitchableEvent(SwitchEvent {}.into())) + Option::Some(SwitchContract::Event::SwitchableEvent(SwitchEvent {}.into())), ); } diff --git a/listings/applications/components_dependencies/src/contract_countable.cairo b/listings/applications/components_dependencies/src/contract_countable.cairo index 42f1d76a..7de2ec71 100644 --- a/listings/applications/components_dependencies/src/contract_countable.cairo +++ b/listings/applications/components_dependencies/src/contract_countable.cairo @@ -14,7 +14,7 @@ mod CountableContract { struct Storage { #[substorage(v0)] counter: countable_component::Storage, - switch: bool + switch: bool, } // Implementation of the dependency: @@ -48,16 +48,15 @@ mod tests { use components::countable::{ICountableDispatcher, ICountableDispatcherTrait}; use components::switchable::{ISwitchableDispatcher, ISwitchableDispatcherTrait}; - use starknet::SyscallResultTrait; use starknet::syscalls::deploy_syscall; fn deploy() -> (ICountableDispatcher, ISwitchableDispatcher) { let (contract_address, _) = deploy_syscall( - CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); - (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address },) + (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address }) } #[test] diff --git a/listings/applications/components_dependencies/src/contract_countable_switchable.cairo b/listings/applications/components_dependencies/src/contract_countable_switchable.cairo index d190e997..b8aa72f9 100644 --- a/listings/applications/components_dependencies/src/contract_countable_switchable.cairo +++ b/listings/applications/components_dependencies/src/contract_countable_switchable.cairo @@ -18,7 +18,7 @@ mod CountableContract { #[substorage(v0)] counter: countable_component::Storage, #[substorage(v0)] - switch: switchable_component::Storage + switch: switchable_component::Storage, } #[constructor] @@ -41,16 +41,15 @@ mod tests { use components::countable::{ICountableDispatcher, ICountableDispatcherTrait}; use components::switchable::{ISwitchableDispatcher, ISwitchableDispatcherTrait}; - use starknet::SyscallResultTrait; use starknet::syscalls::deploy_syscall; fn deploy() -> (ICountableDispatcher, ISwitchableDispatcher) { let (contract_address, _) = deploy_syscall( - CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); - (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address },) + (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address }) } #[test] diff --git a/listings/applications/components_dependencies/src/contract_countable_switchable_internal.cairo b/listings/applications/components_dependencies/src/contract_countable_switchable_internal.cairo index b79592aa..2768495b 100644 --- a/listings/applications/components_dependencies/src/contract_countable_switchable_internal.cairo +++ b/listings/applications/components_dependencies/src/contract_countable_switchable_internal.cairo @@ -18,7 +18,7 @@ pub mod CountableContract { #[substorage(v0)] counter: countable_component::Storage, #[substorage(v0)] - switch: switchable_component::Storage + switch: switchable_component::Storage, } #[constructor] @@ -41,16 +41,15 @@ mod tests { use components::countable::{ICountableDispatcher, ICountableDispatcherTrait}; use components::switchable::{ISwitchableDispatcher, ISwitchableDispatcherTrait}; - use starknet::SyscallResultTrait; use starknet::syscalls::deploy_syscall; fn deploy() -> (ICountableDispatcher, ISwitchableDispatcher) { let (contract_address, _) = deploy_syscall( - CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CountableContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); - (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address },) + (ICountableDispatcher { contract_address }, ISwitchableDispatcher { contract_address }) } #[test] diff --git a/listings/applications/components_dependencies/src/countable_dep_switch.cairo b/listings/applications/components_dependencies/src/countable_dep_switch.cairo index ec59fa0d..3d8a7dce 100644 --- a/listings/applications/components_dependencies/src/countable_dep_switch.cairo +++ b/listings/applications/components_dependencies/src/countable_dep_switch.cairo @@ -13,7 +13,7 @@ pub mod countable_component { // [!region impl] #[embeddable_as(Countable)] impl CountableImpl< - TContractState, +HasComponent, +ISwitchable + TContractState, +HasComponent, +ISwitchable, > of ICountable> { fn get(self: @ComponentState) -> u32 { self.countable_value.read() @@ -68,13 +68,12 @@ mod test { use super::MockContract; use components::countable::{ICountableDispatcher, ICountableDispatcherTrait}; use starknet::syscalls::deploy_syscall; - use starknet::SyscallResultTrait; fn deploy_countable() -> ICountableDispatcher { let (contract_address, _) = deploy_syscall( - MockContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + MockContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ICountableDispatcher { contract_address: contract_address } } diff --git a/listings/applications/components_dependencies/src/countable_internal_dep_switch.cairo b/listings/applications/components_dependencies/src/countable_internal_dep_switch.cairo index c6c82ac6..d055128c 100644 --- a/listings/applications/components_dependencies/src/countable_internal_dep_switch.cairo +++ b/listings/applications/components_dependencies/src/countable_internal_dep_switch.cairo @@ -19,17 +19,17 @@ pub mod countable_component { TContractState, +HasComponent, +switchable_component::HasComponent, - +Drop + +Drop, > of GetSwitchableTrait { fn get_switchable( - self: @ComponentState + self: @ComponentState, ) -> @switchable_component::ComponentState { let contract = self.get_contract(); switchable_component::HasComponent::::get_component(contract) } fn get_switchable_mut( - ref self: ComponentState + ref self: ComponentState, ) -> switchable_component::ComponentState { let mut contract = self.get_contract_mut(); switchable_component::HasComponent::::get_component_mut(ref contract) @@ -42,7 +42,7 @@ pub mod countable_component { +HasComponent, +ISwitchable, +switchable_component::HasComponent, - +Drop + +Drop, > of ICountable> { fn get(self: @ComponentState) -> u32 { self.countable_value.read() diff --git a/listings/applications/constant_product_amm/src/contracts.cairo b/listings/applications/constant_product_amm/src/contracts.cairo index b5649115..9b203a8a 100644 --- a/listings/applications/constant_product_amm/src/contracts.cairo +++ b/listings/applications/constant_product_amm/src/contracts.cairo @@ -31,7 +31,7 @@ pub mod ConstantProductAmm { #[constructor] fn constructor( - ref self: ContractState, token0: ContractAddress, token1: ContractAddress, fee: u16 + ref self: ContractState, token0: ContractAddress, token1: ContractAddress, fee: u16, ) { // assert(fee <= 1000, 'fee > 1000'); self.token0.write(IERC20Dispatcher { contract_address: token0 }); @@ -61,7 +61,7 @@ pub mod ConstantProductAmm { assert( token == self.token0.read().contract_address || token == self.token1.read().contract_address, - 'invalid token' + 'invalid token', ); token == self.token0.read().contract_address } @@ -83,11 +83,11 @@ pub mod ConstantProductAmm { let is_token0: bool = self.select_token(token_in); let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = ( - self.token0.read(), self.token1.read() + self.token0.read(), self.token1.read(), ); let (reserve0, reserve1): (u256, u256) = (self.reserve0.read(), self.reserve1.read()); let ( - token_in, token_out, reserve_in, reserve_out + token_in, token_out, reserve_in, reserve_out, ): (IERC20Dispatcher, IERC20Dispatcher, u256, u256) = if (is_token0) { (token0, token1, reserve0, reserve1) @@ -121,7 +121,7 @@ pub mod ConstantProductAmm { let caller = get_caller_address(); let this = get_contract_address(); let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = ( - self.token0.read(), self.token1.read() + self.token0.read(), self.token1.read(), ); token0.transfer_from(caller, this, amount0); @@ -196,7 +196,7 @@ pub mod ConstantProductAmm { (amount0 * amount1).sqrt().into() } else { PrivateFunctions::min( - amount0 * total_supply / reserve0, amount1 * total_supply / reserve1 + amount0 * total_supply / reserve0, amount1 * total_supply / reserve1, ) }; assert(shares > 0, 'shares = 0'); @@ -210,7 +210,7 @@ pub mod ConstantProductAmm { let caller = get_caller_address(); let this = get_contract_address(); let (token0, token1): (IERC20Dispatcher, IERC20Dispatcher) = ( - self.token0.read(), self.token1.read() + self.token0.read(), self.token1.read(), ); // Claim @@ -251,7 +251,7 @@ pub mod ConstantProductAmm { let total_supply = self.total_supply.read(); let (amount0, amount1): (u256, u256) = ( - (shares * bal0) / total_supply, (shares * bal1) / total_supply + (shares * bal0) / total_supply, (shares * bal1) / total_supply, ); assert(amount0 > 0 && amount1 > 0, 'amount0 or amount1 = 0'); diff --git a/listings/applications/constant_product_amm/src/tests.cairo b/listings/applications/constant_product_amm/src/tests.cairo index 7a87e616..e1d1970a 100644 --- a/listings/applications/constant_product_amm/src/tests.cairo +++ b/listings/applications/constant_product_amm/src/tests.cairo @@ -13,14 +13,14 @@ pub mod ERC20Token { #[storage] struct Storage { #[substorage(v0)] - erc20: ERC20Component::Storage + erc20: ERC20Component::Storage, } #[event] #[derive(Drop, starknet::Event)] enum Event { #[flat] - ERC20Event: ERC20Component::Event + ERC20Event: ERC20Component::Event, } #[constructor] @@ -29,7 +29,7 @@ pub mod ERC20Token { initial_supply: u256, recipient: ContractAddress, name: ByteArray, - symbol: ByteArray + symbol: ByteArray, ) { self.erc20.initializer(name, symbol); self.erc20.mint(recipient, initial_supply); diff --git a/listings/applications/crowdfunding/src/campaign.cairo b/listings/applications/crowdfunding/src/campaign.cairo index 607eae69..684093f7 100644 --- a/listings/applications/crowdfunding/src/campaign.cairo +++ b/listings/applications/crowdfunding/src/campaign.cairo @@ -37,8 +37,7 @@ pub mod Campaign { use core::num::traits::Zero; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use starknet::{ - ClassHash, ContractAddress, SyscallResultTrait, get_block_timestamp, get_caller_address, - get_contract_address + ClassHash, ContractAddress, get_block_timestamp, get_caller_address, get_contract_address, }; use components::ownable::ownable_component; use super::pledgeable::pledgeable_component; @@ -125,7 +124,7 @@ pub mod Campaign { #[derive(Drop, starknet::Event)] pub struct Upgraded { - pub implementation: ClassHash + pub implementation: ClassHash, } pub mod Errors { @@ -296,14 +295,15 @@ pub mod Campaign { if let Option::Some(end_time) = new_end_time { assert(end_time >= get_block_timestamp(), Errors::END_BEFORE_NOW); assert( - end_time <= get_block_timestamp() + NINETY_DAYS, Errors::END_BIGGER_THAN_MAX + end_time <= get_block_timestamp() + NINETY_DAYS, + Errors::END_BIGGER_THAN_MAX, ); self.end_time.write(end_time); }; self._refund_all("contract upgraded"); } - starknet::syscalls::replace_class_syscall(impl_hash).unwrap_syscall(); + starknet::syscalls::replace_class_syscall(impl_hash).unwrap(); self.emit(Event::Upgraded(Upgraded { implementation: impl_hash })); } diff --git a/listings/applications/crowdfunding/src/campaign/pledgeable.cairo b/listings/applications/crowdfunding/src/campaign/pledgeable.cairo index 06ffbe5c..2b90459a 100644 --- a/listings/applications/crowdfunding/src/campaign/pledgeable.cairo +++ b/listings/applications/crowdfunding/src/campaign/pledgeable.cairo @@ -18,7 +18,7 @@ pub mod pledgeable_component { use starknet::ContractAddress; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; #[storage] @@ -39,7 +39,7 @@ pub mod pledgeable_component { #[embeddable_as(Pledgeable)] pub impl PledgeableImpl< - TContractState, +HasComponent + TContractState, +HasComponent, > of super::IPledgeable> { fn add(ref self: ComponentState, pledger: ContractAddress, amount: u256) { let old_amount: u256 = self.pledger_to_amount.read(pledger); @@ -134,7 +134,7 @@ mod tests { #[event] #[derive(Drop, starknet::Event)] enum Event { - PledgeableEvent: pledgeable_component::Event + PledgeableEvent: pledgeable_component::Event, } #[abi(embed_v0)] diff --git a/listings/applications/crowdfunding/src/mock_upgrade.cairo b/listings/applications/crowdfunding/src/mock_upgrade.cairo index de4c5e60..ee89427c 100644 --- a/listings/applications/crowdfunding/src/mock_upgrade.cairo +++ b/listings/applications/crowdfunding/src/mock_upgrade.cairo @@ -5,8 +5,7 @@ pub mod MockUpgrade { use core::num::traits::Zero; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use starknet::{ - ClassHash, ContractAddress, SyscallResultTrait, get_block_timestamp, get_caller_address, - get_contract_address + ClassHash, ContractAddress, get_block_timestamp, get_caller_address, get_contract_address, }; use components::ownable::ownable_component; use crowdfunding::campaign::pledgeable::pledgeable_component; @@ -93,7 +92,7 @@ pub mod MockUpgrade { #[derive(Drop, starknet::Event)] pub struct Upgraded { - pub implementation: ClassHash + pub implementation: ClassHash, } const NINETY_DAYS: u64 = 90 * 24 * 60 * 60; @@ -237,14 +236,15 @@ pub mod MockUpgrade { if let Option::Some(end_time) = new_end_time { assert(end_time >= get_block_timestamp(), Errors::END_BEFORE_NOW); assert( - end_time <= get_block_timestamp() + NINETY_DAYS, Errors::END_BIGGER_THAN_MAX + end_time <= get_block_timestamp() + NINETY_DAYS, + Errors::END_BIGGER_THAN_MAX, ); self.end_time.write(end_time); }; self._refund_all("contract upgraded"); } - starknet::syscalls::replace_class_syscall(impl_hash).unwrap_syscall(); + starknet::syscalls::replace_class_syscall(impl_hash).unwrap(); self.emit(Event::Upgraded(Upgraded { implementation: impl_hash })); } diff --git a/listings/applications/crowdfunding/src/tests.cairo b/listings/applications/crowdfunding/src/tests.cairo index 11f2aaa5..57f0ecec 100644 --- a/listings/applications/crowdfunding/src/tests.cairo +++ b/listings/applications/crowdfunding/src/tests.cairo @@ -1,8 +1,8 @@ -use starknet::{ContractAddress, get_block_timestamp, contract_address_const,}; +use starknet::{ContractAddress, get_block_timestamp, contract_address_const}; use snforge_std::{ declare, ContractClass, ContractClassTrait, start_cheat_caller_address, stop_cheat_caller_address, spy_events, EventSpyAssertionsTrait, get_class_hash, - DeclareResultTrait, start_cheat_block_timestamp_global + DeclareResultTrait, start_cheat_block_timestamp_global, }; use crowdfunding::campaign::{Campaign, ICampaignDispatcher, ICampaignDispatcherTrait}; @@ -17,7 +17,7 @@ fn deploy( goal: u256, start_time: u64, end_time: u64, - token: ContractAddress + token: ContractAddress, ) -> ICampaignDispatcher { let creator = contract_address_const::<'creator'>(); let mut calldata: Array:: = array![]; @@ -35,7 +35,7 @@ fn deploy( } fn deploy_with_token( - contract: ContractClass, token: ContractClass + contract: ContractClass, token: ContractClass, ) -> (ICampaignDispatcher, IERC20Dispatcher) { // define ERC20 data let token_name: ByteArray = "My Token"; @@ -65,7 +65,7 @@ fn deploy_with_token( let start_time = get_block_timestamp(); let end_time = start_time + 60; let campaign_dispatcher = deploy( - contract, "title 1", "description 1", 10000, start_time, end_time, token_address + contract, "title 1", "description 1", 10000, start_time, end_time, token_address, ); // approve the pledges for each pledger @@ -96,7 +96,7 @@ fn test_deploy() { 10000, start_time, end_time, - contract_address_const::<'token'>() + contract_address_const::<'token'>(), ); let details = campaign.get_details(); @@ -143,10 +143,10 @@ fn test_successful_campaign() { ( campaign.contract_address, Campaign::Event::PledgeMade( - Campaign::PledgeMade { pledger: pledger_1, amount: 3000 } - ) - ) - ] + Campaign::PledgeMade { pledger: pledger_1, amount: 3000 }, + ), + ), + ], ); // 2nd donation @@ -163,10 +163,10 @@ fn test_successful_campaign() { ( campaign.contract_address, Campaign::Event::PledgeMade( - Campaign::PledgeMade { pledger: pledger_2, amount: 500 } - ) - ) - ] + Campaign::PledgeMade { pledger: pledger_2, amount: 500 }, + ), + ), + ], ); // 3rd donation @@ -183,10 +183,10 @@ fn test_successful_campaign() { ( campaign.contract_address, Campaign::Event::PledgeMade( - Campaign::PledgeMade { pledger: pledger_3, amount: 7000 } - ) - ) - ] + Campaign::PledgeMade { pledger: pledger_3, amount: 7000 }, + ), + ), + ], ); // claim @@ -202,9 +202,9 @@ fn test_successful_campaign() { @array![ ( campaign.contract_address, - Campaign::Event::Claimed(Campaign::Claimed { amount: 10500 }) - ) - ] + Campaign::Event::Claimed(Campaign::Claimed { amount: 10500 }), + ), + ], ); } @@ -230,9 +230,11 @@ fn test_upgrade_class_hash() { @array![ ( campaign.contract_address, - Campaign::Event::Upgraded(Campaign::Upgraded { implementation: new_class_hash }) - ) - ] + Campaign::Event::Upgraded( + Campaign::Upgraded { implementation: new_class_hash }, + ), + ), + ], ); // test active campaign @@ -268,15 +270,17 @@ fn test_upgrade_class_hash() { @array![ ( campaign.contract_address, - Campaign::Event::Upgraded(Campaign::Upgraded { implementation: new_class_hash }) + Campaign::Event::Upgraded( + Campaign::Upgraded { implementation: new_class_hash }, + ), ), ( campaign.contract_address, Campaign::Event::RefundedAll( - Campaign::RefundedAll { reason: "contract upgraded" } - ) - ) - ] + Campaign::RefundedAll { reason: "contract upgraded" }, + ), + ), + ], ); } @@ -325,13 +329,13 @@ fn test_cancel() { @array![ ( campaign.contract_address, - Campaign::Event::RefundedAll(Campaign::RefundedAll { reason: "testing" }) + Campaign::Event::RefundedAll(Campaign::RefundedAll { reason: "testing" }), ), ( campaign.contract_address, - Campaign::Event::Canceled(Campaign::Canceled { reason: "testing" }) - ) - ] + Campaign::Event::Canceled(Campaign::Canceled { reason: "testing" }), + ), + ], ); // test failed campaign @@ -376,13 +380,13 @@ fn test_cancel() { @array![ ( campaign.contract_address, - Campaign::Event::RefundedAll(Campaign::RefundedAll { reason: "testing" }) + Campaign::Event::RefundedAll(Campaign::RefundedAll { reason: "testing" }), ), ( campaign.contract_address, - Campaign::Event::Canceled(Campaign::Canceled { reason: "testing" }) - ) - ] + Campaign::Event::Canceled(Campaign::Canceled { reason: "testing" }), + ), + ], ); } @@ -391,7 +395,7 @@ fn test_refund() { // setup let (campaign, token) = deploy_with_token( *declare("Campaign").unwrap().contract_class(), - *declare("ERC20Upgradeable").unwrap().contract_class() + *declare("ERC20Upgradeable").unwrap().contract_class(), ); let mut spy = spy_events(); let creator = contract_address_const::<'creator'>(); @@ -430,11 +434,11 @@ fn test_refund() { campaign.contract_address, Campaign::Event::Refunded( Campaign::Refunded { - pledger: pledger_1, amount: amount_1, reason: "testing" - } - ) - ) - ] + pledger: pledger_1, amount: amount_1, reason: "testing", + }, + ), + ), + ], ); } @@ -443,7 +447,7 @@ fn test_unpledge() { // setup let (campaign, token) = deploy_with_token( *declare("Campaign").unwrap().contract_class(), - *declare("ERC20Upgradeable").unwrap().contract_class() + *declare("ERC20Upgradeable").unwrap().contract_class(), ); let mut spy = spy_events(); let pledger = contract_address_const::<'pledger_1'>(); @@ -469,9 +473,9 @@ fn test_unpledge() { ( campaign.contract_address, Campaign::Event::Unpledged( - Campaign::Unpledged { pledger, amount, reason: "testing" } - ) - ) - ] + Campaign::Unpledged { pledger, amount, reason: "testing" }, + ), + ), + ], ); } diff --git a/listings/applications/erc20/src/token.cairo b/listings/applications/erc20/src/token.cairo index 467e6e85..4baa0e43 100644 --- a/listings/applications/erc20/src/token.cairo +++ b/listings/applications/erc20/src/token.cairo @@ -9,19 +9,19 @@ pub trait IERC20 { fn get_total_supply(self: @TContractState) -> felt252; fn balance_of(self: @TContractState, account: ContractAddress) -> felt252; fn allowance( - self: @TContractState, owner: ContractAddress, spender: ContractAddress + self: @TContractState, owner: ContractAddress, spender: ContractAddress, ) -> felt252; fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252); fn transfer_from( ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, - amount: felt252 + amount: felt252, ); fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252); fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: felt252); fn decrease_allowance( - ref self: TContractState, spender: ContractAddress, subtracted_value: felt252 + ref self: TContractState, spender: ContractAddress, subtracted_value: felt252, ); } // [!endregion interface] @@ -35,7 +35,7 @@ pub mod erc20 { use starknet::ContractAddress; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; #[storage] @@ -83,7 +83,7 @@ pub mod erc20 { name: felt252, decimals: u8, initial_supply: felt252, - symbol: felt252 + symbol: felt252, ) { self.name.write(name); self.symbol.write(symbol); @@ -114,7 +114,7 @@ pub mod erc20 { } fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress + self: @ContractState, owner: ContractAddress, spender: ContractAddress, ) -> felt252 { self.allowances.read((owner, spender)) } @@ -128,7 +128,7 @@ pub mod erc20 { ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, - amount: felt252 + amount: felt252, ) { let caller = get_caller_address(); self.spend_allowance(sender, caller, amount); @@ -141,22 +141,22 @@ pub mod erc20 { } fn increase_allowance( - ref self: ContractState, spender: ContractAddress, added_value: felt252 + ref self: ContractState, spender: ContractAddress, added_value: felt252, ) { let caller = get_caller_address(); self .approve_helper( - caller, spender, self.allowances.read((caller, spender)) + added_value + caller, spender, self.allowances.read((caller, spender)) + added_value, ); } fn decrease_allowance( - ref self: ContractState, spender: ContractAddress, subtracted_value: felt252 + ref self: ContractState, spender: ContractAddress, subtracted_value: felt252, ) { let caller = get_caller_address(); self .approve_helper( - caller, spender, self.allowances.read((caller, spender)) - subtracted_value + caller, spender, self.allowances.read((caller, spender)) - subtracted_value, ); } } @@ -167,7 +167,7 @@ pub mod erc20 { ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, - amount: felt252 + amount: felt252, ) { assert(sender.is_non_zero(), Errors::TRANSFER_FROM_ZERO); assert(recipient.is_non_zero(), Errors::TRANSFER_TO_ZERO); @@ -180,7 +180,7 @@ pub mod erc20 { ref self: ContractState, owner: ContractAddress, spender: ContractAddress, - amount: felt252 + amount: felt252, ) { let allowance = self.allowances.read((owner, spender)); self.allowances.write((owner, spender), allowance - amount); @@ -190,7 +190,7 @@ pub mod erc20 { ref self: ContractState, owner: ContractAddress, spender: ContractAddress, - amount: felt252 + amount: felt252, ) { assert(spender.is_non_zero(), Errors::APPROVE_TO_ZERO); self.allowances.write((owner, spender), amount); @@ -207,9 +207,9 @@ pub mod erc20 { .emit( Event::Transfer( Transfer { - from: contract_address_const::<0>(), to: recipient, value: amount - } - ) + from: contract_address_const::<0>(), to: recipient, value: amount, + }, + ), ); } } @@ -220,9 +220,7 @@ pub mod erc20 { mod tests { use super::{erc20, IERC20Dispatcher, IERC20DispatcherTrait, erc20::{Event, Transfer, Approval}}; - use starknet::{ - ContractAddress, SyscallResultTrait, syscalls::deploy_syscall, contract_address_const - }; + use starknet::{ContractAddress, syscalls::deploy_syscall, contract_address_const}; use core::num::traits::Zero; use starknet::testing::set_contract_address; @@ -239,16 +237,16 @@ mod tests { erc20::TEST_CLASS_HASH.try_into().unwrap(), recipient.into(), array![recipient.into(), token_name, decimals.into(), initial_supply, symbols].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); (IERC20Dispatcher { contract_address }, contract_address) } #[test] - #[should_panic(expected: ('ERC20: mint to 0', 'CONSTRUCTOR_FAILED'))] + #[should_panic] fn test_deploy_when_recipient_is_address_zero() { let recipient: ContractAddress = Zero::zero(); @@ -256,9 +254,9 @@ mod tests { erc20::TEST_CLASS_HASH.try_into().unwrap(), recipient.into(), array![recipient.into(), token_name, decimals.into(), initial_supply, symbols].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); } #[test] fn test_deploy_success() { @@ -268,9 +266,9 @@ mod tests { starknet::testing::pop_log(contract_address), Option::Some( Event::Transfer( - Transfer { from: Zero::zero(), to: recipient, value: initial_supply } - ) - ) + Transfer { from: Zero::zero(), to: recipient, value: initial_supply }, + ), + ), ); } @@ -305,7 +303,7 @@ mod tests { let recipient = contract_address_const::<'initialized_recipient'>(); let (dispatcher, _) = deploy(); assert( - dispatcher.balance_of(recipient) == initial_supply, 'incorrect balance of recipient' + dispatcher.balance_of(recipient) == initial_supply, 'incorrect balance of recipient', ); } @@ -353,14 +351,14 @@ mod tests { starknet::testing::pop_log(contract_address), Option::Some( Event::Transfer( - Transfer { from: Zero::zero(), to: recipient, value: initial_supply } - ) - ) + Transfer { from: Zero::zero(), to: recipient, value: initial_supply }, + ), + ), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Approval(Approval { owner: caller, spender, value })) + Option::Some(Event::Approval(Approval { owner: caller, spender, value })), ); } @@ -386,7 +384,7 @@ mod tests { set_contract_address(caller); dispatcher.increase_allowance(spender, 100); assert( - dispatcher.allowance(caller, spender) == amount + 100, 'incorrect increased allowance' + dispatcher.allowance(caller, spender) == amount + 100, 'incorrect increased allowance', ); // emits one transfer event and two approval events @@ -395,19 +393,19 @@ mod tests { starknet::testing::pop_log(contract_address), Option::Some( Event::Transfer( - Transfer { from: Zero::zero(), to: recipient, value: initial_supply } - ) - ) + Transfer { from: Zero::zero(), to: recipient, value: initial_supply }, + ), + ), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount })) + Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount })), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount + 100 })) + Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount + 100 })), ); } @@ -434,7 +432,7 @@ mod tests { set_contract_address(caller); dispatcher.decrease_allowance(spender, 90); assert( - dispatcher.allowance(caller, spender) == amount - 90, 'incorrect decreased allowance' + dispatcher.allowance(caller, spender) == amount - 90, 'incorrect decreased allowance', ); // emits one transfer event and two approval events @@ -443,19 +441,19 @@ mod tests { starknet::testing::pop_log(contract_address), Option::Some( Event::Transfer( - Transfer { from: Zero::zero(), to: recipient, value: initial_supply } - ) - ) + Transfer { from: Zero::zero(), to: recipient, value: initial_supply }, + ), + ), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount })) + Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount })), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount - 90 })) + Option::Some(Event::Approval(Approval { owner: caller, spender, value: amount - 90 })), ); } @@ -494,13 +492,13 @@ mod tests { assert_eq!( starknet::testing::pop_log(contract_address), Option::Some( - Event::Transfer(Transfer { from: Zero::zero(), to: caller, value: initial_supply }) - ) + Event::Transfer(Transfer { from: Zero::zero(), to: caller, value: initial_supply }), + ), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Transfer(Transfer { from: caller, to: receiver, value: amount })) + Option::Some(Event::Transfer(Transfer { from: caller, to: receiver, value: amount })), ); } @@ -543,13 +541,13 @@ mod tests { assert_eq!( starknet::testing::pop_log(contract_address), Option::Some( - Event::Transfer(Transfer { from: Zero::zero(), to: caller, value: initial_supply }) - ) + Event::Transfer(Transfer { from: Zero::zero(), to: caller, value: initial_supply }), + ), ); assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Transfer(Transfer { from: caller, to: receiver, value: amount })) + Option::Some(Event::Transfer(Transfer { from: caller, to: receiver, value: amount })), ); } } diff --git a/listings/applications/merkle_tree/src/contract.cairo b/listings/applications/merkle_tree/src/contract.cairo index bc5a2d67..e26e1d03 100644 --- a/listings/applications/merkle_tree/src/contract.cairo +++ b/listings/applications/merkle_tree/src/contract.cairo @@ -14,7 +14,7 @@ pub trait IMerkleTree { fn get_root(self: @TContractState) -> felt252; // function to verify if leaf node exists in the merkle tree fn verify( - self: @TContractState, proof: Array, root: felt252, leaf: felt252, index: usize + self: @TContractState, proof: Array, root: felt252, leaf: felt252, index: usize, ) -> bool; } @@ -28,19 +28,19 @@ pub mod MerkleTree { use core::poseidon::PoseidonTrait; use core::hash::{HashStateTrait, HashStateExTrait}; use starknet::storage::{ - StoragePointerWriteAccess, StoragePointerReadAccess, Vec, MutableVecTrait, VecTrait + StoragePointerWriteAccess, StoragePointerReadAccess, Vec, MutableVecTrait, VecTrait, }; use super::ByteArrayHashTrait; #[storage] struct Storage { - pub hashes: Vec + pub hashes: Vec, } #[derive(Drop, Serde, Copy)] struct Vec2 { x: u32, - y: u32 + y: u32, } #[abi(embed_v0)] @@ -96,7 +96,7 @@ pub mod MerkleTree { mut proof: Array, root: felt252, leaf: felt252, - mut index: usize + mut index: usize, ) -> bool { let mut current_hash = leaf; diff --git a/listings/applications/merkle_tree/src/tests.cairo b/listings/applications/merkle_tree/src/tests.cairo index 9188cea3..65904224 100644 --- a/listings/applications/merkle_tree/src/tests.cairo +++ b/listings/applications/merkle_tree/src/tests.cairo @@ -1,7 +1,7 @@ use merkle_tree::contract::IMerkleTreeDispatcherTrait; use merkle_tree::contract::{IMerkleTreeDispatcher, MerkleTree, ByteArrayHashTrait}; +use starknet::ContractAddress; use starknet::syscalls::deploy_syscall; -use starknet::{ContractAddress, SyscallResultTrait}; use starknet::testing::set_contract_address; use core::poseidon::PoseidonTrait; use core::hash::{HashStateTrait, HashStateExTrait}; @@ -9,7 +9,7 @@ use starknet::storage::{VecTrait, StoragePointerReadAccess}; fn deploy_util(class_hash: felt252, calldata: Array) -> ContractAddress { let (address, _) = deploy_syscall(class_hash.try_into().unwrap(), 0, calldata.span(), false) - .unwrap_syscall(); + .unwrap(); address } @@ -83,11 +83,9 @@ fn build_tree_succeeds() { assert_eq!(state.hashes.len(), expected_hashes.len().into()); - for i in 0 - ..expected_hashes - .len() { - assert_eq!(state.hashes.at(i.into()).read(), *expected_hashes.at(i)); - } + for i in 0..expected_hashes.len() { + assert_eq!(state.hashes.at(i.into()).read(), *expected_hashes.at(i)); + } } #[test] @@ -173,9 +171,9 @@ fn verify_leaf_fails() { let res = deploy .verify( wrong_proof, // proof - *hashes.at(6), // root - data_3.hash(), // leaf - 2 // leaf index + *hashes.at(6), // root + data_3.hash(), // leaf + 2 // leaf index ); assert(!res, '2- Leaf should NOT be in tree'); } diff --git a/listings/applications/nft_dutch_auction/src/erc721.cairo b/listings/applications/nft_dutch_auction/src/erc721.cairo index b18c6a05..3802a797 100644 --- a/listings/applications/nft_dutch_auction/src/erc721.cairo +++ b/listings/applications/nft_dutch_auction/src/erc721.cairo @@ -9,12 +9,12 @@ pub trait IERC721 { fn owner_of(self: @TContractState, token_id: u256) -> ContractAddress; fn get_approved(self: @TContractState, token_id: u256) -> ContractAddress; fn is_approved_for_all( - self: @TContractState, owner: ContractAddress, operator: ContractAddress + self: @TContractState, owner: ContractAddress, operator: ContractAddress, ) -> bool; fn approve(ref self: TContractState, to: ContractAddress, token_id: u256); fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool); fn transfer_from( - ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256, ); fn mint(ref self: TContractState, to: ContractAddress, token_id: u256); } @@ -27,7 +27,7 @@ mod ERC721 { use starknet::{ContractAddress, get_caller_address}; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; use core::num::traits::Zero; @@ -50,7 +50,7 @@ mod ERC721 { enum Event { Approval: Approval, Transfer: Transfer, - ApprovalForAll: ApprovalForAll + ApprovalForAll: ApprovalForAll, } //////////////////////////////// @@ -60,7 +60,7 @@ mod ERC721 { struct Approval { owner: ContractAddress, to: ContractAddress, - token_id: u256 + token_id: u256, } //////////////////////////////// @@ -70,7 +70,7 @@ mod ERC721 { struct Transfer { from: ContractAddress, to: ContractAddress, - token_id: u256 + token_id: u256, } //////////////////////////////// @@ -80,7 +80,7 @@ mod ERC721 { struct ApprovalForAll { owner: ContractAddress, operator: ContractAddress, - approved: bool + approved: bool, } @@ -145,7 +145,7 @@ mod ERC721 { // is_approved_for_all function returns approved operator for a token //////////////////////////////// fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress + self: @ContractState, owner: ContractAddress, operator: ContractAddress, ) -> bool { self.operator_approvals.read((owner, operator)) } @@ -159,7 +159,7 @@ mod ERC721 { assert( get_caller_address() == owner || self.is_approved_for_all(owner, get_caller_address()), - 'Not token owner' + 'Not token owner', ); self.token_approvals.write(token_id, to); self.emit(Approval { owner: self.owner_of(token_id), to: to, token_id: token_id }); @@ -169,7 +169,7 @@ mod ERC721 { // set_approval_for_all function approves an operator to spend all tokens //////////////////////////////// fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool + ref self: ContractState, operator: ContractAddress, approved: bool, ) { let owner = get_caller_address(); assert(owner != operator, 'ERC721: approve to caller'); @@ -181,11 +181,11 @@ mod ERC721 { // transfer_from function is used to transfer a token //////////////////////////////// fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, ) { assert( self._is_approved_or_owner(get_caller_address(), token_id), - 'neither owner nor approved' + 'neither owner nor approved', ); self._transfer(from, to, token_id); } @@ -209,7 +209,7 @@ mod ERC721 { // _is_approved_or_owner checks if an address is an approved spender or owner //////////////////////////////// fn _is_approved_or_owner( - self: @ContractState, spender: ContractAddress, token_id: u256 + self: @ContractState, spender: ContractAddress, token_id: u256, ) -> bool { let owner = self.owners.read(token_id); spender == owner @@ -229,7 +229,7 @@ mod ERC721 { // internal function that performs the transfer logic //////////////////////////////// fn _transfer( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, ) { // check that from address is equal to owner of token assert(from == self.owner_of(token_id), 'ERC721: Caller is not owner'); diff --git a/listings/applications/nft_dutch_auction/src/nft_dutch_auction.cairo b/listings/applications/nft_dutch_auction/src/nft_dutch_auction.cairo index dabf5c4c..48085039 100644 --- a/listings/applications/nft_dutch_auction/src/nft_dutch_auction.cairo +++ b/listings/applications/nft_dutch_auction/src/nft_dutch_auction.cairo @@ -9,19 +9,19 @@ pub trait IERC20 { fn get_total_supply(self: @TContractState) -> felt252; fn balance_of(self: @TContractState, account: ContractAddress) -> felt252; fn allowance( - self: @TContractState, owner: ContractAddress, spender: ContractAddress + self: @TContractState, owner: ContractAddress, spender: ContractAddress, ) -> felt252; fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252); fn transfer_from( ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, - amount: felt252 + amount: felt252, ); fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252); fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: felt252); fn decrease_allowance( - ref self: TContractState, spender: ContractAddress, subtracted_value: felt252 + ref self: TContractState, spender: ContractAddress, subtracted_value: felt252, ); } @@ -34,12 +34,12 @@ trait IERC721 { fn owner_of(self: @TContractState, token_id: u256) -> ContractAddress; fn get_approved(self: @TContractState, token_id: u256) -> ContractAddress; fn is_approved_for_all( - self: @TContractState, owner: ContractAddress, operator: ContractAddress + self: @TContractState, owner: ContractAddress, operator: ContractAddress, ) -> bool; fn approve(ref self: TContractState, to: ContractAddress, token_id: u256); fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool); fn transfer_from( - ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256, ); fn mint(ref self: TContractState, to: ContractAddress, token_id: u256); } @@ -67,7 +67,7 @@ pub mod NFTDutchAuction { start_at: u64, expires_at: u64, purchase_count: u128, - total_supply: u128 + total_supply: u128, } mod Errors { @@ -85,7 +85,7 @@ pub mod NFTDutchAuction { seller: ContractAddress, duration: u64, discount_rate: u64, - total_supply: u128 + total_supply: u128, ) { assert(starting_price >= discount_rate * duration, Errors::LOW_STARTING_PRICE); @@ -117,7 +117,7 @@ pub mod NFTDutchAuction { let erc20_dispatcher = IERC20Dispatcher { contract_address: self.erc20_token.read() }; let erc721_dispatcher = IERC721Dispatcher { - contract_address: self.erc721_token.read() + contract_address: self.erc721_token.read(), }; let caller = get_caller_address(); @@ -142,7 +142,7 @@ mod tests { use starknet::ContractAddress; use snforge_std::{ declare, DeclareResultTrait, ContractClassTrait, cheat_caller_address, CheatSpan, - cheat_block_timestamp + cheat_block_timestamp, }; use nft_dutch_auction::erc721::{IERC721Dispatcher, IERC721DispatcherTrait}; use super::{INFTDutchAuctionDispatcher, INFTDutchAuctionDispatcherTrait}; @@ -176,7 +176,7 @@ mod tests { erc20_name, erc20_decimals.into(), erc20_initial_supply.into(), - erc20_symbol + erc20_symbol, ]; let (erc20_address, _) = erc20.deploy(@erc20_constructor_calldata).unwrap(); let nft_auction = declare("NFTDutchAuction").unwrap().contract_class(); @@ -187,7 +187,7 @@ mod tests { seller, duration, discount_rate, - total_supply + total_supply, ]; let (nft_auction_address, _) = nft_auction .deploy(@nft_auction_constructor_calldata) @@ -201,7 +201,7 @@ mod tests { let erc721_dispatcher = IERC721Dispatcher { contract_address: erc721_address }; let erc20_dispatcher = IERC20Dispatcher { contract_address: erc20_address }; let nft_auction_dispatcher = INFTDutchAuctionDispatcher { - contract_address: nft_auction_address + contract_address: nft_auction_address, }; let erc20_admin: ContractAddress = 'admin'.try_into().unwrap(); let seller: ContractAddress = 'seller'.try_into().unwrap(); @@ -256,7 +256,7 @@ mod tests { let (_, erc20_address, nft_auction_address) = get_contract_addresses(); let erc20_dispatcher = IERC20Dispatcher { contract_address: erc20_address }; let nft_auction_dispatcher = INFTDutchAuctionDispatcher { - contract_address: nft_auction_address + contract_address: nft_auction_address, }; let erc20_admin: ContractAddress = 'admin'.try_into().unwrap(); let buyer: ContractAddress = 'buyer'.try_into().unwrap(); @@ -300,7 +300,7 @@ mod tests { let (_, erc20_address, nft_auction_address) = get_contract_addresses(); let erc20_dispatcher = IERC20Dispatcher { contract_address: erc20_address }; let nft_auction_dispatcher = INFTDutchAuctionDispatcher { - contract_address: nft_auction_address + contract_address: nft_auction_address, }; let erc20_admin: ContractAddress = 'admin'.try_into().unwrap(); let buyer: ContractAddress = 'buyer'.try_into().unwrap(); @@ -337,7 +337,7 @@ mod tests { fn test_price_decreases_after_some_time() { let (_, _, nft_auction_address) = get_contract_addresses(); let nft_auction_dispatcher = INFTDutchAuctionDispatcher { - contract_address: nft_auction_address + contract_address: nft_auction_address, }; let nft_price_before_time_travel = nft_auction_dispatcher.get_price(); diff --git a/listings/applications/simple_storage_starknetjs/src/storage.cairo b/listings/applications/simple_storage_starknetjs/src/storage.cairo index c7e71819..4a9a5f00 100644 --- a/listings/applications/simple_storage_starknetjs/src/storage.cairo +++ b/listings/applications/simple_storage_starknetjs/src/storage.cairo @@ -11,7 +11,7 @@ mod SimpleStorage { #[storage] struct Storage { - stored_data: u128 + stored_data: u128, } #[abi(embed_v0)] diff --git a/listings/applications/simple_vault/Scarb.toml b/listings/applications/simple_vault/Scarb.toml index d96a0664..a6d3ace3 100644 --- a/listings/applications/simple_vault/Scarb.toml +++ b/listings/applications/simple_vault/Scarb.toml @@ -14,3 +14,4 @@ cairo_test.workspace = true test.workspace = true [[target.starknet-contract]] +build-external-contracts = ["erc20::token::erc20"] diff --git a/listings/applications/simple_vault/src/lib.cairo b/listings/applications/simple_vault/src/lib.cairo index b08098a0..1745c06d 100644 --- a/listings/applications/simple_vault/src/lib.cairo +++ b/listings/applications/simple_vault/src/lib.cairo @@ -1,4 +1 @@ mod simple_vault; - -#[cfg(test)] -mod tests; diff --git a/listings/applications/simple_vault/src/simple_vault.cairo b/listings/applications/simple_vault/src/simple_vault.cairo index c528f281..8ae7d074 100644 --- a/listings/applications/simple_vault/src/simple_vault.cairo +++ b/listings/applications/simple_vault/src/simple_vault.cairo @@ -11,19 +11,19 @@ pub trait IERC20 { fn get_total_supply(self: @TContractState) -> felt252; fn balance_of(self: @TContractState, account: ContractAddress) -> felt252; fn allowance( - self: @TContractState, owner: ContractAddress, spender: ContractAddress + self: @TContractState, owner: ContractAddress, spender: ContractAddress, ) -> felt252; fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252); fn transfer_from( ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, - amount: felt252 + amount: felt252, ); fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252); fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: felt252); fn decrease_allowance( - ref self: TContractState, spender: ContractAddress, subtracted_value: felt252 + ref self: TContractState, spender: ContractAddress, subtracted_value: felt252, ); } @@ -41,14 +41,14 @@ pub mod SimpleVault { use starknet::{ContractAddress, get_caller_address, get_contract_address}; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; #[storage] struct Storage { token: IERC20Dispatcher, total_supply: u256, - balance_of: Map + balance_of: Map, } #[constructor] @@ -127,17 +127,16 @@ pub mod SimpleVault { } // [!endregion contract] +// TODO migrate to sn-foundry #[cfg(test)] mod tests { - use super::{SimpleVault, ISimpleVaultDispatcher, ISimpleVaultDispatcherTrait,}; + use super::{SimpleVault, ISimpleVaultDispatcher, ISimpleVaultDispatcherTrait}; use erc20::token::{ IERC20DispatcherTrait as IERC20DispatcherTrait_token, - IERC20Dispatcher as IERC20Dispatcher_token + IERC20Dispatcher as IERC20Dispatcher_token, }; use starknet::testing::{set_contract_address, set_account_contract_address}; - use starknet::{ - ContractAddress, SyscallResultTrait, syscalls::deploy_syscall, contract_address_const - }; + use starknet::{ContractAddress, syscalls::deploy_syscall, contract_address_const}; const token_name: felt252 = 'myToken'; const decimals: u8 = 18; @@ -151,23 +150,23 @@ mod tests { let (token_contract_address, _) = deploy_syscall( erc20::token::erc20::TEST_CLASS_HASH.try_into().unwrap(), caller.into(), - array![caller.into(), 'myToken', '8', '1000'.into(), 'MYT'].span(), - false + array![caller.into(), token_name, decimals.into(), initial_supply, symbols].span(), + false, ) - .unwrap_syscall(); + .expect('1'); let (contract_address, _) = deploy_syscall( SimpleVault::TEST_CLASS_HASH.try_into().unwrap(), 0, array![token_contract_address.into()].span(), - false + false, ) - .unwrap_syscall(); + .expect('2'); ( ISimpleVaultDispatcher { contract_address }, contract_address, - IERC20Dispatcher_token { contract_address: token_contract_address } + IERC20Dispatcher_token { contract_address: token_contract_address }, ) } diff --git a/listings/applications/simple_vault/src/tests.cairo b/listings/applications/simple_vault/src/tests.cairo deleted file mode 100644 index 361dba07..00000000 --- a/listings/applications/simple_vault/src/tests.cairo +++ /dev/null @@ -1,2 +0,0 @@ -mod tests { // TODO -} diff --git a/listings/applications/staking/src/contract.cairo b/listings/applications/staking/src/contract.cairo index 5980b2c0..7cebd961 100644 --- a/listings/applications/staking/src/contract.cairo +++ b/listings/applications/staking/src/contract.cairo @@ -28,7 +28,7 @@ pub mod StakingContract { use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, - StoragePointerWriteAccess + StoragePointerWriteAccess, }; #[storage] @@ -98,7 +98,7 @@ pub mod StakingContract { // can only set duration if the previous duration has already finished assert( self.finish_at.read() < get_block_timestamp().into(), - super::Errors::UNFINISHED_DURATION + super::Errors::UNFINISHED_DURATION, ); self.duration.write(duration); @@ -124,7 +124,7 @@ pub mod StakingContract { assert( self.reward_token.read().balance_of(get_contract_address()) >= rate * self.duration.read(), - super::Errors::NOT_ENOUGH_REWARDS + super::Errors::NOT_ENOUGH_REWARDS, ); self.reward_rate.write(rate); @@ -158,7 +158,7 @@ pub mod StakingContract { assert( self.staking_token.read().balance_of(user) >= amount, - super::Errors::NOT_ENOUGH_BALANCE + super::Errors::NOT_ENOUGH_BALANCE, ); self.update_rewards(user); diff --git a/listings/applications/staking/src/tests/staking_tests.cairo b/listings/applications/staking/src/tests/staking_tests.cairo index d899b876..50d95f5e 100644 --- a/listings/applications/staking/src/tests/staking_tests.cairo +++ b/listings/applications/staking/src/tests/staking_tests.cairo @@ -5,11 +5,10 @@ mod tests { use staking::tests::tokens::{RewardToken, StakingToken}; use staking::contract::{ StakingContract, IStakingContractDispatcher, StakingContract::Event, - StakingContract::Deposit, StakingContract::Withdrawal, StakingContract::RewardsFinished + StakingContract::Deposit, StakingContract::Withdrawal, StakingContract::RewardsFinished, }; use openzeppelin::token::erc20::{interface::IERC20Dispatcher}; use starknet::syscalls::deploy_syscall; - use starknet::SyscallResultTrait; use core::serde::Serde; use starknet::testing::{set_contract_address, set_block_timestamp, pop_log}; use starknet::{contract_address_const, ContractAddress}; @@ -19,18 +18,18 @@ mod tests { struct Deployment { contract: IStakingContractDispatcher, staking_token: IERC20Dispatcher, - reward_token: IERC20Dispatcher + reward_token: IERC20Dispatcher, } fn deploy_util(class_hash: felt252, calldata: Array) -> ContractAddress { let (address, _) = deploy_syscall(class_hash.try_into().unwrap(), 0, calldata.span(), false) - .unwrap_syscall(); + .unwrap(); address } fn deploy_erc20( - class_hash: felt252, name: ByteArray, symbol: ByteArray + class_hash: felt252, name: ByteArray, symbol: ByteArray, ) -> (ContractAddress, IERC20Dispatcher) { let supply: u256 = 1000000; let recipient = contract_address_const::<'recipient'>(); @@ -46,7 +45,7 @@ mod tests { } fn deploy_staking_contract( - staking_token_address: ContractAddress, reward_token_address: ContractAddress + staking_token_address: ContractAddress, reward_token_address: ContractAddress, ) -> (ContractAddress, IStakingContractDispatcher) { let mut calldata: Array = array![]; calldata.append(staking_token_address.into()); @@ -55,7 +54,7 @@ mod tests { let staking_contract_address = deploy_util(StakingContract::TEST_CLASS_HASH, calldata); ( staking_contract_address, - IStakingContractDispatcher { contract_address: staking_contract_address } + IStakingContractDispatcher { contract_address: staking_contract_address }, ) } @@ -68,14 +67,14 @@ mod tests { ); let (_, staking_contract) = deploy_staking_contract( - staking_token_address, reward_token_address + staking_token_address, reward_token_address, ); Deployment { contract: staking_contract, staking_token, reward_token } } fn mint_and_approve_staking_tokens_to( - recipient: ContractAddress, amount: u256, deploy: Deployment, value_to_approve: u256 + recipient: ContractAddress, amount: u256, deploy: Deployment, value_to_approve: u256, ) { // mint tokens let mut state = StakingToken::contract_state_for_testing(); @@ -89,7 +88,7 @@ mod tests { } fn mint_reward_tokens_to( - deployed_contract: ContractAddress, amount: u256, reward_token_address: ContractAddress + deployed_contract: ContractAddress, amount: u256, reward_token_address: ContractAddress, ) { // mint tokens let mut state = RewardToken::contract_state_for_testing(); @@ -116,10 +115,10 @@ mod tests { /// then assert_eq!(state.owner.read(), owner); assert_eq!( - state.staking_token.read().contract_address, deploy.staking_token.contract_address + state.staking_token.read().contract_address, deploy.staking_token.contract_address, ); assert_eq!( - state.reward_token.read().contract_address, deploy.reward_token.contract_address + state.reward_token.read().contract_address, deploy.reward_token.contract_address, ); } @@ -153,11 +152,11 @@ mod tests { // check 1st & 2nd event - when user stakes assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards not active yet' })) + Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards not active yet' })), ); assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::Deposit(Deposit { user, amount: stake_amount })) + Option::Some(Event::Deposit(Deposit { user, amount: stake_amount })), ); /// when - withdrawal @@ -173,17 +172,17 @@ mod tests { assert_eq!(state.total_supply.read(), stake_amount - withdrawal_amount); assert_eq!( deploy.staking_token.balance_of(user), - amount_tokens_minted - stake_amount + withdrawal_amount + amount_tokens_minted - stake_amount + withdrawal_amount, ); // check 3rd & 4th events - when user withdraws assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards not active yet' })) + Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards not active yet' })), ); assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::Withdrawal(Withdrawal { user, amount: withdrawal_amount })) + Option::Some(Event::Withdrawal(Withdrawal { user, amount: withdrawal_amount })), ); } @@ -201,7 +200,7 @@ mod tests { mint_reward_tokens_to( deploy.contract.contract_address, reward_tokens_amount, - deploy.reward_token.contract_address + deploy.reward_token.contract_address, ); // owner sets up rewards duration and amount @@ -226,7 +225,7 @@ mod tests { let alice_stake_amount = 40; let alice_amount_tokens_minted = 100; mint_and_approve_staking_tokens_to( - alice, alice_amount_tokens_minted, deploy, alice_stake_amount + alice, alice_amount_tokens_minted, deploy, alice_stake_amount, ); // alice stakes @@ -262,7 +261,7 @@ mod tests { let john_stake_amount = 30; let john_amount_tokens_minted = 100; mint_and_approve_staking_tokens_to( - john, john_amount_tokens_minted, deploy, john_stake_amount + john, john_amount_tokens_minted, deploy, john_stake_amount, ); // john stakes @@ -327,7 +326,7 @@ mod tests { // timestamp after the duration is finished set_block_timestamp( - block_timestamp.try_into().unwrap() + reward_duration.try_into().unwrap() + 10 + block_timestamp.try_into().unwrap() + reward_duration.try_into().unwrap() + 10, ); // alice claims @@ -405,7 +404,7 @@ mod tests { mint_reward_tokens_to( deploy.contract.contract_address, reward_tokens_amount, - deploy.reward_token.contract_address + deploy.reward_token.contract_address, ); // owner sets up rewards duration and amount @@ -429,7 +428,7 @@ mod tests { // alice claims her rewards after the duration is over set_block_timestamp( - block_timestamp.try_into().unwrap() + reward_duration.try_into().unwrap() + block_timestamp.try_into().unwrap() + reward_duration.try_into().unwrap(), ); deploy.contract.claim_rewards(); @@ -449,21 +448,25 @@ mod tests { // check 1st event - when alice stakes assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::Deposit(Deposit { user: alice, amount: alice_stake_amount })) + Option::Some(Event::Deposit(Deposit { user: alice, amount: alice_stake_amount })), ); // check 2nd event - when alice claims assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards all distributed' })) + Option::Some( + Event::RewardsFinished(RewardsFinished { msg: 'Rewards all distributed' }), + ), ); // check 3rd & 4th events - when bob stakes assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::RewardsFinished(RewardsFinished { msg: 'Rewards all distributed' })) + Option::Some( + Event::RewardsFinished(RewardsFinished { msg: 'Rewards all distributed' }), + ), ); assert_eq!( pop_log(deploy.contract.contract_address), - Option::Some(Event::Deposit(Deposit { user: bob, amount: bob_stake_amount })) + Option::Some(Event::Deposit(Deposit { user: bob, amount: bob_stake_amount })), ); } @@ -481,7 +484,7 @@ mod tests { mint_reward_tokens_to( deploy.contract.contract_address, reward_tokens_amount, - deploy.reward_token.contract_address + deploy.reward_token.contract_address, ); // owner sets up rewards duration and amount diff --git a/listings/applications/staking/src/tests/tokens.cairo b/listings/applications/staking/src/tests/tokens.cairo index 0b0148c6..89e1a4bd 100644 --- a/listings/applications/staking/src/tests/tokens.cairo +++ b/listings/applications/staking/src/tests/tokens.cairo @@ -28,7 +28,7 @@ pub mod RewardToken { name: ByteArray, symbol: ByteArray, initial_supply: u256, - recipient: ContractAddress + recipient: ContractAddress, ) { self.erc20.initializer(name, symbol); self.erc20.mint(recipient, initial_supply); @@ -65,7 +65,7 @@ pub mod StakingToken { name: ByteArray, symbol: ByteArray, initial_supply: u256, - recipient: ContractAddress + recipient: ContractAddress, ) { self.erc20.initializer(name, symbol); self.erc20.mint(recipient, initial_supply); diff --git a/listings/applications/timelock/src/erc721.cairo b/listings/applications/timelock/src/erc721.cairo index fddeda94..36ae6448 100644 --- a/listings/applications/timelock/src/erc721.cairo +++ b/listings/applications/timelock/src/erc721.cairo @@ -36,7 +36,7 @@ pub mod ERC721 { symbol: ByteArray, base_uri: ByteArray, recipient: ContractAddress, - token_id: u256 + token_id: u256, ) { self.erc721.initializer(name, symbol, base_uri); self.erc721.mint(recipient, token_id); diff --git a/listings/applications/timelock/src/tests/timelock.cairo b/listings/applications/timelock/src/tests/timelock.cairo index dd0c98da..bfc1893e 100644 --- a/listings/applications/timelock/src/tests/timelock.cairo +++ b/listings/applications/timelock/src/tests/timelock.cairo @@ -3,7 +3,7 @@ use starknet::account::Call; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use core::hash::HashStateTrait; use snforge_std::{ - cheat_caller_address, cheat_block_timestamp, CheatSpan, spy_events, EventSpyAssertionsTrait + cheat_caller_address, cheat_block_timestamp, CheatSpan, spy_events, EventSpyAssertionsTrait, }; use openzeppelin::token::erc721::interface::IERC721DispatcherTrait; use openzeppelin::token::erc721::erc721::ERC721Component; @@ -34,7 +34,9 @@ fn test_queue_only_owner() { .timelock_safe .queue(timelock_test.get_call(), timelock_test.get_timestamp()) { Result::Ok(_) => panic_with_felt252('FAIL'), - Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); } + Result::Err(panic_data) => { + assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); + }, } } @@ -47,7 +49,7 @@ fn test_queue_already_queued() { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::ALREADY_QUEUED); - } + }, } } @@ -58,7 +60,7 @@ fn test_queue_timestamp_not_in_range() { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::TIMESTAMP_NOT_IN_RANGE); - } + }, } match timelock_test .timelock_safe @@ -66,7 +68,7 @@ fn test_queue_timestamp_not_in_range() { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::TIMESTAMP_NOT_IN_RANGE); - } + }, } } @@ -82,10 +84,10 @@ fn test_queue_success() { ( timelock_test.timelock_address, TimeLock::Event::Queue( - TimeLock::Queue { tx_id, call: timelock_test.get_call(), timestamp } - ) - ) - ] + TimeLock::Queue { tx_id, call: timelock_test.get_call(), timestamp }, + ), + ), + ], ); assert_eq!(tx_id, timelock_test.timelock.get_tx_id(timelock_test.get_call(), timestamp)); } @@ -98,7 +100,9 @@ fn test_execute_only_owner() { .timelock_safe .execute(timelock_test.get_call(), timelock_test.get_timestamp()) { Result::Ok(_) => panic_with_felt252('FAIL'), - Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); } + Result::Err(panic_data) => { + assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); + }, } } @@ -109,7 +113,7 @@ fn test_execute_not_queued() { .timelock_safe .execute(timelock_test.get_call(), timelock_test.get_timestamp()) { Result::Ok(_) => panic_with_felt252('FAIL'), - Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::NOT_QUEUED); } + Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::NOT_QUEUED); }, } } @@ -122,7 +126,7 @@ fn test_execute_timestamp_not_passed() { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::TIMESTAMP_NOT_PASSED); - } + }, } } @@ -134,13 +138,13 @@ fn test_execute_timestamp_expired() { cheat_block_timestamp( timelock_test.timelock_address, timestamp + TimeLock::GRACE_PERIOD + 1, - CheatSpan::TargetCalls(1) + CheatSpan::TargetCalls(1), ); match timelock_test.timelock_safe.execute(timelock_test.get_call(), timestamp) { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::TIMESTAMP_EXPIRED); - } + }, } } @@ -160,10 +164,10 @@ fn test_execute_success() { ( timelock_test.timelock_address, TimeLock::Event::Execute( - TimeLock::Execute { tx_id, call: timelock_test.get_call(), timestamp } - ) - ) - ] + TimeLock::Execute { tx_id, call: timelock_test.get_call(), timestamp }, + ), + ), + ], ); } @@ -177,7 +181,7 @@ fn test_execute_failed() { Result::Ok(_) => panic_with_felt252('FAIL'), Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), ERC721Component::Errors::UNAUTHORIZED); - } + }, } } @@ -190,7 +194,9 @@ fn test_cancel_only_owner() { cheat_caller_address(timelock_test.timelock_address, OTHER(), CheatSpan::TargetCalls(1)); match timelock_test.timelock_safe.cancel(tx_id) { Result::Ok(_) => panic_with_felt252('FAIL'), - Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); } + Result::Err(panic_data) => { + assert_eq!(*panic_data.at(0), ownable::Errors::UNAUTHORIZED); + }, } } @@ -202,7 +208,7 @@ fn test_cancel_not_queued() { .get_tx_id(timelock_test.get_call(), timelock_test.get_timestamp()); match timelock_test.timelock_safe.cancel(tx_id) { Result::Ok(_) => panic_with_felt252('FAIL'), - Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::NOT_QUEUED); } + Result::Err(panic_data) => { assert_eq!(*panic_data.at(0), TimeLock::Errors::NOT_QUEUED); }, } } @@ -219,8 +225,8 @@ fn test_cancel_success() { @array![ ( timelock_test.timelock_address, - TimeLock::Event::Cancel(TimeLock::Cancel { tx_id }) - ) - ] + TimeLock::Event::Cancel(TimeLock::Cancel { tx_id }), + ), + ], ); } diff --git a/listings/applications/timelock/src/tests/utils.cairo b/listings/applications/timelock/src/tests/utils.cairo index 32973908..f380b445 100644 --- a/listings/applications/timelock/src/tests/utils.cairo +++ b/listings/applications/timelock/src/tests/utils.cairo @@ -59,7 +59,7 @@ pub impl TimeLockTestImpl of TimeLockTestTrait { Call { to: *self.erc721_address, selector: selector!("transfer_from"), - calldata: calldata.span() + calldata: calldata.span(), } } fn get_timestamp(self: @TimeLockTest) -> u64 { diff --git a/listings/applications/timelock/src/timelock.cairo b/listings/applications/timelock/src/timelock.cairo index 38e42ed9..e6540d56 100644 --- a/listings/applications/timelock/src/timelock.cairo +++ b/listings/applications/timelock/src/timelock.cairo @@ -12,7 +12,7 @@ pub trait ITimeLock { pub mod TimeLock { use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use core::hash::HashStateTrait; - use starknet::{get_caller_address, get_block_timestamp, SyscallResultTrait, syscalls}; + use starknet::{get_caller_address, get_block_timestamp, syscalls}; use starknet::account::Call; use components::ownable::ownable_component; use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; @@ -38,7 +38,7 @@ pub mod TimeLock { OwnableEvent: ownable_component::Event, Queue: Queue, Execute: Execute, - Cancel: Cancel + Cancel: Cancel, } #[derive(Drop, starknet::Event)] @@ -46,7 +46,7 @@ pub mod TimeLock { #[key] pub tx_id: felt252, pub call: Call, - pub timestamp: u64 + pub timestamp: u64, } #[derive(Drop, starknet::Event)] @@ -54,13 +54,13 @@ pub mod TimeLock { #[key] pub tx_id: felt252, pub call: Call, - pub timestamp: u64 + pub timestamp: u64, } #[derive(Drop, starknet::Event)] pub struct Cancel { #[key] - pub tx_id: felt252 + pub tx_id: felt252, } pub const MIN_DELAY: u64 = 10; // seconds @@ -103,7 +103,7 @@ pub mod TimeLock { timestamp >= block_timestamp + MIN_DELAY && timestamp <= block_timestamp + MAX_DELAY, - Errors::TIMESTAMP_NOT_IN_RANGE + Errors::TIMESTAMP_NOT_IN_RANGE, ); self.queued.write(tx_id, true); @@ -126,7 +126,7 @@ pub mod TimeLock { self.queued.write(tx_id, false); let result = syscalls::call_contract_syscall(call.to, call.selector, call.calldata) - .unwrap_syscall(); + .unwrap(); self.emit(Execute { tx_id, call: self._copy_call(@call), timestamp }); diff --git a/listings/applications/upgradeable_contract/src/tests.cairo b/listings/applications/upgradeable_contract/src/tests.cairo index a3ff7ba0..fe9f11a6 100644 --- a/listings/applications/upgradeable_contract/src/tests.cairo +++ b/listings/applications/upgradeable_contract/src/tests.cairo @@ -4,18 +4,17 @@ mod tests { use super::super::upgradeable_contract_v0::{ UpgradeableContract_V0, IUpgradeableContractDispatcher as IUpgradeableContractDispatcher_v0, IUpgradeableContractDispatcherTrait as UpgradeableContractDispatcherTrait_v0, - UpgradeableContract_V0::{Event, Upgraded} + UpgradeableContract_V0::{Event, Upgraded}, }; use super::super::upgradeable_contract_v1::{ UpgradeableContract_V1, IUpgradeableContractDispatcher as IUpgradeableContractDispatcher_v1, - IUpgradeableContractDispatcherTrait as UpgradeableContractDispatcherTrait_v1 + IUpgradeableContractDispatcherTrait as UpgradeableContractDispatcherTrait_v1, }; use starknet::{ - ContractAddress, SyscallResultTrait, syscalls::deploy_syscall, get_caller_address, - contract_address_const + ContractAddress, syscalls::deploy_syscall, get_caller_address, contract_address_const, }; use core::num::traits::Zero; @@ -24,26 +23,26 @@ mod tests { // deploy v0 contract fn deploy_v0() -> (IUpgradeableContractDispatcher_v0, ContractAddress, ClassHash) { let (contract_address, _) = deploy_syscall( - UpgradeableContract_V0::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + UpgradeableContract_V0::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ( IUpgradeableContractDispatcher_v0 { contract_address }, contract_address, - UpgradeableContract_V0::TEST_CLASS_HASH.try_into().unwrap() + UpgradeableContract_V0::TEST_CLASS_HASH.try_into().unwrap(), ) } // deploy v1 contract fn deploy_v1() -> (IUpgradeableContractDispatcher_v1, ContractAddress, ClassHash) { let (contract_address, _) = deploy_syscall( - UpgradeableContract_V1::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + UpgradeableContract_V1::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ( IUpgradeableContractDispatcher_v1 { contract_address }, contract_address, - UpgradeableContract_V1::TEST_CLASS_HASH.try_into().unwrap() + UpgradeableContract_V1::TEST_CLASS_HASH.try_into().unwrap(), ) } @@ -78,7 +77,7 @@ mod tests { // emit event assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::Upgraded(Upgraded { implementation: class_hash })) + Option::Some(Event::Upgraded(Upgraded { implementation: class_hash })), ); assert(dispatcher_v0.version() == 1, ' version did not upgrade'); diff --git a/listings/applications/upgradeable_contract/src/upgradeable_contract_v0.cairo b/listings/applications/upgradeable_contract/src/upgradeable_contract_v0.cairo index e8d912ba..571ec785 100644 --- a/listings/applications/upgradeable_contract/src/upgradeable_contract_v0.cairo +++ b/listings/applications/upgradeable_contract/src/upgradeable_contract_v0.cairo @@ -10,7 +10,6 @@ pub trait IUpgradeableContract { #[starknet::contract] pub mod UpgradeableContract_V0 { use starknet::class_hash::ClassHash; - use starknet::SyscallResultTrait; use core::num::traits::Zero; #[storage] @@ -24,7 +23,7 @@ pub mod UpgradeableContract_V0 { #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] pub struct Upgraded { - pub implementation: ClassHash + pub implementation: ClassHash, } #[abi(embed_v0)] @@ -32,7 +31,7 @@ pub mod UpgradeableContract_V0 { // [!region upgrade] fn upgrade(ref self: ContractState, impl_hash: ClassHash) { assert(impl_hash.is_non_zero(), 'Class hash cannot be zero'); - starknet::syscalls::replace_class_syscall(impl_hash).unwrap_syscall(); + starknet::syscalls::replace_class_syscall(impl_hash).unwrap(); self.emit(Event::Upgraded(Upgraded { implementation: impl_hash })) } // [!endregion upgrade] diff --git a/listings/applications/upgradeable_contract/src/upgradeable_contract_v1.cairo b/listings/applications/upgradeable_contract/src/upgradeable_contract_v1.cairo index 78baa8b1..052b4cbf 100644 --- a/listings/applications/upgradeable_contract/src/upgradeable_contract_v1.cairo +++ b/listings/applications/upgradeable_contract/src/upgradeable_contract_v1.cairo @@ -9,7 +9,6 @@ pub trait IUpgradeableContract { #[starknet::contract] pub mod UpgradeableContract_V1 { use starknet::class_hash::ClassHash; - use starknet::SyscallResultTrait; use core::num::traits::Zero; #[storage] @@ -18,19 +17,19 @@ pub mod UpgradeableContract_V1 { #[event] #[derive(Drop, starknet::Event)] enum Event { - Upgraded: Upgraded + Upgraded: Upgraded, } #[derive(Drop, starknet::Event)] struct Upgraded { - implementation: ClassHash + implementation: ClassHash, } #[abi(embed_v0)] impl UpgradeableContract of super::IUpgradeableContract { fn upgrade(ref self: ContractState, impl_hash: ClassHash) { assert(impl_hash.is_non_zero(), 'Class hash cannot be zero'); - starknet::syscalls::replace_class_syscall(impl_hash).unwrap_syscall(); + starknet::syscalls::replace_class_syscall(impl_hash).unwrap(); self.emit(Event::Upgraded(Upgraded { implementation: impl_hash })) } diff --git a/listings/cairo_cheatsheet/Scarb.toml b/listings/cairo_cheatsheet/Scarb.toml index 4daa2a61..5cf958bf 100644 --- a/listings/cairo_cheatsheet/Scarb.toml +++ b/listings/cairo_cheatsheet/Scarb.toml @@ -13,4 +13,3 @@ cairo_test.workspace = true test.workspace = true [[target.starknet-contract]] -allowed-libfuncs-list.name = "experimental" diff --git a/listings/cairo_cheatsheet/src/enum_example.cairo b/listings/cairo_cheatsheet/src/enum_example.cairo index 32ea6800..a6d94c69 100644 --- a/listings/cairo_cheatsheet/src/enum_example.cairo +++ b/listings/cairo_cheatsheet/src/enum_example.cairo @@ -7,6 +7,7 @@ struct Position { #[derive(Drop, Serde, Copy, starknet::Store)] enum UserCommand { + #[default] Login, UpdateProfile, Logout, @@ -14,11 +15,12 @@ enum UserCommand { #[derive(Drop, Serde, Copy, starknet::Store)] enum Action { + #[default] Quit, Move: Position, SendMessage: felt252, ChangeAvatarColor: (u8, u8, u8), - ProfileState: UserCommand + ProfileState: UserCommand, } // [!endregion enums] @@ -45,20 +47,20 @@ mod EnumContract { fn register_action(ref self: ContractState, action: Action) { // quick note: match takes ownership of variable (but enum Action implements Copy trait) match action { - Action::Quit => { println!("Quit"); }, - Action::Move(value) => { println!("Move with x: {} and y: {}", value.x, value.y); }, - Action::SendMessage(msg) => { println!("Write with message: {}", msg); }, + Action::Quit => "Quit", + Action::Move(value) => format!("Move with x: {} and y: {}", value.x, value.y), + Action::SendMessage(msg) => format!("Write with message: {}", msg), Action::ChangeAvatarColor(( - r, g, b - )) => { println!("Change color to r: {}, g: {}, b: {}", r, g, b); }, + r, g, b, + )) => format!("Change color to r: {}, g: {}, b: {}", r, g, b), Action::ProfileState(state) => { let profile_state = match state { UserCommand::Login => 1, UserCommand::UpdateProfile => 2, UserCommand::Logout => 3, }; - println!("profile_state: {}", profile_state); - } + format!("profile_state: {}", profile_state) + }, }; self.most_recent_action.write(action); diff --git a/listings/cairo_cheatsheet/src/if_let_example.cairo b/listings/cairo_cheatsheet/src/if_let_example.cairo index 5fd56033..329157d3 100644 --- a/listings/cairo_cheatsheet/src/if_let_example.cairo +++ b/listings/cairo_cheatsheet/src/if_let_example.cairo @@ -13,15 +13,15 @@ fn if_let() { // "if `let` destructures `number` into `Some(i)`: // evaluate the block (`{}`). if let Option::Some(i) = number { - println!("Matched {}", i); + format!("Matched {}", i); } // If you need to specify a failure, use an else: if let Option::Some(i) = letter { - println!("Matched {}", i); + format!("Matched {}", i); } else { // Destructure failed. Change to the failure case. - println!("Didn't match a number."); + format!("Didn't match a number."); } // Using `if let` with enum @@ -31,19 +31,19 @@ fn if_let() { // Variable a matches Foo::Bar if let Foo::Bar = a { - println!("a is foobar"); + format!("a is foobar"); } // Variable b does not match Foo::Bar // So this will print nothing if let Foo::Bar = b { - println!("b is foobar"); + format!("b is foobar"); } // Variable c matches Foo::Qux which has a value // Similar to Some() in the previous example if let Foo::Qux(value) = c { - println!("c is {}", value); + format!("c is {}", value); } } // [!endregion sheet] diff --git a/listings/cairo_cheatsheet/src/mapping_example.cairo b/listings/cairo_cheatsheet/src/mapping_example.cairo index 176a2240..6befd79c 100644 --- a/listings/cairo_cheatsheet/src/mapping_example.cairo +++ b/listings/cairo_cheatsheet/src/mapping_example.cairo @@ -4,11 +4,11 @@ use starknet::ContractAddress; trait IMappingExample { fn register_user(ref self: TContractState, student_add: ContractAddress, studentName: felt252); fn record_student_score( - ref self: TContractState, student_add: ContractAddress, subject: felt252, score: u16 + ref self: TContractState, student_add: ContractAddress, subject: felt252, score: u16, ); fn view_student_name(self: @TContractState, student_add: ContractAddress) -> felt252; fn view_student_score( - self: @TContractState, student_add: ContractAddress, subject: felt252 + self: @TContractState, student_add: ContractAddress, subject: felt252, ) -> u16; } @@ -26,13 +26,13 @@ mod MappingContract { #[abi(embed_v0)] impl External of super::IMappingExample { fn register_user( - ref self: ContractState, student_add: ContractAddress, studentName: felt252 + ref self: ContractState, student_add: ContractAddress, studentName: felt252, ) { self.students_name.write(student_add, studentName); } fn record_student_score( - ref self: ContractState, student_add: ContractAddress, subject: felt252, score: u16 + ref self: ContractState, student_add: ContractAddress, subject: felt252, score: u16, ) { self.students_result_record.write((student_add, subject), score); } @@ -42,7 +42,7 @@ mod MappingContract { } fn view_student_score( - self: @ContractState, student_add: ContractAddress, subject: felt252 + self: @ContractState, student_add: ContractAddress, subject: felt252, ) -> u16 { // for a 2D mapping its important to take note of the amount of brackets being used. self.students_result_record.read((student_add, subject)) diff --git a/listings/cairo_cheatsheet/src/match_example.cairo b/listings/cairo_cheatsheet/src/match_example.cairo index f32d2df1..3273ea19 100644 --- a/listings/cairo_cheatsheet/src/match_example.cairo +++ b/listings/cairo_cheatsheet/src/match_example.cairo @@ -4,7 +4,7 @@ enum Colour { Blue, Green, Orange, - Black + Black, } #[derive(Drop, Serde)] diff --git a/listings/cairo_cheatsheet/src/struct_example.cairo b/listings/cairo_cheatsheet/src/struct_example.cairo index 7601e0e1..55b7f227 100644 --- a/listings/cairo_cheatsheet/src/struct_example.cairo +++ b/listings/cairo_cheatsheet/src/struct_example.cairo @@ -2,5 +2,5 @@ #[derive(Drop, starknet::Store)] struct Data { address: starknet::ContractAddress, - age: u8 + age: u8, } diff --git a/listings/cairo_cheatsheet/src/while_let_example.cairo b/listings/cairo_cheatsheet/src/while_let_example.cairo index 54b5e7b1..56d6aad5 100644 --- a/listings/cairo_cheatsheet/src/while_let_example.cairo +++ b/listings/cairo_cheatsheet/src/while_let_example.cairo @@ -6,10 +6,8 @@ fn while_let() { // evaluate the block (`{}`), else `break` while let Option::Some(i) = option { if i > 0 { - println!("Greater than 0, break..."); option = Option::None; } else { - println!("`i` is `{:?}`. Try again.", i); option = Option::Some(i + 1); } } diff --git a/listings/getting-started/bytearray/src/bytearray.cairo b/listings/getting-started/bytearray/src/bytearray.cairo index d6d10be9..03911b70 100644 --- a/listings/getting-started/bytearray/src/bytearray.cairo +++ b/listings/getting-started/bytearray/src/bytearray.cairo @@ -11,7 +11,7 @@ pub mod MessageContract { #[storage] struct Storage { - pub message: ByteArray + pub message: ByteArray, } #[constructor] diff --git a/listings/getting-started/calling_other_contracts/src/caller.cairo b/listings/getting-started/calling_other_contracts/src/caller.cairo index 1f599266..7a088711 100644 --- a/listings/getting-started/calling_other_contracts/src/caller.cairo +++ b/listings/getting-started/calling_other_contracts/src/caller.cairo @@ -27,7 +27,7 @@ pub mod Callee { #[starknet::interface] pub trait ICaller { fn set_value_from_address( - ref self: TContractState, addr: starknet::ContractAddress, value: u128 + ref self: TContractState, addr: starknet::ContractAddress, value: u128, ); } @@ -54,21 +54,21 @@ pub mod Caller { #[cfg(test)] mod tests { use super::{Callee, ICalleeDispatcher, Caller, ICallerDispatcher, ICallerDispatcherTrait}; - use starknet::{testing::set_contract_address, syscalls::deploy_syscall, SyscallResultTrait}; + use starknet::{testing::set_contract_address, syscalls::deploy_syscall}; use starknet::storage::StoragePointerReadAccess; fn deploy() -> (ICalleeDispatcher, ICallerDispatcher) { let (address_callee, _) = deploy_syscall( - Callee::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + Callee::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); let (address_caller, _) = deploy_syscall( - Caller::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + Caller::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ( ICalleeDispatcher { contract_address: address_callee }, - ICallerDispatcher { contract_address: address_caller } + ICallerDispatcher { contract_address: address_caller }, ) } diff --git a/listings/getting-started/constructor/src/constructor.cairo b/listings/getting-started/constructor/src/constructor.cairo index 55540099..c384b00a 100644 --- a/listings/getting-started/constructor/src/constructor.cairo +++ b/listings/getting-started/constructor/src/constructor.cairo @@ -22,7 +22,7 @@ pub mod ExampleConstructor { #[cfg(test)] mod tests { use super::ExampleConstructor; - use starknet::{ContractAddress, SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::{ContractAddress, syscalls::deploy_syscall}; use starknet::{contract_address_const, testing::{set_contract_address}}; use starknet::storage::StorageMapReadAccess; @@ -35,9 +35,9 @@ mod tests { ExampleConstructor::TEST_CLASS_HASH.try_into().unwrap(), 0, array![name, address.into()].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); let state = @ExampleConstructor::contract_state_for_testing(); set_contract_address(contract_address); diff --git a/listings/getting-started/counter/src/counter.cairo b/listings/getting-started/counter/src/counter.cairo index e44bb058..593d2342 100644 --- a/listings/getting-started/counter/src/counter.cairo +++ b/listings/getting-started/counter/src/counter.cairo @@ -46,16 +46,16 @@ pub mod SimpleCounter { #[cfg(test)] mod test { use super::{SimpleCounter, ISimpleCounterDispatcher, ISimpleCounterDispatcherTrait}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; fn deploy(init_value: u128) -> ISimpleCounterDispatcher { let (contract_address, _) = deploy_syscall( SimpleCounter::TEST_CLASS_HASH.try_into().unwrap(), 0, array![init_value.into()].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); ISimpleCounterDispatcher { contract_address } } diff --git a/listings/getting-started/custom_type_serde/src/contract.cairo b/listings/getting-started/custom_type_serde/src/contract.cairo index 8515f554..abd441ea 100644 --- a/listings/getting-started/custom_type_serde/src/contract.cairo +++ b/listings/getting-started/custom_type_serde/src/contract.cairo @@ -10,7 +10,7 @@ pub trait ISerdeCustomType { #[derive(Drop, Serde)] pub struct Person { pub age: u8, - pub name: felt252 + pub name: felt252, } #[starknet::contract] @@ -34,15 +34,15 @@ pub mod SerdeCustomType { #[cfg(test)] mod tests { use super::{ - SerdeCustomType, Person, ISerdeCustomTypeDispatcher, ISerdeCustomTypeDispatcherTrait + SerdeCustomType, Person, ISerdeCustomTypeDispatcher, ISerdeCustomTypeDispatcherTrait, }; - use starknet::{syscalls::deploy_syscall, SyscallResultTrait}; + use starknet::syscalls::deploy_syscall; fn deploy() -> ISerdeCustomTypeDispatcher { let (contract_address, _) = deploy_syscall( - SerdeCustomType::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + SerdeCustomType::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ISerdeCustomTypeDispatcher { contract_address } } diff --git a/listings/getting-started/errors/src/custom_errors.cairo b/listings/getting-started/errors/src/custom_errors.cairo index 5361b10e..b287514f 100644 --- a/listings/getting-started/errors/src/custom_errors.cairo +++ b/listings/getting-started/errors/src/custom_errors.cairo @@ -35,15 +35,15 @@ pub mod CustomErrorsExample { #[cfg(test)] mod test { use super::{ - CustomErrorsExample, ICustomErrorsExampleDispatcher, ICustomErrorsExampleDispatcherTrait + CustomErrorsExample, ICustomErrorsExampleDispatcher, ICustomErrorsExampleDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; fn deploy() -> ICustomErrorsExampleDispatcher { let (contract_address, _) = deploy_syscall( - CustomErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + CustomErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); ICustomErrorsExampleDispatcher { contract_address } } diff --git a/listings/getting-started/errors/src/simple_errors.cairo b/listings/getting-started/errors/src/simple_errors.cairo index 7598794f..1477e1c8 100644 --- a/listings/getting-started/errors/src/simple_errors.cairo +++ b/listings/getting-started/errors/src/simple_errors.cairo @@ -31,13 +31,13 @@ pub mod ErrorsExample { #[cfg(test)] mod test { use super::{ErrorsExample, IErrorsExampleDispatcher, IErrorsExampleDispatcherTrait}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; fn deploy() -> IErrorsExampleDispatcher { let (contract_address, _) = deploy_syscall( - ErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + ErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); IErrorsExampleDispatcher { contract_address } } diff --git a/listings/getting-started/errors/src/vault_errors.cairo b/listings/getting-started/errors/src/vault_errors.cairo index 595f9a9d..4da8a4e8 100644 --- a/listings/getting-started/errors/src/vault_errors.cairo +++ b/listings/getting-started/errors/src/vault_errors.cairo @@ -49,15 +49,15 @@ pub mod VaultErrorsExample { #[cfg(test)] mod test { use super::{ - VaultErrorsExample, IVaultErrorsExampleDispatcher, IVaultErrorsExampleDispatcherTrait + VaultErrorsExample, IVaultErrorsExampleDispatcher, IVaultErrorsExampleDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; fn deploy() -> IVaultErrorsExampleDispatcher { let (contract_address, _) = deploy_syscall( - VaultErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + VaultErrorsExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); IVaultErrorsExampleDispatcher { contract_address } } diff --git a/listings/getting-started/events/src/counter.cairo b/listings/getting-started/events/src/counter.cairo index fa11878d..612c81e5 100644 --- a/listings/getting-started/events/src/counter.cairo +++ b/listings/getting-started/events/src/counter.cairo @@ -21,14 +21,14 @@ pub mod EventCounter { // It must also derive at least the `Drop` and `starknet::Event` traits. pub enum Event { CounterIncreased: CounterIncreased, - UserIncreaseCounter: UserIncreaseCounter + UserIncreaseCounter: UserIncreaseCounter, } // By deriving the `starknet::Event` trait, we indicate to the compiler that // this struct will be used when emitting events. #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] pub struct CounterIncreased { - pub amount: u128 + pub amount: u128, } #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] @@ -51,9 +51,9 @@ pub mod EventCounter { .emit( Event::UserIncreaseCounter( UserIncreaseCounter { - user: get_caller_address(), new_value: self.counter.read() - } - ) + user: get_caller_address(), new_value: self.counter.read(), + }, + ), ); // [!endregion emit] } @@ -65,18 +65,18 @@ pub mod EventCounter { mod tests { use super::{ EventCounter, EventCounter::{Event, CounterIncreased, UserIncreaseCounter}, - IEventCounterDispatcherTrait, IEventCounterDispatcher + IEventCounterDispatcherTrait, IEventCounterDispatcher, }; - use starknet::{contract_address_const, SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::{contract_address_const, syscalls::deploy_syscall}; use starknet::testing::set_contract_address; use starknet::storage::StoragePointerReadAccess; #[test] fn test_increment_events() { let (contract_address, _) = deploy_syscall( - EventCounter::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + EventCounter::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IEventCounterDispatcher { contract_address }; let state = @EventCounter::contract_state_for_testing(); @@ -94,14 +94,14 @@ mod tests { // [!region test_events] assert_eq!( starknet::testing::pop_log(contract_address), - Option::Some(Event::CounterIncreased(CounterIncreased { amount })) + Option::Some(Event::CounterIncreased(CounterIncreased { amount })), ); // [!endregion test_events] assert_eq!( starknet::testing::pop_log(contract_address), Option::Some( - Event::UserIncreaseCounter(UserIncreaseCounter { user: caller, new_value: amount }) - ) + Event::UserIncreaseCounter(UserIncreaseCounter { user: caller, new_value: amount }), + ), ); } } diff --git a/listings/getting-started/factory/src/simple_factory.cairo b/listings/getting-started/factory/src/simple_factory.cairo index 1d93badc..95fb8766 100644 --- a/listings/getting-started/factory/src/simple_factory.cairo +++ b/listings/getting-started/factory/src/simple_factory.cairo @@ -18,7 +18,7 @@ pub trait ICounterFactory { #[starknet::contract] pub mod CounterFactory { - use starknet::{ContractAddress, ClassHash, SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::{ContractAddress, ClassHash, syscalls::deploy_syscall}; use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; #[storage] @@ -44,9 +44,9 @@ pub mod CounterFactory { // Contract deployment let (deployed_address, _) = deploy_syscall( - self.counter_class_hash.read(), 0, constructor_calldata.span(), false + self.counter_class_hash.read(), 0, constructor_calldata.span(), false, ) - .unwrap_syscall(); + .unwrap(); deployed_address } @@ -70,7 +70,7 @@ pub mod CounterFactory { #[cfg(test)] mod tests { use super::{CounterFactory, ICounterFactoryDispatcher, ICounterFactoryDispatcherTrait}; - use starknet::{SyscallResultTrait, ClassHash, syscalls::deploy_syscall}; + use starknet::{ClassHash, syscalls::deploy_syscall}; // Define a target contract to deploy mod target { @@ -120,19 +120,19 @@ mod tests { /// Deploy a counter factory contract fn deploy_factory( - counter_class_hash: ClassHash, init_value: u128 + counter_class_hash: ClassHash, init_value: u128, ) -> ICounterFactoryDispatcher { let mut constructor_calldata: Array:: = array![ - init_value.into(), counter_class_hash.into() + init_value.into(), counter_class_hash.into(), ]; let (contract_address, _) = deploy_syscall( CounterFactory::TEST_CLASS_HASH.try_into().unwrap(), 0, constructor_calldata.span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); ICounterFactoryDispatcher { contract_address } } diff --git a/listings/getting-started/interfaces_traits/src/explicit.cairo b/listings/getting-started/interfaces_traits/src/explicit.cairo index e9ab6b46..4454cc23 100644 --- a/listings/getting-started/interfaces_traits/src/explicit.cairo +++ b/listings/getting-started/interfaces_traits/src/explicit.cairo @@ -11,7 +11,7 @@ pub mod ExplicitInterfaceContract { #[storage] struct Storage { - value: u32 + value: u32, } #[abi(embed_v0)] @@ -31,9 +31,9 @@ pub mod ExplicitInterfaceContract { mod tests { use super::{ ExplicitInterfaceContract, IExplicitInterfaceContractDispatcher, - IExplicitInterfaceContractDispatcherTrait + IExplicitInterfaceContractDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_interface() { @@ -41,9 +41,9 @@ mod tests { ExplicitInterfaceContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IExplicitInterfaceContractDispatcher { contract_address }; let value: u32 = 20; diff --git a/listings/getting-started/interfaces_traits/src/implicit.cairo b/listings/getting-started/interfaces_traits/src/implicit.cairo index aa7f5400..0ab2d6d2 100644 --- a/listings/getting-started/interfaces_traits/src/implicit.cairo +++ b/listings/getting-started/interfaces_traits/src/implicit.cairo @@ -5,7 +5,7 @@ pub mod ImplicitInterfaceContract { #[storage] struct Storage { - value: u32 + value: u32, } #[abi(per_item)] @@ -27,7 +27,7 @@ pub mod ImplicitInterfaceContract { #[cfg(test)] mod tests { use super::{ImplicitInterfaceContract, ImplicitInterfaceContract::IImplicitInterfaceContract}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall, testing::set_contract_address}; + use starknet::{syscalls::deploy_syscall, testing::set_contract_address}; #[test] fn test_interface() { @@ -35,9 +35,9 @@ mod tests { ImplicitInterfaceContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); set_contract_address(contract_address); let mut state = ImplicitInterfaceContract::contract_state_for_testing(); diff --git a/listings/getting-started/interfaces_traits/src/implicit_internal.cairo b/listings/getting-started/interfaces_traits/src/implicit_internal.cairo index 0979d18e..74bdca0f 100644 --- a/listings/getting-started/interfaces_traits/src/implicit_internal.cairo +++ b/listings/getting-started/interfaces_traits/src/implicit_internal.cairo @@ -12,7 +12,7 @@ pub mod ImplicitInternalContract { #[storage] struct Storage { - value: u32 + value: u32, } #[generate_trait] @@ -52,17 +52,20 @@ pub mod ImplicitInternalContract { mod tests { use super::{ ImplicitInternalContract, IImplicitInternalContractDispatcher, - IImplicitInternalContractDispatcherTrait + IImplicitInternalContractDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_interface() { // Set up. let (contract_address, _) = deploy_syscall( - ImplicitInternalContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + ImplicitInternalContract::TEST_CLASS_HASH.try_into().unwrap(), + 0, + array![].span(), + false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IImplicitInternalContractDispatcher { contract_address }; let initial_value: u32 = 0; diff --git a/listings/getting-started/mappings/src/mappings.cairo b/listings/getting-started/mappings/src/mappings.cairo index 39286151..7a4aa932 100644 --- a/listings/getting-started/mappings/src/mappings.cairo +++ b/listings/getting-started/mappings/src/mappings.cairo @@ -33,14 +33,14 @@ pub mod MapContract { #[cfg(test)] mod test { use super::{MapContract, IMapContractDispatcher, IMapContractDispatcherTrait}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_deploy_and_set_get() { let (contract_address, _) = deploy_syscall( - MapContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + MapContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = IMapContractDispatcher { contract_address }; // Write to map. diff --git a/listings/getting-started/storage/src/contract.cairo b/listings/getting-started/storage/src/contract.cairo index c9cae875..4ae5443c 100644 --- a/listings/getting-started/storage/src/contract.cairo +++ b/listings/getting-started/storage/src/contract.cairo @@ -5,7 +5,7 @@ pub mod Contract { struct Storage { pub a: u128, pub b: u8, - pub c: u256 + pub c: u256, } } // [!endregion contract] @@ -13,15 +13,15 @@ pub mod Contract { #[cfg(test)] mod test { use super::Contract; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; use starknet::storage::StoragePointerReadAccess; #[test] fn test_can_deploy() { let (_contract_address, _) = deploy_syscall( - Contract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + Contract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); } #[test] diff --git a/listings/getting-started/storage/src/minimal_contract.cairo b/listings/getting-started/storage/src/minimal_contract.cairo index a9bf24df..ef8ae142 100644 --- a/listings/getting-started/storage/src/minimal_contract.cairo +++ b/listings/getting-started/storage/src/minimal_contract.cairo @@ -10,14 +10,14 @@ pub mod Contract { #[cfg(test)] mod test { use super::Contract; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_can_deploy() { let (_contract_address, _) = deploy_syscall( - Contract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + Contract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); // Not much to test } } diff --git a/listings/getting-started/storing_custom_types/src/contract.cairo b/listings/getting-started/storing_custom_types/src/contract.cairo index 9d29c617..cd2ad282 100644 --- a/listings/getting-started/storing_custom_types/src/contract.cairo +++ b/listings/getting-started/storing_custom_types/src/contract.cairo @@ -10,7 +10,7 @@ pub trait IStoringCustomType { #[derive(Drop, Serde, Copy, starknet::Store)] pub struct Person { pub age: u8, - pub name: felt252 + pub name: felt252, } #[starknet::contract] @@ -20,7 +20,7 @@ pub mod StoringCustomType { #[storage] struct Storage { - pub person: Person + pub person: Person, } #[abi(embed_v0)] @@ -40,7 +40,7 @@ pub mod StoringCustomType { #[cfg(test)] mod tests { - use super::{IStoringCustomType, StoringCustomType, Person,}; + use super::{IStoringCustomType, StoringCustomType, Person}; use starknet::storage::StoragePointerReadAccess; #[test] diff --git a/listings/getting-started/testing_how_to/src/contract.cairo b/listings/getting-started/testing_how_to/src/contract.cairo index 5b9efff1..00a232b4 100644 --- a/listings/getting-started/testing_how_to/src/contract.cairo +++ b/listings/getting-started/testing_how_to/src/contract.cairo @@ -14,7 +14,7 @@ pub mod SimpleContract { #[storage] struct Storage { pub value: u32, - pub owner: ContractAddress + pub owner: ContractAddress, } #[constructor] @@ -48,7 +48,7 @@ mod tests { use super::{SimpleContract, ISimpleContractDispatcher, ISimpleContractDispatcherTrait}; // Import the deploy syscall to be able to deploy the contract. - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; use starknet::{get_contract_address, contract_address_const}; // Use starknet test utils to fake the contract_address @@ -61,9 +61,9 @@ mod tests { SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![initial_value.into()].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); // Return the dispatcher. // The dispatcher allows to interact with the contract based on its interface. @@ -164,7 +164,7 @@ mod tests_with_states { // But we can also deploy the contract and interact with it using the dispatcher // as shown in the previous tests, and still use the state for testing. use super::{ISimpleContractDispatcher, ISimpleContractDispatcherTrait}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall, testing::set_contract_address}; + use starknet::{syscalls::deploy_syscall, testing::set_contract_address}; #[test] fn test_state_with_contract() { @@ -178,9 +178,9 @@ mod tests_with_states { SimpleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![initial_value.into()].span(), - false + false, ) - .unwrap_syscall(); + .unwrap(); let mut contract = ISimpleContractDispatcher { contract_address }; // create the state diff --git a/listings/getting-started/variables/src/global_variables.cairo b/listings/getting-started/variables/src/global_variables.cairo index c0dcf9d3..01e7af48 100644 --- a/listings/getting-started/variables/src/global_variables.cairo +++ b/listings/getting-started/variables/src/global_variables.cairo @@ -26,14 +26,14 @@ pub mod GlobalExample { #[cfg(test)] mod test { use super::GlobalExample; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_can_deploy() { let (_contract_address, _) = deploy_syscall( - GlobalExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + GlobalExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); // Not much to test } } diff --git a/listings/getting-started/variables/src/local_variables.cairo b/listings/getting-started/variables/src/local_variables.cairo index c7f2a2e6..b6d62839 100644 --- a/listings/getting-started/variables/src/local_variables.cairo +++ b/listings/getting-started/variables/src/local_variables.cairo @@ -32,16 +32,16 @@ pub mod LocalVariablesExample { mod test { use super::{ LocalVariablesExample, ILocalVariablesExampleDispatcher, - ILocalVariablesExampleDispatcherTrait + ILocalVariablesExampleDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; #[test] fn test_can_deploy_and_do_something() { let (contract_address, _) = deploy_syscall( - LocalVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + LocalVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); let contract = ILocalVariablesExampleDispatcher { contract_address }; let value = 10; diff --git a/listings/getting-started/variables/src/storage_variables.cairo b/listings/getting-started/variables/src/storage_variables.cairo index 98fff616..3369445e 100644 --- a/listings/getting-started/variables/src/storage_variables.cairo +++ b/listings/getting-started/variables/src/storage_variables.cairo @@ -15,7 +15,7 @@ pub mod StorageVariablesExample { #[storage] struct Storage { // Storage variable holding a number - pub value: u32 + pub value: u32, } #[abi(embed_v0)] @@ -38,18 +38,18 @@ pub mod StorageVariablesExample { mod test { use super::{ StorageVariablesExample, IStorageVariableExampleDispatcher, - IStorageVariableExampleDispatcherTrait + IStorageVariableExampleDispatcherTrait, }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; use starknet::testing::set_contract_address; use starknet::storage::StoragePointerReadAccess; #[test] fn test_can_deploy_and_mutate_storage() { let (contract_address, _) = deploy_syscall( - StorageVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + StorageVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); let contract = IStorageVariableExampleDispatcher { contract_address }; diff --git a/listings/getting-started/visibility/src/visibility.cairo b/listings/getting-started/visibility/src/visibility.cairo index c3b4e2f4..6143566c 100644 --- a/listings/getting-started/visibility/src/visibility.cairo +++ b/listings/getting-started/visibility/src/visibility.cairo @@ -11,7 +11,7 @@ pub mod ExampleContract { #[storage] struct Storage { - pub value: u32 + pub value: u32, } // The `#[abi(embed_v0)]` attribute indicates that all @@ -57,7 +57,7 @@ pub mod ExampleContract { #[cfg(test)] mod test { use super::{ExampleContract, IExampleContractDispatcher, IExampleContractDispatcherTrait}; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::syscalls::deploy_syscall; use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; // These imports will allow us to directly access and set the contract state: @@ -71,9 +71,9 @@ mod test { #[test] fn can_call_set_and_get() { let (contract_address, _) = deploy_syscall( - ExampleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + ExampleContract::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false, ) - .unwrap_syscall(); + .unwrap(); // You can interact with the external entrypoints of the contract using the dispatcher. let contract = IExampleContractDispatcher { contract_address }; diff --git a/pages/components/collisions.md b/pages/components/collisions.md index 32e0e20c..32757d10 100644 --- a/pages/components/collisions.md +++ b/pages/components/collisions.md @@ -21,7 +21,7 @@ Interface: // [!include ~/listings/applications/components/src/others/switch_collision.cairo:interface] ``` -Here's the storage of the contract (you can expand the code snippet to see the full contract and tests): +Here's the storage of the contract: ```cairo // [!include ~/listings/applications/components/src/others/switch_collision.cairo:storage] diff --git a/pages/getting-started/basics/storage.md b/pages/getting-started/basics/storage.md index 78acbdb4..16210f31 100644 --- a/pages/getting-started/basics/storage.md +++ b/pages/getting-started/basics/storage.md @@ -17,7 +17,7 @@ You can define [storage variables](/getting-started/basics/variables#storage-var :::note Actually these two contracts have the same underlying Sierra program. -From the compiler's perspective, the storage variables don't exist until they are used. +The Sierra code is generated only for storage variables that are actually accessed in the contract's functions. Declaring but never using a storage variable doesn't affect the compiled contract size/gas costs. ::: You can also read about [storing custom types](/getting-started/basics/storing-custom-types). diff --git a/pages/getting-started/basics/syscalls.md b/pages/getting-started/basics/syscalls.md index 9c93fdda..64ce911e 100644 --- a/pages/getting-started/basics/syscalls.md +++ b/pages/getting-started/basics/syscalls.md @@ -163,7 +163,7 @@ let values = array![]; values.append(1); values.append(2); values.append(3); -emit_event_syscall(keys, values).unwrap_syscall(); +emit_event_syscall(keys, values).unwrap(); ``` --> #### library_call diff --git a/pages/getting-started/testing/contract-testing.md b/pages/getting-started/testing/contract-testing.md index 21805f6b..2deff011 100644 --- a/pages/getting-started/testing/contract-testing.md +++ b/pages/getting-started/testing/contract-testing.md @@ -30,9 +30,6 @@ Now, let's move on to the testing process: - Use `assert` to verify that the contract behaves as expected in the given context - You can also use assertion macros: `assert_eq!`, `assert_ne!`, `assert_gt!`, `assert_ge!`, `assert_lt!`, `assert_le!` -If you haven't noticed yet, every example in this book has hidden tests, you can see them by clicking the "Show hidden lines" (eyes icon) on the top right of code blocks. -You can also find a detailed explanation of testing in Cairo in [The Cairo Book](https://book.cairo-lang.org/ch10-00-testing-cairo-programs.html). - ## Using the contract state You can use the `Contract::contract_state_for_testing` function to access the contract state. This function is only available in the test environment and allows you to mutate and read the contract state directly. diff --git a/pages/index.mdx b/pages/index.mdx index 75576b25..0814302d 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -1,4 +1,13 @@ import { Sponsors } from "vocs/components"; +import { ThemeImage } from "../components/ThemeImage"; + +
+ +
# Introduction @@ -30,7 +39,7 @@ You can run each example online by using the [Starknet Remix Plugin](https://rem ## Further reading If you want to learn more about the Cairo programming language, you can read the [Cairo Book](https://book.cairo-lang.org). -If you want to learn more about Starknet, you can read the [Starknet documentation](https://docs.starknet.io/) and the [Starknet Book](https://book.starknet.io). +If you want to learn more about Starknet, you can read the [Starknet documentation](https://docs.starknet.io/) and the [Starknet Book](https://docs.starknet.io/). For more resources, check [Awesome Starknet](https://github.com/keep-starknet-strange/awesome-starknet). diff --git a/public/svg/Horizontal_Dark.svg b/public/svg/Horizontal_Dark.svg new file mode 100644 index 00000000..368ecd63 --- /dev/null +++ b/public/svg/Horizontal_Dark.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svg/Horizontal_Light.svg b/public/svg/Horizontal_Light.svg new file mode 100644 index 00000000..671fff8f --- /dev/null +++ b/public/svg/Horizontal_Light.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svg/Icon_Dark.svg b/public/svg/Icon_Dark.svg new file mode 100644 index 00000000..1b45fb36 --- /dev/null +++ b/public/svg/Icon_Dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/svg/Icon_Light.svg b/public/svg/Icon_Light.svg new file mode 100644 index 00000000..01643c89 --- /dev/null +++ b/public/svg/Icon_Light.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/svg/Vertical_Dark.svg b/public/svg/Vertical_Dark.svg new file mode 100644 index 00000000..c3535199 --- /dev/null +++ b/public/svg/Vertical_Dark.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svg/Vertical_Light.svg b/public/svg/Vertical_Light.svg new file mode 100644 index 00000000..e8028a49 --- /dev/null +++ b/public/svg/Vertical_Light.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/routes.ts b/routes.ts index d8348c7f..0faacdaf 100644 --- a/routes.ts +++ b/routes.ts @@ -198,19 +198,20 @@ const config: Sidebar = [ }, ], }, - { - text: "Account Abstraction", - items: [ - { - text: "AA on Starknet", - link: "/advanced-concepts/account_abstraction", - }, - { - text: "Account Contract", - link: "/advanced-concepts/account_abstraction/account_contract", - }, - ], - }, + // Hidden as the content is not 100% correct + // { + // text: "Account Abstraction", + // items: [ + // { + // text: "AA on Starknet", + // link: "/advanced-concepts/account_abstraction", + // }, + // { + // text: "Account Contract", + // link: "/advanced-concepts/account_abstraction/account_contract", + // }, + // ], + // }, { text: "Library Calls", link: "/advanced-concepts/library_calls", @@ -313,7 +314,6 @@ const generateSidebarConfig = (sidebar: SidebarItem[]): Sidebar => { // Configure for all top-level routes getTopLevelRoutes(sidebar).forEach(([route, sectionName]) => { - // console.log(`config["${route}"] = sidebarFocusOn(sidebar, "${sectionName}", true)`) config[`/${route}`] = sidebarFocusOn(sidebar, sectionName, true); }); diff --git a/vocs.config.ts b/vocs.config.ts index ce39fd02..da4225c3 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -8,13 +8,22 @@ import rehypeKatex from "rehype-katex"; // This require custom highlighter, and patch of vocs to remove initial shiki instance export default defineConfig({ + iconUrl: "/svg/Icon_Light.svg", + // iconUrl: { + // light: "/svg/Icon_Light.svg", + // dark: "/svg/Icon_Dark.svg", + // }, + logoUrl: { + light: "/svg/Horizontal_Light.svg", + dark: "/svg/Horizontal_Dark.svg", + }, title: "Starknet by Example", rootDir: ".", sidebar: routes, editLink: { text: "Contribute", pattern: - "https://github.com/NethermindEth/StarknetByExample/edit/vocs/pages/:path", + "https://github.com/NethermindEth/StarknetByExample/edit/dev/pages/:path", }, socials: [ { @@ -89,8 +98,8 @@ export default defineConfig({ // Theme configuration theme: { accentColor: { - dark: "#F69D50", - light: "#ff4b01", + dark: "#ff3000", + light: "#ff3000", }, }, font: { From 082924828ddc307c5119147b6c2602882ef702df Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:06:54 +0700 Subject: [PATCH 03/13] fix(app): correct sidebar placement --- styles.css | 7 ------- 1 file changed, 7 deletions(-) diff --git a/styles.css b/styles.css index 4aeb1128..742942b0 100644 --- a/styles.css +++ b/styles.css @@ -124,10 +124,3 @@ section.vocs_Sidebar_level left: 22px; justify-content: start; } - -/* Force show theme switcher */ -@media screen and (max-width: 1280px) { - .vocs_DesktopTopNav_hideCompact { - display: block; - } -} From b534027cb35cc39738f6c92a3728ffae0d63008c Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:51:08 +0700 Subject: [PATCH 04/13] fix(app): responsive content centering --- styles.css | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/styles.css b/styles.css index 742942b0..e4e1cbe7 100644 --- a/styles.css +++ b/styles.css @@ -60,27 +60,31 @@ section.vocs_Sidebar_level } /* Make sidebar collapsible */ -@media screen and (min-width: 1080px) { - .vocs_DocsLayout_gutterLeft { - margin-left: 0; - transition: margin 0.3s ease; - width: var(--vocs-sidebar_width); - } - .sidebar_hidden .vocs_DocsLayout_gutterLeft { - margin-left: calc(var(--vocs-sidebar_width) * -1); - } +.vocs_DocsLayout_gutterLeft { + top: 0; + left: 0; + bottom: 0; +} +.vocs_DocsLayout_gutterLeft { + margin-left: 0; + transition: margin 0.3s ease; + width: var(--vocs-sidebar_width); +} +.sidebar_hidden .vocs_DocsLayout_gutterLeft { + margin-left: calc(var(--vocs-sidebar_width) * -1); +}; - .vocs_DocsLayout_content_withSidebar { - margin-left: var(--vocs-sidebar_width); - } - .sidebar_hidden .vocs_DocsLayout_content_withSidebar { - margin-left: 0 !important; - } - .vocs_DocsLayout_content_withSidebar { - margin-left: var(--vocs-sidebar_width); - transition: margin 300ms ease !important; - max-width: unset; - } +.vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); +} +.sidebar_hidden .vocs_DocsLayout_content_withSidebar { + margin-left: 0 !important; +} +.vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); + transition: margin 300ms ease !important; + max-width: unset; +} .vocs_DesktopTopNav_logo a { margin-top: 2px !important; From 0a2e64cf983c95424cebcd0ffd86fb372440a585 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:25:05 +0700 Subject: [PATCH 05/13] fix(app): responsive content centering --- styles.css | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/styles.css b/styles.css index e4e1cbe7..4aeb1128 100644 --- a/styles.css +++ b/styles.css @@ -60,31 +60,27 @@ section.vocs_Sidebar_level } /* Make sidebar collapsible */ -.vocs_DocsLayout_gutterLeft { - top: 0; - left: 0; - bottom: 0; -} -.vocs_DocsLayout_gutterLeft { - margin-left: 0; - transition: margin 0.3s ease; - width: var(--vocs-sidebar_width); -} -.sidebar_hidden .vocs_DocsLayout_gutterLeft { - margin-left: calc(var(--vocs-sidebar_width) * -1); -}; +@media screen and (min-width: 1080px) { + .vocs_DocsLayout_gutterLeft { + margin-left: 0; + transition: margin 0.3s ease; + width: var(--vocs-sidebar_width); + } + .sidebar_hidden .vocs_DocsLayout_gutterLeft { + margin-left: calc(var(--vocs-sidebar_width) * -1); + } -.vocs_DocsLayout_content_withSidebar { - margin-left: var(--vocs-sidebar_width); -} -.sidebar_hidden .vocs_DocsLayout_content_withSidebar { - margin-left: 0 !important; -} -.vocs_DocsLayout_content_withSidebar { - margin-left: var(--vocs-sidebar_width); - transition: margin 300ms ease !important; - max-width: unset; -} + .vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); + } + .sidebar_hidden .vocs_DocsLayout_content_withSidebar { + margin-left: 0 !important; + } + .vocs_DocsLayout_content_withSidebar { + margin-left: var(--vocs-sidebar_width); + transition: margin 300ms ease !important; + max-width: unset; + } .vocs_DesktopTopNav_logo a { margin-top: 2px !important; @@ -128,3 +124,10 @@ section.vocs_Sidebar_level left: 22px; justify-content: start; } + +/* Force show theme switcher */ +@media screen and (max-width: 1280px) { + .vocs_DesktopTopNav_hideCompact { + display: block; + } +} From a6e25e39b2352e54ec69c7022db44007fc003222 Mon Sep 17 00:00:00 2001 From: Nuelo Date: Tue, 26 Nov 2024 20:30:25 +0100 Subject: [PATCH 06/13] feat: sierra explanation --- pages/advanced-concepts/sierra_ir.md | 432 +++++++++++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 pages/advanced-concepts/sierra_ir.md diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md new file mode 100644 index 00000000..463edcc4 --- /dev/null +++ b/pages/advanced-concepts/sierra_ir.md @@ -0,0 +1,432 @@ +# Understanding Cairo's Sierra IR: From High-Level Cairo to Safe IR + +## Introduction + +Sierra (Safe Intermediate RepresentAtion) is a critical intermediate language in the Cairo compilation pipeline, designed to bridge the gap between high-level Cairo and low-level CASM (Cairo Assembly). Its primary purpose is to provide memory safety guarantees while maintaining the expressive power needed for zero-knowledge proof generation. + +## Historical Context and Evolution + +### Transition from Cairo 0 to Cairo 1.0 + +Before Starknet Alpha v0.11.0: + +- Developers wrote contracts in Cairo 0 +- Contracts were compiled directly to Cairo assembly (CASM) +- Contract class was submitted to Starknet sequencer via DECLARE transaction + +With Cairo 1.0: + +- Contract class no longer includes CASM directly +- Introduces Sierra as an intermediate representation +- Sequencer performs Sierra → CASM compilation +- CASM code is executed by the Starknet OS + +### Key Problems Solved + +1. Transaction Provability: Every transaction execution must be provable, even failed transactions. +2. Sequencer Protection: Ensures sequencers can charge fees for all transactions, including failed ones. +3. Safety Guarantees: Prevents runtime errors through compile-time checks +4. Memory Safety: Enforces strict ownership rules and prevents invalid memory access + +## The Compilation Pipeline + + ``` + Cairo 1.0 Source (High-level) + ↓ + Cairo-to-Sierra Compiler + ↓ + Sierra IR (Safe, Provable Code) + ↓ + Sierra-to-CASM Compiler (Run by Sequencer) + ↓ + CASM (Cairo Assembly) + ↓ + STARK Proofs (Proof Generation) + ``` + +### Why CASM? + +CASM serves a fundamental role because: + +- Starknet requires STARK proofs for block validity +- STARK proofs work with polynomial constraints +- CASM instructions translate directly to these constraints +- Enables formulation of "This Starknet block is valid" in provable form + +### Why Sierra? + +Sierra addresses several critical needs: + +1. **Provability Guarantees**: + + - Ensures all generated CASM is provable + - Prevents unprovable code patterns + - Handles transaction reverts safely + +2. **Security Considerations**: + + - Protects against DoS attacks + - Ensures sequencer compensation + - Manages transaction failures gracefully + +3. **Technical Benefits**: + + - Memory Safety + - Type Safety + - Optimization opportunities + - Verification layer for smart contracts + +4. **Gas Metering**: + - Predictable execution costs + - Protection against gas-based attacks + - Pre-execution gas requirement calculations + +## Key Concepts in Sierra + +### 1. Type System + +Sierra implements a robust type system with: + +- Concrete types (felt252, u256, etc.) +- Generic types with constraints +- User-defined types +- References and boxing mechanisms + +The type system ensures that: + +- Memory access is always valid +- No uninitialized variables are used +- Type constraints are properly enforced + +### 2. Memory Model + +Sierra's memory model is designed for safety: + +- Linear memory management +- Explicit deallocation +- No implicit copies +- Reference counting for complex data structures + +### 3. Control Flow + +Control flow in Sierra is represented through: + +- Basic blocks +- Branch instructions +- Function calls with explicit stack management +- Loop structures with invariant checking + +## Compilation Process Deep Dive + ``` + Cairo Source Code + ↓ + AST Generation + ↓ + Semantic Analysis + ↓ + Sierra IR Generation + ↓ + Sierra Optimization + ↓ + CASM Generation + ↓ + Proof Generation + ``` + + +### 1. Source to AST(Abstract Syntax Tree) + +```cairo +// Original Cairo code +fn add_numbers(a: felt252, b: felt252) -> felt252 { + let sum = a + b; + sum +} +``` + +Transforms into AST representation (conceptual): + + ```rust + FunctionDefinition { + name: "add_numbers", + params: [ + Parameter { name: "a", type: Felt252 }, + Parameter { name: "b", type: Felt252 } + ], + return_type: Felt252, + body: Block { + statements: [ + LetStatement { + pattern: "sum", + value: BinaryOperation { + left: Identifier("a"), + operator: Add, + right: Identifier("b") + } + }, + ExpressionStatement { + expression: Identifier("sum") + } + ] + } + } + ``` + +### 2. Semantic Analysis + +During this phase, the compiler: + +#### 1. Type Checking: + +```cairo +// This passes semantic analysis +fn safe_add(a: u256, b: u256) -> Result { + match check_overflow(a, b) { + Option::Some(sum) => Result::Ok(sum), + Option::None => Result::Err('overflow') + } +} + +// This fails semantic analysis +fn unsafe_add(a: u256, b: felt252) -> u256 { + a + b // Type mismatch error +} +``` + +#### 2. Variable Resolution: + +```cairo +// Semantic analysis tracks variable scope and usage +fn complex_calculation() -> felt252 { + let x = 5; + { + let x = 10; // New scope, shadows outer x + // Semantic analyzer tracks both x variables + } + x // Analyzer knows this refers to outer x +} +``` + +#### 3. Sierra IR Generation + +The process transforms high-level constructs into sierra's intermediate representation: + +```cairo +// Original Cairo code +fn process_array(arr: Array) -> felt252 { + let mut sum = 0; + let len = arr.len(); + + let mut i = 0; + loop { + if i >= len { + break; + } + sum += arr[i]; + i += 1; + } + sum +} +``` + +#### Transforms into Sierra IR: + +``` +type Array = Array +type felt252 = felt252 +type usize = usize + +libfunc array_len = array_len +libfunc felt252_add = felt252_add +libfunc usize_add = usize_add +libfunc array_get = array_get +libfunc branch_align = branch_align +libfunc jump = jump +libfunc store_temp = store_temp +libfunc felt252_const = felt252_const + +process_array(arr: Array) -> felt252 { + entrance: + felt252_const<0>() -> (sum) // Initialize sum + array_len(arr) -> (len) // Get array length + felt252_const<0>() -> (i) // Initialize counter + jump(loop_start) // Jump to loop + + loop_start: + store_temp(i) -> (i_temp) // Store loop variables + store_temp(sum) -> (sum_temp) + branch_align() -> () + usize_lt(i_temp, len) -> (should_continue) + jump_nz(should_continue, loop_body, loop_end) + + loop_body: + array_get(arr, i) -> (element) + felt252_add(sum_temp, element) -> (new_sum) + usize_add(i_temp, 1) -> (new_i) + store_temp(new_sum) -> (sum) + store_temp(new_i) -> (i) + jump(loop_start) + + loop_end: + ret(sum_temp) +} +``` + +#### 4. Sierra Optimization Phase + +The optimizer performs several passes: + + 1. Dead Code Elimination: + + ``` + // Before optimization + temp0 = felt252_const<1>() + temp1 = felt252_const<2>() + temp2 = felt252_add(temp0, temp1) + temp3 = felt252_const<5>() // Unused + ret(temp2) + + // After optimization + temp0 = felt252_const<1>() + temp1 = felt252_const<2>() + temp2 = felt252_add(temp0, temp1) + ret(temp2) + ``` + + 2. Constant Folding: + + ``` + // Before optimization + temp0 = felt252_const<3>() + temp1 = felt252_const<4>() + temp2 = felt252_add(temp0, temp1) + + // After optimization + temp0 = felt252_const<7>() // Computed at compile time + ``` + + 3. Instruction Combining: + ``` + // Before optimization + temp0 = felt252_mul(x, felt252_const<1>()) + temp1 = felt252_add(temp0, felt252_const<0>()) + + // After optimization + temp0 = x // Unnecessary operations removed + ``` + +#### 5. CASM Generation + +The final stage generates CASM instructions: + + ``` + // Sierra IR + temp0 = felt252_add(a, b) + ret(temp0) + + // Generated CASM + [ap] = [fp - 3] + [fp - 4] # Add values + ret # Return + ``` + +### Special Handling Cases + +1. Complex Data Structures + +```cairo +// Cairo struct +struct Point { + x: felt252, + y: felt252 +} + +// Sierra handling +type Point = Struct +libfunc point_construct = struct_construct +libfunc point_deconstruct = struct_deconstruct +``` + +2. Generic Functions + +```cairo +// Cairo generic function +fn swap(a: T, b: T) -> (T, T) { + (b, a) +} + +// Sierra representation +generic_swap(a: T, b: T) -> (T, T) { + enter: + store_temp(b) -> (temp_b) + store_temp(a) -> (temp_a) + struct_construct>(temp_b, temp_a) -> (result) + ret(result) +} +``` + +3. Error Handling + +```cairo +// Cairo Result type +fn divide(a: felt252, b: felt252) -> Result { + if b == 0 { + Result::Err('Division by zero') + } else { + Result::Ok(a / b) + } +} + +// Sierra error handling +divide(a: felt252, b: felt252) -> Result { + entrance: + felt252_is_zero(b) -> (is_zero) + branch_align() -> () + jump_nz(is_zero, error_path, success_path) + + error_path: + felt252_const<'Division by zero'>() -> (err_msg) + enum_init(err_msg) -> (result) + ret(result) + + success_path: + felt252_div(a, b) -> (quotient) + enum_init(quotient) -> (result) + ret(result) +} +``` + +### Gas Calculation During Compilation + +The compiler calculates gas costs during compilation: + +```cairo +// Original function +fn process_data(data: Array) -> felt252 { + let mut sum = 0; + for item in data { + sum += item; + } + sum +} + +// Sierra with gas tracking +process_data(data: Array) -> felt252 { + entrance: + // Calculate required gas + array_len(data) -> (len) + const(GAS_PER_ITEM) -> (gas_per_item) + mul_gas_requirement(len, gas_per_item) -> (required_gas) + check_gas(required_gas) -> () + + // Continue with actual processing + // ... +} +``` + +### This detailed compilation process ensures: + +Type safety throughout the transformation +Memory safety in the generated code +Proper gas metering +Optimized performance +Deterministic execution From 2e3006ba78385cf5f80a7596ddf6a03ce5a41ada Mon Sep 17 00:00:00 2001 From: Nuelo Date: Wed, 27 Nov 2024 03:08:19 +0100 Subject: [PATCH 07/13] docs: add external resource --- pages/advanced-concepts/sierra_ir.md | 226 ++++++++++++++------------- 1 file changed, 117 insertions(+), 109 deletions(-) diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md index 463edcc4..99b7530b 100644 --- a/pages/advanced-concepts/sierra_ir.md +++ b/pages/advanced-concepts/sierra_ir.md @@ -30,19 +30,19 @@ With Cairo 1.0: ## The Compilation Pipeline - ``` - Cairo 1.0 Source (High-level) - ↓ - Cairo-to-Sierra Compiler - ↓ - Sierra IR (Safe, Provable Code) - ↓ - Sierra-to-CASM Compiler (Run by Sequencer) - ↓ - CASM (Cairo Assembly) - ↓ - STARK Proofs (Proof Generation) - ``` + ``` + Cairo 1.0 Source (High-level) + ↓ + Cairo-to-Sierra Compiler + ↓ + Sierra IR (Safe, Provable Code) + ↓ + Sierra-to-CASM Compiler (Run by Sequencer) + ↓ + CASM (Cairo Assembly) + ↓ + STARK Proofs (Proof Generation) + ``` ### Why CASM? @@ -117,24 +117,24 @@ Control flow in Sierra is represented through: - Loop structures with invariant checking ## Compilation Process Deep Dive - ``` - Cairo Source Code - ↓ - AST Generation - ↓ - Semantic Analysis - ↓ - Sierra IR Generation - ↓ - Sierra Optimization - ↓ - CASM Generation - ↓ - Proof Generation - ``` - - -### 1. Source to AST(Abstract Syntax Tree) + + ``` + Cairo Source Code + ↓ + AST Generation + ↓ + Semantic Analysis + ↓ + Sierra IR Generation + ↓ + Sierra Optimization + ↓ + CASM Generation + ↓ + Proof Generation + ``` + +### 1. Source to AST(Abstract Syntax Tree) ```cairo // Original Cairo code @@ -146,37 +146,37 @@ fn add_numbers(a: felt252, b: felt252) -> felt252 { Transforms into AST representation (conceptual): - ```rust - FunctionDefinition { - name: "add_numbers", - params: [ - Parameter { name: "a", type: Felt252 }, - Parameter { name: "b", type: Felt252 } - ], - return_type: Felt252, - body: Block { - statements: [ - LetStatement { - pattern: "sum", - value: BinaryOperation { - left: Identifier("a"), - operator: Add, - right: Identifier("b") - } - }, - ExpressionStatement { - expression: Identifier("sum") - } - ] - } - } - ``` + ```rust + FunctionDefinition { + name: "add_numbers", + params: [ + Parameter { name: "a", type: Felt252 }, + Parameter { name: "b", type: Felt252 } + ], + return_type: Felt252, + body: Block { + statements: [ + LetStatement { + pattern: "sum", + value: BinaryOperation { + left: Identifier("a"), + operator: Add, + right: Identifier("b") + } + }, + ExpressionStatement { + expression: Identifier("sum") + } + ] + } + } + ``` ### 2. Semantic Analysis During this phase, the compiler: -#### 1. Type Checking: +#### 1. Type Checking: ```cairo // This passes semantic analysis @@ -209,14 +209,14 @@ fn complex_calculation() -> felt252 { #### 3. Sierra IR Generation -The process transforms high-level constructs into sierra's intermediate representation: +The process transforms high-level constructs into sierra's intermediate representation: ```cairo // Original Cairo code fn process_array(arr: Array) -> felt252 { let mut sum = 0; let len = arr.len(); - + let mut i = 0; loop { if i >= len { @@ -276,58 +276,58 @@ process_array(arr: Array) -> felt252 { The optimizer performs several passes: - 1. Dead Code Elimination: - - ``` - // Before optimization - temp0 = felt252_const<1>() - temp1 = felt252_const<2>() - temp2 = felt252_add(temp0, temp1) - temp3 = felt252_const<5>() // Unused - ret(temp2) - - // After optimization - temp0 = felt252_const<1>() - temp1 = felt252_const<2>() - temp2 = felt252_add(temp0, temp1) - ret(temp2) - ``` - - 2. Constant Folding: - - ``` - // Before optimization - temp0 = felt252_const<3>() - temp1 = felt252_const<4>() - temp2 = felt252_add(temp0, temp1) - - // After optimization - temp0 = felt252_const<7>() // Computed at compile time - ``` - - 3. Instruction Combining: - ``` - // Before optimization - temp0 = felt252_mul(x, felt252_const<1>()) - temp1 = felt252_add(temp0, felt252_const<0>()) - - // After optimization - temp0 = x // Unnecessary operations removed - ``` + 1. Dead Code Elimination: + + ``` + // Before optimization + temp0 = felt252_const<1>() + temp1 = felt252_const<2>() + temp2 = felt252_add(temp0, temp1) + temp3 = felt252_const<5>() // Unused + ret(temp2) + + // After optimization + temp0 = felt252_const<1>() + temp1 = felt252_const<2>() + temp2 = felt252_add(temp0, temp1) + ret(temp2) + ``` + + 2. Constant Folding: + + ``` + // Before optimization + temp0 = felt252_const<3>() + temp1 = felt252_const<4>() + temp2 = felt252_add(temp0, temp1) + + // After optimization + temp0 = felt252_const<7>() // Computed at compile time + ``` + + 3. Instruction Combining: + ``` + // Before optimization + temp0 = felt252_mul(x, felt252_const<1>()) + temp1 = felt252_add(temp0, felt252_const<0>()) + + // After optimization + temp0 = x // Unnecessary operations removed + ``` #### 5. CASM Generation -The final stage generates CASM instructions: +The final stage generates CASM instructions: - ``` - // Sierra IR - temp0 = felt252_add(a, b) - ret(temp0) + ``` + // Sierra IR + temp0 = felt252_add(a, b) + ret(temp0) - // Generated CASM - [ap] = [fp - 3] + [fp - 4] # Add values - ret # Return - ``` + // Generated CASM + [ap] = [fp - 3] + [fp - 4] # Add values + ret # Return + ``` ### Special Handling Cases @@ -364,9 +364,9 @@ generic_swap(a: T, b: T) -> (T, T) { } ``` -3. Error Handling +3. Error Handling -```cairo +```cairo // Cairo Result type fn divide(a: felt252, b: felt252) -> Result { if b == 0 { @@ -417,7 +417,7 @@ process_data(data: Array) -> felt252 { const(GAS_PER_ITEM) -> (gas_per_item) mul_gas_requirement(len, gas_per_item) -> (required_gas) check_gas(required_gas) -> () - + // Continue with actual processing // ... } @@ -430,3 +430,11 @@ Memory safety in the generated code Proper gas metering Optimized performance Deterministic execution + +## Further Reading + +- [Cairo and Sierra](https://docs.starknet.io/architecture-and-concepts/smart-contracts/cairo-and-sierra/) + +- [Sierra - Deep Dive](https://www.starknet.io/blog/sierra-deep-dive-video/) + +- [Under the hood of Cairo 1.0: Exploring Sierra](https://medium.com/nethermind-eth/under-the-hood-of-cairo-1-0-exploring-sierra-7f32808421f5) From f5b886552ca933a5b45731393c989e1ce3a22a14 Mon Sep 17 00:00:00 2001 From: Nuelo Date: Sun, 1 Dec 2024 08:46:22 +0100 Subject: [PATCH 08/13] feat: update sierra explanation file --- .../sierra_ir/simple_program.cairo | 7 + .../sierra_ir/simple_program.sierra | 10 + .../sierra_ir/storage_variable.sierra | 323 ++++++++++ .../sierra_ir/storage_variables.cairo | 59 ++ pages/advanced-concepts/sierra_ir.md | 609 +++++++----------- 5 files changed, 641 insertions(+), 367 deletions(-) create mode 100644 listings/advanced-concepts/sierra_ir/simple_program.cairo create mode 100644 listings/advanced-concepts/sierra_ir/simple_program.sierra create mode 100644 listings/advanced-concepts/sierra_ir/storage_variable.sierra create mode 100644 listings/advanced-concepts/sierra_ir/storage_variables.cairo diff --git a/listings/advanced-concepts/sierra_ir/simple_program.cairo b/listings/advanced-concepts/sierra_ir/simple_program.cairo new file mode 100644 index 00000000..5dfe2041 --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/simple_program.cairo @@ -0,0 +1,7 @@ +// [!region contract] +#[starknet::contract] +fn add_numbers(a: felt252, b: felt252) -> felt252 { + let sum = a + b; + sum +} +// [!endregion contract] diff --git a/listings/advanced-concepts/sierra_ir/simple_program.sierra b/listings/advanced-concepts/sierra_ir/simple_program.sierra new file mode 100644 index 00000000..b050b10e --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/simple_program.sierra @@ -0,0 +1,10 @@ +type felt252 = felt252 [storable: true, drop: true, dup: true, zero_sized: false]; + +libfunc felt252_add = felt252_add; +libfunc store_temp = store_temp; + +felt252_add([0], [1]) -> ([2]); // 0 +store_temp([2]) -> ([2]); // 1 +return([2]); // 2 + +simple::simple::add_numbers@0([0]: felt252, [1]: felt252) -> (felt252); diff --git a/listings/advanced-concepts/sierra_ir/storage_variable.sierra b/listings/advanced-concepts/sierra_ir/storage_variable.sierra new file mode 100644 index 00000000..6d1f6833 --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/storage_variable.sierra @@ -0,0 +1,323 @@ +type RangeCheck = RangeCheck [storable: true, drop: false, dup: false, zero_sized: false]; +type Const = Const [storable: false, drop: false, dup: false, zero_sized: false]; +type StorageBaseAddress = StorageBaseAddress [storable: true, drop: true, dup: true, zero_sized: false]; +type core::starknet::storage::StoragePointer0Offset:: = Struct [storable: true, drop: true, dup: true, zero_sized: false]; +type Const = Const [storable: false, drop: false, dup: false, zero_sized: false]; +type Const = Const [storable: false, drop: false, dup: false, zero_sized: false]; +type Array = Array [storable: true, drop: true, dup: false, zero_sized: false]; +type Snapshot> = Snapshot> [storable: true, drop: true, dup: true, zero_sized: false]; +type core::array::Span:: = Struct>> [storable: true, drop: true, dup: true, zero_sized: false]; +type Tuple> = Struct> [storable: true, drop: true, dup: true, zero_sized: false]; +type Const = Const [storable: false, drop: false, dup: false, zero_sized: false]; +type StorageAddress = StorageAddress [storable: true, drop: true, dup: true, zero_sized: false]; +type BuiltinCosts = BuiltinCosts [storable: true, drop: true, dup: true, zero_sized: false]; +type System = System [storable: true, drop: false, dup: false, zero_sized: false]; +type core::panics::Panic = Struct [storable: true, drop: true, dup: true, zero_sized: true]; +type Tuple> = Struct> [storable: true, drop: true, dup: false, zero_sized: false]; +type core::panics::PanicResult::<(core::array::Span::,)> = Enum>, Tuple>> [storable: true, drop: true, dup: false, zero_sized: false]; +type Const = Const [storable: false, drop: false, dup: false, zero_sized: false]; +type u32 = u32 [storable: true, drop: true, dup: true, zero_sized: false]; +type Unit = Struct [storable: true, drop: true, dup: true, zero_sized: true]; +type Box = Box [storable: true, drop: true, dup: true, zero_sized: false]; +type core::option::Option::> = Enum, Unit> [storable: true, drop: true, dup: true, zero_sized: false]; +type felt252 = felt252 [storable: true, drop: true, dup: true, zero_sized: false]; +type GasBuiltin = GasBuiltin [storable: true, drop: false, dup: false, zero_sized: false]; + +libfunc revoke_ap_tracking = revoke_ap_tracking; +libfunc withdraw_gas = withdraw_gas; +libfunc branch_align = branch_align; +libfunc struct_deconstruct> = struct_deconstruct>; +libfunc enable_ap_tracking = enable_ap_tracking; +libfunc store_temp = store_temp; +libfunc array_snapshot_pop_front = array_snapshot_pop_front; +libfunc enum_init>, 0> = enum_init>, 0>; +libfunc store_temp>> = store_temp>>; +libfunc store_temp>> = store_temp>>; +libfunc jump = jump; +libfunc struct_construct = struct_construct; +libfunc enum_init>, 1> = enum_init>, 1>; +libfunc enum_match>> = enum_match>>; +libfunc unbox = unbox; +libfunc rename = rename; +libfunc store_temp = store_temp; +libfunc u32_try_from_felt252 = u32_try_from_felt252; +libfunc disable_ap_tracking = disable_ap_tracking; +libfunc drop>> = drop>>; +libfunc drop> = drop>; +libfunc drop = drop; +libfunc array_new = array_new; +libfunc const_as_immediate> = const_as_immediate>; +libfunc array_append = array_append; +libfunc struct_construct = struct_construct; +libfunc struct_construct>> = struct_construct>>; +libfunc enum_init,)>, 1> = enum_init,)>, 1>; +libfunc store_temp = store_temp; +libfunc store_temp = store_temp; +libfunc store_temp,)>> = store_temp,)>>; +libfunc get_builtin_costs = get_builtin_costs; +libfunc store_temp = store_temp; +libfunc withdraw_gas_all = withdraw_gas_all; +libfunc storage_base_address_const<763158443913282032384596498131031794477249071826004797576159089783775391621> = storage_base_address_const<763158443913282032384596498131031794477249071826004797576159089783775391621>; +libfunc u32_to_felt252 = u32_to_felt252; +libfunc storage_address_from_base = storage_address_from_base; +libfunc const_as_immediate> = const_as_immediate>; +libfunc store_temp = store_temp; +libfunc store_temp = store_temp; +libfunc storage_write_syscall = storage_write_syscall; +libfunc snapshot_take> = snapshot_take>; +libfunc drop> = drop>; +libfunc struct_construct> = struct_construct>; +libfunc struct_construct>> = struct_construct>>; +libfunc enum_init,)>, 0> = enum_init,)>, 0>; +libfunc const_as_immediate> = const_as_immediate>; +libfunc drop = drop; +libfunc const_as_immediate> = const_as_immediate>; +libfunc drop> = drop>; +libfunc struct_construct> = struct_construct>; +libfunc snapshot_take> = snapshot_take>; +libfunc drop> = drop>; +libfunc struct_deconstruct> = struct_deconstruct>; +libfunc rename = rename; +libfunc storage_read_syscall = storage_read_syscall; +libfunc const_as_immediate> = const_as_immediate>; +libfunc store_temp> = store_temp>; + +revoke_ap_tracking() -> (); // 0 +withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; // 1 +branch_align() -> (); // 2 +struct_deconstruct>([3]) -> ([8]); // 3 +enable_ap_tracking() -> (); // 4 +store_temp([4]) -> ([4]); // 5 +array_snapshot_pop_front([8]) { fallthrough([9], [10]) 12([11]) }; // 6 +branch_align() -> (); // 7 +enum_init>, 0>([10]) -> ([12]); // 8 +store_temp>>([9]) -> ([13]); // 9 +store_temp>>([12]) -> ([14]); // 10 +jump() { 17() }; // 11 +branch_align() -> (); // 12 +struct_construct() -> ([15]); // 13 +enum_init>, 1>([15]) -> ([16]); // 14 +store_temp>>([11]) -> ([13]); // 15 +store_temp>>([16]) -> ([14]); // 16 +enum_match>>([14]) { fallthrough([17]) 97([18]) }; // 17 +branch_align() -> (); // 18 +unbox([17]) -> ([19]); // 19 +rename([19]) -> ([20]); // 20 +store_temp([20]) -> ([20]); // 21 +u32_try_from_felt252([4], [20]) { fallthrough([21], [22]) 93([23]) }; // 22 +branch_align() -> (); // 23 +store_temp([21]) -> ([21]); // 24 +array_snapshot_pop_front([13]) { fallthrough([24], [25]) 43([26]) }; // 25 +branch_align() -> (); // 26 +disable_ap_tracking() -> (); // 27 +drop>>([24]) -> (); // 28 +drop>([25]) -> (); // 29 +drop([22]) -> (); // 30 +array_new() -> ([27]); // 31 +const_as_immediate>() -> ([28]); // 32 +store_temp([28]) -> ([28]); // 33 +array_append([27], [28]) -> ([29]); // 34 +struct_construct() -> ([30]); // 35 +struct_construct>>([30], [29]) -> ([31]); // 36 +enum_init,)>, 1>([31]) -> ([32]); // 37 +store_temp([21]) -> ([21]); // 38 +store_temp([5]) -> ([5]); // 39 +store_temp([2]) -> ([2]); // 40 +store_temp,)>>([32]) -> ([32]); // 41 +return([21], [5], [2], [32]); // 42 +branch_align() -> (); // 43 +disable_ap_tracking() -> (); // 44 +drop>>([26]) -> (); // 45 +get_builtin_costs() -> ([33]); // 46 +store_temp([33]) -> ([33]); // 47 +withdraw_gas_all([21], [5], [33]) { fallthrough([34], [35]) 79([36], [37]) }; // 48 +branch_align() -> (); // 49 +storage_base_address_const<763158443913282032384596498131031794477249071826004797576159089783775391621>() -> ([38]); // 50 +u32_to_felt252([22]) -> ([39]); // 51 +storage_address_from_base([38]) -> ([40]); // 52 +const_as_immediate>() -> ([41]); // 53 +store_temp([41]) -> ([41]); // 54 +store_temp([40]) -> ([40]); // 55 +store_temp([34]) -> ([34]); // 56 +storage_write_syscall([35], [2], [41], [40], [39]) { fallthrough([42], [43]) 70([44], [45], [46]) }; // 57 +branch_align() -> (); // 58 +array_new() -> ([47]); // 59 +snapshot_take>([47]) -> ([48], [49]); // 60 +drop>([48]) -> (); // 61 +struct_construct>([49]) -> ([50]); // 62 +struct_construct>>([50]) -> ([51]); // 63 +enum_init,)>, 0>([51]) -> ([52]); // 64 +store_temp([34]) -> ([34]); // 65 +store_temp([42]) -> ([42]); // 66 +store_temp([43]) -> ([43]); // 67 +store_temp,)>>([52]) -> ([52]); // 68 +return([34], [42], [43], [52]); // 69 +branch_align() -> (); // 70 +struct_construct() -> ([53]); // 71 +struct_construct>>([53], [46]) -> ([54]); // 72 +enum_init,)>, 1>([54]) -> ([55]); // 73 +store_temp([34]) -> ([34]); // 74 +store_temp([44]) -> ([44]); // 75 +store_temp([45]) -> ([45]); // 76 +store_temp,)>>([55]) -> ([55]); // 77 +return([34], [44], [45], [55]); // 78 +branch_align() -> (); // 79 +drop([22]) -> (); // 80 +array_new() -> ([56]); // 81 +const_as_immediate>() -> ([57]); // 82 +store_temp([57]) -> ([57]); // 83 +array_append([56], [57]) -> ([58]); // 84 +struct_construct() -> ([59]); // 85 +struct_construct>>([59], [58]) -> ([60]); // 86 +enum_init,)>, 1>([60]) -> ([61]); // 87 +store_temp([36]) -> ([36]); // 88 +store_temp([37]) -> ([37]); // 89 +store_temp([2]) -> ([2]); // 90 +store_temp,)>>([61]) -> ([61]); // 91 +return([36], [37], [2], [61]); // 92 +branch_align() -> (); // 93 +drop>>([13]) -> (); // 94 +store_temp([23]) -> ([62]); // 95 +jump() { 101() }; // 96 +branch_align() -> (); // 97 +drop([18]) -> (); // 98 +drop>>([13]) -> (); // 99 +store_temp([4]) -> ([62]); // 100 +disable_ap_tracking() -> (); // 101 +array_new() -> ([63]); // 102 +const_as_immediate>() -> ([64]); // 103 +store_temp([64]) -> ([64]); // 104 +array_append([63], [64]) -> ([65]); // 105 +struct_construct() -> ([66]); // 106 +struct_construct>>([66], [65]) -> ([67]); // 107 +enum_init,)>, 1>([67]) -> ([68]); // 108 +store_temp([62]) -> ([62]); // 109 +store_temp([5]) -> ([5]); // 110 +store_temp([2]) -> ([2]); // 111 +store_temp,)>>([68]) -> ([68]); // 112 +return([62], [5], [2], [68]); // 113 +branch_align() -> (); // 114 +drop>([3]) -> (); // 115 +array_new() -> ([69]); // 116 +const_as_immediate>() -> ([70]); // 117 +store_temp([70]) -> ([70]); // 118 +array_append([69], [70]) -> ([71]); // 119 +struct_construct() -> ([72]); // 120 +struct_construct>>([72], [71]) -> ([73]); // 121 +enum_init,)>, 1>([73]) -> ([74]); // 122 +store_temp([6]) -> ([6]); // 123 +store_temp([7]) -> ([7]); // 124 +store_temp([2]) -> ([2]); // 125 +store_temp,)>>([74]) -> ([74]); // 126 +return([6], [7], [2], [74]); // 127 +revoke_ap_tracking() -> (); // 128 +withdraw_gas([0], [1]) { fallthrough([4], [5]) 222([6], [7]) }; // 129 +branch_align() -> (); // 130 +struct_deconstruct>([3]) -> ([8]); // 131 +store_temp([4]) -> ([4]); // 132 +array_snapshot_pop_front([8]) { fallthrough([9], [10]) 149([11]) }; // 133 +branch_align() -> (); // 134 +drop>>([9]) -> (); // 135 +drop>([10]) -> (); // 136 +array_new() -> ([12]); // 137 +const_as_immediate>() -> ([13]); // 138 +store_temp([13]) -> ([13]); // 139 +array_append([12], [13]) -> ([14]); // 140 +struct_construct() -> ([15]); // 141 +struct_construct>>([15], [14]) -> ([16]); // 142 +enum_init,)>, 1>([16]) -> ([17]); // 143 +store_temp([4]) -> ([4]); // 144 +store_temp([5]) -> ([5]); // 145 +store_temp([2]) -> ([2]); // 146 +store_temp,)>>([17]) -> ([17]); // 147 +return([4], [5], [2], [17]); // 148 +branch_align() -> (); // 149 +drop>>([11]) -> (); // 150 +get_builtin_costs() -> ([18]); // 151 +store_temp([18]) -> ([18]); // 152 +withdraw_gas_all([4], [5], [18]) { fallthrough([19], [20]) 209([21], [22]) }; // 153 +branch_align() -> (); // 154 +storage_base_address_const<763158443913282032384596498131031794477249071826004797576159089783775391621>() -> ([23]); // 155 +struct_construct>([23]) -> ([24]); // 156 +snapshot_take>([24]) -> ([25], [26]); // 157 +drop>([25]) -> (); // 158 +struct_deconstruct>([26]) -> ([27]); // 159 +rename([27]) -> ([28]); // 160 +storage_address_from_base([28]) -> ([29]); // 161 +const_as_immediate>() -> ([30]); // 162 +store_temp([30]) -> ([30]); // 163 +store_temp([29]) -> ([29]); // 164 +store_temp([19]) -> ([19]); // 165 +storage_read_syscall([20], [2], [30], [29]) { fallthrough([31], [32], [33]) 196([34], [35], [36]) }; // 166 +branch_align() -> (); // 167 +store_temp([33]) -> ([33]); // 168 +store_temp([31]) -> ([31]); // 169 +store_temp([32]) -> ([32]); // 170 +u32_try_from_felt252([19], [33]) { fallthrough([37], [38]) 186([39]) }; // 171 +branch_align() -> (); // 172 +array_new() -> ([40]); // 173 +u32_to_felt252([38]) -> ([41]); // 174 +array_append([40], [41]) -> ([42]); // 175 +snapshot_take>([42]) -> ([43], [44]); // 176 +drop>([43]) -> (); // 177 +struct_construct>([44]) -> ([45]); // 178 +struct_construct>>([45]) -> ([46]); // 179 +enum_init,)>, 0>([46]) -> ([47]); // 180 +store_temp([37]) -> ([37]); // 181 +store_temp([31]) -> ([31]); // 182 +store_temp([32]) -> ([32]); // 183 +store_temp,)>>([47]) -> ([47]); // 184 +return([37], [31], [32], [47]); // 185 +branch_align() -> (); // 186 +array_new() -> ([48]); // 187 +const_as_immediate>() -> ([49]); // 188 +store_temp([49]) -> ([49]); // 189 +array_append([48], [49]) -> ([50]); // 190 +store_temp([39]) -> ([51]); // 191 +store_temp([31]) -> ([52]); // 192 +store_temp([32]) -> ([53]); // 193 +store_temp>([50]) -> ([54]); // 194 +jump() { 201() }; // 195 +branch_align() -> (); // 196 +store_temp([19]) -> ([51]); // 197 +store_temp([34]) -> ([52]); // 198 +store_temp([35]) -> ([53]); // 199 +store_temp>([36]) -> ([54]); // 200 +struct_construct() -> ([55]); // 201 +struct_construct>>([55], [54]) -> ([56]); // 202 +enum_init,)>, 1>([56]) -> ([57]); // 203 +store_temp([51]) -> ([51]); // 204 +store_temp([52]) -> ([52]); // 205 +store_temp([53]) -> ([53]); // 206 +store_temp,)>>([57]) -> ([57]); // 207 +return([51], [52], [53], [57]); // 208 +branch_align() -> (); // 209 +array_new() -> ([58]); // 210 +const_as_immediate>() -> ([59]); // 211 +store_temp([59]) -> ([59]); // 212 +array_append([58], [59]) -> ([60]); // 213 +struct_construct() -> ([61]); // 214 +struct_construct>>([61], [60]) -> ([62]); // 215 +enum_init,)>, 1>([62]) -> ([63]); // 216 +store_temp([21]) -> ([21]); // 217 +store_temp([22]) -> ([22]); // 218 +store_temp([2]) -> ([2]); // 219 +store_temp,)>>([63]) -> ([63]); // 220 +return([21], [22], [2], [63]); // 221 +branch_align() -> (); // 222 +drop>([3]) -> (); // 223 +array_new() -> ([64]); // 224 +const_as_immediate>() -> ([65]); // 225 +store_temp([65]) -> ([65]); // 226 +array_append([64], [65]) -> ([66]); // 227 +struct_construct() -> ([67]); // 228 +struct_construct>>([67], [66]) -> ([68]); // 229 +enum_init,)>, 1>([68]) -> ([69]); // 230 +store_temp([6]) -> ([6]); // 231 +store_temp([7]) -> ([7]); // 232 +store_temp([2]) -> ([2]); // 233 +store_temp,)>>([69]) -> ([69]); // 234 +return([6], [7], [2], [69]); // 235 + +storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__set@0([0]: RangeCheck, [1]: GasBuiltin, [2]: System, [3]: core::array::Span::) -> (RangeCheck, GasBuiltin, System, core::panics::PanicResult::<(core::array::Span::,)>); +storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__get@128([0]: RangeCheck, [1]: GasBuiltin, [2]: System, [3]: core::array::Span::) -> (RangeCheck, GasBuiltin, System, core::panics::PanicResult::<(core::array::Span::,)>); diff --git a/listings/advanced-concepts/sierra_ir/storage_variables.cairo b/listings/advanced-concepts/sierra_ir/storage_variables.cairo new file mode 100644 index 00000000..66f1d52b --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/storage_variables.cairo @@ -0,0 +1,59 @@ +#[starknet::interface] +pub trait IStorageVariableExample { + fn set(ref self: TContractState, value: u32); + fn get(self: @TContractState) -> u32; +} + +// [!region contract] +#[starknet::contract] +pub mod StorageVariablesExample { + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + + #[storage] + struct Storage { + pub value: u32 + } + + #[abi(embed_v0)] + impl StorageVariablesExample of super::IStorageVariableExample { + fn set(ref self: ContractState, value: u32) { + self.value.write(value); + } + + fn get(self: @ContractState) -> u32 { + self.value.read() + } + } +} +// [!endregion contract] + +#[cfg(test)] +mod test { + use super::{ + StorageVariablesExample, IStorageVariableExampleDispatcher, + IStorageVariableExampleDispatcherTrait + }; + use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; + use starknet::testing::set_contract_address; + use starknet::storage::StoragePointerReadAccess; + + #[test] + fn test_can_deploy_and_mutate_storage() { + let (contract_address, _) = deploy_syscall( + StorageVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false + ) + .unwrap_syscall(); + + let contract = IStorageVariableExampleDispatcher { contract_address }; + + let initial_value = 10; + + contract.set(initial_value); + assert_eq!(contract.get(), initial_value); + + // With contract state directly + let state = @StorageVariablesExample::contract_state_for_testing(); + set_contract_address(contract_address); + assert_eq!(state.value.read(), initial_value); + } +} diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md index 99b7530b..e9a4f293 100644 --- a/pages/advanced-concepts/sierra_ir.md +++ b/pages/advanced-concepts/sierra_ir.md @@ -2,439 +2,314 @@ ## Introduction -Sierra (Safe Intermediate RepresentAtion) is a critical intermediate language in the Cairo compilation pipeline, designed to bridge the gap between high-level Cairo and low-level CASM (Cairo Assembly). Its primary purpose is to provide memory safety guarantees while maintaining the expressive power needed for zero-knowledge proof generation. +Sierra (Safe Intermediate RepresentAtion) is a critical intermediate language in the Cairo compilation pipeline, designed to bridge the gap between high-level Cairo and low-level CASM (Cairo Assembly). Its primary purpose is mostly to be able to compile to a subset of casm that we call safe casm that ensure that any transaction sent is provable, while being able to have a high-level language (cairo1) with high memory safety. -## Historical Context and Evolution +## From Cairo 1(High-level) to Sierra: Evolution and Problem Solving in Starknet -### Transition from Cairo 0 to Cairo 1.0 +Before Starknet Alpha v0.11.0, developers wrote contracts in Cairo 0 which compiled directly to Cairo assembly (CASM), and the contract class was submitted to the Starknet sequencer via `DECLARE` transaction. This approach had risks of unprovable transactions and potential sequencer attacks, with limited safety guarantees at compile time. -Before Starknet Alpha v0.11.0: +Cairo 1.0 transformed this landscape by introducing Sierra as an intermediate representation, where contract classes no longer include CASM directly. Instead, the sequencer performs Sierra → CASM compilation before the CASM code is executed by the Starknet OS. This shift ensures every transaction (including failed ones) must be provable, sequencers can charge fees for all transactions, and the system enforces strict memory safety and ownership rules. -- Developers wrote contracts in Cairo 0 -- Contracts were compiled directly to Cairo assembly (CASM) -- Contract class was submitted to Starknet sequencer via DECLARE transaction +This evolution solved critical issues through: +- Guaranteed transaction provability for both successful and failed executions +- Protected sequencers through guaranteed compensation and DoS attack prevention +- Enhanced safety through compile-time checks and strong type system enforcement +- Robust memory safety with strict ownership rules and reliable resource cleanup -With Cairo 1.0: - -- Contract class no longer includes CASM directly -- Introduces Sierra as an intermediate representation -- Sequencer performs Sierra → CASM compilation -- CASM code is executed by the Starknet OS - -### Key Problems Solved - -1. Transaction Provability: Every transaction execution must be provable, even failed transactions. -2. Sequencer Protection: Ensures sequencers can charge fees for all transactions, including failed ones. -3. Safety Guarantees: Prevents runtime errors through compile-time checks -4. Memory Safety: Enforces strict ownership rules and prevents invalid memory access +This comprehensive transition maintains backward compatibility while significantly improving both security and the development experience in the Starknet ecosystem. ## The Compilation Pipeline - - ``` +``` Cairo 1.0 Source (High-level) ↓ - Cairo-to-Sierra Compiler + ↓ with Cairo-to-Sierra Compiler ↓ Sierra IR (Safe, Provable Code) ↓ - Sierra-to-CASM Compiler (Run by Sequencer) + ↓ with Sierra-to-CASM Compiler (Run by Sequencer) ↓ CASM (Cairo Assembly) ↓ + ↓ with CairoVM Execution + ↓ STARK Proofs (Proof Generation) - ``` - -### Why CASM? - -CASM serves a fundamental role because: - -- Starknet requires STARK proofs for block validity -- STARK proofs work with polynomial constraints -- CASM instructions translate directly to these constraints -- Enables formulation of "This Starknet block is valid" in provable form - -### Why Sierra? - -Sierra addresses several critical needs: - -1. **Provability Guarantees**: +``` +At its core, Sierra's compilation process is all about safety and efficiency. It carefully checks types at every step of the transformation, makes sure memory is handled safely in the final code, and keeps track of gas usage with precision. The compiler also focuses on generating optimized code while ensuring that every operation will run the same way each time - something crucial for smart contracts. If you're interested in really understanding how the compilation works under the hood, check out [cairo-compiler-workshop](https://github.com/software-mansion-labs/cairo-compiler-workshop). - - Ensures all generated CASM is provable - - Prevents unprovable code patterns - - Handles transaction reverts safely +## Key Concepts in Sierra -2. **Security Considerations**: +### 1. Type System - - Protects against DoS attacks - - Ensures sequencer compensation - - Manages transaction failures gracefully +Sierra implements a powerful linear type system, where each value must be used exactly once. This "use-once" principle is fundamental to Sierra's safety guarantees, preventing both resource leaks and double-use errors. The system includes concrete types like felt252 and u256, which form the foundation of Sierra's type hierarchy. These are complemented by generic types with constraints, enabling flexible but safe abstractions. User-defined types extend the system's capabilities while maintaining safety guarantees. The type system employs references and boxing mechanisms to manage memory safely, ensuring all memory access is valid, variables are properly initialized before use, and type constraints are consistently enforced throughout the program's execution. -3. **Technical Benefits**: +### 2. Memory Model - - Memory Safety - - Type Safety - - Optimization opportunities - - Verification layer for smart contracts +Sierra's memory model prioritizes safety through deliberate design choices. It implements linear memory management, requiring explicit tracking of resource ownership and lifecycle. Memory operations are handled through explicit deallocation, preventing memory leaks and use-after-free errors. The model prohibits implicit copies, making data movement explicit and traceable. For complex data structures, Sierra employs reference counting to manage shared resources safely, ensuring proper cleanup when resources are no longer needed. This careful approach to memory management forms a cornerstone of Sierra's safety guarantees. -4. **Gas Metering**: - - Predictable execution costs - - Protection against gas-based attacks - - Pre-execution gas requirement calculations +### 3. Control Flow -## Key Concepts in Sierra +Control flow in Sierra is structured through a clear, explicit model that maintains safety while enabling complex program logic. Basic blocks serve as the fundamental units of execution, with explicit branch instructions managing program flow between them. Function calls are handled with explicit stack management, ensuring resource safety across function boundaries. Loop structures incorporate invariant checking, maintaining safety properties throughout iterations. This explicit control flow model enables comprehensive static analysis while preventing common control flow errors. -### 1. Type System -Sierra implements a robust type system with: +## Sierra Code Explanation for a simple cairo program +### original cairo program +```cairo +// [!include ~/listings/advanced-concepts/sierra_ir/simple_cairo.cairo:contract] +``` -- Concrete types (felt252, u256, etc.) -- Generic types with constraints -- User-defined types -- References and boxing mechanisms +### compiled sierra +The above program compiled [sierra code](~/listings/advanced-concepts/sierra_ir/simple_program.sierra) -The type system ensures that: +Sierra (Safe Intermediate Representation and Execution) is a critical intermediate representation in Starknet's Cairo contract compilation process. For the simple add_numbers function, here's a detailed breakdown: -- Memory access is always valid -- No uninitialized variables are used -- Type constraints are properly enforced +1. Type Declarations defines the fundamental data types and their attributes used in the Sierra code. +- `felt252`: Represents the field element type +- Attributes: + - `storable: true`: this attributecan be stored + - `drop: true`: this attribute can be discarded + - `dup: true`: this attributes can be duplicated + - `zero_sized: false`: this attributes has a non-zero memory footprint -### 2. Memory Model +2. Libfunc Declarations specify the library functions available for performing operations on these types. + - `felt252_add`: Performs addition on field elements + - `store_temp`: Temporarily stores the result -Sierra's memory model is designed for safety: +3. Compilation Steps show the actual sequence of operations that happen during code execution. + - Line 0: `felt252_add([0], [1]) -> ([2]): Add input parameters + - Line 1: `store_temp([2]) -> ([2]): Store the temporary result + - Line 2: `return([2]): Return the computed value -- Linear memory management -- Explicit deallocation -- No implicit copies -- Reference counting for complex data structures +4. Libfunc Restrictions: +- Starknet uses an allowed [list](https://github.com/starkware-libs/cairo/tree/main/crates/cairo-lang-starknet-classes/src/allowed_libfuncs_lists) of libfuncs to ensure: + - Security: + Sierra enforces security by allowing only whitelisted operations with predefined behaviors, while maintaining strict control over memory operations and eliminating arbitrary pointer arithmetic to prevent vulnerabilities. + - Predictability: + The restricted libfunc approach ensures deterministic execution across all operations, enabling precise gas cost calculations and well-defined state transitions, while keeping all side effects explicitly managed and traceable. + - Verifiability: + By limiting library functions, Sierra simplifies the proof generation process and makes constraint system generation more efficient, which reduces verification complexity and ensures consistent behavior across different implementations. + - Error Prevention + The restricted library functions eliminate undefined behavior by catching potential runtime errors at compile time, while enforcing explicit resource management and maintaining type safety throughout the entire execution process. +The restricted libfunc approach helps maintain the safety and efficiency of smart contracts on the Starknet platform. -### 3. Control Flow -Control flow in Sierra is represented through: - -- Basic blocks -- Branch instructions -- Function calls with explicit stack management -- Loop structures with invariant checking - -## Compilation Process Deep Dive - - ``` - Cairo Source Code - ↓ - AST Generation - ↓ - Semantic Analysis - ↓ - Sierra IR Generation - ↓ - Sierra Optimization - ↓ - CASM Generation - ↓ - Proof Generation - ``` - -### 1. Source to AST(Abstract Syntax Tree) +## Sierra Code Explanation for Storage Smart Contract ```cairo -// Original Cairo code -fn add_numbers(a: felt252, b: felt252) -> felt252 { - let sum = a + b; - sum -} +// [!include ~/listings/advanced-concepts/sierra_ir/storage_variable.cairo:contract] ``` -Transforms into AST representation (conceptual): - - ```rust - FunctionDefinition { - name: "add_numbers", - params: [ - Parameter { name: "a", type: Felt252 }, - Parameter { name: "b", type: Felt252 } - ], - return_type: Felt252, - body: Block { - statements: [ - LetStatement { - pattern: "sum", - value: BinaryOperation { - left: Identifier("a"), - operator: Add, - right: Identifier("b") - } - }, - ExpressionStatement { - expression: Identifier("sum") - } - ] - } - } - ``` - -### 2. Semantic Analysis - -During this phase, the compiler: - -#### 1. Type Checking: +### compiled sierra +The Storage smart contract compiled [sierra code](~/listings/advanced-concepts/sierra_ir/storage_variable.sierra) + +### 1. Type Decalarations: +This section defines the fundamental types that Sierra uses to ensure type safety and memory management. + +- System and Base Types + ```cairo + type RangeCheck = RangeCheck [storable: true, drop: false, dup: false, zero_sized: false]; + type felt252 = felt252 [storable: true, drop: true, dup: true, zero_sized: false]; + type u32 = u32 [storable: true, drop: true, dup: true, zero_sized: false]; + type GasBuiltin = GasBuiltin [storable: true, drop: false, dup: false, zero_sized: false]; + ``` + What This Means: + + - `RangeCheck`: A type used for validating numeric ranges. It can't be dropped or duplicated, ensuring that range checks are always properly handled. + - `felt252`: Field element type, the basic numeric type in Cairo. It's flexible - can be stored, dropped, and duplicated. + - `u32`: 32-bit unsigned integer, with similar properties to felt252. + - `GasBuiltin`: Tracks gas consumption. Can't be dropped or duplicated to prevent gas accounting errors. + +- Storage-Related Types + ```cairo + type StorageBaseAddress = StorageBaseAddress [storable: true, drop: true, dup: true, zero_sized: false]; + type core::starknet::storage::StoragePointer0Offset:: = + Struct; + type StorageAddress = StorageAddress [storable: true, drop: true, dup: true, zero_sized: false]; + ``` + What This Means: + + - `StorageBaseAddress`: Represents the base location in contract storage. + - `StoragePointer0Offset`: A structured type that points to u32 values in storage. + - `StorageAddress`: The actual address used for storage operations. + +### 2. Library Functions(libfunc) +Sierra provides a set of built-in functions (libfuncs) for handling memory, storage, and gas operations. +- Memory Management + ```cairo + libfunc revoke_ap_tracking = revoke_ap_tracking; + libfunc enable_ap_tracking = enable_ap_tracking; + libfunc disable_ap_tracking = disable_ap_tracking; + + + libfunc store_temp = store_temp; + libfunc drop = drop; + ``` + #### Purpose: + These functions control the allocation pointer (ap) tracking system, which is crucial for memory safety: + + - Enable/disable tracking when needed + - Prevent memory leaks + - Ensure proper memory allocation + + + +- Storage Operations + ```cairo + libfunc storage_base_address_const<...> = storage_base_address_const<...>; + libfunc storage_address_from_base = storage_address_from_base; + libfunc storage_write_syscall = storage_write_syscall; + libfunc storage_read_syscall = storage_read_syscall; + ``` + #### Purpose: + These functions handle all storage interactions: + + - Computing storage addresses + - Reading from storage + - Writing to storage + - Managing storage layout + + +- Gas Management + ```cairo + libfunc withdraw_gas = withdraw_gas; + libfunc withdraw_gas_all = withdraw_gas_all; + libfunc get_builtin_costs = get_builtin_costs; + ``` + #### Purpose: + These functions handle all aspects of gas accounting: + + - Track gas consumption + - Withdraw gas for operations + - Calculate operation costs + - Prevent out-of-gas scenarios + +### 3. Execution Flow Analysis + +- Initialization and Gas Management Phase +This phase marks the beginning of contract execution where Sierra prepares the execution environment and handles initial gas costs. First, it disables the allocation pointer tracking, which is a safety measure to prevent memory tracking overhead during gas calculations. Then, it performs a critical gas withdrawal check - this ensures the contract has sufficient gas to execute, with fallback paths for both successful and failed gas checks. After gas validation, it aligns the execution branch for consistent memory layout and finally deconstructs the input parameters into their base components for further processing. +The phase is crucial for: + + - Setting up memory safety mechanisms + - Ensuring gas availability + - Preparing input parameters + - Establishing execution paths + ```cairo + // The actual code implementation + revoke_ap_tracking() -> (); // 0 + withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; // 1 + branch_align() -> (); // 2 + struct_deconstruct>([3]) -> ([8]); // 3 + ``` + +- Parameter Processing Phase +In this phase, Sierra handles the processing and validation of input parameters. It reactivates the allocation pointer tracking, which was disabled during gas calculations, to ensure memory safety during parameter processing. The range check pointer is stored for numeric validations, crucial for ensuring values are within acceptable ranges. The system then processes array inputs through snapshots - a mechanism that provides safe, immutable views of array data. Finally, it handles option types, which are essential for representing potentially null or invalid values. This phase is fundamental for type safety and memory integrity. ```cairo -// This passes semantic analysis -fn safe_add(a: u256, b: u256) -> Result { - match check_overflow(a, b) { - Option::Some(sum) => Result::Ok(sum), - Option::None => Result::Err('overflow') - } -} - -// This fails semantic analysis -fn unsafe_add(a: u256, b: felt252) -> u256 { - a + b // Type mismatch error -} +enable_ap_tracking() -> (); // 4 +store_temp([4]) -> ([4]); // 5 +array_snapshot_pop_front([8]) { fallthrough([9], [10]) 12([11]) }; // 6 +enum_init>, 0>([10]) -> ([12]); // 8 ``` -#### 2. Variable Resolution: +- Storage Operation Phase +The storage operation phase is where Sierra manages contract storage interactions. It begins by computing the storage base address - a unique identifier for the storage variable. This address is derived from contract-specific constants and variable positions. The system then converts this base address into a concrete storage address that can be used for actual storage operations. During write operations, the system includes multiple checks and fallback paths to handle potential failures, ensuring storage consistency even in error cases. ```cairo -// Semantic analysis tracks variable scope and usage -fn complex_calculation() -> felt252 { - let x = 5; - { - let x = 10; // New scope, shadows outer x - // Semantic analyzer tracks both x variables - } - x // Analyzer knows this refers to outer x -} +storage_base_address_const<...>() -> ([38]); // 50 +storage_address_from_base([38]) -> ([40]); // 52 +storage_write_syscall([35], [2], [41], [40], [39]) { + fallthrough([42], [43]) 70([44], [45], [46]) +}; // 57 ``` -#### 3. Sierra IR Generation - -The process transforms high-level constructs into sierra's intermediate representation: +- Value Processing Phase +During value processing, Sierra handles type conversions and validations of data. This phase is critical for ensuring type safety and data integrity. The system attempts to convert between different numeric types (like felt252 to u32) with built-in overflow checks. Temporary storage is used to maintain values during processing, with careful management of memory resources. Each conversion includes fallback paths for handling potential failures. ```cairo -// Original Cairo code -fn process_array(arr: Array) -> felt252 { - let mut sum = 0; - let len = arr.len(); - - let mut i = 0; - loop { - if i >= len { - break; - } - sum += arr[i]; - i += 1; - } - sum -} -``` - -#### Transforms into Sierra IR: - -``` -type Array = Array -type felt252 = felt252 -type usize = usize - -libfunc array_len = array_len -libfunc felt252_add = felt252_add -libfunc usize_add = usize_add -libfunc array_get = array_get -libfunc branch_align = branch_align -libfunc jump = jump -libfunc store_temp = store_temp -libfunc felt252_const = felt252_const - -process_array(arr: Array) -> felt252 { - entrance: - felt252_const<0>() -> (sum) // Initialize sum - array_len(arr) -> (len) // Get array length - felt252_const<0>() -> (i) // Initialize counter - jump(loop_start) // Jump to loop - - loop_start: - store_temp(i) -> (i_temp) // Store loop variables - store_temp(sum) -> (sum_temp) - branch_align() -> () - usize_lt(i_temp, len) -> (should_continue) - jump_nz(should_continue, loop_body, loop_end) - - loop_body: - array_get(arr, i) -> (element) - felt252_add(sum_temp, element) -> (new_sum) - usize_add(i_temp, 1) -> (new_i) - store_temp(new_sum) -> (sum) - store_temp(new_i) -> (i) - jump(loop_start) - - loop_end: - ret(sum_temp) -} +u32_try_from_felt252([4], [20]) { fallthrough([21], [22]) 93([23]) }; // 22 +store_temp([20]) -> ([20]); // 21 ``` -#### 4. Sierra Optimization Phase - -The optimizer performs several passes: - - 1. Dead Code Elimination: - - ``` - // Before optimization - temp0 = felt252_const<1>() - temp1 = felt252_const<2>() - temp2 = felt252_add(temp0, temp1) - temp3 = felt252_const<5>() // Unused - ret(temp2) - - // After optimization - temp0 = felt252_const<1>() - temp1 = felt252_const<2>() - temp2 = felt252_add(temp0, temp1) - ret(temp2) - ``` - - 2. Constant Folding: - - ``` - // Before optimization - temp0 = felt252_const<3>() - temp1 = felt252_const<4>() - temp2 = felt252_add(temp0, temp1) - - // After optimization - temp0 = felt252_const<7>() // Computed at compile time - ``` - - 3. Instruction Combining: - ``` - // Before optimization - temp0 = felt252_mul(x, felt252_const<1>()) - temp1 = felt252_add(temp0, felt252_const<0>()) - - // After optimization - temp0 = x // Unnecessary operations removed - ``` - -#### 5. CASM Generation - -The final stage generates CASM instructions: - - ``` - // Sierra IR - temp0 = felt252_add(a, b) - ret(temp0) - - // Generated CASM - [ap] = [fp - 3] + [fp - 4] # Add values - ret # Return - ``` - -### Special Handling Cases - -1. Complex Data Structures +- Error Handling Phase +The error handling phase implements Sierra's robust error management system. It constructs panic results for error cases, ensuring that failures are handled gracefully and securely. The system creates structured error information including panic details and relevant error data. This phase is crucial for maintaining contract reliability and providing meaningful error feedback. All error states are carefully packaged into result types that can be safely returned and handled by the calling context. ```cairo -// Cairo struct -struct Point { - x: felt252, - y: felt252 -} - -// Sierra handling -type Point = Struct -libfunc point_construct = struct_construct -libfunc point_deconstruct = struct_deconstruct +struct_construct() -> ([30]); // 35 +struct_construct>>([30], [29]) -> ([31]); // 36 +enum_init,)>, 1>([31]) -> ([32]); // 37 ``` -2. Generic Functions +- Return Phase +The return phase is responsible for finalizing the execution and preparing the return values. It ensures all resources are properly accounted for by storing final values for range checking, gas tracking, and system state. The phase carefully packages all return values, maintaining type safety and memory integrity. This phase is critical for ensuring the contract's state is consistent after execution. ```cairo -// Cairo generic function -fn swap(a: T, b: T) -> (T, T) { - (b, a) -} - -// Sierra representation -generic_swap(a: T, b: T) -> (T, T) { - enter: - store_temp(b) -> (temp_b) - store_temp(a) -> (temp_a) - struct_construct>(temp_b, temp_a) -> (result) - ret(result) -} +store_temp([21]) -> ([21]); // 38 +store_temp([5]) -> ([5]); // 39 +store_temp([2]) -> ([2]); // 40 +return([21], [5], [2], [32]); // 42 ``` -3. Error Handling +- Storage Read Flow +The storage read operation is a specialized flow that handles retrieving values from contract storage. It begins with a storage address computation, followed by a syscall to read the storage value. The read value is then processed and converted to the appropriate type with necessary validations. This operation includes comprehensive error handling for cases like invalid storage addresses or type conversion failures. -```cairo -// Cairo Result type -fn divide(a: felt252, b: felt252) -> Result { - if b == 0 { - Result::Err('Division by zero') - } else { - Result::Ok(a / b) - } -} - -// Sierra error handling -divide(a: felt252, b: felt252) -> Result { - entrance: - felt252_is_zero(b) -> (is_zero) - branch_align() -> () - jump_nz(is_zero, error_path, success_path) - - error_path: - felt252_const<'Division by zero'>() -> (err_msg) - enum_init(err_msg) -> (result) - ret(result) - - success_path: - felt252_div(a, b) -> (quotient) - enum_init(quotient) -> (result) - ret(result) -} +```cairo +storage_read_syscall([20], [2], [30], [29]) { + fallthrough([31], [32], [33]) 196([34], [35], [36]) +}; // 166 +store_temp([33]) -> ([33]); // 168 +u32_try_from_felt252([19], [33]); // 171 ``` -### Gas Calculation During Compilation - -The compiler calculates gas costs during compilation: +- Storage Write Flow +The storage write operation manages a secure and atomic process for updating contract state in Sierra. It begins with precise gas calculations and withdrawals to ensure sufficient resources for the complete operation. The system then computes a unique storage address through a two-step process: generating a base address from contract-specific constants and transforming it into a concrete storage location. Finally, it executes the atomic write operation through a system call, with comprehensive error handling to maintain storage integrity. The entire process ensures consistent state updates, prevents data corruption, and handles failures gracefully. + + ```cairo + withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; + + storage_base_address_const<...>() -> ([38]); + storage_address_from_base([38]) -> ([40]); + + storage_write_syscall([35], [2], [41], [40], [39]); + ``` + +### 4. Function Implementation Analysis +- Set Function Implementation + ```cairo + // Function wrapper + storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__set@0( + [0]: RangeCheck, // For numeric checks + [1]: GasBuiltin, // For gas tracking + [2]: System, // For system calls + [3]: core::array::Span:: // Input parameters + ) + ``` + Key Operations: + 1. `Gas` withdrawal and checks + 2. `Parameter` validation + 3. `Storage` address computation + 4. `Value` writing to storage + 5. `Return` handling with panic checks + +- Get Function Implementation + storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__get@128( + // Similar parameters as set + ) + + Key Operations: + 1. `Gas` checks + 2. `Storage` address computation + 3. `Value` reading from storage + 4. `Type` conversion and validation + 5. `Result` packaging and return -```cairo -// Original function -fn process_data(data: Array) -> felt252 { - let mut sum = 0; - for item in data { - sum += item; - } - sum -} - -// Sierra with gas tracking -process_data(data: Array) -> felt252 { - entrance: - // Calculate required gas - array_len(data) -> (len) - const(GAS_PER_ITEM) -> (gas_per_item) - mul_gas_requirement(len, gas_per_item) -> (required_gas) - check_gas(required_gas) -> () - - // Continue with actual processing - // ... -} -``` +## Further Reading -### This detailed compilation process ensures: +- [Under the hood of Cairo 1.0: Exploring Sierra](https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-1) -Type safety throughout the transformation -Memory safety in the generated code -Proper gas metering -Optimized performance -Deterministic execution +- [Under the hood of Cairo 2.0: Exploring Sierra](https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-2) -## Further Reading +- [Under the hood of Cairo 1.0: Exploring Sierra](https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-3) - [Cairo and Sierra](https://docs.starknet.io/architecture-and-concepts/smart-contracts/cairo-and-sierra/) - [Sierra - Deep Dive](https://www.starknet.io/blog/sierra-deep-dive-video/) -- [Under the hood of Cairo 1.0: Exploring Sierra](https://medium.com/nethermind-eth/under-the-hood-of-cairo-1-0-exploring-sierra-7f32808421f5) From 436665734b9fab53c760f1642b820740ae01d3d7 Mon Sep 17 00:00:00 2001 From: Nuelo Date: Mon, 2 Dec 2024 17:40:00 +0100 Subject: [PATCH 09/13] refact: return value of add_number --- listings/advanced-concepts/sierra_ir/simple_program.cairo | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/listings/advanced-concepts/sierra_ir/simple_program.cairo b/listings/advanced-concepts/sierra_ir/simple_program.cairo index 5dfe2041..6707f0f5 100644 --- a/listings/advanced-concepts/sierra_ir/simple_program.cairo +++ b/listings/advanced-concepts/sierra_ir/simple_program.cairo @@ -1,7 +1,6 @@ // [!region contract] #[starknet::contract] fn add_numbers(a: felt252, b: felt252) -> felt252 { - let sum = a + b; - sum + a + b; } // [!endregion contract] From 83fece7596d0bd1ced9c615dce50d07b4c70cb6e Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:03:06 +0100 Subject: [PATCH 10/13] fix sierra_ir (wip) --- .gitignore | 3 + Scarb.lock | 4 + .../advanced-concepts/sierra_ir/.gitignore | 1 + .../advanced-concepts/sierra_ir/Scarb.toml | 16 + .../sierra_ir/simple_program.cairo | 6 - .../sierra_ir/simple_program.sierra | 2 +- .../advanced-concepts/sierra_ir/src/lib.cairo | 1 + .../sierra_ir/src/simple_program.cairo | 3 + .../sierra_ir/storage_variables.cairo | 59 --- .../variables/storage_variables.sierra} | 0 pages/advanced-concepts/sierra_ir.md | 346 +++++------------- .../sierra_ir_storage_contract.md | 3 + routes.ts | 4 + 13 files changed, 128 insertions(+), 320 deletions(-) create mode 100644 listings/advanced-concepts/sierra_ir/.gitignore create mode 100644 listings/advanced-concepts/sierra_ir/Scarb.toml delete mode 100644 listings/advanced-concepts/sierra_ir/simple_program.cairo create mode 100644 listings/advanced-concepts/sierra_ir/src/lib.cairo create mode 100644 listings/advanced-concepts/sierra_ir/src/simple_program.cairo delete mode 100644 listings/advanced-concepts/sierra_ir/storage_variables.cairo rename listings/{advanced-concepts/sierra_ir/storage_variable.sierra => getting-started/variables/storage_variables.sierra} (100%) create mode 100644 pages/advanced-concepts/sierra_ir_storage_contract.md diff --git a/.gitignore b/.gitignore index 2e243330..6a924305 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ src/**/*.md node_modules + +# windsurf rules +.windsurfrules diff --git a/Scarb.lock b/Scarb.lock index a7c69be7..0658f032 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -249,6 +249,10 @@ name = "pragma_lib" version = "1.0.0" source = "git+https://github.com/astraly-labs/pragma-lib?tag=2.9.1#ee1f3f7e9276cf64e19e267832de380d84c04d28" +[[package]] +name = "sierra_ir" +version = "0.1.0" + [[package]] name = "simple_account" version = "0.1.0" diff --git a/listings/advanced-concepts/sierra_ir/.gitignore b/listings/advanced-concepts/sierra_ir/.gitignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/.gitignore @@ -0,0 +1 @@ +target diff --git a/listings/advanced-concepts/sierra_ir/Scarb.toml b/listings/advanced-concepts/sierra_ir/Scarb.toml new file mode 100644 index 00000000..d6496a44 --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/Scarb.toml @@ -0,0 +1,16 @@ +[package] +name = "sierra_ir" +version.workspace = true +edition.workspace = true + +[lib] +sierra-text = true + +[dependencies] +starknet.workspace = true + +[dev-dependencies] +cairo_test.workspace = true + +[scripts] +test.workspace = true diff --git a/listings/advanced-concepts/sierra_ir/simple_program.cairo b/listings/advanced-concepts/sierra_ir/simple_program.cairo deleted file mode 100644 index 6707f0f5..00000000 --- a/listings/advanced-concepts/sierra_ir/simple_program.cairo +++ /dev/null @@ -1,6 +0,0 @@ -// [!region contract] -#[starknet::contract] -fn add_numbers(a: felt252, b: felt252) -> felt252 { - a + b; -} -// [!endregion contract] diff --git a/listings/advanced-concepts/sierra_ir/simple_program.sierra b/listings/advanced-concepts/sierra_ir/simple_program.sierra index b050b10e..e0447566 100644 --- a/listings/advanced-concepts/sierra_ir/simple_program.sierra +++ b/listings/advanced-concepts/sierra_ir/simple_program.sierra @@ -7,4 +7,4 @@ felt252_add([0], [1]) -> ([2]); // 0 store_temp([2]) -> ([2]); // 1 return([2]); // 2 -simple::simple::add_numbers@0([0]: felt252, [1]: felt252) -> (felt252); +sierra_ir::add_numbers@0([0]: felt252, [1]: felt252) -> (felt252); diff --git a/listings/advanced-concepts/sierra_ir/src/lib.cairo b/listings/advanced-concepts/sierra_ir/src/lib.cairo new file mode 100644 index 00000000..981e6956 --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/src/lib.cairo @@ -0,0 +1 @@ +mod simple_program; \ No newline at end of file diff --git a/listings/advanced-concepts/sierra_ir/src/simple_program.cairo b/listings/advanced-concepts/sierra_ir/src/simple_program.cairo new file mode 100644 index 00000000..651b1472 --- /dev/null +++ b/listings/advanced-concepts/sierra_ir/src/simple_program.cairo @@ -0,0 +1,3 @@ +fn add_numbers(a: felt252, b: felt252) -> felt252 { + a + b +} diff --git a/listings/advanced-concepts/sierra_ir/storage_variables.cairo b/listings/advanced-concepts/sierra_ir/storage_variables.cairo deleted file mode 100644 index 66f1d52b..00000000 --- a/listings/advanced-concepts/sierra_ir/storage_variables.cairo +++ /dev/null @@ -1,59 +0,0 @@ -#[starknet::interface] -pub trait IStorageVariableExample { - fn set(ref self: TContractState, value: u32); - fn get(self: @TContractState) -> u32; -} - -// [!region contract] -#[starknet::contract] -pub mod StorageVariablesExample { - use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - - #[storage] - struct Storage { - pub value: u32 - } - - #[abi(embed_v0)] - impl StorageVariablesExample of super::IStorageVariableExample { - fn set(ref self: ContractState, value: u32) { - self.value.write(value); - } - - fn get(self: @ContractState) -> u32 { - self.value.read() - } - } -} -// [!endregion contract] - -#[cfg(test)] -mod test { - use super::{ - StorageVariablesExample, IStorageVariableExampleDispatcher, - IStorageVariableExampleDispatcherTrait - }; - use starknet::{SyscallResultTrait, syscalls::deploy_syscall}; - use starknet::testing::set_contract_address; - use starknet::storage::StoragePointerReadAccess; - - #[test] - fn test_can_deploy_and_mutate_storage() { - let (contract_address, _) = deploy_syscall( - StorageVariablesExample::TEST_CLASS_HASH.try_into().unwrap(), 0, array![].span(), false - ) - .unwrap_syscall(); - - let contract = IStorageVariableExampleDispatcher { contract_address }; - - let initial_value = 10; - - contract.set(initial_value); - assert_eq!(contract.get(), initial_value); - - // With contract state directly - let state = @StorageVariablesExample::contract_state_for_testing(); - set_contract_address(contract_address); - assert_eq!(state.value.read(), initial_value); - } -} diff --git a/listings/advanced-concepts/sierra_ir/storage_variable.sierra b/listings/getting-started/variables/storage_variables.sierra similarity index 100% rename from listings/advanced-concepts/sierra_ir/storage_variable.sierra rename to listings/getting-started/variables/storage_variables.sierra diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md index e9a4f293..4f69a315 100644 --- a/pages/advanced-concepts/sierra_ir.md +++ b/pages/advanced-concepts/sierra_ir.md @@ -1,305 +1,144 @@ -# Understanding Cairo's Sierra IR: From High-Level Cairo to Safe IR +# Understanding Sierra: From High-Level Cairo to Safe CASM -## Introduction +Sierra (**S**afe **I**nt**er**mediate **R**epresent**a**tion) is an intermediate representation of Cairo instructions, designed to bridge the gap between high-level Cairo 1 and low-level Cairo Assembly (CASM). +Sierra can be compiled to a subset of CASM that we call `Safe CASM{:md}`. It ensures that every function returns by using a compiler that can detect operations that can't be proven such as infinite loops, unsatisfiable constraints, etc. -Sierra (Safe Intermediate RepresentAtion) is a critical intermediate language in the Cairo compilation pipeline, designed to bridge the gap between high-level Cairo and low-level CASM (Cairo Assembly). Its primary purpose is mostly to be able to compile to a subset of casm that we call safe casm that ensure that any transaction sent is provable, while being able to have a high-level language (cairo1) with high memory safety. +### From Cairo 1 to Sierra -## From Cairo 1(High-level) to Sierra: Evolution and Problem Solving in Starknet +Before Starknet Alpha v0.11.0, developers wrote contracts in Cairo 0 which compiled directly to Cairo Assembly (CASM), and the contract classes were submitted to the sequencer with `DECLARE` transactions. This approach had risks as the sequencer would not be able to know if a given transaction would fail or not without executing it, and would not be able to charge fees for failed transactions. -Before Starknet Alpha v0.11.0, developers wrote contracts in Cairo 0 which compiled directly to Cairo assembly (CASM), and the contract class was submitted to the Starknet sequencer via `DECLARE` transaction. This approach had risks of unprovable transactions and potential sequencer attacks, with limited safety guarantees at compile time. +Cairo 1 introduced contract class compilation to this new Sierra intermediate representation instead of directly to CASM. The Sierra code is then submitted to the sequencer, compiled down to CASM, and finally executed by the Starknet OS. +The usage of Sierra ensures that every transactions (including failed ones) must be provable, and the sequencers can charge fees for all submitted transactions making DoS attacks really expensive. -Cairo 1.0 transformed this landscape by introducing Sierra as an intermediate representation, where contract classes no longer include CASM directly. Instead, the sequencer performs Sierra → CASM compilation before the CASM code is executed by the Starknet OS. This shift ensures every transaction (including failed ones) must be provable, sequencers can charge fees for all transactions, and the system enforces strict memory safety and ownership rules. +### Compilation Pipeline -This evolution solved critical issues through: -- Guaranteed transaction provability for both successful and failed executions -- Protected sequencers through guaranteed compensation and DoS attack prevention -- Enhanced safety through compile-time checks and strong type system enforcement -- Robust memory safety with strict ownership rules and reliable resource cleanup - -This comprehensive transition maintains backward compatibility while significantly improving both security and the development experience in the Starknet ecosystem. - -## The Compilation Pipeline ``` Cairo 1.0 Source (High-level) - ↓ - ↓ with Cairo-to-Sierra Compiler - ↓ + | + | with Cairo-to-Sierra Compiler + V Sierra IR (Safe, Provable Code) - ↓ - ↓ with Sierra-to-CASM Compiler (Run by Sequencer) - ↓ + | + | with Sierra-to-CASM Compiler (Run by Sequencer) + V CASM (Cairo Assembly) - ↓ - ↓ with CairoVM Execution - ↓ + | + | with CairoVM Execution + V STARK Proofs (Proof Generation) ``` -At its core, Sierra's compilation process is all about safety and efficiency. It carefully checks types at every step of the transformation, makes sure memory is handled safely in the final code, and keeps track of gas usage with precision. The compiler also focuses on generating optimized code while ensuring that every operation will run the same way each time - something crucial for smart contracts. If you're interested in really understanding how the compilation works under the hood, check out [cairo-compiler-workshop](https://github.com/software-mansion-labs/cairo-compiler-workshop). - -## Key Concepts in Sierra -### 1. Type System +At its core, Sierra's compilation process is all about safety and efficiency. It carefully checks types at every step of the transformation, makes sure memory is handled safely in the final code, and keeps track of gas usage. The compiler also focuses on generating optimized code while ensuring that every operation will run the same way each time. +If you're interested in really understanding how the compilation works under the hood, check out the [cairo-compiler-workshop](https://github.com/software-mansion-labs/cairo-compiler-workshop). -Sierra implements a powerful linear type system, where each value must be used exactly once. This "use-once" principle is fundamental to Sierra's safety guarantees, preventing both resource leaks and double-use errors. The system includes concrete types like felt252 and u256, which form the foundation of Sierra's type hierarchy. These are complemented by generic types with constraints, enabling flexible but safe abstractions. User-defined types extend the system's capabilities while maintaining safety guarantees. The type system employs references and boxing mechanisms to manage memory safely, ensuring all memory access is valid, variables are properly initialized before use, and type constraints are consistently enforced throughout the program's execution. +### Anatomy of a Sierra Program -### 2. Memory Model +### Type Declarations -Sierra's memory model prioritizes safety through deliberate design choices. It implements linear memory management, requiring explicit tracking of resource ownership and lifecycle. Memory operations are handled through explicit deallocation, preventing memory leaks and use-after-free errors. The model prohibits implicit copies, making data movement explicit and traceable. For complex data structures, Sierra employs reference counting to manage shared resources safely, ensuring proper cleanup when resources are no longer needed. This careful approach to memory management forms a cornerstone of Sierra's safety guarantees. +Sierra uses a **linear type system**, where each value **must be used exactly once**. +During the compilation, an unique identifier is assigned to each type. -### 3. Control Flow - -Control flow in Sierra is structured through a clear, explicit model that maintains safety while enabling complex program logic. Basic blocks serve as the fundamental units of execution, with explicit branch instructions managing program flow between them. Function calls are handled with explicit stack management, ensuring resource safety across function boundaries. Loop structures incorporate invariant checking, maintaining safety properties throughout iterations. This explicit control flow model enables comprehensive static analysis while preventing common control flow errors. +When types can safely be used multiple times, they need to be duplicated using the `dup` instruction, which will assign two new identifiers to preserve linearity. +Type declaration is done with the following syntax: +```cairo +type type_id = concrete_type; +``` -## Sierra Code Explanation for a simple cairo program -### original cairo program + -### compiled sierra -The above program compiled [sierra code](~/listings/advanced-concepts/sierra_ir/simple_program.sierra) +### Library Function Declarations -Sierra (Safe Intermediate Representation and Execution) is a critical intermediate representation in Starknet's Cairo contract compilation process. For the simple add_numbers function, here's a detailed breakdown: +Sierra comes with a set of built-in functions (`libfuncs`) that always compile to Safe CASM. After types declaration, a Sierra program must define all the libfuncs used in the program with the inpt type expected. -1. Type Declarations defines the fundamental data types and their attributes used in the Sierra code. -- `felt252`: Represents the field element type -- Attributes: - - `storable: true`: this attributecan be stored - - `drop: true`: this attribute can be discarded - - `dup: true`: this attributes can be duplicated - - `zero_sized: false`: this attributes has a non-zero memory footprint +Libfunc declaration is done with the following syntax: +```cairo +libfunc libfunc_id = libfunc_name; +``` -2. Libfunc Declarations specify the library functions available for performing operations on these types. - - `felt252_add`: Performs addition on field elements - - `store_temp`: Temporarily stores the result +### Statements -3. Compilation Steps show the actual sequence of operations that happen during code execution. - - Line 0: `felt252_add([0], [1]) -> ([2]): Add input parameters - - Line 1: `store_temp([2]) -> ([2]): Store the temporary result - - Line 2: `return([2]): Return the computed value +This part shows the sequence of operations that happen during execution, which describes the actual logic of the program. A statement either invokes a libfunc or returns a value. -4. Libfunc Restrictions: -- Starknet uses an allowed [list](https://github.com/starkware-libs/cairo/tree/main/crates/cairo-lang-starknet-classes/src/allowed_libfuncs_lists) of libfuncs to ensure: - - Security: - Sierra enforces security by allowing only whitelisted operations with predefined behaviors, while maintaining strict control over memory operations and eliminating arbitrary pointer arithmetic to prevent vulnerabilities. - - Predictability: - The restricted libfunc approach ensures deterministic execution across all operations, enabling precise gas cost calculations and well-defined state transitions, while keeping all side effects explicitly managed and traceable. - - Verifiability: - By limiting library functions, Sierra simplifies the proof generation process and makes constraint system generation more efficient, which reduces verification complexity and ensures consistent behavior across different implementations. - - Error Prevention - The restricted library functions eliminate undefined behavior by catching potential runtime errors at compile time, while enforcing explicit resource management and maintaining type safety throughout the entire execution process. -The restricted libfunc approach helps maintain the safety and efficiency of smart contracts on the Starknet platform. +A statement is declared with the following syntax: +```cairo +libfunc_id(input_variables) -> (output_variables); +``` + +To return a value, we use the `return(variable_id)` statement. +### User Defined Functions Declarations -## Sierra Code Explanation for Storage Smart Contract +At the very end of the Sierra program, each user defined function is declared with an unique identifier and an index to specify the location of the statement where the execution of the function should start. +An user defined function is declared with the following syntax: ```cairo -// [!include ~/listings/advanced-concepts/sierra_ir/storage_variable.cairo:contract] +function_id@statement_index(parameters: types) -> (return_types); ``` -### compiled sierra -The Storage smart contract compiled [sierra code](~/listings/advanced-concepts/sierra_ir/storage_variable.sierra) - -### 1. Type Decalarations: -This section defines the fundamental types that Sierra uses to ensure type safety and memory management. - -- System and Base Types - ```cairo - type RangeCheck = RangeCheck [storable: true, drop: false, dup: false, zero_sized: false]; - type felt252 = felt252 [storable: true, drop: true, dup: true, zero_sized: false]; - type u32 = u32 [storable: true, drop: true, dup: true, zero_sized: false]; - type GasBuiltin = GasBuiltin [storable: true, drop: false, dup: false, zero_sized: false]; - ``` - What This Means: - - - `RangeCheck`: A type used for validating numeric ranges. It can't be dropped or duplicated, ensuring that range checks are always properly handled. - - `felt252`: Field element type, the basic numeric type in Cairo. It's flexible - can be stored, dropped, and duplicated. - - `u32`: 32-bit unsigned integer, with similar properties to felt252. - - `GasBuiltin`: Tracks gas consumption. Can't be dropped or duplicated to prevent gas accounting errors. - -- Storage-Related Types - ```cairo - type StorageBaseAddress = StorageBaseAddress [storable: true, drop: true, dup: true, zero_sized: false]; - type core::starknet::storage::StoragePointer0Offset:: = - Struct; - type StorageAddress = StorageAddress [storable: true, drop: true, dup: true, zero_sized: false]; - ``` - What This Means: - - - `StorageBaseAddress`: Represents the base location in contract storage. - - `StoragePointer0Offset`: A structured type that points to u32 values in storage. - - `StorageAddress`: The actual address used for storage operations. - -### 2. Library Functions(libfunc) -Sierra provides a set of built-in functions (libfuncs) for handling memory, storage, and gas operations. -- Memory Management - ```cairo - libfunc revoke_ap_tracking = revoke_ap_tracking; - libfunc enable_ap_tracking = enable_ap_tracking; - libfunc disable_ap_tracking = disable_ap_tracking; - - - libfunc store_temp = store_temp; - libfunc drop = drop; - ``` - #### Purpose: - These functions control the allocation pointer (ap) tracking system, which is crucial for memory safety: - - - Enable/disable tracking when needed - - Prevent memory leaks - - Ensure proper memory allocation - - - -- Storage Operations - ```cairo - libfunc storage_base_address_const<...> = storage_base_address_const<...>; - libfunc storage_address_from_base = storage_address_from_base; - libfunc storage_write_syscall = storage_write_syscall; - libfunc storage_read_syscall = storage_read_syscall; - ``` - #### Purpose: - These functions handle all storage interactions: - - - Computing storage addresses - - Reading from storage - - Writing to storage - - Managing storage layout - - -- Gas Management - ```cairo - libfunc withdraw_gas = withdraw_gas; - libfunc withdraw_gas_all = withdraw_gas_all; - libfunc get_builtin_costs = get_builtin_costs; - ``` - #### Purpose: - These functions handle all aspects of gas accounting: - - - Track gas consumption - - Withdraw gas for operations - - Calculate operation costs - - Prevent out-of-gas scenarios - -### 3. Execution Flow Analysis - -- Initialization and Gas Management Phase -This phase marks the beginning of contract execution where Sierra prepares the execution environment and handles initial gas costs. First, it disables the allocation pointer tracking, which is a safety measure to prevent memory tracking overhead during gas calculations. Then, it performs a critical gas withdrawal check - this ensures the contract has sufficient gas to execute, with fallback paths for both successful and failed gas checks. After gas validation, it aligns the execution branch for consistent memory layout and finally deconstructs the input parameters into their base components for further processing. -The phase is crucial for: - - - Setting up memory safety mechanisms - - Ensuring gas availability - - Preparing input parameters - - Establishing execution paths - ```cairo - // The actual code implementation - revoke_ap_tracking() -> (); // 0 - withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; // 1 - branch_align() -> (); // 2 - struct_deconstruct>([3]) -> ([8]); // 3 - ``` - -- Parameter Processing Phase -In this phase, Sierra handles the processing and validation of input parameters. It reactivates the allocation pointer tracking, which was disabled during gas calculations, to ensure memory safety during parameter processing. The range check pointer is stored for numeric validations, crucial for ensuring values are within acceptable ranges. The system then processes array inputs through snapshots - a mechanism that provides safe, immutable views of array data. Finally, it handles option types, which are essential for representing potentially null or invalid values. This phase is fundamental for type safety and memory integrity. +## Simple Sierra Program Breakdown + +Let's go through the following Cairo program: ```cairo -enable_ap_tracking() -> (); // 4 -store_temp([4]) -> ([4]); // 5 -array_snapshot_pop_front([8]) { fallthrough([9], [10]) 12([11]) }; // 6 -enum_init>, 0>([10]) -> ([12]); // 8 +// [!include ~/listings/advanced-concepts/sierra_ir/src/simple_program.cairo] ``` -- Storage Operation Phase -The storage operation phase is where Sierra manages contract storage interactions. It begins by computing the storage base address - a unique identifier for the storage variable. This address is derived from contract-specific constants and variable positions. The system then converts this base address into a concrete storage address that can be used for actual storage operations. During write operations, the system includes multiple checks and fallback paths to handle potential failures, ensuring storage consistency even in error cases. +It compiles to the following Sierra code: ```cairo -storage_base_address_const<...>() -> ([38]); // 50 -storage_address_from_base([38]) -> ([40]); // 52 -storage_write_syscall([35], [2], [41], [40], [39]) { - fallthrough([42], [43]) 70([44], [45], [46]) -}; // 57 +// [!include ~/listings/advanced-concepts/sierra_ir/simple_program.sierra] ``` -- Value Processing Phase -During value processing, Sierra handles type conversions and validations of data. This phase is critical for ensuring type safety and data integrity. The system attempts to convert between different numeric types (like felt252 to u32) with built-in overflow checks. Temporary storage is used to maintain values during processing, with careful management of memory resources. Each conversion includes fallback paths for handling potential failures. - -```cairo -u32_try_from_felt252([4], [20]) { fallthrough([21], [22]) 93([23]) }; // 22 -store_temp([20]) -> ([20]); // 21 +:::info +To enable Sierra code generation in human-readable format, you can add the `sierra-text{:md}` flag to the library target in your `Scarb.toml{:md}` file: +```toml +[lib] +sierra-text = true ``` +::: -- Error Handling Phase -The error handling phase implements Sierra's robust error management system. It constructs panic results for error cases, ensuring that failures are handled gracefully and securely. The system creates structured error information including panic details and relevant error data. This phase is crucial for maintaining contract reliability and providing meaningful error feedback. All error states are carefully packaged into result types that can be safely returned and handled by the calling context. +We can break it down: -```cairo -struct_construct() -> ([30]); // 35 -struct_construct>>([30], [29]) -> ([31]); // 36 -enum_init,)>, 1>([31]) -> ([32]); // 37 -``` +Type Declarations: + - `felt252`: Represents the field element type -- Return Phase -The return phase is responsible for finalizing the execution and preparing the return values. It ensures all resources are properly accounted for by storing final values for range checking, gas tracking, and system state. The phase carefully packages all return values, maintaining type safety and memory integrity. This phase is critical for ensuring the contract's state is consistent after execution. +Libfunc Declarations: + - `felt252_add`: Performs addition on field elements + - `store_temp`: Temporarily stores the result -```cairo -store_temp([21]) -> ([21]); // 38 -store_temp([5]) -> ([5]); // 39 -store_temp([2]) -> ([2]); // 40 -return([21], [5], [2], [32]); // 42 -``` +Compilation Steps: + - Step 0: `felt252_add([0], [1]) -> ([2])`: Call the `felt252_add` libfunc on memory slot 0 and 1 and store the result in memory slot 2. So `[2] = [0] + [1]` and the value of `[0]` and `[1]` were used. + - Step 1: `store_temp([2]) -> ([2])`: Store the value of `[2]` in a temporary memory slot `[2]`. Because the type `felt252` has `storable: true` and `dup: true`, it is possible to + - Step 2: `return([2])`: Return the value of `[2]` -- Storage Read Flow -The storage read operation is a specialized flow that handles retrieving values from contract storage. It begins with a storage address computation, followed by a syscall to read the storage value. The read value is then processed and converted to the appropriate type with necessary validations. This operation includes comprehensive error handling for cases like invalid storage addresses or type conversion failures. +4. Libfunc Restrictions: -```cairo -storage_read_syscall([20], [2], [30], [29]) { - fallthrough([31], [32], [33]) 196([34], [35], [36]) -}; // 166 -store_temp([33]) -> ([33]); // 168 -u32_try_from_felt252([19], [33]); // 171 -``` +- Starknet uses an allowed [list](https://github.com/starkware-libs/cairo/tree/main/crates/cairo-lang-starknet-classes/src/allowed_libfuncs_lists) of libfuncs to ensure: + - Security: + Sierra enforces security by allowing only whitelisted operations with predefined behaviors, while maintaining strict control over memory operations and eliminating arbitrary pointer arithmetic to prevent vulnerabilities. + - Predictability: + The restricted libfunc approach ensures deterministic execution across all operations, enabling precise gas cost calculations and well-defined state transitions, while keeping all side effects explicitly managed and traceable. + - Verifiability: + By limiting library functions, Sierra simplifies the proof generation process and makes constraint system generation more efficient, which reduces verification complexity and ensures consistent behavior across different implementations. + - Error Prevention + The restricted library functions eliminate undefined behavior by catching potential runtime errors at compile time, while enforcing explicit resource management and maintaining type safety throughout the entire execution process. -- Storage Write Flow -The storage write operation manages a secure and atomic process for updating contract state in Sierra. It begins with precise gas calculations and withdrawals to ensure sufficient resources for the complete operation. The system then computes a unique storage address through a two-step process: generating a base address from contract-specific constants and transforming it into a concrete storage location. Finally, it executes the atomic write operation through a system call, with comprehensive error handling to maintain storage integrity. The entire process ensures consistent state updates, prevents data corruption, and handles failures gracefully. - - ```cairo - withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; - - storage_base_address_const<...>() -> ([38]); - storage_address_from_base([38]) -> ([40]); - - storage_write_syscall([35], [2], [41], [40], [39]); - ``` - -### 4. Function Implementation Analysis -- Set Function Implementation - ```cairo - // Function wrapper - storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__set@0( - [0]: RangeCheck, // For numeric checks - [1]: GasBuiltin, // For gas tracking - [2]: System, // For system calls - [3]: core::array::Span:: // Input parameters - ) - ``` - Key Operations: - 1. `Gas` withdrawal and checks - 2. `Parameter` validation - 3. `Storage` address computation - 4. `Value` writing to storage - 5. `Return` handling with panic checks - -- Get Function Implementation - storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__get@128( - // Similar parameters as set - ) - - Key Operations: - 1. `Gas` checks - 2. `Storage` address computation - 3. `Value` reading from storage - 4. `Type` conversion and validation - 5. `Result` packaging and return +The restricted libfunc approach helps maintain the safety and efficiency of smart contracts on the Starknet platform. + +### Storage Variables Smart Contract Sierra Code + +You can find a more complex example of the [compiled Sierra code](/advanced-concepts/sierra_ir_storage_contract) of the [Storage Variables Example](/getting-started/basics/variables#storage-variables). ## Further Reading @@ -312,4 +151,3 @@ The storage write operation manages a secure and atomic process for updating con - [Cairo and Sierra](https://docs.starknet.io/architecture-and-concepts/smart-contracts/cairo-and-sierra/) - [Sierra - Deep Dive](https://www.starknet.io/blog/sierra-deep-dive-video/) - diff --git a/pages/advanced-concepts/sierra_ir_storage_contract.md b/pages/advanced-concepts/sierra_ir_storage_contract.md new file mode 100644 index 00000000..b73a43fd --- /dev/null +++ b/pages/advanced-concepts/sierra_ir_storage_contract.md @@ -0,0 +1,3 @@ +```cairo +// [!include ~/listings/getting-started/variables/storage_variables.sierra] +``` \ No newline at end of file diff --git a/routes.ts b/routes.ts index 0faacdaf..4b71caf0 100644 --- a/routes.ts +++ b/routes.ts @@ -224,6 +224,10 @@ const config: Sidebar = [ text: "Signature Verification", link: "/advanced-concepts/signature_verification", }, + { + text: "Sierra IR", + link: "/advanced-concepts/sierra_ir", + } ], }, { From c6b562aa17e35f02c8cef3ea0feeb63f5e6c4ec2 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:56:54 +0100 Subject: [PATCH 11/13] feat: sierra explanations --- .../advanced-concepts/sierra_ir/src/lib.cairo | 2 +- pages/advanced-concepts/sierra_ir.md | 104 +++-- pnpm-lock.yaml | 425 +++++++++--------- 3 files changed, 271 insertions(+), 260 deletions(-) diff --git a/listings/advanced-concepts/sierra_ir/src/lib.cairo b/listings/advanced-concepts/sierra_ir/src/lib.cairo index 981e6956..6d68b7fd 100644 --- a/listings/advanced-concepts/sierra_ir/src/lib.cairo +++ b/listings/advanced-concepts/sierra_ir/src/lib.cairo @@ -1 +1 @@ -mod simple_program; \ No newline at end of file +mod simple_program; diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md index 4f69a315..75cc2f78 100644 --- a/pages/advanced-concepts/sierra_ir.md +++ b/pages/advanced-concepts/sierra_ir.md @@ -1,14 +1,17 @@ # Understanding Sierra: From High-Level Cairo to Safe CASM -Sierra (**S**afe **I**nt**er**mediate **R**epresent**a**tion) is an intermediate representation of Cairo instructions, designed to bridge the gap between high-level Cairo 1 and low-level Cairo Assembly (CASM). -Sierra can be compiled to a subset of CASM that we call `Safe CASM{:md}`. It ensures that every function returns by using a compiler that can detect operations that can't be proven such as infinite loops, unsatisfiable constraints, etc. +Sierra (**S**afe **I**nt**er**mediate **R**epresent**a**tion) is a linear intermediate representation of Cairo instructions, designed to bridge the gap between high-level Cairo 1 and low-level Cairo Assembly (CASM). +Sierra can be compiled to a subset of CASM, known as `Safe CASM{:md}`. + +Sierra ensures that programs are always **provable** by preventing the compilation of programs with infinite loops or invalid constraints. ### From Cairo 1 to Sierra -Before Starknet Alpha v0.11.0, developers wrote contracts in Cairo 0 which compiled directly to Cairo Assembly (CASM), and the contract classes were submitted to the sequencer with `DECLARE` transactions. This approach had risks as the sequencer would not be able to know if a given transaction would fail or not without executing it, and would not be able to charge fees for failed transactions. +Before Starknet Alpha v0.11.0, developers wrote contracts in Cairo 0, which compiled directly to Cairo Assembly (CASM), and contract classes were submitted to the sequencer via `DECLARE` transactions. +This approach had risks, as the sequencer could not determine whether a given transaction would fail without executing it, and therefore could not charge fees for failed transactions. -Cairo 1 introduced contract class compilation to this new Sierra intermediate representation instead of directly to CASM. The Sierra code is then submitted to the sequencer, compiled down to CASM, and finally executed by the Starknet OS. -The usage of Sierra ensures that every transactions (including failed ones) must be provable, and the sequencers can charge fees for all submitted transactions making DoS attacks really expensive. +Cairo 1 introduced contract class compilation to this new Sierra intermediate representation instead of directly compiling to CASM. The Sierra code is then submitted to the sequencer, compiled down to CASM, and finally executed by the Starknet OS. +Using Sierra ensures that all transactions (including failed ones) are provable, and allows sequencers to charge fees for all submitted transactions, making DoS attacks significantly more expensive. ### Compilation Pipeline @@ -28,49 +31,66 @@ The usage of Sierra ensures that every transactions (including failed ones) must STARK Proofs (Proof Generation) ``` -At its core, Sierra's compilation process is all about safety and efficiency. It carefully checks types at every step of the transformation, makes sure memory is handled safely in the final code, and keeps track of gas usage. The compiler also focuses on generating optimized code while ensuring that every operation will run the same way each time. +At its core, Sierra's compilation process is focused on safety and efficiency. +Cairo 1 uses a linear type system and a non-deterministic, immutable, contiguous memory model, which guarantees that dereferencing never fails. + +Sierra transforms loops into recursion and keeps track of gas usage, which prevents infinite loops. + +:::note If you're interested in really understanding how the compilation works under the hood, check out the [cairo-compiler-workshop](https://github.com/software-mansion-labs/cairo-compiler-workshop). +::: ### Anatomy of a Sierra Program ### Type Declarations -Sierra uses a **linear type system**, where each value **must be used exactly once**. -During the compilation, an unique identifier is assigned to each type. +Sierra, as a Cairo representation, also uses a **linear type system**, where each value **must be used exactly once**. +During the compilation, a unique identifier is assigned to each type. When types can safely be used multiple times, they need to be duplicated using the `dup` instruction, which will assign two new identifiers to preserve linearity. Type declaration is done with the following syntax: + ```cairo type type_id = concrete_type; ``` - + +::: ### Library Function Declarations -Sierra comes with a set of built-in functions (`libfuncs`) that always compile to Safe CASM. After types declaration, a Sierra program must define all the libfuncs used in the program with the inpt type expected. +Sierra comes with a set of built-in functions (`libfuncs`) that represent the call to low-level units of code known to be safe. After type declarations, a Sierra program must define all the libfuncs used in the program along with their expected input types. Libfunc declaration is done with the following syntax: + ```cairo libfunc libfunc_id = libfunc_name; ``` +:::note +While this section is generic, Starknet uses an allowed [list](https://github.com/starkware-libs/cairo/tree/main/crates/cairo-lang-starknet-classes/src/allowed_libfuncs_lists) of libfuncs. +::: + ### Statements -This part shows the sequence of operations that happen during execution, which describes the actual logic of the program. A statement either invokes a libfunc or returns a value. +This section shows the sequence of operations that occur during execution, describing the actual logic of the program. A statement either invokes a libfunc or returns a value. + +Statements are declared with the following syntax: -A statement is declared with the following syntax: ```cairo libfunc_id(input_variables) -> (output_variables); ``` @@ -79,9 +99,10 @@ To return a value, we use the `return(variable_id)` statement. ### User Defined Functions Declarations -At the very end of the Sierra program, each user defined function is declared with an unique identifier and an index to specify the location of the statement where the execution of the function should start. +At the end of a Sierra program, each user-defined function is declared with a unique identifier and the statement index where the function starts. This provides information about the function, such as its signature, while the implementation is defined in the statements section. An user defined function is declared with the following syntax: + ```cairo function_id@statement_index(parameters: types) -> (return_types); ``` @@ -100,41 +121,34 @@ It compiles to the following Sierra code: // [!include ~/listings/advanced-concepts/sierra_ir/simple_program.sierra] ``` -:::info -To enable Sierra code generation in human-readable format, you can add the `sierra-text{:md}` flag to the library target in your `Scarb.toml{:md}` file: -```toml -[lib] -sierra-text = true -``` -::: - -We can break it down: - Type Declarations: - - `felt252`: Represents the field element type + +- `felt252`: Represents the field element type Libfunc Declarations: - - `felt252_add`: Performs addition on field elements - - `store_temp`: Temporarily stores the result -Compilation Steps: - - Step 0: `felt252_add([0], [1]) -> ([2])`: Call the `felt252_add` libfunc on memory slot 0 and 1 and store the result in memory slot 2. So `[2] = [0] + [1]` and the value of `[0]` and `[1]` were used. - - Step 1: `store_temp([2]) -> ([2])`: Store the value of `[2]` in a temporary memory slot `[2]`. Because the type `felt252` has `storable: true` and `dup: true`, it is possible to - - Step 2: `return([2])`: Return the value of `[2]` +- `felt252_add`: Performs addition on field elements +- `store_temp`: Temporarily stores the result + +Statements Section: + +- Statement 0: calls the `felt252_add` libfunc to add the values from memory cells 0 and 1, storing the result in memory cell 2 +- Statement 1: calls the `store_temp` libfunc to prepare the result for the return statement +- Statement 2: returns the value from memory cell 2 -4. Libfunc Restrictions: +User Defined Functions: -- Starknet uses an allowed [list](https://github.com/starkware-libs/cairo/tree/main/crates/cairo-lang-starknet-classes/src/allowed_libfuncs_lists) of libfuncs to ensure: - - Security: - Sierra enforces security by allowing only whitelisted operations with predefined behaviors, while maintaining strict control over memory operations and eliminating arbitrary pointer arithmetic to prevent vulnerabilities. - - Predictability: - The restricted libfunc approach ensures deterministic execution across all operations, enabling precise gas cost calculations and well-defined state transitions, while keeping all side effects explicitly managed and traceable. - - Verifiability: - By limiting library functions, Sierra simplifies the proof generation process and makes constraint system generation more efficient, which reduces verification complexity and ensures consistent behavior across different implementations. - - Error Prevention - The restricted library functions eliminate undefined behavior by catching potential runtime errors at compile time, while enforcing explicit resource management and maintaining type safety throughout the entire execution process. +- `add_numbers`: Takes two `felt252` types in memory cells 0 and 1 and returns a `felt252` value by starting at statement 0 -The restricted libfunc approach helps maintain the safety and efficiency of smart contracts on the Starknet platform. +:::info +To enable Sierra code generation in a human-readable format, add the `sierra-text` flag to the library target in your `Scarb.toml{:md}` file: + +```toml +[lib] +sierra-text = true +``` + +::: ### Storage Variables Smart Contract Sierra Code @@ -151,3 +165,5 @@ You can find a more complex example of the [compiled Sierra code](/advanced-conc - [Cairo and Sierra](https://docs.starknet.io/architecture-and-concepts/smart-contracts/cairo-and-sierra/) - [Sierra - Deep Dive](https://www.starknet.io/blog/sierra-deep-dive-video/) + +- [Cairo and MLIR](https://blog.lambdaclass.com/cairo-and-mlir/) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cce0bde..06575621 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,7 +23,7 @@ importers: dependencies: '@types/react': specifier: latest - version: 19.0.8 + version: 19.0.9 react: specifier: ^19.0.0 version: 19.0.0 @@ -41,11 +41,11 @@ importers: version: 5.7.3 vocs: specifier: 1.0.0-alpha.62 - version: 1.0.0-alpha.62(patch_hash=472ea4771ea28176fd7a35b8f83fe164ce160c07b9b50111ae749eb8da92176d)(@types/node@22.13.1)(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(acorn@8.14.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.6)(typescript@5.7.3) + version: 1.0.0-alpha.62(patch_hash=472ea4771ea28176fd7a35b8f83fe164ce160c07b9b50111ae749eb8da92176d)(@types/node@22.13.1)(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(acorn@8.14.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.6)(typescript@5.7.3) devDependencies: '@types/react-dom': specifier: ^18.3.1 - version: 18.3.5(@types/react@19.0.8) + version: 18.3.5(@types/react@19.0.9) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.5.1) @@ -1059,8 +1059,8 @@ packages: peerDependencies: '@types/react': ^18.0.0 - '@types/react@19.0.8': - resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} + '@types/react@19.0.9': + resolution: {integrity: sha512-FedNTYgmMwSZmD1Sru/W1gJKuiYCN/3SuBkmZkcxX+FpO5zL76B22A9YNfAKg4HQO3Neh/30AiynP6BELdU0qQ==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1384,9 +1384,6 @@ packages: emoji-regex-xs@1.0.0: resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} - emoji-regex-xs@1.0.0: - resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} - emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -3061,10 +3058,10 @@ snapshots: - acorn - supports-color - '@mdx-js/react@3.1.0(@types/react@19.0.8)(react@19.0.0)': + '@mdx-js/react@3.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: '@types/mdx': 2.0.13 - '@types/react': 19.0.8 + '@types/react': 19.0.9 react: 19.0.0 '@mdx-js/rollup@3.1.0(acorn@8.14.0)(rollup@4.34.6)': @@ -3099,336 +3096,336 @@ snapshots: '@radix-ui/primitive@1.1.1': {} - '@radix-ui/react-accordion@1.2.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-accordion@1.2.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-collapsible@1.1.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-collapsible@1.1.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-context@1.1.1(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-context@1.1.1(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) aria-hidden: 1.2.4 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-direction@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-direction@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) '@radix-ui/react-icons@1.3.2(react@19.0.0)': dependencies: react: 19.0.0 - '@radix-ui/react-id@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-id@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-navigation-menu@1.2.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-navigation-menu@1.2.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-popover@1.1.6(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-popover@1.1.6(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) aria-hidden: 1.2.4 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-popper@1.2.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-popper@1.2.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.9)(react@19.0.0) '@radix-ui/rect': 1.1.0 react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-slot': 1.1.2(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-slot@1.1.2(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-slot@1.1.2(@types/react@19.0.9)(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-previous@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-previous@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: '@radix-ui/rect': 1.1.0 react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-use-size@1.1.0(@types/react@19.0.8)(react@19.0.0)': + '@radix-ui/react-use-size@1.1.0(@types/react@19.0.9)(react@19.0.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0) react: 19.0.0 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 - '@types/react-dom': 18.3.5(@types/react@19.0.8) + '@types/react': 19.0.9 + '@types/react-dom': 18.3.5(@types/react@19.0.9) '@radix-ui/rect@1.1.0': {} @@ -3603,11 +3600,11 @@ snapshots: dependencies: undici-types: 6.20.0 - '@types/react-dom@18.3.5(@types/react@19.0.8)': + '@types/react-dom@18.3.5(@types/react@19.0.9)': dependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - '@types/react@19.0.8': + '@types/react@19.0.9': dependencies: csstype: 3.1.3 @@ -3940,8 +3937,6 @@ snapshots: emoji-regex-xs@1.0.0: {} - emoji-regex-xs@1.0.0: {} - emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -5182,24 +5177,24 @@ snapshots: react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.8(@types/react@19.0.8)(react@19.0.0): + react-remove-scroll-bar@2.3.8(@types/react@19.0.9)(react@19.0.0): dependencies: react: 19.0.0 - react-style-singleton: 2.2.3(@types/react@19.0.8)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.9)(react@19.0.0) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - react-remove-scroll@2.6.3(@types/react@19.0.8)(react@19.0.0): + react-remove-scroll@2.6.3(@types/react@19.0.9)(react@19.0.0): dependencies: react: 19.0.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.0.8)(react@19.0.0) - react-style-singleton: 2.2.3(@types/react@19.0.8)(react@19.0.0) + react-remove-scroll-bar: 2.3.8(@types/react@19.0.9)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.9)(react@19.0.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.0.8)(react@19.0.0) - use-sidecar: 1.1.3(@types/react@19.0.8)(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.0.9)(react@19.0.0) + use-sidecar: 1.1.3(@types/react@19.0.9)(react@19.0.0) optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 react-router-dom@6.29.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: @@ -5217,13 +5212,13 @@ snapshots: dependencies: react: 19.0.0 - react-style-singleton@2.2.3(@types/react@19.0.8)(react@19.0.0): + react-style-singleton@2.2.3(@types/react@19.0.9)(react@19.0.0): dependencies: get-nonce: 1.0.1 react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 react@19.0.0: {} @@ -5709,20 +5704,20 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - use-callback-ref@1.3.3(@types/react@19.0.8)(react@19.0.0): + use-callback-ref@1.3.3(@types/react@19.0.9)(react@19.0.0): dependencies: react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 - use-sidecar@1.1.3(@types/react@19.0.8)(react@19.0.0): + use-sidecar@1.1.3(@types/react@19.0.9)(react@19.0.0): dependencies: detect-node-es: 1.1.0 react: 19.0.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.0.8 + '@types/react': 19.0.9 util-deprecate@1.0.2: {} @@ -5782,21 +5777,21 @@ snapshots: '@types/node': 22.13.1 fsevents: 2.3.3 - vocs@1.0.0-alpha.62(patch_hash=472ea4771ea28176fd7a35b8f83fe164ce160c07b9b50111ae749eb8da92176d)(@types/node@22.13.1)(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(acorn@8.14.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.6)(typescript@5.7.3): + vocs@1.0.0-alpha.62(patch_hash=472ea4771ea28176fd7a35b8f83fe164ce160c07b9b50111ae749eb8da92176d)(@types/node@22.13.1)(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(acorn@8.14.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.6)(typescript@5.7.3): dependencies: '@floating-ui/react': 0.26.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@hono/node-server': 1.13.8(hono@3.12.12) - '@mdx-js/react': 3.1.0(@types/react@19.0.8)(react@19.0.0) + '@mdx-js/react': 3.1.0(@types/react@19.0.9)(react@19.0.0) '@mdx-js/rollup': 3.1.0(acorn@8.14.0)(rollup@4.34.6) '@noble/hashes': 1.7.1 '@radix-ui/colors': 3.0.0 - '@radix-ui/react-accordion': 1.2.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-accordion': 1.2.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-icons': 1.3.2(react@19.0.0) - '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-navigation-menu': 1.2.5(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-popover': 1.1.6(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) - '@radix-ui/react-tabs': 1.1.3(@types/react-dom@18.3.5(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-navigation-menu': 1.2.5(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-popover': 1.1.6(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-tabs': 1.1.3(@types/react-dom@18.3.5(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@shikijs/rehype': 1.23.1 '@shikijs/transformers': 1.23.1 '@shikijs/twoslash': 1.23.1(typescript@5.7.3) From a55fb24782c3d9ade05e11c46250d1c889319636 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:58:08 +0100 Subject: [PATCH 12/13] fix: remove duplicate part --- CONTRIBUTING.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7a570db3..40f4b0ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,12 +10,6 @@ You should never open a pull request to merge your changes directly into `main`. The `dev` branch is deployed at -The release branch is `main`. The development branch is `dev` and is considered stable (but not released yet). -When you want to contribute, please create a new branch from `dev` and open a pull request to merge your changes back into `dev`. -You should never open a pull request to merge your changes directly into `main`. - -The `dev` branch is deployed at https://starknet-by-example-dev.voyager.online/ - Please note we have a code of conduct, please follow it in all your interactions with the project. ## Table of Contents From d1a5c5152050c95aa327073f84a150005a8469d7 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:09:36 +0100 Subject: [PATCH 13/13] fix: typos --- pages/advanced-concepts/sierra_ir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/advanced-concepts/sierra_ir.md b/pages/advanced-concepts/sierra_ir.md index 75cc2f78..737beafb 100644 --- a/pages/advanced-concepts/sierra_ir.md +++ b/pages/advanced-concepts/sierra_ir.md @@ -1,6 +1,6 @@ # Understanding Sierra: From High-Level Cairo to Safe CASM -Sierra (**S**afe **I**nt**er**mediate **R**epresent**a**tion) is a linear intermediate representation of Cairo instructions, designed to bridge the gap between high-level Cairo 1 and low-level Cairo Assembly (CASM). +Sierra (Safe Intermediate REpresentAtion) is a linear intermediate representation of Cairo instructions, designed to bridge the gap between high-level Cairo 1 intermdiate and low-level Cairo Assembly (CASM). Sierra can be compiled to a subset of CASM, known as `Safe CASM{:md}`. Sierra ensures that programs are always **provable** by preventing the compilation of programs with infinite loops or invalid constraints.