Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Significant dyn-abi fixes :) #168

Merged
merged 17 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions crates/dyn-abi/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,29 +134,35 @@ impl<'a> DynToken<'a> {
let dynamic = self.is_dynamic();
match self {
Self::Word(w) => *w = WordToken::decode_from(dec)?.0,
Self::FixedSeq(tokens, size) => {
Self::FixedSeq(_, _) => {
let mut child = if dynamic {
dec.take_indirection()?
} else {
dec.raw_child()
};
for token in tokens.to_mut().iter_mut().take(*size) {
token.decode_populate(&mut child)?;

self.decode_sequence_populate(&mut child)?;

if !dynamic {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: missed offset propagation resulted in bad decoding

dec.take_offset(child);
}
}
Self::DynSeq { contents, template } => {
let mut child = dec.take_indirection()?;
let size = child.take_u32()? as usize;
let mut new_tokens: Vec<DynToken<'a>> = Vec::with_capacity(size);
for _ in 0..size {
let mut t = if let Some(item) = new_tokens.first() {
item.clone()
} else {
*(template.take().unwrap())
};
t.decode_populate(&mut child)?;
new_tokens.push(t);
}
// This appears to be an unclarity in the solidity spec. The
// spec specifies that offsets are relative to the beginning of
// `enc(X)`. But known-good test vectors have it relative to the
// word AFTER the array size
let mut child = child.raw_child();

let mut new_tokens: Vec<_> = Vec::with_capacity(size);
new_tokens.resize(size, *(template.take().unwrap()));
DaniPopes marked this conversation as resolved.
Show resolved Hide resolved

new_tokens
.iter_mut()
.for_each(|t| t.decode_populate(&mut child).unwrap());

*contents = new_tokens.into();
}
Self::PackedSeq(buf) => *buf = PackedSeqToken::decode_from(dec)?.0,
Expand All @@ -169,8 +175,8 @@ impl<'a> DynToken<'a> {
#[inline]
pub(crate) fn decode_sequence_populate(&mut self, dec: &mut Decoder<'a>) -> Result<()> {
match self {
Self::FixedSeq(buf, _) => {
for item in buf.to_mut().iter_mut() {
Self::FixedSeq(buf, size) => {
for item in buf.to_mut().iter_mut().take(*size) {
item.decode_populate(dec)?;
}
Ok(())
Expand Down
283 changes: 283 additions & 0 deletions crates/dyn-abi/src/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,29 @@ mod tests {
use alloy_primitives::Address;
use serde_json::json;

use hex_literal::hex;

macro_rules! encoder_test {
($ty:literal, $encoded:ident) => {
DaniPopes marked this conversation as resolved.
Show resolved Hide resolved
let t: DynSolType = $ty.parse().expect("parsing failed");
let dec = t.decode_params(&$encoded).expect("decoding failed");

// Tuples are treated as top-level lists. So if we encounter a
// dynamic tuple, the total length of the encoded data will include
// the offset, but the encoding/decoding process will not. To
// account for this, we add 32 bytes to the expected length when
// the type is a dynamic tuple.
if dec.as_tuple().is_some() && dec.is_dynamic() {
assert_eq!(dec.total_words() * 32, $encoded.len() + 32);
} else {
assert_eq!(dec.total_words() * 32, $encoded.len());
}

let re_encoded = dec.encode_params();
assert_eq!(re_encoded, $encoded);
};
}

#[test]
fn dynamically_encodes() {
let word1 = "0000000000000000000000000101010101010101010101010101010101010101"
Expand Down Expand Up @@ -462,4 +485,264 @@ mod tests {
}
)
}

#[test]
fn address() {
let enc = hex! {"0000000000000000000000001111111111111111111111111111111111111111"};
encoder_test!("address", enc);
}

#[test]
fn dynamic_array_of_addresses() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
"
);
encoder_test!("address[]", encoded);
}

#[test]
fn fixed_array_of_addresses() {
let encoded = hex!(
"
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
"
);
encoder_test!("address[2]", encoded);
}

#[test]
fn two_addresses() {
let encoded = hex!(
"
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
"
);
encoder_test!("(address,address)", encoded);
}

#[test]
fn fixed_array_of_dyanmic_arrays_of_addresses() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000040
00000000000000000000000000000000000000000000000000000000000000a0
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000003333333333333333333333333333333333333333
0000000000000000000000004444444444444444444444444444444444444444
"
);
encoder_test!("address[][2]", encoded);
}

#[test]
fn dynamic_array_of_fixed_arrays_of_addresses() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
0000000000000000000000003333333333333333333333333333333333333333
0000000000000000000000004444444444444444444444444444444444444444
"
);
encoder_test!("address[2][]", encoded);
}

#[test]
fn dynamic_array_of_dynamic_arrays() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000080
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000002222222222222222222222222222222222222222
"
);
encoder_test!("address[][]", encoded);
}

#[test]
fn dynamic_array_of_dynamic_arrays2() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000040
00000000000000000000000000000000000000000000000000000000000000a0
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000003333333333333333333333333333333333333333
0000000000000000000000004444444444444444444444444444444444444444
"
);
encoder_test!("address[][]", encoded);
}

#[test]
fn fixed_array_of_fixed_arrays() {
let encoded = hex!(
"
0000000000000000000000001111111111111111111111111111111111111111
0000000000000000000000002222222222222222222222222222222222222222
0000000000000000000000003333333333333333333333333333333333333333
0000000000000000000000004444444444444444444444444444444444444444
"
);
encoder_test!("address[2][2]", encoded);
}

#[test]
fn fixed_array_of_static_tuples_followed_by_dynamic_type() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000005930cc5
0000000000000000000000000000000000000000000000000000000015002967
0000000000000000000000004444444444444444444444444444444444444444
000000000000000000000000000000000000000000000000000000000000307b
00000000000000000000000000000000000000000000000000000000000001c3
0000000000000000000000002222222222222222222222222222222222222222
00000000000000000000000000000000000000000000000000000000000000e0
0000000000000000000000000000000000000000000000000000000000000009
6761766f66796f726b0000000000000000000000000000000000000000000000
"
);

encoder_test!("((uint256,uint256,address)[2],string)", encoded);
}

#[test]
fn empty_array() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000000
"
);
encoder_test!("address[]", encoded);
}

#[test]
fn empty_array_2() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
"
);
encoder_test!("(address[],address[])", encoded);
}

#[test]
fn empty_array_3() {
// Nested empty arrays
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000040
00000000000000000000000000000000000000000000000000000000000000a0
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000000
"
);
encoder_test!("(address[][], address[][])", encoded);
}

#[test]
fn fixed_bytes() {
let encoded = hex!("1234000000000000000000000000000000000000000000000000000000000000");
encoder_test!("bytes2", encoded);
}

#[test]
fn string() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000009
6761766f66796f726b0000000000000000000000000000000000000000000000
"
);
encoder_test!("string", encoded);
}

#[test]
fn bytes() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000002
1234000000000000000000000000000000000000000000000000000000000000
"
);
encoder_test!("bytes", encoded);
}

#[test]
fn bytes_2() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
000000000000000000000000000000000000000000000000000000000000001f
1000000000000000000000000000000000000000000000000000000000000200
"
);
encoder_test!("bytes", encoded);
}

#[test]
fn bytes_3() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000040
1000000000000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000000000000
"
);
encoder_test!("bytes", encoded);
}

#[test]
fn two_bytes() {
let encoded = hex!(
"
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000080
000000000000000000000000000000000000000000000000000000000000001f
1000000000000000000000000000000000000000000000000000000000000200
0000000000000000000000000000000000000000000000000000000000000020
0010000000000000000000000000000000000000000000000000000000000002
"
);
encoder_test!("(bytes,bytes)", encoded);
}

#[test]
fn uint() {
let encoded = hex!("0000000000000000000000000000000000000000000000000000000000000004");
encoder_test!("uint", encoded);
}
}
Loading