Summary
Scope asynchronous activity-row metadata resolution to the active chain so network switches cannot display stale token symbols or trigger late registry work from an obsolete row.
This is a non-blocking display-correctness issue. It does not affect transaction construction or execution and has no identified funds-at-risk path.
References
Introduced/exposed by:
Affected paths at the merged revision:
Root cause
resolveSymbol() checks resolvedSymbols before ensureClient() validates whether rpcUrl changed. If an address was resolved on chain A, the same address can return the chain-A symbol immediately after switching to chain B without invalidating the cache.
An older chain-A readErc20StringField() call can also complete after chain-B invalidation and write its result into the new cache because asynchronous completions are not associated with an RPC/chain generation.
Separately, ActivityEventRow starts fetchVaultCategory(address) work without watcher cleanup or an event/chain generation check. A row unmounted or replaced during a network switch can therefore initiate later registry resolution against the new global chain. The registry re-resolves against current state, so this does not automatically write chain-A metadata into chain B, but it creates stale cross-chain work and can compound multi-await chain-switch races.
Reproduction scenarios
Cached symbol
- On chain A, resolve an otherwise unknown token address and cache symbol
AAA.
- Switch to chain B, where the same address has symbol
BBB or no token contract.
- Render an oracle-route or resolved-vault activity row containing that address.
resolveSymbol() returns cached AAA before observing the changed RPC URL.
Late completion
- Start a token-symbol lookup on chain A.
- Switch to chain B and trigger cache invalidation.
- Allow the chain-A lookup to resolve afterward.
- Its completion writes the chain-A symbol into the chain-B cache.
Expected behavior
Activity metadata must be derived from the event/current chain consistently. Results started under an obsolete RPC, chain, event, or component lifecycle must not update the active display cache or registry.
Acceptance criteria
Validation notes
The original #774 validation passed focused tests, the full suite, lint, typecheck, production build, and headed desktop/mobile preview smoke. Existing tests cover synchronous display helpers but do not discriminate these network-switch and component-lifecycle races.
Summary
Scope asynchronous activity-row metadata resolution to the active chain so network switches cannot display stale token symbols or trigger late registry work from an obsolete row.
This is a non-blocking display-correctness issue. It does not affect transaction construction or execution and has no identified funds-at-risk path.
References
Introduced/exposed by:
fix: display oracle router activity events60cc27bAffected paths at the merged revision:
useTokenSymbolResolver.ts:16-23— RPC-change invalidationuseTokenSymbolResolver.ts:43-80— cache reads and asynchronous completionActivityEventRow.vue:60-83— token resolver use and asynchronous vault-category watcherActivityEventRow.vue:106-113— activity token-symbol lookupActivityEventRow.vue:198-218— oracle/resolved-vault change renderingRoot cause
resolveSymbol()checksresolvedSymbolsbeforeensureClient()validates whetherrpcUrlchanged. If an address was resolved on chain A, the same address can return the chain-A symbol immediately after switching to chain B without invalidating the cache.An older chain-A
readErc20StringField()call can also complete after chain-B invalidation and write its result into the new cache because asynchronous completions are not associated with an RPC/chain generation.Separately,
ActivityEventRowstartsfetchVaultCategory(address)work without watcher cleanup or an event/chain generation check. A row unmounted or replaced during a network switch can therefore initiate later registry resolution against the new global chain. The registry re-resolves against current state, so this does not automatically write chain-A metadata into chain B, but it creates stale cross-chain work and can compound multi-await chain-switch races.Reproduction scenarios
Cached symbol
AAA.BBBor no token contract.resolveSymbol()returns cachedAAAbefore observing the changed RPC URL.Late completion
Expected behavior
Activity metadata must be derived from the event/current chain consistently. Results started under an obsolete RPC, chain, event, or component lifecycle must not update the active display cache or registry.
Acceptance criteria
USD,EUR,BTC,ETH) and current same-chain caching behavior.ActivityEventRowvault-category watcher with Vue cleanup or an equivalent{ event.id, event.chainId, address }generation guard.Validation notes
The original #774 validation passed focused tests, the full suite, lint, typecheck, production build, and headed desktop/mobile preview smoke. Existing tests cover synchronous display helpers but do not discriminate these network-switch and component-lifecycle races.