1use 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#[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#[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#[derive(Debug, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct Function {
63 pub name: String,
65 #[serde(default = "default_parameters")]
67 pub inputs: Vec<Parameter>,
68 #[serde(default = "default_parameters")]
70 pub outputs: Vec<Parameter>,
71 pub state_mutability: StateMutability,
75}
76
77impl Function {
78 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) = ¶m.components {
90 let element = Self::to_signature(components);
91 match ¶m.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#[derive(Debug, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct Constructor {
119 pub inputs: Vec<Parameter>,
121 pub state_mutability: StateMutability,
125}
126
127impl Constructor {
128 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) = ¶m.components {
140 let element = Self::to_signature(components);
141 match ¶m.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#[derive(Debug, Serialize, Deserialize)]
163#[serde(rename_all = "camelCase")]
164pub struct Receive {
165 pub state_mutability: StateMutability,
169}
170
171#[derive(Debug, Serialize, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct Fallback {
175 pub state_mutability: StateMutability,
179}
180
181#[derive(Debug, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub enum StateMutability {
184 Pure,
185 View,
186 Nonpayable,
187 Payable,
188}
189
190#[derive(Debug, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct Event {
194 pub name: String,
196 pub inputs: Vec<Parameter>,
198 pub anonymous: bool,
200}
201
202#[derive(Debug, Serialize, Deserialize)]
204#[serde(rename_all = "camelCase")]
205pub struct Error {
206 pub name: String,
208 pub inputs: Vec<Parameter>,
210}
211#[derive(Debug, Clone, Serialize, Deserialize)]
213#[serde(rename_all = "camelCase")]
214pub struct Parameter {
215 pub name: String,
217 pub r#type: Type,
219 pub components: Option<Vec<Parameter>>,
221 #[serde(default = "default_indexed")]
223 pub indexed: bool,
224 pub internal_type: Option<String>,
226}
227
228fn default_indexed() -> bool {
229 false
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
234#[serde(rename_all = "camelCase")]
235pub enum SimpleType {
236 Address,
237 Uint,
238 Int,
239 Bool,
240 Fixed,
241 Ufixed,
242 Function,
244 Bytes,
245 String,
246 Tuple,
247}
248
249impl ToString for SimpleType {
250 fn to_string(&self) -> String {
251 match self {
253 Self::Ufixed => "fixed128x18".into(),
254 Self::Fixed => "ufixed128x18".into(),
255 Self::Int => "int256".into(),
256 Self::Uint => "uint256".into(),
257 _ => {
258 let data = serde_json::to_string(self).unwrap();
259
260 data[1..data.len() - 1].to_string()
261 }
262 }
263 }
264}
265
266impl SimpleType {
267 pub fn is_tuple(&self) -> bool {
268 match self {
269 Self::Tuple => true,
270 _ => false,
271 }
272 }
273}
274
275#[derive(Debug, Clone, PartialEq)]
276pub struct FixedMN {
278 pub m: usize,
279 pub n: usize,
280 pub signed: bool,
281}
282
283impl Display for FixedMN {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 let value = serde_json::to_string(self).expect("Serialize type to json");
286 write!(f, "{}", &value[1..value.len() - 1])
287 }
288}
289
290impl Serialize for FixedMN {
291 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
292 where
293 S: serde::Serializer,
294 {
295 if self.signed {
296 serializer.serialize_str(&format!("fixed{}x{}", self.m, self.n))
297 } else {
298 serializer.serialize_str(&format!("ufixed{}x{}", self.m, self.n))
299 }
300 }
301}
302
303fn fixed_regex() -> Regex {
304 Regex::new(r"^(u){0,1}fixed(\d{1,3})x(\d{1,3})$").unwrap()
305}
306
307impl<'de> Deserialize<'de> for FixedMN {
308 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
309 where
310 D: serde::Deserializer<'de>,
311 {
312 let data = String::deserialize(deserializer)?;
313
314 if let Some(captures) = fixed_regex().captures(&data) {
315 let signed = captures.get(1).map(|_| false).unwrap_or(true);
316
317 let m: usize = (&captures[2]).parse().map_err(serde::de::Error::custom)?;
318 let n: usize = (&captures[3]).parse().map_err(serde::de::Error::custom)?;
319
320 if m < 8 || m > 256 || m % 8 != 0 {
321 return Err(AbiError::FixedMN(
322 data,
323 "M bits must meet the condition 0 < M <= 256, M % 8 == 0".to_string(),
324 ))
325 .map_err(serde::de::Error::custom);
326 }
327
328 if n > 80 {
329 return Err(AbiError::FixedMN(
330 data,
331 "decimal numbers N must meet the condition 0 < N <= 80".to_string(),
332 ))
333 .map_err(serde::de::Error::custom);
334 }
335
336 Ok(Self { signed, m, n })
337 } else {
338 return Err(AbiError::FixedMN(
339 data,
340 "{u}fixed<M>x<N>: fixed-point decimal number of M bits, 8 <= M <= 256, M % 8 == 0, and 0 < N <= 80"
341 .to_string(),
342 ))
343 .map_err(serde::de::Error::custom);
344 }
345 }
346}
347
348#[derive(Debug, Clone, PartialEq)]
350pub struct IntegerM {
351 pub signed: bool,
352 pub m: usize,
353}
354
355impl Display for IntegerM {
356 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
357 let value = serde_json::to_string(self).expect("Serialize type to json");
358 write!(f, "{}", &value[1..value.len() - 1])
359 }
360}
361
362impl Serialize for IntegerM {
363 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
364 where
365 S: serde::Serializer,
366 {
367 if self.signed {
368 serializer.serialize_str(&format!("int{}", self.m,))
369 } else {
370 serializer.serialize_str(&format!("uint{}", self.m,))
371 }
372 }
373}
374
375fn integer_regex() -> Regex {
376 Regex::new(r"^(u){0,1}int(\d{1,3})$").unwrap()
377}
378
379impl<'de> Deserialize<'de> for IntegerM {
380 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
381 where
382 D: serde::Deserializer<'de>,
383 {
384 let data = String::deserialize(deserializer)?;
385
386 if let Some(captures) = integer_regex().captures(&data) {
387 let signed = captures.get(1).map(|_| false).unwrap_or(true);
388
389 let m: usize = (&captures[2]).parse().map_err(serde::de::Error::custom)?;
390
391 if m < 8 || m > 256 || m % 8 != 0 {
392 return Err(AbiError::IntegerM(
393 data,
394 "M bits must meet the condition 0 < M <= 256, M % 8 == 0".to_string(),
395 ))
396 .map_err(serde::de::Error::custom);
397 }
398
399 Ok(Self { signed, m })
400 } else {
401 return Err(AbiError::FixedMN(
402 data,
403 "{u}int<M>: unsigned integer type of M bits, 0 < M <= 256, M % 8 == 0".to_string(),
404 ))
405 .map_err(serde::de::Error::custom);
406 }
407 }
408}
409
410#[derive(Debug, Clone, PartialEq)]
411pub struct BytesM {
413 pub m: usize,
414}
415
416impl Display for BytesM {
417 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
418 let value = serde_json::to_string(self).expect("Serialize type to json");
419 write!(f, "{}", &value[1..value.len() - 1])
420 }
421}
422
423impl Serialize for BytesM {
424 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
425 where
426 S: serde::Serializer,
427 {
428 serializer.serialize_str(&format!("bytes{}", self.m,))
429 }
430}
431
432impl<'de> Deserialize<'de> for BytesM {
433 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
434 where
435 D: serde::Deserializer<'de>,
436 {
437 let data = String::deserialize(deserializer)?;
438
439 if data.starts_with("bytes") {
440 let m: usize = (&data[5..]).parse().map_err(serde::de::Error::custom)?;
441
442 if m > 32 {
443 return Err(AbiError::BytesM(data, "0 < M <= 32".to_string()))
444 .map_err(serde::de::Error::custom);
445 }
446
447 Ok(Self { m })
448 } else {
449 return Err(AbiError::BytesM(
450 data,
451 "bytes<M>: binary type of M bytes, 0 < M <= 32".to_string(),
452 ))
453 .map_err(serde::de::Error::custom);
454 }
455 }
456}
457
458#[derive(Debug, Clone, PartialEq)]
459pub enum Type {
460 Simple(SimpleType),
461
462 BytesM(BytesM),
463
464 IntegerM(IntegerM),
465
466 FixedMN(FixedMN),
467
468 ArrayM(Box<ArrayM>),
469 Array(Box<Array>),
470}
471
472impl From<Type> for String {
473 fn from(value: Type) -> Self {
474 let str = serde_json::to_string(&value).unwrap();
475
476 str[1..str.len() - 1].to_owned()
477 }
478}
479
480impl FromStr for Type {
481 type Err = serde_json::Error;
482 fn from_str(s: &str) -> Result<Self, Self::Err> {
483 serde_json::from_str(&format!("\"{}\"", s))
484 }
485}
486
487impl Display for Type {
488 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
489 let value = serde_json::to_string(self).expect("Serialize type to json");
490 write!(f, "{}", &value[1..value.len() - 1])
491 }
492}
493
494impl Serialize for Type {
495 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
496 where
497 S: serde::Serializer,
498 {
499 match self {
500 Self::Simple(simple) => simple.serialize(serializer),
501 Self::BytesM(byte_m) => byte_m.serialize(serializer),
502 Self::IntegerM(integer_m) => integer_m.serialize(serializer),
503 Self::FixedMN(fixed_m) => fixed_m.serialize(serializer),
504 Self::ArrayM(array_m) => array_m.serialize(serializer),
505 Self::Array(array) => array.serialize(serializer),
506 }
507 }
508}
509
510impl<'de> Deserialize<'de> for Type {
511 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
512 where
513 D: serde::Deserializer<'de>,
514 {
515 let data = String::deserialize(deserializer)?;
516
517 let data = format!("\"{}\"", data);
518
519 if let Ok(array_m) = serde_json::from_str::<ArrayM>(&data) {
520 return Ok(Self::ArrayM(Box::new(array_m)));
521 }
522
523 if let Ok(array) = serde_json::from_str::<Array>(&data) {
524 return Ok(Self::Array(Box::new(array)));
525 }
526
527 if let Ok(fixed_m_n) = serde_json::from_str::<FixedMN>(&data) {
528 return Ok(Self::FixedMN(fixed_m_n));
529 }
530
531 if let Ok(integer_m) = serde_json::from_str::<IntegerM>(&data) {
532 return Ok(Self::IntegerM(integer_m));
533 }
534
535 if let Ok(bytes_m) = serde_json::from_str::<BytesM>(&data) {
536 return Ok(Self::BytesM(bytes_m));
537 }
538
539 if let Ok(simple_type) = serde_json::from_str::<SimpleType>(&data) {
540 return Ok(Self::Simple(simple_type));
541 }
542
543 return Err(AbiError::UnknownType(data)).map_err(serde::de::Error::custom);
544 }
545}
546
547#[derive(Debug, Clone, PartialEq)]
548pub struct ArrayM {
550 pub element: Type,
551 pub m: usize,
553}
554
555impl Display for ArrayM {
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 ArrayM {
563 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
564 where
565 S: serde::Serializer,
566 {
567 let element = serde_json::to_string(&self.element).map_err(serde::ser::Error::custom)?;
568
569 serializer.serialize_str(&format!("{}[{}]", &element[1..element.len() - 1], self.m))
570 }
571}
572
573fn array_m_regex() -> Regex {
574 Regex::new(r"\[(\d{1,3})\]$").unwrap()
575}
576
577impl<'de> Deserialize<'de> for ArrayM {
578 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
579 where
580 D: serde::Deserializer<'de>,
581 {
582 let array_m = String::deserialize(deserializer)?;
583
584 let end_with_regex = array_m_regex();
585
586 if let Some(caps) = end_with_regex.captures(&array_m) {
587 let m: usize = (&caps[1]).parse().map_err(serde::de::Error::custom)?;
588
589 let data = format!("\"{}\"", &array_m[..array_m.len() - caps.len() - 2]);
590
591 let element: Type = serde_json::from_str(&data).map_err(serde::de::Error::custom)?;
592
593 return Ok(Self { element, m });
594 } else {
595 return Err(AbiError::ArrayM(
596 array_m,
597 "<type>[M]: a fixed-length array of M elements, M >= 0, of the given type"
598 .to_string(),
599 ))
600 .map_err(serde::de::Error::custom);
601 }
602 }
603}
604
605#[derive(Debug, Clone, PartialEq)]
606pub struct Array {
608 pub element: Type,
609}
610
611impl Display for Array {
612 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
613 let value = serde_json::to_string(self).expect("Serialize type to json");
614 write!(f, "{}", &value[1..value.len() - 1])
615 }
616}
617
618impl Serialize for Array {
619 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
620 where
621 S: serde::Serializer,
622 {
623 let element = serde_json::to_string(&self.element).map_err(serde::ser::Error::custom)?;
624
625 serializer.serialize_str(&format!("{}[]", &element[1..element.len() - 1]))
626 }
627}
628
629impl<'de> Deserialize<'de> for Array {
630 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
631 where
632 D: serde::Deserializer<'de>,
633 {
634 let array_m = String::deserialize(deserializer)?;
635
636 if array_m.ends_with("[]") {
637 let data = format!("\"{}\"", &array_m[..array_m.len() - 2]);
638 let element: Type = serde_json::from_str(&data).map_err(serde::de::Error::custom)?;
639
640 return Ok(Self { element });
641 } else {
642 return Err(AbiError::Array(
643 array_m,
644 "<type>[]: a variable-length array of elements of the given type.".to_string(),
645 ))
646 .map_err(serde::de::Error::custom);
647 }
648 }
649}
650
651#[cfg(test)]
652mod tests {
653
654 use super::*;
655
656 #[test]
657 fn test_fixed_regex() {
658 _ = pretty_env_logger::try_init();
659 let re = fixed_regex();
660
661 assert!(re.is_match("ufixed100x18"));
662
663 assert!(re.is_match("fixed100x18"));
664
665 assert!(!re.is_match("fixed1000x18"));
666
667 assert!(!re.is_match("ufixed1000x18"));
668 assert!(!re.is_match("uufixed1000x18"));
669
670 assert!(!re.is_match("fixed-100x18"));
671
672 if let Some(captures) = fixed_regex().captures("fixed128x18") {
673 assert_eq!(captures.get(1), None);
674 assert_eq!(captures.get(2).map(|c| c.as_str()), Some("128"));
675 assert_eq!(captures.get(3).map(|c| c.as_str()), Some("18"));
676 }
677 }
678
679 #[test]
680 fn test_fixed_json() {
681 let fixed: FixedMN = serde_json::from_str(r#""fixed128x18""#).expect("Parse fixed");
682
683 assert_eq!(fixed.signed, true);
684 assert_eq!(fixed.m, 128);
685 assert_eq!(fixed.n, 18);
686
687 let fixed: FixedMN = serde_json::from_str(r#""ufixed128x18""#).expect("Parse fixed");
688
689 assert_eq!(fixed.signed, false);
690 assert_eq!(fixed.m, 128);
691 assert_eq!(fixed.n, 18);
692
693 serde_json::from_str::<FixedMN>(r#""ufixed100x18""#).expect_err("M % 8 == 0");
694
695 serde_json::from_str::<FixedMN>(r#""ufixed128x180""#).expect_err("N <= 80");
696 }
697
698 #[test]
699 fn test_int_json() {
700 let fixed: IntegerM = serde_json::from_str(r#""int128""#).expect("Parse integer");
701
702 assert_eq!(fixed.signed, true);
703 assert_eq!(fixed.m, 128);
704
705 let fixed: IntegerM = serde_json::from_str(r#""uint128""#).expect("Parse integer");
706
707 assert_eq!(fixed.signed, false);
708 assert_eq!(fixed.m, 128);
709
710 serde_json::from_str::<IntegerM>(r#""uint100""#).expect_err("M % 8 == 0");
711 }
712
713 #[test]
714 fn test_end_with() {
715 let end_with_regex = array_m_regex();
716
717 let caps = end_with_regex.captures("Hello[1][123]").unwrap();
718
719 assert_eq!(&caps[1], "123");
720 }
721
722 #[test]
723 fn test_type_serde() {
724 _ = pretty_env_logger::try_init();
725 fn check(expect: &str) {
726 let t: Type = expect.parse().expect("Parse type string");
727
728 let data: String = t.into();
729
730 assert_eq!(data, expect);
731 }
732
733 let test_vector = vec![
734 "uint256",
735 "int256",
736 "address",
737 "int8",
738 "uint",
739 "int",
740 "bool",
741 "fixed128x16",
742 "ufixed128x16",
743 "fixed",
744 "ufixed",
745 "bytes",
746 "bytes24",
747 "tuple",
748 "function",
749 "string",
750 "tuple[]",
751 "tuple[][32]",
752 "bool[20]",
753 "uint256[20]",
754 ];
755
756 for v in test_vector {
757 check(v);
758 }
759 }
760
761 #[test]
762 fn test_hardhat_artifact() {
763 let _: HardhatArtifact =
764 serde_json::from_str(include_str!("abi.json")).expect("Parse hardhat artifact");
765 }
766
767 #[test]
768 fn test_field() {
769 let data = r#"
770 {
771 "inputs": [
772 {
773 "internalType": "address",
774 "name": "WETH_",
775 "type": "address"
776 }
777 ],
778 "stateMutability": "nonpayable",
779 "type": "constructor"
780 }
781 "#;
782
783 _ = serde_json::from_str::<AbiField>(data).expect("Parse abi field");
784 }
785}