Skip to main content

foundry_evm_core/
env.rs

1pub use alloy_evm::EvmEnv;
2use revm::{
3    Context, Database, Journal, JournalEntry,
4    context::{BlockEnv, CfgEnv, JournalInner, JournalTr, TxEnv},
5    primitives::hardfork::SpecId,
6};
7
8/// Helper container type for [`EvmEnv`] and [`TxEnv`].
9#[derive(Clone, Debug, Default)]
10pub struct Env {
11    pub evm_env: EvmEnv,
12    pub tx: TxEnv,
13}
14
15/// Helper container type for [`EvmEnv`] and [`TxEnv`].
16impl Env {
17    pub fn default_with_spec_id(spec_id: SpecId) -> Self {
18        let mut cfg = CfgEnv::default();
19        cfg.spec = spec_id;
20
21        Self::from(cfg, BlockEnv::default(), TxEnv::default())
22    }
23
24    pub fn from(cfg: CfgEnv, block: BlockEnv, tx: TxEnv) -> Self {
25        Self { evm_env: EvmEnv { cfg_env: cfg, block_env: block }, tx }
26    }
27
28    pub fn new_with_spec_id(cfg: CfgEnv, block: BlockEnv, tx: TxEnv, spec_id: SpecId) -> Self {
29        let mut cfg = cfg;
30        cfg.spec = spec_id;
31
32        Self::from(cfg, block, tx)
33    }
34}
35
36/// Helper struct with mutable references to the block and cfg environments.
37pub struct EnvMut<'a> {
38    pub block: &'a mut BlockEnv,
39    pub cfg: &'a mut CfgEnv,
40    pub tx: &'a mut TxEnv,
41}
42
43impl EnvMut<'_> {
44    /// Returns a copy of the environment.
45    pub fn to_owned(&self) -> Env {
46        Env {
47            evm_env: EvmEnv { cfg_env: self.cfg.to_owned(), block_env: self.block.to_owned() },
48            tx: self.tx.to_owned(),
49        }
50    }
51
52    /// Writes an owned [`Env`] back into the context.
53    ///
54    /// Counterpart to [`to_owned`](Self::to_owned): completes the read/write pair so callers
55    /// that receive an updated [`Env`] by value (e.g. after a fork switch or snapshot revert)
56    /// can apply it without manually assigning each field.
57    pub fn set_env(&mut self, env: Env) {
58        *self.block = env.evm_env.block_env;
59        *self.cfg = env.evm_env.cfg_env;
60        *self.tx = env.tx;
61    }
62}
63
64pub trait AsEnvMut {
65    fn as_env_mut(&mut self) -> EnvMut<'_>;
66}
67
68impl AsEnvMut for EnvMut<'_> {
69    fn as_env_mut(&mut self) -> EnvMut<'_> {
70        EnvMut { block: self.block, cfg: self.cfg, tx: self.tx }
71    }
72}
73
74impl AsEnvMut for Env {
75    fn as_env_mut(&mut self) -> EnvMut<'_> {
76        EnvMut {
77            block: &mut self.evm_env.block_env,
78            cfg: &mut self.evm_env.cfg_env,
79            tx: &mut self.tx,
80        }
81    }
82}
83
84impl<DB: Database, J: JournalTr<Database = DB>, C> AsEnvMut
85    for Context<BlockEnv, TxEnv, CfgEnv, DB, J, C>
86{
87    fn as_env_mut(&mut self) -> EnvMut<'_> {
88        EnvMut { block: &mut self.block, cfg: &mut self.cfg, tx: &mut self.tx }
89    }
90}
91
92pub trait ContextExt {
93    type DB: Database;
94
95    fn as_db_env_and_journal(
96        &mut self,
97    ) -> (&mut Self::DB, &mut JournalInner<JournalEntry>, EnvMut<'_>);
98}
99
100impl<DB: Database, C> ContextExt
101    for Context<BlockEnv, TxEnv, CfgEnv, DB, Journal<DB, JournalEntry>, C>
102{
103    type DB = DB;
104
105    fn as_db_env_and_journal(
106        &mut self,
107    ) -> (&mut Self::DB, &mut JournalInner<JournalEntry>, EnvMut<'_>) {
108        (
109            &mut self.journaled_state.database,
110            &mut self.journaled_state.inner,
111            EnvMut { block: &mut self.block, cfg: &mut self.cfg, tx: &mut self.tx },
112        )
113    }
114}