1use crate::{Error, ParamType, Token, Word};
12
13#[derive(Debug)]
14struct DecodeResult {
15 token: Token,
16 new_offset: usize,
17}
18
19fn as_usize(slice: &Word) -> Result<usize, Error> {
20 if !slice[..28].iter().all(|x| *x == 0) {
21 return Err(Error::InvalidData);
22 }
23
24 let result = ((slice[28] as usize) << 24)
25 + ((slice[29] as usize) << 16)
26 + ((slice[30] as usize) << 8)
27 + (slice[31] as usize);
28
29 Ok(result)
30}
31
32fn as_bool(slice: &Word) -> Result<bool, Error> {
33 if !slice[..31].iter().all(|x| *x == 0) {
34 return Err(Error::InvalidData);
35 }
36
37 Ok(slice[31] == 1)
38}
39
40pub fn decode(types: &[ParamType], data: &[u8]) -> Result<Vec<Token>, Error> {
42 let is_empty_bytes_valid_encoding = types.iter().all(|t| t.is_empty_bytes_valid_encoding());
43 if !is_empty_bytes_valid_encoding && data.is_empty() {
44 return Err(Error::InvalidName(
45 "please ensure the contract and method you're calling exist! \
46 failed to decode empty bytes. if you're using jsonrpc this is \
47 likely due to jsonrpc returning `0x` in case contract or method \
48 don't exist"
49 .into(),
50 ));
51 }
52
53 let mut tokens = vec![];
54 let mut offset = 0;
55
56 for param in types {
57 let res = decode_param(param, data, offset)?;
58 offset = res.new_offset;
59 tokens.push(res.token);
60 }
61
62 Ok(tokens)
63}
64
65fn peek(data: &[u8], offset: usize, len: usize) -> Result<&[u8], Error> {
66 if offset + len > data.len() {
67 return Err(Error::InvalidData);
68 } else {
69 Ok(&data[offset..(offset + len)])
70 }
71}
72
73fn peek_32_bytes(data: &[u8], offset: usize) -> Result<Word, Error> {
74 peek(data, offset, 32).map(|x| {
75 let mut out: Word = [0u8; 32];
76 out.copy_from_slice(&x[0..32]);
77 out
78 })
79}
80
81fn take_bytes(data: &[u8], offset: usize, len: usize) -> Result<Vec<u8>, Error> {
82 if offset + len > data.len() {
83 return Err(Error::InvalidData);
84 } else {
85 Ok((&data[offset..(offset + len)]).to_vec())
86 }
87}
88
89fn decode_param(param: &ParamType, data: &[u8], offset: usize) -> Result<DecodeResult, Error> {
90 match *param {
91 ParamType::Address => {
92 let slice = peek_32_bytes(data, offset)?;
93 let mut address = [0u8; 20];
94 address.copy_from_slice(&slice[12..]);
95 let result = DecodeResult { token: Token::Address(address.into()), new_offset: offset + 32 };
96 Ok(result)
97 }
98 ParamType::Int(_) => {
99 let slice = peek_32_bytes(data, offset)?;
100 let result = DecodeResult { token: Token::Int(slice.clone().into()), new_offset: offset + 32 };
101 Ok(result)
102 }
103 ParamType::Uint(_) => {
104 let slice = peek_32_bytes(data, offset)?;
105 let result = DecodeResult { token: Token::Uint(slice.clone().into()), new_offset: offset + 32 };
106 Ok(result)
107 }
108 ParamType::Bool => {
109 let b = as_bool(&peek_32_bytes(data, offset)?)?;
110 let result = DecodeResult { token: Token::Bool(b), new_offset: offset + 32 };
111 Ok(result)
112 }
113 ParamType::FixedBytes(len) => {
114 let bytes = take_bytes(data, offset, len)?;
117 let result = DecodeResult { token: Token::FixedBytes(bytes), new_offset: offset + 32 };
118 Ok(result)
119 }
120 ParamType::Bytes => {
121 let dynamic_offset = as_usize(&peek_32_bytes(data, offset)?)?;
122 let len = as_usize(&peek_32_bytes(data, dynamic_offset)?)?;
123 let bytes = take_bytes(data, dynamic_offset + 32, len)?;
124 let result = DecodeResult { token: Token::Bytes(bytes), new_offset: offset + 32 };
125 Ok(result)
126 }
127 ParamType::String => {
128 let dynamic_offset = as_usize(&peek_32_bytes(data, offset)?)?;
129 let len = as_usize(&peek_32_bytes(data, dynamic_offset)?)?;
130 let bytes = take_bytes(data, dynamic_offset + 32, len)?;
131 let result = DecodeResult {
132 token: Token::String(String::from_utf8_lossy(&*bytes).into()),
137 new_offset: offset + 32,
138 };
139 Ok(result)
140 }
141 ParamType::Array(ref t) => {
142 let len_offset = as_usize(&peek_32_bytes(data, offset)?)?;
143 let len = as_usize(&peek_32_bytes(data, len_offset)?)?;
144
145 let tail_offset = len_offset + 32;
146 let tail = &data[tail_offset..];
147
148 let mut tokens = vec![];
149 let mut new_offset = 0;
150
151 for _ in 0..len {
152 let res = decode_param(t, &tail, new_offset)?;
153 new_offset = res.new_offset;
154 tokens.push(res.token);
155 }
156
157 let result = DecodeResult { token: Token::Array(tokens), new_offset: offset + 32 };
158
159 Ok(result)
160 }
161 ParamType::FixedArray(ref t, len) => {
162 let is_dynamic = param.is_dynamic();
163
164 let (tail, mut new_offset) =
165 if is_dynamic { (&data[as_usize(&peek_32_bytes(data, offset)?)?..], 0) } else { (data, offset) };
166
167 let mut tokens = vec![];
168
169 for _ in 0..len {
170 let res = decode_param(t, &tail, new_offset)?;
171 new_offset = res.new_offset;
172 tokens.push(res.token);
173 }
174
175 let result = DecodeResult {
176 token: Token::FixedArray(tokens),
177 new_offset: if is_dynamic { offset + 32 } else { new_offset },
178 };
179
180 Ok(result)
181 }
182 ParamType::Tuple(ref t) => {
183 let is_dynamic = param.is_dynamic();
184
185 let (tail, mut new_offset) =
188 if is_dynamic { (&data[as_usize(&peek_32_bytes(data, offset)?)?..], 0) } else { (data, offset) };
189
190 let len = t.len();
191 let mut tokens = Vec::with_capacity(len);
192 for param in t {
193 let res = decode_param(param, &tail, new_offset)?;
194 new_offset = res.new_offset;
195 tokens.push(res.token);
196 }
197
198 let result = DecodeResult {
202 token: Token::Tuple(tokens),
203 new_offset: if is_dynamic { offset + 32 } else { new_offset },
204 };
205
206 Ok(result)
207 }
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use crate::{decode, ParamType, Token, Uint};
214 use hex_literal::hex;
215
216 #[test]
217 fn decode_from_empty_byte_slice() {
218 assert!(decode(&[ParamType::Address], &[]).is_err());
220 assert!(decode(&[ParamType::Bytes], &[]).is_err());
221 assert!(decode(&[ParamType::Int(0)], &[]).is_err());
222 assert!(decode(&[ParamType::Int(1)], &[]).is_err());
223 assert!(decode(&[ParamType::Int(0)], &[]).is_err());
224 assert!(decode(&[ParamType::Int(1)], &[]).is_err());
225 assert!(decode(&[ParamType::Bool], &[]).is_err());
226 assert!(decode(&[ParamType::String], &[]).is_err());
227 assert!(decode(&[ParamType::Array(Box::new(ParamType::Bool))], &[]).is_err());
228 assert!(decode(&[ParamType::FixedBytes(1)], &[]).is_err());
229 assert!(decode(&[ParamType::FixedArray(Box::new(ParamType::Bool), 1)], &[]).is_err());
230
231 assert!(decode(&[ParamType::FixedBytes(0)], &[]).is_ok());
233 assert!(decode(&[ParamType::FixedArray(Box::new(ParamType::Bool), 0)], &[]).is_ok());
234 }
235
236 #[test]
237 fn decode_static_tuple_of_addresses_and_uints() {
238 let encoded = hex!(
239 "
240 0000000000000000000000001111111111111111111111111111111111111111
241 0000000000000000000000002222222222222222222222222222222222222222
242 1111111111111111111111111111111111111111111111111111111111111111
243 "
244 );
245 let address1 = Token::Address([0x11u8; 20].into());
246 let address2 = Token::Address([0x22u8; 20].into());
247 let uint = Token::Uint([0x11u8; 32].into());
248 let tuple = Token::Tuple(vec![address1, address2, uint]);
249 let expected = vec![tuple];
250 let decoded =
251 decode(&[ParamType::Tuple(vec![ParamType::Address, ParamType::Address, ParamType::Uint(32)])], &encoded)
252 .unwrap();
253 assert_eq!(decoded, expected);
254 }
255
256 #[test]
257 fn decode_dynamic_tuple() {
258 let encoded = hex!(
259 "
260 0000000000000000000000000000000000000000000000000000000000000020
261 0000000000000000000000000000000000000000000000000000000000000040
262 0000000000000000000000000000000000000000000000000000000000000080
263 0000000000000000000000000000000000000000000000000000000000000009
264 6761766f66796f726b0000000000000000000000000000000000000000000000
265 0000000000000000000000000000000000000000000000000000000000000009
266 6761766f66796f726b0000000000000000000000000000000000000000000000
267 "
268 );
269 let string1 = Token::String("gavofyork".to_owned());
270 let string2 = Token::String("gavofyork".to_owned());
271 let tuple = Token::Tuple(vec![string1, string2]);
272 let decoded = decode(&[ParamType::Tuple(vec![ParamType::String, ParamType::String])], &encoded).unwrap();
273 let expected = vec![tuple];
274 assert_eq!(decoded, expected);
275 }
276
277 #[test]
278 fn decode_nested_tuple() {
279 let encoded = hex!(
280 "
281 0000000000000000000000000000000000000000000000000000000000000020
282 0000000000000000000000000000000000000000000000000000000000000080
283 0000000000000000000000000000000000000000000000000000000000000001
284 00000000000000000000000000000000000000000000000000000000000000c0
285 0000000000000000000000000000000000000000000000000000000000000100
286 0000000000000000000000000000000000000000000000000000000000000004
287 7465737400000000000000000000000000000000000000000000000000000000
288 0000000000000000000000000000000000000000000000000000000000000006
289 6379626f72670000000000000000000000000000000000000000000000000000
290 0000000000000000000000000000000000000000000000000000000000000060
291 00000000000000000000000000000000000000000000000000000000000000a0
292 00000000000000000000000000000000000000000000000000000000000000e0
293 0000000000000000000000000000000000000000000000000000000000000005
294 6e69676874000000000000000000000000000000000000000000000000000000
295 0000000000000000000000000000000000000000000000000000000000000003
296 6461790000000000000000000000000000000000000000000000000000000000
297 0000000000000000000000000000000000000000000000000000000000000040
298 0000000000000000000000000000000000000000000000000000000000000080
299 0000000000000000000000000000000000000000000000000000000000000004
300 7765656500000000000000000000000000000000000000000000000000000000
301 0000000000000000000000000000000000000000000000000000000000000008
302 66756e7465737473000000000000000000000000000000000000000000000000
303 "
304 );
305 let string1 = Token::String("test".to_owned());
306 let string2 = Token::String("cyborg".to_owned());
307 let string3 = Token::String("night".to_owned());
308 let string4 = Token::String("day".to_owned());
309 let string5 = Token::String("weee".to_owned());
310 let string6 = Token::String("funtests".to_owned());
311 let bool = Token::Bool(true);
312 let deep_tuple = Token::Tuple(vec![string5, string6]);
313 let inner_tuple = Token::Tuple(vec![string3, string4, deep_tuple]);
314 let outer_tuple = Token::Tuple(vec![string1, bool, string2, inner_tuple]);
315 let expected = vec![outer_tuple];
316 let decoded = decode(
317 &[ParamType::Tuple(vec![
318 ParamType::String,
319 ParamType::Bool,
320 ParamType::String,
321 ParamType::Tuple(vec![
322 ParamType::String,
323 ParamType::String,
324 ParamType::Tuple(vec![ParamType::String, ParamType::String]),
325 ]),
326 ])],
327 &encoded,
328 )
329 .unwrap();
330 assert_eq!(decoded, expected);
331 }
332
333 #[test]
334 fn decode_complex_tuple_of_dynamic_and_static_types() {
335 let encoded = hex!(
336 "
337 0000000000000000000000000000000000000000000000000000000000000020
338 1111111111111111111111111111111111111111111111111111111111111111
339 0000000000000000000000000000000000000000000000000000000000000080
340 0000000000000000000000001111111111111111111111111111111111111111
341 0000000000000000000000002222222222222222222222222222222222222222
342 0000000000000000000000000000000000000000000000000000000000000009
343 6761766f66796f726b0000000000000000000000000000000000000000000000
344 "
345 );
346 let uint = Token::Uint([0x11u8; 32].into());
347 let string = Token::String("gavofyork".to_owned());
348 let address1 = Token::Address([0x11u8; 20].into());
349 let address2 = Token::Address([0x22u8; 20].into());
350 let tuple = Token::Tuple(vec![uint, string, address1, address2]);
351 let expected = vec![tuple];
352 let decoded = decode(
353 &[ParamType::Tuple(vec![ParamType::Uint(32), ParamType::String, ParamType::Address, ParamType::Address])],
354 &encoded,
355 )
356 .unwrap();
357 assert_eq!(decoded, expected);
358 }
359
360 #[test]
361 fn decode_params_containing_dynamic_tuple() {
362 let encoded = hex!(
363 "
364 0000000000000000000000002222222222222222222222222222222222222222
365 00000000000000000000000000000000000000000000000000000000000000a0
366 0000000000000000000000003333333333333333333333333333333333333333
367 0000000000000000000000004444444444444444444444444444444444444444
368 0000000000000000000000000000000000000000000000000000000000000000
369 0000000000000000000000000000000000000000000000000000000000000001
370 0000000000000000000000000000000000000000000000000000000000000060
371 00000000000000000000000000000000000000000000000000000000000000a0
372 0000000000000000000000000000000000000000000000000000000000000009
373 7370616365736869700000000000000000000000000000000000000000000000
374 0000000000000000000000000000000000000000000000000000000000000006
375 6379626f72670000000000000000000000000000000000000000000000000000
376 "
377 );
378 let address1 = Token::Address([0x22u8; 20].into());
379 let bool1 = Token::Bool(true);
380 let string1 = Token::String("spaceship".to_owned());
381 let string2 = Token::String("cyborg".to_owned());
382 let tuple = Token::Tuple(vec![bool1, string1, string2]);
383 let address2 = Token::Address([0x33u8; 20].into());
384 let address3 = Token::Address([0x44u8; 20].into());
385 let bool2 = Token::Bool(false);
386 let expected = vec![address1, tuple, address2, address3, bool2];
387 let decoded = decode(
388 &[
389 ParamType::Address,
390 ParamType::Tuple(vec![ParamType::Bool, ParamType::String, ParamType::String]),
391 ParamType::Address,
392 ParamType::Address,
393 ParamType::Bool,
394 ],
395 &encoded,
396 )
397 .unwrap();
398 assert_eq!(decoded, expected);
399 }
400
401 #[test]
402 fn decode_params_containing_static_tuple() {
403 let encoded = hex!(
404 "
405 0000000000000000000000001111111111111111111111111111111111111111
406 0000000000000000000000002222222222222222222222222222222222222222
407 0000000000000000000000000000000000000000000000000000000000000001
408 0000000000000000000000000000000000000000000000000000000000000000
409 0000000000000000000000003333333333333333333333333333333333333333
410 0000000000000000000000004444444444444444444444444444444444444444
411 "
412 );
413 let address1 = Token::Address([0x11u8; 20].into());
414 let address2 = Token::Address([0x22u8; 20].into());
415 let bool1 = Token::Bool(true);
416 let bool2 = Token::Bool(false);
417 let tuple = Token::Tuple(vec![address2, bool1, bool2]);
418 let address3 = Token::Address([0x33u8; 20].into());
419 let address4 = Token::Address([0x44u8; 20].into());
420
421 let expected = vec![address1, tuple, address3, address4];
422 let decoded = decode(
423 &[
424 ParamType::Address,
425 ParamType::Tuple(vec![ParamType::Address, ParamType::Bool, ParamType::Bool]),
426 ParamType::Address,
427 ParamType::Address,
428 ],
429 &encoded,
430 )
431 .unwrap();
432 assert_eq!(decoded, expected);
433 }
434
435 #[test]
436 fn decode_data_with_size_that_is_not_a_multiple_of_32() {
437 let encoded = hex!(
438 "
439 0000000000000000000000000000000000000000000000000000000000000000
440 00000000000000000000000000000000000000000000000000000000000000a0
441 0000000000000000000000000000000000000000000000000000000000000152
442 0000000000000000000000000000000000000000000000000000000000000001
443 000000000000000000000000000000000000000000000000000000000054840d
444 0000000000000000000000000000000000000000000000000000000000000092
445 3132323033393637623533326130633134633938306235616566666231373034
446 3862646661656632633239336139353039663038656233633662306635663866
447 3039343265376239636337366361353163636132366365353436393230343438
448 6533303866646136383730623565326165313261323430396439343264653432
449 3831313350373230703330667073313678390000000000000000000000000000
450 0000000000000000000000000000000000103933633731376537633061363531
451 3761
452 "
453 );
454
455 assert_eq!(
456 decode(
457 &[
458 ParamType::Uint(256),
459 ParamType::String,
460 ParamType::String,
461 ParamType::Uint(256),
462 ParamType::Uint(256),
463 ],
464 &encoded,
465 ).unwrap(),
466 &[
467 Token::Uint(Uint::from(0)),
468 Token::String(String::from("12203967b532a0c14c980b5aeffb17048bdfaef2c293a9509f08eb3c6b0f5f8f0942e7b9cc76ca51cca26ce546920448e308fda6870b5e2ae12a2409d942de428113P720p30fps16x9")),
469 Token::String(String::from("93c717e7c0a6517a")),
470 Token::Uint(Uint::from(1)),
471 Token::Uint(Uint::from(5538829))
472 ]
473 );
474 }
475
476 #[test]
477 fn decode_after_fixed_bytes_with_less_than_32_bytes() {
478 let encoded = hex!(
479 "
480 0000000000000000000000008497afefdc5ac170a664a231f6efb25526ef813f
481 0000000000000000000000000000000000000000000000000000000000000000
482 0000000000000000000000000000000000000000000000000000000000000000
483 0000000000000000000000000000000000000000000000000000000000000080
484 000000000000000000000000000000000000000000000000000000000000000a
485 3078303030303030314600000000000000000000000000000000000000000000
486 "
487 );
488
489 assert_eq!(
490 decode(
491 &[ParamType::Address, ParamType::FixedBytes(32), ParamType::FixedBytes(4), ParamType::String,],
492 &encoded,
493 )
494 .unwrap(),
495 &[
496 Token::Address(hex!("8497afefdc5ac170a664a231f6efb25526ef813f").into()),
497 Token::FixedBytes([0u8; 32].to_vec()),
498 Token::FixedBytes([0u8; 4].to_vec()),
499 Token::String("0x0000001F".into()),
500 ]
501 )
502 }
503
504 #[test]
505 fn decode_broken_utf8() {
506 let encoded = hex!(
507 "
508 0000000000000000000000000000000000000000000000000000000000000020
509 0000000000000000000000000000000000000000000000000000000000000004
510 e4b88de500000000000000000000000000000000000000000000000000000000
511 "
512 );
513
514 assert_eq!(decode(&[ParamType::String,], &encoded).unwrap(), &[Token::String("不�".into())]);
515 }
516}