|
| 1 | +# Understanding Sierra: From High-Level Cairo to Safe CASM |
| 2 | + |
| 3 | +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). |
| 4 | +Sierra can be compiled to a subset of CASM, known as `Safe CASM{:md}`. |
| 5 | + |
| 6 | +Sierra ensures that programs are always **provable** by preventing the compilation of programs with infinite loops or invalid constraints. |
| 7 | + |
| 8 | +### From Cairo 1 to Sierra |
| 9 | + |
| 10 | +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. |
| 11 | +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. |
| 12 | + |
| 13 | +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. |
| 14 | +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. |
| 15 | + |
| 16 | +### Compilation Pipeline |
| 17 | + |
| 18 | +``` |
| 19 | + Cairo 1.0 Source (High-level) |
| 20 | + | |
| 21 | + | with Cairo-to-Sierra Compiler |
| 22 | + V |
| 23 | + Sierra IR (Safe, Provable Code) |
| 24 | + | |
| 25 | + | with Sierra-to-CASM Compiler (Run by Sequencer) |
| 26 | + V |
| 27 | + CASM (Cairo Assembly) |
| 28 | + | |
| 29 | + | with CairoVM Execution |
| 30 | + V |
| 31 | + STARK Proofs (Proof Generation) |
| 32 | +``` |
| 33 | + |
| 34 | +At its core, Sierra's compilation process is focused on safety and efficiency. |
| 35 | +Cairo 1 uses a linear type system and a non-deterministic, immutable, contiguous memory model, which guarantees that dereferencing never fails. |
| 36 | + |
| 37 | +Sierra transforms loops into recursion and keeps track of gas usage, which prevents infinite loops. |
| 38 | + |
| 39 | +:::note |
| 40 | +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). |
| 41 | +::: |
| 42 | + |
| 43 | +### Anatomy of a Sierra Program |
| 44 | + |
| 45 | +### Type Declarations |
| 46 | + |
| 47 | +Sierra, as a Cairo representation, also uses a **linear type system**, where each value **must be used exactly once**. |
| 48 | +During the compilation, a unique identifier is assigned to each type. |
| 49 | + |
| 50 | +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. |
| 51 | + |
| 52 | +Type declaration is done with the following syntax: |
| 53 | + |
| 54 | +```cairo |
| 55 | +type type_id = concrete_type; |
| 56 | +``` |
| 57 | + |
| 58 | +:::info |
| 59 | +In addition, each type has a set of attributes that describe how it can be used: |
| 60 | + |
| 61 | +- storable |
| 62 | +- droppable |
| 63 | +- duplicatable |
| 64 | +- zero_sized |
| 65 | + |
| 66 | +They are added in the type declaration: |
| 67 | + |
| 68 | +```cairo |
| 69 | +type type_id = concrete_type [storable: bool, drop: bool, dup: bool, zero_sized: bool] |
| 70 | +``` |
| 71 | + |
| 72 | +::: |
| 73 | + |
| 74 | +### Library Function Declarations |
| 75 | + |
| 76 | +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. |
| 77 | + |
| 78 | +Libfunc declaration is done with the following syntax: |
| 79 | + |
| 80 | +```cairo |
| 81 | +libfunc libfunc_id = libfunc_name<input_types>; |
| 82 | +``` |
| 83 | + |
| 84 | +:::note |
| 85 | +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. |
| 86 | +::: |
| 87 | + |
| 88 | +### Statements |
| 89 | + |
| 90 | +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. |
| 91 | + |
| 92 | +Statements are declared with the following syntax: |
| 93 | + |
| 94 | +```cairo |
| 95 | +libfunc_id<input_types>(input_variables) -> (output_variables); |
| 96 | +``` |
| 97 | + |
| 98 | +To return a value, we use the `return(variable_id)` statement. |
| 99 | + |
| 100 | +### User Defined Functions Declarations |
| 101 | + |
| 102 | +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. |
| 103 | + |
| 104 | +An user defined function is declared with the following syntax: |
| 105 | + |
| 106 | +```cairo |
| 107 | +function_id@statement_index(parameters: types) -> (return_types); |
| 108 | +``` |
| 109 | + |
| 110 | +## Simple Sierra Program Breakdown |
| 111 | + |
| 112 | +Let's go through the following Cairo program: |
| 113 | + |
| 114 | +```cairo |
| 115 | +// [!include ~/listings/advanced-concepts/sierra_ir/src/simple_program.cairo] |
| 116 | +``` |
| 117 | + |
| 118 | +It compiles to the following Sierra code: |
| 119 | + |
| 120 | +```cairo |
| 121 | +// [!include ~/listings/advanced-concepts/sierra_ir/simple_program.sierra] |
| 122 | +``` |
| 123 | + |
| 124 | +Type Declarations: |
| 125 | + |
| 126 | +- `felt252`: Represents the field element type |
| 127 | + |
| 128 | +Libfunc Declarations: |
| 129 | + |
| 130 | +- `felt252_add`: Performs addition on field elements |
| 131 | +- `store_temp<felt252>`: Temporarily stores the result |
| 132 | + |
| 133 | +Statements Section: |
| 134 | + |
| 135 | +- Statement 0: calls the `felt252_add` libfunc to add the values from memory cells 0 and 1, storing the result in memory cell 2 |
| 136 | +- Statement 1: calls the `store_temp<felt252>` libfunc to prepare the result for the return statement |
| 137 | +- Statement 2: returns the value from memory cell 2 |
| 138 | + |
| 139 | +User Defined Functions: |
| 140 | + |
| 141 | +- `add_numbers`: Takes two `felt252` types in memory cells 0 and 1 and returns a `felt252` value by starting at statement 0 |
| 142 | + |
| 143 | +:::info |
| 144 | +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: |
| 145 | + |
| 146 | +```toml |
| 147 | +[lib] |
| 148 | +sierra-text = true |
| 149 | +``` |
| 150 | + |
| 151 | +::: |
| 152 | + |
| 153 | +### Storage Variables Smart Contract Sierra Code |
| 154 | + |
| 155 | +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). |
| 156 | + |
| 157 | +## Further Reading |
| 158 | + |
| 159 | +- [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) |
| 160 | + |
| 161 | +- [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) |
| 162 | + |
| 163 | +- [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) |
| 164 | + |
| 165 | +- [Cairo and Sierra](https://docs.starknet.io/architecture-and-concepts/smart-contracts/cairo-and-sierra/) |
| 166 | + |
| 167 | +- [Sierra - Deep Dive](https://www.starknet.io/blog/sierra-deep-dive-video/) |
| 168 | + |
| 169 | +- [Cairo and MLIR](https://blog.lambdaclass.com/cairo-and-mlir/) |
0 commit comments