ethers_core/abi/human_readable/
mod.rs

1use ethabi::AbiError;
2use std::collections::{BTreeMap, HashMap, VecDeque};
3
4use crate::abi::{
5    error::{bail, format_err, ParseError, Result},
6    struct_def::{FieldType, StructFieldType},
7    Abi, Constructor, Event, EventParam, Function, HumanReadableParser, Param, ParamType,
8    SolStruct, StateMutability,
9};
10pub mod lexer;
11
12/// A parser that turns a "human readable abi" into a `Abi`
13pub struct AbiParser {
14    /// solidity structs
15    pub structs: HashMap<String, SolStruct>,
16    /// solidity structs as tuples
17    pub struct_tuples: HashMap<String, Vec<ParamType>>,
18    /// (function name, param name) -> struct which are the identifying properties we get the name
19    /// from ethabi.
20    pub function_params: HashMap<(String, String), String>,
21    /// (event name, idx) -> struct which are the identifying properties we get the name
22    /// from ethabi.
23    ///
24    /// Note: we need to map the index of the event here because events can contain nameless inputs
25    pub event_params: HashMap<(String, usize), String>,
26    /// (function name) -> `Vec<structs>` all structs the function returns
27    pub outputs: HashMap<String, Vec<String>>,
28}
29
30impl AbiParser {
31    /// Parses a "human readable abi" string
32    ///
33    /// # Example
34    ///
35    /// ```
36    ///  # use ethers_core::abi::AbiParser;
37    /// let abi = AbiParser::default().parse_str("[
38    ///         function setValue(string)
39    ///         function getValue() external view returns (string)
40    ///         event ValueChanged(address indexed author, string oldValue, string newValue)
41    ///     ]").unwrap();
42    /// ```
43    pub fn parse_str(&mut self, s: &str) -> Result<Abi> {
44        self.parse(
45            &s.trim().trim_start_matches('[').trim_end_matches(']').lines().collect::<Vec<_>>(),
46        )
47    }
48
49    /// Parses a "human readable abi" string vector
50    ///
51    /// # Example
52    /// ```
53    /// use ethers_core::abi::AbiParser;
54    ///
55    /// let abi = AbiParser::default().parse(&[
56    ///     "function x() external view returns (uint256)",
57    /// ]).unwrap();
58    /// ```
59    pub fn parse(&mut self, input: &[&str]) -> Result<Abi> {
60        // parse struct first
61        let mut abi = Abi {
62            constructor: None,
63            functions: BTreeMap::new(),
64            events: BTreeMap::new(),
65            errors: BTreeMap::new(),
66            receive: false,
67            fallback: false,
68        };
69
70        let (structs, types): (Vec<_>, Vec<_>) = input
71            .iter()
72            .map(|s| escape_quotes(s))
73            .map(str::trim)
74            .filter(|s| !s.is_empty())
75            .partition(|s| s.starts_with("struct"));
76
77        for sol in structs {
78            let s = SolStruct::parse(sol)?;
79            if self.structs.contains_key(s.name()) {
80                bail!("Duplicate struct declaration for struct `{}`", s.name())
81            }
82            self.structs.insert(s.name().to_string(), s);
83        }
84        self.substitute_structs()?;
85
86        for mut line in types {
87            line = line.trim_start();
88            if line.starts_with("event") {
89                let event = self.parse_event(line)?;
90                abi.events.entry(event.name.clone()).or_default().push(event);
91            } else if let Some(err) = line.strip_prefix("error") {
92                // an error is essentially a function without outputs, so we parse as function here
93                let function = match self.parse_function(err) {
94                    Ok(function) => function,
95                    Err(_) => bail!("Illegal abi `{}`, expected error", line),
96                };
97                if !function.outputs.is_empty() {
98                    bail!("Illegal abi `{}`, expected error", line);
99                }
100                let error = AbiError { name: function.name, inputs: function.inputs };
101                abi.errors.entry(error.name.clone()).or_default().push(error);
102            } else if line.starts_with("constructor") {
103                let inputs = self
104                    .constructor_inputs(line)?
105                    .into_iter()
106                    .map(|(input, struct_name)| {
107                        if let Some(struct_name) = struct_name {
108                            // keep track of the user defined struct of that param
109                            self.function_params.insert(
110                                ("constructor".to_string(), input.name.clone()),
111                                struct_name,
112                            );
113                        }
114                        input
115                    })
116                    .collect();
117
118                abi.constructor = Some(Constructor { inputs });
119            } else {
120                // function may have shorthand declaration, so it won't start with "function"
121                let function = match self.parse_function(line) {
122                    Ok(function) => function,
123                    Err(_) => bail!("Illegal abi `{}`, expected function", line),
124                };
125                abi.functions.entry(function.name.clone()).or_default().push(function);
126            }
127        }
128        Ok(abi)
129    }
130
131    /// Substitutes any other struct references within structs with tuples
132    fn substitute_structs(&mut self) -> Result<()> {
133        let mut unresolved = self.structs.keys().collect::<VecDeque<_>>();
134        let mut sequential_retries = 0;
135        while let Some(name) = unresolved.pop_front() {
136            let mut unresolved_field = None;
137            let sol = &self.structs[name];
138            let mut tuple = Vec::with_capacity(sol.fields().len());
139            for field in sol.fields() {
140                match field.r#type() {
141                    FieldType::Elementary(param) => tuple.push(param.clone()),
142                    FieldType::Struct(ty) => {
143                        if let Some(param) = self.struct_tuples.get(ty.name()) {
144                            tuple.push(ty.as_param(ParamType::Tuple(param.clone())))
145                        } else {
146                            unresolved_field = Some(field);
147                            break
148                        }
149                    }
150                    FieldType::Mapping(_) => {
151                        bail!(
152                            "mappings are not allowed as params in public functions of struct `{}`",
153                            sol.name()
154                        )
155                    }
156                }
157            }
158            if let Some(f) = unresolved_field {
159                sequential_retries += 1;
160                if sequential_retries > unresolved.len() {
161                    bail!("Could not resolve field of struct '{name}': `{}: {:?}`", f.name, f.ty)
162                }
163                unresolved.push_back(name);
164            } else {
165                sequential_retries = 0;
166                self.struct_tuples.insert(sol.name().to_string(), tuple);
167            }
168        }
169        Ok(())
170    }
171
172    /// Link additional structs for parsing
173    pub fn with_structs(structs: Vec<SolStruct>) -> Self {
174        Self {
175            structs: structs.into_iter().map(|s| (s.name().to_string(), s)).collect(),
176            struct_tuples: HashMap::new(),
177            function_params: Default::default(),
178            event_params: Default::default(),
179            outputs: Default::default(),
180        }
181    }
182
183    /// Parses a solidity event declaration from `event <name> (args*) anonymous?`
184    pub fn parse_event(&mut self, s: &str) -> Result<Event> {
185        let mut event = s.trim();
186        if !event.starts_with("event ") {
187            bail!("Not an event `{}`", s)
188        }
189        event = &event[5..];
190
191        let name = parse_identifier(&mut event)?;
192
193        let mut chars = event.chars();
194
195        loop {
196            match chars.next() {
197                None => bail!("Expected event"),
198                Some('(') => {
199                    event = chars.as_str().trim();
200                    let mut anonymous = false;
201                    if event.ends_with("anonymous") {
202                        anonymous = true;
203                        event = event[..event.len() - 9].trim_end();
204                    }
205                    event = event
206                        .trim()
207                        .strip_suffix(')')
208                        .ok_or_else(|| format_err!("Expected closing `)` in `{}`", s))?;
209
210                    let inputs = if event.is_empty() {
211                        Vec::new()
212                    } else {
213                        event
214                            .split(',')
215                            .map(|e| self.parse_event_arg(e))
216                            .collect::<Result<Vec<_>, _>>()?
217                            .into_iter()
218                            .enumerate()
219                            .map(|(idx, (input, struct_name))| {
220                                if let Some(struct_name) = struct_name {
221                                    // keep track of the user defined struct of that param
222                                    self.event_params.insert((name.clone(), idx), struct_name);
223                                }
224                                input
225                            })
226                            .collect()
227                    };
228
229                    let event = Event { name, inputs, anonymous };
230                    return Ok(event)
231                }
232                Some(' ') | Some('\t') => continue,
233                Some(c) => {
234                    bail!("Illegal char `{}` at `{}`", c, s)
235                }
236            }
237        }
238    }
239
240    /// Parse a single event param
241    ///
242    /// See [`Self::parse_type`]
243    fn parse_event_arg(&self, input: &str) -> Result<(EventParam, Option<String>)> {
244        let mut iter = input.trim().rsplitn(3, is_whitespace);
245        let mut indexed = false;
246        let mut name =
247            iter.next().ok_or_else(|| format_err!("Empty event param at `{}`", input))?;
248
249        let type_str;
250        if let Some(mid) = iter.next() {
251            if let Some(ty) = iter.next() {
252                if mid != "indexed" {
253                    bail!("Expected indexed keyword at `{}`", input)
254                }
255                indexed = true;
256                type_str = ty;
257            } else {
258                if name == "indexed" {
259                    indexed = true;
260                    name = "";
261                }
262                type_str = mid;
263            }
264        } else {
265            type_str = name;
266            name = "";
267        }
268
269        let (kind, user_ty) = self.parse_type(type_str)?;
270        Ok((EventParam { name: name.to_string(), indexed, kind }, user_ty))
271    }
272
273    /// Returns the parsed function from the input string
274    ///
275    /// # Example
276    ///
277    /// ```
278    /// use ethers_core::abi::AbiParser;
279    /// let f = AbiParser::default()
280    ///     .parse_function("bar(uint256 x, uint256 y, address addr)").unwrap();
281    /// ```
282    pub fn parse_function(&mut self, s: &str) -> Result<Function> {
283        let mut input = s.trim();
284        let shorthand = !input.starts_with("function ");
285
286        if !shorthand {
287            input = &input[8..];
288        }
289
290        let name = parse_identifier(&mut input)?;
291        input = input
292            .strip_prefix('(')
293            .ok_or_else(|| format_err!("Expected input args parentheses at `{}`", s))?;
294
295        let (input_args_modifiers, output_args) = match input.rsplit_once('(') {
296            Some((first, second)) => (first, Some(second)),
297            None => (input, None),
298        };
299
300        let mut input_args_modifiers_iter = input_args_modifiers
301            .trim_end()
302            .strip_suffix(" returns")
303            .unwrap_or(input_args_modifiers)
304            .splitn(2, ')');
305
306        let input_args = match input_args_modifiers_iter
307            .next()
308            .ok_or_else(|| format_err!("Expected input args parentheses at `{}`", s))?
309        {
310            "" => None,
311            input_params_args => Some(input_params_args),
312        };
313        let modifiers = match input_args_modifiers_iter
314            .next()
315            .ok_or_else(|| format_err!("Expected input args parentheses at `{}`", s))?
316        {
317            "" => None,
318            modifiers => Some(modifiers),
319        };
320
321        let inputs = if let Some(params) = input_args {
322            self.parse_params(params)?
323                .into_iter()
324                .map(|(input, struct_name)| {
325                    if let Some(struct_name) = struct_name {
326                        // keep track of the user defined struct of that param
327                        self.function_params
328                            .insert((name.clone(), input.name.clone()), struct_name);
329                    }
330                    input
331                })
332                .collect()
333        } else {
334            Vec::new()
335        };
336
337        let outputs = if let Some(params) = output_args {
338            let params = params
339                .trim()
340                .strip_suffix(')')
341                .ok_or_else(|| format_err!("Expected output args parentheses at `{}`", s))?;
342            let output_params = self.parse_params(params)?;
343            let mut outputs = Vec::with_capacity(output_params.len());
344            let mut output_types = Vec::new();
345
346            for (output, struct_name) in output_params {
347                if let Some(struct_name) = struct_name {
348                    // keep track of the user defined struct of that param
349                    output_types.push(struct_name);
350                }
351                outputs.push(output);
352            }
353            self.outputs.insert(name.clone(), output_types);
354            outputs
355        } else {
356            Vec::new()
357        };
358
359        let state_mutability = modifiers.map(detect_state_mutability).unwrap_or_default();
360
361        Ok(
362            #[allow(deprecated)]
363            Function { name, inputs, outputs, state_mutability, constant: None },
364        )
365    }
366
367    fn parse_params(&self, s: &str) -> Result<Vec<(Param, Option<String>)>> {
368        s.split(',')
369            .filter(|s| !s.is_empty())
370            .map(|s| self.parse_param(s))
371            .collect::<Result<Vec<_>, _>>()
372    }
373
374    /// Returns the `ethabi` `ParamType` for the function parameter and the aliased struct type, if
375    /// it is a user defined struct
376    ///
377    /// **NOTE**: the  `ethabi` Reader treats unknown identifiers as `UInt(8)`, because solc uses
378    /// the _name_ of a solidity enum for the value of the `type` of the ABI, but only in sol
379    /// libraries. If the enum is defined in a contract the value of the `type` is `uint8`
380    ///
381    /// # Example ABI for an enum in a __contract__
382    /// ```json
383    /// {
384    ///   "internalType": "enum ContractTest.TestEnum",
385    ///   "name": "test",
386    ///   "type": "uint8"
387    /// }
388    /// ```
389    ///
390    /// # Example ABI for an enum in a __library__
391    /// ```json
392    /// {
393    ///   "internalType": "enum ContractTest.TestEnum",
394    ///   "name": "test",
395    ///   "type": "ContractTest.TestEnum"
396    /// }
397    /// ```
398    ///
399    /// See <https://github.com/rust-ethereum/ethabi/issues/254>
400    ///
401    /// Therefore, we need to double-check if the `ethabi::Reader` parsed an `uint8`, and ignore the
402    /// type if `type_str` is not uint8. However can lead to some problems if a function param is
403    /// array of custom types for example, like `Foo[]`, which the `Reader` would identify as
404    /// `uint8[]`. Therefor if the `Reader` returns an `uint8` we also check that the input string
405    /// contains a `uint8`. This however can still lead to false detection of `uint8` and is only
406    /// solvable with a more sophisticated parser: <https://github.com/gakonst/ethers-rs/issues/474>
407    fn parse_type(&self, type_str: &str) -> Result<(ParamType, Option<String>)> {
408        if let Ok(kind) = HumanReadableParser::parse_type(type_str) {
409            Ok((kind, None))
410        } else {
411            // try struct instead
412            self.parse_struct_type(type_str)
413        }
414    }
415
416    /// Attempts to parse the `type_str` as a `struct`, resolving all fields of the struct into a
417    /// `ParamType::Tuple`
418    fn parse_struct_type(&self, type_str: &str) -> Result<(ParamType, Option<String>)> {
419        if let Ok(field) = StructFieldType::parse(type_str) {
420            let struct_ty = field
421                .as_struct()
422                .ok_or_else(|| format_err!("Expected struct type `{}`", type_str))?;
423            let name = struct_ty.name();
424            let tuple = self
425                .struct_tuples
426                .get(name)
427                .cloned()
428                .map(ParamType::Tuple)
429                .ok_or_else(|| format_err!("Unknown struct `{}`", struct_ty.name()))?;
430
431            if let Some(field) = field.as_struct() {
432                Ok((field.as_param(tuple), Some(name.to_string())))
433            } else {
434                bail!("Expected struct type")
435            }
436        } else {
437            bail!("Failed determine event type `{}`", type_str)
438        }
439    }
440
441    pub fn parse_constructor(&self, s: &str) -> Result<Constructor> {
442        let inputs = self.constructor_inputs(s)?.into_iter().map(|s| s.0).collect();
443        Ok(Constructor { inputs })
444    }
445
446    fn constructor_inputs(&self, s: &str) -> Result<Vec<(Param, Option<String>)>> {
447        let mut input = s.trim();
448        if !input.starts_with("constructor") {
449            bail!("Not a constructor `{}`", input)
450        }
451        input = input[11..]
452            .trim_start()
453            .strip_prefix('(')
454            .ok_or_else(|| format_err!("Expected leading `(` in `{}`", s))?;
455
456        let params = input
457            .rsplitn(2, ')')
458            .last()
459            .ok_or_else(|| format_err!("Expected closing `)` in `{}`", s))?;
460
461        self.parse_params(params)
462    }
463
464    fn parse_param(&self, param: &str) -> Result<(Param, Option<String>)> {
465        let mut iter = param.trim().rsplitn(3, is_whitespace);
466
467        let mut name =
468            iter.next().ok_or_else(|| ParseError::ParseError(super::Error::InvalidData))?;
469
470        let type_str;
471        if let Some(ty) = iter.last() {
472            if name == "memory" || name == "calldata" {
473                name = "";
474            }
475            type_str = ty;
476        } else {
477            type_str = name;
478            name = "";
479        }
480        let (kind, user_struct) = self.parse_type(type_str)?;
481        Ok((Param { name: name.to_string(), kind, internal_type: None }, user_struct))
482    }
483}
484
485impl Default for AbiParser {
486    fn default() -> Self {
487        Self::with_structs(Vec::new())
488    }
489}
490
491/// Parses a "human readable abi" string vector
492///
493/// ```
494/// use ethers_core::abi::parse_abi;
495///
496/// let abi = parse_abi(&[
497///     "function x() external view returns (uint256)",
498/// ]).unwrap();
499/// ```
500pub fn parse(input: &[&str]) -> Result<Abi> {
501    AbiParser::default().parse(input)
502}
503
504/// Parses a "human readable abi" string
505///
506/// See also `AbiParser::parse_str`
507pub fn parse_str(input: &str) -> Result<Abi> {
508    AbiParser::default().parse_str(input)
509}
510
511/// Parses an identifier like event or function name
512pub(crate) fn parse_identifier(input: &mut &str) -> Result<String> {
513    let mut chars = input.trim_start().chars();
514    let mut name = String::new();
515    let c = chars.next().ok_or_else(|| format_err!("Empty identifier in `{}`", input))?;
516    if is_first_ident_char(c) {
517        name.push(c);
518        loop {
519            match chars.clone().next() {
520                Some(c) if is_ident_char(c) => {
521                    chars.next();
522                    name.push(c);
523                }
524                _ => break,
525            }
526        }
527    }
528    if name.is_empty() {
529        return Err(ParseError::ParseError(super::Error::InvalidName(input.to_string())))
530    }
531    *input = chars.as_str();
532    Ok(name)
533}
534
535fn detect_state_mutability(s: &str) -> StateMutability {
536    if s.contains("pure") {
537        StateMutability::Pure
538    } else if s.contains("view") {
539        StateMutability::View
540    } else if s.contains("payable") {
541        StateMutability::Payable
542    } else {
543        StateMutability::NonPayable
544    }
545}
546
547pub(crate) fn is_first_ident_char(c: char) -> bool {
548    matches!(c, 'a'..='z' | 'A'..='Z' | '_')
549}
550
551pub(crate) fn is_ident_char(c: char) -> bool {
552    matches!(c, 'a'..='z' | 'A'..='Z' | '0'..='9' | '_')
553}
554
555pub(crate) fn is_whitespace(c: char) -> bool {
556    matches!(c, ' ' | '\t')
557}
558
559fn escape_quotes(input: &str) -> &str {
560    input.trim_matches(is_whitespace).trim_matches('\"')
561}
562
563#[cfg(test)]
564mod tests {
565    use super::*;
566
567    #[test]
568    fn parses_approve() {
569        let fn_str = "function approve(address _spender, uint256 value) external returns(bool)";
570        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
571        assert_eq!(parsed.name, "approve");
572        assert_eq!(parsed.inputs[0].name, "_spender");
573        assert_eq!(parsed.inputs[0].kind, ParamType::Address,);
574        assert_eq!(parsed.inputs[1].name, "value");
575        assert_eq!(parsed.inputs[1].kind, ParamType::Uint(256),);
576        assert_eq!(parsed.outputs[0].name, "");
577        assert_eq!(parsed.outputs[0].kind, ParamType::Bool);
578    }
579
580    #[test]
581    fn parses_function_arguments_return() {
582        let fn_str = "function foo(uint32[] memory x) external view returns (address)";
583        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
584        assert_eq!(parsed.name, "foo");
585        assert_eq!(parsed.inputs[0].name, "x");
586        assert_eq!(parsed.inputs[0].kind, ParamType::Array(Box::new(ParamType::Uint(32))));
587        assert_eq!(parsed.outputs[0].name, "");
588        assert_eq!(parsed.outputs[0].kind, ParamType::Address);
589    }
590
591    #[test]
592    fn parses_function_empty() {
593        let fn_str = "function foo()";
594        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
595        assert_eq!(parsed.name, "foo");
596        assert!(parsed.inputs.is_empty());
597        assert!(parsed.outputs.is_empty());
598    }
599
600    #[test]
601    fn parses_function_payable() {
602        let fn_str = "function foo() public payable";
603        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
604        assert_eq!(parsed.state_mutability, StateMutability::Payable);
605    }
606
607    #[test]
608    fn parses_function_view() {
609        let fn_str = "function foo() external view";
610        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
611        assert_eq!(parsed.state_mutability, StateMutability::View);
612    }
613
614    #[test]
615    fn parses_function_pure() {
616        let fn_str = "function foo()  pure";
617        let parsed = AbiParser::default().parse_function(fn_str).unwrap();
618        assert_eq!(parsed.state_mutability, StateMutability::Pure);
619    }
620
621    #[test]
622    fn parses_event() {
623        assert_eq!(
624            AbiParser::default()
625                .parse_event("event Foo (address indexed x, uint y, bytes32[] z)")
626                .unwrap(),
627            Event {
628                anonymous: false,
629                name: "Foo".to_string(),
630                inputs: vec![
631                    EventParam { name: "x".to_string(), kind: ParamType::Address, indexed: true },
632                    EventParam {
633                        name: "y".to_string(),
634                        kind: ParamType::Uint(256),
635                        indexed: false,
636                    },
637                    EventParam {
638                        name: "z".to_string(),
639                        kind: ParamType::Array(Box::new(ParamType::FixedBytes(32))),
640                        indexed: false,
641                    },
642                ],
643            }
644        );
645    }
646
647    #[test]
648    fn parses_anonymous_event() {
649        assert_eq!(
650            AbiParser::default().parse_event("event Foo() anonymous").unwrap(),
651            Event { anonymous: true, name: "Foo".to_string(), inputs: vec![] }
652        );
653    }
654
655    #[test]
656    fn parses_unnamed_event() {
657        assert_eq!(
658            AbiParser::default().parse_event("event Foo(address)").unwrap(),
659            Event {
660                anonymous: false,
661                name: "Foo".to_string(),
662                inputs: vec![EventParam {
663                    name: "".to_string(),
664                    kind: ParamType::Address,
665                    indexed: false,
666                }],
667            }
668        );
669    }
670
671    #[test]
672    fn parses_unnamed_indexed_event() {
673        assert_eq!(
674            AbiParser::default().parse_event("event Foo(address indexed)").unwrap(),
675            Event {
676                anonymous: false,
677                name: "Foo".to_string(),
678                inputs: vec![EventParam {
679                    name: "".to_string(),
680                    kind: ParamType::Address,
681                    indexed: true,
682                }],
683            }
684        );
685    }
686
687    #[test]
688    fn parse_event_input() {
689        assert_eq!(
690            AbiParser::default().parse_event_arg("address indexed x").unwrap().0,
691            EventParam { name: "x".to_string(), kind: ParamType::Address, indexed: true }
692        );
693
694        assert_eq!(
695            AbiParser::default().parse_event_arg("address x").unwrap().0,
696            EventParam { name: "x".to_string(), kind: ParamType::Address, indexed: false }
697        );
698    }
699
700    #[test]
701    fn can_parse_functions() {
702        [
703            "function foo(uint256[] memory x) external view returns (address)",
704            "function bar(uint256[] memory x) returns(address)",
705            "function bar(uint256[] memory x, uint32 y) returns (address, uint256)",
706            "function foo(address[] memory, bytes memory) returns (bytes memory)",
707            "function bar(uint256[] memory x)",
708            "function bar()",
709            "bar(uint256[] memory x)(address)",
710            "bar(uint256[] memory x, uint32 y)(address, uint256)",
711            "foo(address[] memory, bytes memory)(bytes memory)",
712            "bar(uint256[] memory x)()",
713            "bar()()",
714            "bar(uint256)",
715            "bar()",
716        ]
717        .iter()
718        .for_each(|x| {
719            AbiParser::default().parse_function(x).unwrap();
720        });
721    }
722
723    #[test]
724    fn can_parse_structs_and_functions() {
725        let abi = &[
726            "struct Demo {bytes  x; address payable d;}",
727            "struct Voter {  uint weight;  bool voted;  address delegate; uint vote; }",
728            "event FireEvent(Voter v, NestedVoter2 n)",
729            "function foo(uint256[] memory x) external view returns (address)",
730            "function call(Voter memory voter) returns (address, uint256)",
731            "foo(uint256[] memory x)()",
732            "call(Voter memory voter)(address, uint256)",
733            "struct NestedVoter {  Voter voter;  bool voted;  address delegate; uint vote; }",
734            "struct NestedVoter2 {  NestedVoter[] voter;  Voter[10] votes;  address delegate; uint vote; }",
735        ];
736        parse(abi).unwrap();
737    }
738
739    #[test]
740    fn can_parse_params() {
741        [
742            "address x",
743            "address",
744            "bytes memory y",
745            "bytes memory",
746            "bytes32[] memory",
747            "bytes32[] memory z",
748        ]
749        .iter()
750        .for_each(|x| {
751            AbiParser::default().parse_param(x).unwrap();
752        });
753    }
754
755    #[test]
756    fn can_read_backslashes() {
757        parse(&[
758            "\"function setValue(string)\"",
759            "\"function getValue() external view returns(string)\"",
760        ])
761        .unwrap();
762    }
763
764    #[test]
765    fn can_substitute_structs() {
766        let abi = parse(&[
767            "struct MyStruct {int y; address _addr;}",
768            "event FireEvent(MyStruct m, address indexed newOwner)",
769        ])
770        .unwrap();
771        assert_eq!(
772            abi.events["FireEvent"][0].inputs.clone(),
773            vec![
774                EventParam {
775                    name: "m".to_string(),
776                    kind: ParamType::Tuple(vec![ParamType::Int(256), ParamType::Address]),
777                    indexed: false
778                },
779                EventParam {
780                    name: "newOwner".to_string(),
781                    kind: ParamType::Address,
782                    indexed: true
783                },
784            ]
785        );
786    }
787
788    #[test]
789    fn can_substitute_array_structs() {
790        let abi = parse(&[
791            "struct MyStruct {int y; address _addr;}",
792            "event FireEvent(MyStruct[] m, MyStruct[10] m2)",
793        ])
794        .unwrap();
795
796        assert_eq!(
797            abi.events["FireEvent"][0].inputs.clone(),
798            vec![
799                EventParam {
800                    name: "m".to_string(),
801                    kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
802                        ParamType::Int(256),
803                        ParamType::Address
804                    ]))),
805                    indexed: false
806                },
807                EventParam {
808                    name: "m2".to_string(),
809                    kind: ParamType::FixedArray(
810                        Box::new(ParamType::Tuple(vec![ParamType::Int(256), ParamType::Address])),
811                        10
812                    ),
813                    indexed: false
814                },
815            ]
816        );
817    }
818
819    #[test]
820    fn can_substitute_nested_array_structs() {
821        let abi = parse(&[
822            "struct MyStruct {int y; address _addr;}",
823            "event FireEvent(MyStruct[] m, MyStructWrapper w)",
824            "struct MyStructWrapper {MyStruct y; int y; address _addr;}",
825        ])
826        .unwrap();
827
828        assert_eq!(
829            abi.events["FireEvent"][0].inputs.clone(),
830            vec![
831                EventParam {
832                    name: "m".to_string(),
833                    kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
834                        ParamType::Int(256),
835                        ParamType::Address
836                    ]))),
837                    indexed: false
838                },
839                EventParam {
840                    name: "w".to_string(),
841                    kind: ParamType::Tuple(vec![
842                        ParamType::Tuple(vec![ParamType::Int(256), ParamType::Address]),
843                        ParamType::Int(256),
844                        ParamType::Address
845                    ]),
846                    indexed: false
847                },
848            ]
849        );
850    }
851}