Skip to content

Commit

Permalink
feat: add logs, add log dynamic decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Sep 22, 2023
1 parent 0c21fcc commit 8ebdc85
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 28 deletions.
29 changes: 27 additions & 2 deletions crates/dyn-abi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloc::{borrow::Cow, string::String};
use alloy_primitives::B256;
use alloy_sol_type_parser::Error as TypeParserError;
use alloy_sol_types::Error as SolTypesError;
use core::fmt;
Expand Down Expand Up @@ -37,6 +38,21 @@ pub enum Error {
actual: usize,
},

/// Length mismatch during event topic decoding.
TopicLengthMismatch {
/// The expected length.
expected: usize,
/// The actual length.
actual: usize,
},
/// Invalid event signature.
EventSignatureMismatch {
/// The expected signature.
expected: B256,
/// The actual signature.
actual: B256,
},

/// [`hex`] error.
Hex(hex::FromHexError),
/// [`alloy_sol_type_parser`] error.
Expand Down Expand Up @@ -88,11 +104,20 @@ impl fmt::Display for Error {

Self::TypeMismatch { expected, actual } => write!(
f,
"type mismatch, expected type {expected:?}, got value with type {actual:?}",
"type mismatch: expected type {expected:?}, got value with type {actual:?}",
),
&Self::EncodeLengthMismatch { expected, actual } => write!(
f,
"encode length mismatch, expected {expected} types, got {actual}",
"encode length mismatch: expected {expected} types, got {actual}",
),

&Self::TopicLengthMismatch { expected, actual } => write!(
f,
"invalid log topic list length: expected {expected} topics, got {actual}",
),
Self::EventSignatureMismatch { expected, actual } => write!(
f,
"invalid event signature: expected {expected}, got {actual}",
),

Self::Hex(e) => e.fmt(f),
Expand Down
29 changes: 15 additions & 14 deletions crates/dyn-abi/src/ext/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub trait JsonAbiExt: Sealed {
///
/// This function will return an error if the decoded data does not match
/// the expected input types.
fn decode_input(&self, data: &[u8]) -> Result<Vec<DynSolValue>>;
fn decode_input(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>>;
}

/// Provide ABI encoding and decoding for the [`Function`] type.
Expand All @@ -78,7 +78,7 @@ pub trait FunctionExt: JsonAbiExt + Sealed {
/// ABI-decodes the given data according to this functions's output types.
///
/// This method does not check for any prefixes or selectors.
fn decode_output(&self, data: &[u8]) -> Result<Vec<DynSolValue>>;
fn decode_output(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>>;
}

impl JsonAbiExt for Constructor {
Expand All @@ -93,8 +93,8 @@ impl JsonAbiExt for Constructor {
}

#[inline]
fn decode_input(&self, data: &[u8]) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs)
fn decode_input(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs, validate)
}
}

Expand All @@ -110,8 +110,8 @@ impl JsonAbiExt for Error {
}

#[inline]
fn decode_input(&self, data: &[u8]) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs)
fn decode_input(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs, validate)
}
}

Expand All @@ -127,8 +127,8 @@ impl JsonAbiExt for Function {
}

#[inline]
fn decode_input(&self, data: &[u8]) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs)
fn decode_input(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
decode(data, &self.inputs, validate)
}
}

Expand All @@ -139,8 +139,8 @@ impl FunctionExt for Function {
}

#[inline]
fn decode_output(&self, data: &[u8]) -> Result<Vec<DynSolValue>> {
decode(data, &self.outputs)
fn decode_output(&self, data: &[u8], validate: bool) -> Result<Vec<DynSolValue>> {
decode(data, &self.outputs, validate)
}
}

Expand Down Expand Up @@ -182,9 +182,9 @@ fn encode(values: &[DynSolValue]) -> Vec<u8> {
DynSolValue::encode_seq(values)
}

fn decode(data: &[u8], params: &[Param]) -> Result<Vec<DynSolValue>> {
fn decode(data: &[u8], params: &[Param], validate: bool) -> Result<Vec<DynSolValue>> {
let mut values = Vec::with_capacity(params.len());
let mut decoder = Decoder::new(data, false);
let mut decoder = Decoder::new(data, validate);
for param in params {
let ty = param.resolve()?;
let value = ty._decode(&mut decoder, crate::DynToken::decode_single_populate)?;
Expand Down Expand Up @@ -252,11 +252,12 @@ mod tests {

// decode
let response = U256::from(1u8).to_be_bytes_vec();
let decoded = func.decode_output(&response).unwrap();
let decoded = func.decode_output(&response, true).unwrap();
assert_eq!(decoded, [DynSolValue::Uint(U256::from(1u8), 256)]);

// Fail on wrong response type
let bad_response = Address::repeat_byte(3u8).to_vec();
assert!(func.decode_output(&bad_response).is_err());
assert!(func.decode_output(&bad_response, true).is_err());
assert!(func.decode_output(&bad_response, false).is_err());
}
}
Loading

0 comments on commit 8ebdc85

Please sign in to comment.