pathfinder_common/
casm_class.rs

1use num_bigint::BigUint;
2use num_traits::Num;
3use pathfinder_crypto::Felt;
4use serde::{Deserialize, Serialize};
5
6use crate::EntryPoint;
7
8/// A contract in the Starknet network.
9#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
10pub struct CasmContractClass {
11    pub bytecode: Vec<Felt>,
12    #[serde(default, skip_serializing_if = "Option::is_none")]
13    pub bytecode_segment_lengths: Option<NestedIntList>,
14    pub compiler_version: String,
15    pub hints: serde_json::Value,
16    pub entry_points_by_type: CasmContractEntryPoints,
17    pub prime: BigUintAsHex,
18}
19
20/// The entry points (functions) of a contract.
21#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
22pub struct CasmContractEntryPoints {
23    #[serde(rename = "EXTERNAL")]
24    pub external: Vec<CasmContractEntryPoint>,
25    #[serde(rename = "L1_HANDLER")]
26    pub l1_handler: Vec<CasmContractEntryPoint>,
27    #[serde(rename = "CONSTRUCTOR")]
28    pub constructor: Vec<CasmContractEntryPoint>,
29}
30
31/// An entry point (function) of a contract.
32#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
33pub struct CasmContractEntryPoint {
34    /// A field element that encodes the signature of the called function.
35    pub selector: EntryPoint,
36    /// The offset of the instruction that should be called within the contract
37    /// bytecode.
38    pub offset: usize,
39    // List of builtins.
40    pub builtins: Vec<String>,
41}
42
43/// A field element that encodes the signature of the called function.
44#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
45#[serde(transparent)]
46pub struct BigUintAsHex {
47    /// A field element that encodes the signature of the called function.
48    #[serde(
49        serialize_with = "serialize_big_uint",
50        deserialize_with = "deserialize_big_uint"
51    )]
52    pub value: BigUint,
53}
54
55pub fn serialize_big_uint<S>(num: &BigUint, serializer: S) -> Result<S::Ok, S::Error>
56where
57    S: serde::Serializer,
58{
59    serializer.serialize_str(&format!("{num:#x}"))
60}
61
62pub fn deserialize_big_uint<'a, D>(deserializer: D) -> Result<BigUint, D::Error>
63where
64    D: serde::Deserializer<'a>,
65{
66    let s = &<String as serde::Deserialize>::deserialize(deserializer)?;
67    match s.strip_prefix("0x") {
68        Some(num_no_prefix) => BigUint::from_str_radix(num_no_prefix, 16)
69            .map_err(|error| serde::de::Error::custom(format!("{error}"))),
70        None => Err(serde::de::Error::custom(format!(
71            "{s} does not start with `0x` is missing."
72        ))),
73    }
74}
75
76/// NestedIntList is either a list of NestedIntList or an integer.
77/// E.g., `[0, [1, 2], [3, [4]]]`.
78///
79/// Used to represents the lengths of the segments in a contract, which are in a
80/// form of a tree.
81///
82/// For example, the contract may be segmented by functions, where each function
83/// is segmented by its branches. It is also possible to have the inner
84/// segmentation only for some of the functions, while others are kept as
85/// non-segmented leaves in the tree.
86#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
87#[serde(untagged)]
88pub enum NestedIntList {
89    Leaf(usize),
90    Node(Vec<NestedIntList>),
91}
92
93impl TryFrom<&str> for CasmContractClass {
94    type Error = serde_json::Error;
95
96    fn try_from(value: &str) -> Result<Self, Self::Error> {
97        serde_json::from_str(value)
98    }
99}