// Copyright 2015-2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use ethabi_decode::{decode, ParamKind, Token, U256}; use hex_literal::hex; use paste; macro_rules! test_encode_decode { (name: $name:tt, types: $types:expr, tokens: $tokens:expr, data: $data:tt) => { paste::item! { #[test] fn []() { 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: [ParamKind::Address], tokens: [Token::Address([0x11u8; 20].into())], data: "0000000000000000000000001111111111111111111111111111111111111111" } test_encode_decode! { name: addresses, types: [ ParamKind::Address, ParamKind::Address ], tokens: [ Token::Address([0x11u8; 20].into()), Token::Address([0x22u8; 20].into()) ], data: " 0000000000000000000000001111111111111111111111111111111111111111 0000000000000000000000002222222222222222222222222222222222222222" } // test bytes test_encode_decode! { name: bytes, types: [ParamKind::Bytes], tokens: [Token::Bytes(vec![0x12, 0x34])], data: " 0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000002 1234000000000000000000000000000000000000000000000000000000000000" } test_encode_decode! { name: bytes2, types: [ParamKind::Bytes], tokens: [Token::Bytes(hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec())], data: " 0000000000000000000000000000000000000000000000000000000000000020 000000000000000000000000000000000000000000000000000000000000001f 1000000000000000000000000000000000000000000000000000000000000200" } test_encode_decode! { name: bytes3, types: [ParamKind::Bytes], tokens: [ Token::Bytes(hex!(" 1000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 ").to_vec()) ], data: " 0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000040 1000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000" } test_encode_decode! { name: two_bytes, types: [ParamKind::Bytes, ParamKind::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: [ParamKind::Int(32)], tokens: [Token::Int(U256::from_big_endian(&[0x11u8; 32]))], data: "1111111111111111111111111111111111111111111111111111111111111111" } test_encode_decode! { name: int2, types: [ParamKind::Int(32)], tokens: { let mut int = [0u8; 32]; int[31] = 4; [Token::Int(U256::from_big_endian(&int))] }, data: "0000000000000000000000000000000000000000000000000000000000000004" } // test uint test_encode_decode! { name: uint, types: [ParamKind::Uint(32)], tokens: [Token::Uint(U256::from_big_endian(&[0x11u8; 32]))], data: "1111111111111111111111111111111111111111111111111111111111111111" } test_encode_decode! { name: uint2, types: [ParamKind::Uint(32)], tokens: { let mut uint = [0u8; 32]; uint[31] = 4; [Token::Uint(U256::from_big_endian(&uint))] }, data: "0000000000000000000000000000000000000000000000000000000000000004" } // test bool test_encode_decode! { name: bool, types: [ParamKind::Bool], tokens: [Token::Bool(true)], data: "0000000000000000000000000000000000000000000000000000000000000001" } test_encode_decode! { name: bool2, types: [ParamKind::Bool], tokens: [Token::Bool(false)], data: "0000000000000000000000000000000000000000000000000000000000000000" } // test string test_encode_decode! { name: string, types: [ParamKind::String], tokens: [Token::String("gavofyork".as_bytes().to_vec())], data: " 0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000009 6761766f66796f726b0000000000000000000000000000000000000000000000" } // test array test_encode_decode! { name: dynamic_array_of_addresses, types: [ParamKind::Array(Box::new(ParamKind::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: [ ParamKind::Array(Box::new( ParamKind::FixedArray(Box::new(ParamKind::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: [ ParamKind::Array(Box::new( ParamKind::FixedArray(Box::new(ParamKind::Array(Box::new(ParamKind::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: [ ParamKind::Array(Box::new( ParamKind::Array(Box::new(ParamKind::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: [ ParamKind::Array(Box::new( ParamKind::Array(Box::new(ParamKind::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: [ParamKind::Array(Box::new(ParamKind::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: [ParamKind::Array(Box::new(ParamKind::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: [ParamKind::Array(Box::new(ParamKind::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: [ ParamKind::Array(Box::new(ParamKind::Bool)), ParamKind::Array(Box::new(ParamKind::Bool)), ], tokens: [ Token::Array(vec![]), Token::Array(vec![]) ], data: " 0000000000000000000000000000000000000000000000000000000000000040 0000000000000000000000000000000000000000000000000000000000000060 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000" } test_encode_decode! { name: dynamic_array_of_empty_dynamic_array, types: [ ParamKind::Array(Box::new(ParamKind::Array(Box::new(ParamKind::Bool)))), ParamKind::Array(Box::new(ParamKind::Array(Box::new(ParamKind::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: [ParamKind::FixedArray(Box::new(ParamKind::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_fixed_arrays, types: [ ParamKind::FixedArray( Box::new(ParamKind::FixedArray(Box::new(ParamKind::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: [ ParamKind::FixedArray( Box::new(ParamKind::Array(Box::new(ParamKind::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: [ParamKind::FixedBytes(2)], tokens: [Token::FixedBytes(vec![0x12, 0x34])], data: "1234000000000000000000000000000000000000000000000000000000000000" } // comprehensive test test_encode_decode! { name: comprehensive_test, types: [ ParamKind::Int(32), ParamKind::Bytes, ParamKind::Int(32), ParamKind::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: [ ParamKind::Int(32), ParamKind::String, ParamKind::Int(32), ParamKind::Int(32), ParamKind::Int(32), ParamKind::Array(Box::new(ParamKind::Int(32))), ], tokens: [ Token::Int(1.into()), Token::String("gavofyork".as_bytes().to_vec()), 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" }