1use std::collections::HashMap;
2use std::fs::File;
3use std::path::Path;
4
5use tiny_keccak::{Hasher, Keccak};
6
7mod function;
8mod parameter;
9
10use function::Function;
11pub use function::StateMutability;
12pub use parameter::Parameter;
13use parameter::ParameterType;
14
15pub struct Abi {
20 pub functions: HashMap<String, Function>,
21}
22
23impl Default for Abi {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl Abi {
30 #[inline]
32 pub fn new() -> Self {
33 Self {
34 functions: HashMap::new(),
35 }
36 }
37
38 pub fn parse_json(&mut self, abi: serde_json::Value) -> Result<(), AbiParserError> {
40 let mut i: usize = 0;
41 while abi[i] != serde_json::Value::Null {
42 if abi[i]["type"] == "function" {
43 if abi[i]["name"] != serde_json::Value::Null {
44 let name = abi[i]["name"].as_str().unwrap().to_owned();
45 self.functions.insert(name, Function::parse(&abi[i])?);
46 } else {
47 return Err(AbiParserError::MissingData(
48 "Function name is missing from ABI.".to_owned(),
49 ));
50 }
51 }
52 i += 1;
53 }
54
55 Ok(())
56 }
57
58 pub fn parse_file(&mut self, path_to_abi: &Path) -> Result<(), AbiParserError> {
60 let reader =
61 File::open(path_to_abi).map_err(|e| AbiParserError::FileIoError(e.to_string()))?;
62 let abi: serde_json::Value =
63 serde_json::from_reader(reader).map_err(|e| AbiParserError::Serde(e.to_string()))?;
64
65 self.parse_json(abi)
66 }
67
68 pub fn get_state_mutability(&self, function_name: &str) -> Option<StateMutability> {
69 if let Some(function) = self.functions.get(function_name) {
70 return function.state_mutability;
71 }
72
73 None
74 }
75
76 pub fn encode(
83 &self,
84 function_name: &str,
85 parameters: Vec<Parameter>,
86 ) -> Result<Vec<u8>, AbiParserError> {
87 if let Some(function) = self.functions.get(function_name) {
88 let mut abi_arguments = Vec::<String>::with_capacity(parameters.len());
89 for (input, param) in function.inputs.iter().zip(parameters.iter()) {
90 if input.parameter_type.type_check(param) {
91 abi_arguments.push(input.parameter_type.as_abi_string())
92 } else {
93 return Err(AbiParserError::InvalidAbiEncoding(format!(
94 "Invalid parameter type supplied. Expected {:?}",
95 input.parameter_type
96 )));
97 }
98 }
99 let signature = format!("{}({})", function_name, abi_arguments.join(","));
100 let mut hasher = Keccak::v256();
101 hasher.update(signature.as_bytes());
102 let mut out = [0_u8; 32];
104 hasher.finalize(&mut out);
105 let mut hash = out[0..4].to_vec();
106 parameter::encode_into(&mut hash, parameters);
108 Ok(hash)
109 } else {
110 Err(AbiParserError::MissingData(
111 "Function name not found in ABI".to_owned(),
112 ))
113 }
114 }
115
116 pub fn decode(
121 &self,
122 function_name: &str,
123 hash: &[u8],
124 ) -> Result<Vec<Parameter>, AbiParserError> {
125 if let Some(function) = self.functions.get(function_name) {
126 let mut start_index = 0;
127 let mut parameters = Vec::<Parameter>::with_capacity(function.outputs.len());
128 for output in &function.outputs {
129 let (parameter, i) =
130 Parameter::decode(&output.parameter_type, &hash[start_index..]);
131 start_index += i;
132 parameters.push(parameter);
133 }
134
135 Ok(parameters)
136 } else {
137 Err(AbiParserError::MissingData(
138 "Function name not found in ABI".to_owned(),
139 ))
140 }
141 }
142}
143
144#[derive(Debug)]
145pub enum AbiParserError {
146 FileIoError(String),
147 Serde(String),
148 MissingData(String),
149 InvalidAbiEncoding(String),
150 TypeError,
151}