ethrex_levm/opcode_handlers/
logging.rs1use std::mem;
7
8use crate::{
9 errors::{ExceptionalHalt, OpcodeResult, VMError},
10 gas_cost,
11 memory::calculate_memory_size,
12 opcode_handlers::OpcodeHandler,
13 utils::size_offset_to_usize,
14 vm::VM,
15};
16use ethrex_common::{H256, U256, types::Log};
17
18pub struct OpLogHandler<const N: usize>;
20impl<const N: usize> OpcodeHandler for OpLogHandler<N> {
21 #[inline(always)]
22 fn eval(vm: &mut VM<'_>) -> Result<OpcodeResult, VMError> {
23 if vm.current_call_frame.is_static {
24 return Err(ExceptionalHalt::OpcodeNotAllowedInStaticContext.into());
25 }
26
27 let [offset, len] = *vm.current_call_frame.stack.pop()?;
28 let topics = vm.current_call_frame.stack.pop::<N>()?.map(|topic| {
29 #[expect(unsafe_code)]
30 unsafe {
31 let mut hash = mem::transmute::<U256, H256>(topic);
32 hash.0.reverse();
33 hash
34 }
35 });
36 let (len, offset) = size_offset_to_usize(len, offset)?;
37
38 vm.current_call_frame.increase_consumed_gas(gas_cost::log(
39 calculate_memory_size(offset, len)?,
40 vm.current_call_frame.memory.len(),
41 len,
42 N,
43 )?)?;
44
45 let log = Log {
46 address: vm.current_call_frame.to,
47 topics: topics.into(),
48 data: vm.current_call_frame.memory.load_range(offset, len)?,
49 };
50 vm.tracer.log(&log)?;
51 vm.substate.add_log(log);
52
53 Ok(OpcodeResult::Continue)
54 }
55}