use crate::{
helpers::Ctx, EvmErrored, EvmNeedsTx, EvmReady, EvmTransacted, NeedsTx, TransactedState, Trevm,
};
use alloy::primitives::Bytes;
use revm::{
context::{
result::{ExecutionResult, ResultAndState},
ContextTr,
},
database::TryDatabaseCommit,
state::EvmState,
Database, DatabaseCommit, Inspector,
};
impl<Db, Insp> AsRef<ResultAndState> for EvmTransacted<Db, Insp>
where
Db: Database,
Insp: Inspector<Ctx<Db>>,
{
fn as_ref(&self) -> &ResultAndState {
&self.state.result
}
}
impl<Db, Insp> AsRef<ExecutionResult> for EvmTransacted<Db, Insp>
where
Db: Database,
Insp: Inspector<Ctx<Db>>,
{
fn as_ref(&self) -> &ExecutionResult {
&self.state.result.result
}
}
impl<Db, Insp> EvmTransacted<Db, Insp>
where
Db: Database,
Insp: Inspector<Ctx<Db>>,
{
pub fn result(&self) -> &ExecutionResult {
self.as_ref()
}
pub const fn result_mut_unchecked(&mut self) -> &mut ExecutionResult {
&mut self.state.result.result
}
pub const fn state(&self) -> &EvmState {
&self.state.result.state
}
pub const fn state_mut_unchecked(&mut self) -> &mut EvmState {
&mut self.state.result.state
}
pub fn result_and_state(&self) -> &ResultAndState {
self.as_ref()
}
pub const fn result_and_state_mut_unchecked(&mut self) -> &mut ResultAndState {
&mut self.state.result
}
pub fn output(&self) -> Option<&Bytes> {
self.result().output()
}
pub fn output_sol<T: alloy::sol_types::SolCall>(
&self,
validate: bool,
) -> Option<alloy::sol_types::Result<T::Return>>
where
T::Return: alloy::sol_types::SolType,
{
if validate {
return self.output().map(|output| T::abi_decode_returns_validate(output));
}
self.output().map(|output| T::abi_decode_returns(output))
}
pub fn gas_used(&self) -> u64 {
self.state.result.result.gas_used()
}
pub fn reject(self) -> EvmNeedsTx<Db, Insp> {
Trevm { inner: self.inner, state: NeedsTx::new() }
}
pub fn into_result_and_state(self) -> ResultAndState {
self.state.result
}
pub fn take_result_and_state(self) -> (ResultAndState, EvmNeedsTx<Db, Insp>) {
let Self { inner, state: TransactedState { result } } = self;
(result, Trevm { inner, state: NeedsTx::new() })
}
pub fn take_result(self) -> (ExecutionResult, EvmNeedsTx<Db, Insp>) {
let Self { inner, state: TransactedState { result } } = self;
(result.result, Trevm { inner, state: NeedsTx::new() })
}
pub fn accept(self) -> (ExecutionResult, EvmNeedsTx<Db, Insp>)
where
Db: DatabaseCommit,
{
let Self { mut inner, state: TransactedState { result } } = self;
inner.db_mut().commit(result.state);
(result.result, Trevm { inner, state: NeedsTx::new() })
}
#[allow(clippy::type_complexity)]
pub fn try_accept(
self,
) -> Result<
(ExecutionResult, EvmNeedsTx<Db, Insp>),
EvmErrored<Db, Insp, <Db as TryDatabaseCommit>::Error>,
>
where
Db: TryDatabaseCommit,
{
let Self { mut inner, state: TransactedState { result } } = self;
trevm_try!(inner.db_mut().try_commit(result.state), Trevm { inner, state: NeedsTx::new() });
Ok((result.result, Trevm { inner, state: NeedsTx::new() }))
}
pub fn accept_state(self) -> EvmNeedsTx<Db, Insp>
where
Db: DatabaseCommit,
{
self.accept().1
}
pub fn try_accept_state(
self,
) -> Result<EvmNeedsTx<Db, Insp>, EvmErrored<Db, Insp, <Db as TryDatabaseCommit>::Error>>
where
Db: TryDatabaseCommit,
{
self.try_accept().map(|(_, evm)| evm)
}
#[cfg(feature = "estimate_gas")]
pub fn estimation(&self) -> crate::EstimationResult {
use crate::EstimationResult;
EstimationResult::from_limit_and_execution_result(self.gas_limit(), self.result())
}
#[cfg(feature = "estimate_gas")]
pub fn take_estimation(self) -> (crate::EstimationResult, EvmReady<Db, Insp>) {
let estimation = self.estimation();
(estimation, Trevm { inner: self.inner, state: crate::Ready::new() })
}
}