Skip to content
This repository was archived by the owner on Aug 5, 2026. It is now read-only.
This repository was archived by the owner on Aug 5, 2026. It is now read-only.

ENSIndexer: Resolver.extended (is_extended) goes stale for proxy resolvers that activate IExtendedResolver after assignment — breaks wildcard resolution (.box) #2275

Description

@shrugs

Summary

The resolvers.is_extended flag (whether a Resolver implements ENSIP-10 IExtendedResolver, surfaced as Resolver.extended) is classified once, at the block the resolver is first seen, via an eip-165 supportsInterface probe through Ponder's context.client. For proxy resolvers that activate IExtendedResolver after they're assigned (deploy-then-upgrade / lazy-init — extremely common), the flag is computed against the pre-upgrade implementation and gets stuck false forever.

Because extended must stay indexed (we deliberately avoid an RPC probe at omnigraph-query / accelerated-resolution time), a stale false silently breaks wildcard resolution: affected names don't virtualize into UnindexedDomain and Domain.resolve returns null. This hits whole TLDs (e.g. .box / 3DNS) and any wildcard whose resolver was a proxy at assignment time.

Evidence (cast, mainnet)

box TLD resolver 0xf97aac6c8dbaebcb54ff166d79706e3af7a813c8 (EIP-1967 proxy):

block event supportsInterface(IExtendedResolver=0x9061b923)
19128555 (2024-01-31) proxy deployed and set as box's resolver (same block); impl slot = 0xb4cd…959b reverts
19128940 (~1.3h later) EIP-1967 Upgraded → impl slot = 0xee65…4546 true (from here on)

ENSIndexer probed supportsInterface at the assignment block (19128555, old impl → revert) → cached is_extended=false. Never re-checked. Result: mystery.box returns domain: null instead of resolving (0x130EF17d1E1616470B3c51AfDf31625B7F767562).

Requirements

  • Keep extended indexed — no supportsInterface RPC at query / acceleration time.
  • Agreed direction: classify on first visibility + re-check on known upgrade patterns.

Constraints / why the obvious approaches don't work

  1. "Just probe at latest/finalized instead of the event block." We don't trivially have access to "the most recent block" inside the indexing context, so we can't simply move the probe to head.
  2. Ponder factory() to watch each resolver's Upgraded events won't work. NewResolver registers/references a pre-existing contract, it doesn't create it — so Ponder only sees the resolver from its "connection" point forward and misses upgrade events prior to first visibility. Not a general solution.

Proposed approach (scope: support the .box case for now)

  • Initial classification at first visibility (current behavior) — keep.
  • Re-check is_extended when the resolver undergoes a known proxy upgrade pattern, re-running the eip-165 probe and updating the row:
    • EIP-1967 Upgraded(address) (transparent / UUPS) — the .box case
    • BeaconUpgraded(address) + the beacon's Upgraded (beacon proxies — one beacon ⇒ many resolvers)
    • (later) EIP-2535 DiamondCut if any resolver uses facets
  • Open design question: how to observe these upgrade events given constraint NameWrapper + Checkpointing #2 (factory won't catch pre-visibility upgrades). Options to evaluate: a topic-scoped Upgraded log source filtered to known resolver addresses; statically watching the known 3DNS resolver/beacon contracts; or a bounded re-probe of resolvers on a finalized cadence. Pick the narrowest thing that fixes .box.

Stopgap already applied (current 1.15.2 green index)

Manually set is_extended=true for 1-0xf97aac6c8dbaebcb54ff166d79706e3af7a813c8 in alphaSchema1.15.2 (session-local session_replication_role=replica to bypass the live_query/reorg triggers). Verified: mystery.box → 0x130EF…7562. The real fix lands in the next release.

Related

Sibling resolution-robustness fix (separate, already patched in working tree): multicoin addr(node, 60) decode crashes when a resolver returns address-encoding instead of bytes (e.g. world.id) — apps/ensapi/src/lib/resolution/execute-operations.ts.

Part of #1360.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions