1#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14#[cfg(not(feature = "std"))]
15use crate::no_std_prelude::*;
16use crate::{
17 decode, encode, signature::short_signature, Bytes, Error, Param, ParamType, Result, StateMutability, Token,
18};
19
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[derive(Debug, Clone, PartialEq)]
23pub struct Function {
24 #[cfg_attr(feature = "serde", serde(deserialize_with = "crate::util::sanitize_name::deserialize"))]
26 pub name: String,
27 pub inputs: Vec<Param>,
29 pub outputs: Vec<Param>,
31 #[deprecated(note = "The constant attribute was removed in Solidity 0.5.0 and has been \
32 replaced with stateMutability.")]
33 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
35 pub constant: Option<bool>,
36 #[cfg_attr(feature = "serde", serde(rename = "stateMutability", default))]
38 pub state_mutability: StateMutability,
39}
40
41impl Function {
42 fn input_param_types(&self) -> Vec<ParamType> {
44 self.inputs.iter().map(|p| p.kind.clone()).collect()
45 }
46
47 fn output_param_types(&self) -> Vec<ParamType> {
49 self.outputs.iter().map(|p| p.kind.clone()).collect()
50 }
51
52 pub fn encode_input(&self, tokens: &[Token]) -> Result<Bytes> {
54 let params = self.input_param_types();
55
56 if !Token::types_check(tokens, ¶ms) {
57 return Err(Error::InvalidData);
58 }
59
60 let signed = short_signature(&self.name, ¶ms).to_vec();
61 let encoded = encode(tokens);
62 Ok(signed.into_iter().chain(encoded.into_iter()).collect())
63 }
64
65 pub fn short_signature(&self) -> [u8; 4] {
67 let params = self.input_param_types();
68 short_signature(&self.name, ¶ms)
69 }
70
71 pub fn decode_output(&self, data: &[u8]) -> Result<Vec<Token>> {
73 decode(&self.output_param_types(), data)
74 }
75
76 pub fn decode_input(&self, data: &[u8]) -> Result<Vec<Token>> {
78 decode(&self.input_param_types(), data)
79 }
80
81 pub fn signature(&self) -> String {
89 let inputs = self.inputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");
90
91 let outputs = self.outputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");
92
93 match (inputs.len(), outputs.len()) {
94 (_, 0) => format!("{}({inputs})", self.name),
95 (_, _) => format!("{}({inputs}):({outputs})", self.name),
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use hex_literal::hex;
103
104 #[cfg(not(feature = "std"))]
105 use crate::no_std_prelude::*;
106 use crate::{Function, Param, ParamType, StateMutability, Token};
107
108 #[test]
109 fn test_function_encode_call() {
110 #[allow(deprecated)]
111 let func = Function {
112 name: "baz".to_owned(),
113 inputs: vec![
114 Param { name: "a".to_owned(), kind: ParamType::Uint(32), internal_type: None },
115 Param { name: "b".to_owned(), kind: ParamType::Bool, internal_type: None },
116 ],
117 outputs: vec![],
118 constant: None,
119 state_mutability: StateMutability::Payable,
120 };
121
122 let mut uint = [0u8; 32];
123 uint[31] = 69;
124 let encoded = func.encode_input(&[Token::Uint(uint.into()), Token::Bool(true)]).unwrap();
125 let expected = hex!("cdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001").to_vec();
126 assert_eq!(encoded, expected);
127
128 let expected_sig = hex!("cdcd77c0").to_vec();
129 assert_eq!(func.short_signature().to_vec(), expected_sig);
130 }
131}