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