1pub mod declaration;
4mod json;
5
6use crate::{function::Selector, primitive::Word, value::ValueKind};
7use ethprim::Hasher;
8use serde::{Deserialize, Serialize};
9use std::fmt::{self, Display, Formatter, Write as _};
10
11pub type Abi = Vec<Descriptor>;
13
14#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
16#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
17pub enum Descriptor {
18 Function(FunctionDescriptor),
20 Constructor(ConstructorDescriptor),
22 Receive,
24 Fallback(StateMutability),
26 Event(EventDescriptor),
28 Error(ErrorDescriptor),
30}
31
32#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
34#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
35pub struct FunctionDescriptor {
36 pub name: String,
38 pub inputs: Vec<Parameter>,
40 pub outputs: Vec<Parameter>,
42 pub state_mutability: StateMutability,
44}
45
46impl FunctionDescriptor {
47 pub fn canonical(&self) -> Canonical<'_, Self> {
49 Canonical(self)
50 }
51
52 pub fn signature(&self) -> Signature<'_> {
58 Signature(self)
59 }
60
61 pub fn selector(&self) -> Selector {
63 let mut hasher = Hasher::new();
64 write!(&mut hasher, "{}", self.canonical()).unwrap();
65 selector(hasher)
66 }
67}
68
69impl Display for Canonical<'_, FunctionDescriptor> {
70 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
71 f.write_str(&self.0.name)?;
72 fmt_fields(f, &self.0.inputs)
73 }
74}
75
76#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
78#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
79pub struct ConstructorDescriptor {
80 pub inputs: Vec<Parameter>,
82 pub state_mutability: StateMutability,
84}
85
86#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
88#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
89pub struct EventDescriptor {
90 pub name: String,
92 pub inputs: Vec<EventField>,
94 pub anonymous: bool,
96}
97
98impl EventDescriptor {
99 pub fn canonical(&self) -> Canonical<'_, Self> {
101 Canonical(self)
102 }
103
104 pub fn selector(&self) -> Option<Word> {
106 if self.anonymous {
107 return None;
108 }
109
110 let mut hasher = Hasher::new();
111 write!(&mut hasher, "{}", self.canonical()).unwrap();
112 Some(topic(hasher))
113 }
114}
115
116impl Display for Canonical<'_, EventDescriptor> {
117 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
118 f.write_str(&self.0.name)?;
119 fmt_fields(f, &self.0.inputs)
120 }
121}
122
123#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
125#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
126pub struct ErrorDescriptor {
127 pub name: String,
129 pub inputs: Vec<Field>,
131}
132
133impl ErrorDescriptor {
134 pub fn canonical(&self) -> Canonical<'_, Self> {
136 Canonical(self)
137 }
138
139 pub fn selector(&self) -> Selector {
141 let mut hasher = Hasher::new();
142 write!(&mut hasher, "{}", self.canonical()).unwrap();
143 selector(hasher)
144 }
145}
146
147impl Display for Canonical<'_, ErrorDescriptor> {
148 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
149 f.write_str(&self.0.name)?;
150 fmt_fields(f, &self.0.inputs)
151 }
152}
153
154#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
156#[serde(try_from = "json::Field", into = "json::Field")]
157pub struct Field {
158 pub name: String,
160 pub kind: ValueKind,
162 pub components: Option<Vec<Field>>,
166 pub internal_type: Option<String>,
171}
172
173impl Display for Canonical<'_, Field> {
174 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
175 write!(f, "{}", self.0.kind)
176 }
177}
178
179#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
181#[serde(try_from = "json::Field", into = "json::Field")]
182pub struct Parameter {
183 pub field: Field,
185 pub kind_name: Option<String>,
193}
194
195impl Display for Canonical<'_, Parameter> {
196 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
197 match &self.0.kind_name {
198 Some(kind_name) => f.write_str(kind_name),
199 None => write!(f, "{}", Canonical(&self.0.field)),
200 }
201 }
202}
203
204#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
206#[serde(try_from = "json::Field", into = "json::Field")]
207pub struct EventField {
208 pub field: Field,
210 pub indexed: bool,
212}
213
214impl Display for Canonical<'_, EventField> {
215 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
216 write!(f, "{}", Canonical(&self.0.field))
217 }
218}
219
220#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
222#[serde(rename_all = "lowercase")]
223pub enum StateMutability {
224 Pure,
226 View,
228 NonPayable,
231 Payable,
234}
235
236impl StateMutability {
237 fn with_flags(constant: bool, payable: bool) -> StateMutability {
239 match (constant, payable) {
240 (_, true) => Self::Payable,
241 (false, _) => Self::NonPayable,
242 (true, _) => Self::View,
243 }
244 }
245}
246
247pub struct Canonical<'a, T>(&'a T);
252
253pub struct Signature<'a>(&'a FunctionDescriptor);
255
256impl Display for Signature<'_> {
257 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
258 write!(f, "{}:", Canonical(self.0))?;
259 fmt_fields(f, &self.0.outputs)
260 }
261}
262
263fn fmt_fields<'a, T, I>(f: &mut Formatter, fields: I) -> fmt::Result
264where
265 T: 'a,
266 Canonical<'a, T>: Display,
267 I: IntoIterator<Item = &'a T> + 'a,
268{
269 f.write_str("(")?;
270 for (i, field) in fields.into_iter().enumerate() {
271 if i != 0 {
272 f.write_str(",")?;
273 }
274 write!(f, "{}", Canonical(field))?;
275 }
276 f.write_str(")")
277}
278
279fn selector(hasher: Hasher) -> Selector {
280 let digest = hasher.finalize();
281 Selector(digest[..4].try_into().unwrap())
282}
283
284fn topic(hasher: Hasher) -> [u8; 32] {
285 *hasher.finalize()
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291 use hex_literal::hex;
292
293 #[test]
294 fn function_selector() {
295 let function =
296 FunctionDescriptor::parse_declaration("function transfer(address to, uint value)")
297 .unwrap();
298 assert_eq!(function.selector(), hex!("a9059cbb"));
299 }
300
301 #[test]
302 fn function_signature() {
303 let function = FunctionDescriptor::parse_declaration(
304 "function transfer(address to, uint value) returns (bool)",
305 )
306 .unwrap();
307 assert_eq!(
308 function.signature().to_string(),
309 "transfer(address,uint256):(bool)",
310 );
311 }
312
313 #[test]
314 fn event_selector() {
315 let event = EventDescriptor::parse_declaration(
316 "event Transfer(address indexed to, address indexed from, uint256 value)",
317 )
318 .unwrap();
319 assert_eq!(
320 event.selector().unwrap(),
321 hex!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
322 );
323 }
324
325 #[test]
326 fn anonymous_event_selector() {
327 let event = EventDescriptor::parse_declaration("event Foo() anonymous").unwrap();
328 assert!(event.selector().is_none());
329 }
330
331 #[test]
332 fn error_selector() {
333 let error = ErrorDescriptor::parse_declaration("error Error(string message)").unwrap();
334 assert_eq!(error.selector(), hex!("08c379a0"));
335 }
336}