@@ -18,9 +18,11 @@ use alloy::providers::{Provider, ProviderBuilder};
1818use alloy:: rpc:: types:: { Block , BlockTransactions , Header , Log } ;
1919use alloy:: transports:: mock:: Asserter ;
2020use apollo_l1_provider:: event_identifiers_to_track;
21+ use assert_matches:: assert_matches;
2122use papyrus_base_layer:: ethereum_base_layer_contract:: {
2223 EthereumBaseLayerConfig ,
2324 EthereumBaseLayerContract ,
25+ EthereumBaseLayerError ,
2426} ;
2527use papyrus_base_layer:: test_utils:: {
2628 DEFAULT_ANVIL_L1_ACCOUNT_ADDRESS ,
@@ -132,6 +134,37 @@ async fn all_event_types_must_be_filtered_and_parsed() {
132134 }
133135}
134136
137+ #[ tokio:: test]
138+ async fn cannot_parse_log_message_to_l1 ( ) {
139+ // Setup.
140+ // Make a mock L1
141+ let asserter = Asserter :: new ( ) ;
142+ let provider = ProviderBuilder :: new ( ) . connect_mocked_client ( asserter. clone ( ) ) ;
143+
144+ let mut base_layer = EthereumBaseLayerContract :: new_with_provider (
145+ EthereumBaseLayerConfig :: default ( ) ,
146+ provider. root ( ) . clone ( ) ,
147+ ) ;
148+
149+ // We can just return the same block all the time, it will only affect the timestamps.
150+ let dummy_block: Block < B256 , Header > = dummy_block ( ) ;
151+
152+ // This log is for LogMessageToL1 event.
153+ let expected_message_to_l1_log =
154+ encode_log_message_to_l1_log ( & [ U256 :: from ( 15 ) , U256 :: from ( 202 ) ] ) ;
155+ asserter. push_success ( & vec ! [ expected_message_to_l1_log. clone( ) ] ) ;
156+ // asserter.push_success(&Vec::<Log>::new());
157+ asserter. push_success ( & dummy_block) ;
158+
159+ let result = base_layer. events ( 0 ..=1 , event_identifiers_to_track ( ) ) . await ;
160+
161+ assert ! ( result. is_err( ) , "expected error" ) ;
162+ assert_matches ! (
163+ result,
164+ Err ( EthereumBaseLayerError :: TypeError ( alloy:: sol_types:: Error :: InvalidLog { .. } ) )
165+ ) ;
166+ }
167+
135168fn dummy_block < T > ( ) -> Block < T , Header > {
136169 Block {
137170 header : Header {
@@ -246,3 +279,48 @@ fn encode_message_into_log(
246279 removed : false ,
247280 }
248281}
282+
283+ // Generate a LogMessageToL1 log (which we do not filter on).
284+ fn encode_log_message_to_l1_log ( payload : & [ U256 ] ) -> Log {
285+ let selector = "LogMessageToL1(address,uint256[],uint256,uint256)" ;
286+ let block_number = 1 ;
287+ let starknet_address = DEFAULT_ANVIL_L1_ACCOUNT_ADDRESS . to_bigint ( ) . to_str_radix ( 16 ) ;
288+ let starknet_address = format ! ( "{:0>64}" , starknet_address) ;
289+
290+ let offset = U256 :: from ( 32u64 ) ;
291+
292+ let mut encoded = Vec :: new ( ) ;
293+ // Offset to the array data (96 bytes).
294+ encoded. extend_from_slice ( & offset. to_be_bytes :: < 32 > ( ) ) ;
295+
296+ // Tail section has the payload array data only. It starts with the length of the array.
297+ let array_len = U256 :: from ( payload. len ( ) ) ;
298+ encoded. extend_from_slice ( & array_len. to_be_bytes :: < 32 > ( ) ) ;
299+ // Finally, write the array elements.
300+ for item in payload {
301+ encoded. extend_from_slice ( & item. to_be_bytes :: < 32 > ( ) ) ;
302+ }
303+
304+ let log_data = Bytes :: from ( encoded) ;
305+
306+ Log {
307+ inner : LogInner {
308+ address : DEFAULT_ANVIL_L1_DEPLOYED_ADDRESS . parse ( ) . unwrap ( ) ,
309+ data : LogData :: new_unchecked (
310+ vec ! [
311+ filter_to_hash( selector) . parse( ) . unwrap( ) ,
312+ starknet_address. parse( ) . unwrap( ) ,
313+ U256 :: from( L1_CONTRACT_ADDRESS ) . into( ) ,
314+ ] ,
315+ log_data,
316+ ) ,
317+ } ,
318+ block_hash : Some ( BlockHash :: from_str ( FAKE_HASH ) . unwrap ( ) ) ,
319+ block_number : Some ( block_number) ,
320+ block_timestamp : None ,
321+ transaction_hash : Some ( TxHash :: from_str ( FAKE_HASH ) . unwrap ( ) ) ,
322+ transaction_index : Some ( block_number + 1 ) ,
323+ log_index : Some ( block_number + 2 ) ,
324+ removed : false ,
325+ }
326+ }
0 commit comments