1use blockifier::blockifier_versioned_constants::VersionedConstants;
2use blockifier::bouncer::{BouncerConfig, BouncerWeights, BuiltinWeights};
3use blockifier::transaction::objects::TransactionExecutionInfo;
4use starknet_api::block::StarknetVersion;
5use starknet_api::versioned_constants_logic::VersionedConstantsTrait;
6use starknet_rs_core::types::Felt;
7use starknet_types::patricia_key::{PatriciaKey, StorageKey};
8
9use crate::error::DevnetResult;
10
11pub mod random_number_generator {
12 use rand::{Rng, SeedableRng, rng};
13 use rand_mt::Mt64;
14
15 pub fn generate_u32_random_number() -> u32 {
16 rng().random()
17 }
18
19 pub(crate) fn generate_u128_random_numbers(seed: u32, random_numbers_count: u8) -> Vec<u128> {
20 let mut result: Vec<u128> = Vec::new();
21 let mut rng: Mt64 = SeedableRng::seed_from_u64(seed as u64);
22
23 for _ in 0..random_numbers_count {
24 result.push(rng.random());
25 }
26
27 result
28 }
29}
30
31pub(crate) fn get_storage_var_address(
33 storage_var_name: &str,
34 args: &[Felt],
35) -> DevnetResult<StorageKey> {
36 let storage_var_address =
37 starknet_rs_core::utils::get_storage_var_address(storage_var_name, args)
38 .map_err(|err| crate::error::Error::UnexpectedInternalError { msg: err.to_string() })?;
39
40 Ok(PatriciaKey::new(storage_var_address)?)
41}
42
43pub(crate) fn get_versioned_constants() -> VersionedConstants {
45 #[allow(clippy::unwrap_used)]
46 VersionedConstants::get(&StarknetVersion::V0_14_1).unwrap().clone()
47}
48
49pub(crate) fn custom_bouncer_config() -> BouncerConfig {
56 BouncerConfig {
57 block_max_capacity: BouncerWeights {
58 l1_gas: 4_950_000,
59 sierra_gas: starknet_api::execution_resources::GasAmount(2_000_000_000),
60 state_diff_size: 4_000,
61 n_events: 5_000,
62 ..BouncerWeights::max()
63 },
64 builtin_weights: BuiltinWeights::default(),
65 blake_weight: 5263, }
67}
68
69#[macro_export]
70macro_rules! nonzero_gas_price {
71 ($value:expr) => {{
72 let gas_price = starknet_api::block::GasPrice(($value).get());
73 starknet_api::block::NonzeroGasPrice::new(gas_price).unwrap()
74 }};
75}
76
77pub(crate) fn maybe_extract_failure_reason(
78 execution_info: &TransactionExecutionInfo,
79) -> Option<String> {
80 execution_info.revert_error.as_ref().map(|err| err.to_string())
81}
82
83#[cfg(test)]
84pub(crate) mod test_utils {
85 use cairo_lang_starknet_classes::contract_class::ContractClass as SierraContractClass;
86 use starknet_api::data_availability::DataAvailabilityMode;
87 use starknet_api::transaction::fields::Tip;
88 use starknet_rs_core::types::Felt;
89 use starknet_types::contract_address::ContractAddress;
90 use starknet_types::contract_class::deprecated::json_contract_class::Cairo0Json;
91 use starknet_types::contract_class::{Cairo0ContractClass, ContractClass};
92 use starknet_types::rpc::transactions::broadcasted_declare_transaction_v3::BroadcastedDeclareTransactionV3;
93 use starknet_types::rpc::transactions::broadcasted_invoke_transaction_v3::BroadcastedInvokeTransactionV3;
94 use starknet_types::rpc::transactions::declare_transaction_v3::DeclareTransactionV3;
95 use starknet_types::rpc::transactions::{
96 BroadcastedDeclareTransaction, BroadcastedInvokeTransaction,
97 BroadcastedTransactionCommonV3, DeclareTransaction, ResourceBoundsWrapper, Transaction,
98 TransactionWithHash,
99 };
100 use starknet_types::traits::HashProducer;
101
102 use crate::account::KeyPair;
103 use crate::constants::DEVNET_DEFAULT_CHAIN_ID;
104
105 pub(crate) fn dummy_felt() -> Felt {
106 Felt::from_hex_unchecked("0xDD10")
107 }
108
109 pub(crate) fn dummy_cairo_1_contract_class() -> SierraContractClass {
110 let json_str =
111 std::fs::read_to_string("../../contracts/test_artifacts/cairo1/cairo_1_test.sierra")
112 .unwrap();
113
114 ContractClass::cairo_1_from_sierra_json_str(&json_str).unwrap()
115 }
116
117 pub static DUMMY_CAIRO_1_COMPILED_CLASS_HASH: Felt = Felt::from_hex_unchecked(
119 "0x586026f886dd7ee74f6b32b12c9678f0bc090260c881a41d192103a17c110e8",
120 );
121
122 pub(crate) fn dummy_contract_address() -> ContractAddress {
123 ContractAddress::new(Felt::from_hex_unchecked("0xADD4E55")).unwrap()
124 }
125
126 pub(crate) fn resource_bounds_with_price_1(
128 l1_gas: u64,
129 l1_data_gas: u64,
130 l2_gas: u64,
131 ) -> ResourceBoundsWrapper {
132 ResourceBoundsWrapper::new(l1_gas, 1, l1_data_gas, 1, l2_gas, 1)
133 }
134
135 pub(crate) fn broadcasted_declare_tx_v3_of_dummy_class(
138 sender_address: ContractAddress,
139 nonce: Felt,
140 resource_bounds: ResourceBoundsWrapper,
141 ) -> BroadcastedDeclareTransactionV3 {
142 broadcasted_declare_tx_v3(
143 sender_address,
144 nonce,
145 dummy_cairo_1_contract_class(),
146 DUMMY_CAIRO_1_COMPILED_CLASS_HASH,
147 resource_bounds,
148 )
149 }
150
151 pub(crate) fn broadcasted_declare_tx_v3(
154 sender_address: ContractAddress,
155 nonce: Felt,
156 contract_class: cairo_lang_starknet_classes::contract_class::ContractClass,
157 compiled_class_hash: Felt,
158 resource_bounds: ResourceBoundsWrapper,
159 ) -> BroadcastedDeclareTransactionV3 {
160 BroadcastedDeclareTransactionV3 {
161 common: BroadcastedTransactionCommonV3 {
162 version: Felt::THREE,
163 signature: vec![],
164 nonce,
165 resource_bounds,
166 tip: Tip(0),
167 paymaster_data: vec![],
168 nonce_data_availability_mode: DataAvailabilityMode::L1,
169 fee_data_availability_mode: DataAvailabilityMode::L1,
170 },
171 contract_class,
172 sender_address,
173 compiled_class_hash,
174 account_deployment_data: vec![],
175 }
176 }
177
178 pub(crate) fn dummy_declare_tx_v3_with_hash() -> TransactionWithHash {
179 let declare_txn = broadcasted_declare_tx_v3_of_dummy_class(
180 dummy_contract_address(),
181 Felt::ZERO,
182 ResourceBoundsWrapper::new(
183 1, 1, 0, 0, 0, 0, ),
187 );
188 let sierra_hash =
189 ContractClass::Cairo1(declare_txn.contract_class.clone()).generate_hash().unwrap();
190
191 let tx_hash = BroadcastedDeclareTransaction::V3(Box::new(declare_txn.clone()))
192 .create_sn_api_declare(&DEVNET_DEFAULT_CHAIN_ID.to_felt())
193 .unwrap()
194 .tx_hash;
195
196 TransactionWithHash::new(
197 *tx_hash,
198 Transaction::Declare(DeclareTransaction::V3(DeclareTransactionV3::new(
199 &declare_txn,
200 sierra_hash,
201 ))),
202 )
203 }
204
205 pub(crate) fn cairo_0_account_without_validations() -> Cairo0ContractClass {
206 let account_json_path =
207 "../../contracts/test_artifacts/cairo0/account_without_validations/account.json";
208
209 Cairo0Json::raw_json_from_path(account_json_path).unwrap().into()
210 }
211
212 pub fn dummy_key_pair() -> KeyPair {
213 KeyPair { public_key: dummy_felt(), private_key: dummy_felt() }
214 }
215
216 pub fn test_invoke_transaction_v3(
217 account_address: ContractAddress,
218 contract_address: ContractAddress,
219 function_selector: Felt,
220 params: &[Felt],
221 nonce: u128,
222 resource_bounds: ResourceBoundsWrapper,
223 ) -> BroadcastedInvokeTransaction {
224 let mut calldata = vec![Felt::from(contract_address), function_selector];
226 calldata.push(params.len().into());
227 calldata.extend_from_slice(params);
228
229 BroadcastedInvokeTransaction::V3(BroadcastedInvokeTransactionV3 {
230 common: BroadcastedTransactionCommonV3 {
231 version: Felt::THREE,
232 signature: vec![],
233 nonce: Felt::from(nonce),
234 resource_bounds,
235 tip: Tip(0),
236 paymaster_data: vec![],
237 nonce_data_availability_mode:
238 starknet_api::data_availability::DataAvailabilityMode::L1,
239 fee_data_availability_mode:
240 starknet_api::data_availability::DataAvailabilityMode::L1,
241 },
242 sender_address: account_address,
243 calldata,
244 account_deployment_data: vec![],
245 })
246 }
247}
248
249#[cfg(any(test, feature = "test_utils"))]
250#[allow(clippy::unwrap_used)]
251pub mod exported_test_utils {
252 use starknet_types::contract_class::Cairo0ContractClass;
253 use starknet_types::contract_class::deprecated::json_contract_class::Cairo0Json;
254
255 pub fn dummy_cairo_l1l2_contract() -> Cairo0ContractClass {
256 let json_str =
257 std::fs::read_to_string("../../contracts/test_artifacts/cairo0/l1l2.json").unwrap();
258
259 Cairo0Json::raw_json_from_json_str(&json_str).unwrap().into()
260 }
261
262 pub fn dummy_cairo_0_contract_class() -> Cairo0ContractClass {
263 let json_str =
264 std::fs::read_to_string("../../contracts/test_artifacts/cairo0/simple_contract.json")
265 .unwrap();
266
267 Cairo0Json::raw_json_from_json_str(&json_str).unwrap().into()
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use super::get_storage_var_address;
274 use super::test_utils::{self};
275
276 #[test]
277 fn correct_simple_storage_var_address_generated() {
278 let expected_storage_var_address =
279 starknet_api::abi::abi_utils::get_storage_var_address("simple", &[]);
280 let generated_storage_var_address = get_storage_var_address("simple", &[]).unwrap();
281
282 assert_eq!(
283 expected_storage_var_address.0.key().to_bytes_be(),
284 generated_storage_var_address.to_felt().to_bytes_be()
285 );
286 }
287
288 #[test]
289 fn correct_complex_storage_var_address_generated() {
290 let expected_storage_var_address = starknet_api::abi::abi_utils::get_storage_var_address(
291 "complex",
292 &[test_utils::dummy_felt()],
293 );
294
295 let generated_storage_var_address =
296 get_storage_var_address("complex", &[test_utils::dummy_felt()]).unwrap();
297
298 assert_eq!(
299 expected_storage_var_address.0.key().to_bytes_be(),
300 generated_storage_var_address.to_felt().to_bytes_be()
301 );
302 }
303}