diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index 1d5692aec12..98a2aa9df1a 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -10,14 +10,18 @@ use cairo_native::starknet::{ SyscallResult, U256, }; +use cairo_native::starknet_stub::encode_str_as_felts; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; use crate::execution::call_info::{CallInfo, OrderedEvent, OrderedL2ToL1Message, Retdata}; use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionContext}; -use crate::execution::native::utils::encode_str_as_felts; -use crate::execution::syscalls::hint_processor::{SyscallCounter, OUT_OF_GAS_ERROR}; +use crate::execution::syscalls::hint_processor::{ + SyscallCounter, + SyscallExecutionError, + OUT_OF_GAS_ERROR, +}; use crate::execution::syscalls::SyscallSelector; use crate::state::state_api::State; @@ -98,7 +102,6 @@ impl<'state> NativeSyscallHandler<'state> { /// handling all gas-related logics and additional metadata such as `SyscallCounter`). The /// difference for native execution is that we need to explicitly call this method at the /// beginning of each syscall. - #[allow(dead_code)] fn pre_execute_syscall( &mut self, remaining_gas: &mut u128, @@ -185,21 +188,59 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn storage_read( &mut self, - _address_domain: u32, - _address: Felt, - _remaining_gas: &mut u128, + address_domain: u32, + address: Felt, + remaining_gas: &mut u128, ) -> SyscallResult { - todo!("Implement storage_read syscall."); + self.pre_execute_syscall( + remaining_gas, + SyscallSelector::StorageRead, + self.context.gas_costs().storage_read_gas_cost, + )?; + + if address_domain != 0 { + let address_domain = Felt::from(address_domain); + let err = SyscallExecutionError::InvalidAddressDomain { address_domain }; + return Err(encode_str_as_felts(&err.to_string())); + } + + let key = StorageKey::try_from(address).map_err(|e| encode_str_as_felts(&e.to_string()))?; + + let read_result = self.state.get_storage_at(self.call.storage_address, key); + let value = read_result.map_err(|e| encode_str_as_felts(&e.to_string()))?; + + self.accessed_keys.insert(key); + self.read_values.push(value); + + Ok(value) } fn storage_write( &mut self, - _address_domain: u32, - _address: Felt, - _value: Felt, - _remaining_gas: &mut u128, + address_domain: u32, + address: Felt, + value: Felt, + remaining_gas: &mut u128, ) -> SyscallResult<()> { - todo!("Implement storage_write syscall."); + self.pre_execute_syscall( + remaining_gas, + SyscallSelector::StorageWrite, + self.context.gas_costs().storage_write_gas_cost, + )?; + + if address_domain != 0 { + let address_domain = Felt::from(address_domain); + let err = SyscallExecutionError::InvalidAddressDomain { address_domain }; + return Err(encode_str_as_felts(&err.to_string())); + } + + let key = StorageKey::try_from(address).map_err(|e| encode_str_as_felts(&e.to_string()))?; + self.accessed_keys.insert(key); + + let write_result = self.state.set_storage_at(self.call.storage_address, key, value); + write_result.map_err(|e| encode_str_as_felts(&e.to_string()))?; + + Ok(()) } fn emit_event( diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/storage_read_write.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/storage_read_write.rs index dbc85fff6ba..bebde966a44 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/storage_read_write.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/storage_read_write.rs @@ -13,6 +13,10 @@ use crate::test_utils::contracts::FeatureContract; use crate::test_utils::initial_test_state::test_state; use crate::test_utils::{trivial_external_entry_point_new, CairoVersion, BALANCE}; +#[cfg_attr( + feature = "cairo_native", + test_case(FeatureContract::TestContract(CairoVersion::Native), 27290; "Native") +)] #[test_case(FeatureContract::TestContract(CairoVersion::Cairo1), REQUIRED_GAS_STORAGE_READ_WRITE_TEST; "VM")] fn test_storage_read_write(test_contract: FeatureContract, expected_gas: u64) { let chain_info = &ChainInfo::create_for_testing();