fix: event decoding for events with zero or one parameters (#300)
* fix: support events with zero or one paramaters * test: test against events with zero and one parameter
This commit is contained in:
parent
ac6d4d70a6
commit
b5a2ee9a3d
|
@ -785,15 +785,40 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// there might be the case that the event has only 1 params, which is not a tuple
|
||||||
|
let (from_token_impl, into_token_impl) = match params_len {
|
||||||
|
0 => (
|
||||||
quote! {
|
quote! {
|
||||||
impl<#generic_params> ethers_core::abi::Tokenizable for #name<#generic_args>
|
Ok(#init_struct_impl)
|
||||||
where
|
},
|
||||||
#generic_predicates
|
// can't encode an empty struct
|
||||||
#tokenize_predicates
|
// TODO: panic instead?
|
||||||
{
|
quote! {
|
||||||
|
ethers_core::abi::Token::Tuple(vec![])
|
||||||
|
},
|
||||||
|
),
|
||||||
|
1 => {
|
||||||
|
// This is a hacky solution in order to keep the same tokenstream as for tuples
|
||||||
|
let from_token = quote! {
|
||||||
|
let mut iter = Some(token).into_iter();
|
||||||
|
Ok(#init_struct_impl)
|
||||||
|
};
|
||||||
|
|
||||||
fn from_token(token: ethers_core::abi::Token) -> Result<Self, ethers_core::abi::InvalidOutputType> where
|
// This is a hack to get rid of the trailing comma introduced in the macro that concatenates all the fields
|
||||||
Self: Sized {
|
if let Ok(into_token) = into_token_impl
|
||||||
|
.to_string()
|
||||||
|
.as_str()
|
||||||
|
.trim_end_matches(',')
|
||||||
|
.parse()
|
||||||
|
{
|
||||||
|
(from_token, into_token)
|
||||||
|
} else {
|
||||||
|
return Error::new(input.span(), "Failed to derive Tokenizeable implementation")
|
||||||
|
.to_compile_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let from_token = quote! {
|
||||||
if let ethers_core::abi::Token::Tuple(tokens) = token {
|
if let ethers_core::abi::Token::Tuple(tokens) = token {
|
||||||
if tokens.len() != #params_len {
|
if tokens.len() != #params_len {
|
||||||
return Err(ethers_core::abi::InvalidOutputType(format!(
|
return Err(ethers_core::abi::InvalidOutputType(format!(
|
||||||
|
@ -813,14 +838,33 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
token
|
token
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
fn into_token(self) -> ethers_core::abi::Token {
|
let into_token = quote! {
|
||||||
ethers_core::abi::Token::Tuple(
|
ethers_core::abi::Token::Tuple(
|
||||||
vec![
|
vec![
|
||||||
#into_token_impl
|
#into_token_impl
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
};
|
||||||
|
(from_token, into_token)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl<#generic_params> ethers_core::abi::Tokenizable for #name<#generic_args>
|
||||||
|
where
|
||||||
|
#generic_predicates
|
||||||
|
#tokenize_predicates
|
||||||
|
{
|
||||||
|
|
||||||
|
fn from_token(token: ethers_core::abi::Token) -> Result<Self, ethers_core::abi::InvalidOutputType> where
|
||||||
|
Self: Sized {
|
||||||
|
#from_token_impl
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_token(self) -> ethers_core::abi::Token {
|
||||||
|
#into_token_impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,3 +268,44 @@ fn can_decode_event_with_no_topics() {
|
||||||
assert_eq!(event.seize_tokens, 5250648u64.into());
|
assert_eq!(event.seize_tokens, 5250648u64.into());
|
||||||
assert_eq!(event.repay_amount, 653800000000000000u64.into());
|
assert_eq!(event.repay_amount, 653800000000000000u64.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_decode_event_single_param() {
|
||||||
|
#[derive(Debug, PartialEq, EthEvent)]
|
||||||
|
pub struct OneParam {
|
||||||
|
#[ethevent(indexed)]
|
||||||
|
param1: U256,
|
||||||
|
}
|
||||||
|
|
||||||
|
let log = RawLog {
|
||||||
|
topics: vec![
|
||||||
|
"bd9bb67345a2fcc8ef3b0857e7e2901f5a0dcfc7fe5e3c10dc984f02842fb7ba"
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000007b"
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
],
|
||||||
|
data: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let event = <OneParam as EthLogDecode>::decode_log(&log).unwrap();
|
||||||
|
assert_eq!(event.param1, 123u64.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_decode_event_with_no_params() {
|
||||||
|
#[derive(Debug, PartialEq, EthEvent)]
|
||||||
|
pub struct NoParam {}
|
||||||
|
|
||||||
|
let log = RawLog {
|
||||||
|
topics: vec![
|
||||||
|
"59a6f900daaeb7581ff830f3a97097fa6372db29b0b50c6d1818ede9d1daaa0c"
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
],
|
||||||
|
data: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = <NoParam as EthLogDecode>::decode_log(&log).unwrap();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue