ethbind/
typedef.rs

1//! The rust types of Solidity(Contract) ABI metadata
2//!
3//! Visit [`official document`](https://docs.soliditylang.org/en/v0.8.17/abi-spec.html#json) for details
4
5use std::{fmt::Display, str::FromStr};
6
7use regex::Regex;
8use serde::{Deserialize, Serialize};
9
10use thiserror::Error;
11
12#[derive(Debug, Error)]
13pub enum AbiError {
14    #[error("Invalid fixed type declare {0}, {1}")]
15    FixedMN(String, String),
16
17    #[error("Invalid integer type declare {0}, {1}")]
18    IntegerM(String, String),
19
20    #[error("Invalid fixed length binary type declare {0}, {1}")]
21    BytesM(String, String),
22
23    #[error("Invalid tuple type declare {0}, {1}")]
24    Tuple(String, String),
25
26    #[error("Invalid fixed-length Array type declare {0}, {1}")]
27    ArrayM(String, String),
28
29    #[error("Invalid Array type declare {0}, {1}")]
30    Array(String, String),
31
32    #[error("Invalid Type declare {0}")]
33    UnknownType(String),
34}
35
36/// Hardhat generate artifact
37#[derive(Debug, Serialize, Deserialize)]
38#[serde(rename_all = "camelCase")]
39pub struct HardhatArtifact {
40    pub contract_name: String,
41    pub source_name: String,
42    pub abi: Vec<AbiField>,
43    pub bytecode: String,
44    pub deployed_bytecode: String,
45}
46
47/// Contract interface type enum
48#[derive(Debug, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase", tag = "type")]
50pub enum AbiField {
51    Function(Function),
52    Constructor(Constructor),
53    Receive(Receive),
54    Fallback(Fallback),
55    Event(Event),
56    Error(Error),
57}
58
59/// A structure type to represent `function` abi
60#[derive(Debug, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct Function {
63    /// the function name
64    pub name: String,
65    /// An array of function's input params
66    #[serde(default = "default_parameters")]
67    pub inputs: Vec<Parameter>,
68    /// An array of function's output params
69    #[serde(default = "default_parameters")]
70    pub outputs: Vec<Parameter>,
71    /// a string with one of the following values: pure (specified to not read blockchain state),
72    /// view (specified to not modify the blockchain state),
73    /// nonpayable (function does not accept Ether - the default) and payable (function accepts Ether)
74    pub state_mutability: StateMutability,
75}
76
77impl Function {
78    /// Only include inputs,e.g: withdraw(address)
79    pub fn signature(&self) -> String {
80        let tuple = Self::to_signature(&self.inputs);
81
82        format!("{}{}", self.name, tuple)
83    }
84
85    fn to_signature(params: &[Parameter]) -> String {
86        let mut pairs = vec![];
87
88        for param in params.iter() {
89            if let Some(components) = &param.components {
90                let element = Self::to_signature(components);
91                match &param.r#type {
92                    Type::Array(_) => {
93                        pairs.push(format!("{}[]", element));
94                    }
95                    Type::ArrayM(array_m) => {
96                        pairs.push(format!("{}[{}]", element, array_m.m));
97                    }
98                    _ => {
99                        pairs.push(format!("{}", element));
100                    }
101                }
102            } else {
103                pairs.push(format!("{}", param.r#type));
104            }
105        }
106
107        format!("({})", pairs.join(","))
108    }
109}
110
111fn default_parameters() -> Vec<Parameter> {
112    vec![]
113}
114
115/// A structure type to represent `constructor` abi
116#[derive(Debug, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct Constructor {
119    /// An array of function's input params
120    pub inputs: Vec<Parameter>,
121    /// a string with one of the following values: pure (specified to not read blockchain state),
122    /// view (specified to not modify the blockchain state),
123    /// nonpayable (function does not accept Ether - the default) and payable (function accepts Ether)
124    pub state_mutability: StateMutability,
125}
126
127impl Constructor {
128    /// Only include inputs,e.g: withdraw(address)
129    pub fn signature(&self) -> String {
130        let tuple = Self::to_signature(&self.inputs);
131
132        format!("Constructor{}", tuple)
133    }
134
135    fn to_signature(params: &[Parameter]) -> String {
136        let mut pairs = vec![];
137
138        for param in params.iter() {
139            if let Some(components) = &param.components {
140                let element = Self::to_signature(components);
141                match &param.r#type {
142                    Type::Array(_) => {
143                        pairs.push(format!("{}[]", element));
144                    }
145                    Type::ArrayM(array_m) => {
146                        pairs.push(format!("{}[{}]", element, array_m.m));
147                    }
148                    _ => {
149                        pairs.push(format!("{}", element));
150                    }
151                }
152            } else {
153                pairs.push(format!("{}", param.r#type));
154            }
155        }
156
157        format!("({})", pairs.join(","))
158    }
159}
160
161/// A structure type to represent `receive function` abi
162#[derive(Debug, Serialize, Deserialize)]
163#[serde(rename_all = "camelCase")]
164pub struct Receive {
165    /// a string with one of the following values: pure (specified to not read blockchain state),
166    /// view (specified to not modify the blockchain state),
167    /// nonpayable (function does not accept Ether - the default) and payable (function accepts Ether)
168    pub state_mutability: StateMutability,
169}
170
171/// A structure type to represent `fallback function` abi
172#[derive(Debug, Serialize, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct Fallback {
175    /// a string with one of the following values: pure (specified to not read blockchain state),
176    /// view (specified to not modify the blockchain state),
177    /// nonpayable (function does not accept Ether - the default) and payable (function accepts Ether)
178    pub state_mutability: StateMutability,
179}
180
181#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub enum StateMutability {
184    Pure,
185    View,
186    Nonpayable,
187    Payable,
188}
189
190/// A structure type to represent `event` abi
191#[derive(Debug, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct Event {
194    /// the function name
195    pub name: String,
196    /// An array of function's input params
197    pub inputs: Vec<Parameter>,
198    /// `true` if the event was declared as anonymous
199    pub anonymous: bool,
200}
201
202impl Event {
203    /// Only include inputs,e.g: withdraw(address)
204    pub fn signature(&self) -> String {
205        let tuple = Self::to_signature(&self.inputs);
206
207        format!("{}{}", self.name, tuple)
208    }
209
210    fn to_signature(params: &[Parameter]) -> String {
211        let mut pairs = vec![];
212
213        for param in params.iter() {
214            if let Some(components) = &param.components {
215                let element = Self::to_signature(components);
216                match &param.r#type {
217                    Type::Array(_) => {
218                        pairs.push(format!("{}[]", element));
219                    }
220                    Type::ArrayM(array_m) => {
221                        pairs.push(format!("{}[{}]", element, array_m.m));
222                    }
223                    _ => {
224                        pairs.push(format!("{}", element));
225                    }
226                }
227            } else {
228                pairs.push(format!("{}", param.r#type));
229            }
230        }
231
232        format!("({})", pairs.join(","))
233    }
234}
235
236/// A structure type to represent `event` abi
237#[derive(Debug, Serialize, Deserialize)]
238#[serde(rename_all = "camelCase")]
239pub struct Error {
240    /// the function name
241    pub name: String,
242    /// An array of function's input params
243    pub inputs: Vec<Parameter>,
244}
245
246impl Error {
247    /// Only include inputs,e.g: withdraw(address)
248    pub fn signature(&self) -> String {
249        let tuple = Self::to_signature(&self.inputs);
250
251        format!("{}{}", self.name, tuple)
252    }
253
254    fn to_signature(params: &[Parameter]) -> String {
255        let mut pairs = vec![];
256
257        for param in params.iter() {
258            if let Some(components) = &param.components {
259                let element = Self::to_signature(components);
260                match &param.r#type {
261                    Type::Array(_) => {
262                        pairs.push(format!("{}[]", element));
263                    }
264                    Type::ArrayM(array_m) => {
265                        pairs.push(format!("{}[{}]", element, array_m.m));
266                    }
267                    _ => {
268                        pairs.push(format!("{}", element));
269                    }
270                }
271            } else {
272                pairs.push(format!("{}", param.r#type));
273            }
274        }
275
276        format!("({})", pairs.join(","))
277    }
278}
279/// Handle Function/Event/Error 's input or output parameter type
280#[derive(Debug, Clone, Serialize, Deserialize)]
281#[serde(rename_all = "camelCase")]
282pub struct Parameter {
283    /// The name of the parameter
284    pub name: String,
285    /// The canonical type of the parameter
286    pub r#type: Type,
287    /// used for tuple types, only if the type field start with prefix `tuple`. e.g, `tupe[]`,`tuple`
288    pub components: Option<Vec<Parameter>>,
289    /// This field is only meaningful for `Event` or `Error`
290    #[serde(default = "default_indexed")]
291    pub indexed: bool,
292    /// Hardhat extension field
293    pub internal_type: Option<String>,
294}
295
296fn default_indexed() -> bool {
297    false
298}
299
300/// Contract abi simple types enum
301#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
302#[serde(rename_all = "camelCase")]
303pub enum SimpleType {
304    Address,
305    Uint,
306    Int,
307    Bool,
308    Fixed,
309    Ufixed,
310    /// an address (20 bytes) followed by a function selector (4 bytes). Encoded identical to bytes24.
311    Function,
312    Bytes,
313    String,
314    Tuple,
315}
316
317impl ToString for SimpleType {
318    fn to_string(&self) -> String {
319        // to canonical type name
320        match self {
321            Self::Ufixed => "fixed128x18".into(),
322            Self::Fixed => "ufixed128x18".into(),
323            Self::Int => "int256".into(),
324            Self::Uint => "uint256".into(),
325            _ => {
326                let data = serde_json::to_string(self).unwrap();
327
328                data[1..data.len() - 1].to_string()
329            }
330        }
331    }
332}
333
334impl SimpleType {
335    pub fn is_tuple(&self) -> bool {
336        match self {
337            Self::Tuple => true,
338            _ => false,
339        }
340    }
341}
342
343#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
344/// fixed-point decimal number of M bits, 8 <= M <= 256, M % 8 == 0, and 0 < N <= 80, which denotes the value v as v / (10 ** N).
345pub struct FixedMN {
346    pub m: usize,
347    pub n: usize,
348    pub signed: bool,
349}
350
351impl Display for FixedMN {
352    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
353        let value = serde_json::to_string(self).expect("Serialize type to json");
354        write!(f, "{}", &value[1..value.len() - 1])
355    }
356}
357
358impl Serialize for FixedMN {
359    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
360    where
361        S: serde::Serializer,
362    {
363        if self.signed {
364            serializer.serialize_str(&format!("fixed{}x{}", self.m, self.n))
365        } else {
366            serializer.serialize_str(&format!("ufixed{}x{}", self.m, self.n))
367        }
368    }
369}
370
371fn fixed_regex() -> Regex {
372    Regex::new(r"^(u){0,1}fixed(\d{1,3})x(\d{1,3})$").unwrap()
373}
374
375impl<'de> Deserialize<'de> for FixedMN {
376    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
377    where
378        D: serde::Deserializer<'de>,
379    {
380        let data = String::deserialize(deserializer)?;
381
382        if let Some(captures) = fixed_regex().captures(&data) {
383            let signed = captures.get(1).map(|_| false).unwrap_or(true);
384
385            let m: usize = (&captures[2]).parse().map_err(serde::de::Error::custom)?;
386            let n: usize = (&captures[3]).parse().map_err(serde::de::Error::custom)?;
387
388            if m < 8 || m > 256 || m % 8 != 0 {
389                return Err(AbiError::FixedMN(
390                    data,
391                    "M bits must meet the condition 0 < M <= 256, M % 8 == 0".to_string(),
392                ))
393                .map_err(serde::de::Error::custom);
394            }
395
396            if n > 80 {
397                return Err(AbiError::FixedMN(
398                    data,
399                    "decimal numbers N must meet the condition 0 < N <= 80".to_string(),
400                ))
401                .map_err(serde::de::Error::custom);
402            }
403
404            Ok(Self { signed, m, n })
405        } else {
406            return Err(AbiError::FixedMN(
407                data,
408                "{u}fixed<M>x<N>: fixed-point decimal number of M bits, 8 <= M <= 256, M % 8 == 0, and 0 < N <= 80"
409                    .to_string(),
410            ))
411            .map_err(serde::de::Error::custom);
412        }
413    }
414}
415
416/// integer type of M bits, 0 < M <= 256, M % 8 == 0. e.g. uint32, uint8
417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
418pub struct IntegerM {
419    pub signed: bool,
420    pub m: usize,
421}
422
423impl Display for IntegerM {
424    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
425        let value = serde_json::to_string(self).expect("Serialize type to json");
426        write!(f, "{}", &value[1..value.len() - 1])
427    }
428}
429
430impl Serialize for IntegerM {
431    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
432    where
433        S: serde::Serializer,
434    {
435        if self.signed {
436            serializer.serialize_str(&format!("int{}", self.m,))
437        } else {
438            serializer.serialize_str(&format!("uint{}", self.m,))
439        }
440    }
441}
442
443fn integer_regex() -> Regex {
444    Regex::new(r"^(u){0,1}int(\d{1,3})$").unwrap()
445}
446
447impl<'de> Deserialize<'de> for IntegerM {
448    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
449    where
450        D: serde::Deserializer<'de>,
451    {
452        let data = String::deserialize(deserializer)?;
453
454        if let Some(captures) = integer_regex().captures(&data) {
455            let signed = captures.get(1).map(|_| false).unwrap_or(true);
456
457            let m: usize = (&captures[2]).parse().map_err(serde::de::Error::custom)?;
458
459            if m < 8 || m > 256 || m % 8 != 0 {
460                return Err(AbiError::IntegerM(
461                    data,
462                    "M bits must meet the condition 0 < M <= 256, M % 8 == 0".to_string(),
463                ))
464                .map_err(serde::de::Error::custom);
465            }
466
467            Ok(Self { signed, m })
468        } else {
469            return Err(AbiError::FixedMN(
470                data,
471                "{u}int<M>: unsigned integer type of M bits, 0 < M <= 256, M % 8 == 0".to_string(),
472            ))
473            .map_err(serde::de::Error::custom);
474        }
475    }
476}
477
478#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
479/// binary type of M bytes, 0 < M <= 32
480pub struct BytesM {
481    pub m: usize,
482}
483
484impl Display for BytesM {
485    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
486        let value = serde_json::to_string(self).expect("Serialize type to json");
487        write!(f, "{}", &value[1..value.len() - 1])
488    }
489}
490
491impl Serialize for BytesM {
492    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
493    where
494        S: serde::Serializer,
495    {
496        serializer.serialize_str(&format!("bytes{}", self.m,))
497    }
498}
499
500impl<'de> Deserialize<'de> for BytesM {
501    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
502    where
503        D: serde::Deserializer<'de>,
504    {
505        let data = String::deserialize(deserializer)?;
506
507        if data.starts_with("bytes") {
508            let m: usize = (&data[5..]).parse().map_err(serde::de::Error::custom)?;
509
510            if m > 32 {
511                return Err(AbiError::BytesM(data, "0 < M <= 32".to_string()))
512                    .map_err(serde::de::Error::custom);
513            }
514
515            Ok(Self { m })
516        } else {
517            return Err(AbiError::BytesM(
518                data,
519                "bytes<M>: binary type of M bytes, 0 < M <= 32".to_string(),
520            ))
521            .map_err(serde::de::Error::custom);
522        }
523    }
524}
525
526#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
527pub enum Type {
528    Simple(SimpleType),
529
530    BytesM(BytesM),
531
532    IntegerM(IntegerM),
533
534    FixedMN(FixedMN),
535
536    ArrayM(Box<ArrayM>),
537    Array(Box<Array>),
538}
539
540impl From<Type> for String {
541    fn from(value: Type) -> Self {
542        let str = serde_json::to_string(&value).unwrap();
543
544        str[1..str.len() - 1].to_owned()
545    }
546}
547
548impl FromStr for Type {
549    type Err = serde_json::Error;
550    fn from_str(s: &str) -> Result<Self, Self::Err> {
551        serde_json::from_str(&format!("\"{}\"", s))
552    }
553}
554
555impl Display for Type {
556    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
557        let value = serde_json::to_string(self).expect("Serialize type to json");
558        write!(f, "{}", &value[1..value.len() - 1])
559    }
560}
561
562impl Serialize for Type {
563    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
564    where
565        S: serde::Serializer,
566    {
567        match self {
568            Self::Simple(simple) => simple.serialize(serializer),
569            Self::BytesM(byte_m) => byte_m.serialize(serializer),
570            Self::IntegerM(integer_m) => integer_m.serialize(serializer),
571            Self::FixedMN(fixed_m) => fixed_m.serialize(serializer),
572            Self::ArrayM(array_m) => array_m.serialize(serializer),
573            Self::Array(array) => array.serialize(serializer),
574        }
575    }
576}
577
578impl<'de> Deserialize<'de> for Type {
579    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
580    where
581        D: serde::Deserializer<'de>,
582    {
583        let data = String::deserialize(deserializer)?;
584
585        let data = format!("\"{}\"", data);
586
587        if let Ok(array_m) = serde_json::from_str::<ArrayM>(&data) {
588            return Ok(Self::ArrayM(Box::new(array_m)));
589        }
590
591        if let Ok(array) = serde_json::from_str::<Array>(&data) {
592            return Ok(Self::Array(Box::new(array)));
593        }
594
595        if let Ok(fixed_m_n) = serde_json::from_str::<FixedMN>(&data) {
596            return Ok(Self::FixedMN(fixed_m_n));
597        }
598
599        if let Ok(integer_m) = serde_json::from_str::<IntegerM>(&data) {
600            return Ok(Self::IntegerM(integer_m));
601        }
602
603        if let Ok(bytes_m) = serde_json::from_str::<BytesM>(&data) {
604            return Ok(Self::BytesM(bytes_m));
605        }
606
607        if let Ok(simple_type) = serde_json::from_str::<SimpleType>(&data) {
608            return Ok(Self::Simple(simple_type));
609        }
610
611        return Err(AbiError::UnknownType(data)).map_err(serde::de::Error::custom);
612    }
613}
614
615#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
616/// a fixed-length array of M elements, M >= 0, of the given type.
617pub struct ArrayM {
618    pub element: Type,
619    /// fixed-length array of `m` elements, M >= 0,
620    pub m: usize,
621}
622
623impl Display for ArrayM {
624    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
625        let value = serde_json::to_string(self).expect("Serialize type to json");
626        write!(f, "{}", &value[1..value.len() - 1])
627    }
628}
629
630impl Serialize for ArrayM {
631    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
632    where
633        S: serde::Serializer,
634    {
635        let element = serde_json::to_string(&self.element).map_err(serde::ser::Error::custom)?;
636
637        serializer.serialize_str(&format!("{}[{}]", &element[1..element.len() - 1], self.m))
638    }
639}
640
641fn array_m_regex() -> Regex {
642    Regex::new(r"\[(\d{1,3})\]$").unwrap()
643}
644
645impl<'de> Deserialize<'de> for ArrayM {
646    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
647    where
648        D: serde::Deserializer<'de>,
649    {
650        let array_m = String::deserialize(deserializer)?;
651
652        let end_with_regex = array_m_regex();
653
654        if let Some(caps) = end_with_regex.captures(&array_m) {
655            let m: usize = (&caps[1]).parse().map_err(serde::de::Error::custom)?;
656
657            let data = format!("\"{}\"", &array_m[..array_m.len() - caps.len() - 2]);
658
659            let element: Type = serde_json::from_str(&data).map_err(serde::de::Error::custom)?;
660
661            return Ok(Self { element, m });
662        } else {
663            return Err(AbiError::ArrayM(
664                array_m,
665                "<type>[M]: a fixed-length array of M elements, M >= 0, of the given type"
666                    .to_string(),
667            ))
668            .map_err(serde::de::Error::custom);
669        }
670    }
671}
672
673#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
674/// a variable-length array of elements of the given type
675pub struct Array {
676    pub element: Type,
677}
678
679impl Display for Array {
680    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
681        let value = serde_json::to_string(self).expect("Serialize type to json");
682        write!(f, "{}", &value[1..value.len() - 1])
683    }
684}
685
686impl Serialize for Array {
687    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
688    where
689        S: serde::Serializer,
690    {
691        let element = serde_json::to_string(&self.element).map_err(serde::ser::Error::custom)?;
692
693        serializer.serialize_str(&format!("{}[]", &element[1..element.len() - 1]))
694    }
695}
696
697impl<'de> Deserialize<'de> for Array {
698    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
699    where
700        D: serde::Deserializer<'de>,
701    {
702        let array_m = String::deserialize(deserializer)?;
703
704        if array_m.ends_with("[]") {
705            let data = format!("\"{}\"", &array_m[..array_m.len() - 2]);
706            let element: Type = serde_json::from_str(&data).map_err(serde::de::Error::custom)?;
707
708            return Ok(Self { element });
709        } else {
710            return Err(AbiError::Array(
711                array_m,
712                "<type>[]: a variable-length array of elements of the given type.".to_string(),
713            ))
714            .map_err(serde::de::Error::custom);
715        }
716    }
717}
718
719#[cfg(test)]
720mod tests {
721
722    use super::*;
723
724    #[test]
725    fn test_fixed_regex() {
726        // _ = pretty_env_logger::try_init();
727        let re = fixed_regex();
728
729        assert!(re.is_match("ufixed100x18"));
730
731        assert!(re.is_match("fixed100x18"));
732
733        assert!(!re.is_match("fixed1000x18"));
734
735        assert!(!re.is_match("ufixed1000x18"));
736        assert!(!re.is_match("uufixed1000x18"));
737
738        assert!(!re.is_match("fixed-100x18"));
739
740        if let Some(captures) = fixed_regex().captures("fixed128x18") {
741            assert_eq!(captures.get(1), None);
742            assert_eq!(captures.get(2).map(|c| c.as_str()), Some("128"));
743            assert_eq!(captures.get(3).map(|c| c.as_str()), Some("18"));
744        }
745    }
746
747    #[test]
748    fn test_fixed_json() {
749        let fixed: FixedMN = serde_json::from_str(r#""fixed128x18""#).expect("Parse fixed");
750
751        assert_eq!(fixed.signed, true);
752        assert_eq!(fixed.m, 128);
753        assert_eq!(fixed.n, 18);
754
755        let fixed: FixedMN = serde_json::from_str(r#""ufixed128x18""#).expect("Parse fixed");
756
757        assert_eq!(fixed.signed, false);
758        assert_eq!(fixed.m, 128);
759        assert_eq!(fixed.n, 18);
760
761        serde_json::from_str::<FixedMN>(r#""ufixed100x18""#).expect_err("M % 8 == 0");
762
763        serde_json::from_str::<FixedMN>(r#""ufixed128x180""#).expect_err("N <= 80");
764    }
765
766    #[test]
767    fn test_int_json() {
768        let fixed: IntegerM = serde_json::from_str(r#""int128""#).expect("Parse integer");
769
770        assert_eq!(fixed.signed, true);
771        assert_eq!(fixed.m, 128);
772
773        let fixed: IntegerM = serde_json::from_str(r#""uint128""#).expect("Parse integer");
774
775        assert_eq!(fixed.signed, false);
776        assert_eq!(fixed.m, 128);
777
778        serde_json::from_str::<IntegerM>(r#""uint100""#).expect_err("M % 8 == 0");
779    }
780
781    #[test]
782    fn test_end_with() {
783        let end_with_regex = array_m_regex();
784
785        let caps = end_with_regex.captures("Hello[1][123]").unwrap();
786
787        assert_eq!(&caps[1], "123");
788    }
789
790    #[test]
791    fn test_type_serde() {
792        // _ = pretty_env_logger::try_init();
793        fn check(expect: &str) {
794            let t: Type = expect.parse().expect("Parse type string");
795
796            let data: String = t.into();
797
798            assert_eq!(data, expect);
799        }
800
801        let test_vector = vec![
802            "uint256",
803            "int256",
804            "address",
805            "int8",
806            "uint",
807            "int",
808            "bool",
809            "fixed128x16",
810            "ufixed128x16",
811            "fixed",
812            "ufixed",
813            "bytes",
814            "bytes24",
815            "tuple",
816            "function",
817            "string",
818            "tuple[]",
819            "tuple[][32]",
820            "bool[20]",
821            "uint256[20]",
822        ];
823
824        for v in test_vector {
825            check(v);
826        }
827    }
828
829    #[test]
830    fn test_hardhat_artifact() {
831        let _: HardhatArtifact =
832            serde_json::from_str(include_str!("abi.json")).expect("Parse hardhat artifact");
833    }
834
835    #[test]
836    fn test_field() {
837        let data = r#"
838             {
839      "inputs": [
840        {
841          "internalType": "address",
842          "name": "WETH_",
843          "type": "address"
844        }
845      ],
846      "stateMutability": "nonpayable",
847      "type": "constructor"
848    }
849        "#;
850
851        _ = serde_json::from_str::<AbiField>(data).expect("Parse abi field");
852    }
853}