cairo_lang_starknet_classes/
contract_class.rs1use cairo_lang_sierra as sierra;
2use cairo_lang_utils::bigint::{BigUintAsHex, deserialize_big_uint, serialize_big_uint};
3use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
4use num_bigint::BigUint;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use thiserror::Error;
8
9use crate::abi::Contract;
10use crate::allowed_libfuncs::{AllowedLibfuncsError, ListSelector, lookup_allowed_libfuncs_list};
11use crate::compiler_version::{VersionId, current_compiler_version_id, current_sierra_version_id};
12use crate::felt252_serde::{
13 Felt252SerdeError, sierra_from_felt252s, sierra_to_felt252s, version_id_from_felt252s,
14};
15
16#[cfg(test)]
17#[path = "contract_class_test.rs"]
18mod test;
19
20#[derive(Error, Debug, Eq, PartialEq)]
21pub enum StarknetCompilationError {
22 #[error("Invalid entry point.")]
23 EntryPointError,
24 #[error(transparent)]
25 AllowedLibfuncsError(#[from] AllowedLibfuncsError),
26}
27
28#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
30pub struct ContractClass {
31 pub sierra_program: Vec<BigUintAsHex>,
32 pub sierra_program_debug_info: Option<sierra::debug_info::DebugInfo>,
33 pub contract_class_version: String,
34 pub entry_points_by_type: ContractEntryPoints,
35 pub abi: Option<Contract>,
36}
37impl ContractClass {
38 pub fn new(
40 program: &sierra::program::Program,
41 entry_points_by_type: ContractEntryPoints,
42 abi: Option<Contract>,
43 annotations: OrderedHashMap<String, Value>,
44 ) -> Result<Self, Felt252SerdeError> {
45 let mut sierra_program_debug_info = sierra::debug_info::DebugInfo::extract(program);
46 sierra_program_debug_info.annotations.extend(annotations);
47
48 Ok(Self {
49 sierra_program: sierra_to_felt252s(
50 current_sierra_version_id(),
51 current_compiler_version_id(),
52 program,
53 )?,
54 sierra_program_debug_info: Some(sierra_program_debug_info),
55 contract_class_version: DEFAULT_CONTRACT_CLASS_VERSION.into(),
56 entry_points_by_type,
57 abi,
58 })
59 }
60
61 pub fn extract_sierra_program(&self) -> Result<sierra::program::Program, Felt252SerdeError> {
64 let (_, _, mut sierra_program) = sierra_from_felt252s(&self.sierra_program)?;
65 if let Some(info) = &self.sierra_program_debug_info {
66 info.populate(&mut sierra_program);
67 }
68 Ok(sierra_program)
69 }
70
71 pub fn sanity_check(&self) {
74 if let Some(abi) = &self.abi {
75 abi.sanity_check(
76 self.entry_points_by_type.external.len(),
77 self.entry_points_by_type.l1_handler.len(),
78 self.entry_points_by_type.constructor.len(),
79 );
80 }
81 }
82
83 pub fn validate_version_compatible(
86 self: &ContractClass,
87 list_selector: ListSelector,
88 ) -> Result<(), AllowedLibfuncsError> {
89 let list_name = list_selector.to_string();
90 let allowed_libfuncs = lookup_allowed_libfuncs_list(list_selector)?;
91 let (_, _, sierra_program) = sierra_from_felt252s(&self.sierra_program)
92 .map_err(|_| AllowedLibfuncsError::SierraProgramError)?;
93 for libfunc in &sierra_program.libfunc_declarations {
94 if !allowed_libfuncs.allowed_libfuncs.contains(&libfunc.long_id.generic_id) {
95 return Err(AllowedLibfuncsError::UnsupportedLibfunc {
96 invalid_libfunc: libfunc.long_id.generic_id.to_string(),
97 allowed_libfuncs_list_name: list_name,
98 });
99 }
100 }
101 Ok(())
102 }
103}
104
105const DEFAULT_CONTRACT_CLASS_VERSION: &str = "0.1.0";
106
107#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
108pub struct ContractEntryPoints {
109 #[serde(rename = "EXTERNAL")]
110 pub external: Vec<ContractEntryPoint>,
111 #[serde(rename = "L1_HANDLER")]
112 pub l1_handler: Vec<ContractEntryPoint>,
113 #[serde(rename = "CONSTRUCTOR")]
114 pub constructor: Vec<ContractEntryPoint>,
115}
116
117#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
118pub struct ContractEntryPoint {
119 #[serde(serialize_with = "serialize_big_uint", deserialize_with = "deserialize_big_uint")]
121 pub selector: BigUint,
122 pub function_idx: usize,
124}
125
126pub fn version_id_from_serialized_sierra_program(
132 sierra_program: &[BigUintAsHex],
133) -> Result<(VersionId, VersionId), Felt252SerdeError> {
134 let (sierra_version_id, compiler_version_id, _) = version_id_from_felt252s(sierra_program)?;
135 Ok((sierra_version_id, compiler_version_id))
136}