Skip to content

Instantly share code, notes, and snippets.

@bernardoaraujor
Last active May 1, 2023 06:36
Show Gist options
  • Save bernardoaraujor/96c80ba1ed810a4212488bd11f05bce8 to your computer and use it in GitHub Desktop.
Save bernardoaraujor/96c80ba1ed810a4212488bd11f05bce8 to your computer and use it in GitHub Desktop.
-- file: ethabi/Cargo.toml --
[package]
name = "ethabi"
version = "18.0.0"
authors = [
    "Parity Technologies <[email protected]>",
    "Artem Vorotnikov <[email protected]>",
    "Nicholas Rodrigues Lordello <[email protected]>",
]
homepage = "https://github.com/rust-ethereum/ethabi"
license = "Apache-2.0"
keywords = ["ethereum", "eth", "abi", "solidity"]
description = "Easy to use conversion of ethereum contract calls to bytecode."
edition = "2021"

[dependencies]
hex = { version = "0.4", default-features = false, features = ["alloc"] }
serde = { version = "1.0", optional =  true, default-features = false, features = ["derive"] }
serde_json = { version = "1.0", optional = true }
sha3 = { version = "0.10", default-features = false }
ethereum-types = { version = "0.14.0", default-features = false }
thiserror = { version = "1", optional = true }
uint = { version = "0.9.0", default-features = false, optional = true }
regex = { version = "1.5.4", optional = true }
once_cell = { version = "1.9.0", optional = true }

[dev-dependencies]
hex-literal = "0.3"
paste = "1"
serde_json = "1.0"

[features]
default = [
	"std",
	"full-serde",
	"rlp",
]
std = [
	"hex/std",
	"sha3/std",
	"ethereum-types/std",
	"thiserror",
	"uint?/std",
	"serde?/std",
]

serde = [
	"dep:serde",
	"ethereum-types/serialize",
	"uint",
]

# To enable custom `Reader`/`Tokenizer` and `serde` features support
full-serde = [
	"std",
	"serde",
	"serde_json",
	"regex",
	"once_cell"
]

rlp = [
	"ethereum-types/rlp",
]

parity-codec = [
	"ethereum-types/codec"
]

-- file: ethabi/src/token/strict.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;

use crate::{errors::Error, token::Tokenizer};

/// Tries to parse string as a token. Require string to clearly represent the value.
pub struct StrictTokenizer;

impl Tokenizer for StrictTokenizer {
	fn tokenize_address(value: &str) -> Result<[u8; 20], Error> {
		let hex: Vec<u8> = hex::decode(value)?;
		match hex.len() == 20 {
			false => Err(Error::InvalidData),
			true => {
				let mut address = [0u8; 20];
				address.copy_from_slice(&hex);
				Ok(address)
			}
		}
	}

	fn tokenize_string(value: &str) -> Result<String, Error> {
		Ok(value.to_owned())
	}

	fn tokenize_bool(value: &str) -> Result<bool, Error> {
		match value {
			"true" | "1" => Ok(true),
			"false" | "0" => Ok(false),
			_ => Err(Error::InvalidData),
		}
	}

	fn tokenize_bytes(value: &str) -> Result<Vec<u8>, Error> {
		hex::decode(value).map_err(Into::into)
	}

	fn tokenize_fixed_bytes(value: &str, len: usize) -> Result<Vec<u8>, Error> {
		let hex: Vec<u8> = hex::decode(value)?;
		match hex.len() == len {
			true => Ok(hex),
			false => Err(Error::InvalidData),
		}
	}

	fn tokenize_uint(value: &str) -> Result<[u8; 32], Error> {
		let hex: Vec<u8> = hex::decode(value)?;
		match hex.len() == 32 {
			true => {
				let mut uint = [0u8; 32];
				uint.copy_from_slice(&hex);
				Ok(uint)
			}
			false => Err(Error::InvalidData),
		}
	}

	fn tokenize_int(value: &str) -> Result<[u8; 32], Error> {
		Self::tokenize_uint(value)
	}
}

#[cfg(test)]
mod tests {
	use crate::{
		token::{StrictTokenizer, Token, Tokenizer},
		ParamType,
	};

	#[test]
	fn tokenize_address() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::Address, "1111111111111111111111111111111111111111").unwrap(),
			Token::Address([0x11u8; 20].into())
		);
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::Address, "2222222222222222222222222222222222222222").unwrap(),
			Token::Address([0x22u8; 20].into())
		);
	}

	#[test]
	fn tokenize_string() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::String, "gavofyork").unwrap(),
			Token::String("gavofyork".to_owned())
		);
		assert_eq!(StrictTokenizer::tokenize(&ParamType::String, "hello").unwrap(), Token::String("hello".to_owned()));
	}

	#[test]
	fn tokenize_bool() {
		assert_eq!(StrictTokenizer::tokenize(&ParamType::Bool, "true").unwrap(), Token::Bool(true));
		assert_eq!(StrictTokenizer::tokenize(&ParamType::Bool, "1").unwrap(), Token::Bool(true));
		assert_eq!(StrictTokenizer::tokenize(&ParamType::Bool, "false").unwrap(), Token::Bool(false));
		assert_eq!(StrictTokenizer::tokenize(&ParamType::Bool, "0").unwrap(), Token::Bool(false));
	}

	#[test]
	fn tokenize_bytes() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::Bytes, "123456").unwrap(),
			Token::Bytes(vec![0x12, 0x34, 0x56])
		);
		assert_eq!(StrictTokenizer::tokenize(&ParamType::Bytes, "0017").unwrap(), Token::Bytes(vec![0x00, 0x17]));
	}

	#[test]
	fn tokenize_fixed_bytes() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::FixedBytes(3), "123456").unwrap(),
			Token::FixedBytes(vec![0x12, 0x34, 0x56])
		);
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::FixedBytes(2), "0017").unwrap(),
			Token::FixedBytes(vec![0x00, 0x17])
		);
	}

	#[test]
	fn tokenize_uint() {
		assert_eq!(
			StrictTokenizer::tokenize(
				&ParamType::Uint(256),
				"1111111111111111111111111111111111111111111111111111111111111111"
			)
			.unwrap(),
			Token::Uint([0x11u8; 32].into())
		);

		assert_eq!(
			StrictTokenizer::tokenize(
				&ParamType::Uint(256),
				"2222222222222222222222222222222222222222222222222222222222222222"
			)
			.unwrap(),
			Token::Uint([0x22u8; 32].into())
		);
	}

	#[test]
	fn tokenize_int() {
		assert_eq!(
			StrictTokenizer::tokenize(
				&ParamType::Int(256),
				"1111111111111111111111111111111111111111111111111111111111111111"
			)
			.unwrap(),
			Token::Int([0x11u8; 32].into())
		);

		assert_eq!(
			StrictTokenizer::tokenize(
				&ParamType::Int(256),
				"2222222222222222222222222222222222222222222222222222222222222222"
			)
			.unwrap(),
			Token::Int([0x22u8; 32].into())
		);
	}

	#[test]
	fn tokenize_empty_array() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::Array(Box::new(ParamType::Bool)), "[]").unwrap(),
			Token::Array(vec![])
		);
	}

	#[test]
	fn tokenize_bool_array() {
		assert_eq!(
			StrictTokenizer::tokenize(&ParamType::Array(Box::new(ParamType::Bool)), "[true,1,0,false]").unwrap(),
			Token::Array(vec![Token::Bool(true), Token::Bool(true), Token::Bool(false), Token::Bool(false)])
		);
	}

	#[test]
	fn tokenize_bool_array_of_arrays() {
		assert_eq!(
			StrictTokenizer::tokenize(
				&ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool)))),
				"[[true,1,0],[false]]"
			)
			.unwrap(),
			Token::Array(vec![
				Token::Array(vec![Token::Bool(true), Token::Bool(true), Token::Bool(false)]),
				Token::Array(vec![Token::Bool(false)])
			])
		);
	}
}

-- file: ethabi/src/token/token.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Ethereum ABI params.

use core::fmt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{Address, Bytes, FixedBytes, Int, ParamType, Uint};

/// Ethereum ABI params.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Clone)]
pub enum Token {
	/// Address.
	///
	/// solidity name: address
	/// Encoded to left padded [0u8; 32].
	Address(Address),
	/// Vector of bytes with known size.
	///
	/// solidity name eg.: bytes8, bytes32, bytes64, bytes1024
	/// Encoded to right padded [0u8; ((N + 31) / 32) * 32].
	FixedBytes(FixedBytes),
	/// Vector of bytes of unknown size.
	///
	/// solidity name: bytes
	/// Encoded in two parts.
	/// Init part: offset of 'closing part`.
	/// Closing part: encoded length followed by encoded right padded bytes.
	Bytes(Bytes),
	/// Signed integer.
	///
	/// solidity name: int
	Int(Int),
	/// Unsigned integer.
	///
	/// solidity name: uint
	Uint(Uint),
	/// Boolean value.
	///
	/// solidity name: bool
	/// Encoded as left padded [0u8; 32], where last bit represents boolean value.
	Bool(bool),
	/// String.
	///
	/// solidity name: string
	/// Encoded in the same way as bytes. Must be utf8 compliant.
	String(String),
	/// Array with known size.
	///
	/// solidity name eg.: int[3], bool[3], address[][8]
	/// Encoding of array is equal to encoding of consecutive elements of array.
	FixedArray(Vec<Token>),
	/// Array of params with unknown size.
	///
	/// solidity name eg. int[], bool[], address[5][]
	Array(Vec<Token>),
	/// Tuple of params of variable types.
	///
	/// solidity name: tuple
	Tuple(Vec<Token>),
}

impl fmt::Display for Token {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Token::Bool(b) => write!(f, "{b}"),
			Token::String(ref s) => write!(f, "{s}"),
			Token::Address(ref a) => write!(f, "{a:x}"),
			Token::Bytes(ref bytes) | Token::FixedBytes(ref bytes) => write!(f, "{}", hex::encode(bytes)),
			Token::Uint(ref i) | Token::Int(ref i) => write!(f, "{i:x}"),
			Token::Array(ref arr) | Token::FixedArray(ref arr) => {
				let s = arr.iter().map(|ref t| format!("{t}")).collect::<Vec<String>>().join(",");

				write!(f, "[{s}]")
			}
			Token::Tuple(ref s) => {
				let s = s.iter().map(|ref t| format!("{t}")).collect::<Vec<String>>().join(",");

				write!(f, "({s})")
			}
		}
	}
}

impl Token {
	/// Check whether the type of the token matches the given parameter type.
	///
	/// Numeric types (`Int` and `Uint`) type check if the size of the token
	/// type is of greater or equal size than the provided parameter type.
	pub fn type_check(&self, param_type: &ParamType) -> bool {
		match *self {
			Token::Address(_) => *param_type == ParamType::Address,
			Token::Bytes(_) => *param_type == ParamType::Bytes,
			Token::Int(_) => {
				matches!(*param_type, ParamType::Int(_))
			}
			Token::Uint(_) => {
				matches!(*param_type, ParamType::Uint(_))
			}
			Token::Bool(_) => *param_type == ParamType::Bool,
			Token::String(_) => *param_type == ParamType::String,
			Token::FixedBytes(ref bytes) => {
				if let ParamType::FixedBytes(size) = *param_type {
					size >= bytes.len()
				} else {
					false
				}
			}
			Token::Array(ref tokens) => {
				if let ParamType::Array(ref param_type) = *param_type {
					tokens.iter().all(|t| t.type_check(param_type))
				} else {
					false
				}
			}
			Token::FixedArray(ref tokens) => {
				if let ParamType::FixedArray(ref param_type, size) = *param_type {
					size == tokens.len() && tokens.iter().all(|t| t.type_check(param_type))
				} else {
					false
				}
			}
			Token::Tuple(ref tokens) => {
				if let ParamType::Tuple(ref param_type) = *param_type {
					tokens.iter().enumerate().all(|(i, t)| t.type_check(&param_type[i]))
				} else {
					false
				}
			}
		}
	}

	/// Converts token to...
	pub fn into_address(self) -> Option<Address> {
		match self {
			Token::Address(address) => Some(address),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_fixed_bytes(self) -> Option<Vec<u8>> {
		match self {
			Token::FixedBytes(bytes) => Some(bytes),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_bytes(self) -> Option<Vec<u8>> {
		match self {
			Token::Bytes(bytes) => Some(bytes),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_int(self) -> Option<Int> {
		match self {
			Token::Int(int) => Some(int),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_uint(self) -> Option<Uint> {
		match self {
			Token::Uint(uint) => Some(uint),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_bool(self) -> Option<bool> {
		match self {
			Token::Bool(b) => Some(b),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_string(self) -> Option<String> {
		match self {
			Token::String(s) => Some(s),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_fixed_array(self) -> Option<Vec<Token>> {
		match self {
			Token::FixedArray(arr) => Some(arr),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_array(self) -> Option<Vec<Token>> {
		match self {
			Token::Array(arr) => Some(arr),
			_ => None,
		}
	}

	/// Converts token to...
	pub fn into_tuple(self) -> Option<Vec<Token>> {
		match self {
			Token::Tuple(tuple) => Some(tuple),
			_ => None,
		}
	}

	/// Check if all the types of the tokens match the given parameter types.
	pub fn types_check(tokens: &[Token], param_types: &[ParamType]) -> bool {
		param_types.len() == tokens.len() && {
			param_types.iter().zip(tokens).all(|(param_type, token)| token.type_check(param_type))
		}
	}

	/// Check if the token is a dynamic type resulting in prefixed encoding
	pub fn is_dynamic(&self) -> bool {
		match self {
			Token::Bytes(_) | Token::String(_) | Token::Array(_) => true,
			Token::FixedArray(tokens) => tokens.iter().any(|token| token.is_dynamic()),
			Token::Tuple(tokens) => tokens.iter().any(|token| token.is_dynamic()),
			_ => false,
		}
	}
}

#[cfg(test)]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{ParamType, Token};

	#[test]
	fn test_type_check() {
		fn assert_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
			assert!(Token::types_check(&tokens, &param_types))
		}

		fn assert_not_type_check(tokens: Vec<Token>, param_types: Vec<ParamType>) {
			assert!(!Token::types_check(&tokens, &param_types))
		}

		assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(256), ParamType::Bool]);
		assert_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32), ParamType::Bool]);

		assert_not_type_check(vec![Token::Uint(0.into())], vec![ParamType::Uint(32), ParamType::Bool]);
		assert_not_type_check(vec![Token::Uint(0.into()), Token::Bool(false)], vec![ParamType::Uint(32)]);
		assert_not_type_check(
			vec![Token::Bool(false), Token::Uint(0.into())],
			vec![ParamType::Uint(32), ParamType::Bool],
		);

		assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(4)]);
		assert_type_check(vec![Token::FixedBytes(vec![0, 0, 0])], vec![ParamType::FixedBytes(4)]);
		assert_not_type_check(vec![Token::FixedBytes(vec![0, 0, 0, 0])], vec![ParamType::FixedBytes(3)]);

		assert_type_check(
			vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
			vec![ParamType::Array(Box::new(ParamType::Bool))],
		);
		assert_not_type_check(
			vec![Token::Array(vec![Token::Bool(false), Token::Uint(0.into())])],
			vec![ParamType::Array(Box::new(ParamType::Bool))],
		);
		assert_not_type_check(
			vec![Token::Array(vec![Token::Bool(false), Token::Bool(true)])],
			vec![ParamType::Array(Box::new(ParamType::Address))],
		);

		assert_type_check(
			vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
			vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)],
		);
		assert_not_type_check(
			vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
			vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3)],
		);
		assert_not_type_check(
			vec![Token::FixedArray(vec![Token::Bool(false), Token::Uint(0.into())])],
			vec![ParamType::FixedArray(Box::new(ParamType::Bool), 2)],
		);
		assert_not_type_check(
			vec![Token::FixedArray(vec![Token::Bool(false), Token::Bool(true)])],
			vec![ParamType::FixedArray(Box::new(ParamType::Address), 2)],
		);
	}

	#[test]
	fn test_is_dynamic() {
		assert!(!Token::Address("0000000000000000000000000000000000000000".parse().unwrap()).is_dynamic());
		assert!(Token::Bytes(vec![0, 0, 0, 0]).is_dynamic());
		assert!(!Token::FixedBytes(vec![0, 0, 0, 0]).is_dynamic());
		assert!(!Token::Uint(0.into()).is_dynamic());
		assert!(!Token::Int(0.into()).is_dynamic());
		assert!(!Token::Bool(false).is_dynamic());
		assert!(Token::String("".into()).is_dynamic());
		assert!(Token::Array(vec![Token::Bool(false)]).is_dynamic());
		assert!(!Token::FixedArray(vec![Token::Uint(0.into())]).is_dynamic());
		assert!(Token::FixedArray(vec![Token::String("".into())]).is_dynamic());
		assert!(Token::FixedArray(vec![Token::Array(vec![Token::Bool(false)])]).is_dynamic());
	}
}

-- file: ethabi/src/token/lenient.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::{
	errors::Error,
	token::{StrictTokenizer, Tokenizer},
	Uint,
};
use std::borrow::Cow;

use once_cell::sync::Lazy;
static RE: Lazy<regex::Regex> =
	Lazy::new(|| regex::Regex::new(r"^([0-9]+)(\.[0-9]+)?\s*(ether|gwei|nanoether|nano|wei)$").expect("invalid regex"));

/// Tries to parse string as a token. Does not require string to clearly represent the value.
pub struct LenientTokenizer;

impl Tokenizer for LenientTokenizer {
	fn tokenize_address(value: &str) -> Result<[u8; 20], Error> {
		StrictTokenizer::tokenize_address(value)
	}

	fn tokenize_string(value: &str) -> Result<String, Error> {
		StrictTokenizer::tokenize_string(value)
	}

	fn tokenize_bool(value: &str) -> Result<bool, Error> {
		StrictTokenizer::tokenize_bool(value)
	}

	fn tokenize_bytes(value: &str) -> Result<Vec<u8>, Error> {
		StrictTokenizer::tokenize_bytes(value)
	}

	fn tokenize_fixed_bytes(value: &str, len: usize) -> Result<Vec<u8>, Error> {
		StrictTokenizer::tokenize_fixed_bytes(value, len)
	}

	fn tokenize_uint(value: &str) -> Result<[u8; 32], Error> {
		let result = StrictTokenizer::tokenize_uint(value);
		if result.is_ok() {
			return result;
		}

		// Tries to parse it as is first. If it fails, tries to check for
		// expectable units with the following format: 'Number[Spaces]Unit'.
		//   If regex fails, then the original FromDecStrErr should take priority
		let uint = match Uint::from_dec_str(value) {
			Ok(_uint) => _uint,
			Err(dec_error) => {
				let original_dec_error = dec_error.to_string();

				match RE.captures(value) {
					Some(captures) => {
						let integer = captures.get(1).expect("capture group does not exist").as_str();
						let fract = captures.get(2).map(|c| c.as_str().trim_start_matches('.')).unwrap_or_else(|| "");
						let units = captures.get(3).expect("capture group does not exist").as_str();

						let units = Uint::from(match units.to_lowercase().as_str() {
							"ether" => 18,
							"gwei" | "nano" | "nanoether" => 9,
							"wei" => 0,
							_ => return Err(dec_error.into()),
						});

						let integer = Uint::from_dec_str(integer)?.checked_mul(Uint::from(10u32).pow(units));

						if fract.is_empty() {
							integer.ok_or(dec_error)?
						} else {
							// makes sure we don't go beyond 18 decimals
							let fract_pow = units.checked_sub(Uint::from(fract.len())).ok_or(dec_error)?;

							let fract = Uint::from_dec_str(fract)?
								.checked_mul(Uint::from(10u32).pow(fract_pow))
								.ok_or_else(|| Error::Other(Cow::Owned(original_dec_error.clone())))?;

							integer
								.and_then(|integer| integer.checked_add(fract))
								.ok_or(Error::Other(Cow::Owned(original_dec_error)))?
						}
					}
					None => return Err(dec_error.into()),
				}
			}
		};

		Ok(uint.into())
	}

	// We don't have a proper signed int 256-bit long type, so here we're cheating. We build a U256
	// out of it and check that it's within the lower/upper bound of a hypothetical I256 type: half
	// the `U256::max_value().
	fn tokenize_int(value: &str) -> Result<[u8; 32], Error> {
		let result = StrictTokenizer::tokenize_int(value);
		if result.is_ok() {
			return result;
		}

		let abs = Uint::from_dec_str(value.trim_start_matches('-'))?;
		let max = Uint::max_value() / 2;
		let int = if value.starts_with('-') {
			if abs.is_zero() {
				return Ok(abs.into());
			} else if abs > max + 1 {
				return Err(Error::Other(Cow::Borrowed("int256 parse error: Underflow")));
			}
			!abs + 1 // two's complement
		} else {
			if abs > max {
				return Err(Error::Other(Cow::Borrowed("int256 parse error: Overflow")));
			}
			abs
		};
		Ok(int.into())
	}
}

#[cfg(test)]
mod tests {
	use ethereum_types::FromDecStrErr;

	use crate::{
		errors::Error,
		token::{LenientTokenizer, Token, Tokenizer},
		ParamType, Uint,
	};

	#[test]
	fn tokenize_uint() {
		assert_eq!(
			LenientTokenizer::tokenize(
				&ParamType::Uint(256),
				"1111111111111111111111111111111111111111111111111111111111111111"
			)
			.unwrap(),
			Token::Uint([0x11u8; 32].into())
		);
	}

	#[test]
	fn tokenize_uint_wei() {
		assert_eq!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1wei").unwrap(), Token::Uint(Uint::from(1)));

		assert_eq!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1 wei").unwrap(), Token::Uint(Uint::from(1)));
	}

	#[test]
	fn tokenize_uint_gwei() {
		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1nano").unwrap(),
			Token::Uint(Uint::from_dec_str("1000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1nanoether").unwrap(),
			Token::Uint(Uint::from_dec_str("1000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1gwei").unwrap(),
			Token::Uint(Uint::from_dec_str("1000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "0.1 gwei").unwrap(),
			Token::Uint(Uint::from_dec_str("100000000").unwrap())
		);
	}

	#[test]
	fn tokenize_uint_ether() {
		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "10000000000ether").unwrap(),
			Token::Uint(Uint::from_dec_str("10000000000000000000000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1ether").unwrap(),
			Token::Uint(Uint::from_dec_str("1000000000000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "0.01 ether").unwrap(),
			Token::Uint(Uint::from_dec_str("10000000000000000").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "0.000000000000000001ether").unwrap(),
			Token::Uint(Uint::from_dec_str("1").unwrap())
		);

		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "0.000000000000000001ether").unwrap(),
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1wei").unwrap(),
		);
	}

	#[test]
	fn tokenize_uint_array_ether() {
		assert_eq!(
			LenientTokenizer::tokenize(&ParamType::Array(Box::new(ParamType::Uint(256))), "[1ether,0.1 ether]")
				.unwrap(),
			Token::Array(vec![
				Token::Uint(Uint::from_dec_str("1000000000000000000").unwrap()),
				Token::Uint(Uint::from_dec_str("100000000000000000").unwrap())
			])
		);
	}

	#[test]
	fn tokenize_uint_invalid_units() {
		let _error = Error::from(FromDecStrErr::InvalidCharacter);

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "0.1 wei"), Err(_error)));

		// 0.1 wei
		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "0.0000000000000000001ether"), Err(_error)));

		// 1 ether + 0.1 wei
		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1.0000000000000000001ether"), Err(_error)));

		// 1_000_000_000 ether + 0.1 wei
		assert!(matches!(
			LenientTokenizer::tokenize(&ParamType::Uint(256), "1000000000.0000000000000000001ether"),
			Err(_error)
		));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "0..1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "..1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1. gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), ".1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "2.1.1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), ".1.1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1abc"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1 gwei "), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "g 1 gwei"), Err(_error)));

		assert!(matches!(LenientTokenizer::tokenize(&ParamType::Uint(256), "1gwei 1 gwei"), Err(_error)));
	}
}

-- file: ethabi/src/token/mod.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! ABI param and parsing for it.

#[cfg(feature = "full-serde")]
mod lenient;
#[cfg(feature = "full-serde")]
pub use lenient::LenientTokenizer;

#[cfg(feature = "full-serde")]
mod strict;
#[cfg(feature = "full-serde")]
pub use strict::StrictTokenizer;

mod token;
pub use token::Token;

#[cfg(all(feature = "serde", not(feature = "std")))]
use crate::no_std_prelude::*;
#[cfg(feature = "serde")]
use core::cmp::Ordering::{Equal, Less};

#[cfg(feature = "serde")]
use crate::{Error, ParamType};

/// This trait should be used to parse string values as tokens.
#[cfg(feature = "serde")]
pub trait Tokenizer {
	/// Tries to parse a string as a token of given type.
	fn tokenize(param: &ParamType, value: &str) -> Result<Token, Error> {
		match *param {
			ParamType::Address => {
				Self::tokenize_address(value.strip_prefix("0x").unwrap_or(value)).map(|a| Token::Address(a.into()))
			}
			ParamType::String => Self::tokenize_string(value).map(Token::String),
			ParamType::Bool => Self::tokenize_bool(value).map(Token::Bool),
			ParamType::Bytes => Self::tokenize_bytes(value.strip_prefix("0x").unwrap_or(value)).map(Token::Bytes),
			ParamType::FixedBytes(len) => {
				Self::tokenize_fixed_bytes(value.strip_prefix("0x").unwrap_or(value), len).map(Token::FixedBytes)
			}
			ParamType::Uint(_) => Self::tokenize_uint(value).map(Into::into).map(Token::Uint),
			ParamType::Int(_) => Self::tokenize_int(value).map(Into::into).map(Token::Int),
			ParamType::Array(ref p) => Self::tokenize_array(value, p).map(Token::Array),
			ParamType::FixedArray(ref p, len) => Self::tokenize_fixed_array(value, p, len).map(Token::FixedArray),
			ParamType::Tuple(ref p) => Self::tokenize_struct(value, p).map(Token::Tuple),
		}
	}

	/// Tries to parse a value as a vector of tokens of fixed size.
	fn tokenize_fixed_array(value: &str, param: &ParamType, len: usize) -> Result<Vec<Token>, Error> {
		let result = Self::tokenize_array(value, param)?;
		match result.len() == len {
			true => Ok(result),
			false => Err(Error::InvalidData),
		}
	}

	/// Tried to parse a struct as a vector of tokens
	fn tokenize_struct(value: &str, param: &[ParamType]) -> Result<Vec<Token>, Error> {
		if !value.starts_with('(') || !value.ends_with(')') {
			return Err(Error::InvalidData);
		}

		if value.chars().count() == 2 {
			return Ok(vec![]);
		}

		let mut result = vec![];
		let mut nested = 0isize;
		let mut ignore = false;
		let mut last_item = 1;

		let mut array_nested = 0isize;
		let mut array_item_start = 1;
		let mut last_is_array = false;

		let mut params = param.iter();
		for (pos, ch) in value.chars().enumerate() {
			match ch {
				'[' if !ignore => {
					if array_nested == 0 {
						array_item_start = pos;
					}
					array_nested += 1;
				}
				']' if !ignore => {
					array_nested -= 1;

					if nested > 0 {
						// still in nested tuple
						continue;
					}

					match array_nested.cmp(&0) {
						Less => {
							return Err(Error::InvalidData);
						}
						Equal => {
							let sub = &value[array_item_start..pos + 1];
							let token = Self::tokenize(params.next().ok_or(Error::InvalidData)?, sub)?;
							result.push(token);
							last_is_array = !last_is_array;
						}
						_ => {}
					}
				}
				_ if array_nested != 0 => continue,
				'(' if !ignore => {
					nested += 1;
				}
				')' if !ignore && last_is_array => {
					nested -= 1;
					last_is_array = !last_is_array;
				}
				')' if !ignore => {
					nested -= 1;

					match nested.cmp(&0) {
						Less => {
							return Err(Error::InvalidData);
						}
						Equal => {
							if last_is_array {
								last_is_array = !last_is_array;
							} else {
								let sub = &value[last_item..pos];
								let token = Self::tokenize(params.next().ok_or(Error::InvalidData)?, sub)?;
								result.push(token);
								last_item = pos + 1;
							}
						}
						_ => {}
					}
				}
				'"' => {
					ignore = !ignore;
				}
				',' if array_nested == 0 && nested == 1 && !ignore && last_is_array => {
					last_is_array = !last_is_array;
				}
				',' if nested == 1 && !ignore => {
					let sub = &value[last_item..pos];
					let token = Self::tokenize(params.next().ok_or(Error::InvalidData)?, sub)?;
					result.push(token);
					last_item = pos + 1;
				}
				_ => (),
			}
		}

		if ignore {
			return Err(Error::InvalidData);
		}

		Ok(result)
	}

	/// Tries to parse a value as a vector of tokens.
	fn tokenize_array(value: &str, param: &ParamType) -> Result<Vec<Token>, Error> {
		if !value.starts_with('[') || !value.ends_with(']') {
			return Err(Error::InvalidData);
		}

		if value.chars().count() == 2 {
			return Ok(vec![]);
		}

		let mut result = vec![];
		let mut nested = 0isize;
		let mut ignore = false;
		let mut last_item = 1;

		let mut tuple_nested = 0isize;
		let mut tuple_item_start = 1;
		let mut last_is_tuple = false;
		for (i, ch) in value.chars().enumerate() {
			match ch {
				'(' if !ignore => {
					if tuple_nested == 0 {
						tuple_item_start = i;
					}
					tuple_nested += 1;
				}
				')' if !ignore => {
					tuple_nested -= 1;
					match tuple_nested.cmp(&0) {
						Less => {
							return Err(Error::InvalidData);
						}
						Equal => {
							let sub = &value[tuple_item_start..i + 1];
							let token = Self::tokenize(param, sub)?;
							result.push(token);
							last_is_tuple = !last_is_tuple;
						}
						_ => {}
					}
				}
				_ if tuple_nested != 0 => continue,
				'[' if !ignore => {
					nested += 1;
				}
				']' if !ignore && last_is_tuple => {
					nested -= 1;
					last_is_tuple = !last_is_tuple;
				}
				']' if !ignore => {
					nested -= 1;
					match nested.cmp(&0) {
						Less => {
							return Err(Error::InvalidData);
						}
						Equal => {
							if last_is_tuple {
								last_is_tuple = !last_is_tuple;
							} else {
								let sub = &value[last_item..i];
								let token = Self::tokenize(param, sub)?;
								result.push(token);
								last_item = i + 1;
							}
						}
						_ => {}
					}
				}
				'"' => {
					ignore = !ignore;
				}
				',' if tuple_nested == 0 && nested == 1 && !ignore && last_is_tuple => {
					last_is_tuple = !last_is_tuple;
				}
				',' if tuple_nested == 0 && nested == 1 && !ignore => {
					let sub = &value[last_item..i];
					let token = Self::tokenize(param, sub)?;
					result.push(token);
					last_item = i + 1;
				}
				_ => (),
			}
		}

		if ignore {
			return Err(Error::InvalidData);
		}

		Ok(result)
	}

	/// Tries to parse a value as an address.
	fn tokenize_address(value: &str) -> Result<[u8; 20], Error>;

	/// Tries to parse a value as a string.
	fn tokenize_string(value: &str) -> Result<String, Error>;

	/// Tries to parse a value as a bool.
	fn tokenize_bool(value: &str) -> Result<bool, Error>;

	/// Tries to parse a value as bytes.
	fn tokenize_bytes(value: &str) -> Result<Vec<u8>, Error>;

	/// Tries to parse a value as bytes.
	fn tokenize_fixed_bytes(value: &str, len: usize) -> Result<Vec<u8>, Error>;

	/// Tries to parse a value as unsigned integer.
	fn tokenize_uint(value: &str) -> Result<[u8; 32], Error>;

	/// Tries to parse a value as signed integer.
	fn tokenize_int(value: &str) -> Result<[u8; 32], Error>;
}

#[cfg(all(test, feature = "full-serde"))]
mod test {
	use super::{LenientTokenizer, ParamType, Tokenizer};
	use crate::Token;

	#[test]
	fn single_quoted_in_array_must_error() {
		assert!(LenientTokenizer::tokenize_array("[1,\"0,false]", &ParamType::Bool).is_err());
		assert!(LenientTokenizer::tokenize_array("[false\"]", &ParamType::Bool).is_err());
		assert!(LenientTokenizer::tokenize_array("[1,false\"]", &ParamType::Bool).is_err());
		assert!(LenientTokenizer::tokenize_array("[1,\"0\",false]", &ParamType::Bool).is_err());
		assert!(LenientTokenizer::tokenize_array("[1,0]", &ParamType::Bool).is_ok());
	}

	#[test]
	fn tuples_arrays_mixed() {
		assert_eq!(
			LenientTokenizer::tokenize_array(
				"[([(true)],[(false,true)])]",
				&ParamType::Tuple(vec![
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Bool]))),
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Bool, ParamType::Bool]))),
				]),
			)
			.unwrap(),
			vec![Token::Tuple(vec![
				Token::Array(vec![Token::Tuple(vec![Token::Bool(true)])]),
				Token::Array(vec![Token::Tuple(vec![Token::Bool(false), Token::Bool(true)])]),
			])]
		);

		assert_eq!(
			LenientTokenizer::tokenize_struct(
				"([(true)],[(false,true)])",
				&[
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Bool]))),
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Bool, ParamType::Bool]))),
				]
			)
			.unwrap(),
			vec![
				Token::Array(vec![Token::Tuple(vec![Token::Bool(true)])]),
				Token::Array(vec![Token::Tuple(vec![Token::Bool(false), Token::Bool(true)])]),
			]
		);
	}

	#[test]
	fn tuple_array_nested() {
		assert_eq!(
			LenientTokenizer::tokenize_struct(
				"([(5c9d55b78febcc2061715ba4f57ecf8ea2711f2c)],2)",
				&[ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address,],)),), ParamType::Uint(256,),]
			)
			.unwrap(),
			vec![
				Token::Array(vec![Token::Tuple(vec![Token::Address(
					"0x5c9d55b78febcc2061715ba4f57ecf8ea2711f2c".parse().unwrap(),
				),])]),
				Token::Uint(2u64.into()),
			]
		);
	}
}

-- file: ethabi/src/param.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Function param.

#[cfg(feature = "serde")]
use core::fmt;

#[cfg(feature = "serde")]
use serde::{
	de::{Error, MapAccess, Visitor},
	ser::{SerializeMap, SerializeSeq},
	Deserialize, Deserializer, Serialize, Serializer,
};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::ParamType;
#[cfg(feature = "serde")]
use crate::{param_type::Writer, TupleParam};

/// Function param.
#[derive(Debug, Clone, PartialEq)]
pub struct Param {
	/// Param name.
	pub name: String,
	/// Param type.
	pub kind: ParamType,
	/// Additional Internal type.
	pub internal_type: Option<String>,
}

#[cfg(feature = "serde")]
impl<'a> Deserialize<'a> for Param {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: Deserializer<'a>,
	{
		deserializer.deserialize_any(ParamVisitor)
	}
}

#[cfg(feature = "serde")]
struct ParamVisitor;

#[cfg(feature = "serde")]
impl<'a> Visitor<'a> for ParamVisitor {
	type Value = Param;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		write!(formatter, "a valid event parameter spec")
	}

	fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
	where
		V: MapAccess<'a>,
	{
		let mut name = None;
		let mut kind = None;
		let mut components = None;
		let mut internal_type = None;

		while let Some(ref key) = map.next_key::<String>()? {
			match key.as_ref() {
				"name" => {
					if name.is_some() {
						return Err(Error::duplicate_field("name"));
					}
					name = Some(map.next_value()?);
				}
				"type" => {
					if kind.is_some() {
						return Err(Error::duplicate_field("kind"));
					}
					kind = Some(map.next_value()?);
				}
				"internalType" => {
					if internal_type.is_some() {
						return Err(Error::duplicate_field("internalType"));
					}
					internal_type = Some(map.next_value()?);
				}
				"components" => {
					if components.is_some() {
						return Err(Error::duplicate_field("components"));
					}
					let component: Vec<TupleParam> = map.next_value()?;
					components = Some(component)
				}
				_ => {}
			}
		}
		let name = name.ok_or_else(|| Error::missing_field("name"))?;
		let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
		set_tuple_components::<V::Error>(&mut kind, components)?;
		Ok(Param { name, kind, internal_type })
	}
}

#[cfg(feature = "serde")]
impl Serialize for Param {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut map = serializer.serialize_map(None)?;
		if let Some(ref internal_type) = self.internal_type {
			map.serialize_entry("internalType", internal_type)?;
		}
		map.serialize_entry("name", &self.name)?;
		map.serialize_entry("type", &Writer::write_for_abi(&self.kind, false))?;
		if let Some(inner_tuple) = inner_tuple(&self.kind) {
			map.serialize_key("components")?;
			map.serialize_value(&SerializeableParamVec(inner_tuple))?;
		}
		map.end()
	}
}

#[cfg(feature = "serde")]
pub(crate) fn inner_tuple_mut(mut param: &mut ParamType) -> Option<&mut Vec<ParamType>> {
	loop {
		match param {
			ParamType::Array(inner) => param = inner.as_mut(),
			ParamType::FixedArray(inner, _) => param = inner.as_mut(),
			ParamType::Tuple(inner) => return Some(inner),
			_ => return None,
		}
	}
}

#[cfg(feature = "serde")]
pub(crate) fn inner_tuple(mut param: &ParamType) -> Option<&Vec<ParamType>> {
	loop {
		match param {
			ParamType::Array(inner) => param = inner.as_ref(),
			ParamType::FixedArray(inner, _) => param = inner.as_ref(),
			ParamType::Tuple(inner) => return Some(inner),
			_ => return None,
		}
	}
}

#[cfg(feature = "serde")]
pub(crate) fn set_tuple_components<Error: serde::de::Error>(
	kind: &mut ParamType,
	components: Option<Vec<TupleParam>>,
) -> Result<(), Error> {
	if let Some(inner_tuple_mut) = inner_tuple_mut(kind) {
		let tuple_params = components.ok_or_else(|| Error::missing_field("components"))?;
		inner_tuple_mut.extend(tuple_params.into_iter().map(|param| param.kind))
	}
	Ok(())
}

#[cfg(feature = "serde")]
pub(crate) struct SerializeableParamVec<'a>(pub(crate) &'a [ParamType]);

#[cfg(feature = "serde")]
impl Serialize for SerializeableParamVec<'_> {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut seq = serializer.serialize_seq(None)?;
		for param in self.0 {
			seq.serialize_element(&SerializeableParam(param))?;
		}
		seq.end()
	}
}

#[cfg(feature = "serde")]
pub(crate) struct SerializeableParam<'a>(pub(crate) &'a ParamType);

#[cfg(feature = "serde")]
impl Serialize for SerializeableParam<'_> {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut map = serializer.serialize_map(None)?;
		map.serialize_entry("type", &Writer::write_for_abi(self.0, false))?;
		if let Some(inner_tuple) = inner_tuple(self.0) {
			map.serialize_key("components")?;
			map.serialize_value(&SerializeableParamVec(inner_tuple))?;
		}
		map.end()
	}
}

#[cfg(all(test, feature = "serde"))]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{
		tests::{assert_json_eq, assert_ser_de},
		Param, ParamType,
	};

	#[test]
	fn param_simple() {
		let s = r#"{
			"name": "foo",
			"type": "address"
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(deserialized, Param { name: "foo".to_owned(), kind: ParamType::Address, internal_type: None });

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_simple_internal_type() {
		let s = r#"{
			"name": "foo",
			"type": "address",
			"internalType": "struct Verifier.Proof"
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Address,
				internal_type: Some("struct Verifier.Proof".to_string())
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple() {
		let s = r#"{
			"name": "foo",
			"type": "tuple",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "tuple",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_internal_type() {
		let s = r#"{
			"name": "foo",
			"type": "tuple",
			"internalType": "struct Pairing.G1Point[]",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "tuple",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				internal_type: Some("struct Pairing.G1Point[]".to_string())
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_named() {
		let s = r#"{
			"name": "foo",
			"type": "tuple",
			"components": [
				{
					"name": "amount",
					"type": "uint48"
				},
				{
					"name": "things",
					"type": "tuple",
					"components": [
						{
							"name": "baseTupleParam",
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				internal_type: None
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn param_tuple_array() {
		let s = r#"{
			"name": "foo",
			"type": "tuple[]",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "address"
				},
				{
					"type": "address"
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
					ParamType::Uint(48),
					ParamType::Address,
					ParamType::Address
				]))),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_array_of_array_of_tuple() {
		let s = r#"{
			"name": "foo",
			"type": "tuple[][]",
			"components": [
				{
					"type": "uint8"
				},
				{
					"type": "uint16"
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();
		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Tuple(vec![
					ParamType::Uint(8),
					ParamType::Uint(16),
				]))))),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_fixed_array() {
		let s = r#"{
			"name": "foo",
			"type": "tuple[2]",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "address"
				},
				{
					"type": "address"
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::FixedArray(
					Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
					2
				),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_with_nested_tuple_arrays() {
		let s = r#"{
			"name": "foo",
			"type": "tuple",
			"components": [
				{
					"type": "tuple[]",
					"components": [
						{
							"type": "address"
						}
					]
				},
				{
					"type": "tuple[42]",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: Param = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Param {
				name: "foo".to_owned(),
				kind: ParamType::Tuple(vec![
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
					ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
				]),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}
}

-- file: ethabi/src/encoder.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! ABI encoder.

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{util::pad_u32, Bytes, Token, Word};

fn pad_bytes_len(bytes: &[u8]) -> u32 {
	// "+ 1" because len is also appended
	((bytes.len() + 31) / 32) as u32 + 1
}

fn pad_bytes_append(data: &mut Vec<Word>, bytes: &[u8]) {
	data.push(pad_u32(bytes.len() as u32));
	fixed_bytes_append(data, bytes);
}

fn fixed_bytes_len(bytes: &[u8]) -> u32 {
	((bytes.len() + 31) / 32) as u32
}

fn fixed_bytes_append(result: &mut Vec<Word>, bytes: &[u8]) {
	let len = (bytes.len() + 31) / 32;
	for i in 0..len {
		let mut padded = [0u8; 32];

		let to_copy = match i == len - 1 {
			false => 32,
			true => match bytes.len() % 32 {
				0 => 32,
				x => x,
			},
		};

		let offset = 32 * i;
		padded[..to_copy].copy_from_slice(&bytes[offset..offset + to_copy]);
		result.push(padded);
	}
}

#[derive(Debug)]
enum Mediate<'a> {
	// head
	Raw(u32, &'a Token),
	RawArray(Vec<Mediate<'a>>),

	// head + tail
	Prefixed(u32, &'a Token),
	PrefixedArray(Vec<Mediate<'a>>),
	PrefixedArrayWithLength(Vec<Mediate<'a>>),
}

impl Mediate<'_> {
	fn head_len(&self) -> u32 {
		match self {
			Mediate::Raw(len, _) => 32 * len,
			Mediate::RawArray(ref mediates) => mediates.iter().map(|mediate| mediate.head_len()).sum(),
			Mediate::Prefixed(_, _) | Mediate::PrefixedArray(_) | Mediate::PrefixedArrayWithLength(_) => 32,
		}
	}

	fn tail_len(&self) -> u32 {
		match self {
			Mediate::Raw(_, _) | Mediate::RawArray(_) => 0,
			Mediate::Prefixed(len, _) => 32 * len,
			Mediate::PrefixedArray(ref mediates) => mediates.iter().fold(0, |acc, m| acc + m.head_len() + m.tail_len()),
			Mediate::PrefixedArrayWithLength(ref mediates) => {
				mediates.iter().fold(32, |acc, m| acc + m.head_len() + m.tail_len())
			}
		}
	}

	fn head_append(&self, acc: &mut Vec<Word>, suffix_offset: u32) {
		match *self {
			Mediate::Raw(_, raw) => encode_token_append(acc, raw),
			Mediate::RawArray(ref raw) => raw.iter().for_each(|mediate| mediate.head_append(acc, 0)),
			Mediate::Prefixed(_, _) | Mediate::PrefixedArray(_) | Mediate::PrefixedArrayWithLength(_) => {
				acc.push(pad_u32(suffix_offset))
			}
		}
	}

	fn tail_append(&self, acc: &mut Vec<Word>) {
		match *self {
			Mediate::Raw(_, _) | Mediate::RawArray(_) => {}
			Mediate::Prefixed(_, raw) => encode_token_append(acc, raw),
			Mediate::PrefixedArray(ref mediates) => encode_head_tail_append(acc, mediates),
			Mediate::PrefixedArrayWithLength(ref mediates) => {
				// + 32 added to offset represents len of the array prepended to tail
				acc.push(pad_u32(mediates.len() as u32));
				encode_head_tail_append(acc, mediates);
			}
		};
	}
}

/// Encodes vector of tokens into ABI compliant vector of bytes.
pub fn encode(tokens: &[Token]) -> Bytes {
	let mediates = &tokens.iter().map(mediate_token).collect::<Vec<_>>();

	encode_head_tail(mediates).into_iter().flatten().collect()
}

fn encode_head_tail(mediates: &[Mediate]) -> Vec<Word> {
	let (heads_len, tails_len) =
		mediates.iter().fold((0, 0), |(head_acc, tail_acc), m| (head_acc + m.head_len(), tail_acc + m.tail_len()));

	let mut result = Vec::with_capacity((heads_len + tails_len) as usize);
	encode_head_tail_append(&mut result, mediates);

	result
}

fn encode_head_tail_append(acc: &mut Vec<Word>, mediates: &[Mediate]) {
	let heads_len = mediates.iter().fold(0, |head_acc, m| head_acc + m.head_len());

	let mut offset = heads_len;
	for mediate in mediates {
		mediate.head_append(acc, offset);
		offset += mediate.tail_len();
	}

	mediates.iter().for_each(|m| m.tail_append(acc));
}

fn mediate_token(token: &Token) -> Mediate {
	match token {
		Token::Address(_) => Mediate::Raw(1, token),
		Token::Bytes(bytes) => Mediate::Prefixed(pad_bytes_len(bytes), token),
		Token::String(s) => Mediate::Prefixed(pad_bytes_len(s.as_bytes()), token),
		Token::FixedBytes(bytes) => Mediate::Raw(fixed_bytes_len(bytes), token),
		Token::Int(_) | Token::Uint(_) | Token::Bool(_) => Mediate::Raw(1, token),
		Token::Array(ref tokens) => {
			let mediates = tokens.iter().map(mediate_token).collect();

			Mediate::PrefixedArrayWithLength(mediates)
		}
		Token::FixedArray(ref tokens) | Token::Tuple(ref tokens) => {
			let mediates = tokens.iter().map(mediate_token).collect();

			if token.is_dynamic() {
				Mediate::PrefixedArray(mediates)
			} else {
				Mediate::RawArray(mediates)
			}
		}
	}
}

fn encode_token_append(data: &mut Vec<Word>, token: &Token) {
	match *token {
		Token::Address(ref address) => {
			let mut padded = [0u8; 32];
			padded[12..].copy_from_slice(address.as_ref());
			data.push(padded);
		}
		Token::Bytes(ref bytes) => pad_bytes_append(data, bytes),
		Token::String(ref s) => pad_bytes_append(data, s.as_bytes()),
		Token::FixedBytes(ref bytes) => fixed_bytes_append(data, bytes),
		Token::Int(int) => data.push(int.into()),
		Token::Uint(uint) => data.push(uint.into()),
		Token::Bool(b) => {
			let mut value = [0u8; 32];
			if b {
				value[31] = 1;
			}
			data.push(value);
		}
		_ => panic!("Unhandled nested token: {:?}", token),
	};
}

#[cfg(test)]
mod tests {
	use hex_literal::hex;

	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{encode, util::pad_u32, Token};

	#[test]
	fn encode_address() {
		let address = Token::Address([0x11u8; 20].into());
		let encoded = encode(&[address]);
		let expected = hex!("0000000000000000000000001111111111111111111111111111111111111111");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let addresses = Token::Array(vec![address1, address2]);
		let encoded = encode(&[addresses]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_fixed_array_of_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let addresses = Token::FixedArray(vec![address1, address2]);
		let encoded = encode(&[addresses]);
		let expected = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_two_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let encoded = encode(&[address1, address2]);
		let expected = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_fixed_array_of_dynamic_array_of_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::Array(vec![address1, address2]);
		let array1 = Token::Array(vec![address3, address4]);
		let fixed = Token::FixedArray(vec![array0, array1]);
		let encoded = encode(&[fixed]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000040
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_fixed_array_of_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::FixedArray(vec![address1, address2]);
		let array1 = Token::FixedArray(vec![address3, address4]);
		let dynamic = Token::Array(vec![array0, array1]);
		let encoded = encode(&[dynamic]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_dynamic_arrays() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let array0 = Token::Array(vec![address1]);
		let array1 = Token::Array(vec![address2]);
		let dynamic = Token::Array(vec![array0, array1]);
		let encoded = encode(&[dynamic]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000002222222222222222222222222222222222222222
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_dynamic_arrays2() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::Array(vec![address1, address2]);
		let array1 = Token::Array(vec![address3, address4]);
		let dynamic = Token::Array(vec![array0, array1]);
		let encoded = encode(&[dynamic]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000000000000000000000000000000000000000000040
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_fixed_array_of_fixed_arrays() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::FixedArray(vec![address1, address2]);
		let array1 = Token::FixedArray(vec![address3, address4]);
		let fixed = Token::FixedArray(vec![array0, array1]);
		let encoded = encode(&[fixed]);
		let expected = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_fixed_array_of_static_tuples_followed_by_dynamic_type() {
		let tuple1 = Token::Tuple(vec![
			Token::Uint(93523141.into()),
			Token::Uint(352332135.into()),
			Token::Address([0x44u8; 20].into()),
		]);
		let tuple2 =
			Token::Tuple(vec![Token::Uint(12411.into()), Token::Uint(451.into()), Token::Address([0x22u8; 20].into())]);
		let fixed = Token::FixedArray(vec![tuple1, tuple2]);
		let s = Token::String("gavofyork".to_owned());
		let encoded = encode(&[fixed, s]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000005930cc5
			0000000000000000000000000000000000000000000000000000000015002967
			0000000000000000000000004444444444444444444444444444444444444444
			000000000000000000000000000000000000000000000000000000000000307b
			00000000000000000000000000000000000000000000000000000000000001c3
			0000000000000000000000002222222222222222222222222222222222222222
			00000000000000000000000000000000000000000000000000000000000000e0
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_empty_array() {
		// Empty arrays
		let encoded = encode(&[Token::Array(vec![]), Token::Array(vec![])]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000060
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);

		// Nested empty arrays
		let encoded = encode(&[Token::Array(vec![Token::Array(vec![])]), Token::Array(vec![Token::Array(vec![])])]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000040
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_bytes() {
		let bytes = Token::Bytes(vec![0x12, 0x34]);
		let encoded = encode(&[bytes]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			1234000000000000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_fixed_bytes() {
		let bytes = Token::FixedBytes(vec![0x12, 0x34]);
		let encoded = encode(&[bytes]);
		let expected = hex!("1234000000000000000000000000000000000000000000000000000000000000");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_string() {
		let s = Token::String("gavofyork".to_owned());
		let encoded = encode(&[s]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_bytes2() {
		let bytes = Token::Bytes(hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec());
		let encoded = encode(&[bytes]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			000000000000000000000000000000000000000000000000000000000000001f
			1000000000000000000000000000000000000000000000000000000000000200
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_bytes3() {
		let bytes = Token::Bytes(
			hex!(
				"
			1000000000000000000000000000000000000000000000000000000000000000
			1000000000000000000000000000000000000000000000000000000000000000
		"
			)
			.to_vec(),
		);
		let encoded = encode(&[bytes]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000040
			1000000000000000000000000000000000000000000000000000000000000000
			1000000000000000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_two_bytes() {
		let bytes1 = Token::Bytes(hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec());
		let bytes2 = Token::Bytes(hex!("0010000000000000000000000000000000000000000000000000000000000002").to_vec());
		let encoded = encode(&[bytes1, bytes2]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			000000000000000000000000000000000000000000000000000000000000001f
			1000000000000000000000000000000000000000000000000000000000000200
			0000000000000000000000000000000000000000000000000000000000000020
			0010000000000000000000000000000000000000000000000000000000000002
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_uint() {
		let mut uint = [0u8; 32];
		uint[31] = 4;
		let encoded = encode(&[Token::Uint(uint.into())]);
		let expected = hex!("0000000000000000000000000000000000000000000000000000000000000004");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_int() {
		let mut int = [0u8; 32];
		int[31] = 4;
		let encoded = encode(&[Token::Int(int.into())]);
		let expected = hex!("0000000000000000000000000000000000000000000000000000000000000004");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_bool() {
		let encoded = encode(&[Token::Bool(true)]);
		let expected = hex!("0000000000000000000000000000000000000000000000000000000000000001");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_bool2() {
		let encoded = encode(&[Token::Bool(false)]);
		let expected = hex!("0000000000000000000000000000000000000000000000000000000000000000");
		assert_eq!(encoded, expected);
	}

	#[test]
	fn comprehensive_test() {
		let bytes = hex!(
			"
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		"
		)
		.to_vec();
		let encoded =
			encode(&[Token::Int(5.into()), Token::Bytes(bytes.clone()), Token::Int(3.into()), Token::Bytes(bytes)]);

		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000005
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000003
			00000000000000000000000000000000000000000000000000000000000000e0
			0000000000000000000000000000000000000000000000000000000000000040
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
			0000000000000000000000000000000000000000000000000000000000000040
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn test_pad_u32() {
		// this will fail if endianess is not supported
		assert_eq!(pad_u32(0x1)[31], 1);
		assert_eq!(pad_u32(0x100)[30], 1);
	}

	#[test]
	fn comprehensive_test2() {
		let encoded = encode(&vec![
			Token::Int(1.into()),
			Token::String("gavofyork".to_owned()),
			Token::Int(2.into()),
			Token::Int(3.into()),
			Token::Int(4.into()),
			Token::Array(vec![Token::Int(5.into()), Token::Int(6.into()), Token::Int(7.into())]),
		]);

		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000001
			00000000000000000000000000000000000000000000000000000000000000c0
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000000000000000000000000000000000000000000003
			0000000000000000000000000000000000000000000000000000000000000004
			0000000000000000000000000000000000000000000000000000000000000100
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000003
			0000000000000000000000000000000000000000000000000000000000000005
			0000000000000000000000000000000000000000000000000000000000000006
			0000000000000000000000000000000000000000000000000000000000000007
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_bytes() {
		let bytes = hex!("019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a4218a274f00d607");
		let encoded = encode(&[Token::Array(vec![Token::Bytes(bytes.to_vec())])]);

		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000026
			019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a421
			8a274f00d6070000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_array_of_bytes2() {
		let bytes = hex!("4444444444444444444444444444444444444444444444444444444444444444444444444444");
		let bytes2 = hex!("6666666666666666666666666666666666666666666666666666666666666666666666666666");
		let encoded = encode(&[Token::Array(vec![Token::Bytes(bytes.to_vec()), Token::Bytes(bytes2.to_vec())])]);

		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000000000000000000000000000000000000000000040
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000026
			4444444444444444444444444444444444444444444444444444444444444444
			4444444444440000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000026
			6666666666666666666666666666666666666666666666666666666666666666
			6666666666660000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_static_tuple_of_addresses() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let encoded = encode(&[Token::Tuple(vec![address1, address2])]);

		let expected = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_tuple() {
		let string1 = Token::String("gavofyork".to_owned());
		let string2 = Token::String("gavofyork".to_owned());
		let tuple = Token::Tuple(vec![string1, string2]);
		let encoded = encode(&[tuple]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_tuple_of_bytes2() {
		let bytes = hex!("4444444444444444444444444444444444444444444444444444444444444444444444444444");
		let bytes2 = hex!("6666666666666666666666666666666666666666666666666666666666666666666666666666");
		let encoded = encode(&[Token::Tuple(vec![Token::Bytes(bytes.to_vec()), Token::Bytes(bytes2.to_vec())])]);

		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000040
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000026
			4444444444444444444444444444444444444444444444444444444444444444
			4444444444440000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000026
			6666666666666666666666666666666666666666666666666666666666666666
			6666666666660000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_complex_tuple() {
		let uint = Token::Uint([0x11u8; 32].into());
		let string = Token::String("gavofyork".to_owned());
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let tuple = Token::Tuple(vec![uint, string, address1, address2]);
		let encoded = encode(&[tuple]);
		let expected = hex!(
			"
            0000000000000000000000000000000000000000000000000000000000000020
            1111111111111111111111111111111111111111111111111111111111111111
            0000000000000000000000000000000000000000000000000000000000000080
            0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_nested_tuple() {
		let string1 = Token::String("test".to_owned());
		let string2 = Token::String("cyborg".to_owned());
		let string3 = Token::String("night".to_owned());
		let string4 = Token::String("day".to_owned());
		let string5 = Token::String("weee".to_owned());
		let string6 = Token::String("funtests".to_owned());
		let bool = Token::Bool(true);
		let deep_tuple = Token::Tuple(vec![string5, string6]);
		let inner_tuple = Token::Tuple(vec![string3, string4, deep_tuple]);
		let outer_tuple = Token::Tuple(vec![string1, bool, string2, inner_tuple]);
		let encoded = encode(&[outer_tuple]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000001
			00000000000000000000000000000000000000000000000000000000000000c0
			0000000000000000000000000000000000000000000000000000000000000100
			0000000000000000000000000000000000000000000000000000000000000004
			7465737400000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000006
			6379626f72670000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000060
			00000000000000000000000000000000000000000000000000000000000000a0
			00000000000000000000000000000000000000000000000000000000000000e0
			0000000000000000000000000000000000000000000000000000000000000005
			6e69676874000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000003
			6461790000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000004
			7765656500000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000008
			66756e7465737473000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_params_containing_dynamic_tuple() {
		let address1 = Token::Address([0x22u8; 20].into());
		let bool1 = Token::Bool(true);
		let string1 = Token::String("spaceship".to_owned());
		let string2 = Token::String("cyborg".to_owned());
		let tuple = Token::Tuple(vec![bool1, string1, string2]);
		let address2 = Token::Address([0x33u8; 20].into());
		let address3 = Token::Address([0x44u8; 20].into());
		let bool2 = Token::Bool(false);
		let encoded = encode(&[address1, tuple, address2, address3, bool2]);
		let expected = hex!(
			"
			0000000000000000000000002222222222222222222222222222222222222222
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000060
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000009
			7370616365736869700000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000006
			6379626f72670000000000000000000000000000000000000000000000000000
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_params_containing_static_tuple() {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let bool1 = Token::Bool(true);
		let bool2 = Token::Bool(false);
		let tuple = Token::Tuple(vec![address2, bool1, bool2]);
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let encoded = encode(&[address1, tuple, address3, address4]);
		let expected = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}

	#[test]
	fn encode_dynamic_tuple_with_nested_static_tuples() {
		let token = {
			use crate::Token::*;
			Tuple(vec![
				Tuple(vec![Tuple(vec![Bool(false), Uint(0x777.into())])]),
				Array(vec![Uint(0x42.into()), Uint(0x1337.into())]),
			])
		};
		let encoded = encode(&[token]);
		let expected = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000777
			0000000000000000000000000000000000000000000000000000000000000060
			0000000000000000000000000000000000000000000000000000000000000002
			0000000000000000000000000000000000000000000000000000000000000042
			0000000000000000000000000000000000000000000000000000000000001337
		"
		)
		.to_vec();
		assert_eq!(encoded, expected);
	}
}

-- file: ethabi/src/operation.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Operation type.

use crate::{error::Error, Constructor, Event, Function};
use serde::{Deserialize, Serialize};

/// Operation type.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Operation {
	/// Contract constructor.
	#[serde(rename = "constructor")]
	Constructor(Constructor),
	/// Contract function.
	#[serde(rename = "function")]
	Function(Function),
	/// Contract event.
	#[serde(rename = "event")]
	Event(Event),
	/// Contract event.
	#[serde(rename = "error")]
	Error(Error),
	/// Fallback function.
	#[serde(rename = "fallback")]
	Fallback,
	/// Receive function.
	#[serde(rename = "receive")]
	Receive,
}

#[cfg(test)]
mod tests {
	use super::Operation;
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{tests::assert_ser_de, Event, EventParam, Function, Param, ParamType, StateMutability};

	#[test]
	fn operation() {
		let s = r#"{
			"type":"function",
			"inputs": [{
				"name":"a",
				"type":"address"
			}],
			"name":"foo",
			"outputs": []
		}"#;

		let deserialized: Operation = serde_json::from_str(s).unwrap();

		#[allow(deprecated)]
		let function = Function {
			name: "foo".to_owned(),
			inputs: vec![Param { name: "a".to_owned(), kind: ParamType::Address, internal_type: None }],
			outputs: vec![],
			constant: None,
			state_mutability: StateMutability::NonPayable,
		};
		assert_eq!(deserialized, Operation::Function(function));

		assert_ser_de(&deserialized);
	}

	#[test]
	fn event_operation_with_tuple_array_input() {
		let s = r#"{
			"type":"event",
			"inputs": [
				{
					"name":"a",
					"type":"address",
					"indexed":true
				},
				{
				  "components": [
					{
					  "internalType": "address",
					  "name": "to",
					  "type": "address"
					},
					{
					  "internalType": "uint256",
					  "name": "value",
					  "type": "uint256"
					},
					{
					  "internalType": "bytes",
					  "name": "data",
					  "type": "bytes"
					}
				  ],
				  "indexed": false,
				  "internalType": "struct Action[]",
				  "name": "b",
				  "type": "tuple[]"
				}
			],
			"name":"E",
			"outputs": [],
			"anonymous": false
		}"#;

		let deserialized: Operation = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			Operation::Event(Event {
				name: "E".to_owned(),
				inputs: vec![
					EventParam { name: "a".to_owned(), kind: ParamType::Address, indexed: true },
					EventParam {
						name: "b".to_owned(),
						kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
							ParamType::Address,
							ParamType::Uint(256),
							ParamType::Bytes
						]))),
						indexed: false
					},
				],
				anonymous: false,
			})
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn sanitize_function_name() {
		fn test_sanitize_function_name(name: &str, expected: &str) {
			let s = format!(
				r#"{{
					"type":"function",
					"inputs": [{{
						"name":"a",
						"type":"address"
					}}],
					"name":"{}",
					"outputs": []
				}}"#,
				name
			);

			let deserialized: Operation = serde_json::from_str(&s).unwrap();
			let function = match &deserialized {
				Operation::Function(f) => f,
				_ => panic!("expected function"),
			};

			assert_eq!(function.name, expected);

			assert_ser_de(&deserialized);
		}

		test_sanitize_function_name("foo", "foo");
		test_sanitize_function_name("foo()", "foo");
		test_sanitize_function_name("()", "");
		test_sanitize_function_name("", "");
	}

	#[test]
	fn sanitize_event_name() {
		fn test_sanitize_event_name(name: &str, expected: &str) {
			let s = format!(
				r#"{{
					"type":"event",
						"inputs": [{{
							"name":"a",
							"type":"address",
							"indexed":true
						}}],
						"name":"{}",
						"outputs": [],
						"anonymous": false
				}}"#,
				name
			);

			let deserialized: Operation = serde_json::from_str(&s).unwrap();
			let event = match deserialized {
				Operation::Event(e) => e,
				_ => panic!("expected event!"),
			};

			assert_eq!(event.name, expected);

			assert_ser_de(&Operation::Event(event));
		}

		test_sanitize_event_name("foo", "foo");
		test_sanitize_event_name("foo()", "foo");
		test_sanitize_event_name("()", "");
		test_sanitize_event_name("", "");
	}
}

-- file: ethabi/src/util.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Utils used by different modules.

use crate::Word;

/// Converts a u32 to a right aligned array of 32 bytes.
pub fn pad_u32(value: u32) -> Word {
	let mut padded = [0u8; 32];
	padded[28..32].copy_from_slice(&value.to_be_bytes());
	padded
}

// This is a workaround to support non-spec compliant function and event names,
// see: https://github.com/paritytech/parity/issues/4122
#[cfg(feature = "serde")]
pub(crate) mod sanitize_name {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use serde::{Deserialize, Deserializer};

	pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
	where
		D: Deserializer<'de>,
	{
		let mut name = String::deserialize(deserializer)?;
		sanitize_name(&mut name);
		Ok(name)
	}

	fn sanitize_name(name: &mut String) {
		if let Some(i) = name.find('(') {
			name.truncate(i);
		}
	}
}

#[cfg(test)]
mod tests {
	use super::pad_u32;
	use hex_literal::hex;

	#[test]
	fn test_pad_u32() {
		// this will fail if endianness is not supported
		assert_eq!(
			pad_u32(0).to_vec(),
			hex!("0000000000000000000000000000000000000000000000000000000000000000").to_vec()
		);
		assert_eq!(
			pad_u32(1).to_vec(),
			hex!("0000000000000000000000000000000000000000000000000000000000000001").to_vec()
		);
		assert_eq!(
			pad_u32(0x100).to_vec(),
			hex!("0000000000000000000000000000000000000000000000000000000000000100").to_vec()
		);
		assert_eq!(
			pad_u32(0xffffffff).to_vec(),
			hex!("00000000000000000000000000000000000000000000000000000000ffffffff").to_vec()
		);
	}
}

-- file: ethabi/src/error.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Contract error

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{
	decode, encode, errors,
	signature::{long_signature, short_signature},
	Bytes, Hash, Param, ParamType, Result, Token,
};

/// Contract error specification.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
	/// Error name.
	#[cfg_attr(feature = "serde", serde(deserialize_with = "crate::util::sanitize_name::deserialize"))]
	pub name: String,
	/// Error input.
	pub inputs: Vec<Param>,
}

impl Error {
	/// Returns types of all params.
	fn param_types(&self) -> Vec<ParamType> {
		self.inputs.iter().map(|p| p.kind.clone()).collect()
	}

	/// Error signature
	pub fn signature(&self) -> Hash {
		long_signature(&self.name, &self.param_types())
	}

	/// Prepares ABI error with given input params.
	pub fn encode(&self, tokens: &[Token]) -> Result<Bytes> {
		let params = self.param_types();

		if !Token::types_check(tokens, &params) {
			return Err(errors::Error::InvalidData);
		}

		let signed = short_signature(&self.name, &params).to_vec();
		let encoded = encode(tokens);
		Ok(signed.into_iter().chain(encoded.into_iter()).collect())
	}

	/// Parses the ABI function input to a list of tokens.
	pub fn decode(&self, data: &[u8]) -> Result<Vec<Token>> {
		decode(&self.param_types(), data)
	}
}

-- file: ethabi/src/param_type/param_type.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Function and event param types.

use core::fmt;

use super::Writer;
#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;

/// Function and event param types.
#[derive(Debug, Clone, PartialEq)]
pub enum ParamType {
	/// Address.
	Address,
	/// Bytes.
	Bytes,
	/// Signed integer.
	Int(usize),
	/// Unsigned integer.
	Uint(usize),
	/// Boolean.
	Bool,
	/// String.
	String,
	/// Array of unknown size.
	Array(Box<ParamType>),
	/// Vector of bytes with fixed size.
	FixedBytes(usize),
	/// Array with fixed size.
	FixedArray(Box<ParamType>, usize),
	/// Tuple containing different types
	Tuple(Vec<ParamType>),
}

impl fmt::Display for ParamType {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", Writer::write(self))
	}
}

impl ParamType {
	/// returns whether a zero length byte slice (`0x`) is
	/// a valid encoded form of this param type
	pub fn is_empty_bytes_valid_encoding(&self) -> bool {
		match self {
			ParamType::FixedBytes(len) => *len == 0,
			ParamType::FixedArray(_, len) => *len == 0,
			_ => false,
		}
	}

	/// returns whether a ParamType is dynamic
	/// used to decide how the ParamType should be encoded
	pub fn is_dynamic(&self) -> bool {
		match self {
			ParamType::Bytes | ParamType::String | ParamType::Array(_) => true,
			ParamType::FixedArray(elem_type, _) => elem_type.is_dynamic(),
			ParamType::Tuple(params) => params.iter().any(|param| param.is_dynamic()),
			_ => false,
		}
	}
}

#[cfg(test)]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::ParamType;

	#[test]
	fn test_param_type_display() {
		assert_eq!(format!("{}", ParamType::Address), "address".to_owned());
		assert_eq!(format!("{}", ParamType::Bytes), "bytes".to_owned());
		assert_eq!(format!("{}", ParamType::FixedBytes(32)), "bytes32".to_owned());
		assert_eq!(format!("{}", ParamType::Uint(256)), "uint256".to_owned());
		assert_eq!(format!("{}", ParamType::Int(64)), "int64".to_owned());
		assert_eq!(format!("{}", ParamType::Bool), "bool".to_owned());
		assert_eq!(format!("{}", ParamType::String), "string".to_owned());
		assert_eq!(format!("{}", ParamType::Array(Box::new(ParamType::Bool))), "bool[]".to_owned());
		assert_eq!(format!("{}", ParamType::FixedArray(Box::new(ParamType::Uint(256)), 2)), "uint256[2]".to_owned());
		assert_eq!(format!("{}", ParamType::FixedArray(Box::new(ParamType::String), 2)), "string[2]".to_owned());
		assert_eq!(
			format!("{}", ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 2)),
			"bool[][2]".to_owned()
		);
	}

	#[test]
	fn test_is_dynamic() {
		assert!(!ParamType::Address.is_dynamic());
		assert!(ParamType::Bytes.is_dynamic());
		assert!(!ParamType::FixedBytes(32).is_dynamic());
		assert!(!ParamType::Uint(256).is_dynamic());
		assert!(!ParamType::Int(64).is_dynamic());
		assert!(!ParamType::Bool.is_dynamic());
		assert!(ParamType::String.is_dynamic());
		assert!(ParamType::Array(Box::new(ParamType::Bool)).is_dynamic());
		assert!(!ParamType::FixedArray(Box::new(ParamType::Uint(256)), 2).is_dynamic());
		assert!(ParamType::FixedArray(Box::new(ParamType::String), 2).is_dynamic());
		assert!(ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 2).is_dynamic());
	}
}

-- file: ethabi/src/param_type/mod.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Function and event param types.

#[cfg(feature = "serde")]
mod deserialize;

mod param_type;
pub use param_type::ParamType;

#[cfg(feature = "serde")]
mod reader;
#[cfg(feature = "serde")]
pub use reader::Reader;

mod writer;
pub use writer::Writer;

-- file: ethabi/src/param_type/deserialize.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::{ParamType, Reader};
#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use core::fmt;
use serde::{
	de::{Error as SerdeError, Visitor},
	Deserialize, Deserializer,
};

impl<'a> Deserialize<'a> for ParamType {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: Deserializer<'a>,
	{
		deserializer.deserialize_identifier(ParamTypeVisitor)
	}
}

struct ParamTypeVisitor;

impl<'a> Visitor<'a> for ParamTypeVisitor {
	type Value = ParamType;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		write!(formatter, "a correct name of abi-encodable parameter type")
	}

	fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
	where
		E: SerdeError,
	{
		Reader::read(value).map_err(|e| SerdeError::custom(format!("{e:?}").as_str()))
	}

	fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
	where
		E: SerdeError,
	{
		self.visit_str(value.as_str())
	}
}

#[cfg(test)]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::ParamType;

	#[test]
	fn param_type_deserialization() {
		let s = r#"["address", "bytes", "bytes32", "bool", "string", "int", "uint", "address[]", "uint[3]", "bool[][5]", "tuple[]"]"#;
		let deserialized: Vec<ParamType> = serde_json::from_str(s).unwrap();
		assert_eq!(
			deserialized,
			vec![
				ParamType::Address,
				ParamType::Bytes,
				ParamType::FixedBytes(32),
				ParamType::Bool,
				ParamType::String,
				ParamType::Int(256),
				ParamType::Uint(256),
				ParamType::Array(Box::new(ParamType::Address)),
				ParamType::FixedArray(Box::new(ParamType::Uint(256)), 3),
				ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 5),
				ParamType::Array(Box::new(ParamType::Tuple(vec![]))),
			]
		);
	}
}

-- file: ethabi/src/param_type/writer.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::ParamType;

/// Output formatter for param type.
pub struct Writer;

impl Writer {
	/// Returns string which is a formatted represenation of param.
	pub fn write(param: &ParamType) -> String {
		Writer::write_for_abi(param, true)
	}

	/// If `serialize_tuple_contents` is `true`, tuples will be represented
	/// as list of inner types in parens, for example `(int256,bool)`.
	/// If it is `false`, tuples will be represented as keyword `tuple`.
	pub fn write_for_abi(param: &ParamType, serialize_tuple_contents: bool) -> String {
		match *param {
			ParamType::Address => "address".to_owned(),
			ParamType::Bytes => "bytes".to_owned(),
			ParamType::FixedBytes(len) => format!("bytes{len}"),
			ParamType::Int(len) => format!("int{len}"),
			ParamType::Uint(len) => format!("uint{len}"),
			ParamType::Bool => "bool".to_owned(),
			ParamType::String => "string".to_owned(),
			ParamType::FixedArray(ref param, len) => {
				format!("{}[{len}]", Writer::write_for_abi(param, serialize_tuple_contents))
			}
			ParamType::Array(ref param) => {
				format!("{}[]", Writer::write_for_abi(param, serialize_tuple_contents))
			}
			ParamType::Tuple(ref params) => {
				if serialize_tuple_contents {
					let formatted = params
						.iter()
						.map(|t| Writer::write_for_abi(t, serialize_tuple_contents))
						.collect::<Vec<String>>()
						.join(",");
					format!("({formatted})")
				} else {
					"tuple".to_owned()
				}
			}
		}
	}
}

#[cfg(test)]
mod tests {
	use super::Writer;
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::ParamType;

	#[test]
	fn test_write_param() {
		assert_eq!(Writer::write(&ParamType::Address), "address".to_owned());
		assert_eq!(Writer::write(&ParamType::Bytes), "bytes".to_owned());
		assert_eq!(Writer::write(&ParamType::FixedBytes(32)), "bytes32".to_owned());
		assert_eq!(Writer::write(&ParamType::Uint(256)), "uint256".to_owned());
		assert_eq!(Writer::write(&ParamType::Int(64)), "int64".to_owned());
		assert_eq!(Writer::write(&ParamType::Bool), "bool".to_owned());
		assert_eq!(Writer::write(&ParamType::String), "string".to_owned());
		assert_eq!(Writer::write(&ParamType::Array(Box::new(ParamType::Bool))), "bool[]".to_owned());
		assert_eq!(Writer::write(&ParamType::FixedArray(Box::new(ParamType::String), 2)), "string[2]".to_owned());
		assert_eq!(
			Writer::write(&ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 2)),
			"bool[][2]".to_owned()
		);
		assert_eq!(
			Writer::write(&ParamType::Array(Box::new(ParamType::Tuple(vec![
				ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Int(256), ParamType::Uint(256)]))),
				ParamType::FixedBytes(32),
			])))),
			"((int256,uint256)[],bytes32)[]".to_owned()
		);

		assert_eq!(
			Writer::write_for_abi(
				&ParamType::Array(Box::new(ParamType::Tuple(vec![
					ParamType::Array(Box::new(ParamType::Int(256))),
					ParamType::FixedBytes(32),
				]))),
				false
			),
			"tuple[]".to_owned()
		);
	}
}

-- file: ethabi/src/param_type/reader.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{Error, ParamType};

/// Used to convert param type represented as a string to rust structure.
pub struct Reader;

impl Reader {
	/// Converts string to param type.
	pub fn read(name: &str) -> Result<ParamType, Error> {
		match name.chars().last() {
			// check if it is a struct
			Some(')') => {
				if !name.starts_with('(') {
					return Err(Error::InvalidName(name.to_owned()));
				};

				let mut subtypes = Vec::new();
				let mut subtuples = Vec::new();
				let mut nested = 0isize;
				let mut top_level_paren_open = 0usize;
				let mut last_item = 1;
				let mut chars = name.chars().enumerate();

				// Iterate over name and build the nested tuple structure
				while let Some((mut pos, c)) = chars.next() {
					match c {
						'(' => {
							top_level_paren_open = pos;
							nested += 1;
							// If an '(' is encountered within the tuple
							// insert an empty subtuples vector to be filled
							if nested > 1 {
								subtuples.push(vec![]);
								last_item = pos + 1;
							}
						}
						')' => {
							nested -= 1;

							// End parsing and return an error if parentheses aren't symmetrical
							if nested < 0 {
								return Err(Error::InvalidName(name.to_owned()));
							}
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							else if name[last_item..pos].is_empty() {
								last_item = pos + 1;
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 0 {
								// check for trailing brackets that indicate array of tuples
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							else if nested > 0 {
								// this makes sure trailing brackets are included for the next step
								loop {
									match chars.clone().next() {
										Some((_, ',')) | Some((_, ')')) | None => break,
										_ => {
											// consume the char and shift position
											chars.next();
											pos += 1;
										}
									}
								}

								// parse the nested tuple
								let inner_tuple = &name[top_level_paren_open..=pos];
								let subtype = Reader::read(inner_tuple)?;

								if nested > 1 {
									let mut subtuple = core::mem::take(&mut subtuples[(nested - 2) as usize]);
									subtuple.push(subtype);
									subtypes.push(ParamType::Tuple(subtuple));
								} else {
									subtypes.push(subtype);
								}
								last_item = pos + 1;
							}
						}
						',' => {
							// If there have not been any characters since the last item
							// increment position without inserting any subtypes
							if name[last_item..pos].is_empty() {
								last_item = pos + 1
							}
							// If the item is in the top level of the tuple insert it into subtypes
							else if nested == 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtypes.push(subtype);
								last_item = pos + 1;
							}
							// If the item is in a sublevel of the tuple
							// insert it into the subtuple vector for the current depth level
							else if nested > 1 {
								let sub = &name[last_item..pos];
								let subtype = Reader::read(sub)?;
								subtuples[(nested - 2) as usize].push(subtype);
								last_item = pos + 1;
							}
						}
						_ => (),
					}
				}
				return Ok(ParamType::Tuple(subtypes));
			}
			// check if it is a fixed or dynamic array.
			Some(']') => {
				// take number part
				let num: String =
					name.chars().rev().skip(1).take_while(|c| *c != '[').collect::<String>().chars().rev().collect();

				let count = name.chars().count();
				return if num.is_empty() {
					// we already know it's a dynamic array!
					let subtype = Reader::read(&name[..count - 2])?;
					Ok(ParamType::Array(Box::new(subtype)))
				} else {
					// it's a fixed array.
					let len = num.parse().map_err(Error::ParseInt)?;
					let subtype = Reader::read(&name[..count - num.len() - 2])?;
					Ok(ParamType::FixedArray(Box::new(subtype), len))
				};
			}
			_ => (),
		}

		let result = match name {
			"address" => ParamType::Address,
			"bytes" => ParamType::Bytes,
			"bool" => ParamType::Bool,
			"string" => ParamType::String,
			"int" => ParamType::Int(256),
			"tuple" => ParamType::Tuple(vec![]),
			"uint" => ParamType::Uint(256),
			s if s.starts_with("int") => {
				let len = s[3..].parse().map_err(Error::ParseInt)?;
				ParamType::Int(len)
			}
			s if s.starts_with("uint") => {
				let len = s[4..].parse().map_err(Error::ParseInt)?;
				ParamType::Uint(len)
			}
			s if s.starts_with("bytes") => {
				let len = s[5..].parse().map_err(Error::ParseInt)?;
				ParamType::FixedBytes(len)
			}
			// As discussed in https://github.com/rust-ethereum/ethabi/issues/254,
			// any type that does not fit the above corresponds to a Solidity
			// `enum`, and as a result we treat it as a `uint8`. This is a unique
			// case which occurs in libraries with exported (`public`) Solidity
			// functions with `enum` parameters.
			_ => ParamType::Uint(8),
		};

		Ok(result)
	}
}

#[cfg(test)]
mod tests {
	use super::Reader;
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::ParamType;

	#[test]
	fn test_read_param() {
		assert_eq!(Reader::read("address").unwrap(), ParamType::Address);
		assert_eq!(Reader::read("bytes").unwrap(), ParamType::Bytes);
		assert_eq!(Reader::read("bytes32").unwrap(), ParamType::FixedBytes(32));
		assert_eq!(Reader::read("bool").unwrap(), ParamType::Bool);
		assert_eq!(Reader::read("string").unwrap(), ParamType::String);
		assert_eq!(Reader::read("int").unwrap(), ParamType::Int(256));
		assert_eq!(Reader::read("uint").unwrap(), ParamType::Uint(256));
		assert_eq!(Reader::read("int32").unwrap(), ParamType::Int(32));
		assert_eq!(Reader::read("uint32").unwrap(), ParamType::Uint(32));
	}

	#[test]
	fn test_read_array_param() {
		assert_eq!(Reader::read("address[]").unwrap(), ParamType::Array(Box::new(ParamType::Address)));
		assert_eq!(Reader::read("uint[]").unwrap(), ParamType::Array(Box::new(ParamType::Uint(256))));
		assert_eq!(Reader::read("bytes[]").unwrap(), ParamType::Array(Box::new(ParamType::Bytes)));
		assert_eq!(
			Reader::read("bool[][]").unwrap(),
			ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool))))
		);
	}

	#[test]
	fn test_read_fixed_array_param() {
		assert_eq!(Reader::read("address[2]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Address), 2));
		assert_eq!(Reader::read("bool[17]").unwrap(), ParamType::FixedArray(Box::new(ParamType::Bool), 17));
		assert_eq!(
			Reader::read("bytes[45][3]").unwrap(),
			ParamType::FixedArray(Box::new(ParamType::FixedArray(Box::new(ParamType::Bytes), 45)), 3)
		);
	}

	#[test]
	fn test_read_mixed_arrays() {
		assert_eq!(
			Reader::read("bool[][3]").unwrap(),
			ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Bool))), 3)
		);
		assert_eq!(
			Reader::read("bool[3][]").unwrap(),
			ParamType::Array(Box::new(ParamType::FixedArray(Box::new(ParamType::Bool), 3)))
		);
	}

	#[test]
	fn test_read_struct_param() {
		assert_eq!(
			Reader::read("(address,bool)").unwrap(),
			ParamType::Tuple(vec![ParamType::Address, ParamType::Bool])
		);
		assert_eq!(
			Reader::read("(bool[3],uint256)").unwrap(),
			ParamType::Tuple(vec![ParamType::FixedArray(Box::new(ParamType::Bool), 3), ParamType::Uint(256)])
		);
	}

	#[test]
	fn test_read_nested_struct_param() {
		assert_eq!(
			Reader::read("(address,bool,(bool,uint256))").unwrap(),
			ParamType::Tuple(vec![
				ParamType::Address,
				ParamType::Bool,
				ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
			])
		);
	}

	#[test]
	fn test_read_complex_nested_struct_param() {
		assert_eq!(
			Reader::read("(address,bool,(bool,uint256,(bool,uint256)),(bool,uint256))").unwrap(),
			ParamType::Tuple(vec![
				ParamType::Address,
				ParamType::Bool,
				ParamType::Tuple(vec![
					ParamType::Bool,
					ParamType::Uint(256),
					ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
				]),
				ParamType::Tuple(vec![ParamType::Bool, ParamType::Uint(256)])
			])
		);
	}

	#[test]
	fn test_read_nested_tuple_array_param() {
		assert_eq!(
			Reader::read("(uint256,bytes32)[]").unwrap(),
			ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)])))
		)
	}

	#[test]
	fn test_read_inner_tuple_array_param() {
		use crate::param_type::Writer;
		let abi = "((uint256,bytes32)[],address)";
		let read = Reader::read(abi).unwrap();

		let param = ParamType::Tuple(vec![
			ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Uint(256), ParamType::FixedBytes(32)]))),
			ParamType::Address,
		]);

		assert_eq!(read, param);

		assert_eq!(abi, Writer::write(&param));
	}
}

-- file: ethabi/src/constructor.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Contract constructor call builder.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{encode, Bytes, Error, Param, ParamType, Result, Token};

/// Contract constructor specification.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Constructor {
	/// Constructor input.
	pub inputs: Vec<Param>,
}

impl Constructor {
	/// Returns all input params of given constructor.
	fn param_types(&self) -> Vec<ParamType> {
		self.inputs.iter().map(|p| p.kind.clone()).collect()
	}

	/// Prepares ABI constructor call with given input params.
	pub fn encode_input(&self, code: Bytes, tokens: &[Token]) -> Result<Bytes> {
		let params = self.param_types();

		if Token::types_check(tokens, &params) {
			Ok(code.into_iter().chain(encode(tokens)).collect())
		} else {
			Err(Error::InvalidData)
		}
	}
}

-- file: ethabi/src/log.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{Bytes, Hash, Result, Token, TopicFilter};

/// Common filtering functions that are available for any event.
pub trait LogFilter {
	/// Match any log parameters.
	fn wildcard_filter(&self) -> TopicFilter;
}

/// trait common to things (events) that have an associated `Log` type
/// that can be parsed from a `RawLog`
pub trait ParseLog {
	/// the associated `Log` type that can be parsed from a `RawLog`
	/// by calling `parse_log`
	type Log;

	/// parse the associated `Log` type from a `RawLog`
	fn parse_log(&self, log: RawLog) -> Result<Self::Log>;
}

/// Ethereum log.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RawLog {
	/// Indexed event params are represented as log topics.
	pub topics: Vec<Hash>,
	/// Others are just plain data.
	pub data: Bytes,
}

impl From<(Vec<Hash>, Bytes)> for RawLog {
	fn from(raw: (Vec<Hash>, Bytes)) -> Self {
		RawLog { topics: raw.0, data: raw.1 }
	}
}

/// Decoded log param.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Clone)]
pub struct LogParam {
	/// Decoded log name.
	pub name: String,
	/// Decoded log value.
	pub value: Token,
}

/// Decoded log.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Clone)]
pub struct Log {
	/// Log params.
	pub params: Vec<LogParam>,
}

-- file: ethabi/src/lib.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Ethereum ABI encoding decoding library.

#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::module_inception)]
#![warn(missing_docs)]

#[cfg_attr(not(feature = "std"), macro_use)]
extern crate alloc;
#[cfg(not(feature = "std"))]
mod no_std_prelude {
	pub use alloc::{
		borrow::{Cow, ToOwned},
		boxed::Box,
		string::{self, String, ToString},
		vec::Vec,
	};
}
#[cfg(feature = "std")]
mod no_std_prelude {
	pub use std::borrow::Cow;
}
#[cfg(not(feature = "std"))]
use no_std_prelude::*;

mod constructor;
mod contract;
mod decoder;
mod encoder;
mod error;
mod errors;
mod event;
mod event_param;
mod filter;
mod function;
mod log;
#[cfg(feature = "serde")]
mod operation;
mod param;
pub mod param_type;
mod signature;
mod state_mutability;
pub mod token;
#[cfg(feature = "serde")]
mod tuple_param;
mod util;

#[cfg(test)]
mod tests;

pub use ethereum_types;

#[cfg(feature = "serde")]
pub use crate::tuple_param::TupleParam;
pub use crate::{
	constructor::Constructor,
	contract::{Contract, Events, Functions},
	decoder::{decode, decode_whole},
	encoder::encode,
	error::Error as AbiError,
	errors::{Error, Result},
	event::Event,
	event_param::EventParam,
	filter::{RawTopicFilter, Topic, TopicFilter},
	function::Function,
	log::{Log, LogFilter, LogParam, ParseLog, RawLog},
	param::Param,
	param_type::ParamType,
	signature::{long_signature, short_signature},
	state_mutability::StateMutability,
	token::Token,
};

/// ABI word.
pub type Word = [u8; 32];

/// ABI address.
pub type Address = ethereum_types::Address;

/// ABI fixed bytes.
pub type FixedBytes = Vec<u8>;

/// ABI bytes.
pub type Bytes = Vec<u8>;

/// ABI signed integer.
pub type Int = ethereum_types::U256;

/// ABI unsigned integer.
pub type Uint = ethereum_types::U256;

/// Commonly used FixedBytes of size 32
pub type Hash = ethereum_types::H256;

/// Contract functions generated by ethabi-derive
pub trait FunctionOutputDecoder {
	/// Output types of the contract function
	type Output;

	/// Decodes the given bytes output for the contract function
	fn decode(&self, _: &[u8]) -> Result<Self::Output>;
}

-- file: ethabi/src/decoder.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! ABI decoder.

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{Error, ParamType, Token, Word};

#[derive(Debug)]
struct DecodeResult {
	token: Token,
	new_offset: usize,
}

fn as_usize(slice: &Word) -> Result<usize, Error> {
	if !slice[..28].iter().all(|x| *x == 0) {
		return Err(Error::InvalidData);
	}

	let result = ((slice[28] as usize) << 24)
		+ ((slice[29] as usize) << 16)
		+ ((slice[30] as usize) << 8)
		+ (slice[31] as usize);

	Ok(result)
}

fn as_bool(slice: &Word) -> Result<bool, Error> {
	if !slice[..31].iter().all(|x| *x == 0) {
		return Err(Error::InvalidData);
	}

	Ok(slice[31] == 1)
}

fn decode_offset(types: &[ParamType], data: &[u8]) -> Result<(Vec<Token>, usize), Error> {
	let is_empty_bytes_valid_encoding = types.iter().all(|t| t.is_empty_bytes_valid_encoding());
	if !is_empty_bytes_valid_encoding && data.is_empty() {
		return Err(Error::InvalidName(
			"please ensure the contract and method you're calling exist! \
			 failed to decode empty bytes. if you're using jsonrpc this is \
			 likely due to jsonrpc returning `0x` in case contract or method \
			 don't exist"
				.into(),
		));
	}

	let mut tokens = vec![];
	let mut offset = 0;

	for param in types {
		let res = decode_param(param, data, offset)?;
		offset = res.new_offset;
		tokens.push(res.token);
	}

	Ok((tokens, offset))
}

/// Decodes ABI compliant vector of bytes into vector of tokens described by types param.
/// Fails, if some data left to decode
pub fn decode_whole(types: &[ParamType], data: &[u8]) -> Result<Vec<Token>, Error> {
	decode_offset(types, data).and_then(
		|(tokens, offset)| {
			if offset != data.len() {
				Err(Error::InvalidData)
			} else {
				Ok(tokens)
			}
		},
	)
}

/// Decodes ABI compliant vector of bytes into vector of tokens described by types param.
/// Returns ok, even if some data left to decode
pub fn decode(types: &[ParamType], data: &[u8]) -> Result<Vec<Token>, Error> {
	decode_offset(types, data).map(|(tokens, _)| tokens)
}

fn peek(data: &[u8], offset: usize, len: usize) -> Result<&[u8], Error> {
	if offset + len > data.len() {
		Err(Error::InvalidData)
	} else {
		Ok(&data[offset..(offset + len)])
	}
}

fn peek_32_bytes(data: &[u8], offset: usize) -> Result<Word, Error> {
	peek(data, offset, 32).map(|x| {
		let mut out: Word = [0u8; 32];
		out.copy_from_slice(&x[0..32]);
		out
	})
}

fn take_bytes(data: &[u8], offset: usize, len: usize) -> Result<Vec<u8>, Error> {
	if offset + len > data.len() {
		Err(Error::InvalidData)
	} else {
		Ok(data[offset..(offset + len)].to_vec())
	}
}

fn decode_param(param: &ParamType, data: &[u8], offset: usize) -> Result<DecodeResult, Error> {
	match *param {
		ParamType::Address => {
			let slice = peek_32_bytes(data, offset)?;
			let mut address = [0u8; 20];
			address.copy_from_slice(&slice[12..]);
			let result = DecodeResult { token: Token::Address(address.into()), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::Int(_) => {
			let slice = peek_32_bytes(data, offset)?;
			let result = DecodeResult { token: Token::Int(slice.into()), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::Uint(_) => {
			let slice = peek_32_bytes(data, offset)?;
			let result = DecodeResult { token: Token::Uint(slice.into()), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::Bool => {
			let b = as_bool(&peek_32_bytes(data, offset)?)?;
			let result = DecodeResult { token: Token::Bool(b), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::FixedBytes(len) => {
			// FixedBytes is anything from bytes1 to bytes32. These values
			// are padded with trailing zeros to fill 32 bytes.
			let bytes = take_bytes(data, offset, len)?;
			let result = DecodeResult { token: Token::FixedBytes(bytes), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::Bytes => {
			let dynamic_offset = as_usize(&peek_32_bytes(data, offset)?)?;
			let len = as_usize(&peek_32_bytes(data, dynamic_offset)?)?;
			let bytes = take_bytes(data, dynamic_offset + 32, len)?;
			let result = DecodeResult { token: Token::Bytes(bytes), new_offset: offset + 32 };
			Ok(result)
		}
		ParamType::String => {
			let dynamic_offset = as_usize(&peek_32_bytes(data, offset)?)?;
			let len = as_usize(&peek_32_bytes(data, dynamic_offset)?)?;
			let bytes = take_bytes(data, dynamic_offset + 32, len)?;
			let result = DecodeResult {
				// NOTE: We're decoding strings using lossy UTF-8 decoding to
				// prevent invalid strings written into contracts by either users or
				// Solidity bugs from causing graph-node to fail decoding event
				// data.
				token: Token::String(String::from_utf8_lossy(&bytes).into()),
				new_offset: offset + 32,
			};
			Ok(result)
		}
		ParamType::Array(ref t) => {
			let len_offset = as_usize(&peek_32_bytes(data, offset)?)?;
			let len = as_usize(&peek_32_bytes(data, len_offset)?)?;

			let tail_offset = len_offset + 32;
			let tail = &data[tail_offset..];

			let mut tokens = vec![];
			let mut new_offset = 0;

			for _ in 0..len {
				let res = decode_param(t, tail, new_offset)?;
				new_offset = res.new_offset;
				tokens.push(res.token);
			}

			let result = DecodeResult { token: Token::Array(tokens), new_offset: offset + 32 };

			Ok(result)
		}
		ParamType::FixedArray(ref t, len) => {
			let is_dynamic = param.is_dynamic();

			let (tail, mut new_offset) = if is_dynamic {
				let offset = as_usize(&peek_32_bytes(data, offset)?)?;
				if offset > data.len() {
					return Err(Error::InvalidData);
				}
				(&data[offset..], 0)
			} else {
				(data, offset)
			};

			let mut tokens = vec![];

			for _ in 0..len {
				let res = decode_param(t, tail, new_offset)?;
				new_offset = res.new_offset;
				tokens.push(res.token);
			}

			let result = DecodeResult {
				token: Token::FixedArray(tokens),
				new_offset: if is_dynamic { offset + 32 } else { new_offset },
			};

			Ok(result)
		}
		ParamType::Tuple(ref t) => {
			let is_dynamic = param.is_dynamic();

			// The first element in a dynamic Tuple is an offset to the Tuple's data
			// For a static Tuple the data begins right away
			let (tail, mut new_offset) = if is_dynamic {
				let offset = as_usize(&peek_32_bytes(data, offset)?)?;
				if offset > data.len() {
					return Err(Error::InvalidData);
				}
				(&data[offset..], 0)
			} else {
				(data, offset)
			};

			let len = t.len();
			let mut tokens = Vec::with_capacity(len);
			for param in t {
				let res = decode_param(param, tail, new_offset)?;
				new_offset = res.new_offset;
				tokens.push(res.token);
			}

			// The returned new_offset depends on whether the Tuple is dynamic
			// dynamic Tuple -> follows the prefixed Tuple data offset element
			// static Tuple  -> follows the last data element
			let result = DecodeResult {
				token: Token::Tuple(tokens),
				new_offset: if is_dynamic { offset + 32 } else { new_offset },
			};

			Ok(result)
		}
	}
}

#[cfg(test)]
mod tests {
	use hex_literal::hex;

	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{decode, decode_whole, ParamType, Token, Uint};

	#[test]
	fn decode_from_empty_byte_slice() {
		// these can NOT be decoded from empty byte slice
		assert!(decode(&[ParamType::Address], &[]).is_err());
		assert!(decode(&[ParamType::Bytes], &[]).is_err());
		assert!(decode(&[ParamType::Int(0)], &[]).is_err());
		assert!(decode(&[ParamType::Int(1)], &[]).is_err());
		assert!(decode(&[ParamType::Int(0)], &[]).is_err());
		assert!(decode(&[ParamType::Int(1)], &[]).is_err());
		assert!(decode(&[ParamType::Bool], &[]).is_err());
		assert!(decode(&[ParamType::String], &[]).is_err());
		assert!(decode(&[ParamType::Array(Box::new(ParamType::Bool))], &[]).is_err());
		assert!(decode(&[ParamType::FixedBytes(1)], &[]).is_err());
		assert!(decode(&[ParamType::FixedArray(Box::new(ParamType::Bool), 1)], &[]).is_err());

		// these are the only ones that can be decoded from empty byte slice
		assert!(decode(&[ParamType::FixedBytes(0)], &[]).is_ok());
		assert!(decode(&[ParamType::FixedArray(Box::new(ParamType::Bool), 0)], &[]).is_ok());
	}

	#[test]
	fn decode_static_tuple_of_addresses_and_uints() {
		let encoded = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			1111111111111111111111111111111111111111111111111111111111111111
		"
		);
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let uint = Token::Uint([0x11u8; 32].into());
		let tuple = Token::Tuple(vec![address1, address2, uint]);
		let expected = vec![tuple];
		let decoded =
			decode(&[ParamType::Tuple(vec![ParamType::Address, ParamType::Address, ParamType::Uint(32)])], &encoded)
				.unwrap();
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_dynamic_tuple() {
		let encoded = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		);
		let string1 = Token::String("gavofyork".to_owned());
		let string2 = Token::String("gavofyork".to_owned());
		let tuple = Token::Tuple(vec![string1, string2]);
		let decoded = decode(&[ParamType::Tuple(vec![ParamType::String, ParamType::String])], &encoded).unwrap();
		let expected = vec![tuple];
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_nested_tuple() {
		let encoded = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000001
			00000000000000000000000000000000000000000000000000000000000000c0
			0000000000000000000000000000000000000000000000000000000000000100
			0000000000000000000000000000000000000000000000000000000000000004
			7465737400000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000006
			6379626f72670000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000060
			00000000000000000000000000000000000000000000000000000000000000a0
			00000000000000000000000000000000000000000000000000000000000000e0
			0000000000000000000000000000000000000000000000000000000000000005
			6e69676874000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000003
			6461790000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000040
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000000000000000000000000000000000000000000004
			7765656500000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000008
			66756e7465737473000000000000000000000000000000000000000000000000
		"
		);
		let string1 = Token::String("test".to_owned());
		let string2 = Token::String("cyborg".to_owned());
		let string3 = Token::String("night".to_owned());
		let string4 = Token::String("day".to_owned());
		let string5 = Token::String("weee".to_owned());
		let string6 = Token::String("funtests".to_owned());
		let bool = Token::Bool(true);
		let deep_tuple = Token::Tuple(vec![string5, string6]);
		let inner_tuple = Token::Tuple(vec![string3, string4, deep_tuple]);
		let outer_tuple = Token::Tuple(vec![string1, bool, string2, inner_tuple]);
		let expected = vec![outer_tuple];
		let decoded = decode(
			&[ParamType::Tuple(vec![
				ParamType::String,
				ParamType::Bool,
				ParamType::String,
				ParamType::Tuple(vec![
					ParamType::String,
					ParamType::String,
					ParamType::Tuple(vec![ParamType::String, ParamType::String]),
				]),
			])],
			&encoded,
		)
		.unwrap();
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_complex_tuple_of_dynamic_and_static_types() {
		let encoded = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			1111111111111111111111111111111111111111111111111111111111111111
			0000000000000000000000000000000000000000000000000000000000000080
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000009
			6761766f66796f726b0000000000000000000000000000000000000000000000
		"
		);
		let uint = Token::Uint([0x11u8; 32].into());
		let string = Token::String("gavofyork".to_owned());
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let tuple = Token::Tuple(vec![uint, string, address1, address2]);
		let expected = vec![tuple];
		let decoded = decode(
			&[ParamType::Tuple(vec![ParamType::Uint(32), ParamType::String, ParamType::Address, ParamType::Address])],
			&encoded,
		)
		.unwrap();
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_params_containing_dynamic_tuple() {
		let encoded = hex!(
			"
			0000000000000000000000002222222222222222222222222222222222222222
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000060
			00000000000000000000000000000000000000000000000000000000000000a0
			0000000000000000000000000000000000000000000000000000000000000009
			7370616365736869700000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000006
			6379626f72670000000000000000000000000000000000000000000000000000
		"
		);
		let address1 = Token::Address([0x22u8; 20].into());
		let bool1 = Token::Bool(true);
		let string1 = Token::String("spaceship".to_owned());
		let string2 = Token::String("cyborg".to_owned());
		let tuple = Token::Tuple(vec![bool1, string1, string2]);
		let address2 = Token::Address([0x33u8; 20].into());
		let address3 = Token::Address([0x44u8; 20].into());
		let bool2 = Token::Bool(false);
		let expected = vec![address1, tuple, address2, address3, bool2];
		let decoded = decode(
			&[
				ParamType::Address,
				ParamType::Tuple(vec![ParamType::Bool, ParamType::String, ParamType::String]),
				ParamType::Address,
				ParamType::Address,
				ParamType::Bool,
			],
			&encoded,
		)
		.unwrap();
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_params_containing_static_tuple() {
		let encoded = hex!(
			"
			0000000000000000000000001111111111111111111111111111111111111111
			0000000000000000000000002222222222222222222222222222222222222222
			0000000000000000000000000000000000000000000000000000000000000001
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000003333333333333333333333333333333333333333
			0000000000000000000000004444444444444444444444444444444444444444
		"
		);
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let bool1 = Token::Bool(true);
		let bool2 = Token::Bool(false);
		let tuple = Token::Tuple(vec![address2, bool1, bool2]);
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());

		let expected = vec![address1, tuple, address3, address4];
		let decoded = decode(
			&[
				ParamType::Address,
				ParamType::Tuple(vec![ParamType::Address, ParamType::Bool, ParamType::Bool]),
				ParamType::Address,
				ParamType::Address,
			],
			&encoded,
		)
		.unwrap();
		assert_eq!(decoded, expected);
	}

	#[test]
	fn decode_data_with_size_that_is_not_a_multiple_of_32() {
		let encoded = hex!(
			"
            0000000000000000000000000000000000000000000000000000000000000000
            00000000000000000000000000000000000000000000000000000000000000a0
            0000000000000000000000000000000000000000000000000000000000000152
            0000000000000000000000000000000000000000000000000000000000000001
            000000000000000000000000000000000000000000000000000000000054840d
            0000000000000000000000000000000000000000000000000000000000000092
            3132323033393637623533326130633134633938306235616566666231373034
            3862646661656632633239336139353039663038656233633662306635663866
            3039343265376239636337366361353163636132366365353436393230343438
            6533303866646136383730623565326165313261323430396439343264653432
            3831313350373230703330667073313678390000000000000000000000000000
            0000000000000000000000000000000000103933633731376537633061363531
            3761
        "
		);

		assert_eq!(
			decode(
				&[
					ParamType::Uint(256),
					ParamType::String,
					ParamType::String,
					ParamType::Uint(256),
					ParamType::Uint(256),
				],
				&encoded,
			).unwrap(),
			&[
				Token::Uint(Uint::from(0)),
				Token::String(String::from("12203967b532a0c14c980b5aeffb17048bdfaef2c293a9509f08eb3c6b0f5f8f0942e7b9cc76ca51cca26ce546920448e308fda6870b5e2ae12a2409d942de428113P720p30fps16x9")),
				Token::String(String::from("93c717e7c0a6517a")),
				Token::Uint(Uint::from(1)),
				Token::Uint(Uint::from(5538829))
			]
		);
	}

	#[test]
	fn decode_after_fixed_bytes_with_less_than_32_bytes() {
		let encoded = hex!(
			"
			0000000000000000000000008497afefdc5ac170a664a231f6efb25526ef813f
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000000
			0000000000000000000000000000000000000000000000000000000000000080
			000000000000000000000000000000000000000000000000000000000000000a
			3078303030303030314600000000000000000000000000000000000000000000
		"
		);

		assert_eq!(
			decode(
				&[ParamType::Address, ParamType::FixedBytes(32), ParamType::FixedBytes(4), ParamType::String,],
				&encoded,
			)
			.unwrap(),
			&[
				Token::Address(hex!("8497afefdc5ac170a664a231f6efb25526ef813f").into()),
				Token::FixedBytes([0u8; 32].to_vec()),
				Token::FixedBytes([0u8; 4].to_vec()),
				Token::String("0x0000001F".into()),
			]
		)
	}

	#[test]
	fn decode_broken_utf8() {
		let encoded = hex!(
			"
			0000000000000000000000000000000000000000000000000000000000000020
			0000000000000000000000000000000000000000000000000000000000000004
			e4b88de500000000000000000000000000000000000000000000000000000000
        "
		);

		assert_eq!(decode(&[ParamType::String,], &encoded).unwrap(), &[Token::String("不�".into())]);
	}

	#[test]
	fn decode_corrupted_dynamic_array() {
		// line 1 at 0x00 =   0: tail offset of array
		// line 2 at 0x20 =  32: length of array
		// line 3 at 0x40 =  64: first word
		// line 4 at 0x60 =  96: second word
		let encoded = hex!(
			"
		0000000000000000000000000000000000000000000000000000000000000020
		00000000000000000000000000000000000000000000000000000000ffffffff
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000000000000000000000000000000000000000000002
        "
		);

		assert!(decode(&[ParamType::Array(Box::new(ParamType::Uint(32)))], &encoded).is_err());
	}

	#[test]
	fn decode_corrupted_nested_array_tuple() {
		let input = hex!(
			"
0000000000000000000000000000000000000000000000000000000000000040

00000000000000000000000000000000000000000000000000000000000002a0
0000000000000000000000000000000000000000000000000000000000000009

00000000000000000000000000000000fffffffffffffffffffffffffffffffe
0000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000ffffffffffffffff

0008000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000020000000000000000

0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000001000000000000000000000000000000000000

000000000000000000000000000000000000000000000000000000000000053a
0100000000000000000000000000000000000000000000000000000000000000

0000000000000010000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000002000000
0000000000000000000000000000000000000000000000000000000000100000

0000000000000000000000000000000000000000000000000000000000000000
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

0000000000000000000000000000000000000000000000000000000000000006
00000000000000000000000000000000000000000000000000000000000000c0

0000000000000000000000000000000000000000000000000000000000002ce0
0000000000000000000000000000000000000000000000000000000000005880

0000000000000000000000000000000000000000000000000000000000008280
000000000000000000000000000000000000000000000000000000000000acc0

000000000000000000000000000000000000000000000000000000000000d6e0
0000000000000000000000000000000000000000020000000000000000000000

0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000009

0000000000000000000000000000000000000000000000000000000000000120
0000000000000000000000000000000000000000000000000000000000000720

0000000000000000000000000000000000000000000000000000000000000b80
0000000000000000000000000000000000000000000000000000000000000fe0

"
		);

		let func = {
			use crate::{Function, Param};
			use ParamType::*;
			#[allow(deprecated)]
			Function {
				name: "f_tuple".to_string(),
				inputs: vec![
					Param {
						name: "c".to_string(),
						kind: Array(Box::new(Tuple(vec![Uint(256), Uint(256)]))),
						internal_type: None,
					},
					Param {
						name: "d".to_string(),
						kind: Array(Box::new(Tuple(vec![
							Uint(256),
							Array(Box::new(Tuple(vec![Uint(256), Array(Box::new(ParamType::String))]))),
						]))),
						internal_type: None,
					},
				],
				outputs: vec![],
				constant: None,
				state_mutability: crate::StateMutability::default(),
			}
		};
		assert!(func.decode_input(&input).is_err());
	}

	#[test]
	fn decode_corrupted_fixed_array_of_strings() {
		let input = hex!(
			"
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000001000040
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000000000000000000000000000000000000000000008
5445535454455354000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000008
5445535454455354000000000000000000000000000000000000000000000000
"
		);

		let func = {
			use crate::{Function, Param};
			use ParamType::*;
			#[allow(deprecated)]
			Function {
				name: "f".to_string(),
				inputs: vec![
					Param { name: "i".to_string(), kind: Uint(256), internal_type: None },
					Param {
						name: "p".to_string(),
						kind: FixedArray(Box::new(ParamType::String), 2),
						internal_type: None,
					},
				],
				outputs: vec![],
				constant: None,
				state_mutability: crate::StateMutability::default(),
			}
		};
		assert!(func.decode_input(&input).is_err());
	}

	#[test]
	fn decode_whole_addresses() {
		let input = hex!(
			"
		0000000000000000000000000000000000000000000000000000000000012345
		0000000000000000000000000000000000000000000000000000000000054321
		"
		);
		assert!(decode(&[ParamType::Address], &input).is_ok());
		assert!(decode_whole(&[ParamType::Address], &input).is_err());
		assert!(decode_whole(&[ParamType::Address, ParamType::Address], &input).is_ok());
	}
}

-- file: ethabi/src/event.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Contract event.

use alloc::collections::BTreeMap;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use sha3::{Digest, Keccak256};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{
	decode, decode_whole, encode, signature::long_signature, Error, EventParam, Hash, Log, LogParam, ParamType, RawLog,
	RawTopicFilter, Result, Token, Topic, TopicFilter,
};

/// Contract event.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct Event {
	/// Event name.
	#[cfg_attr(feature = "serde", serde(deserialize_with = "crate::util::sanitize_name::deserialize"))]
	pub name: String,
	/// Event input.
	pub inputs: Vec<EventParam>,
	/// If anonymous, event cannot be found using `from` filter.
	pub anonymous: bool,
}

impl Event {
	/// Returns names of all params.
	fn params_names(&self) -> Vec<String> {
		self.inputs.iter().map(|p| p.name.clone()).collect()
	}

	/// Returns types of all params.
	fn param_types(&self) -> Vec<ParamType> {
		self.inputs.iter().map(|p| p.kind.clone()).collect()
	}

	/// Returns all params of the event.
	fn indexed_params(&self, indexed: bool) -> Vec<EventParam> {
		self.inputs.iter().filter(|p| p.indexed == indexed).cloned().collect()
	}

	/// Event signature
	pub fn signature(&self) -> Hash {
		long_signature(&self.name, &self.param_types())
	}

	/// Creates topic filter
	pub fn filter(&self, raw: RawTopicFilter) -> Result<TopicFilter> {
		fn convert_token(token: Token, kind: &ParamType) -> Result<Hash> {
			if !token.type_check(kind) {
				return Err(Error::InvalidData);
			}
			let encoded = encode(&[token]);
			if encoded.len() == 32 {
				let mut data = [0u8; 32];
				data.copy_from_slice(&encoded);
				Ok(data.into())
			} else {
				Ok(Hash::from_slice(Keccak256::digest(&encoded).as_slice()))
			}
		}

		fn convert_topic(topic: Topic<Token>, kind: Option<&ParamType>) -> Result<Topic<Hash>> {
			match topic {
				Topic::Any => Ok(Topic::Any),
				Topic::OneOf(tokens) => match kind {
					None => Err(Error::InvalidData),
					Some(kind) => {
						let topics =
							tokens.into_iter().map(|token| convert_token(token, kind)).collect::<Result<Vec<_>>>()?;
						Ok(Topic::OneOf(topics))
					}
				},
				Topic::This(token) => match kind {
					None => Err(Error::InvalidData),
					Some(kind) => Ok(Topic::This(convert_token(token, kind)?)),
				},
			}
		}

		let kinds: Vec<_> = self.indexed_params(true).into_iter().map(|param| param.kind).collect();
		let result = if self.anonymous {
			TopicFilter {
				topic0: convert_topic(raw.topic0, kinds.get(0))?,
				topic1: convert_topic(raw.topic1, kinds.get(1))?,
				topic2: convert_topic(raw.topic2, kinds.get(2))?,
				topic3: Topic::Any,
			}
		} else {
			TopicFilter {
				topic0: Topic::This(self.signature()),
				topic1: convert_topic(raw.topic0, kinds.get(0))?,
				topic2: convert_topic(raw.topic1, kinds.get(1))?,
				topic3: convert_topic(raw.topic2, kinds.get(2))?,
			}
		};

		Ok(result)
	}

	// Converts param types for indexed parameters to bytes32 where appropriate
	// This applies to strings, arrays, structs and bytes to follow the encoding of
	// these indexed param types according to
	// https://solidity.readthedocs.io/en/develop/abi-spec.html#encoding-of-indexed-event-parameters
	fn convert_topic_param_type(&self, kind: &ParamType) -> ParamType {
		match kind {
			ParamType::String
			| ParamType::Bytes
			| ParamType::Array(_)
			| ParamType::FixedArray(_, _)
			| ParamType::Tuple(_) => ParamType::FixedBytes(32),
			_ => kind.clone(),
		}
	}

	fn parse_log_inner<F: Fn(&[ParamType], &[u8]) -> Result<Vec<Token>>>(&self, log: RawLog, decode: F) -> Result<Log> {
		let topics = log.topics;
		let data = log.data;
		let topics_len = topics.len();
		// obtains all params info
		let topic_params = self.indexed_params(true);
		let data_params = self.indexed_params(false);
		// then take first topic if event is not anonymous
		let to_skip = if self.anonymous {
			0
		} else {
			// verify
			let event_signature = topics.get(0).ok_or(Error::InvalidData)?;
			if event_signature != &self.signature() {
				return Err(Error::InvalidData);
			}
			1
		};

		let topic_types =
			topic_params.iter().map(|p| self.convert_topic_param_type(&p.kind)).collect::<Vec<ParamType>>();

		let flat_topics = topics.into_iter().skip(to_skip).flat_map(|t| t.as_ref().to_vec()).collect::<Vec<u8>>();

		let topic_tokens = decode(&topic_types, &flat_topics)?;

		// topic may be only a 32 bytes encoded token
		if topic_tokens.len() != topics_len - to_skip {
			return Err(Error::InvalidData);
		}

		let topics_named_tokens = topic_params.into_iter().map(|p| p.name).zip(topic_tokens.into_iter());

		let data_types = data_params.iter().map(|p| p.kind.clone()).collect::<Vec<ParamType>>();

		let data_tokens = decode(&data_types, &data)?;

		let data_named_tokens = data_params.into_iter().map(|p| p.name).zip(data_tokens.into_iter());

		let named_tokens = topics_named_tokens.chain(data_named_tokens).collect::<BTreeMap<String, Token>>();

		let decoded_params = self
			.params_names()
			.into_iter()
			.map(|name| LogParam { name: name.clone(), value: named_tokens[&name].clone() })
			.collect();

		let result = Log { params: decoded_params };

		Ok(result)
	}

	/// Parses `RawLog` and retrieves all log params from it.
	/// Fails, if some data left to decode
	pub fn parse_log_whole(&self, log: RawLog) -> Result<Log> {
		self.parse_log_inner(log, decode_whole)
	}

	/// Parses `RawLog` and retrieves all log params from it.
	/// Returns ok, even if some data left to decode
	pub fn parse_log(&self, log: RawLog) -> Result<Log> {
		self.parse_log_inner(log, decode)
	}
}

#[cfg(test)]
mod tests {
	use hex_literal::hex;

	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{
		log::{Log, RawLog},
		signature::long_signature,
		token::Token,
		Event, EventParam, LogParam, ParamType,
	};

	#[test]
	fn test_decoding_event() {
		let event = Event {
			name: "foo".to_owned(),
			inputs: vec![
				EventParam { name: "a".to_owned(), kind: ParamType::Int(256), indexed: false },
				EventParam { name: "b".to_owned(), kind: ParamType::Int(256), indexed: true },
				EventParam { name: "c".to_owned(), kind: ParamType::Address, indexed: false },
				EventParam { name: "d".to_owned(), kind: ParamType::Address, indexed: true },
				EventParam { name: "e".to_owned(), kind: ParamType::String, indexed: true },
				EventParam {
					name: "f".to_owned(),
					kind: ParamType::Array(Box::new(ParamType::Int(256))),
					indexed: true,
				},
				EventParam {
					name: "g".to_owned(),
					kind: ParamType::FixedArray(Box::new(ParamType::Address), 5),
					indexed: true,
				},
			],
			anonymous: false,
		};

		let log = RawLog {
			topics: vec![
				long_signature(
					"foo",
					&[
						ParamType::Int(256),
						ParamType::Int(256),
						ParamType::Address,
						ParamType::Address,
						ParamType::String,
						ParamType::Array(Box::new(ParamType::Int(256))),
						ParamType::FixedArray(Box::new(ParamType::Address), 5),
					],
				),
				hex!("0000000000000000000000000000000000000000000000000000000000000002").into(),
				hex!("0000000000000000000000001111111111111111111111111111111111111111").into(),
				hex!("00000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").into(),
				hex!("00000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").into(),
				hex!("00000000000000000ccccccccccccccccccccccccccccccccccccccccccccccc").into(),
			],
			data: hex!(
				"
				0000000000000000000000000000000000000000000000000000000000000003
				0000000000000000000000002222222222222222222222222222222222222222
			"
			)
			.into(),
		};
		let result = event.parse_log(log).unwrap();

		assert_eq!(
			result,
			Log {
				params: [
					("a", Token::Int(hex!("0000000000000000000000000000000000000000000000000000000000000003").into()),),
					("b", Token::Int(hex!("0000000000000000000000000000000000000000000000000000000000000002").into()),),
					("c", Token::Address(hex!("2222222222222222222222222222222222222222").into())),
					("d", Token::Address(hex!("1111111111111111111111111111111111111111").into())),
					(
						"e",
						Token::FixedBytes(
							hex!("00000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").into()
						)
					),
					(
						"f",
						Token::FixedBytes(
							hex!("00000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").into()
						)
					),
					(
						"g",
						Token::FixedBytes(
							hex!("00000000000000000ccccccccccccccccccccccccccccccccccccccccccccccc").into()
						)
					),
				]
				.iter()
				.cloned()
				.map(|(name, value)| LogParam { name: name.to_string(), value })
				.collect::<Vec<_>>()
			}
		);
	}

	#[test]
	fn parse_log_whole() {
		let correct_event = Event {
			name: "Test".into(),
			inputs: vec![
				EventParam {
					name: "tuple".into(),
					kind: ParamType::Tuple(vec![ParamType::Address, ParamType::Address]),
					indexed: false,
				},
				EventParam { name: "addr".into(), kind: ParamType::Address, indexed: true },
			],
			anonymous: false,
		};
		// swap indexed params
		let mut wrong_event = correct_event.clone();
		wrong_event.inputs[0].indexed = true;
		wrong_event.inputs[1].indexed = false;

		let log = RawLog {
			topics: vec![
				hex!("cf74b4e62f836eeedcd6f92120ffb5afea90e6fa490d36f8b81075e2a7de0cf7").into(),
				hex!("0000000000000000000000000000000000000000000000000000000000012321").into(),
			],
			data: hex!(
				"
			0000000000000000000000000000000000000000000000000000000000012345
			0000000000000000000000000000000000000000000000000000000000054321
			"
			)
			.into(),
		};

		assert!(wrong_event.parse_log(log.clone()).is_ok());
		assert!(wrong_event.parse_log_whole(log.clone()).is_err());
		assert!(correct_event.parse_log_whole(log).is_ok());
	}
}

-- file: ethabi/src/event_param.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Event param specification.

#[cfg(feature = "serde")]
use core::fmt;

#[cfg(feature = "serde")]
use serde::{
	de::{Error, MapAccess, Visitor},
	ser::SerializeMap,
	Deserialize, Deserializer, Serialize, Serializer,
};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::ParamType;
#[cfg(feature = "serde")]
use crate::{param_type::Writer, TupleParam};

/// Event param specification.
#[derive(Debug, Clone, PartialEq)]
pub struct EventParam {
	/// Param name.
	pub name: String,
	/// Param type.
	pub kind: ParamType,
	/// Indexed flag. If true, param is used to build block bloom.
	pub indexed: bool,
}

#[cfg(feature = "serde")]
impl<'a> Deserialize<'a> for EventParam {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: Deserializer<'a>,
	{
		deserializer.deserialize_any(EventParamVisitor)
	}
}

#[cfg(feature = "serde")]
struct EventParamVisitor;

#[cfg(feature = "serde")]
impl<'a> Visitor<'a> for EventParamVisitor {
	type Value = EventParam;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		write!(formatter, "a valid event parameter spec")
	}

	fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
	where
		V: MapAccess<'a>,
	{
		let mut name = None;
		let mut kind = None;
		let mut indexed = None;
		let mut components = None;

		while let Some(ref key) = map.next_key::<String>()? {
			match key.as_ref() {
				"name" => {
					if name.is_some() {
						return Err(Error::duplicate_field("name"));
					}
					name = Some(map.next_value()?);
				}
				"type" => {
					if kind.is_some() {
						return Err(Error::duplicate_field("kind"));
					}
					kind = Some(map.next_value()?);
				}
				"components" => {
					if components.is_some() {
						return Err(Error::duplicate_field("components"));
					}
					let component: Vec<TupleParam> = map.next_value()?;
					components = Some(component)
				}
				"indexed" => {
					if indexed.is_some() {
						return Err(Error::duplicate_field("indexed"));
					}
					indexed = Some(map.next_value()?);
				}
				_ => {}
			}
		}
		let name = name.ok_or_else(|| Error::missing_field("name"))?;
		let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
		crate::param::set_tuple_components(&mut kind, components)?;
		let indexed = indexed.unwrap_or(false);
		Ok(EventParam { name, kind, indexed })
	}
}

#[cfg(feature = "serde")]
impl Serialize for EventParam {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut map = serializer.serialize_map(None)?;
		map.serialize_entry("name", &self.name)?;
		map.serialize_entry("type", &Writer::write_for_abi(&self.kind, false))?;
		map.serialize_entry("indexed", &self.indexed)?;
		if let Some(inner_tuple) = crate::param::inner_tuple(&self.kind) {
			map.serialize_key("components")?;
			map.serialize_value(&crate::param::SerializeableParamVec(inner_tuple))?;
		}
		map.end()
	}
}

#[cfg(all(test, feature = "serde"))]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{tests::assert_json_eq, EventParam, ParamType};

	#[test]
	fn event_param_deserialization() {
		let s = r#"{
			"name": "foo",
			"type": "address",
			"indexed": true
		}"#;

		let deserialized: EventParam = serde_json::from_str(s).unwrap();

		assert_eq!(deserialized, EventParam { name: "foo".to_owned(), kind: ParamType::Address, indexed: true });

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn event_param_tuple_deserialization() {
		let s = r#"{
			"name": "foo",
			"type": "tuple",
			"indexed": true,
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "tuple",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: EventParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			EventParam {
				name: "foo".to_owned(),
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				indexed: true,
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn event_param_tuple_array_deserialization() {
		let s = r#"{
			"components": [
				{ "type": "uint256" },
				{ "type": "address" },
				{
					"components": [
						{ "type": "address" },
						{ "type": "address" }
					],
					"type": "tuple"
				},
				{ "type": "uint256" },
				{
					"components": [
						{
							"components": [
								{ "type": "address" },
								{ "type": "bytes" }
							],
							"type": "tuple[]"
						},
						{
							"components": [
								{ "type": "address" },
								{ "type": "uint256" }
							],
							"type": "tuple[]"
						},
						{ "type": "uint256" }
					],
					"type": "tuple[]"
				},
				{ "type": "uint256" }
			],
			"indexed": false,
			"name": "LogTaskSubmitted",
			"type": "tuple"
        }"#;

		let deserialized: EventParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			EventParam {
				name: "LogTaskSubmitted".to_owned(),
				kind: ParamType::Tuple(vec![
					ParamType::Uint(256),
					ParamType::Address,
					ParamType::Tuple(vec![ParamType::Address, ParamType::Address]),
					ParamType::Uint(256),
					ParamType::Array(Box::new(ParamType::Tuple(vec![
						ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address, ParamType::Bytes,]))),
						ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address, ParamType::Uint(256)]))),
						ParamType::Uint(256),
					]))),
					ParamType::Uint(256),
				]),
				indexed: false,
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}
}

-- file: ethabi/src/state_mutability.rs --
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// Whether a function modifies or reads blockchain state
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StateMutability {
	/// Specified not to read blockchain state
	#[cfg_attr(feature = "serde", serde(rename = "pure"))]
	Pure,
	/// Specified to not modify the blockchain state
	#[cfg_attr(feature = "serde", serde(rename = "view"))]
	View,
	/// Function does not accept Ether - the default
	#[cfg_attr(feature = "serde", serde(rename = "nonpayable"))]
	NonPayable,
	/// Function accepts Ether
	#[cfg_attr(feature = "serde", serde(rename = "payable"))]
	Payable,
}

impl Default for StateMutability {
	fn default() -> Self {
		Self::NonPayable
	}
}

#[cfg(all(test, feature = "serde"))]
mod test {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{tests::assert_json_eq, StateMutability};

	#[test]
	fn state_mutability() {
		let json = r#"
			[
				"pure",
				"view",
				"nonpayable",
				"payable"
			]
		"#;

		let deserialized: Vec<StateMutability> = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			vec![StateMutability::Pure, StateMutability::View, StateMutability::NonPayable, StateMutability::Payable,]
		);

		assert_json_eq(json, &serde_json::to_string(&deserialized).unwrap());
	}
}

-- file: ethabi/src/function.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Contract function call builder.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{
	decode, encode, signature::short_signature, Bytes, Error, Param, ParamType, Result, StateMutability, Token,
};

/// Contract function specification.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Function {
	/// Function name.
	#[cfg_attr(feature = "serde", serde(deserialize_with = "crate::util::sanitize_name::deserialize"))]
	pub name: String,
	/// Function input.
	pub inputs: Vec<Param>,
	/// Function output.
	pub outputs: Vec<Param>,
	#[deprecated(note = "The constant attribute was removed in Solidity 0.5.0 and has been \
				replaced with stateMutability.")]
	/// Constant function.
	#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
	pub constant: Option<bool>,
	/// Whether the function reads or modifies blockchain state
	#[cfg_attr(feature = "serde", serde(rename = "stateMutability", default))]
	pub state_mutability: StateMutability,
}

impl Function {
	/// Returns all input params of given function.
	fn input_param_types(&self) -> Vec<ParamType> {
		self.inputs.iter().map(|p| p.kind.clone()).collect()
	}

	/// Returns all output params of given function.
	fn output_param_types(&self) -> Vec<ParamType> {
		self.outputs.iter().map(|p| p.kind.clone()).collect()
	}

	/// Prepares ABI function call with given input params.
	pub fn encode_input(&self, tokens: &[Token]) -> Result<Bytes> {
		let params = self.input_param_types();

		if !Token::types_check(tokens, &params) {
			return Err(Error::InvalidData);
		}

		let signed = short_signature(&self.name, &params).to_vec();
		let encoded = encode(tokens);
		Ok(signed.into_iter().chain(encoded.into_iter()).collect())
	}

	/// Return the 4 byte short signature of this function.
	pub fn short_signature(&self) -> [u8; 4] {
		let params = self.input_param_types();
		short_signature(&self.name, &params)
	}

	/// Parses the ABI function output to list of tokens.
	pub fn decode_output(&self, data: &[u8]) -> Result<Vec<Token>> {
		decode(&self.output_param_types(), data)
	}

	/// Parses the ABI function input to a list of tokens.
	pub fn decode_input(&self, data: &[u8]) -> Result<Vec<Token>> {
		decode(&self.input_param_types(), data)
	}

	/// Returns a signature that uniquely identifies this function.
	///
	/// Examples:
	/// - `functionName()`
	/// - `functionName():(uint256)`
	/// - `functionName(bool):(uint256,string)`
	/// - `functionName(uint256,bytes32):(string,uint256)`
	pub fn signature(&self) -> String {
		let inputs = self.inputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");

		let outputs = self.outputs.iter().map(|p| p.kind.to_string()).collect::<Vec<_>>().join(",");

		match (inputs.len(), outputs.len()) {
			(_, 0) => format!("{}({inputs})", self.name),
			(_, _) => format!("{}({inputs}):({outputs})", self.name),
		}
	}
}

#[cfg(test)]
mod tests {
	use hex_literal::hex;

	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{Function, Param, ParamType, StateMutability, Token};

	#[test]
	fn test_function_encode_call() {
		#[allow(deprecated)]
		let func = Function {
			name: "baz".to_owned(),
			inputs: vec![
				Param { name: "a".to_owned(), kind: ParamType::Uint(32), internal_type: None },
				Param { name: "b".to_owned(), kind: ParamType::Bool, internal_type: None },
			],
			outputs: vec![],
			constant: None,
			state_mutability: StateMutability::Payable,
		};

		let mut uint = [0u8; 32];
		uint[31] = 69;
		let encoded = func.encode_input(&[Token::Uint(uint.into()), Token::Bool(true)]).unwrap();
		let expected = hex!("cdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001").to_vec();
		assert_eq!(encoded, expected);

		let expected_sig = hex!("cdcd77c0").to_vec();
		assert_eq!(func.short_signature().to_vec(), expected_sig);
	}
}

-- file: ethabi/src/errors.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::no_std_prelude::Cow;
#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
#[cfg(feature = "serde")]
use core::num;
#[cfg(feature = "std")]
use thiserror::Error;

/// Ethabi result type
pub type Result<T> = core::result::Result<T, Error>;

/// Ethabi errors
#[cfg_attr(feature = "std", derive(Error))]
#[derive(Debug)]
pub enum Error {
	/// Invalid entity such as a bad function name.
	#[cfg_attr(feature = "std", error("Invalid name: {0}"))]
	InvalidName(String),
	/// Invalid data.
	#[cfg_attr(feature = "std", error("Invalid data"))]
	InvalidData,
	/// Serialization error.
	#[cfg(feature = "full-serde")]
	#[error("Serialization error: {0}")]
	SerdeJson(#[from] serde_json::Error),
	/// Integer parsing error.
	#[cfg(feature = "serde")]
	#[cfg_attr(feature = "std", error("Integer parsing error: {0}"))]
	ParseInt(#[cfg_attr(feature = "std", from)] num::ParseIntError),
	/// Hex string parsing error.
	#[cfg(feature = "serde")]
	#[cfg_attr(feature = "std", error("Hex parsing error: {0}"))]
	Hex(#[cfg_attr(feature = "std", from)] hex::FromHexError),
	/// Other errors.
	#[cfg_attr(feature = "std", error("{0}"))]
	Other(Cow<'static, str>),
}

#[cfg(feature = "serde")]
impl From<uint::FromDecStrErr> for Error {
	fn from(err: uint::FromDecStrErr) -> Self {
		use uint::FromDecStrErr::*;
		match err {
			InvalidCharacter => Self::Other(Cow::Borrowed("Uint parse error: InvalidCharacter")),
			InvalidLength => Self::Other(Cow::Borrowed("Uint parse error: InvalidLength")),
		}
	}
}

-- file: ethabi/src/contract.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use alloc::collections::{btree_map::Values, BTreeMap};
#[cfg(feature = "serde")]
use core::fmt;
use core::iter::Flatten;
#[cfg(feature = "full-serde")]
use std::io;

#[cfg(feature = "serde")]
use serde::{
	de::{SeqAccess, Visitor},
	ser::SerializeSeq,
	Deserialize, Deserializer, Serialize, Serializer,
};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
#[cfg(feature = "serde")]
use crate::operation::Operation;
use crate::{error::Error as AbiError, errors, Constructor, Error, Event, Function};

/// API building calls to contracts ABI.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Contract {
	/// Contract constructor.
	pub constructor: Option<Constructor>,
	/// Contract functions.
	pub functions: BTreeMap<String, Vec<Function>>,
	/// Contract events, maps signature to event.
	pub events: BTreeMap<String, Vec<Event>>,
	/// Contract errors, maps signature to error.
	pub errors: BTreeMap<String, Vec<AbiError>>,
	/// Contract has receive function.
	pub receive: bool,
	/// Contract has fallback function.
	pub fallback: bool,
}

#[cfg(feature = "serde")]
impl<'a> Deserialize<'a> for Contract {
	fn deserialize<D>(deserializer: D) -> Result<Contract, D::Error>
	where
		D: Deserializer<'a>,
	{
		deserializer.deserialize_any(ContractVisitor)
	}
}

#[cfg(feature = "serde")]
struct ContractVisitor;

#[cfg(feature = "serde")]
impl<'a> Visitor<'a> for ContractVisitor {
	type Value = Contract;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		formatter.write_str("valid abi spec file")
	}

	fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
	where
		A: SeqAccess<'a>,
	{
		let mut result = Contract::default();
		while let Some(operation) = seq.next_element()? {
			match operation {
				Operation::Constructor(constructor) => {
					result.constructor = Some(constructor);
				}
				Operation::Function(func) => {
					result.functions.entry(func.name.clone()).or_default().push(func);
				}
				Operation::Event(event) => {
					result.events.entry(event.name.clone()).or_default().push(event);
				}
				Operation::Error(error) => {
					result.errors.entry(error.name.clone()).or_default().push(error);
				}
				Operation::Fallback => {
					result.fallback = true;
				}
				Operation::Receive => {
					result.receive = true;
				}
			}
		}

		Ok(result)
	}
}

#[cfg(feature = "serde")]
impl Serialize for Contract {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		// Serde's FlatMapSerializer is private, so we'll have to improvise...
		#[derive(Serialize)]
		#[serde(tag = "type")]
		enum OperationRef<'a> {
			#[serde(rename = "constructor")]
			Constructor(&'a Constructor),

			#[serde(rename = "function")]
			Function(&'a Function),

			#[serde(rename = "event")]
			Event(&'a Event),

			#[serde(rename = "error")]
			Error(&'a AbiError),

			#[serde(rename = "fallback")]
			Fallback,

			#[serde(rename = "receive")]
			Receive,
		}

		let mut seq = serializer.serialize_seq(None)?;

		if let Some(constructor) = &self.constructor {
			seq.serialize_element(&OperationRef::Constructor(constructor))?;
		}

		for functions in self.functions.values() {
			for function in functions {
				seq.serialize_element(&OperationRef::Function(function))?;
			}
		}

		for events in self.events.values() {
			for event in events {
				seq.serialize_element(&OperationRef::Event(event))?;
			}
		}

		for errors in self.errors.values() {
			for error in errors {
				seq.serialize_element(&OperationRef::Error(error))?;
			}
		}

		if self.receive {
			seq.serialize_element(&OperationRef::Receive)?;
		}

		if self.fallback {
			seq.serialize_element(&OperationRef::Fallback)?;
		}

		seq.end()
	}
}

impl Contract {
	/// Loads contract from json.
	#[cfg(feature = "full-serde")]
	pub fn load<T: io::Read>(reader: T) -> errors::Result<Self> {
		serde_json::from_reader(reader).map_err(From::from)
	}

	/// Creates constructor call builder.
	pub fn constructor(&self) -> Option<&Constructor> {
		self.constructor.as_ref()
	}

	/// Get the function named `name`, the first if there are overloaded
	/// versions of the same function.
	pub fn function(&self, name: &str) -> errors::Result<&Function> {
		self.functions.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Get the contract event named `name`, the first if there are multiple.
	pub fn event(&self, name: &str) -> errors::Result<&Event> {
		self.events.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Get the contract error named `name`, the first if there are multiple.
	pub fn error(&self, name: &str) -> errors::Result<&AbiError> {
		self.errors.get(name).into_iter().flatten().next().ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Get all contract events named `name`.
	pub fn events_by_name(&self, name: &str) -> errors::Result<&Vec<Event>> {
		self.events.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Get all functions named `name`.
	pub fn functions_by_name(&self, name: &str) -> errors::Result<&Vec<Function>> {
		self.functions.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Get all errors named `name`.
	pub fn errors_by_name(&self, name: &str) -> errors::Result<&Vec<AbiError>> {
		self.errors.get(name).ok_or_else(|| Error::InvalidName(name.to_owned()))
	}

	/// Iterate over all functions of the contract in arbitrary order.
	pub fn functions(&self) -> Functions {
		Functions(self.functions.values().flatten())
	}

	/// Iterate over all events of the contract in arbitrary order.
	pub fn events(&self) -> Events {
		Events(self.events.values().flatten())
	}

	/// Iterate over all errors of the contract in arbitrary order.
	pub fn errors(&self) -> AbiErrors {
		AbiErrors(self.errors.values().flatten())
	}
}

/// Contract functions iterator.
pub struct Functions<'a>(Flatten<Values<'a, String, Vec<Function>>>);

impl<'a> Iterator for Functions<'a> {
	type Item = &'a Function;

	fn next(&mut self) -> Option<Self::Item> {
		self.0.next()
	}
}

/// Contract events iterator.
pub struct Events<'a>(Flatten<Values<'a, String, Vec<Event>>>);

impl<'a> Iterator for Events<'a> {
	type Item = &'a Event;

	fn next(&mut self) -> Option<Self::Item> {
		self.0.next()
	}
}

/// Contract errors iterator.
pub struct AbiErrors<'a>(Flatten<Values<'a, String, Vec<AbiError>>>);

impl<'a> Iterator for AbiErrors<'a> {
	type Item = &'a AbiError;

	fn next(&mut self) -> Option<Self::Item> {
		self.0.next()
	}
}

#[cfg(all(test, feature = "serde"))]
#[allow(deprecated)]
mod test {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use alloc::collections::BTreeMap;
	use core::iter::FromIterator;

	use crate::{tests::assert_ser_de, AbiError, Constructor, Contract, Event, EventParam, Function, Param, ParamType};

	#[test]
	fn empty() {
		let json = "[]";

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn constructor() {
		let json = r#"
			[
				{
					"type": "constructor",
					"inputs": [
						{
							"name":"a",
							"type":"address"
						}
					]
				}
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: Some(Constructor {
					inputs: vec![Param { name: "a".to_string(), kind: ParamType::Address, internal_type: None }]
				}),
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn functions() {
		let json = r#"
			[
				{
					"type": "function",
					"name": "foo",
					"inputs": [
						{
							"name":"a",
							"type":"address"
						}
					],
					"outputs": [
						{
							"name": "res",
							"type":"address"
						}
					]
				},
				{
					"type": "function",
					"name": "bar",
					"inputs": [],
					"outputs": []
				}
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::from_iter(vec![
					(
						"foo".to_string(),
						vec![Function {
							name: "foo".to_string(),
							inputs: vec![Param {
								name: "a".to_string(),
								kind: ParamType::Address,
								internal_type: None,
							}],
							outputs: vec![Param {
								name: "res".to_string(),
								kind: ParamType::Address,
								internal_type: None,
							}],
							constant: None,
							state_mutability: Default::default(),
						}]
					),
					(
						"bar".to_string(),
						vec![Function {
							name: "bar".to_string(),
							inputs: vec![],
							outputs: vec![],
							constant: None,
							state_mutability: Default::default(),
						}]
					),
				]),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn functions_overloads() {
		let json = r#"
			[
				{
					"type": "function",
					"name": "foo",
					"inputs": [
						{
							"name":"a",
							"type":"address"
						}
					],
					"outputs": [
						{
							"name": "res",
							"type":"address"
						}
					]
				},
				{
					"type": "function",
					"name": "foo",
					"inputs": [],
					"outputs": []
				}
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::from_iter(vec![(
					"foo".to_string(),
					vec![
						Function {
							name: "foo".to_string(),
							inputs: vec![Param {
								name: "a".to_string(),
								kind: ParamType::Address,
								internal_type: None,
							}],
							outputs: vec![Param {
								name: "res".to_string(),
								kind: ParamType::Address,
								internal_type: None,
							}],
							constant: None,
							state_mutability: Default::default(),
						},
						Function {
							name: "foo".to_string(),
							inputs: vec![],
							outputs: vec![],
							constant: None,
							state_mutability: Default::default(),
						},
					]
				)]),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn events() {
		let json = r#"
			[
				{
					"type": "event",
					"name": "foo",
					"inputs": [
						{
							"name":"a",
							"type":"address"
						}
					],
					"anonymous": false
				},
				{
					"type": "event",
					"name": "bar",
					"inputs": [
						{
							"name":"a",
							"type":"address",
							"indexed": true
						}
					],
					"anonymous": false
				}
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::from_iter(vec![
					(
						"foo".to_string(),
						vec![Event {
							name: "foo".to_string(),
							inputs: vec![EventParam {
								name: "a".to_string(),
								kind: ParamType::Address,
								indexed: false,
							}],
							anonymous: false,
						}]
					),
					(
						"bar".to_string(),
						vec![Event {
							name: "bar".to_string(),
							inputs: vec![EventParam { name: "a".to_string(), kind: ParamType::Address, indexed: true }],
							anonymous: false,
						}]
					),
				]),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn events_overload() {
		let json = r#"
			[
				{
					"type": "event",
					"name": "foo",
					"inputs": [
						{
							"name":"a",
							"type":"address"
						}
					],
					"anonymous": false
				},
				{
					"type": "event",
					"name": "foo",
					"inputs": [
						{
							"name":"a",
							"type":"address",
							"indexed": true
						}
					],
					"anonymous": false
				}
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::from_iter(vec![(
					"foo".to_string(),
					vec![
						Event {
							name: "foo".to_string(),
							inputs: vec![EventParam {
								name: "a".to_string(),
								kind: ParamType::Address,
								indexed: false,
							}],
							anonymous: false,
						},
						Event {
							name: "foo".to_string(),
							inputs: vec![EventParam { name: "a".to_string(), kind: ParamType::Address, indexed: true }],
							anonymous: false,
						},
					]
				)]),
				errors: BTreeMap::new(),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn errors() {
		let json = r#"
            [
              {
                "type": "error",
                "inputs": [
                  {
                    "name": "available",
                    "type": "uint256"
                  },
                  {
                    "name": "required",
                    "type": "address"
                  }
                ],
                "name": "foo"
              },
              {
                "type": "error",
                "inputs": [
                  {
                    "name": "a",
                    "type": "uint256"
                  },
                  {
                    "name": "b",
                    "type": "address"
                  }
                ],
                "name": "bar"
              }
            ]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::from_iter(vec![
					(
						"foo".to_string(),
						vec![AbiError {
							name: "foo".to_string(),
							inputs: vec![
								Param {
									name: "available".to_string(),
									kind: ParamType::Uint(256),
									internal_type: None,
								},
								Param { name: "required".to_string(), kind: ParamType::Address, internal_type: None }
							],
						}]
					),
					(
						"bar".to_string(),
						vec![AbiError {
							name: "bar".to_string(),
							inputs: vec![
								Param { name: "a".to_string(), kind: ParamType::Uint(256), internal_type: None },
								Param { name: "b".to_string(), kind: ParamType::Address, internal_type: None }
							],
						}]
					),
				]),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn errors_overload() {
		let json = r#"
			[
			  {
				"type": "error",
				"inputs": [
				  {
					"name": "a",
					"type": "uint256"
				  }
				],
				"name": "foo"
			  },
			  {
				"type": "error",
				"inputs": [
				  {
					"name": "a",
					"type": "uint256"
				  },
				  {
					"name": "b",
					"type": "address"
				  }
				],
				"name": "foo"
			  }
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::from_iter(vec![(
					"foo".to_string(),
					vec![
						AbiError {
							name: "foo".to_string(),
							inputs: vec![Param {
								name: "a".to_string(),
								kind: ParamType::Uint(256),
								internal_type: None,
							}],
						},
						AbiError {
							name: "foo".to_string(),
							inputs: vec![
								Param { name: "a".to_string(), kind: ParamType::Uint(256), internal_type: None },
								Param { name: "b".to_string(), kind: ParamType::Address, internal_type: None }
							],
						},
					]
				),]),
				receive: false,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn receive() {
		let json = r#"
			[
				{ "type": "receive" }
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: true,
				fallback: false,
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn fallback() {
		let json = r#"
			[
				{ "type": "fallback" }
			]
		"#;

		let deserialized: Contract = serde_json::from_str(json).unwrap();

		assert_eq!(
			deserialized,
			Contract {
				constructor: None,
				functions: BTreeMap::new(),
				events: BTreeMap::new(),
				errors: BTreeMap::new(),
				receive: false,
				fallback: true,
			}
		);

		assert_ser_de(&deserialized);
	}
}

-- file: ethabi/src/signature.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use sha3::{Digest, Keccak256};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{
	param_type::{ParamType, Writer},
	Hash,
};

/// Returns the first four bytes of the Keccak-256 hash of the signature of the given params
pub fn short_signature(name: &str, params: &[ParamType]) -> [u8; 4] {
	let mut result = [0u8; 4];
	fill_signature(name, params, &mut result);
	result
}

/// Returns the full Keccak-256 hash of the signature of the given params
pub fn long_signature(name: &str, params: &[ParamType]) -> Hash {
	let mut result = [0u8; 32];
	fill_signature(name, params, &mut result);
	result.into()
}

fn fill_signature(name: &str, params: &[ParamType], result: &mut [u8]) {
	let types = params.iter().map(Writer::write).collect::<Vec<String>>().join(",");

	let data: Vec<u8> = From::from(format!("{name}({types})").as_str());

	result.copy_from_slice(&Keccak256::digest(data)[..result.len()])
}

#[cfg(test)]
mod tests {
	use super::short_signature;
	use crate::ParamType;
	use hex_literal::hex;

	#[test]
	fn test_signature() {
		assert_eq!(hex!("cdcd77c0"), short_signature("baz", &[ParamType::Uint(32), ParamType::Bool]));
	}
}

-- file: ethabi/src/tests.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "serde")]
use core::fmt::Debug;

use hex_literal::hex;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
use serde_json::Value;

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{decode, encode, ParamType, Token};

#[cfg(feature = "serde")]
pub(crate) fn assert_json_eq(left: &str, right: &str) {
	let left: Value = serde_json::from_str(left).unwrap();
	let right: Value = serde_json::from_str(right).unwrap();
	assert_eq!(left, right);
}

#[cfg(feature = "serde")]
pub(crate) fn assert_ser_de<T>(canon: &T)
where
	T: Serialize + for<'a> Deserialize<'a> + PartialEq + Debug,
{
	let ser = serde_json::to_string(canon).unwrap();
	let de = serde_json::from_str(&ser).unwrap();
	assert_eq!(canon, &de);
}

macro_rules! test_encode_decode {
	(name: $name:tt, types: $types:expr, tokens: $tokens:expr, data: $data:tt) => {
		paste::item! {
			#[test]
			fn [<encode_ $name>]() {
				let encoded = encode(&$tokens);
				let expected = hex!($data).to_vec();
				assert_eq!(encoded, expected);
			}

			#[test]
			fn [<decode_ $name>]() {
				let encoded = hex!($data);
				let expected = $tokens;
				let decoded = decode(&$types, &encoded).unwrap();
				assert_eq!(decoded, expected);
			}
		}
	};
}

// test address
test_encode_decode! {
	name: address,
	types: [ParamType::Address],
	tokens: [Token::Address([0x11u8; 20].into())],
	data: "0000000000000000000000001111111111111111111111111111111111111111"
}
test_encode_decode! {
	name: addresses,
	types: [
	  ParamType::Address,
	  ParamType::Address
	],
	tokens: [
	  Token::Address([0x11u8; 20].into()),
	  Token::Address([0x22u8; 20].into())
	],
	data: "
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222"
}

// test bytes
test_encode_decode! {
	name: bytes,
	types: [ParamType::Bytes],
	tokens: [Token::Bytes(vec![0x12, 0x34])],
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		1234000000000000000000000000000000000000000000000000000000000000"
}
test_encode_decode! {
	name: bytes2,
	types: [ParamType::Bytes],
	tokens: [Token::Bytes(hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec())],
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		000000000000000000000000000000000000000000000000000000000000001f
		1000000000000000000000000000000000000000000000000000000000000200"
}
test_encode_decode! {
	name: bytes3,
	types: [ParamType::Bytes],
	tokens: [
		Token::Bytes(hex!("
			1000000000000000000000000000000000000000000000000000000000000000
			1000000000000000000000000000000000000000000000000000000000000000
		").to_vec())
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000040
		1000000000000000000000000000000000000000000000000000000000000000
		1000000000000000000000000000000000000000000000000000000000000000"
}
test_encode_decode! {
	name: two_bytes,
	types: [ParamType::Bytes, ParamType::Bytes],
	tokens: [
		Token::Bytes(hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec()),
		Token::Bytes(hex!("0010000000000000000000000000000000000000000000000000000000000002").to_vec())
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000040
		0000000000000000000000000000000000000000000000000000000000000080
		000000000000000000000000000000000000000000000000000000000000001f
		1000000000000000000000000000000000000000000000000000000000000200
		0000000000000000000000000000000000000000000000000000000000000020
		0010000000000000000000000000000000000000000000000000000000000002"
}

// test int
test_encode_decode! {
	name: int,
	types: [ParamType::Int(32)],
	tokens: [Token::Int([0x11u8; 32].into())],
	data: "1111111111111111111111111111111111111111111111111111111111111111"
}
test_encode_decode! {
	name: int2,
	types: [ParamType::Int(32)],
	tokens: {
		let mut int = [0u8; 32];
		int[31] = 4;
		[Token::Int(int.into())]
	},
	data: "0000000000000000000000000000000000000000000000000000000000000004"
}

// test uint
test_encode_decode! {
	name: uint,
	types: [ParamType::Uint(32)],
	tokens: [Token::Uint([0x11u8; 32].into())],
	data: "1111111111111111111111111111111111111111111111111111111111111111"
}
test_encode_decode! {
	name: uint2,
	types: [ParamType::Uint(32)],
	tokens: {
		let mut uint = [0u8; 32];
		uint[31] = 4;
		[Token::Uint(uint.into())]
	},
	data: "0000000000000000000000000000000000000000000000000000000000000004"
}

// test bool
test_encode_decode! {
	name: bool,
	types: [ParamType::Bool],
	tokens: [Token::Bool(true)],
	data: "0000000000000000000000000000000000000000000000000000000000000001"
}
test_encode_decode! {
	name: bool2,
	types: [ParamType::Bool],
	tokens: [Token::Bool(false)],
	data: "0000000000000000000000000000000000000000000000000000000000000000"
}

// test string
test_encode_decode! {
	name: string,
	types: [ParamType::String],
	tokens: [Token::String("gavofyork".to_owned())],
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000009
		6761766f66796f726b0000000000000000000000000000000000000000000000"
}

// test array
test_encode_decode! {
	name: dynamic_array_of_addresses,
	types: [ParamType::Array(Box::new(ParamType::Address))],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		[Token::Array(vec![address1, address2])]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222"
}
test_encode_decode! {
	name: dynamic_array_of_fixed_arrays_of_addresses,
	types: [
		ParamType::Array(Box::new(
			ParamType::FixedArray(Box::new(ParamType::Address), 2)
		))
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::FixedArray(vec![address1, address2]);
		let array1 = Token::FixedArray(vec![address3, address4]);
		[Token::Array(vec![array0, array1])]
	},
	   data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		0000000000000000000000003333333333333333333333333333333333333333
		0000000000000000000000004444444444444444444444444444444444444444"
}
test_encode_decode! {
	name: dynamic_array_of_fixed_arrays_of_dynamic_array,
	types: [
		ParamType::Array(Box::new(
			ParamType::FixedArray(Box::new(ParamType::Array(Box::new(ParamType::Address))), 2)
		))
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let address5 = Token::Address([0x55u8; 20].into());
		let address6 = Token::Address([0x66u8; 20].into());
		let address7 = Token::Address([0x77u8; 20].into());
		let address8 = Token::Address([0x88u8; 20].into());
		let array0 = Token::FixedArray(vec![
			Token::Array(vec![address1, address2]),
			Token::Array(vec![address3, address4]),
		]);
		let array1 = Token::FixedArray(vec![
			Token::Array(vec![address5, address6]),
			Token::Array(vec![address7, address8]),
		]);
		[Token::Array(vec![array0, array1])]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000040
		0000000000000000000000000000000000000000000000000000000000000140
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000003333333333333333333333333333333333333333
		0000000000000000000000004444444444444444444444444444444444444444
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000005555555555555555555555555555555555555555
		0000000000000000000000006666666666666666666666666666666666666666
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000007777777777777777777777777777777777777777
		0000000000000000000000008888888888888888888888888888888888888888"
	// outer array:
	//   0: 0000000000000000000000000000000000000000000000000000000000000020
	//  32: 0000000000000000000000000000000000000000000000000000000000000002 len outer => 2
	//  64: 0000000000000000000000000000000000000000000000000000000000000040 tail of outer => offset of array0
	//  96: 0000000000000000000000000000000000000000000000000000000000000140
	// array0:
	// 128: 0000000000000000000000000000000000000000000000000000000000000040 tail offset of array0 => offset of array0[0]
	// 160: 00000000000000000000000000000000000000000000000000000000000000a0 offset of array0[1] => 160
	// array0[0]:
	// 192: 0000000000000000000000000000000000000000000000000000000000000002 len of dynamic array array0[0] => 2
	// 224: 0000000000000000000000001111111111111111111111111111111111111111 array0[0][0] = address1
	// 256: 0000000000000000000000002222222222222222222222222222222222222222 array0[0][1] = address2
	// array0[1]:
	// 288: 0000000000000000000000000000000000000000000000000000000000000002 len of dynamic array0[1][0]
	// 320: 0000000000000000000000003333333333333333333333333333333333333333 array0[1][0] = address3
	// 352: 0000000000000000000000004444444444444444444444444444444444444444 array0[1][1] = address4
	// 384: 0000000000000000000000000000000000000000000000000000000000000040
	// 416: 00000000000000000000000000000000000000000000000000000000000000a0
	// 448: 0000000000000000000000000000000000000000000000000000000000000002
	// 480: 0000000000000000000000005555555555555555555555555555555555555555
	// 512: 0000000000000000000000006666666666666666666666666666666666666666
	// 544: 0000000000000000000000000000000000000000000000000000000000000002
	// 576: 0000000000000000000000007777777777777777777777777777777777777777
	// 608: 0000000000000000000000008888888888888888888888888888888888888888"

}
test_encode_decode! {
	name: dynamic_array_of_dynamic_arrays,
	types: [
		ParamType::Array(Box::new(
			ParamType::Array(Box::new(ParamType::Address))
		))
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let array0 = Token::Array(vec![address1]);
		let array1 = Token::Array(vec![address2]);
		let dynamic = Token::Array(vec![array0, array1]);
		[dynamic]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000040
		0000000000000000000000000000000000000000000000000000000000000080
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000002222222222222222222222222222222222222222"

	// Encoding explanation:
	// line 1 at 0x00 =   0: tail offset of dynamic array (0x20 = 32 => line 2)
	// line 2 at 0x20 =  32: length of dynamic array (0x2 = 2)
	// line 3 at 0x40 =  64: offset of array0 (0x80 = 128 = 5 * 32 => line 5)
	// line 4 at 0x60 =  96: offset of array1 (0xc0 = 192 = 7 * 32 => line 7)
	// line 5 at 0x80 = 128: length of array0 (0x1 = 1)
	// line 6 at 0xa0 = 160: value array0[0] (0x1111111111111111111111111111111111111111)
	// line 7 at 0xc0 = 192: length of array1 (0x1 = 1)
	// line 8 at 0xe0 = 224: value array1[0] (0x2222222222222222222222222222222222222222)
}
test_encode_decode! {
	name: dynamic_array_of_dynamic_arrays2,
	types: [
		ParamType::Array(Box::new(
			ParamType::Array(Box::new(ParamType::Address))
		))
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::Array(vec![address1, address2]);
		let array1 = Token::Array(vec![address3, address4]);
		let dynamic = Token::Array(vec![array0, array1]);
		[dynamic]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000003333333333333333333333333333333333333333
		0000000000000000000000004444444444444444444444444444444444444444"
}
test_encode_decode! {
	name: dynamic_array_of_bool,
	types: [ParamType::Array(Box::new(ParamType::Bool))],
	tokens: {
		[Token::Array(vec![Token::Bool(true), Token::Bool(false)])]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000000000000000000000000000000000000000000000
	"
}
test_encode_decode! {
	name: dynamic_array_of_bytes,
	types: [ParamType::Array(Box::new(ParamType::Bytes))],
	tokens: {
		let bytes = hex!("019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a4218a274f00d607").to_vec();
		[Token::Array(vec![Token::Bytes(bytes)])]
	},
	// line 1 at 0x00 =   0: tail offset of array
	// line 2 at 0x20 =  32: length of array
	// line 3 at 0x40 =  64: offset of array[0] (bytes)
	// line 4 at 0x60 =  96: length of array[0] (bytes)
	// line 5 at 0x80 = 128: first word of bytes
	// line 6 at 0xa0 = 160: first word of bytes
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000026
		019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a421
		8a274f00d6070000000000000000000000000000000000000000000000000000"
}
test_encode_decode! {
	name: dynamic_array_of_bytes2,
	types: [ParamType::Array(Box::new(ParamType::Bytes))],
	tokens: [
		Token::Array(vec![
			Token::Bytes(hex!("4444444444444444444444444444444444444444444444444444444444444444444444444444").to_vec()),
			Token::Bytes(hex!("6666666666666666666666666666666666666666666666666666666666666666666666666666").to_vec()),
		])
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000026
		4444444444444444444444444444444444444444444444444444444444444444
		4444444444440000000000000000000000000000000000000000000000000000
		0000000000000000000000000000000000000000000000000000000000000026
		6666666666666666666666666666666666666666666666666666666666666666
		6666666666660000000000000000000000000000000000000000000000000000"
}
test_encode_decode! {
	name: empty_dynamic_array,
	types: [
		ParamType::Array(Box::new(ParamType::Bool)),
		ParamType::Array(Box::new(ParamType::Bool)),
	],
	tokens: [
		Token::Array(vec![]),
		Token::Array(vec![])
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000040
		0000000000000000000000000000000000000000000000000000000000000060
		0000000000000000000000000000000000000000000000000000000000000000
		0000000000000000000000000000000000000000000000000000000000000000"
}
test_encode_decode! {
	name: dynamic_array_of_empty_dynamic_array,
	types: [
		ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool)))),
		ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Bool)))),
	],
	tokens: [
		Token::Array(vec![Token::Array(vec![])]),
		Token::Array(vec![Token::Array(vec![])]),
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000000
		0000000000000000000000000000000000000000000000000000000000000001
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000000"
}

// test fixed array
test_encode_decode! {
	name: fixed_array_of_addresses,
	types: [ParamType::FixedArray(Box::new(ParamType::Address), 2)],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		[Token::FixedArray(vec![address1, address2])]
	},
	data: "
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222"
}
test_encode_decode! {
	name: fixed_array_of_strings,
	types: [ParamType::FixedArray(Box::new(ParamType::String), 2)],
	tokens: {
		let s1 = Token::String("foo".into());
		let s2 = Token::String("bar".into());
		[Token::FixedArray(vec![s1, s2])]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000040
		0000000000000000000000000000000000000000000000000000000000000080
		0000000000000000000000000000000000000000000000000000000000000003
		666f6f0000000000000000000000000000000000000000000000000000000000
		0000000000000000000000000000000000000000000000000000000000000003
		6261720000000000000000000000000000000000000000000000000000000000"
	// `data` explained:
	// line 1 at 0x00 =   0: tail offset for the array
	// line 2 at 0x20 =  32: offset of string 1
	// line 3 at 0x40 =  64: offset of string 2
	// line 4 at 0x60 =  96: length of string 1
	// line 5 at 0x80 = 128: value  of string 1
	// line 6 at 0xa0 = 160: length of string 2
	// line 7 at 0xc0 = 192: value  of string 2
}
test_encode_decode! {
	name: fixed_array_of_fixed_arrays,
	types: [
		ParamType::FixedArray(
			Box::new(ParamType::FixedArray(Box::new(ParamType::Address), 2)),
			2
		)
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::FixedArray(vec![address1, address2]);
		let array1 = Token::FixedArray(vec![address3, address4]);
		let fixed = Token::FixedArray(vec![array0, array1]);
		[fixed]
	},
	data: "
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		0000000000000000000000003333333333333333333333333333333333333333
		0000000000000000000000004444444444444444444444444444444444444444"
}
test_encode_decode! {
	name: fixed_array_of_dynamic_array_of_addresses,
	types: [
		ParamType::FixedArray(
			Box::new(ParamType::Array(Box::new(ParamType::Address))),
			2
		)
	],
	tokens: {
		let address1 = Token::Address([0x11u8; 20].into());
		let address2 = Token::Address([0x22u8; 20].into());
		let address3 = Token::Address([0x33u8; 20].into());
		let address4 = Token::Address([0x44u8; 20].into());
		let array0 = Token::Array(vec![address1, address2]);
		let array1 = Token::Array(vec![address3, address4]);
		[Token::FixedArray(vec![array0, array1])]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000040
		00000000000000000000000000000000000000000000000000000000000000a0
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000001111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000003333333333333333333333333333333333333333
		0000000000000000000000004444444444444444444444444444444444444444"
}

// test fixed bytes
test_encode_decode! {
	name: fixed_bytes,
	types: [ParamType::FixedBytes(2)],
	tokens: [Token::FixedBytes(vec![0x12, 0x34])],
	data: "1234000000000000000000000000000000000000000000000000000000000000"

}

// test tuple with tuple array member
test_encode_decode! {
	name: tuple_with_tuple_array_test,
	types: [
		ParamType::Tuple(vec![
			ParamType::Array(Box::new(ParamType::Tuple(
				vec![
					ParamType::Address,
					ParamType::Uint(256)
				]
			)))
		])
	],
	tokens: {
		[
			Token::Tuple(
				vec![
					Token::Array(vec![
						Token::Tuple(vec![
							Token::Address([0x11u8; 20].into()),
							Token::Uint([0x11u8; 32].into()),
						]),
						Token::Tuple(vec![
							Token::Address([0x22u8; 20].into()),
							Token::Uint([0x22u8; 32].into()),
						]),
						Token::Tuple(vec![
							Token::Address([0x33u8; 20].into()),
							Token::Uint([0x44u8; 32].into()),
						])
					])
				]
			)
		]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000020
		0000000000000000000000000000000000000000000000000000000000000003
		0000000000000000000000001111111111111111111111111111111111111111
		1111111111111111111111111111111111111111111111111111111111111111
		0000000000000000000000002222222222222222222222222222222222222222
		2222222222222222222222222222222222222222222222222222222222222222
		0000000000000000000000003333333333333333333333333333333333333333
		4444444444444444444444444444444444444444444444444444444444444444
	"
}

// comprehensive test
test_encode_decode! {
	name: comprehensive_test,
	types: [
		ParamType::Int(32),
		ParamType::Bytes,
		ParamType::Int(32),
		ParamType::Bytes,
	],
	tokens: {
		let bytes = hex!("
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
			131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		").to_vec();
		[
			Token::Int(5.into()),
			Token::Bytes(bytes.clone()),
			Token::Int(3.into()),
			Token::Bytes(bytes),
		]
	},
	data: "
		0000000000000000000000000000000000000000000000000000000000000005
		0000000000000000000000000000000000000000000000000000000000000080
		0000000000000000000000000000000000000000000000000000000000000003
		00000000000000000000000000000000000000000000000000000000000000e0
		0000000000000000000000000000000000000000000000000000000000000040
		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		0000000000000000000000000000000000000000000000000000000000000040
		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b"
}
test_encode_decode! {
	name: comprehensive_test2,
	types: [
		ParamType::Int(32),
		ParamType::String,
		ParamType::Int(32),
		ParamType::Int(32),
		ParamType::Int(32),
		ParamType::Array(Box::new(ParamType::Int(32))),
	],
	tokens: [
		Token::Int(1.into()),
		Token::String("gavofyork".to_owned()),
		Token::Int(2.into()),
		Token::Int(3.into()),
		Token::Int(4.into()),
		Token::Array(vec![
			Token::Int(5.into()),
			Token::Int(6.into()),
			Token::Int(7.into()),
		])
	],
	data: "
		0000000000000000000000000000000000000000000000000000000000000001
		00000000000000000000000000000000000000000000000000000000000000c0
		0000000000000000000000000000000000000000000000000000000000000002
		0000000000000000000000000000000000000000000000000000000000000003
		0000000000000000000000000000000000000000000000000000000000000004
		0000000000000000000000000000000000000000000000000000000000000100
		0000000000000000000000000000000000000000000000000000000000000009
		6761766f66796f726b0000000000000000000000000000000000000000000000
		0000000000000000000000000000000000000000000000000000000000000003
		0000000000000000000000000000000000000000000000000000000000000005
		0000000000000000000000000000000000000000000000000000000000000006
		0000000000000000000000000000000000000000000000000000000000000007"
}

-- file: ethabi/src/filter.rs --
// Copyright 2015-2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::ops;

#[cfg(feature = "serde")]
use serde::{Serialize, Serializer};

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{Hash, Token};

/// Raw topic filter.
#[derive(Debug, PartialEq, Default)]
pub struct RawTopicFilter {
	/// Topic.
	pub topic0: Topic<Token>,
	/// Topic.
	pub topic1: Topic<Token>,
	/// Topic.
	pub topic2: Topic<Token>,
}

/// Topic filter.
#[derive(Debug, PartialEq, Eq, Default)]
pub struct TopicFilter {
	/// Usually (for not-anonymous transactions) the first topic is event signature.
	pub topic0: Topic<Hash>,
	/// Second topic.
	pub topic1: Topic<Hash>,
	/// Third topic.
	pub topic2: Topic<Hash>,
	/// Fourth topic.
	pub topic3: Topic<Hash>,
}

#[cfg(feature = "serde")]
impl Serialize for TopicFilter {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		vec![&self.topic0, &self.topic1, &self.topic2, &self.topic3].serialize(serializer)
	}
}

/// Acceptable topic possibilities.
#[derive(Debug, PartialEq, Eq)]
pub enum Topic<T> {
	/// Match any.
	Any,
	/// Match any of the hashes.
	OneOf(Vec<T>),
	/// Match only this hash.
	This(T),
}

impl<T> Topic<T> {
	/// Map
	pub fn map<F, O>(self, f: F) -> Topic<O>
	where
		F: Fn(T) -> O,
	{
		match self {
			Topic::Any => Topic::Any,
			Topic::OneOf(topics) => Topic::OneOf(topics.into_iter().map(f).collect()),
			Topic::This(topic) => Topic::This(f(topic)),
		}
	}

	/// Returns true if topic is empty (Topic::Any)
	pub fn is_any(&self) -> bool {
		match *self {
			Topic::Any => true,
			Topic::This(_) | Topic::OneOf(_) => false,
		}
	}
}

impl<T> Default for Topic<T> {
	fn default() -> Self {
		Topic::Any
	}
}

impl<T> From<Option<T>> for Topic<T> {
	fn from(o: Option<T>) -> Self {
		match o {
			Some(topic) => Topic::This(topic),
			None => Topic::Any,
		}
	}
}

impl<T> From<T> for Topic<T> {
	fn from(topic: T) -> Self {
		Topic::This(topic)
	}
}

impl<T> From<Vec<T>> for Topic<T> {
	fn from(topics: Vec<T>) -> Self {
		Topic::OneOf(topics)
	}
}

impl<T> From<Topic<T>> for Vec<T> {
	fn from(topic: Topic<T>) -> Self {
		match topic {
			Topic::Any => vec![],
			Topic::This(topic) => vec![topic],
			Topic::OneOf(topics) => topics,
		}
	}
}

#[cfg(feature = "serde")]
impl Serialize for Topic<Hash> {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		match *self {
			Topic::Any => Option::<()>::None.serialize(serializer),
			Topic::OneOf(ref vec) => vec.serialize(serializer),
			Topic::This(ref hash) => hash.serialize(serializer),
		}
	}
}

impl<T> ops::Index<usize> for Topic<T> {
	type Output = T;

	fn index(&self, index: usize) -> &Self::Output {
		match *self {
			Topic::Any => panic!("Topic unavailable"),
			Topic::This(ref topic) => {
				if index != 0 {
					panic!("Topic unavailable");
				}
				topic
			}
			Topic::OneOf(ref topics) => topics.index(index),
		}
	}
}

#[cfg(test)]
mod tests {
	use super::Topic;
	#[cfg(feature = "serde")]
	use super::TopicFilter;
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	#[cfg(feature = "serde")]
	use crate::Hash;

	#[cfg(feature = "serde")]
	fn hash(s: &'static str) -> Hash {
		s.parse().unwrap()
	}

	#[cfg(feature = "serde")]
	#[test]
	fn test_topic_filter_serialization() {
		let expected = r#"["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",null,["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b","0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"],null]"#;

		let topic = TopicFilter {
			topic0: Topic::This(hash("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b")),
			topic1: Topic::Any,
			topic2: Topic::OneOf(vec![
				hash("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
				hash("0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"),
			]),
			topic3: Topic::Any,
		};

		let topic_str = serde_json::to_string(&topic).unwrap();
		assert_eq!(expected, &topic_str);
	}

	#[test]
	fn test_topic_from() {
		assert_eq!(Topic::Any as Topic<u64>, None.into());
		assert_eq!(Topic::This(10u64), 10u64.into());
		assert_eq!(Topic::OneOf(vec![10u64, 20]), vec![10u64, 20].into());
	}

	#[test]
	fn test_topic_into_vec() {
		let expected: Vec<u64> = vec![];
		let is: Vec<u64> = (Topic::Any as Topic<u64>).into();
		assert_eq!(expected, is);
		let expected: Vec<u64> = vec![10];
		let is: Vec<u64> = Topic::This(10u64).into();
		assert_eq!(expected, is);
		let expected: Vec<u64> = vec![10, 20];
		let is: Vec<u64> = Topic::OneOf(vec![10u64, 20]).into();
		assert_eq!(expected, is);
	}

	#[test]
	fn test_topic_is_any() {
		assert!((Topic::Any as Topic<u8>).is_any());
		assert!(!Topic::OneOf(vec![10u64, 20]).is_any());
		assert!(!Topic::This(10u64).is_any());
	}

	#[test]
	fn test_topic_index() {
		assert_eq!(Topic::OneOf(vec![10u64, 20])[0], 10);
		assert_eq!(Topic::OneOf(vec![10u64, 20])[1], 20);
		assert_eq!(Topic::This(10u64)[0], 10);
	}

	#[test]
	#[should_panic(expected = "Topic unavailable")]
	fn test_topic_index_panic() {
		let _ = (Topic::Any as Topic<u8>)[0];
	}

	#[test]
	#[should_panic(expected = "Topic unavailable")]
	fn test_topic_index_panic2() {
		assert_eq!(Topic::This(10u64)[1], 10);
	}
}

-- file: ethabi/src/tuple_param.rs --
// Copyright 2020 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tuple param type.

#[cfg(not(feature = "std"))]
use crate::no_std_prelude::*;
use crate::{param_type::Writer, ParamType};
use core::fmt;
use serde::{
	de::{Error, MapAccess, Visitor},
	ser::SerializeMap,
	Deserialize, Deserializer, Serialize, Serializer,
};

/// Tuple params specification
#[derive(Debug, Clone, PartialEq)]
pub struct TupleParam {
	/// Param name.
	pub name: Option<String>,

	/// Param type.
	pub kind: ParamType,

	/// Additional Internal type.
	pub internal_type: Option<String>,
}

impl<'a> Deserialize<'a> for TupleParam {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: Deserializer<'a>,
	{
		deserializer.deserialize_any(TupleParamVisitor)
	}
}

struct TupleParamVisitor;

impl<'a> Visitor<'a> for TupleParamVisitor {
	type Value = TupleParam;

	fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
		write!(formatter, "a valid tuple parameter spec")
	}

	fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
	where
		A: MapAccess<'a>,
	{
		let mut name = None;
		let mut kind = None;
		let mut components = None;
		let mut internal_type = None;

		while let Some(ref key) = map.next_key::<String>()? {
			match key.as_ref() {
				"name" => {
					if name.is_some() {
						return Err(Error::duplicate_field("name"));
					}
					name = Some(map.next_value()?);
				}
				"type" => {
					if kind.is_some() {
						return Err(Error::duplicate_field("type"));
					}
					kind = Some(map.next_value()?);
				}
				"internalType" => {
					if internal_type.is_some() {
						return Err(Error::duplicate_field("internalType"));
					}
					internal_type = Some(map.next_value()?);
				}
				"components" => {
					if components.is_some() {
						return Err(Error::duplicate_field("components"));
					}
					let component: Vec<TupleParam> = map.next_value()?;
					components = Some(component)
				}
				_ => {}
			}
		}

		let mut kind = kind.ok_or_else(|| Error::missing_field("kind"))?;
		crate::param::set_tuple_components(&mut kind, components)?;
		Ok(TupleParam { name, kind, internal_type })
	}
}

impl Serialize for TupleParam {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let mut map = serializer.serialize_map(None)?;
		if let Some(ref internal_type) = self.internal_type {
			map.serialize_entry("internalType", internal_type)?;
		}
		if let Some(name) = &self.name {
			map.serialize_entry("name", name)?;
		}
		map.serialize_entry("type", &Writer::write_for_abi(&self.kind, false))?;
		if let Some(inner_tuple) = crate::param::inner_tuple(&self.kind) {
			map.serialize_key("components")?;
			map.serialize_value(&crate::param::SerializeableParamVec(inner_tuple))?;
		}
		map.end()
	}
}

#[cfg(test)]
mod tests {
	#[cfg(not(feature = "std"))]
	use crate::no_std_prelude::*;
	use crate::{
		tests::{assert_json_eq, assert_ser_de},
		ParamType, TupleParam,
	};

	#[test]
	fn param_simple() {
		let s = r#"{
			"name": "foo",
			"type": "address"
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam { name: Some("foo".to_owned()), kind: ParamType::Address, internal_type: None }
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_internal_type() {
		let s = r#"{
		 	"internalType": "struct Verifier.Proof",
			"name": "foo",
			"type": "address"
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: Some("foo".to_owned()),
				kind: ParamType::Address,
				internal_type: Some("struct Verifier.Proof".to_string())
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_unnamed() {
		let s = r#"{
			"type": "address"
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(deserialized, TupleParam { name: None, kind: ParamType::Address, internal_type: None });

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple() {
		let s = r#"{
			"type": "tuple",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "tuple",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_named() {
		let s = r#"{
			"type": "tuple",
			"components": [
				{
					"name": "amount",
					"type": "uint48"
				},
				{
					"name": "things",
					"type": "tuple",
					"components": [
						{
							"name": "baseTupleParam",
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Tuple(vec![ParamType::Address])]),
				internal_type: None
			}
		);

		assert_ser_de(&deserialized);
	}

	#[test]
	fn param_tuple_array() {
		let s = r#"{
			"type": "tuple[]",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "address"
				},
				{
					"type": "address"
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::Array(Box::new(ParamType::Tuple(vec![
					ParamType::Uint(48),
					ParamType::Address,
					ParamType::Address
				]))),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_array_of_array_of_tuple() {
		let s = r#"{
			"type": "tuple[][]",
			"components": [
				{
					"type": "uint8"
				},
				{
					"type": "uint16"
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();
		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::Array(Box::new(ParamType::Array(Box::new(ParamType::Tuple(vec![
					ParamType::Uint(8),
					ParamType::Uint(16),
				]))))),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_fixed_array() {
		let s = r#"{
			"type": "tuple[2]",
			"components": [
				{
					"type": "uint48"
				},
				{
					"type": "address"
				},
				{
					"type": "address"
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::FixedArray(
					Box::new(ParamType::Tuple(vec![ParamType::Uint(48), ParamType::Address, ParamType::Address])),
					2
				),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}

	#[test]
	fn param_tuple_with_nested_tuple_arrays() {
		let s = r#"{
			"type": "tuple",
			"components": [
				{
					"type": "tuple[]",
					"components": [
						{
							"type": "address"
						}
					]
				},
				{
					"type": "tuple[42]",
					"components": [
						{
							"type": "address"
						}
					]
				}
			]
		}"#;

		let deserialized: TupleParam = serde_json::from_str(s).unwrap();

		assert_eq!(
			deserialized,
			TupleParam {
				name: None,
				kind: ParamType::Tuple(vec![
					ParamType::Array(Box::new(ParamType::Tuple(vec![ParamType::Address]))),
					ParamType::FixedArray(Box::new(ParamType::Tuple(vec![ParamType::Address])), 42,)
				]),
				internal_type: None
			}
		);

		assert_json_eq(s, serde_json::to_string(&deserialized).unwrap().as_str());
	}
}


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment