1mod construction;
2pub mod display;
3mod encode_into;
4mod parameter_type;
5mod utils;
6
7pub use encode_into::encode_into;
8pub use parameter_type::ParameterType;
9use utils::*;
10
11use ethane_types::{Address, H256};
12
13#[derive(Clone)]
16pub enum Parameter {
17 Address(H256),
18 Bool(H256),
19 Int(H256, usize),
20 Uint(H256, usize),
21 String(Vec<u8>),
22 Bytes(Vec<u8>),
23 FixedBytes(Vec<u8>),
24 Array(Vec<Parameter>),
25 FixedArray(Vec<Parameter>),
26 Tuple(Vec<Parameter>),
27}
28
29impl Parameter {
30 pub fn static_encode(&self) -> Vec<u8> {
38 match self {
39 Self::Address(data) | Self::Bool(data) | Self::Int(data, _) | Self::Uint(data, _) => {
40 data.as_bytes().to_vec()
41 }
42 Self::FixedBytes(data) => right_pad_to_32_multiples(data).to_vec(),
43 Self::Bytes(data) | Self::String(data) => {
44 let mut encoded = left_pad_to_32_bytes(&data.len().to_be_bytes()).to_vec();
45 encoded.extend_from_slice(&right_pad_to_32_multiples(data));
46 encoded
47 }
48 Self::FixedArray(params) | Self::Tuple(params) => {
49 let mut encoded = Vec::<u8>::new();
50 for p in params {
51 encoded.extend_from_slice(&p.static_encode());
52 }
53 encoded
54 }
55 Self::Array(_) => panic!("Array type cannot be statically encoded!"),
56 }
57 }
58
59 pub fn is_dynamic(&self) -> bool {
66 match self {
67 Self::Array(_) | Self::Bytes(_) | Self::String(_) => true,
68 Self::FixedArray(parameters) | Self::Tuple(parameters) => {
69 parameters.iter().any(|x| x.is_dynamic())
70 }
71 _ => false,
72 }
73 }
74
75 pub fn decode(parameter_type: &ParameterType, raw_bytes: &[u8]) -> (Self, usize) {
76 match parameter_type {
77 ParameterType::Address => {
78 let mut bytes = [0u8; 20];
79 bytes.copy_from_slice(&raw_bytes[12..32]);
80 (Self::from(Address::from(bytes)), 32)
81 }
82 ParameterType::Bool => {
83 let mut bytes = [0u8; 32];
84 bytes.copy_from_slice(&raw_bytes[..32]);
85 (Self::Bool(H256::from(bytes)), 32)
86 }
87 ParameterType::Int(_) => {
88 let mut bytes = [0u8; 32];
89 bytes.copy_from_slice(&raw_bytes[..32]);
90 (Self::new_int(bytes, true), 32)
91 }
92 ParameterType::Uint(_) => {
93 let mut bytes = [0u8; 32];
94 bytes.copy_from_slice(&raw_bytes[..32]);
95 (Self::new_int(bytes, false), 32)
96 }
97 _ => unimplemented!(),
108 }
109 }
110}
111
112#[cfg(test)]
113mod test {
114 use super::*;
115
116 #[test]
117 #[rustfmt::skip]
118 fn parameter_encode() {
119 assert_eq!(Parameter::Address(H256::zero()).static_encode(), vec![0u8; 32]);
120 assert_eq!(Parameter::from("Hello, World!").static_encode(), vec![
121 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0x0d,
125 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57,
126 0x6f, 0x72, 0x6c, 0x64, 0x21, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0,
129 ]);
130 assert_eq!(Parameter::FixedArray(vec![
131 Parameter::Uint(H256::from_int_unchecked(0x4a_u8), 8),
132 Parameter::Uint(H256::from_int_unchecked(0xff_u8), 8),
133 Parameter::Uint(H256::from_int_unchecked(0xde_u8), 8),
134 ]).static_encode(),
135 vec![
136 0, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0x4a, 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0xde, ]);
149 }
150
151 #[test]
152 fn parameter_is_dynamic() {
153 assert!(!Parameter::Address(H256::zero()).is_dynamic());
154 assert!(!Parameter::Bool(H256::zero()).is_dynamic());
155 assert!(Parameter::Bytes(Vec::new()).is_dynamic());
156 assert!(!Parameter::FixedBytes(Vec::new()).is_dynamic());
157 assert!(!Parameter::Uint(H256::zero(), 16).is_dynamic());
158 assert!(!Parameter::Int(H256::zero(), 32).is_dynamic());
159 assert!(Parameter::String(Vec::new()).is_dynamic());
160 assert!(Parameter::Array(vec![Parameter::Address(H256::zero()); 5]).is_dynamic());
161 assert!(Parameter::Array(vec![Parameter::Bytes(Vec::new())]).is_dynamic());
162 assert!(!Parameter::FixedArray(vec![Parameter::Uint(H256::zero(), 64); 3]).is_dynamic());
163 assert!(Parameter::FixedArray(vec![Parameter::String(Vec::new()); 2]).is_dynamic());
164 assert!(!Parameter::Tuple(vec![
165 Parameter::Address(H256::zero()),
166 Parameter::Uint(H256::zero(), 32),
167 Parameter::FixedBytes(Vec::new())
168 ])
169 .is_dynamic());
170 assert!(Parameter::Tuple(vec![
171 Parameter::FixedBytes(Vec::new()),
172 Parameter::Uint(H256::zero(), 32),
173 Parameter::String(Vec::new())
174 ])
175 .is_dynamic());
176 assert!(!Parameter::FixedArray(vec![
177 Parameter::FixedArray(vec![
178 Parameter::Int(
179 H256::zero(),
180 8
181 );
182 5
183 ]);
184 2
185 ])
186 .is_dynamic());
187 assert!(Parameter::Tuple(vec![
188 Parameter::FixedBytes(Vec::new()),
189 Parameter::Uint(H256::zero(), 32),
190 Parameter::FixedArray(vec![Parameter::String(Vec::new()); 3])
191 ])
192 .is_dynamic());
193 }
194
195 #[test]
196 #[rustfmt::skip]
197 fn decode_parameter() {
198 let result = vec![
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0xff,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0xff,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0c, 0xff,
203 ];
204
205 let mut index = 0;
206 let (addr, bytes_read) = Parameter::decode(&ParameterType::Address, &result);
207 index += bytes_read;
208 let (a, bytes_read) = Parameter::decode(&ParameterType::Uint(16), &result[index..]);
209 index += bytes_read;
210 let (b, bytes_read) = Parameter::decode(&ParameterType::Uint(16), &result[index..]);
211 index += bytes_read;
212 let (c, bytes_read) = Parameter::decode(&ParameterType::Uint(16), &result[index..]);
213 index += bytes_read;
214
215 assert_eq!(index, 128);
216 assert_eq!(addr.to_string(), String::from("0xffffffffffffffffffffffffffffffffffffffff"));
217 assert_eq!(a.to_string(), String::from("2815"));
218 assert_eq!(b.to_string(), String::from("3071"));
219 assert_eq!(c.to_string(), String::from("3327"));
220 }
221}