use alloy_primitives::{Address, U256};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SlotDelta {
Add(U256),
Sub(U256),
}
impl SlotDelta {
pub fn apply(self, current: U256) -> U256 {
match self {
SlotDelta::Add(amount) => current.saturating_add(amount),
SlotDelta::Sub(amount) => current.saturating_sub(amount),
}
}
}
impl From<SlotDelta> for evm_fork_cache::SlotDelta {
fn from(delta: SlotDelta) -> Self {
match delta {
SlotDelta::Add(amount) => evm_fork_cache::SlotDelta::Add(amount),
SlotDelta::Sub(amount) => evm_fork_cache::SlotDelta::Sub(amount),
}
}
}
impl From<evm_fork_cache::SlotDelta> for SlotDelta {
fn from(delta: evm_fork_cache::SlotDelta) -> Self {
match delta {
evm_fork_cache::SlotDelta::Add(amount) => SlotDelta::Add(amount),
evm_fork_cache::SlotDelta::Sub(amount) => SlotDelta::Sub(amount),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum StateUpdate {
Slot {
address: Address,
slot: U256,
value: U256,
},
SlotDelta {
address: Address,
slot: U256,
delta: SlotDelta,
},
SlotMasked {
address: Address,
slot: U256,
mask: U256,
value: U256,
},
Purge {
address: Address,
scope: PurgeScope,
},
}
impl StateUpdate {
pub fn slot(address: Address, slot: U256, value: U256) -> Self {
Self::Slot {
address,
slot,
value,
}
}
pub fn slot_delta(address: Address, slot: U256, delta: SlotDelta) -> Self {
Self::SlotDelta {
address,
slot,
delta,
}
}
pub fn slot_masked(address: Address, slot: U256, mask: U256, value: U256) -> Self {
Self::SlotMasked {
address,
slot,
mask,
value,
}
}
pub fn purge(address: Address, scope: PurgeScope) -> Self {
Self::Purge { address, scope }
}
}
impl From<StateUpdate> for evm_fork_cache::StateUpdate {
fn from(update: StateUpdate) -> Self {
match update {
StateUpdate::Slot {
address,
slot,
value,
} => evm_fork_cache::StateUpdate::slot(address, slot, value),
StateUpdate::SlotDelta {
address,
slot,
delta,
} => evm_fork_cache::StateUpdate::slot_delta(address, slot, delta.into()),
StateUpdate::SlotMasked {
address,
slot,
mask,
value,
} => evm_fork_cache::StateUpdate::slot_masked(address, slot, mask, value),
StateUpdate::Purge { address, scope } => {
evm_fork_cache::StateUpdate::purge(address, scope.into())
}
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum PurgeScope {
AllStorage,
Slots(Vec<U256>),
}
impl From<PurgeScope> for evm_fork_cache::PurgeScope {
fn from(scope: PurgeScope) -> Self {
match scope {
PurgeScope::AllStorage => evm_fork_cache::PurgeScope::AllStorage,
PurgeScope::Slots(slots) => evm_fork_cache::PurgeScope::Slots(slots),
}
}
}
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SlotChange {
pub address: Address,
pub slot: U256,
pub old: U256,
pub new: U256,
}
impl SlotChange {
pub fn new(address: Address, slot: U256, old: U256, new: U256) -> Self {
Self {
address,
slot,
old,
new,
}
}
}
impl From<evm_fork_cache::SlotChange> for SlotChange {
fn from(change: evm_fork_cache::SlotChange) -> Self {
Self {
address: change.address,
slot: change.slot,
old: change.old,
new: change.new,
}
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SkippedDelta {
pub address: Address,
pub slot: U256,
pub delta: SlotDelta,
}
impl SkippedDelta {
pub fn new(address: Address, slot: U256, delta: SlotDelta) -> Self {
Self {
address,
slot,
delta,
}
}
}
impl From<evm_fork_cache::SkippedDelta> for SkippedDelta {
fn from(skipped: evm_fork_cache::SkippedDelta) -> Self {
Self {
address: skipped.address,
slot: skipped.slot,
delta: skipped.delta.into(),
}
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SkippedMask {
pub address: Address,
pub slot: U256,
pub mask: U256,
pub value: U256,
}
impl SkippedMask {
pub fn new(address: Address, slot: U256, mask: U256, value: U256) -> Self {
Self {
address,
slot,
mask,
value,
}
}
}
impl From<evm_fork_cache::SkippedMask> for SkippedMask {
fn from(skipped: evm_fork_cache::SkippedMask) -> Self {
Self {
address: skipped.address,
slot: skipped.slot,
mask: skipped.mask,
value: skipped.value,
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct StateDiff {
pub slots: Vec<SlotChange>,
pub skipped: Vec<SkippedDelta>,
pub skipped_masks: Vec<SkippedMask>,
}
impl StateDiff {
pub fn is_empty(&self) -> bool {
self.slots.is_empty()
}
pub fn len(&self) -> usize {
self.slots.len()
}
pub fn has_skipped(&self) -> bool {
!self.skipped.is_empty() || !self.skipped_masks.is_empty()
}
}
impl From<evm_fork_cache::StateDiff> for StateDiff {
fn from(diff: evm_fork_cache::StateDiff) -> Self {
Self {
slots: diff.slots.into_iter().map(SlotChange::from).collect(),
skipped: diff.skipped.into_iter().map(SkippedDelta::from).collect(),
skipped_masks: diff
.skipped_masks
.into_iter()
.map(SkippedMask::from)
.collect(),
}
}
}
pub trait StateView {
fn storage(&self, address: Address, slot: U256) -> Option<U256>;
}
pub struct UpstreamStateView<'a>(pub &'a dyn evm_fork_cache::StateView);
impl StateView for UpstreamStateView<'_> {
fn storage(&self, address: Address, slot: U256) -> Option<U256> {
self.0.storage(address, slot)
}
}