Skip to content

Comments

ENSv2: Refactor Namechain#1659

Open
shrugs wants to merge 7 commits intomainfrom
feat/l1-v2
Open

ENSv2: Refactor Namechain#1659
shrugs wants to merge 7 commits intomainfrom
feat/l1-v2

Conversation

@shrugs
Copy link
Collaborator

@shrugs shrugs commented Feb 20, 2026

removes namechain/l2 concepts, simplifies ensv2 to single-chain

Reviewer Focus (Read This First)

the simplification of v2_getDomainIdByFqdn — the old ETHTLDResolver bridging logic that forwarded from l1 ENSv2 to a namechain l2 ETH registry is removed entirely. reviewers should verify the new behavior (exact match only, return null otherwise) is correct for the current ENSv2 architecture.


Problem & Motivation

ENSv2 no longer uses a separate namechain/l2 for the ETH registry. the ENSv2ETHRegistry datasource and all namechain-specific logic were built around a two-chain model (l1 root registry + l2 ETH registry). with the updated contracts-v2 deployment, everything lives on a single chain, so the l2 chain and bridging resolver logic is obsolete.


What Changed (Concrete)

  1. removed ensTestEnvL2Chain and ensTestEnvL1Chain; replaced with ensTestEnvChain (chain id 0xeeeeed)
  2. removed DatasourceNames.ENSv2ETHRegistry datasource type and all usages
  3. updated ens-test-env contract addresses to match the new contracts-v2 deployment
  4. moved ETHRegistry and ETHRegistrar contracts into ENSv2Root datasource (previously they were in a separate ENSv2ETHRegistry datasource on the l2 chain)
  5. removed ETHRegistrar from sepolia-v2 ENSv2ETHRegistry block; moved into ENSv2Root
  6. simplified v2_getDomainIdByFqdn — removed ETHTLDResolver bridging logic (was: traverse l1 → bridge to l2 eth registry if path terminates at .eth; now: exact match only, null otherwise)
  7. removed ENSv2ETHRegistry from DATASOURCE_NAMES_WITH_ENSv2_CONTRACTS and ensv2 plugin's ALL_DATASOURCE_NAMES
  8. removed registryCanonicalDomain write for the l2 ETH registry in ENSv2Registry.ts handler; left a TODO(bridged-registries) for future generalization

Design & Planning

the new contracts-v2 deployment collapses the two-chain model into one. this PR mechanically removes all code that existed solely to support the l2 chain.

  • planning artifacts: none (mechanical removal following upstream contract changes)
  • reviewed / approved by: n/a

Self-Review

nothing notable.

  • bugs caught: none
  • logic simplified: yes — v2_getDomainIdByFqdn went from ~100 lines to ~10
  • naming / terminology improved: ensTestEnvL1ChainensTestEnvChain, removed "namechain" references
  • dead or unnecessary code removed: yes — all l2/namechain branching logic

Cross-Codebase Alignment

  • search terms used: ENSv2ETHRegistry, ensTestEnvL2Chain, ensTestEnvL1Chain, namechain, ETHTLDResolver
  • reviewed but unchanged: sepolia.ts (no ENSv2ETHRegistry there), ensv2 handlers beyond ENSv2Registry.ts
  • deferred alignment: TODO(bridged-registries) left in ENSv2Registry.ts for future generalized bridging resolver support

Downstream & Consumer Impact

  • public APIs affected: ensTestEnvL1Chain and ensTestEnvL2Chain exports removed from @ensnode/datasources; callers must switch to ensTestEnvChain
  • docs updated: n/a
  • naming decisions worth calling out: unified chain export name reflects the single-chain nature of the new deployment

Testing Evidence

  • testing performed: updated config tests to assert only ensTestEnvChain.id is present; updated RPC URL build tests; CI typecheck/lint
  • known gaps: no integration tests against the new ens-test-env contract addresses
  • what reviewers have to reason about manually: correctness of the new v2_getDomainIdByFqdn (exact-match-only semantics) for the current ENSv2 spec

Scope Reductions

  • follow-ups: generalize registryCanonicalDomain writes for bridged registries (TODO(bridged-registries))
  • why they were deferred: not needed for single-chain model; design is still tbd

Risk Analysis

  • risk areas: ens-test-env contract addresses — if the new addresses are wrong, local dev/test will break silently
  • named owner: @shrugs

Pre-Review Checklist (Blocking)

  • I reviewed every line of this diff and understand it end-to-end
  • I'm prepared to defend this PR line-by-line in review
  • I'm comfortable being the on-call owner for this change
  • Relevant changesets are included (or explicitly not required)

Copilot AI review requested due to automatic review settings February 20, 2026 23:27
@shrugs shrugs requested a review from a team as a code owner February 20, 2026 23:27
@changeset-bot
Copy link

changeset-bot bot commented Feb 20, 2026

🦋 Changeset detected

Latest commit: d343c2a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
ensindexer Major
ensapi Major
ensadmin Major
ensrainbow Major
fallback-ensapi Major
@ensnode/datasources Major
@ensnode/ensrainbow-sdk Major
@ensnode/ponder-metadata Major
@ensnode/ensnode-schema Major
@ensnode/ensnode-react Major
@ensnode/ensnode-sdk Major
@ensnode/ponder-sdk Major
@ensnode/ponder-subgraph Major
@ensnode/shared-configs Major
@docs/ensnode Major
@docs/ensrainbow Major
@docs/mintlify Major
@namehash/ens-referrals Major
@namehash/namehash-ui Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Contributor

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Feb 21, 2026 0:48am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
ensnode.io Skipped Skipped Feb 21, 2026 0:48am
ensrainbow.io Skipped Skipped Feb 21, 2026 0:48am

@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

📝 Walkthrough

Walkthrough

The PR consolidates test env chains into a single ensTestEnvChain, removes the ENSv2ETHRegistry datasource, simplifies ENSv2 domain lookup by removing bridging/ETHTLDResolver logic, and updates devnet contract addresses to align with the ENSv2 refactor onto the ENS Root Chain.

Changes

Cohort / File(s) Summary
Changeset and Version Bump
.changeset/large-cameras-cross.md
Added changeset; bumps minor versions for ensindexer and ensapi, aligning ens-test-env to devnet commit 762de44.
Chain Definition Consolidation
packages/datasources/src/lib/chains.ts
Replaced ensTestEnvL1Chain/ensTestEnvL2Chain with single ensTestEnvChain; added DEVNET_DEFAULT_CHAIN_ID (0xeeeeed); removed L1/L2 constants.
Datasource Removal (ENSv2ETHRegistry)
packages/datasources/src/lib/types.ts, packages/datasources/src/sepolia-v2.ts, packages/datasources/src/ens-test-env.ts, packages/ensnode-sdk/src/shared/datasources-with-ensv2-contracts.ts
Removed ENSv2ETHRegistry from types and all datasource mappings; updated datasources set to exclude ENSv2ETHRegistry.
ENSv2 Plugin & Handler Updates
apps/ensindexer/src/plugins/ensv2/plugin.ts, apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts
Plugin wiring now references ENSv2Root (removed ENSv2ETHRegistry); removed bridging/canonical-domain assignment and related imports/logic from registry handler.
ENS v2 Lookup Simplification
apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts
Removed ENSv2 bridging and ETHTLDResolver branches; v2 lookup now uses rootRegistryId and returns exact leaf domain ID or null for non-exact matches; removed bridging invariants/logging.
Public client CCIP-Read cleanup
apps/ensapi/src/lib/public-client.ts
Removed custom CCIP-Read fallback (ccipRequest) and ensTestEnvL1Chain-specific handler; now uses default CCIP-Read behavior.
Test & Helper Adjustments
apps/ensindexer/src/config/config.test.ts, apps/ensindexer/src/lib/ponder-helpers.ts, packages/ensnode-sdk/src/shared/config/build-rpc-urls.test.ts, packages/ensnode-sdk/src/shared/config/rpc-configs-from-env.ts
Replaced L1/L2 test-chain references with ensTestEnvChain; updated local-chain detection and related test assertions.
Datasources Update (ens-test-env)
packages/datasources/src/ens-test-env.ts
Consolidated chain refs to ensTestEnvChain; updated many devnet contract addresses (ENSRoot, ENSv2Root, UniversalResolver, added UniversalResolverV2, reverse resolver entries).
UI Chain Mapping Updates
packages/namehash-ui/src/components/chains/ChainIcon.tsx, packages/namehash-ui/src/utils/chains.ts
Replaced ensTestEnvL1Chain with ensTestEnvChain in icons, supported chains, and custom chain name mappings.
Docs/JSDoc and Minor Adjustments
packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts
Updated JSDoc @see URL from Namechain to contracts-v2; no behavior changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

ensnode-sdk, ensnode-internal

Poem

🐇 Two chains once hopped across the lea,
One root now stands where both used to be,
Bridging trimmed and addresses set true,
Devnet sings a cleaner view — hop, hop, woohoo!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ENSv2: Refactor Namechain' accurately summarizes the main change: removing namechain/L2 concepts and refactoring ENSv2 to a single-chain model.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering all required template sections: Summary, Why, Testing, Notes for Reviewer, and Pre-Review Checklist with detailed concrete changes and design rationale.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/l1-v2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 20, 2026

Greptile Summary

This PR mechanically removes the namechain/L2 concepts from ENSv2, consolidating from a two-chain model (L1 root + L2 ETH registry) to a single-chain architecture. All ENSv2 contracts now live on one chain (ID 0xeeeeed), and the complex ETHTLDResolver bridging logic that forwarded .eth queries from L1 to L2 has been replaced with simple exact-match semantics.

Major changes:

  • Replaced ensTestEnvL1Chain and ensTestEnvL2Chain with unified ensTestEnvChain (chain ID changed from 0xeeeeee/0xeeeeee-1 to 0xeeeeed)
  • Removed DatasourceNames.ENSv2ETHRegistry datasource type entirely
  • Moved ETHRegistry and ETHRegistrar contracts from separate L2 datasource into ENSv2Root datasource
  • Simplified v2_getDomainIdByFqdn from ~100 lines to ~10 by removing all bridging resolver logic
  • Updated ens-test-env contract addresses to match new devnet deployment (commit 762de44)
  • Removed registryCanonicalDomain write for L2 ETH registry; left TODO(bridged-registries) for future work

Key reviewer concern:
The simplified v2_getDomainIdByFqdn now returns exact matches only, with no fallback to bridging resolvers. This is correct for the new single-chain ENSv2 architecture, but reviewers should verify this aligns with the current ENSv2 spec.

Confidence Score: 4/5

  • This PR is safe to merge with low risk, contingent on correct upstream contract addresses
  • The refactor is mechanical and well-documented. The main risk is if the new ens-test-env contract addresses are incorrect, which would silently break local dev/test environments. The simplified v2_getDomainIdByFqdn logic appears correct for single-chain architecture, but cannot be fully verified without integration tests against the new deployment.
  • Pay close attention to packages/datasources/src/ens-test-env.ts (contract addresses must match devnet deployment) and apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts (verify exact-match-only semantics are correct for ENSv2 spec)

Important Files Changed

Filename Overview
apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts Simplifies v2_getDomainIdByFqdn from ~100 lines to ~10 by removing ETHTLDResolver bridging logic; now returns exact match only
apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts Removes L2 ETH registry canonical domain write logic; replaces with TODO for future bridged-registries generalization
apps/ensindexer/src/plugins/ensv2/plugin.ts Removes ENSv2ETHRegistry from datasource names; moves ETHRegistrar from L2 to ENSv2Root
packages/datasources/src/ens-test-env.ts Consolidates ENSv2 contracts onto single chain; updates all contract addresses to match new devnet deployment; removes ENSv2ETHRegistry datasource
packages/datasources/src/lib/chains.ts Replaces L1/L2 chain definitions with single ensTestEnvChain using new chain ID 0xeeeeed
packages/datasources/src/sepolia-v2.ts Moves ETHRegistrar from ENSv2ETHRegistry datasource into ENSv2Root; removes separate L2 datasource block

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ENSv2 Architecture] --> B{Before: Two-Chain Model}
    A --> C{After: Single-Chain Model}
    
    B --> D[L1: ENS Root Chain<br/>Chain ID: 0xeeeeee - 1]
    B --> E[L2: Namechain<br/>Chain ID: 0xeeeeee]
    
    D --> F[ENSv2Root Datasource<br/>RootRegistry + ETHRegistry]
    E --> G[ENSv2ETHRegistry Datasource<br/>ETHRegistry + ETHRegistrar]
    
    F --> H[ETHTLDResolver Logic<br/>Bridge L1 → L2 for .eth]
    H --> I[Check ENSv1 Registration]
    I --> J{Active?}
    J -->|Yes| K[Return v1Domain]
    J -->|No| L[Forward to L2 ETHRegistry]
    
    C --> M[Single Chain<br/>Chain ID: 0xeeeeed]
    M --> N[ENSv2Root Datasource<br/>RootRegistry + ETHRegistry + ETHRegistrar]
    
    N --> O[Simple Exact Match<br/>No bridging logic]
    O --> P{Exact match?}
    P -->|Yes| Q[Return v2Domain]
    P -->|No| R[Return null]
    
    style B fill:#ffcccc
    style C fill:#ccffcc
    style G fill:#ffcccc
    style H fill:#ffcccc
    style N fill:#ccffcc
    style O fill:#ccffcc
Loading

Last reviewed commit: 6ccee1b

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

16 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors ENSv2 to a single-chain model by removing the namechain/L2 ETH registry datasource and associated bridging logic, updating devnet/sepolia-v2 datasource layouts, and simplifying ENSv2 domain lookup semantics.

Changes:

  • Removes ENSv2ETHRegistry datasource/type and consolidates ENSv2 contracts under ENSv2Root.
  • Replaces ensTestEnvL1Chain/ensTestEnvL2Chain with a single ensTestEnvChain and updates RPC/test logic accordingly.
  • Simplifies v2_getDomainIdByFqdn to “exact match only” (no ETHTLDResolver bridging traversal).

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/namehash-ui/src/utils/chains.ts Switches UI-supported chains and custom names to ensTestEnvChain.
packages/namehash-ui/src/components/chains/ChainIcon.tsx Updates ens-test-env icon mapping to the unified chain id export.
packages/ensnode-sdk/src/shared/datasources-with-ensv2-contracts.ts Removes ENSv2ETHRegistry from the “ENSv2 contracts” datasource list.
packages/ensnode-sdk/src/shared/config/rpc-configs-from-env.ts Collapses dual local-chain RPC injection into ensTestEnvChain.
packages/ensnode-sdk/src/shared/config/build-rpc-urls.test.ts Updates tests to expect only one local chain id for ens-test-env.
packages/datasources/src/sepolia-v2.ts Removes ENSv2ETHRegistry block and places ETH registrar config under ENSv2Root.
packages/datasources/src/lib/types.ts Deletes DatasourceNames.ENSv2ETHRegistry.
packages/datasources/src/lib/chains.ts Replaces L1/L2 devnet chain constants with a single ensTestEnvChain.
packages/datasources/src/ens-test-env.ts Updates devnet datasource chain and contracts to new contracts-v2 deployment addresses and layout.
apps/ensindexer/src/plugins/ensv2/plugin.ts Removes ENSv2ETHRegistry usage and reads ETHRegistrar from ENSv2Root.
apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts Removes ETH-registry canonical-domain write, leaving a TODO for future bridged registries.
apps/ensindexer/src/lib/ponder-helpers.ts Updates local-chain cache disabling to the unified ensTestEnvChain.
apps/ensindexer/src/config/config.test.ts Updates config tests to assert only ensTestEnvChain.id is present.
apps/ensapi/src/lib/public-client.ts Updates ens-test-env chain id check for CCIP-read fallback behavior.
apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts Removes ENSv2 bridging/ETHTLDResolver logic; returns ENSv2 domain only on exact match.
.changeset/large-cameras-cross.md Adds a changeset noting ens-test-env now targets contracts-v2 devnet commit 762de44.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 39 to 42
* https://github.com/ensdomains/namechain
*/
[DatasourceNames.ENSRoot]: {
chain: ensTestEnvL1Chain,
chain: ensTestEnvChain,
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

This doc comment still points to ensdomains/namechain, but this PR removes namechain/L2 concepts and aligns ens-test-env to contracts-v2. Please update the reference (or reword the comment) so it doesn’t imply namechain is still the relevant deployment source for the current ens-test-env setup.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

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

Additional Suggestions:

  1. Outdated comment referencing removed Namechain datasource that is no longer part of the codebase
  1. Documentation references outdated namechain repository that has been removed in favor of contracts-v2 architecture
Fix on Vercel

@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 20, 2026 23:37 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 20, 2026 23:37 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 20, 2026 23:37 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/datasources/src/ens-test-env.ts (1)

29-29: ⚠️ Potential issue | 🟡 Minor

Stale "Namechain" references — update to point to contracts-v2.

Lines 29 and 38-39 still reference the namechain repo and "Namechain devnet". This PR explicitly moves away from Namechain onto the ENS Root Chain (devnet commit 762de44). The @see and "Addresses and Start Blocks" annotation should be updated to the contracts-v2 repo and the relevant commit.

📝 Suggested doc update
-   * `@see` https://github.com/ensdomains/namechain
+   * `@see` https://github.com/ensdomains/contracts-v2/tree/762de44d60b2588b2e92a6d29df941c4de821ae6
     /**
      * ENSRoot Datasource
      *
-     * Addresses and Start Blocks from Namechain devnet
-     * https://github.com/ensdomains/namechain
+     * Addresses and Start Blocks from contracts-v2 devnet commit 762de44
+     * https://github.com/ensdomains/contracts-v2/blob/762de44d60b2588b2e92a6d29df941c4de821ae6
      */

Also applies to: 38-39

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/datasources/src/ens-test-env.ts` at line 29, Update the stale
references to the old Namechain repo in this file by replacing the `@see` link and
the "Addresses and Start Blocks" annotation that mention "Namechain" with the
correct contracts-v2 repository and commit hash 762de44; locate the `@see` comment
(currently pointing to https://github.com/ensdomains/namechain) and the
descriptive comment lines that say "Namechain devnet" or reference Namechain,
and change them to reference the contracts-v2 repo and the specific devnet
commit 762de44 so documentation accurately reflects the ENS Root Chain source.
apps/ensindexer/src/config/config.test.ts (1)

744-756: 🧹 Nitpick | 🔵 Trivial

Use a dynamic key instead of the hardcoded chain ID 15658733.

RPC_URL_15658733 hardcodes the ensTestEnvChain chain ID. If DEVNET_DEFAULT_CHAIN_ID changes, this env var key silently diverges from the actual chain, causing a non-obvious test failure.

♻️ Proposed fix
  stubEnv({
    NAMESPACE: "ens-test-env",
    LABEL_SET_ID: "ens-test-env",
    LABEL_SET_VERSION: "0",
-   RPC_URL_15658733: VALID_RPC_URL,
+   [`RPC_URL_${ensTestEnvChain.id}`]: VALID_RPC_URL,
  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/config/config.test.ts` around lines 744 - 756, The test
currently uses a hardcoded env var key `RPC_URL_15658733` which ties the test to
a specific chain ID; replace that literal with a dynamically constructed key
using the canonical chain-id constant (e.g. DEVNET_DEFAULT_CHAIN_ID or the
ensTestEnvChain constant used by the config code) so the test sets
`process.env[\`RPC_URL_\${DEVNET_DEFAULT_CHAIN_ID}\`]` rather than
`RPC_URL_15658733`, and update any related expectations in the test that rely on
that chain id; locate this in the test near the getConfig() call and change the
env setup to compute the env var name dynamically.
apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts (1)

161-164: 🧹 Nitpick | 🔵 Trivial

Optional: stale namechain/L1BridgeController link in migration TODO.

The comment links to namechain/L1BridgeController.sol, but namechain is being removed in this PR. Consider either removing the URL or replacing it with the relevant ENSv2 contracts reference once they stabilise.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts` around
lines 161 - 164, The inline TODO comment in ENSv2Registry.ts references the
removed namechain L1BridgeController URL; update the comment near the
newExpiry/expiry handling so it no longer points to the stale namechain link —
either remove the URL entirely or replace it with the appropriate ENSv2 contract
reference (or a TODO to add the ENSv2 contract link once stabilized), and keep
the note about unregister semantics for newExpiry === 0n and the commented-out
expiry === 0n return.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts`:
- Around line 102-113: Update the misleading comment above the rows.length === 0
check to accurately describe why zero rows can occur: it happens whenever the
recursive CTE returned no matching nodes (e.g., the TLD/root label is absent),
which includes both pure TLD queries and multi-label names like "foo.eth" when
the root-level label is missing; keep the logic unchanged (the check on rows,
the non-null assertion for leaf, and the exact-match test rows.length ===
labelHashPath.length remain the same) and only edit the prose to reflect that
rows.length === 0 covers any case where the namegraph produced no rows for the
query.

In `@apps/ensapi/src/lib/public-client.ts`:
- Around line 32-33: Update the stale comment in
apps/ensapi/src/lib/public-client.ts: change the phrase "ens-test-env L1 Chain"
to "ens-test-env Chain" where the fallback docker-compose URL is described (the
comment above the fallback to http://localhost:8547 in the public client setup).
Keep the rest of the comment intact to preserve context about adding the
docker-compose-specific URL as a fallback.

In `@packages/ensnode-sdk/src/shared/config/rpc-configs-from-env.ts`:
- Line 76: Update the stale inline comment "// ens-test-env L1 Chain" by
removing the "L1" portion so it reads simply "// ens-test-env Chain" (or just
"// ens-test-env") to reflect there is no L1/L2 distinction; locate and edit the
exact comment string "// ens-test-env L1 Chain" in rpc-configs-from-env.ts and
replace it accordingly.

---

Outside diff comments:
In `@apps/ensindexer/src/config/config.test.ts`:
- Around line 744-756: The test currently uses a hardcoded env var key
`RPC_URL_15658733` which ties the test to a specific chain ID; replace that
literal with a dynamically constructed key using the canonical chain-id constant
(e.g. DEVNET_DEFAULT_CHAIN_ID or the ensTestEnvChain constant used by the config
code) so the test sets `process.env[\`RPC_URL_\${DEVNET_DEFAULT_CHAIN_ID}\`]`
rather than `RPC_URL_15658733`, and update any related expectations in the test
that rely on that chain id; locate this in the test near the getConfig() call
and change the env setup to compute the env var name dynamically.

In `@apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts`:
- Around line 161-164: The inline TODO comment in ENSv2Registry.ts references
the removed namechain L1BridgeController URL; update the comment near the
newExpiry/expiry handling so it no longer points to the stale namechain link —
either remove the URL entirely or replace it with the appropriate ENSv2 contract
reference (or a TODO to add the ENSv2 contract link once stabilized), and keep
the note about unregister semantics for newExpiry === 0n and the commented-out
expiry === 0n return.

In `@packages/datasources/src/ens-test-env.ts`:
- Line 29: Update the stale references to the old Namechain repo in this file by
replacing the `@see` link and the "Addresses and Start Blocks" annotation that
mention "Namechain" with the correct contracts-v2 repository and commit hash
762de44; locate the `@see` comment (currently pointing to
https://github.com/ensdomains/namechain) and the descriptive comment lines that
say "Namechain devnet" or reference Namechain, and change them to reference the
contracts-v2 repo and the specific devnet commit 762de44 so documentation
accurately reflects the ENS Root Chain source.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/ensindexer/src/config/config.test.ts (1)

660-665: 🧹 Nitpick | 🔵 Trivial

Consider asserting exclusivity of the new single chain in rpcConfigs.

The assertion only verifies that ensTestEnvChain.id is present, but does not confirm that no stale L1/L2 chain IDs were inadvertently retained. A size check would make the consolidation guarantee explicit.

🔍 Proposed stronger assertion
  const config = await getConfig();
  expect(config.rpcConfigs.has(ensTestEnvChain.id)).toBe(true);
+ expect(config.rpcConfigs.size).toBe(1);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/config/config.test.ts` around lines 660 - 665, The test
for getConfig currently only checks rpcConfigs.has(ensTestEnvChain.id) which
doesn't assert exclusivity; update the assertion to ensure rpcConfigs contains
only the single expected chain ID (e.g., check rpcConfigs.size === 1 or compare
rpcConfigs.keys()/Array.from(rpcConfigs.keys()) to a single-element set
containing ensTestEnvChain.id) so stale L1/L2 entries cannot be retained—modify
the test in apps/ensindexer/src/config/config.test.ts around the "should provide
ens-test-env rpc defaults" case to include this size/exact-membership check
against rpcConfigs.
apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts (1)

146-156: ⚠️ Potential issue | 🟡 Minor

Pre-existing: error messages reference NameRenewed but handler is ExpiryUpdated.

Lines 148 and 154 both use Invariant(ENSv2Registry:NameRenewed) in their error messages, but the enclosing handler (line 125) is for the ExpiryUpdated event. This predates this PR but could cause confusion during debugging.

Suggested fix
-        throw new Error(`Invariant(ENSv2Registry:NameRenewed): Registration expected, none found.`);
+        throw new Error(`Invariant(ENSv2Registry:ExpiryUpdated): Registration expected, none found.`);
-          `Invariant(ENSv2Registry:NameRenewed): Registration found but it is expired:\n${toJson(registration)}`,
+          `Invariant(ENSv2Registry:ExpiryUpdated): Registration found but it is expired:\n${toJson(registration)}`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts` around
lines 146 - 156, The error messages in the ENSv2Registry ExpiryUpdated handler
incorrectly reference "NameRenewed"; update the two throw new Error calls so
they reference "ExpiryUpdated" instead; specifically edit the throws that use
toJson(registration) and the earlier registration-missing throw in the
ExpiryUpdated handler (around the checks using
isRegistrationFullyExpired(registration, event.block.timestamp) and the
registration null check) to produce clear messages like
Invariant(ENSv2Registry:ExpiryUpdated) so logs point to the correct handler and
keep the existing diagnostic details (registration and toJson output).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts`:
- Line 36: The return expression unnecessarily appends "|| null" because
v1DomainId is already DomainId | null; update the return in get-domain-by-fqdn
(the expression returning v2DomainId || v1DomainId || null) to simply return
v2DomainId || v1DomainId so the redundant fallback is removed while preserving
the same typing and behavior.

In `@packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts`:
- Line 5: The `@see` URL in packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts
points to a non-existent repository and an interface that can't be found; update
the comment to reference the correct ENS repo (ensdomains/ens-contracts) or the
ENSIP-10 documentation, and replace or remove the broken file path. While here,
verify and correct the interface ID used by isDedicatedResolver (or the constant
holding the interface ID) to the ENSIP-10 ExtendedResolver value 0x9061b923 if
this constant was intended for ENSIP-10, and ensure the comment links to the
authoritative source (ens-contracts or ENSIP-10) showing the matching interface
definition.

---

Outside diff comments:
In `@apps/ensindexer/src/config/config.test.ts`:
- Around line 660-665: The test for getConfig currently only checks
rpcConfigs.has(ensTestEnvChain.id) which doesn't assert exclusivity; update the
assertion to ensure rpcConfigs contains only the single expected chain ID (e.g.,
check rpcConfigs.size === 1 or compare
rpcConfigs.keys()/Array.from(rpcConfigs.keys()) to a single-element set
containing ensTestEnvChain.id) so stale L1/L2 entries cannot be retained—modify
the test in apps/ensindexer/src/config/config.test.ts around the "should provide
ens-test-env rpc defaults" case to include this size/exact-membership check
against rpcConfigs.

In `@apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts`:
- Around line 146-156: The error messages in the ENSv2Registry ExpiryUpdated
handler incorrectly reference "NameRenewed"; update the two throw new Error
calls so they reference "ExpiryUpdated" instead; specifically edit the throws
that use toJson(registration) and the earlier registration-missing throw in the
ExpiryUpdated handler (around the checks using
isRegistrationFullyExpired(registration, event.block.timestamp) and the
registration null check) to produce clear messages like
Invariant(ENSv2Registry:ExpiryUpdated) so logs point to the correct handler and
keep the existing diagnostic details (registration and toJson output).

---

Duplicate comments:
In `@apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts`:
- Around line 102-103: Update the inaccurate inline comment above the
rows.length check in get-domain-by-fqdn.ts: replace "this was a query for a TLD
and it does not exist within the ENSv2 namegraph" with a precise description
that rows.length === 0 means the CTE returned no rows (e.g., any FQDN whose
root-level label is not present in the root registry or otherwise yields no
matches), and mention that this covers cases beyond only TLD-only lookups; keep
the check and return null behavior unchanged.


// prefer v2DomainId
// prefer v2Domain over v1Domain
return v2DomainId || v1DomainId || null;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Trailing || null is redundant.

v1DomainId is already typed DomainId | null, so null || null simply evaluates to null — the trailing operand adds no information.

🧹 Proposed cleanup
-  return v2DomainId || v1DomainId || null;
+  return v2DomainId || v1DomainId;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return v2DomainId || v1DomainId || null;
return v2DomainId || v1DomainId;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts` at line 36, The return
expression unnecessarily appends "|| null" because v1DomainId is already
DomainId | null; update the return in get-domain-by-fqdn (the expression
returning v2DomainId || v1DomainId || null) to simply return v2DomainId ||
v1DomainId so the redundant fallback is removed while preserving the same typing
and behavior.

/**
* DedicatedResolver InterfaceId
* @see https://github.com/ensdomains/namechain/blob/main/contracts/src/common/resolver/interfaces/IDedicatedResolverSetters.sol#L9
* @see https://github.com/ensdomains/contracts-v2/blob/main/contracts/src/resolver/interfaces/IDedicatedResolverSetters.sol
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

ensdomains contracts-v2 IDedicatedResolverSetters.sol github

💡 Result:

I couldn’t find any IDedicatedResolverSetters.sol file (or symbol IDedicatedResolverSetters) in ENS’s public GitHub repos via web search, and I also don’t see an ensdomains/contracts-v2 repo showing up in results—ENS’s main contracts repo is ensdomains/ens-contracts. [1]

If you meant ENS “v2” resolver work, it’s most likely inside ensdomains/ens-contracts under resolver-related folders (e.g. contracts/resolvers/**), so the best next step is to use GitHub’s in-repo code search:

https://github.com/ensdomains/ens-contracts/search?q=IDedicatedResolverSetters.sol
https://github.com/ensdomains/ens-contracts/search?q=IDedicatedResolverSetters

If you can share the exact GitHub URL you saw (or the import path that references IDedicatedResolverSetters.sol), I can pinpoint where it lives (or what it was renamed to). [1]

Source
[1] https://github.com/ensdomains/ens-contracts


🌐 Web query:

site:github.com/ensdomains/ens-contracts IDedicatedResolverSetters

💡 Result:

I couldn’t find any reference to IDedicatedResolverSetters in ensdomains/ens-contracts (no matches in indexed GitHub search results for that repo). The most likely explanations are:

  • the identifier name is misspelled (try searching for DedicatedResolver / IDedicatedResolverSetter / similar), or
  • it exists in a different ENS repo (not ens-contracts), or only in an unindexed branch/commit.

Repo: ensdomains/ens-contracts. [1]

How to verify locally (most reliable):

git clone https://github.com/ensdomains/ens-contracts
cd ens-contracts
rg -n "IDedicatedResolverSetters|DedicatedResolverSetters|DedicatedResolver" .

🏁 Script executed:

#!/bin/bash
# Search for IDedicatedResolverSetters or similar patterns in the repository
echo "=== Searching for IDedicatedResolverSetters or DedicatedResolver patterns ==="
rg -i "dedicatedresolver" --type sol

# Also check if there's a contracts-v2 directory or reference
echo ""
echo "=== Checking for 'contracts-v2' references or directories ==="
find . -type d -name "*contracts*v2*" 2>/dev/null | head -20
find . -type f -name "*.sol" | xargs grep -l "IDedicatedResolver" 2>/dev/null | head -10

# Check the specific file mentioned in the review to understand context
echo ""
echo "=== Checking the file being reviewed ==="
cat -n packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts

Repository: namehash/ensnode

Length of output: 812


🌐 Web query:

ensdomains 0x92349baa IDedicatedResolver interface

💡 Result:

I couldn’t find any authoritative ENS Labs/ensdomains source (docs repo, ens-contracts repo mirrors, or verified Etherscan source) that explicitly maps 0x92349baa to an IDedicatedResolver EIP-165 interface id or shows an IDedicatedResolver interface definition containing that value.

What I can confirm from sources is how to resolve any 4-byte selector like 0x92349baa to candidate function signatures:

  • 4byte.directory supports looking up selectors via its REST API: /api/v1/signatures/?hex_signature=0x........ (the 0x prefix is optional). [1]
  • Example usage and collision caveat (multiple signatures can share a selector) are documented in the same API docs / example writeups. [1], [2]

So the practical next step is to query:

curl 'https://www.4byte.directory/api/v1/signatures/?hex_signature=0x92349baa'

and then, if you suspect it’s an EIP-165 interface id, check whether 0x92349baa is being used in supportsInterface(bytes4) in the resolver contract you’re analyzing (because interface ids are what get compared there). [1]

Sources:
[1] https://www.4byte.directory/docs/
[2] https://dbadoy.tistory.com/33


🌐 Web query:

ensdomains resolver interfaces DedicatedResolver 0x92349baa ENSIP-10

💡 Result:

  • ENSIP-10 “Wildcard Resolution” defines the ExtendedResolver / IExtendedResolver interface as a single function: resolve(bytes name, bytes data) external view returns (bytes). Because it’s a single-function ERC‑165 interface, its interface ID equals the function selector of resolve(bytes,bytes) = 0x9061b923. [1][2][3]

  • I could not find any ENS Docs (or other ENS primary docs) reference that defines a resolver interface named DedicatedResolver, nor any resolver interface ID 0x92349baa, as part of ENSIP-10. ENS Docs’ resolver interface reference lists 0x9061b923 for ENSIP‑10, but not 0x92349baa. [1][3]


Fix the broken @see URL that references a non-existent repository.

The URL https://github.com/ensdomains/contracts-v2/blob/main/contracts/src/resolver/interfaces/IDedicatedResolverSetters.sol references a repository (ensdomains/contracts-v2) that doesn't exist. The main ENS contracts repository is ensdomains/ens-contracts. Additionally, IDedicatedResolverSetters cannot be found in any public ENS repositories. If this constant is intended for ENSIP-10, note that ENSIP-10's documented interface ID is 0x9061b923 (for ExtendedResolver), not 0x92349baa. Please verify the correct repository, file path, and interface definition, and update the comment link accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts` at line 5, The `@see`
URL in packages/ensnode-sdk/src/rpc/is-dedicated-resolver.ts points to a
non-existent repository and an interface that can't be found; update the comment
to reference the correct ENS repo (ensdomains/ens-contracts) or the ENSIP-10
documentation, and replace or remove the broken file path. While here, verify
and correct the interface ID used by isDedicatedResolver (or the constant
holding the interface ID) to the ENSIP-10 ExtendedResolver value 0x9061b923 if
this constant was intended for ENSIP-10, and ensure the comment links to the
authoritative source (ens-contracts or ENSIP-10) showing the matching interface
definition.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant