1use crate::node::InMemoryNode;
2use anyhow::Context;
3use std::collections::HashMap;
4use zksync_error::anvil_zksync::node::AnvilNodeResult;
5use zksync_mini_merkle_tree::MiniMerkleTree;
6use zksync_types::api;
7use zksync_types::fee::Fee;
8use zksync_types::hasher::keccak::KeccakHasher;
9use zksync_types::hasher::Hasher;
10use zksync_types::l2_to_l1_log::{
11 l2_to_l1_logs_tree_size, L2ToL1Log, LOG_PROOF_SUPPORTED_METADATA_VERSION,
12};
13use zksync_types::transaction_request::CallRequest;
14use zksync_types::utils::storage_key_for_standard_token_balance;
15use zksync_types::{h256_to_u256, L1BatchNumber};
16use zksync_types::{
17 AccountTreeId, Address, L2BlockNumber, Transaction, H160, H256, L2_BASE_TOKEN_ADDRESS, U256,
18};
19use zksync_web3_decl::error::Web3Error;
20
21impl InMemoryNode {
22 pub async fn estimate_fee_impl(&self, req: CallRequest) -> AnvilNodeResult<Fee> {
23 self.inner.read().await.estimate_gas_impl(req).await
24 }
25
26 pub async fn estimate_gas_l1_to_l2(&self, req: CallRequest) -> AnvilNodeResult<U256> {
27 self.inner
28 .read()
29 .await
30 .estimate_l1_to_l2_gas_impl(req)
31 .await
32 }
33
34 pub async fn get_raw_block_transactions_impl(
35 &self,
36 block_number: L2BlockNumber,
37 ) -> Result<Vec<Transaction>, Web3Error> {
38 let tx_hashes = self
39 .blockchain
40 .get_block_tx_hashes_by_number(block_number)
41 .await;
42 if let Some(tx_hashes) = tx_hashes {
43 let mut transactions = Vec::with_capacity(tx_hashes.len());
44 for tx_hash in tx_hashes {
45 let transaction = self
46 .blockchain
47 .get_zksync_tx(&tx_hash)
48 .await
49 .with_context(|| anyhow::anyhow!("Unexpectedly transaction (hash={tx_hash}) belongs to a block but could not be found"))?;
50 transactions.push(transaction);
51 }
52 Ok(transactions)
53 } else {
54 Ok(self.fork.get_raw_block_transactions(block_number).await?)
55 }
56 }
57
58 pub async fn get_bridge_contracts_impl(&self) -> Result<api::BridgeAddresses, Web3Error> {
59 Ok(self
60 .fork
61 .get_bridge_contracts()
62 .await?
63 .unwrap_or(api::BridgeAddresses {
64 l1_shared_default_bridge: Default::default(),
65 l2_shared_default_bridge: Default::default(),
66 l1_erc20_default_bridge: Default::default(),
67 l2_erc20_default_bridge: Default::default(),
68 l1_weth_bridge: Default::default(),
69 l2_weth_bridge: Default::default(),
70 l2_legacy_shared_bridge: Default::default(),
71 }))
72 }
73
74 pub async fn get_confirmed_tokens_impl(
75 &self,
76 from: u32,
77 limit: u8,
78 ) -> anyhow::Result<Vec<zksync_web3_decl::types::Token>> {
79 Ok(self
80 .fork
81 .get_confirmed_tokens(from, limit)
82 .await?
83 .unwrap_or(vec![zksync_web3_decl::types::Token {
84 l1_address: Address::zero(),
85 l2_address: L2_BASE_TOKEN_ADDRESS,
86 name: "Ether".to_string(),
87 symbol: "ETH".to_string(),
88 decimals: 18,
89 }]))
90 }
91
92 pub async fn get_all_account_balances_impl(
93 &self,
94 address: Address,
95 ) -> Result<HashMap<Address, U256>, Web3Error> {
96 let tokens = self.get_confirmed_tokens_impl(0, 100).await?;
97
98 let balances = {
99 let mut balances = HashMap::new();
100 for token in tokens {
101 let balance_key = storage_key_for_standard_token_balance(
103 AccountTreeId::new(token.l2_address),
104 &address,
105 );
106 let balance = self.storage.read_value_alt(&balance_key).await?;
107 if !balance.is_zero() {
108 balances.insert(token.l2_address, h256_to_u256(balance));
109 }
110 }
111 balances
112 };
113
114 Ok(balances)
115 }
116
117 pub async fn get_block_details_impl(
118 &self,
119 block_number: L2BlockNumber,
120 ) -> anyhow::Result<Option<api::BlockDetails>> {
121 let base_system_contracts_hashes = self.system_contracts.base_system_contracts_hashes();
122 let reader = self.inner.read().await;
123 let l2_fair_gas_price = reader.fee_input_provider.gas_price();
124 let fair_pubdata_price = Some(reader.fee_input_provider.fair_pubdata_price());
125 drop(reader);
126
127 let block_details = self
128 .blockchain
129 .get_block_details_by_number(
130 block_number,
131 l2_fair_gas_price,
132 fair_pubdata_price,
133 base_system_contracts_hashes,
134 )
135 .await;
136
137 match block_details {
138 Some(block_details) => Ok(Some(block_details)),
139 None => self.fork.get_block_details(block_number).await,
140 }
141 }
142
143 pub async fn get_transaction_details_impl(
144 &self,
145 hash: H256,
146 ) -> anyhow::Result<Option<api::TransactionDetails>> {
147 match self.blockchain.get_tx_details(&hash).await {
148 Some(tx_details) => Ok(Some(tx_details)),
149 None => self.fork.get_transaction_details(hash).await,
150 }
151 }
152
153 pub async fn get_bytecode_by_hash_impl(&self, hash: H256) -> anyhow::Result<Option<Vec<u8>>> {
154 if let Some(bytecode) = self.storage.load_factory_dep_alt(hash).await? {
155 return Ok(Some(bytecode));
156 }
157
158 self.fork.get_bytecode_by_hash(hash).await
159 }
160
161 pub async fn get_base_token_l1_address_impl(&self) -> anyhow::Result<Address> {
162 Ok(H160::from_low_u64_be(1))
163 }
164
165 pub async fn get_l2_to_l1_log_proof_impl(
166 &self,
167 tx_hash: H256,
168 index: Option<usize>,
169 ) -> anyhow::Result<Option<api::L2ToL1LogProof>> {
170 let Some(tx_receipt) = self.blockchain.get_tx_receipt(&tx_hash).await else {
171 return Ok(None);
172 };
173 let l1_batch_number = L1BatchNumber(tx_receipt.l1_batch_number.expect("").as_u32());
174 let Some(l1_batch) = self.blockchain.get_batch_header(l1_batch_number).await else {
175 return Ok(None);
176 };
177 let all_l1_logs_in_batch = l1_batch
178 .l2_to_l1_logs
179 .into_iter()
180 .map(|log| log.0)
181 .collect::<Vec<_>>();
182 let l1_batch_tx_index = tx_receipt.l1_batch_tx_index.expect("").as_u32() as u16;
183 let log_filter = |log: &L2ToL1Log| log.tx_number_in_block == l1_batch_tx_index;
184 let index_in_filtered_logs = index.unwrap_or(0);
185
186 let Some((l1_log_index, _)) = all_l1_logs_in_batch
188 .iter()
189 .enumerate()
190 .filter(|(_, log)| log_filter(log))
191 .nth(index_in_filtered_logs)
192 else {
193 return Ok(None);
194 };
195 let merkle_tree_leaves = all_l1_logs_in_batch.iter().map(L2ToL1Log::to_bytes);
196 let tree_size = l2_to_l1_logs_tree_size(self.blockchain.protocol_version());
197
198 let (local_root, proof) = MiniMerkleTree::new(merkle_tree_leaves, Some(tree_size))
199 .merkle_root_and_path(l1_log_index);
200 let Some(aggregated_root) = self
201 .blockchain
202 .get_batch_aggregation_root(l1_batch_number)
203 .await
204 else {
205 return Ok(None);
206 };
207 let root = KeccakHasher.compress(&local_root, &aggregated_root);
208
209 let mut log_leaf_proof = proof;
210 log_leaf_proof.push(aggregated_root);
211
212 let (batch_proof_len, batch_chain_proof, is_final_node) = (0, Vec::<H256>::new(), true);
213
214 let proof = {
215 let mut metadata = [0u8; 32];
216 metadata[0] = LOG_PROOF_SUPPORTED_METADATA_VERSION;
217 metadata[1] = log_leaf_proof.len() as u8;
218 metadata[2] = batch_proof_len as u8;
219 metadata[3] = if is_final_node { 1 } else { 0 };
220
221 let mut result = vec![H256(metadata)];
222
223 result.extend(log_leaf_proof);
224 result.extend(batch_chain_proof);
225
226 result
227 };
228
229 Ok(Some(api::L2ToL1LogProof {
230 proof,
231 root,
232 id: l1_log_index as u32,
233 }))
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use std::str::FromStr;
240
241 use zksync_types::{
242 api, transaction_request::CallRequest, Address, ProtocolVersionId, H160, H256,
243 };
244 use zksync_types::{u256_to_h256, L1BatchNumber};
245
246 use super::*;
247 use crate::node::fork::{ForkClient, ForkConfig};
248 use crate::node::TransactionResult;
249 use crate::{
250 node::InMemoryNode,
251 testing,
252 testing::{ForkBlockConfig, MockServer},
253 };
254
255 #[tokio::test]
256 async fn test_estimate_fee() {
257 let node = InMemoryNode::test(None);
258
259 let mock_request = CallRequest {
260 from: Some(
261 "0xa61464658afeaf65cccaafd3a512b69a83b77618"
262 .parse()
263 .unwrap(),
264 ),
265 to: Some(
266 "0x36615cf349d7f6344891b1e7ca7c72883f5dc049"
267 .parse()
268 .unwrap(),
269 ),
270 gas: Some(U256::from(0)),
271 gas_price: Some(U256::from(0)),
272 max_fee_per_gas: None,
273 max_priority_fee_per_gas: None,
274 value: Some(U256::from(0)),
275 data: Some(vec![0, 0].into()),
276 nonce: Some(U256::from(0)),
277 transaction_type: None,
278 access_list: None,
279 eip712_meta: None,
280 input: None,
281 };
282
283 let result = node.estimate_fee_impl(mock_request).await.unwrap();
284
285 assert_eq!(result.gas_limit, U256::from(153968));
286 assert_eq!(result.max_fee_per_gas, U256::from(45250000));
287 assert_eq!(result.max_priority_fee_per_gas, U256::from(0));
288 assert_eq!(result.gas_per_pubdata_limit, U256::from(168));
289 }
290
291 #[tokio::test]
292 async fn test_get_transaction_details_local() {
293 let node = InMemoryNode::test(None);
295 {
296 let mut writer = node.inner.write().await;
297 writer
298 .insert_tx_result(
299 H256::repeat_byte(0x1),
300 TransactionResult {
301 info: testing::default_tx_execution_info(),
302 new_bytecodes: vec![],
303 receipt: api::TransactionReceipt {
304 logs: vec![],
305 gas_used: Some(U256::from(10_000)),
306 effective_gas_price: Some(U256::from(1_000_000_000)),
307 ..Default::default()
308 },
309 debug: testing::default_tx_debug_info(),
310 },
311 )
312 .await;
313 }
314 let result = node
315 .get_transaction_details_impl(H256::repeat_byte(0x1))
316 .await
317 .expect("get transaction details")
318 .expect("transaction details");
319
320 assert!(matches!(result.status, api::TransactionStatus::Included));
322 assert_eq!(result.fee, U256::from(10_000_000_000_000u64));
323 }
324
325 #[tokio::test]
326 async fn test_get_transaction_details_fork() {
327 let mock_server = MockServer::run_with_config(ForkBlockConfig {
328 number: 10,
329 transaction_count: 0,
330 hash: H256::repeat_byte(0xab),
331 });
332 let input_tx_hash = H256::repeat_byte(0x02);
333 mock_server.expect(
334 "zks_getTransactionDetails",
335 Some(serde_json::json!([format!("{:#x}", input_tx_hash),])),
336 serde_json::json!({
337 "isL1Originated": false,
338 "status": "included",
339 "fee": "0x74293f087500",
340 "gasPerPubdata": "0x4e20",
341 "initiatorAddress": "0x63ab285cd87a189f345fed7dd4e33780393e01f0",
342 "receivedAt": "2023-10-12T15:45:53.094Z",
343 "ethCommitTxHash": null,
344 "ethProveTxHash": null,
345 "ethExecuteTxHash": null
346 }),
347 );
348
349 let node = InMemoryNode::test(Some(
350 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), None)
351 .await
352 .unwrap(),
353 ));
354
355 let result = node
356 .get_transaction_details_impl(input_tx_hash)
357 .await
358 .expect("get transaction details")
359 .expect("transaction details");
360
361 assert!(matches!(result.status, api::TransactionStatus::Included));
362 assert_eq!(result.fee, U256::from(127_720_500_000_000u64));
363 }
364
365 #[tokio::test]
366 async fn test_get_block_details_local() {
367 let node = InMemoryNode::test(None);
369 {
370 let mut writer = node.inner.write().await;
371 let block = api::Block::<api::TransactionVariant>::default();
372 writer.insert_block(H256::repeat_byte(0x1), block).await;
373 writer
374 .insert_block_hash(L2BlockNumber(0), H256::repeat_byte(0x1))
375 .await;
376 }
377 let result = node
378 .get_block_details_impl(L2BlockNumber(0))
379 .await
380 .expect("get block details")
381 .expect("block details");
382
383 assert!(matches!(result.number, L2BlockNumber(0)));
385 assert_eq!(result.l1_batch_number, L1BatchNumber(0));
386 assert_eq!(result.base.timestamp, 0);
387 }
388
389 #[tokio::test]
390 async fn test_get_block_details_fork() {
391 let mock_server = MockServer::run_with_config(ForkBlockConfig {
392 number: 10,
393 transaction_count: 0,
394 hash: H256::repeat_byte(0xab),
395 });
396 let miniblock = L2BlockNumber::from(16474138);
397 mock_server.expect(
398 "zks_getBlockDetails",
399 Some(serde_json::json!([miniblock.0])),
400 serde_json::json!({
401 "number": 16474138,
402 "l1BatchNumber": 270435,
403 "timestamp": 1697405098,
404 "l1TxCount": 0,
405 "l2TxCount": 1,
406 "rootHash": "0xd9e60f9a684fd7fc16e87ae923341a6e4af24f286e76612efdfc2d55f3f4d064",
407 "status": "sealed",
408 "commitTxHash": null,
409 "committedAt": null,
410 "proveTxHash": null,
411 "provenAt": null,
412 "executeTxHash": null,
413 "executedAt": null,
414 "l1GasPrice": 6156252068u64,
415 "l2FairGasPrice": 50000000u64,
416 "fairPubdataPrice": 100u64,
417 "baseSystemContractsHashes": {
418 "bootloader": "0x0100089b8a2f2e6a20ba28f02c9e0ed0c13d702932364561a0ea61621f65f0a8",
419 "default_aa": "0x0100067d16a5485875b4249040bf421f53e869337fe118ec747cf40a4c777e5f"
420 },
421 "operatorAddress": "0xa9232040bf0e0aea2578a5b2243f2916dbfc0a69",
422 "protocolVersion": ProtocolVersionId::Version26,
423 }),
424 );
425
426 let node = InMemoryNode::test(Some(
427 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), None)
428 .await
429 .unwrap(),
430 ));
431
432 let result = node
433 .get_block_details_impl(miniblock)
434 .await
435 .expect("get block details")
436 .expect("block details");
437
438 assert!(matches!(result.number, L2BlockNumber(16474138)));
439 assert_eq!(result.l1_batch_number, L1BatchNumber(270435));
440 assert_eq!(result.base.timestamp, 1697405098);
441 assert_eq!(result.base.fair_pubdata_price, Some(100));
442 }
443
444 #[tokio::test]
445 async fn test_get_bridge_contracts_uses_default_values_if_local() {
446 let node = InMemoryNode::test(None);
448 let expected_bridge_addresses = api::BridgeAddresses {
449 l1_shared_default_bridge: Default::default(),
450 l2_shared_default_bridge: Default::default(),
451 l1_erc20_default_bridge: Default::default(),
452 l2_erc20_default_bridge: Default::default(),
453 l1_weth_bridge: Default::default(),
454 l2_weth_bridge: Default::default(),
455 l2_legacy_shared_bridge: Default::default(),
456 };
457
458 let actual_bridge_addresses = node
459 .get_bridge_contracts_impl()
460 .await
461 .expect("get bridge addresses");
462
463 testing::assert_bridge_addresses_eq(&expected_bridge_addresses, &actual_bridge_addresses)
465 }
466
467 #[tokio::test]
468 async fn test_get_bridge_contracts_uses_fork() {
469 let mock_server = MockServer::run_with_config(ForkBlockConfig {
471 number: 10,
472 transaction_count: 0,
473 hash: H256::repeat_byte(0xab),
474 });
475 let input_bridge_addresses = api::BridgeAddresses {
476 l1_shared_default_bridge: Some(H160::repeat_byte(0x1)),
477 l2_shared_default_bridge: Some(H160::repeat_byte(0x2)),
478 l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
479 l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
480 l1_weth_bridge: Some(H160::repeat_byte(0x3)),
481 l2_weth_bridge: Some(H160::repeat_byte(0x4)),
482 l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
483 };
484 mock_server.expect(
485 "zks_getBridgeContracts",
486 None,
487 serde_json::json!({
488 "l1Erc20SharedBridge": format!("{:#x}", input_bridge_addresses.l1_shared_default_bridge.unwrap()),
489 "l2Erc20SharedBridge": format!("{:#x}", input_bridge_addresses.l2_shared_default_bridge.unwrap()),
490 "l1Erc20DefaultBridge": format!("{:#x}", input_bridge_addresses.l1_erc20_default_bridge.unwrap()),
491 "l2Erc20DefaultBridge": format!("{:#x}", input_bridge_addresses.l2_erc20_default_bridge.unwrap()),
492 "l1WethBridge": format!("{:#x}", input_bridge_addresses.l1_weth_bridge.unwrap()),
493 "l2WethBridge": format!("{:#x}", input_bridge_addresses.l2_weth_bridge.unwrap())
494 }),
495 );
496
497 let node = InMemoryNode::test(Some(
498 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), None)
499 .await
500 .unwrap(),
501 ));
502
503 let actual_bridge_addresses = node
504 .get_bridge_contracts_impl()
505 .await
506 .expect("get bridge addresses");
507
508 testing::assert_bridge_addresses_eq(&input_bridge_addresses, &actual_bridge_addresses)
510 }
511
512 #[tokio::test]
513 async fn test_get_bytecode_by_hash_returns_local_value_if_available() {
514 let node = InMemoryNode::test(None);
516 let input_hash = H256::repeat_byte(0x1);
517 let input_bytecode = vec![0x1];
518 node.inner
519 .write()
520 .await
521 .fork_storage
522 .store_factory_dep(input_hash, input_bytecode.clone());
523
524 let actual = node
525 .get_bytecode_by_hash_impl(input_hash)
526 .await
527 .expect("failed fetching bytecode")
528 .expect("no bytecode was found");
529
530 assert_eq!(input_bytecode, actual);
532 }
533
534 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
536 async fn test_get_bytecode_by_hash_uses_fork_if_value_unavailable() {
537 let mock_server = MockServer::run_with_config(ForkBlockConfig {
539 number: 10,
540 transaction_count: 0,
541 hash: H256::repeat_byte(0xab),
542 });
543 let input_hash = H256::repeat_byte(0x1);
544 let input_bytecode = vec![0x1];
545 mock_server.expect(
546 "zks_getBytecodeByHash",
547 Some(serde_json::json!([format!("{:#x}", input_hash)])),
548 serde_json::json!(input_bytecode),
549 );
550
551 let node = InMemoryNode::test(Some(
552 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), None)
553 .await
554 .unwrap(),
555 ));
556
557 let actual = node
558 .get_bytecode_by_hash_impl(input_hash)
559 .await
560 .expect("failed fetching bytecode")
561 .expect("no bytecode was found");
562
563 assert_eq!(input_bytecode, actual);
565 }
566
567 #[tokio::test]
568 async fn test_get_raw_block_transactions_local() {
569 let node = InMemoryNode::test(None);
571 {
572 let mut writer = node.inner.write().await;
573 let mut block = api::Block::<api::TransactionVariant>::default();
574 let txn = api::Transaction::default();
575 writer
576 .insert_tx_result(
577 txn.hash,
578 TransactionResult {
579 info: testing::default_tx_execution_info(),
580 new_bytecodes: vec![],
581 receipt: api::TransactionReceipt {
582 logs: vec![],
583 gas_used: Some(U256::from(10_000)),
584 effective_gas_price: Some(U256::from(1_000_000_000)),
585 ..Default::default()
586 },
587 debug: testing::default_tx_debug_info(),
588 },
589 )
590 .await;
591 block.transactions.push(api::TransactionVariant::Full(txn));
592 writer.insert_block(H256::repeat_byte(0x1), block).await;
593 writer
594 .insert_block_hash(L2BlockNumber(0), H256::repeat_byte(0x1))
595 .await;
596 }
597
598 let txns = node
599 .get_raw_block_transactions_impl(L2BlockNumber(0))
600 .await
601 .expect("get transaction details");
602
603 assert_eq!(txns.len(), 1);
605 }
606
607 #[tokio::test]
608 async fn test_get_raw_block_transactions_fork() {
609 let mock_server = MockServer::run_with_config(ForkBlockConfig {
610 number: 10,
611 transaction_count: 0,
612 hash: H256::repeat_byte(0xab),
613 });
614 let miniblock = L2BlockNumber::from(16474138);
615 mock_server.expect(
616 "zks_getRawBlockTransactions",
617 Some(serde_json::json!([miniblock.0])),
618 serde_json::json!([
619 {
620 "common_data": {
621 "L2": {
622 "nonce": 86,
623 "fee": {
624 "gas_limit": "0xcc626",
625 "max_fee_per_gas": "0x141dd760",
626 "max_priority_fee_per_gas": "0x0",
627 "gas_per_pubdata_limit": "0x4e20"
628 },
629 "initiatorAddress": "0x840bd73f903ba7dbb501be8326fe521dadcae1a5",
630 "signature": [
631 135,
632 163,
633 2,
634 78,
635 118,
636 14,
637 209
638 ],
639 "transactionType": "EIP1559Transaction",
640 "input": {
641 "hash": "0xc1f625f55d186ad0b439054adfe3317ae703c5f588f4fa1896215e8810a141e0",
642 "data": [
643 2,
644 249,
645 1,
646 110,
647 130
648 ]
649 },
650 "paymasterParams": {
651 "paymaster": "0x0000000000000000000000000000000000000000",
652 "paymasterInput": []
653 }
654 }
655 },
656 "execute": {
657 "contractAddress": "0xbe7d1fd1f6748bbdefc4fbacafbb11c6fc506d1d",
658 "calldata": "0x38ed173900000000000000000000000000000000000000000000000000000000002c34cc00000000000000000000000000000000000000000000000000000000002c9a2500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000840bd73f903ba7dbb501be8326fe521dadcae1a500000000000000000000000000000000000000000000000000000000652c5d1900000000000000000000000000000000000000000000000000000000000000020000000000000000000000008e86e46278518efc1c5ced245cba2c7e3ef115570000000000000000000000003355df6d4c9c3035724fd0e3914de96a5a83aaf4",
659 "value": "0x0",
660 "factoryDeps": null
661 },
662 "received_timestamp_ms": 1697405097873u64,
663 "raw_bytes": "0x02f9016e820144568084141dd760830cc62694be7d1fd1f6748bbdefc4fbacafbb11c6fc506d1d80b9010438ed173900000000000000000000000000000000000000000000000000000000002c34cc00000000000000000000000000000000000000000000000000000000002c9a2500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000840bd73f903ba7dbb501be8326fe521dadcae1a500000000000000000000000000000000000000000000000000000000652c5d1900000000000000000000000000000000000000000000000000000000000000020000000000000000000000008e86e46278518efc1c5ced245cba2c7e3ef115570000000000000000000000003355df6d4c9c3035724fd0e3914de96a5a83aaf4c080a087a3024e760ed14134ef541608bf308e083c899a89dba3c02bf3040f07c8b91b9fc3a7eeb6b3b8b36bb03ea4352415e7815dda4954f4898d255bd7660736285e"
664 }
665 ]),
666 );
667
668 let node = InMemoryNode::test(Some(
669 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), None)
670 .await
671 .unwrap(),
672 ));
673
674 let txns = node
675 .get_raw_block_transactions_impl(miniblock)
676 .await
677 .expect("get transaction details");
678 assert_eq!(txns.len(), 1);
679 }
680
681 #[tokio::test]
682 async fn test_get_all_account_balances_empty() {
683 let node = InMemoryNode::test(None);
684 let balances = node
685 .get_all_account_balances_impl(Address::zero())
686 .await
687 .expect("get balances");
688 assert!(balances.is_empty());
689 }
690
691 #[tokio::test]
692 async fn test_get_confirmed_tokens_eth() {
693 let node = InMemoryNode::test(None);
694 let balances = node
695 .get_confirmed_tokens_impl(0, 100)
696 .await
697 .expect("get balances");
698 assert_eq!(balances.len(), 1);
699 assert_eq!(&balances[0].name, "Ether");
700 }
701
702 #[tokio::test]
703 async fn test_get_all_account_balances_forked() {
704 let cbeth_address = Address::from_str("0x75af292c1c9a37b3ea2e6041168b4e48875b9ed5")
705 .expect("failed to parse address");
706 let mock_server = testing::MockServer::run();
707 mock_server.expect("eth_chainId", None, serde_json::json!("0x104"));
708
709 mock_server.expect(
710 "zks_getBlockDetails",
711 Some(serde_json::json!([1])),
712 serde_json::json!({
713 "baseSystemContractsHashes": {
714 "bootloader": "0x010008a5c30072f79f8e04f90b31f34e554279957e7e2bf85d3e9c7c1e0f834d",
715 "default_aa": "0x01000663d7941c097ba2631096508cf9ec7769ddd40e081fd81b0d04dc07ea0e"
716 },
717 "commitTxHash": null,
718 "committedAt": null,
719 "executeTxHash": null,
720 "executedAt": null,
721 "l1BatchNumber": 0,
722 "l1GasPrice": 0,
723 "l1TxCount": 1,
724 "l2FairGasPrice": 50000000,
725 "l2TxCount": 0,
726 "number": 0,
727 "operatorAddress": "0x0000000000000000000000000000000000000000",
728 "protocolVersion": ProtocolVersionId::Version26,
729 "proveTxHash": null,
730 "provenAt": null,
731 "rootHash": "0xdaa77426c30c02a43d9fba4e841a6556c524d47030762eb14dc4af897e605d9b",
732 "status": "verified",
733 "timestamp": 1000
734 }),
735 );
736 mock_server.expect(
737 "eth_getBlockByHash",
738 Some(serde_json::json!(["0xdaa77426c30c02a43d9fba4e841a6556c524d47030762eb14dc4af897e605d9b", true])),
739 serde_json::json!({
740 "baseFeePerGas": "0x0",
741 "difficulty": "0x0",
742 "extraData": "0x",
743 "gasLimit": "0xffffffff",
744 "gasUsed": "0x0",
745 "hash": "0xdaa77426c30c02a43d9fba4e841a6556c524d47030762eb14dc4af897e605d9b",
746 "l1BatchNumber": "0x0",
747 "l1BatchTimestamp": null,
748 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
749 "miner": "0x0000000000000000000000000000000000000000",
750 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
751 "nonce": "0x0000000000000000",
752 "number": "0x0",
753 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
754 "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
755 "sealFields": [],
756 "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000",
757 "size": "0x0",
758 "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
759 "timestamp": "0x3e8",
760 "totalDifficulty": "0x0",
761 "transactions": [],
762 "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
763 "uncles": []
764 }),
765 );
766 mock_server.expect(
767 "zks_getConfirmedTokens",
768 Some(serde_json::json!([0, 100])),
769 serde_json::json!([
770 {
771 "decimals": 18,
772 "l1Address": "0xbe9895146f7af43049ca1c1ae358b0541ea49704",
773 "l2Address": "0x75af292c1c9a37b3ea2e6041168b4e48875b9ed5",
774 "name": "Coinbase Wrapped Staked ETH",
775 "symbol": "cbETH"
776 }
777 ]),
778 );
779 mock_server.expect(
780 "zks_getFeeParams",
781 None,
782 serde_json::json!({
783 "V2": {
784 "config": {
785 "minimal_l2_gas_price": 25000000,
786 "compute_overhead_part": 0,
787 "pubdata_overhead_part": 1,
788 "batch_overhead_l1_gas": 800000,
789 "max_gas_per_batch": 200000000,
790 "max_pubdata_per_batch": 240000
791 },
792 "l1_gas_price": 46226388803u64,
793 "l1_pubdata_price": 100780475095u64,
794 "conversion_ratio": {
795 "numerator": 1,
796 "denominator": 1
797 }
798 }
799 }),
800 );
801
802 let node = InMemoryNode::test(Some(
803 ForkClient::at_block_number(ForkConfig::unknown(mock_server.url()), Some(1.into()))
804 .await
805 .unwrap(),
806 ));
807
808 {
809 let writer = node.inner.write().await;
810 let mut fork = writer.fork_storage.inner.write().unwrap();
811 fork.raw_storage.set_value(
812 storage_key_for_standard_token_balance(
813 AccountTreeId::new(cbeth_address),
814 &Address::repeat_byte(0x1),
815 ),
816 u256_to_h256(U256::from(1337)),
817 );
818 }
819
820 let balances = node
821 .get_all_account_balances_impl(Address::repeat_byte(0x1))
822 .await
823 .expect("get balances");
824 assert_eq!(balances.get(&cbeth_address).unwrap(), &U256::from(1337));
825 }
826
827 #[tokio::test]
828 async fn test_get_base_token_l1_address() {
829 let node = InMemoryNode::test(None);
830 let token_address = node
831 .get_base_token_l1_address_impl()
832 .await
833 .expect("get base token l1 address");
834 assert_eq!(
835 "0x0000000000000000000000000000000000000001",
836 format!("{:?}", token_address)
837 );
838 }
839}