stratus/eth/primitives/
log.rs1use display_json::DebugAsJson;
2
3use crate::alias::AlloyLog;
4use crate::alias::AlloyLogData;
5use crate::alias::AlloyLogPrimitive;
6use crate::alias::RevmLog;
7use crate::eth::primitives::Address;
8use crate::eth::primitives::BlockNumber;
9use crate::eth::primitives::Bytes;
10use crate::eth::primitives::Hash;
11use crate::eth::primitives::Index;
12use crate::eth::primitives::LogTopic;
13use crate::eth::primitives::UnixTime;
14
15#[derive(DebugAsJson, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17#[cfg_attr(test, derive(fake::Dummy))]
18pub struct Log {
19 pub address: Address,
21
22 pub topic0: Option<LogTopic>,
24 pub topic1: Option<LogTopic>,
25 pub topic2: Option<LogTopic>,
26 pub topic3: Option<LogTopic>,
27
28 pub data: Bytes,
30}
31
32impl Log {
33 pub fn topics(&self) -> [Option<LogTopic>; 4] {
35 [self.topic0, self.topic1, self.topic2, self.topic3]
36 }
37
38 pub fn topics_non_empty(&self) -> Vec<LogTopic> {
40 self.topics().into_iter().flatten().collect()
41 }
42
43 pub fn to_alloy_log(
44 self,
45 block_hash: Hash,
46 block_number: BlockNumber,
47 block_timestamp: UnixTime,
48 transaction_hash: Hash,
49 transaction_index: Index,
50 log_index: Index,
51 ) -> AlloyLog {
52 AlloyLog {
53 inner: AlloyLogPrimitive {
54 address: self.address.into(),
55 data: AlloyLogData::new_unchecked(self.topics_non_empty().into_iter().map(Into::into).collect(), self.data.into()),
57 },
58 block_hash: Some(block_hash.into()),
59 block_number: Some(block_number.as_u64()),
60 block_timestamp: Some(*block_timestamp),
61 transaction_hash: Some(transaction_hash.into()),
62 transaction_index: Some(transaction_index.into()),
63 log_index: Some(log_index.into()),
64 removed: false,
65 }
66 }
67}
68
69impl From<RevmLog> for Log {
73 fn from(value: RevmLog) -> Self {
74 let (topics, data) = value.data.split();
75 let topics_len = topics.len();
76
77 let mut log = Self {
78 address: value.address.into(),
79 data: data.into(),
80 ..Default::default()
81 };
82
83 match topics_len {
85 4 => {
86 log.topic0 = Some(topics[0].into());
87 log.topic1 = Some(topics[1].into());
88 log.topic2 = Some(topics[2].into());
89 log.topic3 = Some(topics[3].into());
90 }
91 3 => {
92 log.topic0 = Some(topics[0].into());
93 log.topic1 = Some(topics[1].into());
94 log.topic2 = Some(topics[2].into());
95 }
96 2 => {
97 log.topic0 = Some(topics[0].into());
98 log.topic1 = Some(topics[1].into());
99 }
100 1 => {
101 log.topic0 = Some(topics[0].into());
102 }
103 _ => {}
104 }
105
106 log
107 }
108}
109
110impl From<AlloyLog> for Log {
111 fn from(value: AlloyLog) -> Self {
112 let topics = value.inner.topics().to_vec();
113 let topics_len = topics.len();
114
115 let mut log = Self {
116 address: value.inner.address.into(),
117 data: value.inner.data.data.into(),
118 ..Default::default()
119 };
120
121 match topics_len {
123 4 => {
124 log.topic0 = Some(topics[0].into());
125 log.topic1 = Some(topics[1].into());
126 log.topic2 = Some(topics[2].into());
127 log.topic3 = Some(topics[3].into());
128 }
129 3 => {
130 log.topic0 = Some(topics[0].into());
131 log.topic1 = Some(topics[1].into());
132 log.topic2 = Some(topics[2].into());
133 }
134 2 => {
135 log.topic0 = Some(topics[0].into());
136 log.topic1 = Some(topics[1].into());
137 }
138 1 => {
139 log.topic0 = Some(topics[0].into());
140 }
141 _ => {}
142 }
143
144 log
145 }
146}