anvil_zksync/
bytecode_override.rs

1use anvil_zksync_core::node::InMemoryNode;
2use anyhow::Context;
3use hex::FromHex;
4use serde::Deserialize;
5use std::str::FromStr;
6use tokio::fs;
7use zksync_types::Address;
8
9#[derive(Debug, Deserialize)]
10struct ContractJson {
11    bytecode: Bytecode,
12}
13
14#[derive(Debug, Deserialize)]
15struct Bytecode {
16    object: String,
17}
18
19// Loads a list of bytecodes and addresses from the directory and then inserts them directly
20// into the Node's storage.
21pub async fn override_bytecodes(node: &InMemoryNode, bytecodes_dir: String) -> anyhow::Result<()> {
22    let mut read_dir = fs::read_dir(bytecodes_dir).await?;
23    while let Some(entry) = read_dir.next_entry().await? {
24        let path = entry.path();
25
26        if path.is_file() {
27            let filename = match path.file_name().and_then(|name| name.to_str()) {
28                Some(name) => name,
29                None => anyhow::bail!("Invalid filename {}", path.display().to_string()),
30            };
31
32            // Look only at .json files.
33            if let Some(filename) = filename.strip_suffix(".json") {
34                let address = Address::from_str(filename)
35                    .with_context(|| format!("Cannot parse {} as address", filename))?;
36
37                let file_content = fs::read_to_string(&path).await?;
38                let contract: ContractJson = serde_json::from_str(&file_content)
39                    .with_context(|| format!("Failed to  parse json file {:?}", path))?;
40
41                let bytecode = Vec::from_hex(contract.bytecode.object)
42                    .with_context(|| format!("Failed to parse hex from {:?}", path))?;
43
44                node.override_bytecode(address, bytecode)
45                    .await
46                    .expect("Failed to override bytecode");
47                tracing::debug!("Replacing bytecode at address {:?}", address);
48            }
49        }
50    }
51    Ok(())
52}