Skip to content

feat(cast): add events command - #16238

Open
stevencartavia wants to merge 9 commits into
masterfrom
steven/cast-events-command
Open

feat(cast): add events command#16238
stevencartavia wants to merge 9 commits into
masterfrom
steven/cast-events-command

Conversation

@stevencartavia

Copy link
Copy Markdown
Member

Adds cast events to fetch and decode events from a transaction receipt or a cast logs-style filter. It supports transaction hashes, addresses, block ranges, topics, and chunked queries, using address-specific explorer ABIs and signature lookup with raw-log fallback.

The command provides readable human output and structured JSON while preserving log metadata and ordering. Proxy diagnostics are routed to stderr so stdout remains machine-readable.

Closes #2340.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Changelog found

The deterministic check will validate the changed entry.

Comment thread crates/evm/traces/src/decoder/mod.rs
Comment thread crates/evm/traces/src/decoder/mod.rs
Comment thread crates/evm/traces/src/decoder/mod.rs
Comment thread crates/cast/src/cmd/events.rs Outdated
Comment thread crates/cast/src/cmd/events.rs Outdated
Comment thread crates/cast/src/cmd/events.rs Outdated
@stevencartavia
stevencartavia requested a review from mablr August 19, 2026 15:23
Comment thread crates/evm/traces/src/identifier/external.rs Outdated
Comment thread crates/evm/traces/src/identifier/external.rs Outdated
@stevencartavia
stevencartavia requested a review from mablr August 19, 2026 17:22

@mattsse mattsse left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few nits+suggestions

Comment thread crates/cast/src/cmd/logs.rs
Comment thread crates/evm/traces/src/identifier/external.rs Outdated
Comment thread crates/cast/src/cmd/events.rs
Comment thread crates/cast/src/cmd/events.rs Outdated
Comment thread crates/cast/src/cmd/events.rs

@mattsse mattsse left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recursive ABI lookup currently regresses proxy trace identities and is responsible for the remaining main CI failure. Please keep address-local identity metadata separate from the full ABI chain used by cast events.

Comment thread crates/evm/traces/src/identifier/external.rs Outdated
.into_iter()
.zip(addresses.iter().copied())
.map(|(chain, address)| {
let result = if chain.abis.is_empty() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the proxy's own ABI fetch succeeds but the implementation fetch fails mid-chain, chain.abis is still non-empty here, so this returns Ok indistinguishable from full success. decode_logs in events.rs only warns on Err, so a partially-resolved proxy silently loses all implementation events with no diagnostic.

.zip(addresses.iter().copied())
.map(|(chain, address)| {
let result = if chain.abis.is_empty() {
Err(eyre::eyre!("external ABI lookup failed"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This collapses every failure cause (rate limit, bad API key, Cloudflare block, genuinely unverified) into one fixed string. The real EtherscanError is warn!-logged in the fetcher but never makes it into self.contracts, so sh_warn!("Failed to fetch ABI for {address}: {err}") in events.rs can never say anything more specific than "external ABI lookup failed".

if let Some(decoded) = decoded {
return decoded;
}
if canonical_signature && regular_events.is_some() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regular_events.is_some() only means an event is registered for this key, not that it decoded successfully. If every candidate here fails decode_log but a uniquely-matching anonymous event exists for the same address/topic-count, this returns undecoded before ever reaching the anonymous_events branch below.

decoder.decode_event_with_address_signature(log.address(), log.data()).await;
EventOutput::new(log, decoded.name, decoded.params)
})
.buffered(MAX_CONCURRENT_RPC_REQUESTS)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SignaturesIdentifier::identify has no in-flight coalescing (checks cache under a read lock, then separately acquires a write lock to fetch), concurrent decode tasks resolving the same unresolved topic0 each issue their own OpenChain HTTP request instead of sharing one lookup.

}

/// Fetches all verified ABIs for each address using the configured external sources.
pub async fn get_abis(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reimplements proxy-chain following (walk proxy/implementation, cycle-guard, accumulate ABIs) that already exists as find_source in crates/common/src/abi.rs, with different depth/cycle handling and no shared fallback logic. A future proxy-detection fix would need to be applied in both places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

feat(cast): add cast events <txHash> to fetch and format events from receipt

3 participants