Skip to content

Fix indexing invariants logic#2350

Open
tk-o wants to merge 7 commits into
mainfrom
hotfix/22f5cb7
Open

Fix indexing invariants logic#2350
tk-o wants to merge 7 commits into
mainfrom
hotfix/22f5cb7

Conversation

@tk-o

@tk-o tk-o commented Jul 13, 2026

Copy link
Copy Markdown
Member

Lite PR

Tip: Review docs on the ENSNode PR process

Summary

  • Updated isRegistrationFullyExpired and isRegistrationInGracePeriod helpers to accurately represent the logic implemented on chain: the very last second of grace period is still a valid moment to renew a registration.
  • Updated handleRegistrationOrReservation event handler to accurately represent the logic implemented onchain: the LabelRegistered event can be emitted multiple times for an existing registration of a reverse name. Such registrations never expire.

Why

  • ENSIndexer Alpha and ENSIndexer V2 Sepolia could not continue indexing due to indexing logic mismatch with onchain logic.

Testing

  • Updated unit tests, and executed them successfully.
  • Tested updates in the green env (used docker images from a preview release).

Notes for Reviewer (Optional)


Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

Align  and  helpers with the indexed smart contracts' logic.
Copilot AI review requested due to automatic review settings July 13, 2026 05:17
@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c3a4db6

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

This PR includes changesets to release 23 packages
Name Type
@ensnode/ensnode-sdk Patch
ensindexer Patch
ensadmin Patch
ensapi Patch
ensrainbow Patch
fallback-ensapi Patch
@docs/ensnode Patch
@namehash/ens-referrals Patch
enscli Patch
@ensnode/ensdb-sdk Patch
@ensnode/ensrainbow-sdk Patch
ensskills Patch
@ensnode/integration-test-env Patch
@namehash/namehash-ui Patch
@ensnode/ensdb-cli Patch
@docs/ensrainbow Patch
enssdk Patch
enskit Patch
@ensnode/datasources Patch
@ensnode/ponder-sdk Patch
@ensnode/ponder-subgraph Patch
@ensnode/shared-configs Patch
@ensnode/ensindexer-perf-testing 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

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f9199206-8829-49b7-912b-2afd5b107d5c

📥 Commits

Reviewing files that changed from the base of the PR and between 1827496 and c3a4db6.

📒 Files selected for processing (1)
  • apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts

📝 Walkthrough

Walkthrough

The SDK updates exact expiration and grace-period boundary semantics with timestamp and null-case tests. ENSv2 registry handling identifies reverse-name registrations and skips the existing expiration invariant for them. Patch changesets document both updates.

Changes

Registration Expiration Helpers

Layer / File(s) Summary
Expiration boundaries and validation
packages/ensnode-sdk/src/registrars/registration-expiration.ts, packages/ensnode-sdk/src/registrars/registration-expiration.test.ts, .changeset/modern-groups-occur.md
Full expiration now requires time beyond the expiry-plus-grace boundary, while grace-period detection includes the exact boundary. Parameterized tests cover timestamps and null values, and the SDK patch changeset documents the update.

ENSv2 Reverse-Name Registrations

Layer / File(s) Summary
Reverse-name registration invariant
apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts, .changeset/two-corners-tease.md
Existing registration validation identifies reverse-name registrations from the registrant and label identifiers and skips the expiration invariant for them. The ensindexer patch changeset records the behavior change.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: javascript

Poem

I’m a rabbit with a registry key,
Boundary clocks now tick precisely.
Reverse names hop past the gate,
Graceful tests confirm their state.
Two patch notes bloom—what a tidy spree!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: fixing indexing invariants logic.
Description check ✅ Passed The description follows the required template and includes summary, why, testing, notes, and checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/22f5cb7

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.

@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
enskit-react-example.ensnode.io Ready Ready Preview, Comment Jul 13, 2026 5:58am
3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Jul 13, 2026 5:58am
ensnode.io Skipped Skipped Jul 13, 2026 5:58am
ensrainbow.io Skipped Skipped Jul 13, 2026 5:58am

@tk-o

tk-o commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@greptile review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 aligns ENS registration expiry/grace-period helpers (used across SDK, indexer, and API layers) with onchain boundary semantics, and relaxes an ENSIndexer ENSv2 invariant to handle repeated LabelRegistered events for reverse-name reservations without halting indexing.

Changes:

  • Updated isRegistrationFullyExpired and isRegistrationInGracePeriod to treat expiry + gracePeriod as an inclusive grace endpoint (renewal still valid at the last second).
  • Added unit tests covering expiry/grace boundary conditions for the registration expiration helpers.
  • Updated ENSv2 registry handler invariant logic to tolerate existing reverse-name registrations that should not be considered expirable.

Reviewed changes

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

File Description
packages/ensnode-sdk/src/registrars/registration-expiration.ts Adjusts expiry/grace boundary comparisons to match onchain semantics.
packages/ensnode-sdk/src/registrars/registration-expiration.test.ts Adds coverage for boundary conditions and null-handling behavior.
apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Updates invariant handling to account for repeated reverse-name LabelRegistered events.
.changeset/modern-groups-occur.md Publishes SDK helper behavior alignment as a patch changeset.

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

Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
Comment thread packages/ensnode-sdk/src/registrars/registration-expiration.ts
@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two indexing invariant logic bugs: the boundary condition in isRegistrationFullyExpired / isRegistrationInGracePeriod is corrected to treat the exact end of the grace period as still-renewable (matching onchain behaviour), and the handleRegistrationOrReservation handler is updated to allow duplicate LabelRegistered events for non-expiring reverse-name registrations.

  • Boundary fix (registration-expiration.ts): isRegistrationFullyExpired changes >=> and isRegistrationInGracePeriod changes >>=, keeping the two predicates mutually exclusive and covering every timestamp relative to expiry + gracePeriod.
  • Reverse-name bypass (ENSv2Registry.ts): when an existing registration's registrantId equals 0x${label} (a valid Ethereum address), the expiry invariant is skipped so a second LabelRegistered for the same label can create a new registration record without crashing the indexer.
  • New unit tests validate every boundary case for all three expiration helpers.

Confidence Score: 5/5

Safe to merge — the two boundary fixes are consistent with each other and correctly align the expiration helpers with onchain semantics, and the reverse-name bypass is well-scoped to a clearly identified protocol special case.

The expiration predicate changes are a single-character operator fix with new tests that explicitly cover the previously-broken boundary values. The reverse-name bypass in handleRegistrationOrReservation is guarded by both isNormalizedAddress and an exact registrantId equality check, so it is narrow and hard to trigger accidentally. All existing callers of the updated functions benefit from the corrected boundary without any change in their surrounding logic.

No files require special attention.

Important Files Changed

Filename Overview
packages/ensnode-sdk/src/registrars/registration-expiration.ts Boundary conditions corrected: isRegistrationFullyExpired uses strict > and isRegistrationInGracePeriod uses >=, making the two predicates mutually exclusive and jointly exhaustive across all timestamp values.
packages/ensnode-sdk/src/registrars/registration-expiration.test.ts New test file thoroughly covers all boundary cases (before expiry, at expiry, mid-grace, at grace end, after grace) plus null-expiry and null-gracePeriod branches for all three helpers.
apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Reverse-name detection added to handleRegistrationOrReservation: when the existing registration's registrantId equals 0x${label} (confirmed as a valid Ethereum address), the expiry invariant is bypassed to allow repeated LabelRegistered events for the same non-expiring reverse name.
.changeset/modern-groups-occur.md Changeset entry for @ensnode/ensnode-sdk patch; description matches the code change.
.changeset/two-corners-tease.md Changeset entry for ensindexer patch; description matches the reverse-name handling change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[LabelRegistered event received] --> B{isReservation?}
    B -- yes --> C{existing registration?}
    C -- yes --> D{isRegistrationFullyExpired?\nnow > expiry + grace}
    D -- no --> E[❌ throw invariant error]
    D -- yes --> F[proceed to upsert domain]
    C -- no --> F

    B -- no --> G{existing registration?}
    G -- no --> F
    G -- yes --> H{isReverseNameRegistration?\nisNormalizedAddress AND\nregistrantId === 0x+label}
    H -- yes --> F
    H -- no --> I{registration.type ===\nENSv2RegistryReservation?}
    I -- yes --> F
    I -- no --> J{isRegistrationFullyExpired?\nnow > expiry + grace}
    J -- yes --> F
    J -- no --> E

    F --> K[insert domain upsert]
    K --> L[insertLatestRegistration\nnew record, incremented index]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[LabelRegistered event received] --> B{isReservation?}
    B -- yes --> C{existing registration?}
    C -- yes --> D{isRegistrationFullyExpired?\nnow > expiry + grace}
    D -- no --> E[❌ throw invariant error]
    D -- yes --> F[proceed to upsert domain]
    C -- no --> F

    B -- no --> G{existing registration?}
    G -- no --> F
    G -- yes --> H{isReverseNameRegistration?\nisNormalizedAddress AND\nregistrantId === 0x+label}
    H -- yes --> F
    H -- no --> I{registration.type ===\nENSv2RegistryReservation?}
    I -- yes --> F
    I -- no --> J{isRegistrationFullyExpired?\nnow > expiry + grace}
    J -- yes --> F
    J -- no --> E

    F --> K[insert domain upsert]
    K --> L[insertLatestRegistration\nnew record, incremented index]
Loading

Reviews (3): Last reviewed commit: "Apply AI PR feedback" | Re-trigger Greptile

Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
tk-o added 2 commits July 13, 2026 07:29
Update invariant logic to meet the relevant smart contract implementation which allows reverse name registration overrides.
…tionInGracePeriod` helpers with onchain logic.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
Comment thread .changeset/modern-groups-occur.md
Copilot AI review requested due to automatic review settings July 13, 2026 05:33
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io July 13, 2026 05:33 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io July 13, 2026 05:33 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io July 13, 2026 05:33 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
Copilot AI review requested due to automatic review settings July 13, 2026 05:47
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io July 13, 2026 05:47 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io July 13, 2026 05:47 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io July 13, 2026 05:47 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 5 out of 5 changed files in this pull request and generated 1 comment.

Copilot AI review requested due to automatic review settings July 13, 2026 05:55
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io July 13, 2026 05:55 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io July 13, 2026 05:55 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io July 13, 2026 05:55 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread apps/ensindexer/src/plugins/unigraph/handlers/ensv2/ENSv2Registry.ts Outdated
Copilot AI review requested due to automatic review settings July 13, 2026 05:58
@tk-o tk-o force-pushed the hotfix/22f5cb7 branch from 6dcb2e5 to c3a4db6 Compare July 13, 2026 05:58
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io July 13, 2026 05:58 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io July 13, 2026 05:58 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io July 13, 2026 05:58 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 5 out of 5 changed files in this pull request and generated no new comments.

@tk-o tk-o marked this pull request as ready for review July 13, 2026 06:47
@tk-o tk-o requested a review from a team as a code owner July 13, 2026 06:47

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

@tk-o Shared some suggestions. Please take the lead to merge when ready 👍

@@ -23,8 +23,8 @@ export function isRegistrationFullyExpired(info: RegistrationExpiryInfo, now: bi
// no expiry, never expired

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.

@tk-o Should we rename this idea of being "full expired" as being "released"?

return now > info.expiry + (info.gracePeriod ?? 0n);
}

/**

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.

Why are all the timestamps in this file typed as bigint? Don't we have a more meaningful type alias for this?

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