#![deny(warnings)] use cairo_lang_starknet::casm_contract_class::CasmContractClass; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use cairo_vm::{felt::Felt252, vm::runners::builtin_runner::RANGE_CHECK_BUILTIN_NAME}; use num_traits::Zero; use starknet_contract_class::EntryPointType; use starknet_rs::definitions::block_context::BlockContext; use starknet_rs::{ definitions::constants::TRANSACTION_VERSION, execution::{ execution_entry_point::ExecutionEntryPoint, CallInfo, CallType, TransactionExecutionContext, }, services::api::contract_classes::deprecated_contract_class::ContractClass, state::cached_state::CachedState, state::{in_memory_state_reader::InMemoryStateReader, ExecutionResourcesManager}, utils::{Address, ClassHash}, }; use std::{collections::HashMap, path::PathBuf}; #[test] fn integration_test() { // --------------------------------------------------------- // Create program and entry point types for contract class // --------------------------------------------------------- let path = PathBuf::from("starknet_programs/fibonacci.json"); let contract_class = ContractClass::try_from(path).unwrap(); let entry_points_by_type = contract_class.entry_points_by_type().clone(); let fib_entrypoint_selector = entry_points_by_type .get(&EntryPointType::External) .unwrap() .get(0) .unwrap() .selector() .clone(); //* -------------------------------------------- //* Create state reader with class hash data //* -------------------------------------------- let mut contract_class_cache = HashMap::new(); // ------------ contract data -------------------- let address = Address(1111.into()); let class_hash: ClassHash = [1; 32]; let nonce = Felt252::zero(); contract_class_cache.insert(class_hash, contract_class); let mut state_reader = InMemoryStateReader::default(); state_reader .address_to_class_hash_mut() .insert(address.clone(), class_hash); state_reader .address_to_nonce_mut() .insert(address.clone(), nonce); //* --------------------------------------- //* Create state with previous data //* --------------------------------------- let mut state = CachedState::new(state_reader, Some(contract_class_cache), None); //* ------------------------------------ //* Create execution entry point //* ------------------------------------ let calldata = [1.into(), 1.into(), 10.into()].to_vec(); let caller_address = Address(0000.into()); let entry_point_type = EntryPointType::External; let exec_entry_point = ExecutionEntryPoint::new( address, calldata.clone(), fib_entrypoint_selector.clone(), caller_address, entry_point_type, Some(CallType::Delegate), Some(class_hash), 0, ); //* -------------------- //* Execute contract //* --------------------- let block_context = BlockContext::default(); let mut tx_execution_context = TransactionExecutionContext::new( Address(0.into()), Felt252::zero(), Vec::new(), 0, 10.into(), block_context.invoke_tx_max_n_steps(), TRANSACTION_VERSION.clone(), ); let mut resources_manager = ExecutionResourcesManager::default(); let expected_call_info = CallInfo { caller_address: Address(0.into()), call_type: Some(CallType::Delegate), contract_address: Address(1111.into()), entry_point_selector: Some(fib_entrypoint_selector), entry_point_type: Some(EntryPointType::External), calldata, retdata: [144.into()].to_vec(), class_hash: Some(class_hash), execution_resources: ExecutionResources { n_steps: 94, ..Default::default() }, ..Default::default() }; assert_eq!( exec_entry_point .execute( &mut state, &block_context, &mut resources_manager, &mut tx_execution_context, false, ) .unwrap(), expected_call_info ); } #[test] fn integration_test_cairo1() { // Create program and entry point types for contract class let program_data = include_bytes!("../starknet_programs/cairo1/fibonacci.casm"); let contract_class: CasmContractClass = serde_json::from_slice(program_data).unwrap(); let entrypoints = contract_class.clone().entry_points_by_type; let fib_entrypoint_selector = &entrypoints.external.get(0).unwrap().selector; // Create state reader with class hash data let mut contract_class_cache = HashMap::new(); let address = Address(1111.into()); let class_hash: ClassHash = [1; 32]; let nonce = Felt252::zero(); contract_class_cache.insert(class_hash, contract_class); let mut state_reader = InMemoryStateReader::default(); state_reader .address_to_class_hash_mut() .insert(address.clone(), class_hash); state_reader .address_to_nonce_mut() .insert(address.clone(), nonce); // Create state from the state_reader and contract cache. let mut state = CachedState::new(state_reader, None, Some(contract_class_cache)); // Create an execution entry point let calldata = [0.into(), 1.into(), 12.into()].to_vec(); let caller_address = Address(0000.into()); let entry_point_type = EntryPointType::External; let exec_entry_point = ExecutionEntryPoint::new( address, calldata.clone(), Felt252::new(fib_entrypoint_selector.clone()), caller_address, entry_point_type, Some(CallType::Delegate), Some(class_hash), 100000, ); // Execute the entrypoint let block_context = BlockContext::default(); let mut tx_execution_context = TransactionExecutionContext::new( Address(0.into()), Felt252::zero(), Vec::new(), 0, 10.into(), block_context.invoke_tx_max_n_steps(), TRANSACTION_VERSION.clone(), ); let mut resources_manager = ExecutionResourcesManager::default(); // expected results let expected_call_info = CallInfo { caller_address: Address(0.into()), call_type: Some(CallType::Delegate), contract_address: Address(1111.into()), entry_point_selector: Some(Felt252::new(fib_entrypoint_selector)), entry_point_type: Some(EntryPointType::External), calldata, retdata: [144.into()].to_vec(), execution_resources: ExecutionResources { n_steps: 421, n_memory_holes: 1, builtin_instance_counter: HashMap::from([(RANGE_CHECK_BUILTIN_NAME.to_string(), 15)]), }, class_hash: Some(class_hash), gas_consumed: 35550, ..Default::default() }; assert_eq!( exec_entry_point .execute( &mut state, &block_context, &mut resources_manager, &mut tx_execution_context, false, ) .unwrap(), expected_call_info ); }