Skip to content

fix(sdk): classify sealevel cross-collateral tokens#8632

Merged
nambrot merged 4 commits intomainfrom
codex/fix-sealevel-cross-collateral-predicate-clean
Apr 21, 2026
Merged

fix(sdk): classify sealevel cross-collateral tokens#8632
nambrot merged 4 commits intomainfrom
codex/fix-sealevel-cross-collateral-predicate-clean

Conversation

@nambrot-agent
Copy link
Copy Markdown
Contributor

@nambrot-agent nambrot-agent commented Apr 19, 2026

Summary

  • fix TokenMetadata.isCrossCollateralToken() to include TokenStandard.SealevelHypCrossCollateral
  • add a focused WarpCore regression test for Sealevel cross-collateral -> EVM cross-collateral routing
  • ensure WarpCore takes the cross-collateral transferRemoteTo path instead of generic transferRemote

Root cause

WarpCore.isCrossCollateralTransfer() relies on originToken.isCrossCollateralToken() and destinationToken.isCrossCollateralToken().

After the TokenMetadata refactor, current main classified only:

  • EvmHypCrossCollateralRouter
  • TronHypCrossCollateralRouter

It omitted SealevelHypCrossCollateral, so a Sealevel cross-collateral source token was misclassified as non-cross-collateral. That caused WarpCore to skip the cross-collateral route and fall back to the generic transfer path.

Repro

On current main, this targeted test fails:

pnpm -C typescript/sdk exec mocha --config .mocharc.json ./src/warp/WarpCore.test.ts --grep "Treats Sealevel cross-collateral to EVM cross-collateral as transferRemoteTo route" --exit

Failure before fix:

AssertionError: expected false to equal true

Validation

After this change:

pnpm turbo run build --filter @hyperlane-xyz/sdk^... --filter @hyperlane-xyz/sdk
pnpm -C typescript/sdk exec mocha --config .mocharc.json ./src/warp/WarpCore.test.ts --grep "Treats Sealevel cross-collateral to EVM cross-collateral as transferRemoteTo route" --exit

Result:

  • 1 passing

Notes

  • This is a source fix on current main, not a release-only workaround.
  • I kept the fix scoped to the predicate plus regression coverage.

Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2780e5d3-78b4-46ed-bc5f-ec9bd62408a3

📥 Commits

Reviewing files that changed from the base of the PR and between 6d7a57d and 096fcac.

📒 Files selected for processing (2)
  • typescript/sdk/src/token/TokenMetadata.ts
  • typescript/sdk/src/warp/WarpCore.test.ts
✅ Files skipped from review due to trivial changes (2)
  • typescript/sdk/src/token/TokenMetadata.ts
  • typescript/sdk/src/warp/WarpCore.test.ts

📝 Walkthrough

Walkthrough

This PR fixes misclassification of Sealevel cross-collateral tokens during WarpCore route building, updates token classification logic, and adds a test that verifies WarpCore generates a transferRemoteTo-style route for Sealevel ↔ EVM cross-collateral pairs.

Changes

Cohort / File(s) Summary
Changeset
.changeset/fix-sealevel-cross-collateral-predicate.md
Adds a patch release changeset for @hyperlane-xyz/sdk documenting the fix.
Token Classification
typescript/sdk/src/token/TokenMetadata.ts
Replaced hard-coded standard checks with membership test against TOKEN_CROSS_COLLATERAL_STANDARDS, ensuring Sealevel standard is recognized as cross-collateral.
Test Coverage
typescript/sdk/src/warp/WarpCore.test.ts
Adds a test asserting WarpCore treats an origin SealevelHypCrossCollateral → destination EvmHypCrossCollateralRouter pair as a cross-collateral transfer and uses populateTransferRemoteToTx (only).
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main fix: classifying Sealevel cross-collateral tokens in the SDK, which is the core change across all modified files.
Description check ✅ Passed The PR description covers all template sections: provides a clear summary, includes related code context, addresses backward compatibility implicitly (patch release), and documents manual validation with test commands.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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.

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.

🧹 Nitpick comments (2)
typescript/sdk/src/token/TokenMetadata.ts (1)

155-160: Use the central cross-collateral set here.

This fixes Sealevel, but the duplicated list is how this drift happened. TOKEN_CROSS_COLLATERAL_STANDARDS already has EVM/Sealevel/Tron.

♻️ Proposed cleanup
 import {
   PROTOCOL_TO_HYP_NATIVE_STANDARD,
   PROTOCOL_TO_NATIVE_STANDARD,
   TOKEN_COLLATERALIZED_STANDARDS,
+  TOKEN_CROSS_COLLATERAL_STANDARDS,
   TOKEN_HYP_STANDARDS,
   TOKEN_MULTI_CHAIN_STANDARDS,
   TOKEN_NFT_STANDARDS,
@@
   isCrossCollateralToken(): boolean {
-    return (
-      this.standard === TokenStandard.EvmHypCrossCollateralRouter ||
-      this.standard === TokenStandard.TronHypCrossCollateralRouter ||
-      this.standard === TokenStandard.SealevelHypCrossCollateral
-    );
+    return TOKEN_CROSS_COLLATERAL_STANDARDS.has(this.standard);
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@typescript/sdk/src/token/TokenMetadata.ts` around lines 155 - 160, The
isCrossCollateralToken method in TokenMetadata currently hardcodes TokenStandard
comparisons; replace that duplicated list with a membership check against the
central TOKEN_CROSS_COLLATERAL_STANDARDS constant (e.g., use
TOKEN_CROSS_COLLATERAL_STANDARDS.includes(this.standard) or .has if it's a Set)
so EVM/Tron/Sealevel stay in sync with the canonical set; update the method to
return the membership boolean and remove the explicit TokenStandard comparisons.
typescript/sdk/src/warp/WarpCore.test.ts (1)

1190-1195: Drop the any cast.

isCrossCollateralTransfer is public, so this can call it directly.

♻️ Proposed cleanup
       expect(
-        (crossCollateralWarpCore as any).isCrossCollateralTransfer(
+        crossCollateralWarpCore.isCrossCollateralTransfer(
           sealevelCrossCollateral,
           evmCrossCollateral,
         ),

As per coding guidelines, No as assertions - every as cast is a potential bug.

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

In `@typescript/sdk/src/warp/WarpCore.test.ts` around lines 1190 - 1195, The test
uses an unnecessary `as any` cast when invoking the public method
isCrossCollateralTransfer; remove the cast and call
(crossCollateralWarpCore).isCrossCollateralTransfer(sealevelCrossCollateral,
evmCrossCollateral) directly, and if TypeScript complains, fix the test variable
typing for crossCollateralWarpCore (or its construction) so it is typed as the
class exposing isCrossCollateralTransfer rather than forcing any. Ensure the
call uses the real method signature of isCrossCollateralTransfer with
sealevelCrossCollateral and evmCrossCollateral.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@typescript/sdk/src/token/TokenMetadata.ts`:
- Around line 155-160: The isCrossCollateralToken method in TokenMetadata
currently hardcodes TokenStandard comparisons; replace that duplicated list with
a membership check against the central TOKEN_CROSS_COLLATERAL_STANDARDS constant
(e.g., use TOKEN_CROSS_COLLATERAL_STANDARDS.includes(this.standard) or .has if
it's a Set) so EVM/Tron/Sealevel stay in sync with the canonical set; update the
method to return the membership boolean and remove the explicit TokenStandard
comparisons.

In `@typescript/sdk/src/warp/WarpCore.test.ts`:
- Around line 1190-1195: The test uses an unnecessary `as any` cast when
invoking the public method isCrossCollateralTransfer; remove the cast and call
(crossCollateralWarpCore).isCrossCollateralTransfer(sealevelCrossCollateral,
evmCrossCollateral) directly, and if TypeScript complains, fix the test variable
typing for crossCollateralWarpCore (or its construction) so it is typed as the
class exposing isCrossCollateralTransfer rather than forcing any. Ensure the
call uses the real method signature of isCrossCollateralTransfer with
sealevelCrossCollateral and evmCrossCollateral.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d23a1634-7f57-4a1c-aa00-86692a4a5179

📥 Commits

Reviewing files that changed from the base of the PR and between 3c1e67a and 6d7a57d.

📒 Files selected for processing (3)
  • .changeset/fix-sealevel-cross-collateral-predicate.md
  • typescript/sdk/src/token/TokenMetadata.ts
  • typescript/sdk/src/warp/WarpCore.test.ts

Copy link
Copy Markdown
Collaborator

@paulbalaji paulbalaji left a comment

Choose a reason for hiding this comment

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

Review Summary

Minimal, correct fix. Replacing the hand-maintained disjunction in TokenMetadata.isCrossCollateralToken() with a lookup against the canonical TOKEN_CROSS_COLLATERAL_STANDARDS removes the drift risk that caused the regression — now the predicate cannot silently lag behind TokenStandard.ts. Regression test is focused and asserts both the classification and the routing outcome.

Prior bot feedback (Devin, CodeRabbit) about reusing the canonical set is already resolved in head. No unresolved threads.

Related PRs

  • #8629 adds the same regression test standalone without the production fix — redundant once this merges.
  • #8628 adds the same regression test plus an unrelated registry version bump.

LGTM.

Comment thread .changeset/fix-sealevel-cross-collateral-predicate.md
@nambrot-agent nambrot-agent enabled auto-merge April 21, 2026 01:08
@nambrot nambrot disabled auto-merge April 21, 2026 03:29
@nambrot nambrot enabled auto-merge April 21, 2026 03:29
@nambrot nambrot added this pull request to the merge queue Apr 21, 2026
Merged via the queue into main with commit a2081df Apr 21, 2026
90 checks passed
@nambrot nambrot deleted the codex/fix-sealevel-cross-collateral-predicate-clean branch April 21, 2026 03:46
@github-project-automation github-project-automation Bot moved this from In Review to Done in Hyperlane Tasks Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants