diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index cabaa3220f..0c577d2e32 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -13,13 +13,14 @@ use cairo_native::starknet::{ use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use starknet_api::core::{ContractAddress, EntryPointSelector}; use starknet_api::state::StorageKey; +use starknet_api::transaction::{EventContent, EventData, EventKey}; 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::SyscallSelector; +use crate::execution::syscalls::{exceeds_event_size_limit, SyscallSelector}; use crate::state::state_api::State; pub struct NativeSyscallHandler<'state> { @@ -236,11 +237,33 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn emit_event( &mut self, - _keys: &[Felt], - _data: &[Felt], - _remaining_gas: &mut u128, + keys: &[Felt], + data: &[Felt], + remaining_gas: &mut u128, ) -> SyscallResult<()> { - todo!("Implement emit_event syscall."); + self.substract_syscall_gas_cost( + remaining_gas, + SyscallSelector::EmitEvent, + self.context.gas_costs().emit_event_gas_cost, + )?; + + let order = self.context.n_emitted_events; + let event = EventContent { + keys: keys.iter().copied().map(EventKey).collect(), + data: EventData(data.to_vec()), + }; + + exceeds_event_size_limit( + self.context.versioned_constants(), + self.context.n_emitted_events + 1, + &event, + ) + .expect("Number of events exceeded the size limit."); + + self.events.push(OrderedEvent { order, event }); + self.context.n_emitted_events += 1; + + Ok(()) } fn send_message_to_l1( diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/emit_event.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/emit_event.rs index 3913e47014..05e9230e41 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/emit_event.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/emit_event.rs @@ -24,11 +24,11 @@ const DATA: [Felt; 3] = [ ]; const N_EMITTED_EVENTS: [Felt; 1] = [Felt::from_hex_unchecked("0x1")]; +#[test_case(FeatureContract::TestContract(CairoVersion::Native), 58930; "Native")] #[test_case(FeatureContract::TestContract(CairoVersion::Cairo1), 48930; "VM")] fn positive_flow(test_contract: FeatureContract, expected_gas: u64) { - // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion - // works. - let call_info = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &DATA).unwrap(); + let call_info = emit_events(test_contract, &N_EMITTED_EVENTS, &KEYS, &DATA) + .expect("emit_events failed with valued parameters"); let event = EventContent { keys: KEYS.into_iter().map(EventKey).collect(), data: EventData(DATA.to_vec()), @@ -44,6 +44,7 @@ fn positive_flow(test_contract: FeatureContract, expected_gas: u64) { ); } +#[test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")] #[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")] fn data_length_exceeds_limit(test_contract: FeatureContract) { let versioned_constants = VersionedConstants::create_for_testing(); @@ -58,6 +59,7 @@ fn data_length_exceeds_limit(test_contract: FeatureContract) { assert!(error.to_string().contains(&expected_error.to_string())); } +#[test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")] #[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")] fn keys_length_exceeds_limit(test_contract: FeatureContract) { let versioned_constants = VersionedConstants::create_for_testing(); @@ -73,6 +75,7 @@ fn keys_length_exceeds_limit(test_contract: FeatureContract) { assert!(error.to_string().contains(&expected_error.to_string())); } +#[test_case(FeatureContract::TestContract(CairoVersion::Native); "Native")] #[test_case(FeatureContract::TestContract(CairoVersion::Cairo1); "VM")] fn event_number_exceeds_limit(test_contract: FeatureContract) { let versioned_constants = VersionedConstants::create_for_testing();