anvil/eth/backend/
genesis.rsuse crate::eth::backend::db::Db;
use alloy_genesis::{Genesis, GenesisAccount};
use alloy_primitives::{Address, U256};
use foundry_evm::{
backend::DatabaseResult,
revm::primitives::{AccountInfo, Bytecode, KECCAK_EMPTY},
};
use tokio::sync::RwLockWriteGuard;
#[derive(Clone, Debug, Default)]
pub struct GenesisConfig {
pub timestamp: u64,
pub balance: U256,
pub accounts: Vec<Address>,
pub genesis_init: Option<Genesis>,
}
impl GenesisConfig {
pub fn account_infos(&self) -> impl Iterator<Item = (Address, AccountInfo)> + '_ {
self.accounts.iter().copied().map(|address| {
let info = AccountInfo {
balance: self.balance,
code_hash: KECCAK_EMPTY,
code: Some(Default::default()),
nonce: 0,
};
(address, info)
})
}
pub fn apply_genesis_json_alloc(
&self,
mut db: RwLockWriteGuard<'_, Box<dyn Db>>,
) -> DatabaseResult<()> {
if let Some(ref genesis) = self.genesis_init {
for (addr, mut acc) in genesis.alloc.clone() {
let storage = std::mem::take(&mut acc.storage);
db.insert_account(addr, self.genesis_to_account_info(&acc));
for (k, v) in storage.unwrap_or_default().iter() {
db.set_storage_at(addr, *k, *v)?;
}
}
}
Ok(())
}
fn genesis_to_account_info(&self, acc: &GenesisAccount) -> AccountInfo {
let GenesisAccount { code, balance, nonce, .. } = acc.clone();
let code = code.map(Bytecode::new_raw);
AccountInfo {
balance,
nonce: nonce.unwrap_or_default(),
code_hash: code.as_ref().map(|code| code.hash_slow()).unwrap_or(KECCAK_EMPTY),
code,
}
}
}