-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: sierra explanation #264
base: dev
Are you sure you want to change the base?
Conversation
i just figured i have to add all cairo contract in listing. I need some more time to migrate all the functions in the sierra_ir.md to the appropriate listing and this would be ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The introduction is mostly good and explains why we need Sierra.
But you focused too much on the compilation process from Cairo to Sierra.
I would like to have a simpler example of compiling simple cairo/ a simple contract to sierra and directly explaining the Sierra. Explains the different parts type declarations/libfuncs declarations/statements/funcs. Why Starknet have an allowed list of libfuncs and not all libfuncs can be used in smart contracts (here).
You can start with your example:
fn add_numbers(a: felt252, b: felt252) -> felt252 {
let sum = a + b;
sum
}
and explain the sierra obtained:
type felt252 = felt252 [storable: true, drop: true, dup: true, zero_sized: false];
libfunc felt252_add = felt252_add;
libfunc store_temp<felt252> = store_temp<felt252>;
felt252_add([0], [1]) -> ([2]); // 0
store_temp<felt252>([2]) -> ([2]); // 1
return([2]); // 2
simple::simple::add_numbers@0([0]: felt252, [1]: felt252) -> (felt252);
Then move on smart contract with a simple example, such as storage variable:
type RangeCheck = RangeCheck [storable: true, drop: false, dup: false, zero_sized: false];
type Const<felt252, 7269940625183576940180048306939577043858226> = Const<felt252, 7269940625183576940180048306939577043858226> [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::<core::integer::u32> = Struct<ut@[898445955114587763707845576501117863064615340801773273203592885525648859513], StorageBaseAddress> [storable: true, drop: true, dup: true, zero_sized: false];
type Const<felt252, 485748461484230571791265682659113160264223489397539653310998840191492913> = Const<felt252, 485748461484230571791265682659113160264223489397539653310998840191492913> [storable: false, drop: false, dup: false, zero_sized: false];
type Const<felt252, 375233589013918064796019> = Const<felt252, 375233589013918064796019> [storable: false, drop: false, dup: false, zero_sized: false];
type Array<felt252> = Array<felt252> [storable: true, drop: true, dup: false, zero_sized: false];
type Snapshot<Array<felt252>> = Snapshot<Array<felt252>> [storable: true, drop: true, dup: true, zero_sized: false];
type core::array::Span::<core::felt252> = Struct<ut@[782572820229152792105145177694740816763001980856532159945905090893343825762], Snapshot<Array<felt252>>> [storable: true, drop: true, dup: true, zero_sized: false];
type Tuple<core::array::Span::<core::felt252>> = Struct<ut@[1325343513152088812341467750635149026053683136611136091911357178651207272643], core::array::Span::<core::felt252>> [storable: true, drop: true, dup: true, zero_sized: false];
type Const<u32, 0> = Const<u32, 0> [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<ut@[640126984585624630990013944782631102820301644699864366139839615702772668018]> [storable: true, drop: true, dup: true, zero_sized: true];
type Tuple<core::panics::Panic, Array<felt252>> = Struct<ut@[1325343513152088812341467750635149026053683136611136091911357178651207272643], core::panics::Panic, Array<felt252>> [storable: true, drop: true, dup: false, zero_sized: false];
type core::panics::PanicResult::<(core::array::Span::<core::felt252>,)> = Enum<ut@[270671131472959732993844072583327084608513343873724697777364695367457417702], Tuple<core::array::Span::<core::felt252>>, Tuple<core::panics::Panic, Array<felt252>>> [storable: true, drop: true, dup: false, zero_sized: false];
type Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595> = Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595> [storable: false, drop: false, dup: false, zero_sized: false];
type u32 = u32 [storable: true, drop: true, dup: true, zero_sized: false];
type Unit = Struct<ut@[1325343513152088812341467750635149026053683136611136091911357178651207272643]> [storable: true, drop: true, dup: true, zero_sized: true];
type Box<felt252> = Box<felt252> [storable: true, drop: true, dup: true, zero_sized: false];
type core::option::Option::<core::box::Box::<@core::felt252>> = Enum<ut@[1182885770396068416776258475038712898857052156962285097349975100489777991911], Box<felt252>, 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<core::array::Span::<core::felt252>> = struct_deconstruct<core::array::Span::<core::felt252>>;
libfunc enable_ap_tracking = enable_ap_tracking;
libfunc store_temp<RangeCheck> = store_temp<RangeCheck>;
libfunc array_snapshot_pop_front<felt252> = array_snapshot_pop_front<felt252>;
libfunc enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 0> = enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 0>;
libfunc store_temp<Snapshot<Array<felt252>>> = store_temp<Snapshot<Array<felt252>>>;
libfunc store_temp<core::option::Option::<core::box::Box::<@core::felt252>>> = store_temp<core::option::Option::<core::box::Box::<@core::felt252>>>;
libfunc jump = jump;
libfunc struct_construct<Unit> = struct_construct<Unit>;
libfunc enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 1> = enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 1>;
libfunc enum_match<core::option::Option::<core::box::Box::<@core::felt252>>> = enum_match<core::option::Option::<core::box::Box::<@core::felt252>>>;
libfunc unbox<felt252> = unbox<felt252>;
libfunc rename<felt252> = rename<felt252>;
libfunc store_temp<felt252> = store_temp<felt252>;
libfunc u32_try_from_felt252 = u32_try_from_felt252;
libfunc disable_ap_tracking = disable_ap_tracking;
libfunc drop<Snapshot<Array<felt252>>> = drop<Snapshot<Array<felt252>>>;
libfunc drop<Box<felt252>> = drop<Box<felt252>>;
libfunc drop<u32> = drop<u32>;
libfunc array_new<felt252> = array_new<felt252>;
libfunc const_as_immediate<Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595>> = const_as_immediate<Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595>>;
libfunc array_append<felt252> = array_append<felt252>;
libfunc struct_construct<core::panics::Panic> = struct_construct<core::panics::Panic>;
libfunc struct_construct<Tuple<core::panics::Panic, Array<felt252>>> = struct_construct<Tuple<core::panics::Panic, Array<felt252>>>;
libfunc enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1> = enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>;
libfunc store_temp<GasBuiltin> = store_temp<GasBuiltin>;
libfunc store_temp<System> = store_temp<System>;
libfunc store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>> = store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>;
libfunc get_builtin_costs = get_builtin_costs;
libfunc store_temp<BuiltinCosts> = store_temp<BuiltinCosts>;
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<u32, 0>> = const_as_immediate<Const<u32, 0>>;
libfunc store_temp<u32> = store_temp<u32>;
libfunc store_temp<StorageAddress> = store_temp<StorageAddress>;
libfunc storage_write_syscall = storage_write_syscall;
libfunc snapshot_take<Array<felt252>> = snapshot_take<Array<felt252>>;
libfunc drop<Array<felt252>> = drop<Array<felt252>>;
libfunc struct_construct<core::array::Span::<core::felt252>> = struct_construct<core::array::Span::<core::felt252>>;
libfunc struct_construct<Tuple<core::array::Span::<core::felt252>>> = struct_construct<Tuple<core::array::Span::<core::felt252>>>;
libfunc enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 0> = enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 0>;
libfunc const_as_immediate<Const<felt252, 375233589013918064796019>> = const_as_immediate<Const<felt252, 375233589013918064796019>>;
libfunc drop<Unit> = drop<Unit>;
libfunc const_as_immediate<Const<felt252, 485748461484230571791265682659113160264223489397539653310998840191492913>> = const_as_immediate<Const<felt252, 485748461484230571791265682659113160264223489397539653310998840191492913>>;
libfunc drop<core::array::Span::<core::felt252>> = drop<core::array::Span::<core::felt252>>;
libfunc struct_construct<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>> = struct_construct<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>;
libfunc snapshot_take<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>> = snapshot_take<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>;
libfunc drop<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>> = drop<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>;
libfunc struct_deconstruct<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>> = struct_deconstruct<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>;
libfunc rename<StorageBaseAddress> = rename<StorageBaseAddress>;
libfunc storage_read_syscall = storage_read_syscall;
libfunc const_as_immediate<Const<felt252, 7269940625183576940180048306939577043858226>> = const_as_immediate<Const<felt252, 7269940625183576940180048306939577043858226>>;
libfunc store_temp<Array<felt252>> = store_temp<Array<felt252>>;
revoke_ap_tracking() -> (); // 0
withdraw_gas([0], [1]) { fallthrough([4], [5]) 114([6], [7]) }; // 1
branch_align() -> (); // 2
struct_deconstruct<core::array::Span::<core::felt252>>([3]) -> ([8]); // 3
enable_ap_tracking() -> (); // 4
store_temp<RangeCheck>([4]) -> ([4]); // 5
array_snapshot_pop_front<felt252>([8]) { fallthrough([9], [10]) 12([11]) }; // 6
branch_align() -> (); // 7
enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 0>([10]) -> ([12]); // 8
store_temp<Snapshot<Array<felt252>>>([9]) -> ([13]); // 9
store_temp<core::option::Option::<core::box::Box::<@core::felt252>>>([12]) -> ([14]); // 10
jump() { 17() }; // 11
branch_align() -> (); // 12
struct_construct<Unit>() -> ([15]); // 13
enum_init<core::option::Option::<core::box::Box::<@core::felt252>>, 1>([15]) -> ([16]); // 14
store_temp<Snapshot<Array<felt252>>>([11]) -> ([13]); // 15
store_temp<core::option::Option::<core::box::Box::<@core::felt252>>>([16]) -> ([14]); // 16
enum_match<core::option::Option::<core::box::Box::<@core::felt252>>>([14]) { fallthrough([17]) 97([18]) }; // 17
branch_align() -> (); // 18
unbox<felt252>([17]) -> ([19]); // 19
rename<felt252>([19]) -> ([20]); // 20
store_temp<felt252>([20]) -> ([20]); // 21
u32_try_from_felt252([4], [20]) { fallthrough([21], [22]) 93([23]) }; // 22
branch_align() -> (); // 23
store_temp<RangeCheck>([21]) -> ([21]); // 24
array_snapshot_pop_front<felt252>([13]) { fallthrough([24], [25]) 43([26]) }; // 25
branch_align() -> (); // 26
disable_ap_tracking() -> (); // 27
drop<Snapshot<Array<felt252>>>([24]) -> (); // 28
drop<Box<felt252>>([25]) -> (); // 29
drop<u32>([22]) -> (); // 30
array_new<felt252>() -> ([27]); // 31
const_as_immediate<Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595>>() -> ([28]); // 32
store_temp<felt252>([28]) -> ([28]); // 33
array_append<felt252>([27], [28]) -> ([29]); // 34
struct_construct<core::panics::Panic>() -> ([30]); // 35
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([30], [29]) -> ([31]); // 36
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([31]) -> ([32]); // 37
store_temp<RangeCheck>([21]) -> ([21]); // 38
store_temp<GasBuiltin>([5]) -> ([5]); // 39
store_temp<System>([2]) -> ([2]); // 40
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([32]) -> ([32]); // 41
return([21], [5], [2], [32]); // 42
branch_align() -> (); // 43
disable_ap_tracking() -> (); // 44
drop<Snapshot<Array<felt252>>>([26]) -> (); // 45
get_builtin_costs() -> ([33]); // 46
store_temp<BuiltinCosts>([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<Const<u32, 0>>() -> ([41]); // 53
store_temp<u32>([41]) -> ([41]); // 54
store_temp<StorageAddress>([40]) -> ([40]); // 55
store_temp<RangeCheck>([34]) -> ([34]); // 56
storage_write_syscall([35], [2], [41], [40], [39]) { fallthrough([42], [43]) 70([44], [45], [46]) }; // 57
branch_align() -> (); // 58
array_new<felt252>() -> ([47]); // 59
snapshot_take<Array<felt252>>([47]) -> ([48], [49]); // 60
drop<Array<felt252>>([48]) -> (); // 61
struct_construct<core::array::Span::<core::felt252>>([49]) -> ([50]); // 62
struct_construct<Tuple<core::array::Span::<core::felt252>>>([50]) -> ([51]); // 63
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 0>([51]) -> ([52]); // 64
store_temp<RangeCheck>([34]) -> ([34]); // 65
store_temp<GasBuiltin>([42]) -> ([42]); // 66
store_temp<System>([43]) -> ([43]); // 67
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([52]) -> ([52]); // 68
return([34], [42], [43], [52]); // 69
branch_align() -> (); // 70
struct_construct<core::panics::Panic>() -> ([53]); // 71
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([53], [46]) -> ([54]); // 72
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([54]) -> ([55]); // 73
store_temp<RangeCheck>([34]) -> ([34]); // 74
store_temp<GasBuiltin>([44]) -> ([44]); // 75
store_temp<System>([45]) -> ([45]); // 76
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([55]) -> ([55]); // 77
return([34], [44], [45], [55]); // 78
branch_align() -> (); // 79
drop<u32>([22]) -> (); // 80
array_new<felt252>() -> ([56]); // 81
const_as_immediate<Const<felt252, 375233589013918064796019>>() -> ([57]); // 82
store_temp<felt252>([57]) -> ([57]); // 83
array_append<felt252>([56], [57]) -> ([58]); // 84
struct_construct<core::panics::Panic>() -> ([59]); // 85
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([59], [58]) -> ([60]); // 86
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([60]) -> ([61]); // 87
store_temp<RangeCheck>([36]) -> ([36]); // 88
store_temp<GasBuiltin>([37]) -> ([37]); // 89
store_temp<System>([2]) -> ([2]); // 90
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([61]) -> ([61]); // 91
return([36], [37], [2], [61]); // 92
branch_align() -> (); // 93
drop<Snapshot<Array<felt252>>>([13]) -> (); // 94
store_temp<RangeCheck>([23]) -> ([62]); // 95
jump() { 101() }; // 96
branch_align() -> (); // 97
drop<Unit>([18]) -> (); // 98
drop<Snapshot<Array<felt252>>>([13]) -> (); // 99
store_temp<RangeCheck>([4]) -> ([62]); // 100
disable_ap_tracking() -> (); // 101
array_new<felt252>() -> ([63]); // 102
const_as_immediate<Const<felt252, 485748461484230571791265682659113160264223489397539653310998840191492913>>() -> ([64]); // 103
store_temp<felt252>([64]) -> ([64]); // 104
array_append<felt252>([63], [64]) -> ([65]); // 105
struct_construct<core::panics::Panic>() -> ([66]); // 106
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([66], [65]) -> ([67]); // 107
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([67]) -> ([68]); // 108
store_temp<RangeCheck>([62]) -> ([62]); // 109
store_temp<GasBuiltin>([5]) -> ([5]); // 110
store_temp<System>([2]) -> ([2]); // 111
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([68]) -> ([68]); // 112
return([62], [5], [2], [68]); // 113
branch_align() -> (); // 114
drop<core::array::Span::<core::felt252>>([3]) -> (); // 115
array_new<felt252>() -> ([69]); // 116
const_as_immediate<Const<felt252, 375233589013918064796019>>() -> ([70]); // 117
store_temp<felt252>([70]) -> ([70]); // 118
array_append<felt252>([69], [70]) -> ([71]); // 119
struct_construct<core::panics::Panic>() -> ([72]); // 120
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([72], [71]) -> ([73]); // 121
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([73]) -> ([74]); // 122
store_temp<RangeCheck>([6]) -> ([6]); // 123
store_temp<GasBuiltin>([7]) -> ([7]); // 124
store_temp<System>([2]) -> ([2]); // 125
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([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<core::array::Span::<core::felt252>>([3]) -> ([8]); // 131
store_temp<RangeCheck>([4]) -> ([4]); // 132
array_snapshot_pop_front<felt252>([8]) { fallthrough([9], [10]) 149([11]) }; // 133
branch_align() -> (); // 134
drop<Snapshot<Array<felt252>>>([9]) -> (); // 135
drop<Box<felt252>>([10]) -> (); // 136
array_new<felt252>() -> ([12]); // 137
const_as_immediate<Const<felt252, 7733229381460288120802334208475838166080759535023995805565484692595>>() -> ([13]); // 138
store_temp<felt252>([13]) -> ([13]); // 139
array_append<felt252>([12], [13]) -> ([14]); // 140
struct_construct<core::panics::Panic>() -> ([15]); // 141
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([15], [14]) -> ([16]); // 142
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([16]) -> ([17]); // 143
store_temp<RangeCheck>([4]) -> ([4]); // 144
store_temp<GasBuiltin>([5]) -> ([5]); // 145
store_temp<System>([2]) -> ([2]); // 146
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([17]) -> ([17]); // 147
return([4], [5], [2], [17]); // 148
branch_align() -> (); // 149
drop<Snapshot<Array<felt252>>>([11]) -> (); // 150
get_builtin_costs() -> ([18]); // 151
store_temp<BuiltinCosts>([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<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>([23]) -> ([24]); // 156
snapshot_take<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>([24]) -> ([25], [26]); // 157
drop<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>([25]) -> (); // 158
struct_deconstruct<core::starknet::storage::StoragePointer0Offset::<core::integer::u32>>([26]) -> ([27]); // 159
rename<StorageBaseAddress>([27]) -> ([28]); // 160
storage_address_from_base([28]) -> ([29]); // 161
const_as_immediate<Const<u32, 0>>() -> ([30]); // 162
store_temp<u32>([30]) -> ([30]); // 163
store_temp<StorageAddress>([29]) -> ([29]); // 164
store_temp<RangeCheck>([19]) -> ([19]); // 165
storage_read_syscall([20], [2], [30], [29]) { fallthrough([31], [32], [33]) 196([34], [35], [36]) }; // 166
branch_align() -> (); // 167
store_temp<felt252>([33]) -> ([33]); // 168
store_temp<GasBuiltin>([31]) -> ([31]); // 169
store_temp<System>([32]) -> ([32]); // 170
u32_try_from_felt252([19], [33]) { fallthrough([37], [38]) 186([39]) }; // 171
branch_align() -> (); // 172
array_new<felt252>() -> ([40]); // 173
u32_to_felt252([38]) -> ([41]); // 174
array_append<felt252>([40], [41]) -> ([42]); // 175
snapshot_take<Array<felt252>>([42]) -> ([43], [44]); // 176
drop<Array<felt252>>([43]) -> (); // 177
struct_construct<core::array::Span::<core::felt252>>([44]) -> ([45]); // 178
struct_construct<Tuple<core::array::Span::<core::felt252>>>([45]) -> ([46]); // 179
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 0>([46]) -> ([47]); // 180
store_temp<RangeCheck>([37]) -> ([37]); // 181
store_temp<GasBuiltin>([31]) -> ([31]); // 182
store_temp<System>([32]) -> ([32]); // 183
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([47]) -> ([47]); // 184
return([37], [31], [32], [47]); // 185
branch_align() -> (); // 186
array_new<felt252>() -> ([48]); // 187
const_as_immediate<Const<felt252, 7269940625183576940180048306939577043858226>>() -> ([49]); // 188
store_temp<felt252>([49]) -> ([49]); // 189
array_append<felt252>([48], [49]) -> ([50]); // 190
store_temp<RangeCheck>([39]) -> ([51]); // 191
store_temp<GasBuiltin>([31]) -> ([52]); // 192
store_temp<System>([32]) -> ([53]); // 193
store_temp<Array<felt252>>([50]) -> ([54]); // 194
jump() { 201() }; // 195
branch_align() -> (); // 196
store_temp<RangeCheck>([19]) -> ([51]); // 197
store_temp<GasBuiltin>([34]) -> ([52]); // 198
store_temp<System>([35]) -> ([53]); // 199
store_temp<Array<felt252>>([36]) -> ([54]); // 200
struct_construct<core::panics::Panic>() -> ([55]); // 201
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([55], [54]) -> ([56]); // 202
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([56]) -> ([57]); // 203
store_temp<RangeCheck>([51]) -> ([51]); // 204
store_temp<GasBuiltin>([52]) -> ([52]); // 205
store_temp<System>([53]) -> ([53]); // 206
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([57]) -> ([57]); // 207
return([51], [52], [53], [57]); // 208
branch_align() -> (); // 209
array_new<felt252>() -> ([58]); // 210
const_as_immediate<Const<felt252, 375233589013918064796019>>() -> ([59]); // 211
store_temp<felt252>([59]) -> ([59]); // 212
array_append<felt252>([58], [59]) -> ([60]); // 213
struct_construct<core::panics::Panic>() -> ([61]); // 214
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([61], [60]) -> ([62]); // 215
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([62]) -> ([63]); // 216
store_temp<RangeCheck>([21]) -> ([21]); // 217
store_temp<GasBuiltin>([22]) -> ([22]); // 218
store_temp<System>([2]) -> ([2]); // 219
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([63]) -> ([63]); // 220
return([21], [22], [2], [63]); // 221
branch_align() -> (); // 222
drop<core::array::Span::<core::felt252>>([3]) -> (); // 223
array_new<felt252>() -> ([64]); // 224
const_as_immediate<Const<felt252, 375233589013918064796019>>() -> ([65]); // 225
store_temp<felt252>([65]) -> ([65]); // 226
array_append<felt252>([64], [65]) -> ([66]); // 227
struct_construct<core::panics::Panic>() -> ([67]); // 228
struct_construct<Tuple<core::panics::Panic, Array<felt252>>>([67], [66]) -> ([68]); // 229
enum_init<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>, 1>([68]) -> ([69]); // 230
store_temp<RangeCheck>([6]) -> ([6]); // 231
store_temp<GasBuiltin>([7]) -> ([7]); // 232
store_temp<System>([2]) -> ([2]); // 233
store_temp<core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>>([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::<core::felt252>) -> (RangeCheck, GasBuiltin, System, core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>);
storage_variables::storage_variables::StorageVariablesExample::__wrapper__StorageVariablesExample__get@128([0]: RangeCheck, [1]: GasBuiltin, [2]: System, [3]: core::array::Span::<core::felt252>) -> (RangeCheck, GasBuiltin, System, core::panics::PanicResult::<(core::array::Span::<core::felt252>,)>);
(You can obtain this with starknet-compile -sr path/to/storage_variables.cairo contract_class.json && starknet-sierra-extract-code contract_class.json output.sierra
)
pages/advanced-concepts/sierra_ir.md
Outdated
``` | ||
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) | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe more:
Cairo 1.0 Source (High-level)
|
| with Cairo-to-Sierra Compiler
V
Sierra IR (Safe, Provable Code)
|
| with Sierra-to-CASM Compiler (Run by Sequencer)
V
CASM (Cairo Assembly)
|
| with CairoVM Execution
V
STARK Proofs (Proof Generation)
pages/advanced-concepts/sierra_ir.md
Outdated
|
||
## 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its primary purpose is to provide memory safety guarantees while maintaining the expressive power needed for zero-knowledge proof generation.
I would say the 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
pages/advanced-concepts/sierra_ir.md
Outdated
### 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge these 2 subsections in one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pages/advanced-concepts/sierra_ir.md
Outdated
### 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this part
pages/advanced-concepts/sierra_ir.md
Outdated
### 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant with what was said before
pages/advanced-concepts/sierra_ir.md
Outdated
### 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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also introduce the concept of linear type system (everything is used once)
pages/advanced-concepts/sierra_ir.md
Outdated
|
||
- [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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this as first reference and use these links instead of medium:
https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-1
https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-2
https://www.nethermind.io/blog/under-the-hood-of-cairo-1-0-exploring-sierra-part-3
pages/advanced-concepts/sierra_ir.md
Outdated
|
||
Sierra's memory model is designed for safety: | ||
|
||
- Linear memory management | ||
- Explicit deallocation | ||
- No implicit copies | ||
- Reference counting for complex data structures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would like to emphasize on the linear/immutable memory layout where a memory cell can only be written to once only
pages/advanced-concepts/sierra_ir.md
Outdated
- Function calls with explicit stack management | ||
- Loop structures with invariant checking | ||
|
||
## Compilation Process Deep Dive |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this section. We want to focus on Sierra and not the compilation process from Cairo to Sierra, that is not really useful for developers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you can add a link to this workshop for the one interested to deep more into the compilation process
pages/advanced-concepts/sierra_ir.md
Outdated
#### 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 | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
casm is not generated with sierra and is out of scope here
No problem, I did an initial review to help you go in the good direction. Maybe this example is a bit different than the other so you don't have to create a scarb listing. Just .cairo /.sierra files in a folder in listings is enough |
Hi @julio4, thank you so much for your help so far — it has been invaluable. Do you think it would be helpful to include a link to guide users on installing and running a Cairo program to Sierra code? Looking forward to your feedback! |
This could be a nice addition but not necessary for now |
let sum = a + b; | ||
sum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let sum = a + b; | |
sum | |
a + b |
Feat: Sierra explanation:
close #260
Description
Creat doc to enable contributors to understanding cairo sierra IR from a high-level cairo to safe starknet.