anvil/eth/backend/
genesis.rs
1use crate::eth::backend::db::Db;
4use alloy_genesis::{Genesis, GenesisAccount};
5use alloy_primitives::{Address, U256};
6use foundry_evm::{
7 backend::DatabaseResult,
8 revm::primitives::{AccountInfo, Bytecode, KECCAK_EMPTY},
9};
10use tokio::sync::RwLockWriteGuard;
11
12#[derive(Clone, Debug, Default)]
14pub struct GenesisConfig {
15 pub number: u64,
17 pub timestamp: u64,
19 pub balance: U256,
21 pub accounts: Vec<Address>,
23 pub genesis_init: Option<Genesis>,
25}
26
27impl GenesisConfig {
28 pub fn account_infos(&self) -> impl Iterator<Item = (Address, AccountInfo)> + '_ {
30 self.accounts.iter().copied().map(|address| {
31 let info = AccountInfo {
32 balance: self.balance,
33 code_hash: KECCAK_EMPTY,
34 code: Some(Default::default()),
36 nonce: 0,
37 };
38 (address, info)
39 })
40 }
41
42 pub fn apply_genesis_json_alloc(
44 &self,
45 mut db: RwLockWriteGuard<'_, Box<dyn Db>>,
46 ) -> DatabaseResult<()> {
47 if let Some(ref genesis) = self.genesis_init {
48 for (addr, mut acc) in genesis.alloc.clone() {
49 let storage = std::mem::take(&mut acc.storage);
50 db.insert_account(addr, self.genesis_to_account_info(&acc));
52 for (k, v) in &storage.unwrap_or_default() {
54 db.set_storage_at(addr, *k, *v)?;
55 }
56 }
57 }
58 Ok(())
59 }
60
61 fn genesis_to_account_info(&self, acc: &GenesisAccount) -> AccountInfo {
63 let GenesisAccount { code, balance, nonce, .. } = acc.clone();
64 let code = code.map(Bytecode::new_raw);
65 AccountInfo {
66 balance,
67 nonce: nonce.unwrap_or_default(),
68 code_hash: code.as_ref().map(|code| code.hash_slow()).unwrap_or(KECCAK_EMPTY),
69 code,
70 }
71 }
72}