use hex_literal::hex;
use primitive_types::{H160, U256};
use super::{AbiEncode, AbiType};
use crate::{types::*, AbiDecode};
pub fn to_lines(is_call: bool, data: impl AsRef<[u8]>) -> Vec<String> {
let mut data = data.as_ref();
let mut offset = 0;
let mut out = Vec::new();
if is_call {
offset += 4;
out.push(hex::encode(&data[..4]));
data = &data[4..];
}
assert!(data.len() % 32 == 0);
for _ in (offset..data.len()).step_by(32) {
let chunk = &data[..32];
out.push(hex::encode(chunk));
data = &data[32..];
}
out
}
fn test_impl<T>(function_identifier: u32, decoded_data: T, encoded_data: &[u8])
where
T: AbiEncode + AbiDecode + std::cmp::PartialEq + std::fmt::Debug,
{
let reencoded = decoded_data.abi_encode_call(BytesFixed(function_identifier.to_be_bytes()));
similar_asserts::assert_eq!(to_lines(true, encoded_data), to_lines(true, reencoded));
let (call, data) = T::abi_decode_call(encoded_data).unwrap();
assert_eq!(call.0, u32::to_be_bytes(function_identifier));
assert_eq!(data, decoded_data);
}
macro_rules! test_impl_uint {
($type:ident) => {
test_impl::<$type>(
0xdeadbeef,
255 as $type,
&hex!(
"
deadbeef
00000000000000000000000000000000000000000000000000000000000000ff
"
),
);
};
}
#[test]
fn encode_decode_uint8() {
test_impl_uint!(u8);
}
#[test]
fn encode_decode_uint32() {
test_impl_uint!(u32);
}
#[test]
fn encode_decode_uint128() {
test_impl_uint!(u128);
}
#[test]
fn encode_decode_uint256() {
test_impl::<U256>(
0xdeadbeef,
U256([255, 0, 0, 0]),
&hex!(
"
deadbeef
00000000000000000000000000000000000000000000000000000000000000ff
"
),
);
}
#[test]
fn encode_decode_string() {
test_impl::<(String,)>(
0xdeadbeef,
("some string".to_string(),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple_string() {
test_impl::<(String,)>(
0xdeadbeef,
("some string".to_string(),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_vec_tuple_address_uint256() {
test_impl::<(Vec<(Address, U256)>,)>(
0x1ACF2D55,
(vec![
(
H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),
U256([10, 0, 0, 0]),
),
(
H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),
U256([20, 0, 0, 0]),
),
(
H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),
U256([30, 0, 0, 0]),
),
],),
&hex!(
"
1ACF2D55
0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]
0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]
0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address
000000000000000000000000000000000000000000000000000000000000000A // uint256
000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address
0000000000000000000000000000000000000000000000000000000000000014 // uint256
0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address
000000000000000000000000000000000000000000000000000000000000001E // uint256
"
),
);
}
#[derive(Debug, PartialEq)]
struct TokenId(u32);
impl AbiType for TokenId {
const SIGNATURE: crate::custom_signature::SignatureUnit = u32::SIGNATURE;
const IS_DYNAMIC: bool = u32::IS_DYNAMIC;
const HEAD_WORDS: u32 = u32::HEAD_WORDS;
}
impl AbiDecode for TokenId {
fn dec(input: &mut crate::AbiDecoder<'_>) -> super::Result<Self> {
Ok(Self(u32::dec(input)?))
}
}
impl AbiEncode for TokenId {
fn enc(&self, out: &mut crate::AbiEncoder) {
self.0.enc(out)
}
}
impl From<u32> for TokenId {
fn from(value: u32) -> Self {
Self(value)
}
}
#[test]
fn encode_decode_vec_tuple_uint256_string() {
test_impl::<(Vec<(TokenId, String)>,)>(
0xdeadbeef,
(vec![
(14u32.into(), "Test URI 0".to_string()),
(11u32.into(), "Test URI 1".to_string()),
(12u32.into(), "Test URI 2".to_string()),
],),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]
0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]
0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem
00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem
0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem
000000000000000000000000000000000000000000000000000000000000000e // first token #60
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203000000000000000000000000000000000000000000000 // string
000000000000000000000000000000000000000000000000000000000000000b // second token #e0
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203100000000000000000000000000000000000000000000 // string
000000000000000000000000000000000000000000000000000000000000000c // third token #160
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203200000000000000000000000000000000000000000000 // string
"
),
);
}
#[test]
fn mint_sample() {
let (call, decoder) = <(Address, u32, String)>::abi_decode_call(&hex!(
"
50bb4e7f
000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000008
5465737420555249000000000000000000000000000000000000000000000000
"
))
.unwrap();
assert_eq!(call, BytesFixed(u32::to_be_bytes(0x50bb4e7f)));
assert_eq!(
format!("{:?}", decoder.0),
"0xad2c0954693c2b5404b7e50967d3481bea432374"
);
assert_eq!(decoder.1, 1);
assert_eq!(decoder.2, "Test URI");
}
#[test]
fn parse_vec_with_dynamic_type() {
let decoded_data = (
0x36543006,
vec![
(1.into(), "Test URI 0".to_string()),
(11.into(), "Test URI 1".to_string()),
(12.into(), "Test URI 2".to_string()),
],
);
let encoded_data = &hex!(
"
36543006
00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address
0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]
0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]
0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem
00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem
0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem
0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203000000000000000000000000000000000000000000000 // string
000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203100000000000000000000000000000000000000000000 // string
000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160
0000000000000000000000000000000000000000000000000000000000000040 // offset of string
000000000000000000000000000000000000000000000000000000000000000a // size of string
5465737420555249203200000000000000000000000000000000000000000000 // string
"
);
let (call, decoder) = <(Address, Vec<(U256, String)>)>::abi_decode_call(encoded_data).unwrap();
assert_eq!(call, BytesFixed(u32::to_be_bytes(decoded_data.0)));
assert_eq!(decoder.1, decoded_data.1);
let ed = (decoder.0, decoded_data.1).abi_encode_call(BytesFixed(decoded_data.0.to_be_bytes()));
similar_asserts::assert_eq!(encoded_data, ed.as_slice());
}
#[test]
fn encode_decode_vec_tuple_string_bytes() {
test_impl::<(Vec<(String, Bytes)>,)>(
0xdeadbeef,
(vec![
(
"Test URI 0".to_string(),
Bytes(vec![
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
]),
),
(
"Test URI 1".to_string(),
Bytes(vec![
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
]),
),
("Test URI 2".to_string(), Bytes(vec![0x33, 0x33])),
],),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000060 // 32
0000000000000000000000000000000000000000000000000000000000000140 // 96
0000000000000000000000000000000000000000000000000000000000000220 // 544
0000000000000000000000000000000000000000000000000000000000000040 // 32
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000000a // 64
5465737420555249203000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000030
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111100000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000040 // 96
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000000a
5465737420555249203100000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000002f
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222220000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000040 // 544
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000000a
5465737420555249203200000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000002
3333000000000000000000000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_tuple1_string_bytes_tuple1_uint8_bytes() {
let int = 0xff;
let by = Bytes(vec![0x11, 0x22, 0x33]);
let string = "some string".to_string();
test_impl::<(((u8,), (String, Bytes), (u8, Bytes)),)>(
0xdeadbeef,
(((int,), (string, by.clone()), (int, by)),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
00000000000000000000000000000000000000000000000000000000000000ff
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000120
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000003
1122330000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000ff
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000003
1122330000000000000000000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8_uint8_tuple1_uint8_uint8() {
test_impl::<((u8,), (u8, u8), (u8, u8))>(
0xdeadbeef,
((43,), (44, 45), (46, 47)),
&hex!(
"
deadbeef
000000000000000000000000000000000000000000000000000000000000002b
000000000000000000000000000000000000000000000000000000000000002c
000000000000000000000000000000000000000000000000000000000000002d
000000000000000000000000000000000000000000000000000000000000002e
000000000000000000000000000000000000000000000000000000000000002f
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8() {
test_impl::<((u8,), (u8,))>(
0xdeadbeef,
((43,), (44,)),
&hex!(
"
deadbeef
000000000000000000000000000000000000000000000000000000000000002b
000000000000000000000000000000000000000000000000000000000000002c
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_uint8() {
test_impl::<((u8, u8),)>(
0xdeadbeef,
((43, 44),),
&hex!(
"
deadbeef
000000000000000000000000000000000000000000000000000000000000002b
000000000000000000000000000000000000000000000000000000000000002c
"
),
);
}
#[test]
fn encode_decode_tuple_uint8_uint8() {
test_impl::<(u8, u8)>(
0xdeadbeef,
(43, 44),
&hex!(
"
deadbeef
000000000000000000000000000000000000000000000000000000000000002b
000000000000000000000000000000000000000000000000000000000000002c
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_uint8_tuple1_uint8_uint8_and_uint8() {
test_impl::<((u8, u8), (u8, u8), u8)>(
0xdeadbeef,
((10, 11), (12, 13), 14),
&hex!(
"
deadbeef
000000000000000000000000000000000000000000000000000000000000000a
000000000000000000000000000000000000000000000000000000000000000b
000000000000000000000000000000000000000000000000000000000000000c
000000000000000000000000000000000000000000000000000000000000000d
000000000000000000000000000000000000000000000000000000000000000e
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_string() {
test_impl::<(((String,),),)>(
0xdeadbeef,
((("some string".to_string(),),),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000020
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_string() {
test_impl::<(((u8, String),),)>(
0xdeadbeef,
(((0xff, "some string".to_string()),),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000020
00000000000000000000000000000000000000000000000000000000000000ff
0000000000000000000000000000000000000000000000000000000000000040
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_string_bytes() {
test_impl::<((String, Bytes),)>(
0xdeadbeef,
(("some string".to_string(), Bytes(vec![1, 2, 3])),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000003
0102030000000000000000000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_tuple0_tuple1_uint8_tuple1_string() {
test_impl::<(((u8,), (String,)),)>(
0xdeadbeef,
(((0xff,), ("some string".to_string(),)),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
00000000000000000000000000000000000000000000000000000000000000ff
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000020
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_option_uint8_some() {
test_impl::<Option<u8>>(
0xdeadbeef,
Some(44),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000001
000000000000000000000000000000000000000000000000000000000000002c
"
),
);
}
#[test]
fn encode_decode_option_uint8_none() {
test_impl::<Option<u8>>(
0xdeadbeef,
None,
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_option_string_some() {
test_impl::<(Option<String>,)>(
0xdeadbeef,
(Some("some string".to_string()),),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000040
000000000000000000000000000000000000000000000000000000000000000b
736f6d6520737472696e67000000000000000000000000000000000000000000
"
),
);
}
#[test]
fn encode_decode_option_string_none() {
test_impl::<(Option<String>,)>(
0xdeadbeef,
(None,),
&hex!(
"
deadbeef
0000000000000000000000000000000000000000000000000000000000000020 // Offset of option
0000000000000000000000000000000000000000000000000000000000000000 // Option value
0000000000000000000000000000000000000000000000000000000000000040 // Offset of string from option
0000000000000000000000000000000000000000000000000000000000000000
"
),
);
}