Struct Event

Source
pub struct Event<S, E> { /* private fields */ }
Expand description

Represents an EVM event query.

This query builder is designed for fetching specific Solidity events that occurred within the block associated with the provided EvmEnv.

§Filtering Capabilities

This Event query builder is intentionally designed to mirror the structure and capabilities of the [alloy_rpc_types::Filter] type used in standard Ethereum RPC calls, adapted for the constraints of the RISC Zero zkVM environment.

You can filter events based on:

  • Contract Addresses: Use the .address() method to specify the event source:
    • A single address matches only events from this address.
    • Multiple addresses (pass a Vec<Address>) matches events from any contract address.
    • Wildcard (default): If .address() is not called, or if an empty Vec is provided, it matches events from any contract address.
  • Indexed Topics: Use the .topic1(), .topic2() and .topic3() to filter by the indexed arguments of the event:
    • A single value matches only events where the topic has this exact value.
    • Multiple values (pass a Vec<B256>) matches events where the topic matches any value in the list.
    • Wildcard (default): If .topicX() is not called or if an empty Vec is provided, it matches any value for that topic position.

Certain filtering options available in [alloy_rpc_types::Filter] are not applicable or are fixed within the Steel environment:

  • Block Specification: The block context for the query is determined by the EvmEnv (retrieved via env.header()) used to create the Event query. You cannot specify a block range or a different block hash.
  • Topic 0 (Event Signature): This topic is automatically set based on the SolEvent type parameter (S) provided to Event::new or Event::preflight (using S::SIGNATURE_HASH). It cannot be altered or set to a wildcard/list. Anonymous events (where S::ANONYMOUS is true) are not supported.

§Usage

The usage pattern mirrors other Steel interactions like Contract:

  • Preflight calls on the Host: To prepare the event query on the host environment and build the necessary proof, use Event::preflight.
  • Calls in the Guest: To initialize the event query in the guest, use Event::new.

§Examples

Basic usage with a single contract address:

let contract_address = address!("dAC17F958D2ee523a2206206994597C13D831ec7");
sol! {
    interface IERC20 {
        event Transfer(address indexed from, address indexed to, uint256 value);
    }
}

// Host:
let url = "https://ethereum-rpc.publicnode.com".parse()?;
let mut env = EthEvmEnv::builder().rpc(url).chain_spec(&ETH_MAINNET_CHAIN_SPEC).build().await?;
let event = Event::preflight::<IERC20::Transfer>(&mut env).address(contract_address);
event.query().await?;

let evm_input = env.into_input().await?;

// Guest:
let env = evm_input.into_env(&ETH_MAINNET_CHAIN_SPEC);
let event = Event::new::<IERC20::Transfer>(&env).address(contract_address);
let logs = event.query();

Advanced filtering with multiple addresses and topics:


// define multiple contract addresses and potential senders
let usdt_address = address!("dAC17F958D2ee523a2206206994597C13D831ec7");
let usdc_address = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");

sol! {
    interface IERC20 {
        event Transfer(address indexed from, address indexed to, uint256 value);
    }
}

let url = "https://ethereum-rpc.publicnode.com".parse()?;
let mut env = EthEvmEnv::builder().rpc(url).chain_spec(&ETH_MAINNET_CHAIN_SPEC).build().await?;

// Create an event query for Transfer events from *either* USDT or USDC contract,
// originating from *either* sender1 or sender2.
let event = Event::preflight::<IERC20::Transfer>(&mut env)
    // filter by contract address: Match USDT OR USDC
    .address(vec![usdt_address, usdc_address])
    // filter by topic 1 (`from`): Match sender1 OR sender2
    .topic1(vec![
        address!("0000000000000000000000000000000000000001").into_word(),
        address!("0000000000000000000000000000000000000002").into_word(),
    ]);
// topic2 (`to`) and topic3 are left as wildcards

let logs = event.query().await?;

Implementations§

Source§

impl<D, F: EvmFactory, C> Event<(), &mut EvmEnv<ProofDb<D>, F, HostCommit<C>>>
where D: EvmDatabase + Send + 'static, <D as RevmDatabase>::Error: StdError + Send + Sync + 'static,

Source

pub fn preflight<S: SolEvent>( env: &mut EvmEnv<ProofDb<D>, F, HostCommit<C>>, ) -> Event<S, &mut EvmEnv<ProofDb<D>, F, HostCommit<C>>>

Available on crate feature host only.

Constructor for preflighting an event query for a specific EVM event.

Initializes the environment for event queries, fetching necessary data via the Provider, and generating a storage proof for any accessed elements using EvmEnv::into_input.

Source§

impl<S: SolEvent, D, F: EvmFactory, C> Event<S, &mut EvmEnv<ProofDb<D>, F, HostCommit<C>>>
where D: EvmDatabase + Send + 'static, <D as RevmDatabase>::Error: StdError + Send + Sync + 'static,

Source

pub async fn query(self) -> Result<Vec<Log<S>>>

Available on crate feature host only.

Executes the event query using an EvmEnv constructed with Event::preflight.

This uses [tokio::task::spawn_blocking] to run the blocking revm execution.

Source§

impl<F: EvmFactory> Event<(), &EvmEnv<StateDb, F, Commitment>>

Source

pub fn new<S: SolEvent>( env: &EvmEnv<StateDb, F, Commitment>, ) -> Event<S, &EvmEnv<StateDb, F, Commitment>>

Constructor for executing an event query for a specific Solidity event.

Source§

impl<S: SolEvent, F: EvmFactory> Event<S, &EvmEnv<StateDb, F, Commitment>>

Source

pub fn query(self) -> Vec<Log<S>>

Executes the query and returns the matching logs and panics on failure.

A convenience wrapper for Event::try_query, panicking if the call fails. Useful when success is expected.

Source

pub fn try_query(self) -> Result<Vec<Log<S>>>

Attempts to execute the query and returns the matching logs or an error.

Source§

impl<S, E> Event<S, E>

Source

pub fn address<T: Into<ValueOrArray<Address>>>(self, address: T) -> Self

Sets the address to query with this filter.

See [Filter::address].

Source

pub fn topic1<T: Into<Topic>>(self, topic: T) -> Self

Sets the 1st indexed topic.

Source

pub fn topic2<T: Into<Topic>>(self, topic: T) -> Self

Sets the 2nd indexed topic.

Source

pub fn topic3<T: Into<Topic>>(self, topic: T) -> Self

Sets the 3rd indexed topic.

Auto Trait Implementations§

§

impl<S, E> !Freeze for Event<S, E>

§

impl<S, E> RefUnwindSafe for Event<S, E>

§

impl<S, E> Send for Event<S, E>
where E: Send, S: Send,

§

impl<S, E> Sync for Event<S, E>
where E: Sync, S: Sync,

§

impl<S, E> Unpin for Event<S, E>
where E: Unpin, S: Unpin,

§

impl<S, E> UnwindSafe for Event<S, E>
where E: UnwindSafe, S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<TxEnv, T> FromRecoveredTx<&T> for TxEnv
where TxEnv: FromRecoveredTx<T>,

§

fn from_recovered_tx(tx: &&T, sender: Address) -> TxEnv

Builds a [TxEnv] from a transaction and a sender address.
§

impl<TxEnv, T> FromTxWithEncoded<&T> for TxEnv
where TxEnv: FromTxWithEncoded<T>,

§

fn from_encoded_tx(tx: &&T, sender: Address, encoded: Bytes) -> TxEnv

Builds a [TxEnv] from a transaction, its sender, and encoded transaction bytes.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,