Skip to content

fix(discovery): remove stale isV2 branch misrouting V12_15/17/19 in parseEngineLight - #339

Open
Morenikeoa wants to merge 1 commit into
dcccrypto:mainfrom
Morenikeoa:fix/parseenginelight-stale-isv2-upstream
Open

fix(discovery): remove stale isV2 branch misrouting V12_15/17/19 in parseEngineLight#339
Morenikeoa wants to merge 1 commit into
dcccrypto:mainfrom
Morenikeoa:fix/parseenginelight-stale-isv2-upstream

Conversation

@Morenikeoa

@Morenikeoa Morenikeoa commented Jun 26, 2026

Copy link
Copy Markdown

Summary

parseEngineLight's isV2 branch (gated on layout.version === 2) used hardcoded fixed offsets written for an old "V2 BPF intermediate" layout (e.g. currentSlot at a fixed base+352). That same version: 2 discriminant is also set by buildLayoutV12_15/17/19 (V12_19 inherits it by spreading V12_17's base layout) — an unrelated reuse of the same enum value — which meant V12_15/17/19 (the currently-deployed mainnet tier line) were silently routed through this stale branch's wrong offsets instead of their own correct per-field offsets.

Verified directly: V12_19's real engineCurrentSlotOff is 200, not 352.

This affected every field parseEngineLight returns for V12_15/17/19, not just one. parseEngineLight backs discoverMarkets() and getMarketsByAddress(), the SDK's primary market-listing entry points.

The layout-driven branch immediately below the removed code already documents that it's meant to cover V_ADL, V12_1, V12_15, V12_17, V12_19, V1M, V1M2, V_SETDEXPOOL and any future layout — the isV2 branch was dead weight left over from a prior refactor that was never cleaned up.

While moving V12_15/17/19 onto the layout-driven branch, also added the engineFundingIndexOff >= 0 guard that the heavy parser (slab.ts parseEngine) already has — V12_15/17/19 set this offset to -1 (the field doesn't exist in those engine structs), and the unguarded read would otherwise read 16 bytes starting one byte before the engine region.

Exported parseEngineLight (was internal) so it can be unit tested directly.

Test plan

  • Added two regression tests for V12_19 in test/drift-check.test.ts:
    1. Proves the real per-field offset (200) is used instead of the dead branch's hardcoded one (352), via a planted decoy value at the old offset.
    2. Proves fundingIndexQpbE6 is 0n instead of an off-by-one read, via a planted marker byte at engineOff - 1.
  • Confirmed both tests fail against the prior code (parseEngineLight not exported / wrong offsets used) and pass against this fix.
  • Full suite green: 853 passed, 31 skipped (882 → 884 total, +2 new tests).

Summary by CodeRabbit

  • Bug Fixes

    • Improved Solana light-engine parsing for newer layouts, making account data handling more reliable.
    • Fixed funding index handling when the value is unavailable, preventing incorrect reads and fallback errors.
    • Removed an outdated layout-specific parsing path, improving consistency across supported formats.
  • Tests

    • Added coverage for newer layout behavior to help prevent regressions.

…arseEngineLight

parseEngineLight's isV2 branch (gated on layout.version === 2) used
hardcoded fixed offsets written for an old "V2 BPF intermediate"
layout (e.g. currentSlot at a fixed base+352). That same version: 2
discriminant is also set by buildLayoutV12_15/17/19 (V12_19 inherits
it by spreading V12_17's base layout) — an unrelated reuse of the
same enum value — which meant V12_15/17/19 (the currently-deployed
mainnet tier line) were silently routed through this stale branch's
wrong offsets instead of their own correct per-field offsets.
Verified directly: V12_19's real engineCurrentSlotOff is 200, not 352.

This affected every field parseEngineLight returns for V12_15/17/19,
not just one. parseEngineLight backs discoverMarkets() and
getMarketsByAddress(), the SDK's primary market-listing entry points.

The layout-driven branch immediately below the removed code already
documents that it's meant to cover V_ADL, V12_1, V12_15, V12_17,
V12_19, V1M, V1M2, V_SETDEXPOOL and any future layout — the isV2
branch was dead weight left over from a prior refactor that was never
cleaned up.

While moving V12_15/17/19 onto the layout-driven branch, also added
the engineFundingIndexOff >= 0 guard that the heavy parser (slab.ts
parseEngine) already has — V12_15/17/19 set this offset to -1 (the
field doesn't exist in those engine structs), and the unguarded read
would otherwise read 16 bytes starting one byte before the engine
region.

Exported parseEngineLight (was internal) so it can be unit tested
directly, and added two regression tests for V12_19 proving (1) the
real per-field offset is used instead of the dead branch's hardcoded
one, and (2) fundingIndexQpbE6 is 0n instead of an off-by-one read.
Both tests fail against the prior code (parseEngineLight not
exported) and pass against this fix.

Full suite: 853 passed | 31 skipped (882 -> 884, +2 new tests).
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR exports parseEngineLight, removes its hardcoded V2 branch, changes funding-index parsing to respect layout offsets and invalid offsets, and adds V12_19 drift-test coverage.

Changes

parseEngineLight offset handling

Layer / File(s) Summary
Public parser and offsets
src/solana/discovery.ts
parseEngineLight is exported, the V2 fixed-offset branch is removed, fundingIndexQpbE6 now skips invalid offsets and chooses 64-bit or 128-bit reads from layout offsets, and the unrecognized-layout error drops the isV2 field.
V12_19 regression test
test/drift-check.test.ts
drift-check.test.ts imports SLAB_TIERS_V12_19 and adds a parseEngineLight test suite that checks the layout-derived currentSlot offset and the -1 funding-index case.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • Issue 337: The new V12_19 test and the layout-driven currentSlot and fundingIndexQpbE6 reads align with the reported wrong-offset behavior in parseEngineLight.

Possibly related PRs

Poem

A bunny hopped through offsets neat,
And found the parser on layout feet.
No stale old branch, no sneaky drift,
Just V12_19 doing its shift.
🐇🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix in parseEngineLight and names the affected V12_15/17/19 layouts.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/solana/discovery.ts`:
- Around line 399-404: The heavy parser in discovery should guard
`lastFundingSlot` the same way as `fundingIndexQpbE6`, because
`engineLastFundingSlotOff` can be `-1` when the field is absent. Update the
object construction in `src/solana/discovery.ts` so `lastFundingSlot` returns
`0n` when `engineLastFundingSlotOff < 0`, otherwise reads with `readU64LE`,
matching the existing offset-sentinel handling used by the other parser fields.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: c4ebbf02-70ae-449d-81ed-9109eef80c9a

📥 Commits

Reviewing files that changed from the base of the PR and between 673bc47 and 65bab56.

📒 Files selected for processing (2)
  • src/solana/discovery.ts
  • test/drift-check.test.ts

Comment thread src/solana/discovery.ts
Comment on lines +399 to 404
fundingIndexQpbE6: l.engineFundingIndexOff >= 0
? ((l.engineLastFundingSlotOff >= 0 && l.engineLastFundingSlotOff - l.engineFundingIndexOff === 8)
? BigInt(readI64LE(data, base + l.engineFundingIndexOff))
: readI128LE(data, base + l.engineFundingIndexOff))
: 0n,
lastFundingSlot: readU64LE(data, base + l.engineLastFundingSlotOff),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Guard lastFundingSlot when its offset is absent.

Line 404 still reads engineLastFundingSlotOff unconditionally. Since slab offsets use -1 for absent fields and the heavy parser returns 0n in that case, mirror that guard here to avoid another base + (-1) read.

Proposed fix
-      lastFundingSlot: readU64LE(data, base + l.engineLastFundingSlotOff),
+      lastFundingSlot: l.engineLastFundingSlotOff >= 0
+        ? readU64LE(data, base + l.engineLastFundingSlotOff)
+        : 0n,
📝 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
fundingIndexQpbE6: l.engineFundingIndexOff >= 0
? ((l.engineLastFundingSlotOff >= 0 && l.engineLastFundingSlotOff - l.engineFundingIndexOff === 8)
? BigInt(readI64LE(data, base + l.engineFundingIndexOff))
: readI128LE(data, base + l.engineFundingIndexOff))
: 0n,
lastFundingSlot: readU64LE(data, base + l.engineLastFundingSlotOff),
fundingIndexQpbE6: l.engineFundingIndexOff >= 0
? ((l.engineLastFundingSlotOff >= 0 && l.engineLastFundingSlotOff - l.engineFundingIndexOff === 8)
? BigInt(readI64LE(data, base + l.engineFundingIndexOff))
: readI128LE(data, base + l.engineFundingIndexOff))
: 0n,
lastFundingSlot: l.engineLastFundingSlotOff >= 0
? readU64LE(data, base + l.engineLastFundingSlotOff)
: 0n,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/solana/discovery.ts` around lines 399 - 404, The heavy parser in
discovery should guard `lastFundingSlot` the same way as `fundingIndexQpbE6`,
because `engineLastFundingSlotOff` can be `-1` when the field is absent. Update
the object construction in `src/solana/discovery.ts` so `lastFundingSlot`
returns `0n` when `engineLastFundingSlotOff < 0`, otherwise reads with
`readU64LE`, matching the existing offset-sentinel handling used by the other
parser fields.

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