1use crate::{masm::MemoryInfo, wasm::ToLSBytes, Error, Function, Result};
4
5impl Function {
6 fn data(&mut self) -> Result<(i32, i32)> {
14 let buffer: Vec<u8> = self.masm.buffer().into();
15
16 let data_len = self.backtrace.popn(2).concat().len();
21 self.masm.decrement_sp(2)?;
22
23 let data = &buffer[(buffer.len() - data_len)..];
24 *self.masm.buffer_mut() = buffer[..(buffer.len() - data_len)].into();
25
26 if !(0x5e..0x8f).contains(&data[0]) {
32 return Err(Error::InvalidDataOffset(data[0].into()));
33 }
34
35 let offset_len = (data[0] - 0x5f) as usize;
36 tracing::trace!("offset len: {offset_len}");
37 let offset = {
38 let mut bytes = [0; 4];
39 bytes[(4 - offset_len)..].copy_from_slice(&data[1..(offset_len + 1)]);
40 bytes.reverse();
41 i32::from_le_bytes(bytes)
42 };
43 tracing::debug!("log offset: {:?}", offset);
44
45 if !(0x5e..0x8f).contains(&data[offset_len + 1]) {
47 return Err(Error::InvalidDataOffset(data[offset_len + 1].into()));
48 }
49 let size = {
50 let mut bytes = [0; 4];
52 let size_bytes = &data[(offset_len + 2)..];
53 bytes[..size_bytes.len()].copy_from_slice(size_bytes);
54 i32::from_le_bytes(bytes)
55 };
56
57 tracing::debug!("log size: {:?}", size);
58 Ok((offset, size))
59 }
60
61 pub fn log(&mut self, count: usize) -> Result<()> {
63 let (offset, size) = self.data()?;
64 let data = self.env.data.load(offset, size as usize)?;
65
66 let MemoryInfo { offset, size } = self.masm.memory_write_bytes(&data)?;
68
69 self.masm.push(&size.to_ls_bytes())?;
71 self.masm.push(&offset)?;
72
73 match count {
75 0 => self.masm._log0(),
76 1 => self.masm._log1(),
77 2 => self.masm._log2(),
78 3 => self.masm._log3(),
79 4 => self.masm._log4(),
80 _ => unreachable!("invalid topics"),
81 }?;
82
83 Ok(())
84 }
85
86 pub fn revert(&mut self, count: usize) -> Result<()> {
88 let mut message = Vec::<Vec<u8>>::default();
89 for slot in 0..count {
90 let (offset, size) = self.data()?;
91 let size = size as usize;
92 let data = self.env.data.load(offset, size)?;
93
94 self.masm.push(&data)?;
95 if slot == 0 {
96 self.masm._push0()?;
97 } else {
98 self.masm.push(&slot.to_ls_bytes())?;
99 }
100 self.masm._mstore()?;
101 message.push(data);
102 }
103
104 tracing::debug!(
105 "revert message: {}",
106 String::from_utf8_lossy(&message.into_iter().flatten().collect::<Vec<u8>>())
107 );
108
109 self.masm.push(&(count * 32).to_ls_bytes())?;
110 self.masm._push0()?;
111
112 self.masm._revert()?;
114 Ok(())
115 }
116}