ethabi_next/
decoder.rs

1// Copyright 2015-2020 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! ABI decoder.
10
11use 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
40/// Decodes ABI compliant vector of bytes into vector of tokens described by types param.
41pub 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			// FixedBytes is anything from bytes1 to bytes32. These values
115			// are padded with trailing zeros to fill 32 bytes.
116			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				// NOTE: We're decoding strings using lossy UTF-8 decoding to
133				// prevent invalid strings written into contracts by either users or
134				// Solidity bugs from causing graph-node to fail decoding event
135				// data.
136				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			// The first element in a dynamic Tuple is an offset to the Tuple's data
186			// For a static Tuple the data begins right away
187			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			// The returned new_offset depends on whether the Tuple is dynamic
199			// dynamic Tuple -> follows the prefixed Tuple data offset element
200			// static Tuple  -> follows the last data element
201			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		// these can NOT be decoded from empty byte slice
219		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		// these are the only ones that can be decoded from empty byte slice
232		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}