Skip to content

Commit 63dc720

Browse files
TAdev0enitrat
andauthored
Core Lib Documentation: Starknet module (#6895)
Co-authored-by: enitrat <[email protected]>
1 parent 6fa9d19 commit 63dc720

File tree

2 files changed

+109
-83
lines changed

2 files changed

+109
-83
lines changed

corelib/src/starknet.cairo

Lines changed: 38 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
//! Functionalities for interacting with the Starknet network.
2+
//!
3+
//! # Core Components
4+
//!
5+
//! - **Storage**: The `storage` module defines abstractions on how to interact with Starknet
6+
//! contract storage.
7+
//! - **Syscalls**: The `syscalls` module contains the extern declarations for all the system calls
8+
//! available in Starknet.
9+
//! - **Contract Addresses**: The `contract_address` and `eth_address` modules provide types and
10+
//! utilities for working with Starknet contract addresses and Ethereum addresses.
11+
//! - **Cryptography**: The `secp256k1`, `secp256r1`, `secp256_trait`, and `eth_signature` modules
12+
//! handle various elliptic curve operations.
13+
//! - **Execution Info**: The `info` module exposes functions for accessing information about the
14+
//! current contract execution, such as the caller address, contract address, block info, and
15+
//! transaction info.
16+
117
#[allow(unused_imports)]
218
use core::box::Box;
319
#[allow(unused_imports)]
@@ -9,9 +25,7 @@ use core::traits::{Into, TryInto};
925
#[allow(unused_imports)]
1026
use core::zeroable::Zeroable;
1127

12-
/// Store trait and implementations for various types.
1328
pub mod storage_access;
14-
/// Re-imports
1529
pub use storage_access::{Store, StorageAddress};
1630
#[allow(unused_imports)]
1731
use storage_access::{
@@ -20,7 +34,6 @@ use storage_access::{
2034
storage_address_try_from_felt252,
2135
};
2236

23-
/// Module containing all the extern declaration of the syscalls.
2437
pub mod syscalls;
2538
#[allow(unused_imports)]
2639
use syscalls::{
@@ -30,12 +43,10 @@ use syscalls::{
3043
get_class_hash_at_syscall,
3144
};
3245

33-
/// secp256
3446
pub mod secp256_trait;
3547
pub mod secp256k1;
3648
pub mod secp256r1;
3749

38-
/// ContractAddress
3950
pub mod contract_address;
4051
pub use contract_address::{ContractAddress, contract_address_const};
4152
#[allow(unused_imports)]
@@ -44,20 +55,17 @@ use contract_address::{
4455
contract_address_try_from_felt252,
4556
};
4657

47-
/// EthAddress
4858
pub mod eth_address;
4959
pub use eth_address::EthAddress;
5060
#[allow(unused_imports)]
5161
use eth_address::{
5262
EthAddressIntoFelt252, EthAddressSerde, EthAddressZeroable, Felt252TryIntoEthAddress,
5363
};
5464

55-
/// EthSignature
5665
pub mod eth_signature;
5766
#[allow(unused_imports)]
5867
use eth_signature::verify_eth_signature;
5968

60-
/// ClassHash
6169
pub mod class_hash;
6270
pub use class_hash::ClassHash;
6371
#[allow(unused_imports)]
@@ -66,7 +74,7 @@ use class_hash::{
6674
class_hash_try_from_felt252,
6775
};
6876

69-
/// Not `pub` on purpose, only used for direct reexport by the next line.
77+
// Not `pub` on purpose, only used for direct reexport by the next line.
7078
mod info;
7179
pub use info::{
7280
v2::ExecutionInfo as ExecutionInfo, BlockInfo, v2::TxInfo as TxInfo, get_execution_info,
@@ -80,91 +88,37 @@ pub use event::Event;
8088
pub mod account;
8189
pub use account::AccountContract;
8290

83-
/// This module contains the storage-related types and traits for Cairo contracts. It provides
84-
/// abstractions for reading and writing to Starknet storage.
85-
///
86-
/// The front facing interface for the user is simple and intuitive, for example consider the
87-
/// following storage struct:
88-
/// ```
89-
/// #[storage]
90-
/// struct Storage {
91-
/// a: felt252,
92-
/// b: Map<felt252, felt52>,
93-
/// c: Map<felt52, Map<felt52, felt52>>,
94-
/// }
95-
/// ```
96-
/// The user can access the storage members `a` and `b` using the following code:
97-
/// ```
98-
/// fn use_storage(self: @ContractState) {
99-
/// let a_value = self.a.read();
100-
/// // For a Map, the user can use the `entry` method to access the value at a specific key:
101-
/// let b_value = self.b.entry(42).read();
102-
/// // Or simply pass the key to the `read` method:
103-
/// let b_value = self.b.read(42);
104-
/// // Accessing a nested Map must be done using the `entry` method, either:
105-
/// let c_value = self.c.entry(42).entry(43).read()
106-
/// // Or:
107-
/// let c_value = self.c.entry(42).read(43);
108-
/// }
109-
/// ```
110-
///
111-
/// Under the hood, the storage access is more complex. The life cycle of a storage object is as
112-
/// follows:
113-
/// 1. The storage struct of a contract is represented by a `FlattenedStorage` struct, which
114-
/// can be derefed into a struct containing a member for each storage member of the contract.
115-
/// This member can be either a `StorageBase` or a `FlattenedStorage` instance. Members are
116-
/// represented as a `FlattenedStorage` if the storage member is attributed with either
117-
/// `#[substorage(v0)]` (for backward compatibility) or `#[flat]`. `FlattenedStorage` is used to
118-
/// structure the storage access; however, it does not affect the address of the storage object.
119-
/// 2. `StorageBase` members of a `FlattenedStorage` struct hold a single `felt252` value, which is
120-
/// the Keccak hash of the name of the member. For simple types, this value will be the address
121-
/// of the member in the storage.
122-
/// 3. `StorageBase` members are then converted to `StoragePath` instances, which are essentially
123-
/// a wrapper around a `HashState` instance, used to account for more values when computing the
124-
/// address of the storage object. `StoragePath` instances can be updated with values coming from
125-
/// two sources:
126-
/// - Storage nodes, which are structs that represent another struct with all its members
127-
/// in the storage, similar to `FlattenedStorage`. However, unlike `FlattenedStorage`, the
128-
/// path to the storage node does affect the address of the storage object. See `StorageNode`
129-
/// for more details.
130-
/// - Storage collections, specifically `Map` and `Vec`, simulate the behavior of collections by
131-
/// updating the hash state with the key or index of the collection member.
132-
/// 4. After finishing the updates, the `StoragePath` instance is finalized, resulting in a
133-
/// `StoragePointer0Offset` instance, which is a pointer to the address of the storage object. If
134-
/// the pointer is to an object of size greater than 1, the object is stored in a sequential
135-
/// manner starting from the address of the pointer. The whole object can be read or written
136-
/// using `read` and `write` methods, and specific members can also be accessed in the case of a
137-
/// struct. See `SubPointers` for more details.
138-
///
139-
/// The transitioning between the different types of storage objects is also called from the
140-
/// `Deref` trait, and thus, allowing an access to the members of the storage object in a simple
141-
/// way.
142-
///
143-
/// The types mentioned above are generic in the stored object type. This is done to provide
144-
/// specific behavior for each type of stored object, e.g., a `StoragePath` of `Map` type will have
145-
/// an `entry` method, but it won't have a `read` or `write` method, as `Map` is not storable by
146-
/// itself, only its values are.
147-
/// The generic type of the storage object can also be wrapped with a `Mutable` type, which
148-
/// indicates that the storage object is mutable, i.e., it was created from a `ref` contract state,
149-
/// and thus the object can be written to.
15091
pub mod storage;
15192

15293
pub extern type System;
15394

154-
/// An Helper function to force the inclusion of `System` in the list of implicits.
95+
// A helper function to force the inclusion of `System` in the list of implicits.
15596
#[deprecated(
15697
feature: "use_system_implicit",
15798
note: "Use `core::internal::require_implicit::<System>` instead.",
15899
)]
159100
fn use_system_implicit() implicits(System) {}
160101

161-
/// The result type for a syscall.
102+
/// The `Result` type for a syscall.
162103
pub type SyscallResult<T> = Result<T, Array<felt252>>;
163104

105+
/// Trait for handling syscalls results.
164106
pub trait SyscallResultTrait<T> {
165-
/// If `val` is `Result::Ok(x)`, returns `x`. Otherwise, panics with the revert reason.
107+
/// Unwraps a syscall result, yielding the content of an `Ok`.
108+
///
109+
/// # Panics
110+
///
111+
/// Panics with the syscall error message if the value is an `Err`.
112+
///
113+
/// # Examples
114+
///
115+
/// ```
116+
/// let result = starknet::syscalls::get_execution_info_v2_syscall();
117+
/// let info = result.unwrap_syscall();
118+
/// ```
166119
fn unwrap_syscall(self: SyscallResult<T>) -> T;
167120
}
121+
168122
impl SyscallResultTraitImpl<T> of SyscallResultTrait<T> {
169123
fn unwrap_syscall(self: SyscallResult<T>) -> T {
170124
match self {
@@ -174,10 +128,11 @@ impl SyscallResultTraitImpl<T> of SyscallResultTrait<T> {
174128
}
175129
}
176130

177-
/// The expected return value of the `__validate*__` functions of an accounted contract.
131+
/// The expected return value of the `__validate__` function in account contracts.
132+
///
133+
/// This constant is used to indicate that a transaction validation was successful.
134+
/// Account contracts must return this value from their `__validate__` function to
135+
/// signal that the transaction should proceed.
178136
pub const VALIDATED: felt252 = 'VALID';
179137

180-
/// Module for starknet testing only.
181-
/// Provides functions useful for testing event emission, starknet state information, and the
182-
/// cheatcode concept in general.
183138
pub mod testing;

corelib/src/starknet/storage.cairo

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,74 @@
1+
//! Contains the storage-related types and traits for Cairo contracts and provides abstractions for
2+
//! reading and writing to Starknet storage.
3+
//!
4+
//! The front facing interface for the user is simple and intuitive, for example consider the
5+
//! following storage struct:
6+
//!
7+
//! ```
8+
//! #[storage]
9+
//! struct Storage {
10+
//! a: felt252,
11+
//! b: Map<felt252, felt52>,
12+
//! c: Map<felt52, Map<felt52, felt52>>,
13+
//! }
14+
//! ```
15+
//!
16+
//! The user can access the storage members `a` and `b` using the following code:
17+
//!
18+
//! ```
19+
//! fn use_storage(self: @ContractState) {
20+
//! let a_value = self.a.read();
21+
//! // For a Map, the user can use the `entry` method to access the value at a specific key:
22+
//! let b_value = self.b.entry(42).read();
23+
//! // Or simply pass the key to the `read` method:
24+
//! let b_value = self.b.read(42);
25+
//! // Accessing a nested Map must be done using the `entry` method, either:
26+
//! let c_value = self.c.entry(42).entry(43).read()
27+
//! // Or:
28+
//! let c_value = self.c.entry(42).read(43);
29+
//! }
30+
//! ```
31+
//!
32+
//! Under the hood, the storage access is more complex. The life cycle of a storage object is as
33+
//! follows:
34+
//! 1. The storage struct of a contract is represented by a `FlattenedStorage` struct, which
35+
//! can be derefed into a struct containing a member for each storage member of the contract.
36+
//! This member can be either a `StorageBase` or a `FlattenedStorage` instance. Members are
37+
//! represented as a `FlattenedStorage` if the storage member is attributed with either
38+
//! `#[substorage(v0)]` (for backward compatibility) or `#[flat]`. `FlattenedStorage` is used to
39+
//! structure the storage access; however, it does not affect the address of the storage object.
40+
//! 2. `StorageBase` members of a `FlattenedStorage` struct hold a single `felt252` value, which is
41+
//! the Keccak hash of the name of the member. For simple types, this value will be the address
42+
//! of the member in the storage.
43+
//! 3. `StorageBase` members are then converted to `StoragePath` instances, which are essentially
44+
//! a wrapper around a `HashState` instance, used to account for more values when computing the
45+
//! address of the storage object. `StoragePath` instances can be updated with values coming from
46+
//! two sources:
47+
//! - Storage nodes, which are structs that represent another struct with all its members
48+
//! in the storage, similar to `FlattenedStorage`. However, unlike `FlattenedStorage`, the
49+
//! path to the storage node does affect the address of the storage object. See `StorageNode`
50+
//! for more details.
51+
//! - Storage collections, specifically `Map` and `Vec`, simulate the behavior of collections by
52+
//! updating the hash state with the key or index of the collection member.
53+
//! 4. After finishing the updates, the `StoragePath` instance is finalized, resulting in a
54+
//! `StoragePointer0Offset` instance, which is a pointer to the address of the storage object. If
55+
//! the pointer is to an object of size greater than 1, the object is stored in a sequential
56+
//! manner starting from the address of the pointer. The whole object can be read or written
57+
//! using `read` and `write` methods, and specific members can also be accessed in the case of a
58+
//! struct. See `SubPointers` for more details.
59+
//!
60+
//! The transitioning between the different types of storage objects is also called from the
61+
//! `Deref` trait, and thus, allowing an access to the members of the storage object in a simple
62+
//! way.
63+
//!
64+
//! The types mentioned above are generic in the stored object type. This is done to provide
65+
//! specific behavior for each type of stored object, e.g., a `StoragePath` of `Map` type will have
66+
//! an `entry` method, but it won't have a `read` or `write` method, as `Map` is not storable by
67+
//! itself, only its values are.
68+
//! The generic type of the storage object can also be wrapped with a `Mutable` type, which
69+
//! indicates that the storage object is mutable, i.e., it was created from a `ref` contract state,
70+
//! and thus the object can be written to.
71+
172
use core::traits::Into;
273
#[allow(unused_imports)]
374
use core::pedersen::HashState;

0 commit comments

Comments
 (0)