1
1
//! Helper functions for deriving `EthEvent`
2
2
3
+ use crate :: { abi_ty, utils} ;
3
4
use ethers_contract_abigen:: Source ;
5
+ use ethers_core:: {
6
+ abi:: { Event , EventExt , EventParam , HumanReadableParser } ,
7
+ macros:: { ethers_contract_crate, ethers_core_crate} ,
8
+ } ;
9
+ use hex:: FromHex ;
4
10
use proc_macro2:: { Span , TokenStream } ;
5
11
use quote:: quote;
6
12
use syn:: {
7
13
parse:: Error , spanned:: Spanned , AttrStyle , Data , DeriveInput , Field , Fields , Lit , Meta ,
8
14
NestedMeta ,
9
15
} ;
10
16
11
- use ethers_core:: {
12
- abi:: { Event , EventExt , EventParam , HumanReadableParser } ,
13
- macros:: { ethers_contract_crate, ethers_core_crate} ,
14
- } ;
15
- use hex:: FromHex ;
16
-
17
- use crate :: { abi_ty, utils} ;
18
-
19
17
/// Generates the `EthEvent` trait support
20
18
pub ( crate ) fn derive_eth_event_impl ( input : DeriveInput ) -> Result < TokenStream , Error > {
21
19
let name = & input. ident ;
@@ -124,10 +122,7 @@ impl EventField {
124
122
}
125
123
}
126
124
127
- fn derive_decode_from_log_impl (
128
- input : & DeriveInput ,
129
- event : & Event ,
130
- ) -> Result < proc_macro2:: TokenStream , Error > {
125
+ fn derive_decode_from_log_impl ( input : & DeriveInput , event : & Event ) -> Result < TokenStream , Error > {
131
126
let ethers_core = ethers_core_crate ( ) ;
132
127
133
128
let fields: Vec < _ > = match input. data {
@@ -159,10 +154,8 @@ fn derive_decode_from_log_impl(
159
154
fields. unnamed . iter ( ) . collect ( )
160
155
}
161
156
Fields :: Unit => {
162
- return Err ( Error :: new (
163
- input. span ( ) ,
164
- "EthEvent cannot be derived for empty structs and unit" ,
165
- ) )
157
+ // Empty structs or unit, no fields
158
+ vec ! [ ]
166
159
}
167
160
} ,
168
161
Data :: Enum ( _) => {
@@ -173,35 +166,6 @@ fn derive_decode_from_log_impl(
173
166
}
174
167
} ;
175
168
176
- let mut event_fields = Vec :: with_capacity ( fields. len ( ) ) ;
177
- for ( index, field) in fields. iter ( ) . enumerate ( ) {
178
- let mut param = event. inputs [ index] . clone ( ) ;
179
-
180
- let ( topic_name, indexed) = parse_field_attributes ( field) ?;
181
- if indexed {
182
- param. indexed = true ;
183
- }
184
- let topic_name =
185
- param. indexed . then ( || topic_name. or_else ( || Some ( param. name . clone ( ) ) ) ) . flatten ( ) ;
186
-
187
- event_fields. push ( EventField { topic_name, index, param } ) ;
188
- }
189
-
190
- // convert fields to params list
191
- let topic_types = event_fields
192
- . iter ( )
193
- . filter ( |f| f. is_indexed ( ) )
194
- . map ( |f| utils:: topic_param_type_quote ( & f. param . kind ) ) ;
195
-
196
- let topic_types_init = quote ! { let topic_types = :: std:: vec![ #( #topic_types ) , * ] ; } ;
197
-
198
- let data_types = event_fields
199
- . iter ( )
200
- . filter ( |f| !f. is_indexed ( ) )
201
- . map ( |f| utils:: param_type_quote ( & f. param . kind ) ) ;
202
-
203
- let data_types_init = quote ! { let data_types = [ #( #data_types ) , * ] ; } ;
204
-
205
169
// decode
206
170
let ( signature_check, flat_topics_init, topic_tokens_len_check) = if event. anonymous {
207
171
(
@@ -234,6 +198,51 @@ fn derive_decode_from_log_impl(
234
198
)
235
199
} ;
236
200
201
+ // Event with no fields, can skip decoding
202
+ if fields. is_empty ( ) {
203
+ return Ok ( quote ! {
204
+
205
+ let #ethers_core:: abi:: RawLog { topics, data} = log;
206
+
207
+ #signature_check
208
+
209
+ if topics. len( ) != 1usize || !data. is_empty( ) {
210
+ return Err ( :: ethers_core:: abi:: Error :: InvalidData ) ;
211
+ }
212
+
213
+ #ethers_core:: abi:: Tokenizable :: from_token( #ethers_core:: abi:: Token :: Tuple ( :: std:: vec:: Vec :: new( ) ) ) . map_err( |_|#ethers_core:: abi:: Error :: InvalidData )
214
+ } )
215
+ }
216
+
217
+ let mut event_fields = Vec :: with_capacity ( fields. len ( ) ) ;
218
+ for ( index, field) in fields. iter ( ) . enumerate ( ) {
219
+ let mut param = event. inputs [ index] . clone ( ) ;
220
+
221
+ let ( topic_name, indexed) = parse_field_attributes ( field) ?;
222
+ if indexed {
223
+ param. indexed = true ;
224
+ }
225
+ let topic_name =
226
+ param. indexed . then ( || topic_name. or_else ( || Some ( param. name . clone ( ) ) ) ) . flatten ( ) ;
227
+
228
+ event_fields. push ( EventField { topic_name, index, param } ) ;
229
+ }
230
+
231
+ // convert fields to params list
232
+ let topic_types = event_fields
233
+ . iter ( )
234
+ . filter ( |f| f. is_indexed ( ) )
235
+ . map ( |f| utils:: topic_param_type_quote ( & f. param . kind ) ) ;
236
+
237
+ let topic_types_init = quote ! { let topic_types = :: std:: vec![ #( #topic_types ) , * ] ; } ;
238
+
239
+ let data_types = event_fields
240
+ . iter ( )
241
+ . filter ( |f| !f. is_indexed ( ) )
242
+ . map ( |f| utils:: param_type_quote ( & f. param . kind ) ) ;
243
+
244
+ let data_types_init = quote ! { let data_types = [ #( #data_types ) , * ] ; } ;
245
+
237
246
// check if indexed are sorted
238
247
let tokens_init = if event_fields
239
248
. iter ( )
0 commit comments