alloy_json_abi/
abi.rs

1use crate::{
2    to_sol::{SolPrinter, ToSolConfig},
3    AbiItem, Constructor, Error, Event, Fallback, Function, Receive,
4};
5use alloc::{collections::btree_map, string::String, vec::Vec};
6use alloy_primitives::Bytes;
7use btree_map::BTreeMap;
8use core::{fmt, iter, iter::Flatten};
9use serde::{
10    de::{MapAccess, SeqAccess, Visitor},
11    ser::SerializeSeq,
12    Deserialize, Deserializer, Serialize,
13};
14
15macro_rules! set_if_none {
16    ($opt:expr, $val:expr) => { set_if_none!(stringify!($opt) => $opt, $val) };
17    (@serde $opt:expr, $val:expr) => { set_if_none!(serde::de::Error::duplicate_field(stringify!($opt)) => $opt, $val) };
18    ($name:expr => $opt:expr, $val:expr) => {{
19        if $opt.is_some() {
20            return Err($name)
21        }
22        $opt = Some($val);
23    }};
24}
25
26macro_rules! entry_and_push {
27    ($map:expr, $v:expr) => {
28        $map.entry($v.name.clone()).or_default().push($v.into_owned())
29    };
30}
31
32type FlattenValues<'a, V> = Flatten<btree_map::Values<'a, String, Vec<V>>>;
33type FlattenValuesMut<'a, V> = Flatten<btree_map::ValuesMut<'a, String, Vec<V>>>;
34type FlattenIntoValues<V> = Flatten<btree_map::IntoValues<String, Vec<V>>>;
35
36/// The JSON contract ABI, as specified in the [Solidity ABI spec][ref].
37///
38/// [ref]: https://docs.soliditylang.org/en/latest/abi-spec.html#json
39#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
40pub struct JsonAbi {
41    /// The constructor function.
42    pub constructor: Option<Constructor>,
43    /// The fallback function.
44    pub fallback: Option<Fallback>,
45    /// The receive function.
46    pub receive: Option<Receive>,
47    /// The functions, indexed by the function name.
48    pub functions: BTreeMap<String, Vec<Function>>,
49    /// The events, indexed by the event name.
50    pub events: BTreeMap<String, Vec<Event>>,
51    /// The errors, indexed by the error name.
52    pub errors: BTreeMap<String, Vec<Error>>,
53}
54
55impl<'a> FromIterator<AbiItem<'a>> for JsonAbi {
56    fn from_iter<T: IntoIterator<Item = AbiItem<'a>>>(iter: T) -> Self {
57        let mut abi = Self::new();
58        for item in iter {
59            let _ = abi.insert_item(item);
60        }
61        abi
62    }
63}
64
65impl JsonAbi {
66    /// Creates an empty ABI object.
67    #[inline]
68    pub fn new() -> Self {
69        Self::default()
70    }
71
72    /// Parse a [Human-Readable ABI] string into a JSON object.
73    ///
74    /// [Human-Readable ABI]: https://docs.ethers.org/v5/api/utils/abi/formats/#abi-formats--human-readable-abi
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// # use alloy_json_abi::JsonAbi;
80    /// assert_eq!(JsonAbi::parse([])?, JsonAbi::new());
81    ///
82    /// let abi = JsonAbi::parse([
83    ///     "constructor(string symbol, string name)",
84    ///     "function transferFrom(address from, address to, uint value)",
85    ///     "function balanceOf(address owner)(uint balance)",
86    ///     "event Transfer(address indexed from, address indexed to, address value)",
87    ///     "error InsufficientBalance(address owner, uint balance)",
88    ///     "function addPerson(tuple(string, uint16) person)",
89    ///     "function addPeople(tuple(string, uint16)[] person)",
90    ///     "function getPerson(uint id)(tuple(string, uint16))",
91    ///     "event PersonAdded(uint indexed id, tuple(string, uint16) person)",
92    /// ])?;
93    /// assert_eq!(abi.len(), 9);
94    /// # Ok::<(), alloy_sol_type_parser::Error>(())
95    /// ```
96    pub fn parse<'a, I: IntoIterator<Item = &'a str>>(strings: I) -> parser::Result<Self> {
97        let mut abi = Self::new();
98        for string in strings {
99            let item = AbiItem::parse(string)?;
100            abi.insert_item(item)
101                .map_err(|s| parser::Error::_new("duplicate JSON ABI field: ", &s))?;
102        }
103        Ok(abi)
104    }
105
106    /// Parse a JSON string into an ABI object.
107    ///
108    /// This is a convenience wrapper around [`serde_json::from_str`].
109    #[cfg(feature = "serde_json")]
110    #[inline]
111    pub fn from_json_str(json: &str) -> Result<Self, serde_json::Error> {
112        serde_json::from_str(json)
113    }
114
115    /// Loads contract from a JSON [Reader](std::io::Read).
116    ///
117    /// This is a convenience wrapper around [`serde_json::from_str`].
118    #[cfg(all(feature = "std", feature = "serde_json"))]
119    pub fn load<T: std::io::Read>(mut reader: T) -> Result<Self, serde_json::Error> {
120        // https://docs.rs/serde_json/latest/serde_json/fn.from_reader.html
121        // serde_json docs recommend buffering the whole reader to a string
122        // This also prevents a borrowing issue when deserializing from a reader
123        let mut json = String::with_capacity(1024);
124        reader.read_to_string(&mut json).map_err(serde_json::Error::io)?;
125
126        Self::from_json_str(&json)
127    }
128
129    /// Returns the total number of items (of any type).
130    pub fn len(&self) -> usize {
131        self.constructor.is_some() as usize
132            + self.fallback.is_some() as usize
133            + self.receive.is_some() as usize
134            + self.functions.values().map(Vec::len).sum::<usize>()
135            + self.events.values().map(Vec::len).sum::<usize>()
136            + self.errors.values().map(Vec::len).sum::<usize>()
137    }
138
139    /// Returns true if the ABI contains no items.
140    #[inline]
141    pub fn is_empty(&self) -> bool {
142        self.len() == 0
143    }
144
145    /// Returns an iterator over all of the items in the ABI.
146    #[inline]
147    pub fn items(&self) -> Items<'_> {
148        self.items_with_len(self.len())
149    }
150
151    // `len` must be `self.len()`
152    #[inline]
153    fn items_with_len(&self, len: usize) -> Items<'_> {
154        Items {
155            len,
156            constructor: self.constructor.as_ref(),
157            fallback: self.fallback.as_ref(),
158            receive: self.receive.as_ref(),
159            functions: self.functions(),
160            events: self.events(),
161            errors: self.errors(),
162        }
163    }
164
165    /// Returns an iterator over all of the items in the ABI.
166    #[inline]
167    pub fn into_items(self) -> IntoItems {
168        IntoItems {
169            len: self.len(),
170            constructor: self.constructor,
171            fallback: self.fallback,
172            receive: self.receive,
173            functions: self.functions.into_values().flatten(),
174            events: self.events.into_values().flatten(),
175            errors: self.errors.into_values().flatten(),
176        }
177    }
178
179    /// Formats this JSON ABI as a Solidity interface.
180    ///
181    /// The order of the definitions is not guaranteed.
182    ///
183    /// Generates:
184    ///
185    /// ```solidity
186    /// interface <name> {
187    ///     <enums>...
188    ///     <UDVTs>...
189    ///     <structs>...
190    ///     <errors>...
191    ///     <events>...
192    ///     <fallback>
193    ///     <receive>
194    ///     <functions>...
195    /// }
196    /// ```
197    ///
198    /// Note that enums are going to be identical to `uint8` UDVTs, since no
199    /// other information about enums is present in the ABI.
200    #[inline]
201    pub fn to_sol(&self, name: &str, config: Option<ToSolConfig>) -> String {
202        let mut out = String::new();
203        self.to_sol_raw(name, &mut out, config);
204        out
205    }
206
207    /// Formats this JSON ABI as a Solidity interface into the given string.
208    ///
209    /// See [`to_sol`](JsonAbi::to_sol) for more information.
210    pub fn to_sol_raw(&self, name: &str, out: &mut String, config: Option<ToSolConfig>) {
211        out.reserve(self.len() * 128);
212        SolPrinter::new(out, name, config.unwrap_or_default()).print(self);
213    }
214
215    /// Deduplicates all functions, errors, and events which have the same name and inputs.
216    pub fn dedup(&mut self) {
217        macro_rules! same_bucket {
218            () => {
219                |a, b| {
220                    // Already grouped by name
221                    debug_assert_eq!(a.name, b.name);
222                    a.inputs == b.inputs
223                }
224            };
225        }
226        for functions in self.functions.values_mut() {
227            functions.dedup_by(same_bucket!());
228        }
229        for errors in self.errors.values_mut() {
230            errors.dedup_by(same_bucket!());
231        }
232        for events in self.events.values_mut() {
233            events.dedup_by(same_bucket!());
234        }
235    }
236
237    /// Returns an immutable reference to the constructor.
238    #[inline]
239    pub const fn constructor(&self) -> Option<&Constructor> {
240        self.constructor.as_ref()
241    }
242
243    /// Returns a mutable reference to the constructor.
244    #[inline]
245    pub fn constructor_mut(&mut self) -> Option<&mut Constructor> {
246        self.constructor.as_mut()
247    }
248
249    /// Returns an immutable reference to the list of all the functions with the given name.
250    #[inline]
251    pub fn function(&self, name: &str) -> Option<&Vec<Function>> {
252        self.functions.get(name)
253    }
254
255    /// Returns a mutable reference to the list of all the functions with the given name.
256    #[inline]
257    pub fn function_mut(&mut self, name: &str) -> Option<&mut Vec<Function>> {
258        self.functions.get_mut(name)
259    }
260
261    /// Returns an immutable reference to the list of all the events with the given name.
262    #[inline]
263    pub fn event(&self, name: &str) -> Option<&Vec<Event>> {
264        self.events.get(name)
265    }
266
267    /// Returns a mutable reference to the list of all the events with the given name.
268    #[inline]
269    pub fn event_mut(&mut self, name: &str) -> Option<&mut Vec<Event>> {
270        self.events.get_mut(name)
271    }
272
273    /// Returns an immutable reference to the list of all the errors with the given name.
274    #[inline]
275    pub fn error(&self, name: &str) -> Option<&Vec<Error>> {
276        self.errors.get(name)
277    }
278
279    /// Returns a mutable reference to the list of all the errors with the given name.
280    #[inline]
281    pub fn error_mut(&mut self, name: &str) -> Option<&mut Vec<Error>> {
282        self.errors.get_mut(name)
283    }
284
285    /// Returns an iterator over immutable references to the functions.
286    #[inline]
287    pub fn functions(&self) -> FlattenValues<'_, Function> {
288        self.functions.values().flatten()
289    }
290
291    /// Returns an iterator over mutable references to the functions.
292    #[inline]
293    pub fn functions_mut(&mut self) -> FlattenValuesMut<'_, Function> {
294        self.functions.values_mut().flatten()
295    }
296
297    /// Returns an iterator over immutable references to the events.
298    #[inline]
299    pub fn events(&self) -> FlattenValues<'_, Event> {
300        self.events.values().flatten()
301    }
302
303    /// Returns an iterator over mutable references to the events.
304    #[inline]
305    pub fn events_mut(&mut self) -> FlattenValuesMut<'_, Event> {
306        self.events.values_mut().flatten()
307    }
308
309    /// Returns an iterator over immutable references to the errors.
310    #[inline]
311    pub fn errors(&self) -> FlattenValues<'_, Error> {
312        self.errors.values().flatten()
313    }
314
315    /// Returns an iterator over mutable references to the errors.
316    #[inline]
317    pub fn errors_mut(&mut self) -> FlattenValuesMut<'_, Error> {
318        self.errors.values_mut().flatten()
319    }
320
321    /// Inserts an item into the ABI.
322    fn insert_item(&mut self, item: AbiItem<'_>) -> Result<(), &'static str> {
323        match item {
324            AbiItem::Constructor(c) => set_if_none!(self.constructor, c.into_owned()),
325            AbiItem::Fallback(f) => set_if_none!(self.fallback, f.into_owned()),
326            AbiItem::Receive(r) => set_if_none!(self.receive, r.into_owned()),
327            AbiItem::Function(f) => entry_and_push!(self.functions, f),
328            AbiItem::Event(e) => entry_and_push!(self.events, e),
329            AbiItem::Error(e) => entry_and_push!(self.errors, e),
330        };
331        Ok(())
332    }
333}
334
335macro_rules! next_item {
336    ($self:ident; $($ident:ident.$f:ident()),* $(,)?) => {$(
337        if let Some(next) = $self.$ident.$f() {
338            $self.len -= 1;
339            return Some(next.into())
340        }
341    )*};
342}
343
344macro_rules! iter_impl {
345    (front) => {
346        fn next(&mut self) -> Option<Self::Item> {
347            next_item!(self;
348                constructor.take(),
349                fallback.take(),
350                receive.take(),
351                functions.next(),
352                events.next(),
353                errors.next(),
354            );
355            debug_assert_eq!(self.len, 0);
356            None
357        }
358
359        #[inline]
360        fn count(self) -> usize {
361            self.len
362        }
363
364        #[inline]
365        fn last(mut self) -> Option<Self::Item> {
366            self.next_back()
367        }
368
369        #[inline]
370        fn size_hint(&self) -> (usize, Option<usize>) {
371            (self.len, Some(self.len))
372        }
373    };
374    (back) => {
375        fn next_back(&mut self) -> Option<Self::Item> {
376            next_item!(self;
377                errors.next_back(),
378                events.next_back(),
379                functions.next_back(),
380                receive.take(),
381                fallback.take(),
382                constructor.take(),
383            );
384            debug_assert_eq!(self.len, 0);
385            None
386        }
387    };
388    (traits $ty:ty) => {
389        impl DoubleEndedIterator for $ty {
390            iter_impl!(back);
391        }
392
393        impl ExactSizeIterator for $ty {
394            #[inline]
395            fn len(&self) -> usize {
396                self.len
397            }
398        }
399
400        impl iter::FusedIterator for $ty {}
401    };
402}
403
404/// An iterator over immutable references of items in an ABI.
405///
406/// This `struct` is created by [`JsonAbi::items`]. See its documentation for
407/// more.
408#[derive(Clone, Debug, Default)]
409pub struct Items<'a> {
410    len: usize,
411    constructor: Option<&'a Constructor>,
412    fallback: Option<&'a Fallback>,
413    receive: Option<&'a Receive>,
414    functions: FlattenValues<'a, Function>,
415    events: FlattenValues<'a, Event>,
416    errors: FlattenValues<'a, Error>,
417}
418
419impl<'a> Iterator for Items<'a> {
420    type Item = AbiItem<'a>;
421
422    iter_impl!(front);
423}
424
425iter_impl!(traits Items<'_>);
426
427/// An iterator over items in an ABI.
428///
429/// This `struct` is created by [`JsonAbi::into_items`]. See its documentation
430/// for more.
431#[derive(Debug, Default)]
432pub struct IntoItems {
433    len: usize,
434    constructor: Option<Constructor>,
435    fallback: Option<Fallback>,
436    receive: Option<Receive>,
437    functions: FlattenIntoValues<Function>,
438    events: FlattenIntoValues<Event>,
439    errors: FlattenIntoValues<Error>,
440}
441
442impl Iterator for IntoItems {
443    type Item = AbiItem<'static>;
444
445    iter_impl!(front);
446}
447
448iter_impl!(traits IntoItems);
449
450impl<'de> Deserialize<'de> for JsonAbi {
451    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
452        deserializer.deserialize_seq(JsonAbiVisitor)
453    }
454}
455
456impl Serialize for JsonAbi {
457    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
458        let len = self.len();
459        let mut seq = serializer.serialize_seq(Some(len))?;
460        for item in self.items_with_len(len) {
461            seq.serialize_element(&item)?;
462        }
463        seq.end()
464    }
465}
466
467struct JsonAbiVisitor;
468
469impl<'de> Visitor<'de> for JsonAbiVisitor {
470    type Value = JsonAbi;
471
472    #[inline]
473    fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
474        f.write_str("a valid JSON ABI sequence")
475    }
476
477    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
478        let mut abi = JsonAbi::new();
479        while let Some(item) = seq.next_element()? {
480            abi.insert_item(item).map_err(serde::de::Error::duplicate_field)?;
481        }
482        Ok(abi)
483    }
484}
485
486/// Represents a generic contract's ABI, bytecode and deployed bytecode.
487///
488/// Can be deserialized from both an ABI array, and a JSON object with the `abi`
489/// field with optionally the bytecode fields.
490#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize)]
491#[serde(rename_all = "camelCase")]
492pub struct ContractObject {
493    /// The contract ABI.
494    #[serde(default, skip_serializing_if = "Option::is_none")]
495    pub abi: Option<JsonAbi>,
496    /// The contract bytecode.
497    #[serde(default, skip_serializing_if = "Option::is_none")]
498    pub bytecode: Option<Bytes>,
499    /// The contract deployed bytecode.
500    #[serde(default, skip_serializing_if = "Option::is_none")]
501    pub deployed_bytecode: Option<Bytes>,
502}
503
504impl<'de> Deserialize<'de> for ContractObject {
505    #[inline]
506    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
507        deserializer.deserialize_any(ContractObjectVisitor)
508    }
509}
510
511// Modified from `ethers_core::abi::raw`:
512// https://github.com/gakonst/ethers-rs/blob/311086466871204c3965065b8c81e47418261412/ethers-core/src/abi/raw.rs#L154
513struct ContractObjectVisitor;
514
515impl<'de> Visitor<'de> for ContractObjectVisitor {
516    type Value = ContractObject;
517
518    #[inline]
519    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520        f.write_str("an ABI sequence or contract object")
521    }
522
523    #[inline]
524    fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
525        JsonAbiVisitor.visit_seq(seq).map(|abi| ContractObject {
526            abi: Some(abi),
527            bytecode: None,
528            deployed_bytecode: None,
529        })
530    }
531
532    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
533        #[derive(Deserialize)]
534        #[serde(untagged)]
535        enum Bytecode {
536            Bytes(Bytes),
537            Object { object: Bytes },
538            Unlinked(String),
539            UnlinkedObject { object: String },
540        }
541
542        impl Bytecode {
543            fn ensure_bytes<E: serde::de::Error>(self) -> Result<Bytes, E> {
544                match self {
545                    Bytecode::Bytes(bytes) | Bytecode::Object { object: bytes } => Ok(bytes),
546                    Bytecode::Unlinked(unlinked)
547                    | Bytecode::UnlinkedObject { object: unlinked } => {
548                        if let Some((_, unlinked)) = unlinked.split_once("__$") {
549                            if let Some((addr, _)) = unlinked.split_once("$__") {
550                                return Err(E::custom(format!("expected bytecode, found unlinked bytecode with placeholder: {addr}")));
551                            }
552                        }
553                        Err(E::custom("invalid contract bytecode"))
554                    }
555                }
556            }
557        }
558
559        /// Represents nested bytecode objects of the `evm` value.
560        #[derive(Deserialize)]
561        struct EvmObj {
562            bytecode: Option<Bytecode>,
563            #[serde(rename = "deployedBytecode")]
564            deployed_bytecode: Option<Bytecode>,
565        }
566
567        let mut abi = None;
568        let mut bytecode = None;
569        let mut deployed_bytecode = None;
570
571        while let Some(key) = map.next_key::<&str>()? {
572            match key {
573                "abi" => set_if_none!(@serde abi, map.next_value()?),
574                "evm" => {
575                    let evm = map.next_value::<EvmObj>()?;
576                    if let Some(bytes) = evm.bytecode {
577                        set_if_none!(@serde bytecode, bytes.ensure_bytes()?);
578                    }
579                    if let Some(bytes) = evm.deployed_bytecode {
580                        set_if_none!(@serde deployed_bytecode, bytes.ensure_bytes()?);
581                    }
582                }
583                "bytecode" | "bin" => {
584                    set_if_none!(@serde bytecode, map.next_value::<Bytecode>()?.ensure_bytes()?);
585                }
586                "deployedBytecode" | "deployedbytecode" | "deployed_bytecode" | "runtimeBin"
587                | "runtimebin" | "runtime " => {
588                    set_if_none!(@serde deployed_bytecode, map.next_value::<Bytecode>()?.ensure_bytes()?);
589                }
590                _ => {
591                    map.next_value::<serde::de::IgnoredAny>()?;
592                }
593            }
594        }
595
596        Ok(ContractObject { abi, bytecode, deployed_bytecode })
597    }
598}