solabi/
abi.rs

1//! Solidity ABI descriptors.
2
3pub 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
11/// A Solidity ABI - i.e. a vector of descriptors.
12pub type Abi = Vec<Descriptor>;
13
14/// A Solidity ABI descriptor.
15#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
16#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
17pub enum Descriptor {
18    /// A function.
19    Function(FunctionDescriptor),
20    /// A constructor.
21    Constructor(ConstructorDescriptor),
22    /// A "receive Ether" function.
23    Receive,
24    /// A fallback function.
25    Fallback(StateMutability),
26    /// An event.
27    Event(EventDescriptor),
28    /// An error.
29    Error(ErrorDescriptor),
30}
31
32/// A function descriptor.
33#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
34#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
35pub struct FunctionDescriptor {
36    /// The name of the function.
37    pub name: String,
38    /// The function input parameters.
39    pub inputs: Vec<Parameter>,
40    /// The function ouput parameters (i.e. `returns` values).
41    pub outputs: Vec<Parameter>,
42    /// The function state mutability.
43    pub state_mutability: StateMutability,
44}
45
46impl FunctionDescriptor {
47    /// Returns the error decriptor's canonical formatter.
48    pub fn canonical(&self) -> Canonical<'_, Self> {
49        Canonical(self)
50    }
51
52    /// Returns a display formatter for the full function signature.
53    ///
54    /// This is different than its canonical representation in that it also
55    /// includes the return types. Function selectors are computed by hashing
56    /// the canonical representation without the return types.
57    pub fn signature(&self) -> Signature<'_> {
58        Signature(self)
59    }
60
61    /// Computes the selector the error type.
62    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/// A constructor descriptor.
77#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
78#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
79pub struct ConstructorDescriptor {
80    /// The function input parameters.
81    pub inputs: Vec<Parameter>,
82    /// The function state mutability.
83    pub state_mutability: StateMutability,
84}
85
86/// An event descriptor.
87#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
88#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
89pub struct EventDescriptor {
90    /// The name of the event.
91    pub name: String,
92    /// The event fields.
93    pub inputs: Vec<EventField>,
94    /// Whether or not the event is anonymous.
95    pub anonymous: bool,
96}
97
98impl EventDescriptor {
99    /// Returns the error decriptor's canonical formatter.
100    pub fn canonical(&self) -> Canonical<'_, Self> {
101        Canonical(self)
102    }
103
104    /// Computes the selector the error type.
105    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/// An error descriptor.
124#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
125#[serde(try_from = "json::Descriptor", into = "json::Descriptor")]
126pub struct ErrorDescriptor {
127    /// The name of the event.
128    pub name: String,
129    /// The event fields.
130    pub inputs: Vec<Field>,
131}
132
133impl ErrorDescriptor {
134    /// Returns the error decriptor's canonical formatter.
135    pub fn canonical(&self) -> Canonical<'_, Self> {
136        Canonical(self)
137    }
138
139    /// Computes the selector the error type.
140    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/// A field.
155#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
156#[serde(try_from = "json::Field", into = "json::Field")]
157pub struct Field {
158    /// The name of the field.
159    pub name: String,
160    /// The canonical type of the field.
161    pub kind: ValueKind,
162    /// The components of a tuple.
163    ///
164    /// This is for information purposes of the individual fields.
165    pub components: Option<Vec<Field>>,
166    /// The internal type name.
167    ///
168    /// This is for informational purposes (can be useful, for example, in the
169    /// context of code generation of user defined types and structures).
170    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/// A input or output parameter.
180#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
181#[serde(try_from = "json::Field", into = "json::Field")]
182pub struct Parameter {
183    /// The field.
184    pub field: Field,
185    /// The type name used for computing function selectors.
186    ///
187    /// Typically, this can be determined by the parameter type (i.e. the `kind`
188    /// field). However, specifically for `library` ABIs, this is not the case.
189    /// Specifically:
190    /// - `enum` parameters use the type name instead of `uint8`
191    /// - `storage` parameters have " storage" appended to the canonical name.
192    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/// An event field.
205#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
206#[serde(try_from = "json::Field", into = "json::Field")]
207pub struct EventField {
208    /// The field.
209    pub field: Field,
210    /// Whether or not the field is part of the EVM log's topics.
211    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/// Code execution state mutability.
221#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
222#[serde(rename_all = "lowercase")]
223pub enum StateMutability {
224    /// Function that executes without reading blockchain state.
225    Pure,
226    /// Function that reads, but does not modify, blockchain state.
227    View,
228    /// Function that potentially modifies blockchain state, but cannot receive
229    /// any Ether value.
230    NonPayable,
231    /// Function that potentially modifies blockchain state, and can receive
232    /// Ether value.
233    Payable,
234}
235
236impl StateMutability {
237    /// Returns the state mutability given constant and payable flags.
238    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
247/// Formatter for the canonical representation of an ABI descriptor.
248///
249/// This is the string representation that is used for hashing in order to
250/// compute selectors.
251pub struct Canonical<'a, T>(&'a T);
252
253/// A function signature formatter.
254pub 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}