ethabi_fork_ethcontract/
function.rs1use std::string::ToString;
12
13use crate::signature::short_signature;
14use crate::{decode, encode, Bytes, Error, Param, ParamType, Result, StateMutability, Token};
15use serde::Deserialize;
16
17#[derive(Debug, Clone, PartialEq, Deserialize)]
19pub struct Function {
20 pub name: String,
22 pub inputs: Vec<Param>,
24 pub outputs: Vec<Param>,
26 #[deprecated(note = "The constant attribute was removed in Solidity 0.5.0 and has been \
27 replaced with stateMutability. If parsing a JSON AST created with \
28 this version or later this value will always be false, which may be wrong.")]
29 #[serde(default)]
31 pub constant: bool,
32 #[serde(rename = "stateMutability", default)]
34 pub state_mutability: StateMutability,
35}
36
37impl Function {
38 fn input_param_types(&self) -> Vec<ParamType> {
40 self.inputs.iter().map(|p| p.kind.clone()).collect()
41 }
42
43 fn output_param_types(&self) -> Vec<ParamType> {
45 self.outputs.iter().map(|p| p.kind.clone()).collect()
46 }
47
48 pub fn encode_input(&self, tokens: &[Token]) -> Result<Bytes> {
50 let params = self.input_param_types();
51
52 if !Token::types_check(tokens, ¶ms) {
53 return Err(Error::InvalidData);
54 }
55
56 let signed = short_signature(&self.name, ¶ms).to_vec();
57 let encoded = encode(tokens);
58 Ok(signed.into_iter().chain(encoded.into_iter()).collect())
59 }
60
61 pub fn decode_output(&self, data: &[u8]) -> Result<Vec<Token>> {
63 decode(&self.output_param_types(), &data)
64 }
65
66 pub fn decode_input(&self, data: &[u8]) -> Result<Vec<Token>> {
68 decode(&self.input_param_types(), &data)
69 }
70
71 pub fn signature(&self) -> String {
79 let inputs = self.inputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");
80
81 let outputs = self.outputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");
82
83 match (inputs.len(), outputs.len()) {
84 (_, 0) => format!("{}({})", self.name, inputs),
85 (_, _) => format!("{}({}):({})", self.name, inputs, outputs),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use crate::{Function, Param, ParamType, StateMutability, Token};
93 use hex_literal::hex;
94
95 #[test]
96 fn test_function_encode_call() {
97 let func = Function {
98 name: "baz".to_owned(),
99 inputs: vec![
100 Param { name: "a".to_owned(), kind: ParamType::Uint(32) },
101 Param { name: "b".to_owned(), kind: ParamType::Bool },
102 ],
103 outputs: vec![],
104 constant: false,
105 state_mutability: StateMutability::Payable,
106 };
107
108 let mut uint = [0u8; 32];
109 uint[31] = 69;
110 let encoded = func.encode_input(&[Token::Uint(uint.into()), Token::Bool(true)]).unwrap();
111 let expected = hex!("cdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001").to_vec();
112 assert_eq!(encoded, expected);
113 }
114}