Skip to content

Commit 70ada25

Browse files
committed
apollo_l1_provider: make sure wrong event types do not get scraped
1 parent 6363378 commit 70ada25

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

crates/apollo_l1_provider/tests/flow_test_event_filters.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use papyrus_base_layer::test_utils::{
2929
use papyrus_base_layer::BaseLayerContract;
3030
use utils::{L1_CONTRACT_ADDRESS, L2_ENTRY_POINT};
3131

32+
use crate::utils::setup_anvil_base_layer;
33+
3234
// This test requires that we do some manual work to produce the logs we expect to get from the
3335
// Starknet L1 contract. The reason we don't just post events to L1 and have them scraped is that
3436
// some of the log types don't correspond to actions we can just do to the base layer, like marking
@@ -132,6 +134,33 @@ 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+
}
163+
135164
fn dummy_block<T>() -> Block<T, Header> {
136165
Block {
137166
header: Header {
@@ -246,3 +275,48 @@ fn encode_message_into_log(
246275
removed: false,
247276
}
248277
}
278+
279+
// Generate a LogMessageToL1 log (which we do not filter on).
280+
fn encode_log_message_to_l1_log(payload: &[U256]) -> Log {
281+
let selector = "LogMessageToL1(address,uint256[],uint256,uint256)";
282+
let block_number = 1;
283+
let starknet_address = DEFAULT_ANVIL_L1_ACCOUNT_ADDRESS.to_bigint().to_str_radix(16);
284+
let starknet_address = format!("{:0>64}", starknet_address);
285+
286+
let offset = U256::from(32u64);
287+
288+
let mut encoded = Vec::new();
289+
// Offset to the array data (96 bytes).
290+
encoded.extend_from_slice(&offset.to_be_bytes::<32>());
291+
292+
// Tail section has the payload array data only. It starts with the length of the array.
293+
let array_len = U256::from(payload.len());
294+
encoded.extend_from_slice(&array_len.to_be_bytes::<32>());
295+
// Finally, write the array elements.
296+
for item in payload {
297+
encoded.extend_from_slice(&item.to_be_bytes::<32>());
298+
}
299+
300+
let log_data = Bytes::from(encoded);
301+
302+
Log {
303+
inner: LogInner {
304+
address: DEFAULT_ANVIL_L1_DEPLOYED_ADDRESS.parse().unwrap(),
305+
data: LogData::new_unchecked(
306+
vec![
307+
filter_to_hash(selector).parse().unwrap(),
308+
starknet_address.parse().unwrap(),
309+
U256::from(L1_CONTRACT_ADDRESS).into(),
310+
],
311+
log_data,
312+
),
313+
},
314+
block_hash: Some(BlockHash::from_str(FAKE_HASH).unwrap()),
315+
block_number: Some(block_number),
316+
block_timestamp: None,
317+
transaction_hash: Some(TxHash::from_str(FAKE_HASH).unwrap()),
318+
transaction_index: Some(block_number + 1),
319+
log_index: Some(block_number + 2),
320+
removed: false,
321+
}
322+
}

crates/papyrus_base_layer/src/eth_events.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub fn parse_event(log: Log, block_timestamp: BlockTimestamp) -> EthereumBaseLay
2424
let log = log.inner;
2525

2626
let event = Starknet::StarknetEvents::decode_log(&log)?.data;
27+
2728
match event {
2829
Starknet::StarknetEvents::LogMessageToL2(event) => {
2930
let fee = Fee(event.fee.try_into().map_err(EthereumBaseLayerError::FeeOutOfRange)?);

crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,13 @@ impl BaseLayerContract for EthereumBaseLayerContract {
161161
.select(block_range.clone())
162162
.events(event_types_to_filter)
163163
.address(immutable_self.config.starknet_contract_address);
164+
164165
let matching_logs = tokio::time::timeout(
165166
immutable_self.config.timeout_millis,
166167
immutable_self.contract.provider().get_logs(&filter),
167168
)
168169
.await??;
170+
169171
// Debugging.
170172
let hashes: Vec<_> = matching_logs.iter().filter_map(|log| log.transaction_hash).collect();
171173
debug!("Got events in {:?}, L1 tx hashes: {:?}", block_range, hashes);

0 commit comments

Comments
 (0)