From 9e332a51eb5b6b33f0bfd795b22702e64ae738b7 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 8 Jun 2023 23:48:01 -0700 Subject: [PATCH 1/6] fix: event trait fixes --- crates/sol-types/src/types/event.rs | 155 +++++++++++++++++++++------- 1 file changed, 115 insertions(+), 40 deletions(-) diff --git a/crates/sol-types/src/types/event.rs b/crates/sol-types/src/types/event.rs index c85981b9de..ce45a24481 100644 --- a/crates/sol-types/src/types/event.rs +++ b/crates/sol-types/src/types/event.rs @@ -1,6 +1,7 @@ -use crate::{no_std_prelude::*, token::TokenSeq, Result, SolType}; use alloy_primitives::B256; +use crate::{token::TokenSeq, SolType}; + /// Solidity event. /// /// ### Implementer's Guide @@ -9,59 +10,133 @@ use alloy_primitives::B256; /// using the [`sol`][crate::sol] proc macro to parse a Solidity event /// definition. pub trait SolEvent: Sized { - /// The underlying tuple type which represents this type's members. + /// The underlying tuple type which represents this event's non-indexed and + /// dynamically-sized event parameters. These parameters are ABI encoded + /// and included in the log body. /// - /// If this type has no arguments, this will be the unit type `()`. - type Tuple: SolType; + /// If this event has no non-indexed and no dynamically-sized parameters, + /// this will be the unit type `()`. + type BodyTuple: SolType; - /// The corresponding [TokenSeq] type. - type Token: TokenSeq; + /// The [`TokenSeq`] type corresponding to the tuple. + type BodyToken: TokenSeq; /// The event's ABI signature. const SIGNATURE: &'static str; - /// The event's first topic: `keccak256(SIGNATURE)` - const TOPIC_ZERO: B256; + /// The keccak256 hash of the event's ABI signature. For non-anonymous + /// events, this will be the topic0 of the event. + const SIGNATURE_HASH: [u8; 32]; + + /// True if the event is anonymous. + const ANONYMOUS: bool; + + /// The number of topics. + const TOPICS_LEN: usize; + + /// Type of Topic 0. This is typically a [`B256`] representing the event's + /// signature. However, for anonymous events, this may be some other type. + /// If an anonymous event has no indexed parameters, this will be the unit + /// type `()`. + type Topic0: SolType; + /// Type of Topic 1. If the event does not have an indexed parameter at this + /// position, this will be the unit type `()`. + type Topic1: SolType; + /// Type of Topic 2. If the event does not have an indexed parameter at this + /// position, this will be the unit type `()`. + type Topic2: SolType; + /// Type of Topic 3. If the event does not have an indexed parameter at this + /// position, this will be the unit type `()`. + type Topic3: SolType; /// Converts to the tuple type used for ABI encoding and decoding. - fn to_rust(&self) -> ::RustType; + fn body_to_rust(&self) -> ::RustType; - /// Convert from the tuple type used for ABI encoding and decoding. - fn from_rust(tuple: ::RustType) -> Self; + fn from_rust( + topic0: ::RustType, + topic1: ::RustType, + topic2: ::RustType, + topic3: ::RustType, + body: ::RustType, + ) -> Self; - /// The size of the encoded data in bytes, **without** its selector. - fn data_size(&self) -> usize; + /// The size of the encoded body data in bytes. + fn body_size(&self) -> usize; - /// ABI decode this call's arguments from the given slice, **without** its - /// selector. - #[inline] - fn decode_raw(data: &[u8], validate: bool) -> Result { - ::decode(data, validate).map(Self::from_rust) - } + fn topic_0(&self) -> ::RustType; + fn topic_1(&self) -> ::RustType; + fn topic_2(&self) -> ::RustType; + fn topic_3(&self) -> ::RustType; +} - /// ABI decode this call's arguments from the given slice, **with** the - /// selector. - #[inline] - fn decode(data: &[u8], validate: bool) -> Result { - let data = data - .strip_prefix(&Self::SELECTOR) - .ok_or_else(|| crate::Error::type_check_fail_sig(data, Self::SIGNATURE))?; - Self::decode_raw(data, validate) - } +mod example { + + use alloy_primitives::{keccak256, U256}; - /// ABI encode the call to the given buffer **without** its selector. - #[inline] - fn encode_raw(&self, out: &mut Vec) { - out.reserve(self.data_size()); - out.extend(::encode(self.to_rust())); + use crate::{sol_data, SolEvent, SolType}; + + // event MyEvent(bytes32 indexed a, uint256 b, string indexed c, bytes d); + pub struct MyEvent { + pub a: [u8; 32], + pub b: U256, + pub c: String, + pub d: Vec, } - /// ABI encode the call to the given buffer **with** its selector. - #[inline] - fn encode(&self) -> Vec { - let mut out = Vec::with_capacity(4 + self.data_size()); - out.extend(&Self::SELECTOR); - self.encode_raw(&mut out); - out + impl SolEvent for MyEvent { + type BodyTuple = (sol_data::Uint<256>, sol_data::String, sol_data::Bytes); + type BodyToken = ( + as SolType>::TokenType, + ::TokenType, + ::TokenType, + ); + const SIGNATURE: &'static str = "MyEvent(bytes32,uint256,string,bytes)"; + const SIGNATURE_HASH: [u8; 32] = [0; 32]; // FIXME + const ANONYMOUS: bool = false; + const TOPICS_LEN: usize = 3; + type Topic0 = sol_data::FixedBytes<32>; // Signature hash + type Topic1 = sol_data::FixedBytes<32>; // Indexed bytes32 a + type Topic2 = sol_data::FixedBytes<32>; // Hash of indexed string c + type Topic3 = (); // no 4th topic + + fn body_to_rust(&self) -> ::RustType { + (self.b, self.c.clone(), self.d.clone()) + } + + fn from_rust( + topic0: ::RustType, + topic1: ::RustType, + topic2: ::RustType, + topic3: ::RustType, + body: ::RustType, + ) -> Self { + Self { + a: topic1, + b: body.0, + c: body.1, + d: body.2, + } + } + + fn body_size(&self) -> usize { + 0 + // FIXME: as data_size for error. + } + + fn topic_0(&self) -> ::RustType { + Self::SIGNATURE_HASH + } + + fn topic_1(&self) -> ::RustType { + self.a + } + + fn topic_2(&self) -> ::RustType { + keccak256(self.c.as_bytes()).into() + } + + fn topic_3(&self) -> ::RustType { + () + } } } From 2b22bd77684ce7ff0e95e5f95dbbe36607cef463 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 8 Jun 2023 23:49:18 -0700 Subject: [PATCH 2/6] fix: re-exporting event --- crates/sol-types/src/lib.rs | 3 ++- crates/sol-types/src/types/mod.rs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/sol-types/src/lib.rs b/crates/sol-types/src/lib.rs index 25c2091fa1..0bb63ff6c4 100644 --- a/crates/sol-types/src/lib.rs +++ b/crates/sol-types/src/lib.rs @@ -180,7 +180,8 @@ pub use errors::{Error, Result}; mod types; pub use types::{ - data_type as sol_data, Panic, PanicKind, Revert, SolCall, SolError, SolStruct, SolType, + data_type as sol_data, Panic, PanicKind, Revert, SolCall, SolError, SolEvent, SolStruct, + SolType, }; mod util; diff --git a/crates/sol-types/src/types/mod.rs b/crates/sol-types/src/types/mod.rs index 0158a224a4..bc3ad86334 100644 --- a/crates/sol-types/src/types/mod.rs +++ b/crates/sol-types/src/types/mod.rs @@ -18,3 +18,6 @@ pub use r#type::SolType; // Solidity user-defined value types. // No exports are needed as the only item is a macro. mod udt; + +mod event; +pub use event::SolEvent; From 8b756a39a99a6ab3a1df50d37d9e7ac5627a3548 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 9 Jun 2023 10:49:49 -0700 Subject: [PATCH 3/6] refactor: event trait take 2 --- crates/sol-types/src/types/event.rs | 248 +++++++++++++++++++--------- 1 file changed, 174 insertions(+), 74 deletions(-) diff --git a/crates/sol-types/src/types/event.rs b/crates/sol-types/src/types/event.rs index ce45a24481..b993edbd99 100644 --- a/crates/sol-types/src/types/event.rs +++ b/crates/sol-types/src/types/event.rs @@ -1,6 +1,88 @@ -use alloy_primitives::B256; +use alloy_primitives::FixedBytes; -use crate::{token::TokenSeq, SolType}; +use crate::{ + token::{TokenSeq, WordToken}, + Result, SolType, Word, +}; + +trait TopicList: SolType + sealed::Sealed { + const COUNT: usize; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType; +} + +impl TopicList for () { + const COUNT: usize = 0; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { + () + } +} + +impl TopicList for (T,) +where + T: SolType, +{ + const COUNT: usize = 1; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { + let mut iter = topics.into_iter().copied(); + let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); + + (topic0,) + } +} + +impl TopicList for (T, U) +where + T: SolType, + U: SolType, +{ + const COUNT: usize = 2; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { + let mut iter = topics.into_iter().copied(); + let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); + (topic0, topic1) + } +} + +impl TopicList for (T, U, V) +where + T: SolType, + U: SolType, + V: SolType, +{ + const COUNT: usize = 3; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { + let mut iter = topics.into_iter().copied(); + let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic2 = V::detokenize(iter.next().unwrap_or_default()).unwrap(); + (topic0, topic1, topic2) + } +} + +impl TopicList for (T, U, V, W) +where + T: SolType, + U: SolType, + V: SolType, + W: SolType, +{ + const COUNT: usize = 4; + + fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { + let mut iter = topics.into_iter().copied(); + let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic2 = V::detokenize(iter.next().unwrap_or_default()).unwrap(); + let topic3 = W::detokenize(iter.next().unwrap_or_default()).unwrap(); + (topic0, topic1, topic2, topic3) + } +} /// Solidity event. /// @@ -16,17 +98,25 @@ pub trait SolEvent: Sized { /// /// If this event has no non-indexed and no dynamically-sized parameters, /// this will be the unit type `()`. - type BodyTuple: SolType; + type DataTuple: SolType; /// The [`TokenSeq`] type corresponding to the tuple. - type BodyToken: TokenSeq; + type DataToken: TokenSeq; - /// The event's ABI signature. + /// The underlying tuple type which represents this event's topics. + /// These are ABI encoded and included in the log structs + type TopicList: TopicList; + + /// The event's ABI signature. For anonymous events, this is unused, but is + /// still present. const SIGNATURE: &'static str; /// The keccak256 hash of the event's ABI signature. For non-anonymous - /// events, this will be the topic0 of the event. - const SIGNATURE_HASH: [u8; 32]; + /// events, this will be the topic0 of the event. For anonymous events, this + /// is unused, but is still present. + /// + /// Also called the event `selector` + const SIGNATURE_HASH: FixedBytes<32>; /// True if the event is anonymous. const ANONYMOUS: bool; @@ -34,44 +124,44 @@ pub trait SolEvent: Sized { /// The number of topics. const TOPICS_LEN: usize; - /// Type of Topic 0. This is typically a [`B256`] representing the event's - /// signature. However, for anonymous events, this may be some other type. - /// If an anonymous event has no indexed parameters, this will be the unit - /// type `()`. - type Topic0: SolType; - /// Type of Topic 1. If the event does not have an indexed parameter at this - /// position, this will be the unit type `()`. - type Topic1: SolType; - /// Type of Topic 2. If the event does not have an indexed parameter at this - /// position, this will be the unit type `()`. - type Topic2: SolType; - /// Type of Topic 3. If the event does not have an indexed parameter at this - /// position, this will be the unit type `()`. - type Topic3: SolType; - - /// Converts to the tuple type used for ABI encoding and decoding. - fn body_to_rust(&self) -> ::RustType; - - fn from_rust( - topic0: ::RustType, - topic1: ::RustType, - topic2: ::RustType, - topic3: ::RustType, - body: ::RustType, - ) -> Self; + /// Decode the body of this event from the given data. + fn decode_body(data: &[u8], validate: bool) -> Result<::RustType> { + ::decode(data, validate) + } + + /// Encode the body of this event. + fn encode_body(&self) -> Vec; + + /// Decode the topics of this event from the given data. + fn decode_topics<'a>( + topics: impl IntoIterator, + ) -> ::RustType { + ::detokenize(topics) + } /// The size of the encoded body data in bytes. fn body_size(&self) -> usize; - fn topic_0(&self) -> ::RustType; - fn topic_1(&self) -> ::RustType; - fn topic_2(&self) -> ::RustType; - fn topic_3(&self) -> ::RustType; + /// Convert decoded rust data to the event type. + fn new( + topics: ::RustType, + body: ::RustType, + ) -> Self; + + fn decode_log<'a>( + topics: impl IntoIterator, + body_data: &[u8], + validate: bool, + ) -> Result { + let topics = Self::decode_topics(topics); + let body = Self::decode_body(body_data, validate)?; + + Ok(Self::new(topics, body)) + } } mod example { - - use alloy_primitives::{keccak256, U256}; + use alloy_primitives::{FixedBytes, U256}; use crate::{sol_data, SolEvent, SolType}; @@ -84,59 +174,69 @@ mod example { } impl SolEvent for MyEvent { - type BodyTuple = (sol_data::Uint<256>, sol_data::String, sol_data::Bytes); - type BodyToken = ( + type DataTuple = (sol_data::Uint<256>, sol_data::String, sol_data::Bytes); + type DataToken = ( as SolType>::TokenType, ::TokenType, ::TokenType, ); + + // this is a, and keccak256(c) + type TopicList = (sol_data::FixedBytes<32>, sol_data::FixedBytes<32>); + const SIGNATURE: &'static str = "MyEvent(bytes32,uint256,string,bytes)"; - const SIGNATURE_HASH: [u8; 32] = [0; 32]; // FIXME + const SIGNATURE_HASH: FixedBytes<32> = FixedBytes([0; 32]); // FIXME: caluclate it const ANONYMOUS: bool = false; const TOPICS_LEN: usize = 3; - type Topic0 = sol_data::FixedBytes<32>; // Signature hash - type Topic1 = sol_data::FixedBytes<32>; // Indexed bytes32 a - type Topic2 = sol_data::FixedBytes<32>; // Hash of indexed string c - type Topic3 = (); // no 4th topic - fn body_to_rust(&self) -> ::RustType { - (self.b, self.c.clone(), self.d.clone()) + fn body_size(&self) -> usize { + 0 + // FIXME: as data_size for error. } - fn from_rust( - topic0: ::RustType, - topic1: ::RustType, - topic2: ::RustType, - topic3: ::RustType, - body: ::RustType, + fn encode_body(&self) -> Vec { + todo!() + } + + fn new( + topics: ::RustType, + body: ::RustType, ) -> Self { Self { - a: topic1, + a: topics.1, b: body.0, c: body.1, d: body.2, } } + } +} - fn body_size(&self) -> usize { - 0 - // FIXME: as data_size for error. - } - - fn topic_0(&self) -> ::RustType { - Self::SIGNATURE_HASH - } - - fn topic_1(&self) -> ::RustType { - self.a - } - - fn topic_2(&self) -> ::RustType { - keccak256(self.c.as_bytes()).into() - } - - fn topic_3(&self) -> ::RustType { - () - } +mod sealed { + use super::*; + + pub(crate) trait Sealed {} + impl Sealed for () {} + impl Sealed for (T,) where T: SolType {} + impl Sealed for (T, U) + where + T: SolType, + U: SolType, + { + } + impl Sealed for (T, U, V) + where + T: SolType, + U: SolType, + V: SolType, + { + } + impl Sealed for (T, U, V, W) + where + T: SolType, + U: SolType, + V: SolType, + W: SolType, + { } } From f99b7a7df0306111a9db39731cf4677212351666 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 9 Jun 2023 13:02:13 -0700 Subject: [PATCH 4/6] refactor: improve topic detokenization --- crates/sol-types/src/lib.rs | 2 +- crates/sol-types/src/types/event.rs | 82 +++++++++++++++++++++-------- crates/sol-types/src/types/mod.rs | 2 +- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/crates/sol-types/src/lib.rs b/crates/sol-types/src/lib.rs index 0bb63ff6c4..0348637447 100644 --- a/crates/sol-types/src/lib.rs +++ b/crates/sol-types/src/lib.rs @@ -181,7 +181,7 @@ pub use errors::{Error, Result}; mod types; pub use types::{ data_type as sol_data, Panic, PanicKind, Revert, SolCall, SolError, SolEvent, SolStruct, - SolType, + SolType, TopicList, }; mod util; diff --git a/crates/sol-types/src/types/event.rs b/crates/sol-types/src/types/event.rs index b993edbd99..17ec5215ac 100644 --- a/crates/sol-types/src/types/event.rs +++ b/crates/sol-types/src/types/event.rs @@ -2,20 +2,37 @@ use alloy_primitives::FixedBytes; use crate::{ token::{TokenSeq, WordToken}, - Result, SolType, Word, + Result, SolType, }; -trait TopicList: SolType + sealed::Sealed { +use sealed::Sealed; + +/// A `TopicList` represents the topics of a Solidity event. A topic list may +/// be 0-4 elements. Topics are included in log +/// +/// This trait is sealed to prevent incorrect downstream implementations of +/// `TopicList` from being created. +pub trait TopicList: SolType + Sealed { + /// The number of topics const COUNT: usize; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType; + /// Detokenize the topics into a tuple of rust types. + /// + /// This function accepts an iterator of `WordToken` + fn detokenize(topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into; } impl TopicList for () { const COUNT: usize = 0; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { - () + fn detokenize(_topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into, + { } } @@ -25,8 +42,12 @@ where { const COUNT: usize = 1; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { - let mut iter = topics.into_iter().copied(); + fn detokenize(topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into, + { + let mut iter = topics.into_iter().map(Into::into); let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); (topic0,) @@ -40,8 +61,13 @@ where { const COUNT: usize = 2; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { - let mut iter = topics.into_iter().copied(); + fn detokenize(topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into, + { + let mut iter: core::iter::Map<::IntoIter, _> = + topics.into_iter().map(Into::into); let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); (topic0, topic1) @@ -56,8 +82,12 @@ where { const COUNT: usize = 3; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { - let mut iter = topics.into_iter().copied(); + fn detokenize(topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into, + { + let mut iter = topics.into_iter().map(Into::into); let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); let topic2 = V::detokenize(iter.next().unwrap_or_default()).unwrap(); @@ -74,8 +104,12 @@ where { const COUNT: usize = 4; - fn detokenize<'a>(topics: impl IntoIterator) -> Self::RustType { - let mut iter = topics.into_iter().copied(); + fn detokenize(topics: I) -> Self::RustType + where + I: IntoIterator, + D: Into, + { + let mut iter = topics.into_iter().map(Into::into); let topic0 = T::detokenize(iter.next().unwrap_or_default()).unwrap(); let topic1 = U::detokenize(iter.next().unwrap_or_default()).unwrap(); let topic2 = V::detokenize(iter.next().unwrap_or_default()).unwrap(); @@ -133,9 +167,11 @@ pub trait SolEvent: Sized { fn encode_body(&self) -> Vec; /// Decode the topics of this event from the given data. - fn decode_topics<'a>( - topics: impl IntoIterator, - ) -> ::RustType { + fn decode_topics(topics: I) -> ::RustType + where + I: IntoIterator, + D: Into, + { ::detokenize(topics) } @@ -148,11 +184,12 @@ pub trait SolEvent: Sized { body: ::RustType, ) -> Self; - fn decode_log<'a>( - topics: impl IntoIterator, - body_data: &[u8], - validate: bool, - ) -> Result { + /// Decode the event from the given log info. + fn decode_log(topics: I, body_data: &[u8], validate: bool) -> Result + where + I: IntoIterator, + D: Into, + { let topics = Self::decode_topics(topics); let body = Self::decode_body(body_data, validate)?; @@ -160,6 +197,7 @@ pub trait SolEvent: Sized { } } +#[allow(clippy::all)] mod example { use alloy_primitives::{FixedBytes, U256}; @@ -215,7 +253,7 @@ mod example { mod sealed { use super::*; - pub(crate) trait Sealed {} + pub trait Sealed {} impl Sealed for () {} impl Sealed for (T,) where T: SolType {} impl Sealed for (T, U) diff --git a/crates/sol-types/src/types/mod.rs b/crates/sol-types/src/types/mod.rs index bc3ad86334..02bea81e83 100644 --- a/crates/sol-types/src/types/mod.rs +++ b/crates/sol-types/src/types/mod.rs @@ -20,4 +20,4 @@ pub use r#type::SolType; mod udt; mod event; -pub use event::SolEvent; +pub use event::{SolEvent, TopicList}; From 8ac5bedc9099466e1c7ddc953bbfb8a1be0bcee3 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 9 Jun 2023 13:40:07 -0700 Subject: [PATCH 5/6] refactor: change events to account for indexed structs not in body --- crates/sol-types/src/types/event.rs | 59 ++++++++++++++++++----------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/crates/sol-types/src/types/event.rs b/crates/sol-types/src/types/event.rs index 17ec5215ac..b10f2aae75 100644 --- a/crates/sol-types/src/types/event.rs +++ b/crates/sol-types/src/types/event.rs @@ -126,19 +126,23 @@ where /// using the [`sol`][crate::sol] proc macro to parse a Solidity event /// definition. pub trait SolEvent: Sized { - /// The underlying tuple type which represents this event's non-indexed and - /// dynamically-sized event parameters. These parameters are ABI encoded - /// and included in the log body. + /// The underlying tuple type which represents this event's non-indexed + /// parameters. These parameters are ABI encoded and included in the log + /// body. /// - /// If this event has no non-indexed and no dynamically-sized parameters, - /// this will be the unit type `()`. + /// If this event has no non-indexed parameters, this will be the unit type + /// `()`. type DataTuple: SolType; /// The [`TokenSeq`] type corresponding to the tuple. type DataToken: TokenSeq; /// The underlying tuple type which represents this event's topics. - /// These are ABI encoded and included in the log structs + /// These are ABI encoded and included in the log struct returned by the + /// RPC node. Complex and dynamic indexed parameters are encoded according + /// to [special rules] and then hashed + /// + /// [special rules]: https://docs.soliditylang.org/en/v0.8.18/abi-spec.html#indexed-event-encoding type TopicList: TopicList; /// The event's ABI signature. For anonymous events, this is unused, but is @@ -158,15 +162,17 @@ pub trait SolEvent: Sized { /// The number of topics. const TOPICS_LEN: usize; - /// Decode the body of this event from the given data. + /// Decode the body of this event from the given data. The event body + /// contains the non-indexed parameters. fn decode_body(data: &[u8], validate: bool) -> Result<::RustType> { ::decode(data, validate) } /// Encode the body of this event. - fn encode_body(&self) -> Vec; + fn encode_data(&self) -> Vec; - /// Decode the topics of this event from the given data. + /// Decode the topics of this event from the given data. The topics contain + /// the selector (for non-anonymous events) and indexed parameters. fn decode_topics(topics: I) -> ::RustType where I: IntoIterator, @@ -176,7 +182,7 @@ pub trait SolEvent: Sized { } /// The size of the encoded body data in bytes. - fn body_size(&self) -> usize; + fn data_size(&self) -> usize; /// Convert decoded rust data to the event type. fn new( @@ -197,42 +203,51 @@ pub trait SolEvent: Sized { } } -#[allow(clippy::all)] -mod example { +#[cfg(test)] +mod compile_test { use alloy_primitives::{FixedBytes, U256}; use crate::{sol_data, SolEvent, SolType}; - // event MyEvent(bytes32 indexed a, uint256 b, string indexed c, bytes d); - pub struct MyEvent { + #[allow(unreachable_pub, dead_code)] + /// event MyEvent(bytes32 indexed a, uint256 b, string indexed c, bytes d); + struct MyEvent { + /// bytes indexed a pub a: [u8; 32], + /// uint256 b pub b: U256, - pub c: String, + /// string indexed c + pub hash_c: [u8; 32], + /// bytes d pub d: Vec, } impl SolEvent for MyEvent { - type DataTuple = (sol_data::Uint<256>, sol_data::String, sol_data::Bytes); + type DataTuple = (sol_data::Uint<256>, sol_data::Bytes); + /// type DataToken = ( as SolType>::TokenType, - ::TokenType, ::TokenType, ); // this is a, and keccak256(c) - type TopicList = (sol_data::FixedBytes<32>, sol_data::FixedBytes<32>); + type TopicList = ( + sol_data::FixedBytes<32>, + sol_data::FixedBytes<32>, + sol_data::FixedBytes<32>, + ); const SIGNATURE: &'static str = "MyEvent(bytes32,uint256,string,bytes)"; const SIGNATURE_HASH: FixedBytes<32> = FixedBytes([0; 32]); // FIXME: caluclate it const ANONYMOUS: bool = false; const TOPICS_LEN: usize = 3; - fn body_size(&self) -> usize { + fn data_size(&self) -> usize { 0 // FIXME: as data_size for error. } - fn encode_body(&self) -> Vec { + fn encode_data(&self) -> Vec { todo!() } @@ -243,8 +258,8 @@ mod example { Self { a: topics.1, b: body.0, - c: body.1, - d: body.2, + hash_c: topics.2, + d: body.1, } } } From c2abcdd12f81c123acca0f967dd711a84535b9ae Mon Sep 17 00:00:00 2001 From: James Date: Fri, 9 Jun 2023 13:40:28 -0700 Subject: [PATCH 6/6] fix: move test to bottom of event --- crates/sol-types/src/types/event.rs | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/crates/sol-types/src/types/event.rs b/crates/sol-types/src/types/event.rs index b10f2aae75..0dad38ac75 100644 --- a/crates/sol-types/src/types/event.rs +++ b/crates/sol-types/src/types/event.rs @@ -203,6 +203,35 @@ pub trait SolEvent: Sized { } } +mod sealed { + use super::*; + + pub trait Sealed {} + impl Sealed for () {} + impl Sealed for (T,) where T: SolType {} + impl Sealed for (T, U) + where + T: SolType, + U: SolType, + { + } + impl Sealed for (T, U, V) + where + T: SolType, + U: SolType, + V: SolType, + { + } + impl Sealed for (T, U, V, W) + where + T: SolType, + U: SolType, + V: SolType, + W: SolType, + { + } +} + #[cfg(test)] mod compile_test { use alloy_primitives::{FixedBytes, U256}; @@ -264,32 +293,3 @@ mod compile_test { } } } - -mod sealed { - use super::*; - - pub trait Sealed {} - impl Sealed for () {} - impl Sealed for (T,) where T: SolType {} - impl Sealed for (T, U) - where - T: SolType, - U: SolType, - { - } - impl Sealed for (T, U, V) - where - T: SolType, - U: SolType, - V: SolType, - { - } - impl Sealed for (T, U, V, W) - where - T: SolType, - U: SolType, - V: SolType, - W: SolType, - { - } -}