Skip to content

fix(ensnode-sdk): skip zero-address placeholders in indexed blockrange#2045

Merged
shrugs merged 3 commits intomainfrom
fix/blockrange-skip-zero-address-placeholders
May 2, 2026
Merged

fix(ensnode-sdk): skip zero-address placeholders in indexed blockrange#2045
shrugs merged 3 commits intomainfrom
fix/blockrange-skip-zero-address-placeholders

Conversation

@shrugs
Copy link
Copy Markdown
Member

@shrugs shrugs commented May 2, 2026

Summary

  • buildIndexedBlockranges now skips contracts whose address === zeroAddress before merging into a chain's indexed blockrange.
  • removes a class of recurring Invalid ChainIndexingStatusSnapshot: latestIndexedBlock must be before or same as backfillEndBlock errors emitted by EnsDbWriterWorker during sepolia-v2 backfill.

Why

  • sepolia-v2 has three plugin-required placeholder entries (LegacyEthRegistrarController, WrappedEthRegistrarController, UniversalRegistrarRenewalWithReferrer) set to address: zeroAddress, startBlock: 0 purely to satisfy the registrar plugin's typesystem. ponder doesn't actually index them.
  • the SDK was still folding their startBlock: 0 into mergeBlockNumberRanges, dragging the chain's indexedBlockrange.startBlock to 0. that propagated into backfillEndBlock = startBlock + historicalTotalBlocks - 1, which then computed ~3.7M blocks below the true chain head (because ponder's historicalTotalBlocks is measured from the real lowest start block, not 0).
  • once the indexer crossed that bogus backfillEndBlock mid-backfill, the snapshot validator threw on every metadata write — ~1 error/second until realtime.

Testing

  • pnpm -F ensnode-sdk typecheck passes.
  • existing 4 tests in indexed-blockranges.test.ts still pass.
  • did not add a new test for the skip; can add one if desired.
  • not yet rerun against the live sepolia-v2 backfill — will verify the warnings stop after restart.

Notes for Reviewer

  • relies on the assumption that ponder treats zero-address contracts as non-indexed (no log filter, no events). worth a quick sanity check — if ponder does fold them into historicalTotalBlocks somehow, this fix would have to match that behavior instead.

Checklist

  • This PR is low-risk and safe to review quickly

Cross-namespace plugin-required datasource fields (e.g. registrar entries
unused in sepolia-v2) carry address=zeroAddress, startBlock=0 purely to
satisfy the typesystem. mergeBlockNumberRanges was including them, dragging
the chain's indexed blockrange.startBlock to 0 even though Ponder doesn't
actually index them. That propagated into backfillEndBlock = startBlock +
historicalTotalBlocks - 1, computing it ~3.7M blocks low and triggering
recurrent ChainIndexingStatusSnapshot validation errors mid-backfill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shrugs shrugs requested a review from a team as a code owner May 2, 2026 13:58
Copilot AI review requested due to automatic review settings May 2, 2026 13:58
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 2, 2026

🦋 Changeset detected

Latest commit: d96be8a

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

This PR includes changesets to release 24 packages
Name Type
@ensnode/ensnode-sdk Patch
ensadmin Patch
ensapi Patch
ensindexer Patch
ensrainbow Patch
fallback-ensapi Patch
@namehash/ens-referrals Patch
@ensnode/ensdb-sdk Patch
@ensnode/ensnode-react Patch
@ensnode/ensrainbow-sdk Patch
@ensnode/integration-test-env Patch
@namehash/namehash-ui Patch
@docs/ensnode Patch
@docs/ensrainbow Patch
enssdk Patch
enscli Patch
enskit Patch
ensskills Patch
@ensnode/datasources Patch
@ensnode/ponder-sdk Patch
@ensnode/ponder-subgraph Patch
@ensnode/shared-configs Patch
@ensnode/ensindexer-perf-testing Patch
@ensnode/enskit-react-example Patch

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
Copy Markdown
Contributor

vercel Bot commented May 2, 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 May 2, 2026 11:26pm
ensnode-enskit-react-example Ready Ready Preview, Comment May 2, 2026 11:26pm
ensnode.io Ready Ready Preview, Comment May 2, 2026 11:26pm
ensrainbow.io Ready Ready Preview, Comment May 2, 2026 11:26pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

Warning

Rate limit exceeded

@shrugs has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 29 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e78744c7-7be4-4a49-8946-29478e79a661

📥 Commits

Reviewing files that changed from the base of the PR and between 88e6dd9 and d96be8a.

📒 Files selected for processing (1)
  • packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts
📝 Walkthrough

Walkthrough

A guard in buildIndexedBlockranges now skips datasource contracts whose address equals the zero address, so placeholder entries do not lower the computed indexed blockrange lower bound. A changeset documents this patch for @ensnode/ensnode-sdk.

Changes

Zero-Address Placeholder Filtering

Layer / File(s) Summary
Core Implementation
packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts
Import zeroAddress from viem and add a guard to continue when datasourceContract.address === zeroAddress, skipping placeholder-only contracts during blockrange computation.
Tests
packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts
Add test skips zero-address placeholder contracts that includes a real contract (startBlock: 100) and a zeroAddress placeholder (startBlock: 0), asserting merged ranges start at the real contract's block and endBlock remains undefined.
Release Notes / Changeset
.changeset/skip-zero-address-placeholders-blockrange.md
Add changeset entry noting the patch-level fix preventing zero-address placeholders from setting startBlock=0 and causing backfill validation errors.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A phantom address hid in the hay,
It pulled our bounds the wrong, wee way.
I hopped in the code, gave placeholders the skip,
Now ranges stand steady — no more backward trip! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: skipping zero-address placeholders when building indexed blockranges.
Description check ✅ Passed The description follows the Lite PR template with complete Summary, Why, Testing, and Notes sections; all required elements are present and substantive.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/blockrange-skip-zero-address-placeholders

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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
Review rate limit: 0/1 reviews remaining, refill in 52 minutes and 29 seconds.

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 2, 2026

Greptile Summary

This PR fixes a bug in buildIndexedBlockranges where zero-address placeholder contracts (used in sepolia-v2 to satisfy the registrar plugin's typesystem) had their startBlock: 0 incorrectly folded into the chain's merged blockrange, dragging backfillEndBlock ~3.7M blocks below the true chain head and causing repeated snapshot validation errors during backfill. The fix adds a one-line guard to skip any ContractConfig whose address === zeroAddress, and adds a corresponding test.

Confidence Score: 5/5

Safe to merge — minimal, well-tested fix with no P0 or P1 issues.

The change is a single-line guard with a clear rationale, backed by a new test that directly exercises the fixed code path. All existing tests continue to pass unaffected. No regressions introduced.

No files require special attention.

Important Files Changed

Filename Overview
packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts Adds a zero-address skip guard before merging a contract's blockrange into the chain's indexed blockrange; clean and targeted fix.
packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts Adds a new test case verifying zero-address contracts are skipped; correctly imports zeroAddress from viem and asserts the merged range uses only the non-zero-address contract's startBlock.
.changeset/skip-zero-address-placeholders-blockrange.md Patch-level changeset entry with a clear description of the fix and its impact.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[buildIndexedBlockranges] --> B[For each plugin datasource name]
    B --> C{datasource exists in namespace?}
    C -- No --> B
    C -- Yes --> D[For each contract in datasource]
    D --> E{address === zeroAddress?}
    E -- Yes: skip --> D
    E -- No --> F[buildBlockNumberRange startBlock endBlock]
    F --> G{existing range for chain?}
    G -- No --> H[use contract range]
    G -- Yes --> I[mergeBlockNumberRanges]
    H --> J[set indexedBlockranges for chainId]
    I --> J
    J --> D
    D --> B
    B --> K[return indexedBlockranges map]
Loading

Reviews (3): Last reviewed commit: "fix lint" | Re-trigger Greptile

Comment thread packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts
Copy link
Copy Markdown
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

This PR updates @ensnode/ensnode-sdk’s indexed blockrange calculation so placeholder datasource contracts configured with the zero address no longer affect the derived per-chain indexing range. In the broader codebase, this feeds the local Ponder client / indexing-status path that computes backfill bounds for ENS indexer chains.

Changes:

  • Skip zero-address datasource contracts when building indexed blockranges.
  • Add a patch changeset documenting the blockrange/backfill fix for @ensnode/ensnode-sdk.

Reviewed changes

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

File Description
packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts Filters zero-address placeholder contracts out of blockrange aggregation.
.changeset/skip-zero-address-placeholders-blockrange.md Records the SDK patch release note for the behavior change.

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

Comment thread packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts
Comment thread packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts
Copy link
Copy Markdown
Contributor

@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.

Caution

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

⚠️ Outside diff range comments (1)
packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts (1)

40-68: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add a unit test covering the zero-address skip.

The PR explicitly notes no test was added for the new guard. Given this is the single logical change in the PR and the bug it fixes was actively causing repeated validation errors in production, a dedicated test case that verifies zero-address contracts are excluded from the computed blockrange (and don't drag startBlock to 0) would lock in the fix.

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

In `@packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts` around lines
40 - 68, Add a unit test that verifies the zero-address guard in
indexed-blockranges.ts skips placeholder contracts: create datasourceContracts
where one contract uses zeroAddress with startBlock=0 and another uses a real
address with startBlock>0, call the function (the module export that builds the
indexedBlockranges which uses buildBlockNumberRange/mergeBlockNumberRanges) and
assert the resulting indexedBlockranges for that chain excludes the zero-address
contribution (i.e., startBlock is the non-zero contract's startBlock and the
rangeType is LeftBounded or Bounded), ensuring zero-address contracts do not set
startBlock to 0.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts`:
- Around line 40-68: Add a unit test that verifies the zero-address guard in
indexed-blockranges.ts skips placeholder contracts: create datasourceContracts
where one contract uses zeroAddress with startBlock=0 and another uses a real
address with startBlock>0, call the function (the module export that builds the
indexedBlockranges which uses buildBlockNumberRange/mergeBlockNumberRanges) and
assert the resulting indexedBlockranges for that chain excludes the zero-address
contribution (i.e., startBlock is the non-zero contract's startBlock and the
rangeType is LeftBounded or Bounded), ensuring zero-address contracts do not set
startBlock to 0.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f7bdf751-abf1-4478-b4cd-2f017724110e

📥 Commits

Reviewing files that changed from the base of the PR and between 17869cf and 680f759.

📒 Files selected for processing (2)
  • .changeset/skip-zero-address-placeholders-blockrange.md
  • packages/ensnode-sdk/src/shared/config/indexed-blockranges.ts

…dBlockranges

Asserts a chain with one real contract and one zero-address placeholder
returns a blockrange derived only from the real contract — preventing the
regression where placeholders dragged startBlock to 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shrugs
Copy link
Copy Markdown
Member Author

shrugs commented May 2, 2026

@greptile review

Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts`:
- Around line 160-193: Add a test that verifies buildIndexedBlockranges skips a
chain when every required datasource contract is the zero-address placeholder:
create a datasource config for a chain (use zeroAddress and startBlock: 0 for
all contracts), register it in datasourcesByName via datasourceMock and have
maybeGetDatasourceMock return it for DatasourceNames.ENSRoot (or whichever
DatasourceName used), set pluginsRequiredDatasourceNames to include that
datasource (e.g., PluginName.Subgraph -> [DatasourceNames.ENSRoot]), call
buildIndexedBlockranges(ENSNamespaceIds.Mainnet, pluginsRequiredDatasourceNames)
and assert the returned Map does not contain an entry for that chain (i.e.,
equals a Map without that chain) rather than a range starting at 0; reference
buildIndexedBlockranges, datasourceMock, maybeGetDatasourceMock, zeroAddress,
PluginName, and DatasourceNames in the test setup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6a001b85-c070-4c6d-b0a5-bcfadf07abb8

📥 Commits

Reviewing files that changed from the base of the PR and between 680f759 and 88e6dd9.

📒 Files selected for processing (1)
  • packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts

Comment thread packages/ensnode-sdk/src/shared/config/indexed-blockranges.test.ts
Copy link
Copy Markdown
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 3 out of 3 changed files in this pull request and generated no new comments.


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

@shrugs shrugs merged commit 54edf26 into main May 2, 2026
25 checks passed
@shrugs shrugs deleted the fix/blockrange-skip-zero-address-placeholders branch May 2, 2026 23:29
@github-actions github-actions Bot mentioned this pull request May 2, 2026
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.

3 participants