Skip to content

chore(slush): read pool, package and version ids from the registry - #97

Merged
harshaalphafi merged 2 commits into
mainfrom
chore/admin-ids-from-registry
Aug 12, 2026
Merged

chore(slush): read pool, package and version ids from the registry#97
harshaalphafi merged 2 commits into
mainfrom
chore/admin-ids-from-registry

Conversation

@rishikesh-chavan

@rishikesh-chavan rishikesh-chavan commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What

Slush code paths no longer hardcode values that move on every contract upgrade or redeploy. They now come from the pool registry (GET {apiBaseUrl}/public/configStrategyContext.getPoolLabels()).

Admin (src/admin/slushAdmin.ts) — three values resolved from the ALPHALEND-SLUSH-WAL-SINGLE-LOOP label instead of constants:

Was Now
ADMIN.ALPHA_SLUSH_LATEST_PACKAGE_ID label.packageId
ADMIN.ALPHA_SLUSH_WAL_LOOP_POOL_ID label.poolId
VERSIONS.SLUSH label.versionId

Both ADMIN constants are deleted — ADMIN is internal (not exported from src/index.ts) and nothing else referenced them.

Strategies (slushLending.ts, slushSingleAssetLooping.ts) — every tx.object(VERSIONS.SLUSH) becomes tx.object(this.poolLabel.versionId). This matters beyond tidiness: version objects are per-pool, not per-strategy-type. ALPHALEND-SLUSH-STSUI-LOOP and ALPHALEND-SLUSH-STSUI-SUI-LOOP sit on different ones (0x1140f0b4… vs 0x146d1785…), so a single constant cannot stay correct as pools are added.

Parser (strategyContext.ts)version_object_id was already in the registry payload but was dropped for both slush types; it is now mapped to versionId, required on both labels, and the TEST_POOLS fixtures carry it (values read off chain per fixture's package lineage, not invented).

Why the two remaining ADMIN ids stay hardcoded

ALPHA_FIRST_PACKAGE_ID and ALPHA_SLUSH_FIRST_PACKAGE_ID name types (distributor::RebalanceCap, alphalend_slush_pool::AdminCap), not call targets. A Sui type tag carries the id of the package version that first defined the struct, and that id never changes on upgrade — so they need no maintenance and deliberately do not come from the API.

They also cannot be derived from the package prefix of a neighbouring type or event string. One package holds types defined across many upgrades; the type-origin table of the current slush package 0x8b7c85…a409 spans six defining ids:

0x41b1de…38c3  alphalend_slush_pool::AdminCap, alphalend_slush_investor::AutoCompoundingEvent
0x3221f3…e7c7  alphalend_slush_locked_loop_pool::XtokenRatioChangeEvent
0xad1991…a989  alphalend_slush_locked_loop_pool::XtokenRatioChangeEventV2
0x2bcf16…8069  alphafi_slush_stsui_sui_loop_pool::*
+ 2 more

Deriving the AdminCap address from the WAL pool's own event type would yield 0x3221f3…, and listOwnedObjects with a wrong type returns empty — surfacing as a bogus "No AdminCap found for address X" permissions error rather than a config error. Both call sites and the constant document this.

Verification

tsc --noEmit, npm run build, ESLint and Prettier are clean.

Behaviour is unchanged: every pool that previously received VERSIONS.SLUSH resolves to that same object (0x146d1785…) from the registry today.

Beyond that, deposit and withdraw were built and simulated on mainnet for all six SlushLending / SlushSingleAssetLooping pools — 12/12 succeeded, with the registry versionId confirmed present in each transaction's resolved inputs. Senders are discovered on chain (position-cap holders with a non-empty position for withdraws, asset holders for deposits); nothing is signed or executed.

Pool deposit withdraw
ALPHALEND-SLUSH-LENDING-USDC
ALPHALEND-SLUSH-LENDING-SUI
ALPHALEND-SLUSH-LENDING-WAL
ALPHALEND-SLUSH-LENDING-DEEP
ALPHALEND-SLUSH-WAL-SINGLE-LOOP
ALPHALEND-SLUSH-USDSUI-SINGLE-LOOP

The green run is not vacuous: forcing a wrong-but-real version::Version object (from the SlushLooping lineage) makes all 12 simulations fail with CommandArgumentError … TypeMismatch on argIdx 0 — the version argument. So the simulation genuinely validates the object being sourced from the registry.

Reproduce with scripts/slushDryRun.ts (no private key or .env needed):

npx tsx scripts/slushDryRun.ts             # expect 12 passed
npx tsx scripts/slushDryRun.ts --negative  # expect 12 rejected, TypeMismatch on argIdx 0

It also warns when the registry contains a slush pool its list does not cover, so a newly added pool surfaces instead of going silently untested.

Notes / follow-ups (not in this PR)

  • VERSIONS.ALPHA_EMBER (used by admin/alphaVault.ts) and the VERSIONS / ALPHA_VERSIONS entries used by the LP, Lending and Looping strategies are likewise version_object_id in the registry payload, dropped by the remaining parsePoolLabelEntry branches. Same treatment applies; it touches those strategy classes. Note LP calls take two version objects — the label supplies the pool's own, the second is a shared base version.
  • PACKAGE_IDS.ALPHAFI_RECEIPT does double duty: the create_alphafi_receipt_v2 call target and the defining id inside ALPHAFI_TRANSFER_REQUEST_TYPE / ..._KEY_TYPE. Both are correct today (the lineage has two versions: v1 0x18533807… defines AlphaFiReceipt, v2 0x8113301d… defines TransferRequest/TransferRequestKey, and v2 is latest), but on the next upgrade the call target must move to v3 while the type constants must stay at v2 — one constant cannot do both.
  • Pre-existing, unrelated: @pythnetwork/pyth-sui-js is CJS and require()s @mysten/sui's ESM build, so importing StrategyContext fails with ERR_REQUIRE_ESM under plain Node and Jest. tsx handles it, which is why the dry-run script runs fine.

…stry

The WAL locked-loop admin functions hardcoded the call-target package id, the pool
object id and the shared Version object, all of which move on every slush upgrade
or redeploy. They now come from the pool registry (`/public/config`) via the
`ALPHALEND-SLUSH-WAL-SINGLE-LOOP` label, so an upgrade needs no SDK change.

`version_object_id` was already in the registry payload but was dropped by the
`SlushSingleAssetLooping` branch of `parsePoolLabelEntry`; it is now parsed into an
optional `versionId` (optional so hand-written label fixtures stay valid), and
`addExternalRewardsWalLockedTxb` throws when it is missing rather than falling back
to a possibly stale constant.

The two remaining `ADMIN` ids stay hardcoded on purpose: they name types
(`distributor::RebalanceCap`, `alphalend_slush_pool::AdminCap`), and a Sui type tag
carries the id of the package version that *defined* the struct, which never changes
on upgrade. They also can't be derived from a neighbouring type or event string —
the current slush package spans six defining ids — and a wrong type makes the
owned-object query return nothing, surfacing as a bogus "no cap found" error.
Documented that on the constant and at both call sites.
   SlushLending and SlushSingleAssetLooping now pass  instead of
   , so a slush upgrade needs no SDK change.
   maps  for both types and the label fixtures carry it.
@rishikesh-chavan
rishikesh-chavan marked this pull request as ready for review August 7, 2026 12:02
@rishikesh-chavan rishikesh-chavan changed the title chore(admin): read slush admin pool/package/version ids from the registry chore(slush): read pool, package and version ids from the registry Aug 7, 2026

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

operate.md: clean — CI green. Registry-miss and staleness semantics are fail-safe (named throws on missing label/versionId; a stale cached packageId aborts on-chain within the 5-min TTL — strictly better than a hardcoded id needing an SDK release), first-package-id type-tag discipline is correct, and the live /public/config was verified to serve version_object_id for all slush pools, so there is no deployment-ordering risk. Non-blocking notes: src/admin/README.md says versionId is optional on SlushSingleAssetLoopingPoolLabel but the interface declares it required (making the guard in addExternalRewardsWalLockedTxb dead per the type system) — fix one side; VERSIONS.SLUSH/SLUSH_LOOP are now dead exports worth a deprecation note; TEST_POOLS fixtures 2-3 pair an old call-target package with the current Version object and would abort if used. Approvals: 2/2 — at threshold.

@harshaalphafi
harshaalphafi merged commit b4487f4 into main Aug 12, 2026
3 checks passed
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.

4 participants