1use crate::{DecodedEvent, DynSolEvent, DynSolType, Error, Result, Specifier};
2use alloc::vec::Vec;
3use alloy_json_abi::Event;
4use alloy_primitives::{LogData, B256};
5
6#[allow(unknown_lints, unnameable_types)]
7mod sealed {
8 pub trait Sealed {}
9 impl Sealed for alloy_json_abi::Event {}
10}
11use sealed::Sealed;
12
13impl Specifier<DynSolEvent> for Event {
14 fn resolve(&self) -> Result<DynSolEvent> {
15 let mut indexed = Vec::with_capacity(self.inputs.len());
16 let mut body = Vec::with_capacity(self.inputs.len());
17 for param in &self.inputs {
18 let ty = param.resolve()?;
19 if param.indexed {
20 indexed.push(ty);
21 } else {
22 body.push(ty);
23 }
24 }
25 let topic_0 = if self.anonymous { None } else { Some(self.selector()) };
26
27 let num_topics = indexed.len() + topic_0.is_some() as usize;
28 if num_topics > 4 {
29 return Err(Error::TopicLengthMismatch { expected: 4, actual: num_topics });
30 }
31
32 Ok(DynSolEvent::new_unchecked(topic_0, indexed, DynSolType::Tuple(body)))
33 }
34}
35
36pub trait EventExt: Sealed {
41 fn decode_log_parts<I>(&self, topics: I, data: &[u8], validate: bool) -> Result<DecodedEvent>
57 where
58 I: IntoIterator<Item = B256>;
59
60 #[inline]
64 fn decode_log(&self, log: &LogData, validate: bool) -> Result<DecodedEvent> {
65 self.decode_log_parts(log.topics().iter().copied(), &log.data, validate)
66 }
67}
68
69impl EventExt for Event {
70 fn decode_log_parts<I>(&self, topics: I, data: &[u8], validate: bool) -> Result<DecodedEvent>
71 where
72 I: IntoIterator<Item = B256>,
73 {
74 self.resolve()?.decode_log_parts(topics, data, validate)
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::DynSolValue;
82 use alloy_json_abi::EventParam;
83 use alloy_primitives::{address, b256, bytes, hex, keccak256, Signed};
84
85 #[test]
86 fn empty() {
87 let mut event = Event { name: "MyEvent".into(), inputs: vec![], anonymous: false };
88
89 let values = event.decode_log_parts(None, &[], false).unwrap();
91 assert!(values.indexed.is_empty());
92 assert!(values.body.is_empty());
93
94 let err = event.decode_log_parts(None, &[], true).unwrap_err();
96 assert_eq!(err, Error::TopicLengthMismatch { expected: 1, actual: 0 });
97
98 let values = event.decode_log_parts(Some(keccak256("MyEvent()")), &[], true).unwrap();
99 assert!(values.indexed.is_empty());
100 assert!(values.body.is_empty());
101 event.anonymous = true;
102 let values = event.decode_log_parts(None, &[], false).unwrap();
103 assert!(values.indexed.is_empty());
104 assert!(values.body.is_empty());
105 let values = event.decode_log_parts(None, &[], true).unwrap();
106 assert!(values.indexed.is_empty());
107 assert!(values.body.is_empty());
108 }
109
110 #[test]
112 fn test_decoding_event() {
113 let event = Event {
114 name: "foo".into(),
115 inputs: vec![
116 EventParam { ty: "int256".into(), indexed: false, ..Default::default() },
117 EventParam { ty: "int256".into(), indexed: true, ..Default::default() },
118 EventParam { ty: "address".into(), indexed: false, ..Default::default() },
119 EventParam { ty: "address".into(), indexed: true, ..Default::default() },
120 EventParam { ty: "string".into(), indexed: true, ..Default::default() },
121 ],
122 anonymous: false,
123 };
124
125 let result = event
126 .decode_log_parts(
127 [
128 b256!("0x0000000000000000000000000000000000000000000000000000000000000000"),
129 b256!("0x0000000000000000000000000000000000000000000000000000000000000002"),
130 b256!("0x0000000000000000000000001111111111111111111111111111111111111111"),
131 b256!("0x00000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
132 b256!("0x00000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
133 b256!("0x00000000000000000ccccccccccccccccccccccccccccccccccccccccccccccc"),
134 ],
135 &hex!(
136 "
137 0000000000000000000000000000000000000000000000000000000000000003
138 0000000000000000000000002222222222222222222222222222222222222222
139 "
140 ),
141 false,
142 )
143 .unwrap();
144
145 assert_eq!(
146 result.body,
147 [
148 DynSolValue::Int(
149 Signed::from_be_bytes(hex!(
150 "0000000000000000000000000000000000000000000000000000000000000003"
151 )),
152 256
153 ),
154 DynSolValue::Address(address!("0x2222222222222222222222222222222222222222")),
155 ]
156 );
157 assert_eq!(
158 result.indexed,
159 [
160 DynSolValue::Int(
161 Signed::from_be_bytes(hex!(
162 "0000000000000000000000000000000000000000000000000000000000000002"
163 )),
164 256
165 ),
166 DynSolValue::Address(address!("0x1111111111111111111111111111111111111111")),
167 DynSolValue::FixedBytes(
168 b256!("0x00000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
169 32
170 ),
171 ]
172 )
173 }
174
175 #[test]
176 fn parse_log_whole() {
177 let correct_event = Event {
178 name: "Test".into(),
179 inputs: vec![
180 EventParam { ty: "(address,address)".into(), indexed: false, ..Default::default() },
181 EventParam { ty: "address".into(), indexed: true, ..Default::default() },
182 ],
183 anonymous: false,
184 };
185 let mut wrong_event = correct_event.clone();
187 wrong_event.inputs[0].indexed = true;
188 wrong_event.inputs[1].indexed = false;
189
190 let log = LogData::new_unchecked(
191 vec![
192 b256!("0xcf74b4e62f836eeedcd6f92120ffb5afea90e6fa490d36f8b81075e2a7de0cf7"),
193 b256!("0x0000000000000000000000000000000000000000000000000000000000012321"),
194 ],
195 bytes!(
196 "
197 0000000000000000000000000000000000000000000000000000000000012345
198 0000000000000000000000000000000000000000000000000000000000054321
199 "
200 ),
201 );
202
203 wrong_event.decode_log(&log, false).unwrap();
204 correct_event.decode_log(&log, false).unwrap();
207 correct_event.decode_log(&log, true).unwrap();
208 }
209}