cairo_lang_sierra/extensions/modules/starknet/
interoperability.rs

1use num_bigint::BigInt;
2
3use super::felt252_span_ty;
4use super::syscalls::SyscallGenericLibfunc;
5use crate::extensions::consts::{ConstGenLibfunc, WrapConstGenLibfunc};
6use crate::extensions::felt252::Felt252Type;
7use crate::extensions::lib_func::{LibfuncSignature, SignatureSpecializationContext};
8use crate::extensions::modules::get_bool_type;
9use crate::extensions::try_from_felt252::TryFromFelt252;
10use crate::extensions::utils::reinterpret_cast_signature;
11use crate::extensions::{
12    NamedType, NoGenericArgsGenericLibfunc, NoGenericArgsGenericType, SpecializationError,
13};
14use crate::ids::GenericTypeId;
15
16/// Type for Starknet contract address, a value in the range [0, 2 ** 251).
17#[derive(Default)]
18pub struct ContractAddressType {}
19impl NoGenericArgsGenericType for ContractAddressType {
20    const ID: GenericTypeId = GenericTypeId::new_inline("ContractAddress");
21    const STORABLE: bool = true;
22    const DUPLICATABLE: bool = true;
23    const DROPPABLE: bool = true;
24    const ZERO_SIZED: bool = false;
25}
26
27/// Libfunc for creating a constant storage address.
28#[derive(Default)]
29pub struct ContractAddressConstLibfuncWrapped {}
30impl ConstGenLibfunc for ContractAddressConstLibfuncWrapped {
31    const STR_ID: &'static str = "contract_address_const";
32    const GENERIC_TYPE_ID: GenericTypeId = <ContractAddressType as NoGenericArgsGenericType>::ID;
33
34    fn bound() -> BigInt {
35        BigInt::from(2).pow(251)
36    }
37}
38
39pub type ContractAddressConstLibfunc = WrapConstGenLibfunc<ContractAddressConstLibfuncWrapped>;
40
41/// Libfunc for attempting to convert a felt252 into a contract address.
42#[derive(Default)]
43pub struct ContractAddressTryFromFelt252Libfunc;
44impl TryFromFelt252 for ContractAddressTryFromFelt252Libfunc {
45    const STR_ID: &'static str = "contract_address_try_from_felt252";
46    const GENERIC_TYPE_ID: GenericTypeId = <ContractAddressType as NoGenericArgsGenericType>::ID;
47}
48
49/// Libfunc for converting a ContractAddress into a felt252.
50#[derive(Default)]
51pub struct ContractAddressToFelt252Libfunc {}
52impl NoGenericArgsGenericLibfunc for ContractAddressToFelt252Libfunc {
53    const STR_ID: &'static str = "contract_address_to_felt252";
54
55    fn specialize_signature(
56        &self,
57        context: &dyn SignatureSpecializationContext,
58    ) -> Result<LibfuncSignature, SpecializationError> {
59        Ok(reinterpret_cast_signature(
60            context.get_concrete_type(ContractAddressType::id(), &[])?,
61            context.get_concrete_type(Felt252Type::id(), &[])?,
62        ))
63    }
64}
65
66/// Type for Starknet class hash, a value in the range [0, 2 ** 251).
67#[derive(Default)]
68pub struct ClassHashType {}
69impl NoGenericArgsGenericType for ClassHashType {
70    const ID: GenericTypeId = GenericTypeId::new_inline("ClassHash");
71    const STORABLE: bool = true;
72    const DUPLICATABLE: bool = true;
73    const DROPPABLE: bool = true;
74    const ZERO_SIZED: bool = false;
75}
76
77/// Libfunc for creating a constant storage address.
78#[derive(Default)]
79pub struct ClassHashConstLibfuncWrapped {}
80impl ConstGenLibfunc for ClassHashConstLibfuncWrapped {
81    const STR_ID: &'static str = "class_hash_const";
82    const GENERIC_TYPE_ID: GenericTypeId = <ClassHashType as NoGenericArgsGenericType>::ID;
83
84    fn bound() -> BigInt {
85        BigInt::from(2).pow(251)
86    }
87}
88
89pub type ClassHashConstLibfunc = WrapConstGenLibfunc<ClassHashConstLibfuncWrapped>;
90
91/// Libfunc for attempting to convert a felt252 into a class hash.
92#[derive(Default)]
93pub struct ClassHashTryFromFelt252Trait;
94impl TryFromFelt252 for ClassHashTryFromFelt252Trait {
95    const STR_ID: &'static str = "class_hash_try_from_felt252";
96    const GENERIC_TYPE_ID: GenericTypeId = <ClassHashType as NoGenericArgsGenericType>::ID;
97}
98
99/// Libfunc for converting a class hash into a felt252.
100#[derive(Default)]
101pub struct ClassHashToFelt252Libfunc {}
102impl NoGenericArgsGenericLibfunc for ClassHashToFelt252Libfunc {
103    const STR_ID: &'static str = "class_hash_to_felt252";
104
105    fn specialize_signature(
106        &self,
107        context: &dyn SignatureSpecializationContext,
108    ) -> Result<LibfuncSignature, SpecializationError> {
109        Ok(reinterpret_cast_signature(
110            context.get_concrete_type(ClassHashType::id(), &[])?,
111            context.get_concrete_type(Felt252Type::id(), &[])?,
112        ))
113    }
114}
115
116/// Libfunc for a storage call contract system call.
117#[derive(Default)]
118pub struct CallContractLibfunc {}
119impl SyscallGenericLibfunc for CallContractLibfunc {
120    const STR_ID: &'static str = "call_contract_syscall";
121
122    fn input_tys(
123        context: &dyn SignatureSpecializationContext,
124    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
125        Ok(vec![
126            // Address
127            context.get_concrete_type(ContractAddressType::id(), &[])?,
128            // Entry point selector.
129            context.get_concrete_type(Felt252Type::id(), &[])?,
130            // Call data
131            felt252_span_ty(context)?,
132        ])
133    }
134
135    fn success_output_tys(
136        context: &dyn SignatureSpecializationContext,
137    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
138        Ok(vec![felt252_span_ty(context)?])
139    }
140}
141
142/// Libfunc for a deploying a declared class system call.
143#[derive(Default)]
144pub struct DeployLibfunc {}
145impl SyscallGenericLibfunc for DeployLibfunc {
146    const STR_ID: &'static str = "deploy_syscall";
147
148    fn input_tys(
149        context: &dyn SignatureSpecializationContext,
150    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
151        Ok(vec![
152            // Class hash
153            context.get_concrete_type(ClassHashType::id(), &[])?,
154            // Contract address salt
155            context.get_concrete_type(Felt252Type::id(), &[])?,
156            // Constructor call data
157            felt252_span_ty(context)?,
158            // Deploy from zero
159            get_bool_type(context)?,
160        ])
161    }
162
163    fn success_output_tys(
164        context: &dyn SignatureSpecializationContext,
165    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
166        Ok(vec![
167            context.get_concrete_type(ContractAddressType::id(), &[])?,
168            felt252_span_ty(context)?,
169        ])
170    }
171}
172
173/// Libfunc for a library call system call.
174#[derive(Default)]
175pub struct LibraryCallLibfunc {}
176impl SyscallGenericLibfunc for LibraryCallLibfunc {
177    const STR_ID: &'static str = "library_call_syscall";
178
179    fn input_tys(
180        context: &dyn SignatureSpecializationContext,
181    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
182        Ok(vec![
183            // Class hash
184            context.get_concrete_type(ClassHashType::id(), &[])?,
185            // Function selector
186            context.get_concrete_type(Felt252Type::id(), &[])?,
187            // Call data
188            felt252_span_ty(context)?,
189        ])
190    }
191
192    fn success_output_tys(
193        context: &dyn SignatureSpecializationContext,
194    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
195        Ok(vec![felt252_span_ty(context)?])
196    }
197}
198
199/// Libfunc for sending message to l1 system call.
200#[derive(Default)]
201pub struct SendMessageToL1Libfunc {}
202impl SyscallGenericLibfunc for SendMessageToL1Libfunc {
203    const STR_ID: &'static str = "send_message_to_l1_syscall";
204
205    fn input_tys(
206        context: &dyn SignatureSpecializationContext,
207    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
208        Ok(vec![
209            // Address
210            context.get_concrete_type(Felt252Type::id(), &[])?,
211            // Payload
212            felt252_span_ty(context)?,
213        ])
214    }
215
216    fn success_output_tys(
217        _context: &dyn SignatureSpecializationContext,
218    ) -> Result<Vec<crate::ids::ConcreteTypeId>, SpecializationError> {
219        Ok(vec![])
220    }
221}