use std::collections::HashMap;
use alloy_primitives::{Address, U256};
use crate::{
error::{DataNetworkPrecompileError, Result},
storage::PrecompileStorageProvider,
};
#[derive(Debug, Default)]
pub struct HashMapStorageProvider {
internals: HashMap<(Address, U256), U256>,
fail_on_sload: Option<(Address, U256)>,
is_static: bool,
counter_sload: u64,
counter_sstore: u64,
}
impl HashMapStorageProvider {
pub fn new() -> Self {
Self::default()
}
pub fn with_static(mut self, is_static: bool) -> Self {
self.is_static = is_static;
self
}
}
impl PrecompileStorageProvider for HashMapStorageProvider {
fn sload(&mut self, address: Address, key: U256) -> Result<U256> {
if self.fail_on_sload == Some((address, key)) {
return Err(DataNetworkPrecompileError::Fatal(
"injected sload failure".into(),
));
}
self.counter_sload += 1;
Ok(self
.internals
.get(&(address, key))
.copied()
.unwrap_or(U256::ZERO))
}
fn sstore(&mut self, address: Address, key: U256, value: U256) -> Result<()> {
self.counter_sstore += 1;
self.internals.insert((address, key), value);
Ok(())
}
fn is_static(&self) -> bool {
self.is_static
}
}
impl HashMapStorageProvider {
pub fn fail_next_sload_at(&mut self, address: Address, slot: U256) {
self.fail_on_sload = Some((address, slot));
}
pub fn counter_sload(&self) -> u64 {
self.counter_sload
}
pub fn counter_sstore(&self) -> u64 {
self.counter_sstore
}
pub fn reset_counters(&mut self) {
self.counter_sload = 0;
self.counter_sstore = 0;
}
pub fn into_storage(self) -> impl Iterator<Item = (Address, U256, U256)> {
self.internals
.into_iter()
.map(|((address, slot), value)| (address, slot, value))
}
}