ethabi_decode/
decoder.rs

1// Copyright 2015-2020 Parity Technologies
2// Copyright 2020 Snowfork
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE or
7// http://www.apache.org/licenses/LICENSE-2.0>. This file may not be
8// copied, modified, or distributed except according to those terms.
9
10//! ABI decoder.
11
12use crate::{util::slice_data, Error, ParamKind, Token, Word, U256};
13
14use crate::std::Vec;
15
16struct DecodeResult {
17	token: Token,
18	new_offset: usize,
19}
20
21struct BytesTaken {
22	bytes: Vec<u8>,
23	new_offset: usize,
24}
25
26fn as_u32(slice: &Word) -> Result<u32, Error> {
27	if !slice[..28].iter().all(|x| *x == 0) {
28		return Err(Error::InvalidData);
29	}
30
31	let result =
32		((slice[28] as u32) << 24) + ((slice[29] as u32) << 16) + ((slice[30] as u32) << 8) + (slice[31] as u32);
33
34	Ok(result)
35}
36
37fn as_bool(slice: &Word) -> Result<bool, Error> {
38	if !slice[..31].iter().all(|x| *x == 0) {
39		return Err(Error::InvalidData);
40	}
41
42	Ok(slice[31] == 1)
43}
44
45/// Decodes ABI compliant vector of bytes into vector of tokens described by types param.
46pub fn decode(types: &[ParamKind], data: &[u8]) -> Result<Vec<Token>, Error> {
47	let is_empty_bytes_valid_encoding = types.iter().all(|t| t.is_empty_bytes_valid_encoding());
48	if !is_empty_bytes_valid_encoding && data.is_empty() {
49		return Err(Error::InvalidName);
50	}
51	let slices = slice_data(data)?;
52	let mut tokens = Vec::with_capacity(types.len());
53	let mut offset = 0;
54	for param in types {
55		let res = decode_param(param, &slices, offset)?;
56		offset = res.new_offset;
57		tokens.push(res.token);
58	}
59	Ok(tokens)
60}
61
62fn peek(slices: &[Word], position: usize) -> Result<&Word, Error> {
63	slices.get(position).ok_or_else(|| Error::InvalidData)
64}
65
66fn take_bytes(slices: &[Word], position: usize, len: usize) -> Result<BytesTaken, Error> {
67	let slices_len = (len + 31) / 32;
68
69	let mut bytes_slices = Vec::with_capacity(slices_len);
70	for i in 0..slices_len {
71		let slice = peek(slices, position + i)?;
72		bytes_slices.push(slice);
73	}
74
75	let bytes = bytes_slices.into_iter().flat_map(|slice| slice.to_vec()).take(len).collect();
76
77	let taken = BytesTaken { bytes, new_offset: position + slices_len };
78
79	Ok(taken)
80}
81
82fn decode_param(param: &ParamKind, slices: &[Word], offset: usize) -> Result<DecodeResult, Error> {
83	match *param {
84		ParamKind::Address => {
85			let slice = peek(slices, offset)?;
86			let mut address = [0u8; 20];
87			address.copy_from_slice(&slice[12..]);
88
89			let result = DecodeResult { token: Token::Address(address.into()), new_offset: offset + 1 };
90
91			Ok(result)
92		}
93		ParamKind::Int(_) => {
94			let slice = peek(slices, offset)?;
95
96			let result = DecodeResult { token: Token::Int(U256::from_big_endian(slice)), new_offset: offset + 1 };
97
98			Ok(result)
99		}
100		ParamKind::Uint(_) => {
101			let slice = peek(slices, offset)?;
102
103			let result = DecodeResult { token: Token::Uint(U256::from_big_endian(slice)), new_offset: offset + 1 };
104
105			Ok(result)
106		}
107		ParamKind::Bool => {
108			let slice = peek(slices, offset)?;
109
110			let b = as_bool(slice)?;
111
112			let result = DecodeResult { token: Token::Bool(b), new_offset: offset + 1 };
113			Ok(result)
114		}
115		ParamKind::FixedBytes(len) => {
116			// FixedBytes is anything from bytes1 to bytes32. These values
117			// are padded with trailing zeros to fill 32 bytes.
118			let taken = take_bytes(slices, offset, len)?;
119			let result = DecodeResult { token: Token::FixedBytes(taken.bytes), new_offset: taken.new_offset };
120			Ok(result)
121		}
122		ParamKind::Bytes => {
123			let offset_slice = peek(slices, offset)?;
124			let len_offset = (as_u32(offset_slice)? / 32) as usize;
125
126			let len_slice = peek(slices, len_offset)?;
127			let len = as_u32(len_slice)? as usize;
128
129			let taken = take_bytes(slices, len_offset + 1, len)?;
130
131			let result = DecodeResult { token: Token::Bytes(taken.bytes), new_offset: offset + 1 };
132			Ok(result)
133		}
134		ParamKind::String => {
135			let offset_slice = peek(slices, offset)?;
136			let len_offset = (as_u32(offset_slice)? / 32) as usize;
137
138			let len_slice = peek(slices, len_offset)?;
139			let len = as_u32(len_slice)? as usize;
140
141			let taken = take_bytes(slices, len_offset + 1, len)?;
142
143			let result = DecodeResult { token: Token::String(taken.bytes), new_offset: offset + 1 };
144			Ok(result)
145		}
146		ParamKind::Array(ref t) => {
147			let offset_slice = peek(slices, offset)?;
148			let len_offset = (as_u32(offset_slice)? / 32) as usize;
149			let len_slice = peek(slices, len_offset)?;
150			let len = as_u32(len_slice)? as usize;
151
152			let tail = &slices[len_offset + 1..];
153			let mut tokens = Vec::with_capacity(len);
154			let mut new_offset = 0;
155
156			for _ in 0..len {
157				let res = decode_param(t, &tail, new_offset)?;
158				new_offset = res.new_offset;
159				tokens.push(res.token);
160			}
161
162			let result = DecodeResult { token: Token::Array(tokens), new_offset: offset + 1 };
163
164			Ok(result)
165		}
166		ParamKind::FixedArray(ref t, len) => {
167			let mut tokens = Vec::with_capacity(len);
168			let is_dynamic = param.is_dynamic();
169
170			let (tail, mut new_offset) = if is_dynamic {
171				(&slices[(as_u32(peek(slices, offset)?)? as usize / 32)..], 0)
172			} else {
173				(slices, offset)
174			};
175
176			for _ in 0..len {
177				let res = decode_param(t, &tail, new_offset)?;
178				new_offset = res.new_offset;
179				tokens.push(res.token);
180			}
181
182			let result = DecodeResult {
183				token: Token::FixedArray(tokens),
184				new_offset: if is_dynamic { offset + 1 } else { new_offset },
185			};
186
187			Ok(result)
188		}
189		ParamKind::Tuple(ref t) => {
190			let is_dynamic = param.is_dynamic();
191
192			// The first element in a dynamic Tuple is an offset to the Tuple's data
193			// For a static Tuple the data begins right away
194			let (tail, mut new_offset) = if is_dynamic {
195				(&slices[(as_u32(peek(slices, offset)?)? as usize / 32)..], 0)
196			} else {
197				(slices, offset)
198			};
199
200			let len = t.len();
201			let mut tokens = Vec::with_capacity(len);
202			for i in 0..len {
203				let res = decode_param(&t[i], &tail, new_offset)?;
204				new_offset = res.new_offset;
205				tokens.push(res.token);
206			}
207
208			// The returned new_offset depends on whether the Tuple is dynamic
209			// dynamic Tuple -> follows the prefixed Tuple data offset element
210			// static Tuple  -> follows the last data element
211			let result = DecodeResult {
212				token: Token::Tuple(tokens),
213				new_offset: if is_dynamic { offset + 1 } else { new_offset },
214			};
215
216			Ok(result)
217		}
218	}
219}
220
221#[cfg(test)]
222mod tests {
223
224	use crate::{decode, ParamKind, Token, U256};
225	use hex_literal::hex;
226
227	#[test]
228	fn decode_from_empty_byte_slice() {
229		// these can NOT be decoded from empty byte slice
230		assert!(decode(&[ParamKind::Address], &[]).is_err());
231		assert!(decode(&[ParamKind::Bytes], &[]).is_err());
232		assert!(decode(&[ParamKind::Int(0)], &[]).is_err());
233		assert!(decode(&[ParamKind::Int(1)], &[]).is_err());
234		assert!(decode(&[ParamKind::Int(0)], &[]).is_err());
235		assert!(decode(&[ParamKind::Int(1)], &[]).is_err());
236		assert!(decode(&[ParamKind::Bool], &[]).is_err());
237		assert!(decode(&[ParamKind::String], &[]).is_err());
238		assert!(decode(&[ParamKind::Array(Box::new(ParamKind::Bool))], &[]).is_err());
239		assert!(decode(&[ParamKind::FixedBytes(1)], &[]).is_err());
240		assert!(decode(&[ParamKind::FixedArray(Box::new(ParamKind::Bool), 1)], &[]).is_err());
241
242		// these are the only ones that can be decoded from empty byte slice
243		assert!(decode(&[ParamKind::FixedBytes(0)], &[]).is_ok());
244		assert!(decode(&[ParamKind::FixedArray(Box::new(ParamKind::Bool), 0)], &[]).is_ok());
245	}
246
247	#[test]
248	fn decode_static_tuple_of_addresses_and_uints() {
249		let encoded = hex!(
250			"
251			0000000000000000000000001111111111111111111111111111111111111111
252			0000000000000000000000002222222222222222222222222222222222222222
253			1111111111111111111111111111111111111111111111111111111111111111
254		"
255		);
256		let address1 = Token::Address([0x11u8; 20].into());
257		let address2 = Token::Address([0x22u8; 20].into());
258		let uint = Token::Uint(U256::from_big_endian(&[0x11u8; 32]));
259		let tuple = Token::Tuple(vec![address1, address2, uint]);
260		let expected = vec![tuple];
261		let decoded = decode(
262			&[ParamKind::Tuple(vec![
263				Box::new(ParamKind::Address),
264				Box::new(ParamKind::Address),
265				Box::new(ParamKind::Uint(32)),
266			])],
267			&encoded,
268		)
269		.unwrap();
270		assert_eq!(decoded, expected);
271	}
272
273	#[test]
274	fn decode_dynamic_tuple() {
275		let encoded = hex!(
276			"
277			0000000000000000000000000000000000000000000000000000000000000020
278			0000000000000000000000000000000000000000000000000000000000000040
279			0000000000000000000000000000000000000000000000000000000000000080
280			0000000000000000000000000000000000000000000000000000000000000009
281			6761766f66796f726b0000000000000000000000000000000000000000000000
282			0000000000000000000000000000000000000000000000000000000000000009
283			6761766f66796f726b0000000000000000000000000000000000000000000000
284		"
285		);
286		let string1 = Token::String("gavofyork".as_bytes().to_vec());
287		let string2 = Token::String("gavofyork".as_bytes().to_vec());
288		let tuple = Token::Tuple(vec![string1, string2]);
289		let decoded =
290			decode(&[ParamKind::Tuple(vec![Box::new(ParamKind::String), Box::new(ParamKind::String)])], &encoded)
291				.unwrap();
292		let expected = vec![tuple];
293		assert_eq!(decoded, expected);
294	}
295
296	#[test]
297	fn decode_nested_tuple() {
298		let encoded = hex!(
299			"
300			0000000000000000000000000000000000000000000000000000000000000020
301			0000000000000000000000000000000000000000000000000000000000000080
302			0000000000000000000000000000000000000000000000000000000000000001
303			00000000000000000000000000000000000000000000000000000000000000c0
304			0000000000000000000000000000000000000000000000000000000000000100
305			0000000000000000000000000000000000000000000000000000000000000004
306			7465737400000000000000000000000000000000000000000000000000000000
307			0000000000000000000000000000000000000000000000000000000000000006
308			6379626f72670000000000000000000000000000000000000000000000000000
309			0000000000000000000000000000000000000000000000000000000000000060
310			00000000000000000000000000000000000000000000000000000000000000a0
311			00000000000000000000000000000000000000000000000000000000000000e0
312			0000000000000000000000000000000000000000000000000000000000000005
313			6e69676874000000000000000000000000000000000000000000000000000000
314			0000000000000000000000000000000000000000000000000000000000000003
315			6461790000000000000000000000000000000000000000000000000000000000
316			0000000000000000000000000000000000000000000000000000000000000040
317			0000000000000000000000000000000000000000000000000000000000000080
318			0000000000000000000000000000000000000000000000000000000000000004
319			7765656500000000000000000000000000000000000000000000000000000000
320			0000000000000000000000000000000000000000000000000000000000000008
321			66756e7465737473000000000000000000000000000000000000000000000000
322		"
323		);
324		let string1 = Token::String("test".as_bytes().to_vec());
325		let string2 = Token::String("cyborg".as_bytes().to_vec());
326		let string3 = Token::String("night".as_bytes().to_vec());
327		let string4 = Token::String("day".as_bytes().to_vec());
328		let string5 = Token::String("weee".as_bytes().to_vec());
329		let string6 = Token::String("funtests".as_bytes().to_vec());
330		let bool = Token::Bool(true);
331		let deep_tuple = Token::Tuple(vec![string5, string6]);
332		let inner_tuple = Token::Tuple(vec![string3, string4, deep_tuple]);
333		let outer_tuple = Token::Tuple(vec![string1, bool, string2, inner_tuple]);
334		let expected = vec![outer_tuple];
335		let decoded = decode(
336			&[ParamKind::Tuple(vec![
337				Box::new(ParamKind::String),
338				Box::new(ParamKind::Bool),
339				Box::new(ParamKind::String),
340				Box::new(ParamKind::Tuple(vec![
341					Box::new(ParamKind::String),
342					Box::new(ParamKind::String),
343					Box::new(ParamKind::Tuple(vec![Box::new(ParamKind::String), Box::new(ParamKind::String)])),
344				])),
345			])],
346			&encoded,
347		)
348		.unwrap();
349		assert_eq!(decoded, expected);
350	}
351
352	#[test]
353	fn decode_complex_tuple_of_dynamic_and_static_types() {
354		let encoded = hex!(
355			"
356			0000000000000000000000000000000000000000000000000000000000000020
357			1111111111111111111111111111111111111111111111111111111111111111
358			0000000000000000000000000000000000000000000000000000000000000080
359			0000000000000000000000001111111111111111111111111111111111111111
360			0000000000000000000000002222222222222222222222222222222222222222
361			0000000000000000000000000000000000000000000000000000000000000009
362			6761766f66796f726b0000000000000000000000000000000000000000000000
363		"
364		);
365		let uint = Token::Uint(U256::from_big_endian(&[0x11u8; 32]));
366		let string = Token::String("gavofyork".as_bytes().to_vec());
367		let address1 = Token::Address([0x11u8; 20].into());
368		let address2 = Token::Address([0x22u8; 20].into());
369		let tuple = Token::Tuple(vec![uint, string, address1, address2]);
370		let expected = vec![tuple];
371		let decoded = decode(
372			&[ParamKind::Tuple(vec![
373				Box::new(ParamKind::Uint(32)),
374				Box::new(ParamKind::String),
375				Box::new(ParamKind::Address),
376				Box::new(ParamKind::Address),
377			])],
378			&encoded,
379		)
380		.unwrap();
381		assert_eq!(decoded, expected);
382	}
383
384	#[test]
385	fn decode_params_containing_dynamic_tuple() {
386		let encoded = hex!(
387			"
388			0000000000000000000000002222222222222222222222222222222222222222
389			00000000000000000000000000000000000000000000000000000000000000a0
390			0000000000000000000000003333333333333333333333333333333333333333
391			0000000000000000000000004444444444444444444444444444444444444444
392			0000000000000000000000000000000000000000000000000000000000000000
393			0000000000000000000000000000000000000000000000000000000000000001
394			0000000000000000000000000000000000000000000000000000000000000060
395			00000000000000000000000000000000000000000000000000000000000000a0
396			0000000000000000000000000000000000000000000000000000000000000009
397			7370616365736869700000000000000000000000000000000000000000000000
398			0000000000000000000000000000000000000000000000000000000000000006
399			6379626f72670000000000000000000000000000000000000000000000000000
400		"
401		);
402		let address1 = Token::Address([0x22u8; 20].into());
403		let bool1 = Token::Bool(true);
404		let string1 = Token::String("spaceship".as_bytes().to_vec());
405		let string2 = Token::String("cyborg".as_bytes().to_vec());
406		let tuple = Token::Tuple(vec![bool1, string1, string2]);
407		let address2 = Token::Address([0x33u8; 20].into());
408		let address3 = Token::Address([0x44u8; 20].into());
409		let bool2 = Token::Bool(false);
410		let expected = vec![address1, tuple, address2, address3, bool2];
411		let decoded = decode(
412			&[
413				ParamKind::Address,
414				ParamKind::Tuple(vec![
415					Box::new(ParamKind::Bool),
416					Box::new(ParamKind::String),
417					Box::new(ParamKind::String),
418				]),
419				ParamKind::Address,
420				ParamKind::Address,
421				ParamKind::Bool,
422			],
423			&encoded,
424		)
425		.unwrap();
426		assert_eq!(decoded, expected);
427	}
428
429	#[test]
430	fn decode_params_containing_static_tuple() {
431		let encoded = hex!(
432			"
433			0000000000000000000000001111111111111111111111111111111111111111
434			0000000000000000000000002222222222222222222222222222222222222222
435			0000000000000000000000000000000000000000000000000000000000000001
436			0000000000000000000000000000000000000000000000000000000000000000
437			0000000000000000000000003333333333333333333333333333333333333333
438			0000000000000000000000004444444444444444444444444444444444444444
439		"
440		);
441		let address1 = Token::Address([0x11u8; 20].into());
442		let address2 = Token::Address([0x22u8; 20].into());
443		let bool1 = Token::Bool(true);
444		let bool2 = Token::Bool(false);
445		let tuple = Token::Tuple(vec![address2, bool1, bool2]);
446		let address3 = Token::Address([0x33u8; 20].into());
447		let address4 = Token::Address([0x44u8; 20].into());
448
449		let expected = vec![address1, tuple, address3, address4];
450		let decoded = decode(
451			&[
452				ParamKind::Address,
453				ParamKind::Tuple(vec![
454					Box::new(ParamKind::Address),
455					Box::new(ParamKind::Bool),
456					Box::new(ParamKind::Bool),
457				]),
458				ParamKind::Address,
459				ParamKind::Address,
460			],
461			&encoded,
462		)
463		.unwrap();
464		assert_eq!(decoded, expected);
465	}
466
467	#[test]
468	fn decode_fixed_array_of_strings() {
469		// line 1 at 0x00 =   0: tail offset for the array
470		// line 2 at 0x20 =  32: offset of string 1
471		// line 3 at 0x40 =  64: offset of string 2
472		// line 4 at 0x60 =  96: length of string 1
473		// line 5 at 0x80 = 128: value  of string 1
474		// line 6 at 0xa0 = 160: length of string 2
475		// line 7 at 0xc0 = 192: value  of string 2
476		let encoded = hex!(
477			"
478			0000000000000000000000000000000000000000000000000000000000000020
479			0000000000000000000000000000000000000000000000000000000000000040
480			0000000000000000000000000000000000000000000000000000000000000080
481			0000000000000000000000000000000000000000000000000000000000000003
482			666f6f0000000000000000000000000000000000000000000000000000000000
483			0000000000000000000000000000000000000000000000000000000000000003
484			6261720000000000000000000000000000000000000000000000000000000000
485		"
486		);
487
488		let s1 = Token::String("foo".as_bytes().to_vec());
489		let s2 = Token::String("bar".as_bytes().to_vec());
490		let array = Token::FixedArray(vec![s1, s2]);
491
492		let expected = vec![array];
493		let decoded = decode(&[ParamKind::FixedArray(Box::new(ParamKind::String), 2)], &encoded).unwrap();
494
495		assert_eq!(decoded, expected);
496	}
497
498	#[test]
499	fn decode_after_fixed_bytes_with_less_than_32_bytes() {
500		let encoded = hex!(
501			"
502			0000000000000000000000008497afefdc5ac170a664a231f6efb25526ef813f
503			0000000000000000000000000000000000000000000000000000000000000000
504			0000000000000000000000000000000000000000000000000000000000000000
505			0000000000000000000000000000000000000000000000000000000000000080
506			000000000000000000000000000000000000000000000000000000000000000a
507			3078303030303030314600000000000000000000000000000000000000000000
508		"
509		);
510
511		assert_eq!(
512			decode(
513				&[ParamKind::Address, ParamKind::FixedBytes(32), ParamKind::FixedBytes(4), ParamKind::String,],
514				&encoded,
515			)
516			.unwrap(),
517			&[
518				Token::Address(hex!("8497afefdc5ac170a664a231f6efb25526ef813f").into()),
519				Token::FixedBytes([0u8; 32].to_vec()),
520				Token::FixedBytes([0u8; 4].to_vec()),
521				Token::String("0x0000001F".into()),
522			]
523		);
524	}
525}