12345678910111213141516171819#![allow(dead_code)]2021#[cfg(not(feature = "std"))]22use alloc::vec::Vec;23use evm_core::ExitError;24use primitive_types::{H160, U256};2526use crate::{27 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},28 types::*,29 make_signature,30 custom_signature::{SignatureUnit},31};32use crate::execution::Result;3334const ABI_ALIGNMENT: usize = 32;3536trait TypeHelper {37 38 fn is_dynamic() -> bool;3940 41 fn size() -> usize;42}434445#[derive(Clone)]46pub struct AbiReader<'i> {47 buf: &'i [u8],48 subresult_offset: usize,49 offset: usize,50}51impl<'i> AbiReader<'i> {52 53 pub fn new(buf: &'i [u8]) -> Self {54 Self {55 buf,56 subresult_offset: 0,57 offset: 0,58 }59 }60 61 pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {62 if buf.len() < 4 {63 return Err(Error::Error(ExitError::OutOfOffset));64 }65 let mut method_id = [0; 4];66 method_id.copy_from_slice(&buf[0..4]);6768 Ok((69 method_id,70 Self {71 buf,72 subresult_offset: 4,73 offset: 4,74 },75 ))76 }7778 fn read_pad<const S: usize>(79 buf: &[u8],80 offset: usize,81 pad_start: usize,82 pad_size: usize,83 block_start: usize,84 block_size: usize,85 ) -> Result<[u8; S]> {86 if buf.len() - offset < ABI_ALIGNMENT {87 return Err(Error::Error(ExitError::OutOfOffset));88 }89 let mut block = [0; S];90 let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0);91 if !is_pad_zeroed {92 return Err(Error::Error(ExitError::InvalidRange));93 }94 block.copy_from_slice(&buf[block_start..block_size]);95 Ok(block)96 }9798 fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {99 let offset = self.offset;100 self.offset += ABI_ALIGNMENT;101 Self::read_pad(102 self.buf,103 offset,104 offset,105 offset + ABI_ALIGNMENT - S,106 offset + ABI_ALIGNMENT - S,107 offset + ABI_ALIGNMENT,108 )109 }110111 fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {112 let offset = self.offset;113 self.offset += ABI_ALIGNMENT;114 Self::read_pad(115 self.buf,116 offset,117 offset + S,118 offset + ABI_ALIGNMENT,119 offset,120 offset + S,121 )122 }123124 125 pub fn address(&mut self) -> Result<H160> {126 Ok(H160(self.read_padleft()?))127 }128129 130 pub fn bool(&mut self) -> Result<bool> {131 let data: [u8; 1] = self.read_padleft()?;132 match data[0] {133 0 => Ok(false),134 1 => Ok(true),135 _ => Err(Error::Error(ExitError::InvalidRange)),136 }137 }138139 140 pub fn bytes4(&mut self) -> Result<[u8; 4]> {141 self.read_padright()142 }143144 145 pub fn bytes(&mut self) -> Result<Vec<u8>> {146 let mut subresult = self.subresult(None)?;147 let length = subresult.uint32()? as usize;148 if subresult.buf.len() < subresult.offset + length {149 return Err(Error::Error(ExitError::OutOfOffset));150 }151 Ok(subresult.buf[subresult.offset..subresult.offset + length].into())152 }153154 155 pub fn string(&mut self) -> Result<string> {156 string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))157 }158159 160 pub fn uint8(&mut self) -> Result<u8> {161 Ok(self.read_padleft::<1>()?[0])162 }163164 165 pub fn uint32(&mut self) -> Result<u32> {166 Ok(u32::from_be_bytes(self.read_padleft()?))167 }168169 170 pub fn uint128(&mut self) -> Result<u128> {171 Ok(u128::from_be_bytes(self.read_padleft()?))172 }173174 175 pub fn uint256(&mut self) -> Result<U256> {176 let buf: [u8; 32] = self.read_padleft()?;177 Ok(U256::from_big_endian(&buf))178 }179180 181 pub fn uint64(&mut self) -> Result<u64> {182 Ok(u64::from_be_bytes(self.read_padleft()?))183 }184185 186 #[deprecated = "dangerous, as usize may have different width in wasm and native execution"]187 pub fn read_usize(&mut self) -> Result<usize> {188 Ok(usize::from_be_bytes(self.read_padleft()?))189 }190191 192 193 fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {194 let subresult_offset = self.subresult_offset;195 let offset = if let Some(size) = size {196 self.offset += size;197 self.subresult_offset += size;198 0199 } else {200 self.uint32()? as usize201 };202203 if offset + self.subresult_offset > self.buf.len() {204 return Err(Error::Error(ExitError::InvalidRange));205 }206207 let new_offset = offset + subresult_offset;208 Ok(AbiReader {209 buf: self.buf,210 subresult_offset: new_offset,211 offset: new_offset,212 })213 }214215 216 pub fn is_finished(&self) -> bool {217 self.buf.len() == self.offset218 }219}220221222#[derive(Default)]223pub struct AbiWriter {224 static_part: Vec<u8>,225 dynamic_part: Vec<(usize, AbiWriter)>,226 had_call: bool,227 is_dynamic: bool,228}229impl AbiWriter {230 231 pub fn new() -> Self {232 Self::default()233 }234235 236 pub fn new_dynamic(is_dynamic: bool) -> Self {237 Self {238 is_dynamic,239 ..Default::default()240 }241 }242 243 pub fn new_call(method_id: u32) -> Self {244 let mut val = Self::new();245 val.static_part.extend(&method_id.to_be_bytes());246 val.had_call = true;247 val248 }249250 fn write_padleft(&mut self, block: &[u8]) {251 assert!(block.len() <= ABI_ALIGNMENT);252 self.static_part253 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);254 self.static_part.extend(block);255 }256257 fn write_padright(&mut self, block: &[u8]) {258 assert!(block.len() <= ABI_ALIGNMENT);259 self.static_part.extend(block);260 self.static_part261 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);262 }263264 265 pub fn address(&mut self, address: &H160) {266 self.write_padleft(&address.0)267 }268269 270 pub fn bool(&mut self, value: &bool) {271 self.write_padleft(&[if *value { 1 } else { 0 }])272 }273274 275 pub fn uint8(&mut self, value: &u8) {276 self.write_padleft(&[*value])277 }278279 280 pub fn uint32(&mut self, value: &u32) {281 self.write_padleft(&u32::to_be_bytes(*value))282 }283284 285 pub fn uint128(&mut self, value: &u128) {286 self.write_padleft(&u128::to_be_bytes(*value))287 }288289 290 pub fn uint256(&mut self, value: &U256) {291 let mut out = [0; 32];292 value.to_big_endian(&mut out);293 self.write_padleft(&out)294 }295296 297 #[deprecated = "dangerous, as usize may have different width in wasm and native execution"]298 pub fn write_usize(&mut self, value: &usize) {299 self.write_padleft(&usize::to_be_bytes(*value))300 }301302 303 pub fn write_subresult(&mut self, result: Self) {304 self.dynamic_part.push((self.static_part.len(), result));305 306 self.write_padleft(&[]);307 }308309 fn memory(&mut self, value: &[u8]) {310 let mut sub = Self::new();311 sub.uint32(&(value.len() as u32));312 for chunk in value.chunks(ABI_ALIGNMENT) {313 sub.write_padright(chunk);314 }315 self.write_subresult(sub);316 }317318 319 pub fn string(&mut self, value: &str) {320 self.memory(value.as_bytes())321 }322323 324 pub fn bytes(&mut self, value: &[u8]) {325 self.memory(value)326 }327328 329 pub fn finish(mut self) -> Vec<u8> {330 for (static_offset, part) in self.dynamic_part {331 let part_offset = self.static_part.len()332 - if self.had_call { 4 } else { 0 }333 - if self.is_dynamic { ABI_ALIGNMENT } else { 0 };334335 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);336 let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();337 let stop = static_offset + ABI_ALIGNMENT;338 self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);339 self.static_part.extend(part.finish())340 }341 self.static_part342 }343}344345346pub trait AbiRead {347 348 fn abi_read(reader: &mut AbiReader) -> Result<Self>349 where350 Self: Sized;351}352353macro_rules! impl_abi_readable {354 ($ty:ty, $method:ident, $dynamic:literal) => {355 impl sealed::CanBePlacedInVec for $ty {}356357 impl TypeHelper for $ty {358 fn is_dynamic() -> bool {359 $dynamic360 }361362 fn size() -> usize {363 ABI_ALIGNMENT364 }365 }366367 impl AbiRead for $ty {368 fn abi_read(reader: &mut AbiReader) -> Result<$ty> {369 reader.$method()370 }371 }372 };373}374375impl_abi_readable!(bool, bool, false);376impl_abi_readable!(uint32, uint32, false);377impl_abi_readable!(uint64, uint64, false);378impl_abi_readable!(uint128, uint128, false);379impl_abi_readable!(uint256, uint256, false);380impl_abi_readable!(bytes4, bytes4, false);381impl_abi_readable!(address, address, false);382impl_abi_readable!(string, string, true);383384impl TypeHelper for uint8 {385 fn is_dynamic() -> bool {386 false387 }388 fn size() -> usize {389 ABI_ALIGNMENT390 }391}392impl AbiRead for uint8 {393 fn abi_read(reader: &mut AbiReader) -> Result<uint8> {394 reader.uint8()395 }396}397398impl TypeHelper for bytes {399 fn is_dynamic() -> bool {400 true401 }402 fn size() -> usize {403 ABI_ALIGNMENT404 }405}406impl AbiRead for bytes {407 fn abi_read(reader: &mut AbiReader) -> Result<bytes> {408 Ok(bytes(reader.bytes()?))409 }410}411412mod sealed {413 414 pub trait CanBePlacedInVec {}415}416417impl<R: AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {418 fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {419 let mut sub = reader.subresult(None)?;420 let size = sub.uint32()? as usize;421 sub.subresult_offset = sub.offset;422 let mut out = Vec::with_capacity(size);423 for _ in 0..size {424 out.push(<R>::abi_read(&mut sub)?);425 }426 Ok(out)427 }428}429430impl<R: Signature> Signature for Vec<R> {431 const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));432}433434impl sealed::CanBePlacedInVec for EthCrossAccount {}435436impl TypeHelper for EthCrossAccount {437 fn is_dynamic() -> bool {438 address::is_dynamic() || uint256::is_dynamic()439 }440441 fn size() -> usize {442 <address as TypeHelper>::size() + <uint256 as TypeHelper>::size()443 }444}445446impl AbiRead for EthCrossAccount {447 fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {448 let size = if !EthCrossAccount::is_dynamic() {449 Some(<EthCrossAccount as TypeHelper>::size())450 } else {451 None452 };453 let mut subresult = reader.subresult(size)?;454 let eth = <address>::abi_read(&mut subresult)?;455 let sub = <uint256>::abi_read(&mut subresult)?;456457 Ok(EthCrossAccount { eth, sub })458 }459}460461impl AbiWrite for EthCrossAccount {462 fn abi_write(&self, writer: &mut AbiWriter) {463 self.eth.abi_write(writer);464 self.sub.abi_write(writer);465 }466}467468macro_rules! impl_tuples {469 ($($ident:ident)+) => {470 impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)471 where472 $(473 $ident: TypeHelper,474 )+475 {476 fn is_dynamic() -> bool {477 false478 $(479 || <$ident>::is_dynamic()480 )*481 }482483 fn size() -> usize {484 0 $(+ <$ident>::size())+485 }486 }487488 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}489490 impl<$($ident),+> AbiRead for ($($ident,)+)491 where492 $($ident: AbiRead,)+493 ($($ident,)+): TypeHelper,494 {495 fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {496 let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };497 let mut subresult = reader.subresult(size)?;498 Ok((499 $(<$ident>::abi_read(&mut subresult)?,)+500 ))501 }502 }503504 #[allow(non_snake_case)]505 impl<$($ident),+> AbiWrite for ($($ident,)+)506 where507 $($ident: AbiWrite,)+508 {509 fn abi_write(&self, writer: &mut AbiWriter) {510 let ($($ident,)+) = self;511 if writer.is_dynamic {512 let mut sub = AbiWriter::new();513 $($ident.abi_write(&mut sub);)+514 writer.write_subresult(sub);515 } else {516 $($ident.abi_write(writer);)+517 }518 }519 }520521 impl<$($ident),+> Signature for ($($ident,)+)522 where523 $($ident: Signature,)+524 {525 const SIGNATURE: SignatureUnit = make_signature!(526 new fixed("(")527 $(nameof(<$ident>::SIGNATURE) fixed(","))+528 shift_left(1)529 fixed(")")530 );531 }532 };533}534535impl_tuples! {A}536impl_tuples! {A B}537impl_tuples! {A B C}538impl_tuples! {A B C D}539impl_tuples! {A B C D E}540impl_tuples! {A B C D E F}541impl_tuples! {A B C D E F G}542impl_tuples! {A B C D E F G H}543impl_tuples! {A B C D E F G H I}544impl_tuples! {A B C D E F G H I J}545546547548pub trait AbiWrite {549 550 fn abi_write(&self, writer: &mut AbiWriter);551 552 553 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {554 let mut writer = AbiWriter::new();555 self.abi_write(&mut writer);556 Ok(writer.into())557 }558}559560561562563564impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {565 fn abi_write(&self, _writer: &mut AbiWriter) {566 debug_assert!(false, "shouldn't be called, see comment")567 }568 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {569 match self {570 Ok(v) => Ok(WithPostDispatchInfo {571 post_info: v.post_info.clone(),572 data: {573 let mut out = AbiWriter::new();574 v.data.abi_write(&mut out);575 out576 },577 }),578 Err(e) => Err(e.clone()),579 }580 }581}582583macro_rules! impl_abi_writeable {584 ($ty:ty, $method:ident) => {585 impl AbiWrite for $ty {586 fn abi_write(&self, writer: &mut AbiWriter) {587 writer.$method(&self)588 }589 }590 };591}592593impl_abi_writeable!(u8, uint8);594impl_abi_writeable!(u32, uint32);595impl_abi_writeable!(u128, uint128);596impl_abi_writeable!(U256, uint256);597impl_abi_writeable!(H160, address);598impl_abi_writeable!(bool, bool);599impl_abi_writeable!(&str, string);600601impl AbiWrite for string {602 fn abi_write(&self, writer: &mut AbiWriter) {603 writer.string(self)604 }605}606607impl AbiWrite for bytes {608 fn abi_write(&self, writer: &mut AbiWriter) {609 writer.bytes(self.0.as_slice())610 }611}612613impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {614 fn abi_write(&self, writer: &mut AbiWriter) {615 let is_dynamic = T::is_dynamic();616 let mut sub = if is_dynamic {617 AbiWriter::new_dynamic(is_dynamic)618 } else {619 AbiWriter::new()620 };621622 623 (self.len() as u32).abi_write(&mut sub);624625 for item in self {626 item.abi_write(&mut sub);627 }628 writer.write_subresult(sub);629 }630}631632impl AbiWrite for () {633 fn abi_write(&self, _writer: &mut AbiWriter) {}634}635636637#[deprecated]638#[macro_export]639macro_rules! abi_decode {640 ($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {641 $(642 let $name = $reader.$typ()?;643 )+644 }645}646647648#[deprecated]649#[macro_export]650macro_rules! abi_encode {651 ($($typ:ident($value:expr)),* $(,)?) => {{652 #[allow(unused_mut)]653 let mut writer = ::evm_coder::abi::AbiWriter::new();654 $(655 writer.$typ($value);656 )*657 writer658 }};659 (call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{660 #[allow(unused_mut)]661 let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);662 $(663 writer.$typ($value);664 )*665 writer666 }}667}668669#[cfg(test)]670pub mod test {671 use crate::{672 abi::{AbiRead, AbiWrite},673 types::*,674 };675676 use super::{AbiReader, AbiWriter};677 use hex_literal::hex;678 use primitive_types::{H160, U256};679 use concat_idents::concat_idents;680681 macro_rules! test_impl {682 ($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => {683 concat_idents!(test_name = encode_decode_, $name {684 #[test]685 fn test_name() {686 let function_identifier: u32 = $function_identifier;687 let decoded_data = $decoded_data;688 let encoded_data = $encoded_data;689690 let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();691 assert_eq!(call, u32::to_be_bytes(function_identifier));692 let data = <$type>::abi_read(&mut decoder).unwrap();693 assert_eq!(data, decoded_data);694695 let mut writer = AbiWriter::new_call(function_identifier);696 decoded_data.abi_write(&mut writer);697 let ed = writer.finish();698 similar_asserts::assert_eq!(encoded_data, ed.as_slice());699 }700 });701 };702 }703704 macro_rules! test_impl_uint {705 ($type:ident) => {706 test_impl!(707 $type,708 $type,709 0xdeadbeef,710 255 as $type,711 &hex!(712 "713 deadbeef714 00000000000000000000000000000000000000000000000000000000000000ff715 "716 )717 );718 };719 }720721 test_impl_uint!(uint8);722 test_impl_uint!(uint32);723 test_impl_uint!(uint128);724725 test_impl!(726 uint256,727 uint256,728 0xdeadbeef,729 U256([255, 0, 0, 0]),730 &hex!(731 "732 deadbeef733 00000000000000000000000000000000000000000000000000000000000000ff734 "735 )736 );737738 test_impl!(739 vec_tuple_address_uint256,740 Vec<(address, uint256)>,741 0x1ACF2D55,742 vec![743 (744 H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),745 U256([10, 0, 0, 0]),746 ),747 (748 H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),749 U256([20, 0, 0, 0]),750 ),751 (752 H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),753 U256([30, 0, 0, 0]),754 ),755 ],756 &hex!(757 "758 1ACF2D55759 0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]760 0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]761762 0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address763 000000000000000000000000000000000000000000000000000000000000000A // uint256764765 000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address766 0000000000000000000000000000000000000000000000000000000000000014 // uint256767768 0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address769 000000000000000000000000000000000000000000000000000000000000001E // uint256770 "771 )772 );773774 test_impl!(775 vec_tuple_uint256_string,776 Vec<(uint256, string)>,777 0xdeadbeef,778 vec![779 (1.into(), "Test URI 0".to_string()),780 (11.into(), "Test URI 1".to_string()),781 (12.into(), "Test URI 2".to_string()),782 ],783 &hex!(784 "785 deadbeef786 0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]787 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]788789 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem790 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem791 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem792793 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60794 0000000000000000000000000000000000000000000000000000000000000040 // offset of string795 000000000000000000000000000000000000000000000000000000000000000a // size of string796 5465737420555249203000000000000000000000000000000000000000000000 // string797798 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0799 0000000000000000000000000000000000000000000000000000000000000040 // offset of string800 000000000000000000000000000000000000000000000000000000000000000a // size of string801 5465737420555249203100000000000000000000000000000000000000000000 // string802803 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160804 0000000000000000000000000000000000000000000000000000000000000040 // offset of string805 000000000000000000000000000000000000000000000000000000000000000a // size of string806 5465737420555249203200000000000000000000000000000000000000000000 // string807 "808 )809 );810811 test_impl!(812 vec_tuple_string_bytes,813 Vec<(string, bytes)>,814 0xdeadbeef,815 vec![816 (817 "Test URI 0".to_string(),818 bytes(vec![819 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,820 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,821 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,822 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11823 ])824 ),825 (826 "Test URI 1".to_string(),827 bytes(vec![828 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,829 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,830 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,831 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22832 ])833 ),834 ("Test URI 2".to_string(), bytes(vec![0x33, 0x33])),835 ],836 &hex!(837 "838 deadbeef839 0000000000000000000000000000000000000000000000000000000000000020840 0000000000000000000000000000000000000000000000000000000000000003841 842 0000000000000000000000000000000000000000000000000000000000000060843 0000000000000000000000000000000000000000000000000000000000000140844 0000000000000000000000000000000000000000000000000000000000000220845846 0000000000000000000000000000000000000000000000000000000000000040847 0000000000000000000000000000000000000000000000000000000000000080848 000000000000000000000000000000000000000000000000000000000000000a849 5465737420555249203000000000000000000000000000000000000000000000850 0000000000000000000000000000000000000000000000000000000000000030851 1111111111111111111111111111111111111111111111111111111111111111852 1111111111111111111111111111111100000000000000000000000000000000853854 0000000000000000000000000000000000000000000000000000000000000040855 0000000000000000000000000000000000000000000000000000000000000080856 000000000000000000000000000000000000000000000000000000000000000a857 5465737420555249203100000000000000000000000000000000000000000000858 000000000000000000000000000000000000000000000000000000000000002f859 2222222222222222222222222222222222222222222222222222222222222222860 2222222222222222222222222222220000000000000000000000000000000000861862 0000000000000000000000000000000000000000000000000000000000000040863 0000000000000000000000000000000000000000000000000000000000000080864 000000000000000000000000000000000000000000000000000000000000000a865 5465737420555249203200000000000000000000000000000000000000000000866 0000000000000000000000000000000000000000000000000000000000000002867 3333000000000000000000000000000000000000000000000000000000000000868 "869 )870 );871872 #[test]873 fn dynamic_after_static() {874 let mut encoder = AbiWriter::new();875 encoder.bool(&true);876 encoder.string("test");877 let encoded = encoder.finish();878879 let mut encoder = AbiWriter::new();880 encoder.bool(&true);881 882 encoder.uint32(&(32 * 2));883 884 encoder.uint32(&4);885 encoder.write_padright(&[b't', b'e', b's', b't']);886 let alternative_encoded = encoder.finish();887888 assert_eq!(encoded, alternative_encoded);889890 let mut decoder = AbiReader::new(&encoded);891 assert!(decoder.bool().unwrap());892 assert_eq!(decoder.string().unwrap(), "test");893 }894895 #[test]896 fn mint_sample() {897 let (call, mut decoder) = AbiReader::new_call(&hex!(898 "899 50bb4e7f900 000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374901 0000000000000000000000000000000000000000000000000000000000000001902 0000000000000000000000000000000000000000000000000000000000000060903 0000000000000000000000000000000000000000000000000000000000000008904 5465737420555249000000000000000000000000000000000000000000000000905 "906 ))907 .unwrap();908 assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));909 assert_eq!(910 format!("{:?}", decoder.address().unwrap()),911 "0xad2c0954693c2b5404b7e50967d3481bea432374"912 );913 assert_eq!(decoder.uint32().unwrap(), 1);914 assert_eq!(decoder.string().unwrap(), "Test URI");915 }916917 #[test]918 fn parse_vec_with_dynamic_type() {919 let decoded_data = (920 0x36543006,921 vec![922 (1.into(), "Test URI 0".to_string()),923 (11.into(), "Test URI 1".to_string()),924 (12.into(), "Test URI 2".to_string()),925 ],926 );927928 let encoded_data = &hex!(929 "930 36543006931 00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address932 0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]933 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]934935 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem936 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem937 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem938939 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60940 0000000000000000000000000000000000000000000000000000000000000040 // offset of string941 000000000000000000000000000000000000000000000000000000000000000a // size of string942 5465737420555249203000000000000000000000000000000000000000000000 // string943944 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0945 0000000000000000000000000000000000000000000000000000000000000040 // offset of string946 000000000000000000000000000000000000000000000000000000000000000a // size of string947 5465737420555249203100000000000000000000000000000000000000000000 // string948949 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160950 0000000000000000000000000000000000000000000000000000000000000040 // offset of string951 000000000000000000000000000000000000000000000000000000000000000a // size of string952 5465737420555249203200000000000000000000000000000000000000000000 // string953 "954 );955956 let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();957 assert_eq!(call, u32::to_be_bytes(decoded_data.0));958 let address = decoder.address().unwrap();959 let data = <Vec<(uint256, string)>>::abi_read(&mut decoder).unwrap();960 assert_eq!(data, decoded_data.1);961962 let mut writer = AbiWriter::new_call(decoded_data.0);963 address.abi_write(&mut writer);964 decoded_data.1.abi_write(&mut writer);965 let ed = writer.finish();966 similar_asserts::assert_eq!(encoded_data, ed.as_slice());967 }968}