use crate::error::InvalidTransaction;
use alloy_primitives::{Address, B256, U256};
use zksync_os_evm_errors::EvmError;
pub trait AnyTracer {
fn as_evm(&mut self) -> Option<&mut impl EvmTracer>;
}
pub trait EvmTracer {
fn on_new_execution_frame(&mut self, request: impl EvmRequest);
fn after_execution_frame_completed(&mut self, result: Option<(EvmResources, CallResult)>);
fn on_storage_read(&mut self, is_transient: bool, address: Address, key: B256, value: B256);
fn on_storage_write(&mut self, is_transient: bool, address: Address, key: B256, value: B256);
fn on_bytecode_change(
&mut self,
address: Address,
new_raw_bytecode: Option<&[u8]>,
new_internal_bytecode_hash: B256,
new_observable_bytecode_length: u32,
);
fn on_event(&mut self, address: Address, topics: Vec<B256>, data: &[u8]);
fn begin_tx(&mut self, calldata: &[u8]);
fn finish_tx(&mut self);
fn before_evm_interpreter_execution_step(
&mut self,
opcode: u8,
frame_state: impl EvmFrameInterface,
);
fn after_evm_interpreter_execution_step(
&mut self,
opcode: u8,
frame_state: impl EvmFrameInterface,
);
fn on_opcode_error(&mut self, error: &EvmError, frame_state: impl EvmFrameInterface);
fn on_call_error(&mut self, error: &EvmError);
fn on_selfdestruct(
&mut self,
beneficiary: Address,
token_value: U256,
frame_state: impl EvmFrameInterface,
);
fn on_create_request(&mut self, is_create2: bool);
}
pub trait EvmRequest {
fn resources(&self) -> EvmResources;
fn caller(&self) -> Address;
fn callee(&self) -> Address;
fn modifier(&self) -> CallModifier;
fn input(&self) -> &[u8];
fn nominal_token_value(&self) -> U256;
}
pub trait EvmFrameInterface {
fn instruction_pointer(&self) -> usize;
fn resources(&self) -> EvmResources;
fn stack(&self) -> &impl EvmStackInterface;
fn caller(&self) -> Address;
fn address(&self) -> Address;
fn calldata(&self) -> &[u8];
fn return_data(&self) -> &[u8];
fn heap(&self) -> &[u8];
fn bytecode(&self) -> &[u8];
fn call_value(&self) -> &U256;
fn refund_counter(&self) -> u32;
fn is_static(&self) -> bool;
fn is_constructor(&self) -> bool;
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct EvmResources {
pub ergs: u64,
pub native: u64,
}
#[allow(clippy::len_without_is_empty)]
pub trait EvmStackInterface {
fn to_slice(&self) -> &[U256];
fn len(&self) -> usize;
fn peek_n(&self, index: usize) -> Result<&U256, EvmError>;
}
pub enum CallResult<'a> {
Failed { returndata: &'a [u8] },
Successful { returndata: &'a [u8] },
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[repr(usize)]
pub enum CallModifier {
#[default]
NoModifier = 0,
Constructor,
Delegate,
Static,
DelegateStatic,
ZKVMSystem,
ZKVMSystemStatic,
EVMCallcode,
EVMCallcodeStatic,
}
#[derive(Default)]
pub struct NopTracer;
impl AnyTracer for NopTracer {
fn as_evm(&mut self) -> Option<&mut impl EvmTracer> {
Some(self)
}
}
impl EvmTracer for NopTracer {
fn on_new_execution_frame(&mut self, _request: impl EvmRequest) {}
fn after_execution_frame_completed(&mut self, _result: Option<(EvmResources, CallResult)>) {}
fn on_storage_read(
&mut self,
_is_transient: bool,
_address: Address,
_key: B256,
_value: B256,
) {
}
fn on_storage_write(
&mut self,
_is_transient: bool,
_address: Address,
_key: B256,
_value: B256,
) {
}
fn on_bytecode_change(
&mut self,
_address: Address,
_new_raw_bytecode: Option<&[u8]>,
_new_internal_bytecode_hash: B256,
_new_observable_bytecode_length: u32,
) {
}
fn on_event(&mut self, _address: Address, _topics: Vec<B256>, _data: &[u8]) {}
fn begin_tx(&mut self, _calldata: &[u8]) {}
fn finish_tx(&mut self) {}
fn before_evm_interpreter_execution_step(
&mut self,
_opcode: u8,
_frame_state: impl EvmFrameInterface,
) {
}
fn after_evm_interpreter_execution_step(
&mut self,
_opcode: u8,
_frame_state: impl EvmFrameInterface,
) {
}
fn on_opcode_error(&mut self, _error: &EvmError, _frame_state: impl EvmFrameInterface) {}
fn on_call_error(&mut self, _error: &EvmError) {}
fn on_selfdestruct(
&mut self,
_beneficiary: Address,
_token_value: U256,
_frame_state: impl EvmFrameInterface,
) {
}
fn on_create_request(&mut self, _is_create2: bool) {}
}
pub type TxValidationResult = Result<(), InvalidTransaction>;
pub struct BeginTxContext<'a> {
pub from: Address,
pub to: Option<Address>,
pub value: U256,
pub calldata: &'a [u8],
pub gas_limit: u64,
}
pub trait AnyTxValidator {
fn as_evm(&mut self) -> Option<&mut impl TxValidator>;
}
impl AnyTxValidator for NopValidator {
#[inline(always)]
fn as_evm(&mut self) -> Option<&mut impl TxValidator> {
Some(self)
}
}
pub trait TxValidator {
fn begin_tx(&mut self, _ctx: &BeginTxContext<'_>) -> TxValidationResult {
Ok(())
}
fn finish_tx(&mut self) -> TxValidationResult {
Ok(())
}
}
#[derive(Default)]
pub struct NopValidator;
impl TxValidator for NopValidator {}