alloy_json_abi/
abi.rs

1use crate::{
2    AbiItem, Constructor, Error, Event, Fallback, Function, Receive,
3    to_sol::{SolPrinter, ToSolConfig},
4};
5use alloc::{collections::btree_map, string::String, vec::Vec};
6use alloy_primitives::{Bytes, Selector};
7use btree_map::BTreeMap;
8use core::{fmt, iter, iter::Flatten};
9use serde::{
10    Deserialize, Deserializer, Serialize,
11    de::{MapAccess, SeqAccess, Visitor},
12    ser::SerializeSeq,
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 the _first_ [`Function`] with a matching selector.
298    #[inline]
299    pub fn function_by_selector(&self, selector: Selector) -> Option<&Function> {
300        self.functions().find(|func| func.selector() == selector)
301    }
302
303    /// Returns an iterator over immutable references to the events.
304    #[inline]
305    pub fn events(&self) -> FlattenValues<'_, Event> {
306        self.events.values().flatten()
307    }
308
309    /// Returns an iterator over mutable references to the events.
310    #[inline]
311    pub fn events_mut(&mut self) -> FlattenValuesMut<'_, Event> {
312        self.events.values_mut().flatten()
313    }
314
315    /// Returns an iterator over immutable references to the errors.
316    #[inline]
317    pub fn errors(&self) -> FlattenValues<'_, Error> {
318        self.errors.values().flatten()
319    }
320
321    /// Returns an iterator over mutable references to the errors.
322    #[inline]
323    pub fn errors_mut(&mut self) -> FlattenValuesMut<'_, Error> {
324        self.errors.values_mut().flatten()
325    }
326
327    /// Inserts an item into the ABI.
328    fn insert_item(&mut self, item: AbiItem<'_>) -> Result<(), &'static str> {
329        match item {
330            AbiItem::Constructor(c) => set_if_none!(self.constructor, c.into_owned()),
331            AbiItem::Fallback(f) => set_if_none!(self.fallback, f.into_owned()),
332            AbiItem::Receive(r) => set_if_none!(self.receive, r.into_owned()),
333            AbiItem::Function(f) => entry_and_push!(self.functions, f),
334            AbiItem::Event(e) => entry_and_push!(self.events, e),
335            AbiItem::Error(e) => entry_and_push!(self.errors, e),
336        };
337        Ok(())
338    }
339}
340
341macro_rules! next_item {
342    ($self:ident; $($ident:ident.$f:ident()),* $(,)?) => {$(
343        if let Some(next) = $self.$ident.$f() {
344            $self.len -= 1;
345            return Some(next.into())
346        }
347    )*};
348}
349
350macro_rules! iter_impl {
351    (front) => {
352        fn next(&mut self) -> Option<Self::Item> {
353            next_item!(self;
354                constructor.take(),
355                fallback.take(),
356                receive.take(),
357                functions.next(),
358                events.next(),
359                errors.next(),
360            );
361            debug_assert_eq!(self.len, 0);
362            None
363        }
364
365        #[inline]
366        fn count(self) -> usize {
367            self.len
368        }
369
370        #[inline]
371        fn last(mut self) -> Option<Self::Item> {
372            self.next_back()
373        }
374
375        #[inline]
376        fn size_hint(&self) -> (usize, Option<usize>) {
377            (self.len, Some(self.len))
378        }
379    };
380    (back) => {
381        fn next_back(&mut self) -> Option<Self::Item> {
382            next_item!(self;
383                errors.next_back(),
384                events.next_back(),
385                functions.next_back(),
386                receive.take(),
387                fallback.take(),
388                constructor.take(),
389            );
390            debug_assert_eq!(self.len, 0);
391            None
392        }
393    };
394    (traits $ty:ty) => {
395        impl DoubleEndedIterator for $ty {
396            iter_impl!(back);
397        }
398
399        impl ExactSizeIterator for $ty {
400            #[inline]
401            fn len(&self) -> usize {
402                self.len
403            }
404        }
405
406        impl iter::FusedIterator for $ty {}
407    };
408}
409
410/// An iterator over immutable references of items in an ABI.
411///
412/// This `struct` is created by [`JsonAbi::items`]. See its documentation for
413/// more.
414#[derive(Clone, Debug, Default)]
415pub struct Items<'a> {
416    len: usize,
417    constructor: Option<&'a Constructor>,
418    fallback: Option<&'a Fallback>,
419    receive: Option<&'a Receive>,
420    functions: FlattenValues<'a, Function>,
421    events: FlattenValues<'a, Event>,
422    errors: FlattenValues<'a, Error>,
423}
424
425impl<'a> Iterator for Items<'a> {
426    type Item = AbiItem<'a>;
427
428    iter_impl!(front);
429}
430
431iter_impl!(traits Items<'_>);
432
433/// An iterator over items in an ABI.
434///
435/// This `struct` is created by [`JsonAbi::into_items`]. See its documentation
436/// for more.
437#[derive(Debug, Default)]
438pub struct IntoItems {
439    len: usize,
440    constructor: Option<Constructor>,
441    fallback: Option<Fallback>,
442    receive: Option<Receive>,
443    functions: FlattenIntoValues<Function>,
444    events: FlattenIntoValues<Event>,
445    errors: FlattenIntoValues<Error>,
446}
447
448impl Iterator for IntoItems {
449    type Item = AbiItem<'static>;
450
451    iter_impl!(front);
452}
453
454iter_impl!(traits IntoItems);
455
456impl<'de> Deserialize<'de> for JsonAbi {
457    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
458        deserializer.deserialize_seq(JsonAbiVisitor)
459    }
460}
461
462impl Serialize for JsonAbi {
463    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
464        let len = self.len();
465        let mut seq = serializer.serialize_seq(Some(len))?;
466        for item in self.items_with_len(len) {
467            seq.serialize_element(&item)?;
468        }
469        seq.end()
470    }
471}
472
473struct JsonAbiVisitor;
474
475impl<'de> Visitor<'de> for JsonAbiVisitor {
476    type Value = JsonAbi;
477
478    #[inline]
479    fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
480        f.write_str("a valid JSON ABI sequence")
481    }
482
483    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
484        let mut abi = JsonAbi::new();
485        while let Some(item) = seq.next_element()? {
486            abi.insert_item(item).map_err(serde::de::Error::duplicate_field)?;
487        }
488        Ok(abi)
489    }
490}
491
492/// Represents a generic contract's ABI, bytecode and deployed bytecode.
493///
494/// Can be deserialized from both an ABI array, and a JSON object with the `abi`
495/// field with optionally the bytecode fields.
496#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize)]
497#[serde(rename_all = "camelCase")]
498pub struct ContractObject {
499    /// The contract ABI.
500    #[serde(default, skip_serializing_if = "Option::is_none")]
501    pub abi: Option<JsonAbi>,
502    /// The contract bytecode.
503    #[serde(default, skip_serializing_if = "Option::is_none")]
504    pub bytecode: Option<Bytes>,
505    /// The contract deployed bytecode.
506    #[serde(default, skip_serializing_if = "Option::is_none")]
507    pub deployed_bytecode: Option<Bytes>,
508}
509
510impl<'de> Deserialize<'de> for ContractObject {
511    #[inline]
512    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
513        deserializer.deserialize_any(ContractObjectVisitor::default())
514    }
515}
516
517#[cfg(feature = "serde_json")]
518impl ContractObject {
519    /// Ignores unlinked bytecode when deserializing the artifact and returns the
520    /// [`ContractObject`].
521    ///
522    /// Unlinked bytecode can be identified by the presence of the `__$` and `$__` placeholders.
523    pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
524        Self::from_json_with(s, true)
525    }
526
527    /// Deserializes an artifact into a [`ContractObject`].
528    ///
529    /// Optionally ignore unlinked bytecode if `ignore_unlinked_bytecode` is set to true.
530    pub fn from_json_with(
531        s: &str,
532        ignore_unlinked_bytecode: bool,
533    ) -> Result<Self, serde_json::Error> {
534        let visitor = ContractObjectVisitor { ignore_unlinked_bytecode };
535        serde_json::Deserializer::from_str(s).deserialize_any(visitor)
536    }
537}
538// Modified from `ethers_core::abi::raw`:
539// https://github.com/gakonst/ethers-rs/blob/311086466871204c3965065b8c81e47418261412/ethers-core/src/abi/raw.rs#L154
540#[derive(Default)]
541struct ContractObjectVisitor {
542    /// Whether unlinked bytecode objects should be ignored.
543    ignore_unlinked_bytecode: bool,
544}
545
546impl<'de> Visitor<'de> for ContractObjectVisitor {
547    type Value = ContractObject;
548
549    #[inline]
550    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551        f.write_str("an ABI sequence or contract object")
552    }
553
554    #[inline]
555    fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
556        JsonAbiVisitor.visit_seq(seq).map(|abi| ContractObject {
557            abi: Some(abi),
558            bytecode: None,
559            deployed_bytecode: None,
560        })
561    }
562
563    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
564        #[derive(Deserialize)]
565        #[serde(untagged)]
566        enum Bytecode {
567            Bytes(Bytes),
568            Object { object: Bytes },
569            Unlinked(String),
570            UnlinkedObject { object: String },
571        }
572
573        impl Bytecode {
574            fn ensure_bytes<E: serde::de::Error>(
575                self,
576                ignore_unlinked_bytecode: bool,
577            ) -> Result<Option<Bytes>, E> {
578                match self {
579                    Bytecode::Bytes(bytes) | Bytecode::Object { object: bytes } => Ok(Some(bytes)),
580                    Bytecode::Unlinked(unlinked)
581                    | Bytecode::UnlinkedObject { object: unlinked } => {
582                        if ignore_unlinked_bytecode {
583                            return Ok(None);
584                        }
585                        if let Some((_, unlinked)) = unlinked.split_once("__$") {
586                            if let Some((addr, _)) = unlinked.split_once("$__") {
587                                return Err(E::custom(format!(
588                                    "expected bytecode, found unlinked bytecode with placeholder: {addr}. Use the `ignore_unlinked` sol attribute to bypass this error."
589                                )));
590                            }
591                        }
592                        Err(E::custom("invalid contract bytecode"))
593                    }
594                }
595            }
596        }
597
598        /// Represents nested bytecode objects of the `evm` value.
599        #[derive(Deserialize)]
600        struct EvmObj {
601            bytecode: Option<Bytecode>,
602            #[serde(rename = "deployedBytecode")]
603            deployed_bytecode: Option<Bytecode>,
604        }
605
606        let mut abi = None;
607        let mut bytecode = None;
608        let mut deployed_bytecode = None;
609
610        while let Some(key) = map.next_key::<&str>()? {
611            match key {
612                "abi" => set_if_none!(@serde abi, map.next_value()?),
613                "evm" => {
614                    let evm = map.next_value::<EvmObj>()?;
615                    if let Some(bytes) = evm.bytecode {
616                        if let Some(b) = bytes.ensure_bytes(self.ignore_unlinked_bytecode)? {
617                            set_if_none!(@serde bytecode, b);
618                        }
619                    }
620                    if let Some(bytes) = evm.deployed_bytecode {
621                        if let Some(b) = bytes.ensure_bytes(self.ignore_unlinked_bytecode)? {
622                            set_if_none!(@serde deployed_bytecode, b);
623                        }
624                    }
625                }
626                "bytecode" | "bin" => {
627                    if let Some(b) =
628                        map.next_value::<Bytecode>()?.ensure_bytes(self.ignore_unlinked_bytecode)?
629                    {
630                        set_if_none!(@serde bytecode, b);
631                    }
632                }
633                "deployedBytecode" | "deployedbytecode" | "deployed_bytecode" | "runtimeBin"
634                | "runtimebin" | "runtime " => {
635                    if let Some(b) =
636                        map.next_value::<Bytecode>()?.ensure_bytes(self.ignore_unlinked_bytecode)?
637                    {
638                        set_if_none!(@serde deployed_bytecode, b);
639                    }
640                }
641                _ => {
642                    map.next_value::<serde::de::IgnoredAny>()?;
643                }
644            }
645        }
646
647        Ok(ContractObject { abi, bytecode, deployed_bytecode })
648    }
649}