feat(community-tax): migrate pair inventory — CL8Y vs Terraport/GDEX next steps + tools #634

Closed
opened 2026-08-25 02:08:32 +00:00 by PlasticDigits · 19 comments
PlasticDigits commented 2026-08-25 02:08:32 +00:00 (Migrated from gitlab.com)

Migrate-adopt #626 (M626-9, M626-10). Autoregister + Manage catch-up + manager tax skip #633 (new CL8Y CreatePair / Manage highest-LP). F6 pin + Refresh #582 / #584 / #585. Template #592. Create/Manage #593. Ops after adopt: docs/runbooks/cw20-code-id-ops.md. Terraport factory table: docs/terraport.md.

This ticket is migrate-only. Do not fold it into #633. #633 covers new CL8Y pair create + Manage “no registered pair yet.” Adopt keeps the CW20 address, so the token may already have CL8Y factory pairs (F6-frozen until governance Refresh) and Terraport / GDEX pairs (not F6-pinned; must never be RegisterListedPair’d). The migrate UI must inventory those venues, say what happens, offer a tool when the connected wallet can act, and give copy-paste instructions when it cannot.


Current codebase

MigrateTokenPage.tsx loads a pasted addr, classifies source code id / admin, and shows one generic line before submit:

MIGRATE_LP_CONFIRM
  Address stays the same. CL8Y pairs pause until governance refreshes them. Terraport and GDEX keep this token.

MIGRATE_LP_CONFIRM_WIPE
  … Old tax leftovers are cleared. … Terraport and GDEX keep this token 1:1.

No pair discovery. No per-pool list. No F6 / pause / Refresh status. No register CTA. Success is only Token migrated. + link to /token/:addr/manage (M626-12). Query params ?token= / ?addr= are ignored.

Adopt ([adopt.rs](smartcontracts/contracts/community-tax-token/src/adopt.rs)) does not call RegisterListedPair. Honest payload is tax-off zeros; ALPHA wipe maps 4.5%/1% → buy 450 / sell 100 but those rates do nothing until a CL8Y pair is registered. Terraport/GDEX keep the same CW20 address and stay 1:1 if left unregistered (M626-10).

Known columbus-5 external LP (LCD 2026-08-24, skill table — not queried by the page):

Source Venue Pair After adopt
ALPHA 8654 terra1x6e64…zysuxz Terraport ALPHA/LUNC terra12u7kh…9e7p6 Wipe → forward 1:1. Do not register.
ALPHA 8654 Terraport ALPHA/USTC terra1jg2vu…wph Same.
8266 Open terra1qz56v…s74n3 Terraport Open/LUNC terra1uxr6m…nypyc 1:1 stay 1:1. Do not register.
GDEX — No factory pin in-repo Address unchanged. Do not register.

CL8Y factory pairs that already include the token fail-close after adopt (live code_id 11619 ≠ pin of 6036/10184/8266/8654) until governance RefreshPairAssetCodeIds. Token admin / new manager cannot Refresh. Ops order: 11619 already listed → SetPairPaused → Refresh (do not Refresh if the other asset is unlisted) → smoke → unpause. Then #633 register so retail buy/sell apply.

Indexer GET /api/v1/tokens/{addr}/pairs is CL8Y-ingested only. Terraport factory is documented (terra1n75fg…rqqr in docs/terraport.md). GDEX factory is not pinned.


Why this is needed

A manager who migrates ALPHA or Open (or any 6036/10184 token that already has a CL8Y pool) is not starting from zero pairs. The current one-liner does not tell them:

  • which CL8Y pools will freeze, that they cannot unfreeze, and who to ask;
  • which Terraport/GDEX pools exist, that those stay 1:1, and that registering them is forbidden;
  • what they can do after Refresh (register the CL8Y pair — #633 tool) vs what they must not do (register external DEX addrs, Refresh themselves, whitelist 8654).

Without that, they will either LP into a frozen CL8Y pair, try to RegisterListedPair a Terraport addr (revert or, if a bug slipped, turn tax on an external AMM — H-01), or assume “Terraport keeps this token” means they should also list it for extra-debit.

#633’s Manage alert is “no registered CL8Y pair yet” for tokens the wallet already manages. It does not run on /token/migrate, does not explain F6/Refresh, and must not offer Terraport addrs as “highest LP.”


Constraints / guardrails

  1. M626-10 / T592-9. Never RegisterListedPair Terraport, GDEX, or any non-config.factory pair. Button/tool must factory-verify first.
  2. M626-9. Token admin cannot Refresh. Do not expose RefreshPairAssetCodeIds / SetPairPaused on this page. Do not Refresh a pair whose other asset is unlisted. Human words only on the card — no tax_info / RegisterListedPair / VITE_* / GetAssetCodeIds.
  3. M626-2 / C593-10. Free. No invoice. Ignore ?payee= / ?manager= / ?pair=.
  4. M626-12 / C593-11. After success, primary next step is Manage (and this inventory). Do not dump into Swap defaults.
  5. O601-2 / H-01. Do not factory-whitelist 8654. Do not add pair/router FoT math.
  6. #489. Retail copy. “CL8Y pool,” “other DEX,” “governance must refresh,” “leave those pools; they stay 1:1.”
  7. #596. Do not turn hybrid off.
  8. C593-8. Post-adopt Manage/register chrome only when LCD code_id is the tax pin.
  9. Incomplete inventory is OK. If GDEX (or an unknown factory) cannot be queried, say so and give instructions — do not invent pairs.
  10. Do not auto-register in the adopt tx. Refresh must happen first on existing CL8Y pairs (trading/provide fail-closed). Register is a later tool, after pins match or on a new CL8Y pair (#633 create).
  11. Cross-link #633 for “register largest CL8Y pool” / manager tax skip. This page owns discovery + venue-specific next steps.

Relevant files

Area Path
Page frontend-dapp/src/pages/MigrateTokenPage.tsx, MigrateTokenPage.test.tsx
Copy / verdict frontend-dapp/src/utils/communityTaxMigrate.ts
Adopt smartcontracts/contracts/community-tax-token/src/adopt.rs
Register (reuse, do not fork) frontend-dapp/src/services/terraclassic/communityTaxToken.ts (registerListedPair, queryCommunityTaxIsExempt)
CL8Y pairs frontend-dapp/src/services/indexer/client.ts getTokenPairs; services/terraclassic/factory.ts; services/terraclassic/pair.ts getPool
F6 probe frontend-dapp/src/services/terraclassic/assetCodeIdFreeze.ts, hooks/usePairCodeIdFreeze.ts
Terraport factory docs/terraport.md (terra1n75fg…rqqr)
Known LP table skills/AGENTS_FRONTEND_TOKEN_MIGRATE.md
Ops Refresh docs/runbooks/cw20-code-id-ops.md § After a retail adopt
Playbook skills/AGENTS_FRONTEND_TOKEN_MIGRATE.md (M626-9, M626-10)

1 — Discover venues when the token is loaded (before and after submit)

Build a small helper (e.g. communityTaxMigratePairs.ts) that returns rows { venue, pair, symbols, note }:

Venue How to find If lookup fails
CL8Y Indexer getTokenPairs + factory Pair verify (official VITE_FACTORY_ADDRESS / launcher factory). LCD Pool for size. F6 GetAssetCodeIds vs live code_id when already on 11619 (post-tx). “No CL8Y pool found” is a valid empty state (they will Create Pair — #633).
Terraport Query documented Terraport factory Pair for this token vs uluna / uusd / other known quotes; overlay the static ALPHA/Open table so those two always show when the loaded addr matches. If factory query fails: keep static known rows + “We could not list every Terraport pool. Leave Terraport pools as they are.”
GDEX No factory pin. Do not guess. Always: “GDEX pools (if any) keep this address. Do not register them. They stay 1:1.”

Show the list on the confirm card and on the success card (refetch after migrate).

2 — Per-venue next steps (copy + tool vs instructions)

CL8Y pair exists (pre- or post-adopt):

  • Tell them: this CL8Y market pauses / fails until CL8Y governance refreshes the pool pin. The manager cannot do that. Provide: pair addr (copy), other-asset identity, and a short “what to send governance” blurb (pair addr + token addr + “RefreshPair after 11619 adopt” in operator language off the retail card — retail card stays human; optional “copy details” that includes addrs for a ticket).
  • After adopt, if F6 still frozen: no register button. CTA disabled with “Wait until governance refreshes this pool.”
  • After pins match (or LocalTerra analogue): offer Register this CL8Y pool (reuse #633 registerListedPair). Same factory verify. Hide when already IsProtocolExempt.protocol.
  • If they have no CL8Y pair: CTA Create Pair → /create (no query prefill) plus one line that new CL8Y pools are registered on create (#633).

Terraport / GDEX:

  • Label Other DEX. “Leave these pools. They stay 1:1. Do not register them here.”
  • No register button. No “highest LP” if that LP is Terraport.
  • Optional finder link (Terraport UI / finder) is OK; not required.

3 — Success card checklist (ordered)

  1. Token address unchanged. You are now the manager (source admin).
  2. CL8Y: wait for governance refresh (list the pairs) or create a new CL8Y pair if none.
  3. After refresh: register the CL8Y pool (button if ready) so buy/sell tax applies for everyone else. Manager LP/trades are not taxed (#633).
  4. Other DEX: do nothing. Do not paste those pair addrs into register.

Keep a single lead sentence on the page (#489). Details live in the inventory card, not a contract essay.

4 — Docs

Extend AGENTS_FRONTEND_TOKEN_MIGRATE.md with this inventory UX (new M626- bullets or a sibling M634 set). Point #633 at this issue for adopt leftovers instead of stretching Manage-only copy.


Acceptance criteria

  • AC1. Loading a migratable token shows a venue list: CL8Y factory pairs (0–n), Terraport rows when discoverable or statically known, and a GDEX/unknown-external instruction row when no GDEX inventory exists.
  • AC2. Copy states CL8Y pools pause until governance refresh; manager cannot refresh; other DEX stays 1:1 and must not be registered.
  • AC3. No control on this page sends RefreshPairAssetCodeIds, SetPairPaused, or AddWhitelistedCodeId.
  • AC4. Register CTA appears only for a factory-verified CL8Y pair, only after adopt, only when F6 pins match (or pair is new/unfrozen), only for the connected manager. Terraport/GDEX never get a register button.
  • AC5. ALPHA / Open known Terraport pairs always appear when that token is loaded, with “leave 1:1 / do not register.”
  • AC6. Token with no CL8Y pair: empty CL8Y section + Create Pair instruction/link (/create, no prefill). Not an error.
  • AC7. Success card repeats the inventory + checklist. Primary link remains Manage.
  • AC8. ?token= / ?addr= / ?pair= / ?payee= do not prefill or retarget register.
  • AC9. Retail card has no wasm/env/code-id essays. Optional “copy details for governance” may include addrs.
  • AC10. Failed Terraport factory query degrades to static known rows + honest “could not list every other-DEX pool” — page still submitable.

Test plan — happy / functional paths

  1. Honest 10184/6036, no CL8Y pair, no known Terraport. Confirm shows CL8Y empty + other-DEX instruction. Submit. Success: Create Pair link + “leave other DEX.” Manage link still present.
  2. Honest token with one CL8Y pair. Confirm lists that pair as “will pause / governance refresh.” After migrate, F6 frozen: register disabled + wait copy. After a mocked unfreeze: register enabled; success hides it (already / protocol true).
  3. Two CL8Y pairs. Both listed with identity. Governance copy can name both. Register is per CL8Y row or one “register ready pools” control that skips frozen and never includes external addrs.
  4. Open 8266. Terraport Open/LUNC row present. No register on that addr. Adopt does not call register.
  5. ALPHA 8654. Both known Terraport rows + wipe confirm copy. No register. No whitelist CTA.
  6. LocalTerra mintable adopt. Factory-whitelisted gem: CL8Y analogue pair listed; Terraport static table empty; GDEX instruction still shown as “if you have other DEX pools.”
  7. Indexer down / token not in catalog. LCD factory pagination or Pair probe still finds a CL8Y pair; empty indexer ≠ “no CL8Y pool” if factory has one.
  8. Terraport factory LCD fail. Static ALPHA/Open still show; generic other-DEX fallback; migrate CTA not blocked.
  9. Already tax (11619). Verdict already_tax; inventory may still show venues as read-only help; no adopt tx.
  10. Non-admin connected. No migrate CTA; inventory can still be informational.
  11. Vitest. Confirm/success copy matrix (wipe vs honest); venue classification (factory vs Terraport vs unknown); register enabled iff CL8Y + post-adopt + not frozen + manager; query params ignored; no Refresh execute in the page module.

Test plan — attack / abuse / hack vectors

  1. Register Terraport addr. UI must not offer it. If a user pastes one into any leftover field, client must factory-verify and refuse. On-chain already rejects (T592-9); keep that as the backstop.
  2. Highest-LP trap. Do not reuse #633 “largest pool” if the largest TVL is Terraport ALPHA/LUNC. Ranking for this page’s register tool is CL8Y-only.
  3. Spoof factory. A pair that reports this token but is not official-factory Pair must not get a register button.
  4. Refresh smuggle. Page must not build refresh_pair_asset_code_ids / set_pair_paused / add_whitelisted_code_id messages (static grep in tests).
  5. Unlisted other asset. Do not tell the user to Refresh a CL8Y pair whose other side is not factory-whitelisted. Copy: governance will skip that pool; create a new CL8Y pair vs a listed asset instead.
  6. 8654 whitelist. No CTA or copy that says “list 8654 to save Terraport LP.”
  7. URL injection. ?pair=terra1terraport… must not become the register target.
  8. Half-migrated / failed UpdateAdmin. If adopt wasm moved but admin is not CMM, show unverified-admin / stop; do not register (catalog/attest rules). Existing C593-7 banner on Manage is not enough on this page if they never leave it.
  9. Register before Refresh. Button stays disabled while F6 frozen so provide/swap do not hit fail-closed + user blame. Do not batch register into the adopt tx.
  10. FoT on unregistered CL8Y + TransferTax. Adopt honest profile has transfer tax off. Do not enable TransferTax in this flow. If they later unlock it, #633 register-before-LP still applies.
  11. Cross-venue confuse. Finder/Terraport links must not use the same button style as “Register CL8Y pool.”
  12. Catalog unattested. Do not treat indexer listing as F6 / whitelist.

Verification criteria

Close only when:

make verify-issue-626
# add make verify-issue-<this> — Migrate inventory Vitest + copy; no Refresh/register-external
  • Manual columbus-5 (or recorded LCD fixtures): load Open terra1qz56v… → Terraport Open/LUNC shown, no register; load ALPHA terra1x6e64… → both Terraport rows, wipe copy, no register.
  • LocalTerra: adopt a factory-listed mintable that already has a CL8Y pair → confirm names that pair as governance-refresh; after Refresh (or local pin already matching), register tool lists only that factory pair; Terraport instruction row still present as “other DEX if any.”
  • Grep: migrate page/helpers never emit refresh_pair_asset_code_ids or call registerListedPair with a non-factory addr.
  • Playbook updated. #633 description should point here for adopt leftovers (comment on #633 is enough).

Do not close if the page still only has the generic MIGRATE_LP_CONFIRM line, or if the only “tool” is a raw pair paste that can target Terraport.


Out of scope

  • Autoregister on new Create Pair / AutoLP bind / manager role tax skip (#633).
  • Giving the token admin RefreshPairAssetCodeIds or factory pause.
  • Building a full GDEX factory indexer.
  • Pair/router wasm changes. Whitelisting 8654. Unregister API.
## Parent / related Migrate-adopt [#626](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/626) (**M626-9**, **M626-10**). Autoregister + Manage catch-up + manager tax skip [#633](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/633) (new CL8Y `CreatePair` / Manage highest-LP). F6 pin + Refresh [#582](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/582) / [#584](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/584) / [#585](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/585). Template [#592](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/592). Create/Manage [#593](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/593). Ops after adopt: [`docs/runbooks/cw20-code-id-ops.md`](docs/runbooks/cw20-code-id-ops.md). Terraport factory table: [`docs/terraport.md`](docs/terraport.md). **This ticket is migrate-only.** Do not fold it into #633. #633 covers *new* CL8Y pair create + Manage “no registered pair yet.” Adopt keeps the CW20 address, so the token may already have **CL8Y factory pairs** (F6-frozen until governance Refresh) **and** **Terraport / GDEX pairs** (not F6-pinned; must never be `RegisterListedPair`’d). The migrate UI must inventory those venues, say what happens, offer a tool when the connected wallet can act, and give copy-paste instructions when it cannot. --- ## Current codebase [`MigrateTokenPage.tsx`](frontend-dapp/src/pages/MigrateTokenPage.tsx) loads a pasted addr, classifies source code id / admin, and shows one generic line before submit: ``` MIGRATE_LP_CONFIRM Address stays the same. CL8Y pairs pause until governance refreshes them. Terraport and GDEX keep this token. MIGRATE_LP_CONFIRM_WIPE … Old tax leftovers are cleared. … Terraport and GDEX keep this token 1:1. ``` No pair discovery. No per-pool list. No F6 / pause / Refresh status. No register CTA. Success is only `Token migrated.` + link to `/token/:addr/manage` (**M626-12**). Query params `?token=` / `?addr=` are ignored. Adopt (`[adopt.rs](smartcontracts/contracts/community-tax-token/src/adopt.rs)`) does **not** call `RegisterListedPair`. Honest payload is tax-off zeros; ALPHA wipe maps 4.5%/1% → buy 450 / sell 100 but those rates do nothing until a **CL8Y** pair is registered. Terraport/GDEX keep the same CW20 address and stay 1:1 if left unregistered (**M626-10**). Known columbus-5 external LP (LCD 2026-08-24, skill table — not queried by the page): | Source | Venue | Pair | After adopt | |--------|--------|------|-------------| | ALPHA **8654** `terra1x6e64…zysuxz` | Terraport ALPHA/LUNC | `terra12u7kh…9e7p6` | Wipe → forward 1:1. Do not register. | | ALPHA **8654** | Terraport ALPHA/USTC | `terra1jg2vu…wph` | Same. | | **8266** Open `terra1qz56v…s74n3` | Terraport Open/LUNC | `terra1uxr6m…nypyc` | 1:1 stay 1:1. Do not register. | | GDEX | — | No factory pin in-repo | Address unchanged. Do not register. | CL8Y factory pairs that already include the token **fail-close** after adopt (live `code_id` 11619 ≠ pin of 6036/10184/8266/8654) until governance `RefreshPairAssetCodeIds`. Token admin / new manager **cannot** Refresh. Ops order: 11619 already listed → `SetPairPaused` → Refresh (do not Refresh if the *other* asset is unlisted) → smoke → unpause. Then #633 register so retail buy/sell apply. Indexer `GET /api/v1/tokens/{addr}/pairs` is CL8Y-ingested only. Terraport factory is documented (`terra1n75fg…rqqr` in `docs/terraport.md`). GDEX factory is **not** pinned. --- ## Why this is needed A manager who migrates ALPHA or Open (or any 6036/10184 token that already has a CL8Y pool) is not starting from zero pairs. The current one-liner does not tell them: - **which** CL8Y pools will freeze, that **they** cannot unfreeze, and who to ask; - **which** Terraport/GDEX pools exist, that those stay 1:1, and that registering them is forbidden; - what they **can** do after Refresh (register the CL8Y pair — #633 tool) vs what they must **not** do (register external DEX addrs, Refresh themselves, whitelist 8654). Without that, they will either LP into a frozen CL8Y pair, try to `RegisterListedPair` a Terraport addr (revert or, if a bug slipped, turn tax on an external AMM — H-01), or assume “Terraport keeps this token” means they should also list it for extra-debit. #633’s Manage alert is “no registered CL8Y pair yet” for tokens the wallet already manages. It does not run on `/token/migrate`, does not explain F6/Refresh, and must not offer Terraport addrs as “highest LP.” --- ## Constraints / guardrails 1. **M626-10 / T592-9.** Never `RegisterListedPair` Terraport, GDEX, or any non-`config.factory` pair. Button/tool must factory-verify first. 2. **M626-9.** Token admin cannot Refresh. Do not expose `RefreshPairAssetCodeIds` / `SetPairPaused` on this page. Do not Refresh a pair whose other asset is unlisted. Human words only on the card — no `tax_info` / `RegisterListedPair` / `VITE_*` / `GetAssetCodeIds`. 3. **M626-2 / C593-10.** Free. No invoice. Ignore `?payee=` / `?manager=` / `?pair=`. 4. **M626-12 / C593-11.** After success, primary next step is Manage (and this inventory). Do not dump into Swap defaults. 5. **O601-2 / H-01.** Do not factory-whitelist 8654. Do not add pair/router FoT math. 6. **#489.** Retail copy. “CL8Y pool,” “other DEX,” “governance must refresh,” “leave those pools; they stay 1:1.” 7. **#596.** Do not turn hybrid off. 8. **C593-8.** Post-adopt Manage/register chrome only when LCD `code_id` is the tax pin. 9. **Incomplete inventory is OK.** If GDEX (or an unknown factory) cannot be queried, say so and give instructions — do not invent pairs. 10. **Do not auto-register in the adopt tx.** Refresh must happen first on existing CL8Y pairs (trading/provide fail-closed). Register is a *later* tool, after pins match or on a *new* CL8Y pair (#633 create). 11. Cross-link #633 for “register largest CL8Y pool” / manager tax skip. This page owns **discovery + venue-specific next steps**. --- ## Relevant files | Area | Path | |------|------| | Page | `frontend-dapp/src/pages/MigrateTokenPage.tsx`, `MigrateTokenPage.test.tsx` | | Copy / verdict | `frontend-dapp/src/utils/communityTaxMigrate.ts` | | Adopt | `smartcontracts/contracts/community-tax-token/src/adopt.rs` | | Register (reuse, do not fork) | `frontend-dapp/src/services/terraclassic/communityTaxToken.ts` (`registerListedPair`, `queryCommunityTaxIsExempt`) | | CL8Y pairs | `frontend-dapp/src/services/indexer/client.ts` `getTokenPairs`; `services/terraclassic/factory.ts`; `services/terraclassic/pair.ts` `getPool` | | F6 probe | `frontend-dapp/src/services/terraclassic/assetCodeIdFreeze.ts`, `hooks/usePairCodeIdFreeze.ts` | | Terraport factory | `docs/terraport.md` (`terra1n75fg…rqqr`) | | Known LP table | `skills/AGENTS_FRONTEND_TOKEN_MIGRATE.md` | | Ops Refresh | `docs/runbooks/cw20-code-id-ops.md` § After a retail adopt | | Playbook | `skills/AGENTS_FRONTEND_TOKEN_MIGRATE.md` (**M626-9**, **M626-10**) | --- ## Recommended direction ### 1 — Discover venues when the token is loaded (before and after submit) Build a small helper (e.g. `communityTaxMigratePairs.ts`) that returns rows `{ venue, pair, symbols, note }`: | Venue | How to find | If lookup fails | |-------|-------------|-----------------| | **CL8Y** | Indexer `getTokenPairs` + factory `Pair` verify (official `VITE_FACTORY_ADDRESS` / launcher `factory`). LCD `Pool` for size. F6 `GetAssetCodeIds` vs live `code_id` when already on 11619 (post-tx). | “No CL8Y pool found” is a valid empty state (they will Create Pair — #633). | | **Terraport** | Query documented Terraport factory `Pair` for this token vs uluna / uusd / other known quotes; overlay the static ALPHA/Open table so those two always show when the loaded addr matches. | If factory query fails: keep static known rows + “We could not list every Terraport pool. Leave Terraport pools as they are.” | | **GDEX** | No factory pin. Do **not** guess. | Always: “GDEX pools (if any) keep this address. Do not register them. They stay 1:1.” | Show the list on the confirm card **and** on the success card (refetch after migrate). ### 2 — Per-venue next steps (copy + tool vs instructions) **CL8Y pair exists (pre- or post-adopt):** - Tell them: this CL8Y market **pauses / fails** until **CL8Y governance** refreshes the pool pin. The manager **cannot** do that. Provide: pair addr (copy), other-asset identity, and a short “what to send governance” blurb (pair addr + token addr + “RefreshPair after 11619 adopt” in operator language **off** the retail card — retail card stays human; optional “copy details” that includes addrs for a ticket). - After adopt, if F6 still frozen: **no** register button. CTA disabled with “Wait until governance refreshes this pool.” - After pins match (or LocalTerra analogue): offer **Register this CL8Y pool** (reuse #633 `registerListedPair`). Same factory verify. Hide when already `IsProtocolExempt.protocol`. - If they have **no** CL8Y pair: CTA **Create Pair** → `/create` (no query prefill) plus one line that new CL8Y pools are registered on create (#633). **Terraport / GDEX:** - Label **Other DEX**. “Leave these pools. They stay 1:1. Do not register them here.” - **No** register button. **No** “highest LP” if that LP is Terraport. - Optional finder link (Terraport UI / finder) is OK; not required. ### 3 — Success card checklist (ordered) 1. Token address unchanged. You are now the manager (source admin). 2. CL8Y: wait for governance refresh (list the pairs) **or** create a new CL8Y pair if none. 3. After refresh: register the CL8Y pool (button if ready) so buy/sell tax applies for everyone else. Manager LP/trades are not taxed (#633). 4. Other DEX: do nothing. Do not paste those pair addrs into register. Keep a single lead sentence on the page (#489). Details live in the inventory card, not a contract essay. ### 4 — Docs Extend `AGENTS_FRONTEND_TOKEN_MIGRATE.md` with this inventory UX (new **M626-** bullets or a sibling **M634** set). Point #633 at this issue for adopt leftovers instead of stretching Manage-only copy. --- ## Acceptance criteria - [ ] **AC1.** Loading a migratable token shows a venue list: CL8Y factory pairs (0–n), Terraport rows when discoverable or statically known, and a GDEX/unknown-external instruction row when no GDEX inventory exists. - [ ] **AC2.** Copy states CL8Y pools pause until governance refresh; manager cannot refresh; other DEX stays 1:1 and must not be registered. - [ ] **AC3.** No control on this page sends `RefreshPairAssetCodeIds`, `SetPairPaused`, or `AddWhitelistedCodeId`. - [ ] **AC4.** Register CTA appears only for a **factory-verified CL8Y** pair, only after adopt, only when F6 pins match (or pair is new/unfrozen), only for the connected manager. Terraport/GDEX never get a register button. - [ ] **AC5.** ALPHA / Open known Terraport pairs always appear when that token is loaded, with “leave 1:1 / do not register.” - [ ] **AC6.** Token with **no** CL8Y pair: empty CL8Y section + Create Pair instruction/link (`/create`, no prefill). Not an error. - [ ] **AC7.** Success card repeats the inventory + checklist. Primary link remains Manage. - [ ] **AC8.** `?token=` / `?addr=` / `?pair=` / `?payee=` do not prefill or retarget register. - [ ] **AC9.** Retail card has no wasm/env/code-id essays. Optional “copy details for governance” may include addrs. - [ ] **AC10.** Failed Terraport factory query degrades to static known rows + honest “could not list every other-DEX pool” — page still submitable. --- ## Test plan — happy / functional paths 1. **Honest 10184/6036, no CL8Y pair, no known Terraport.** Confirm shows CL8Y empty + other-DEX instruction. Submit. Success: Create Pair link + “leave other DEX.” Manage link still present. 2. **Honest token with one CL8Y pair.** Confirm lists that pair as “will pause / governance refresh.” After migrate, F6 frozen: register disabled + wait copy. After a mocked unfreeze: register enabled; success hides it (`already` / protocol true). 3. **Two CL8Y pairs.** Both listed with identity. Governance copy can name both. Register is per CL8Y row or one “register ready pools” control that **skips** frozen and **never** includes external addrs. 4. **Open 8266.** Terraport Open/LUNC row present. No register on that addr. Adopt does not call register. 5. **ALPHA 8654.** Both known Terraport rows + wipe confirm copy. No register. No whitelist CTA. 6. **LocalTerra mintable adopt.** Factory-whitelisted gem: CL8Y analogue pair listed; Terraport static table empty; GDEX instruction still shown as “if you have other DEX pools.” 7. **Indexer down / token not in catalog.** LCD factory pagination or `Pair` probe still finds a CL8Y pair; empty indexer ≠ “no CL8Y pool” if factory has one. 8. **Terraport factory LCD fail.** Static ALPHA/Open still show; generic other-DEX fallback; migrate CTA not blocked. 9. **Already tax (11619).** Verdict `already_tax`; inventory may still show venues as read-only help; no adopt tx. 10. **Non-admin connected.** No migrate CTA; inventory can still be informational. 11. **Vitest.** Confirm/success copy matrix (wipe vs honest); venue classification (factory vs Terraport vs unknown); register enabled iff CL8Y + post-adopt + not frozen + manager; query params ignored; no Refresh execute in the page module. --- ## Test plan — attack / abuse / hack vectors 1. **Register Terraport addr.** UI must not offer it. If a user pastes one into any leftover field, client must factory-verify and refuse. On-chain already rejects (**T592-9**); keep that as the backstop. 2. **Highest-LP trap.** Do not reuse #633 “largest pool” if the largest TVL is Terraport ALPHA/LUNC. Ranking for *this* page’s register tool is CL8Y-only. 3. **Spoof factory.** A pair that reports this token but is not official-factory `Pair` must not get a register button. 4. **Refresh smuggle.** Page must not build `refresh_pair_asset_code_ids` / `set_pair_paused` / `add_whitelisted_code_id` messages (static grep in tests). 5. **Unlisted other asset.** Do not tell the user to Refresh a CL8Y pair whose other side is not factory-whitelisted. Copy: governance will skip that pool; create a new CL8Y pair vs a listed asset instead. 6. **8654 whitelist.** No CTA or copy that says “list 8654 to save Terraport LP.” 7. **URL injection.** `?pair=terra1terraport…` must not become the register target. 8. **Half-migrated / failed UpdateAdmin.** If adopt wasm moved but admin is not CMM, show unverified-admin / stop; do not register (catalog/attest rules). Existing **C593-7** banner on Manage is not enough on this page if they never leave it. 9. **Register before Refresh.** Button stays disabled while F6 frozen so provide/swap do not hit fail-closed + user blame. Do not batch register into the adopt tx. 10. **FoT on unregistered CL8Y + TransferTax.** Adopt honest profile has transfer tax off. Do not enable TransferTax in this flow. If they later unlock it, #633 register-before-LP still applies. 11. **Cross-venue confuse.** Finder/Terraport links must not use the same button style as “Register CL8Y pool.” 12. **Catalog unattested.** Do not treat indexer listing as F6 / whitelist. --- ## Verification criteria Close only when: ```bash make verify-issue-626 # add make verify-issue-<this> — Migrate inventory Vitest + copy; no Refresh/register-external ``` - Manual columbus-5 (or recorded LCD fixtures): load Open `terra1qz56v…` → Terraport Open/LUNC shown, no register; load ALPHA `terra1x6e64…` → both Terraport rows, wipe copy, no register. - LocalTerra: adopt a factory-listed mintable that already has a CL8Y pair → confirm names that pair as governance-refresh; after Refresh (or local pin already matching), register tool lists **only** that factory pair; Terraport instruction row still present as “other DEX if any.” - Grep: migrate page/helpers never emit `refresh_pair_asset_code_ids` or call `registerListedPair` with a non-factory addr. - Playbook updated. #633 description should point here for adopt leftovers (comment on #633 is enough). Do **not** close if the page still only has the generic `MIGRATE_LP_CONFIRM` line, or if the only “tool” is a raw pair paste that can target Terraport. --- ## Out of scope - Autoregister on **new** Create Pair / AutoLP bind / manager role tax skip (#633). - Giving the token admin `RefreshPairAssetCodeIds` or factory pause. - Building a full GDEX factory indexer. - Pair/router wasm changes. Whitelisting 8654. Unregister API.
PlasticDigits commented 2026-08-25 02:08:41 +00:00 (Migrated from gitlab.com)

mentioned in issue #633

mentioned in issue #633
PlasticDigits commented 2026-08-25 02:29:30 +00:00 (Migrated from gitlab.com)

mentioned in issue #635

mentioned in issue #635
PlasticDigits commented 2026-08-25 02:29:31 +00:00 (Migrated from gitlab.com)

marked as related to #635

marked as related to #635
PlasticDigits commented 2026-08-25 02:48:27 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1138

mentioned in merge request !1138
PlasticDigits commented 2026-08-25 02:48:34 +00:00 (Migrated from gitlab.com)

Implemented in !1138. make verify-issue-634 is green (Vitest + docs, twice). Remaining close gates: columbus-5 Open/ALPHA LCD walkthrough and LocalTerra adopt+Refresh+register of an existing CL8Y pair.

Implemented in !1138. `make verify-issue-634` is green (Vitest + docs, twice). Remaining close gates: columbus-5 Open/ALPHA LCD walkthrough and LocalTerra adopt+Refresh+register of an existing CL8Y pair.
PlasticDigits commented 2026-08-25 03:05:25 +00:00 (Migrated from gitlab.com)

mentioned in commit 96b318d9f6

mentioned in commit 96b318d9f6cbe6fd4ae57cb1ed102505cd5f563f
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-25 03:05:25 +00:00
PlasticDigits commented 2026-08-25 03:06:23 +00:00 (Migrated from gitlab.com)

mentioned in issue #636

mentioned in issue #636
PlasticDigits commented 2026-08-25 03:06:23 +00:00 (Migrated from gitlab.com)

marked as related to #636

marked as related to #636
PlasticDigits commented 2026-08-25 03:06:34 +00:00 (Migrated from gitlab.com)

!1138 merge note (no CI wait)

Merged !1138 into main as 96b318d9 (source f4408a3a). GitLab reported no conflicts (can_be_merged); local git merge-tree against current main also produced a clean tree (MR was 0 behind, 1 ahead). Merged with --auto-merge=false (did not wait for CI). Source branch removed on origin.

Sanity / AC

make verify-issue-634 on the source branch: 4/4 PASS (Vitest 25 tests: helper + inventory card + migrate page; docs M634 + no Refresh execute; twice).

AC Result
AC1 venue list Code + Vitest. CL8Y 0–n, Terraport static/factory, GDEX instruction always. Live columbus-5 not run.
AC2 pause / 1:1 copy Helper strings + card. Governance ticket is copy-details only.
AC3 no Refresh / pause / whitelist Grep + docs step. Page never builds those executes.
AC4 register gate CTA only factory-verified CL8Y, post-adopt, F6 unfrozen, manager + CMM + tax pin. Terraport/GDEX never get a button. registerMigrateCl8yPair factory-verifies again.
AC5 ALPHA / Open Terraport Helper overlay + page test for ALPHA. Open is prefix/suffix match (terra1qz56v… / terra1uxr6m…nypyc) — full Open pair bech32 not pinned. Live LCD walkthrough not run.
AC6 empty CL8Y Empty state + Create Pair /create (no prefill).
AC7 success checklist + Manage Success checklist + Manage link remains primary.
AC8 query params ?token= / ?addr= / ?pair= / ?payee= voided; Vitest confirms no prefill / no register retarget.
AC9 retail copy Heading + one lead sentence; no wasm/env/code-id essays on the card.
AC10 Terraport degrade Failed factory query keeps static rows + incomplete copy; page stays submitable (Vitest).

GitLab CI on !1138 failed with ci_quota_exceeded (frontend-build / frontend / gitleaks) — same quota class as !1136 / !1137, not a code defect.

Problems / leftovers (do not reopen this issue)

Tracked on #636:

  • Live columbus-5 Open + ALPHA inventory walkthrough (Terraport rows, no other-DEX register).
  • LocalTerra adopt of a factory-listed mintable that already has a CL8Y pair, then Refresh + register-only-that-factory-pair.
  • Pin full Open Terraport pair bech32 if LCD confirms it.

Adopt wasm / Coolify pin leftovers stay on #628. Autoregister leftovers stay on #635.

## !1138 merge note (no CI wait) Merged [!1138](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/420) into `main` as `96b318d9` (source `f4408a3a`). GitLab reported **no conflicts** (`can_be_merged`); local `git merge-tree` against current `main` also produced a clean tree (MR was 0 behind, 1 ahead). Merged with `--auto-merge=false` (did not wait for CI). Source branch removed on origin. ### Sanity / AC `make verify-issue-634` on the source branch: **4/4 PASS** (Vitest 25 tests: helper + inventory card + migrate page; docs M634 + no Refresh execute; twice). | AC | Result | |----|--------| | AC1 venue list | Code + Vitest. CL8Y 0–n, Terraport static/factory, GDEX instruction always. Live columbus-5 not run. | | AC2 pause / 1:1 copy | Helper strings + card. Governance ticket is copy-details only. | | AC3 no Refresh / pause / whitelist | Grep + docs step. Page never builds those executes. | | AC4 register gate | CTA only factory-verified CL8Y, post-adopt, F6 unfrozen, manager + CMM + tax pin. Terraport/GDEX never get a button. `registerMigrateCl8yPair` factory-verifies again. | | AC5 ALPHA / Open Terraport | Helper overlay + page test for ALPHA. Open is prefix/suffix match (`terra1qz56v…` / `terra1uxr6m…nypyc`) — full Open pair bech32 not pinned. Live LCD walkthrough not run. | | AC6 empty CL8Y | Empty state + Create Pair `/create` (no prefill). | | AC7 success checklist + Manage | Success checklist + Manage link remains primary. | | AC8 query params | `?token=` / `?addr=` / `?pair=` / `?payee=` voided; Vitest confirms no prefill / no register retarget. | | AC9 retail copy | Heading + one lead sentence; no wasm/env/code-id essays on the card. | | AC10 Terraport degrade | Failed factory query keeps static rows + incomplete copy; page stays submitable (Vitest). | GitLab CI on !1138 failed with `ci_quota_exceeded` (frontend-build / frontend / gitleaks) — same quota class as !1136 / !1137, not a code defect. ### Problems / leftovers (do not reopen this issue) Tracked on **[#636](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/636)**: - Live columbus-5 Open + ALPHA inventory walkthrough (Terraport rows, no other-DEX register). - LocalTerra adopt of a factory-listed mintable that already has a CL8Y pair, then Refresh + register-only-that-factory-pair. - Pin full Open Terraport pair bech32 if LCD confirms it. Adopt wasm / Coolify pin leftovers stay on [#628](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/628). Autoregister leftovers stay on [#635](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/635).
PlasticDigits commented 2026-08-25 03:50:57 +00:00 (Migrated from gitlab.com)

mentioned in commit 67a8bdb16c

mentioned in commit 67a8bdb16c7e33581784a3825d70fb9878c4060d
PlasticDigits commented 2026-08-25 03:51:23 +00:00 (Migrated from gitlab.com)

LocalTerra verify (not columbus-5)

Pushed to main as 67a8bdb1 (scripts/qa/localterra-634-migrate-inventory.sh + VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634). Do not reopen this issue — columbus-5 Open/ALPHA leftovers stay on #636.

Ran

  • VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634 → 5/5 PASS (Vitest + M634 docs grep + LocalTerra live).
  • Instantiated a factory-listed mintable that already had a CL8Y pair; honest adopt did not RegisterListedPair.
  • After adopt the CL8Y pair was F6-frozen; ops RefreshPairAssetCodeIds (not the retail page) then register listed only that factory pair.
  • Non-factory register rejected. Terraport factory probe on LocalTerra invented no rows. Mintable with no CL8Y pair is a valid empty inventory.
  • Fix during verify: LocalTerra cw20-mintable writes cw2 crates.io:cw20-base (10184 analogue), not cw20-mintable. Assertion + playbook updated.

Checklist (issue body + comments)

  • LocalTerra: factory-listed mintable with an existing CL8Y pair named for governance-refresh
  • Adopt does not register (M626-10 / M634-4)
  • After ops Refresh, register tool / LCD register lists only that factory pair
  • Terraport probe does not invent LocalTerra rows; GDEX stays instruction-only
  • No-pair mintable is valid empty inventory
  • Non-factory register rejected
  • Grep: migrate page never emits Refresh / pause / whitelist (make verify-issue-634)
  • make verify-issue-626 not re-run in this session
  • columbus-5 Open terra1qz56v… LCD walkthrough
  • columbus-5 ALPHA terra1x6e64… LCD walkthrough
  • Pin full Open Terraport pair bech32 if LCD confirms it

Close decision

Leave closed. LocalTerra M634 leftover from the !1138 merge note is now proven. Columbus-5 inventory walkthroughs remain on #636. No M634 invariant was wrong.

How to re-run: make setup-cloud-localterra (or make deploy-local on a healthy chain), then VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634.

## LocalTerra verify (not columbus-5) Pushed to `main` as `67a8bdb1` (`scripts/qa/localterra-634-migrate-inventory.sh` + `VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634`). **Do not reopen this issue** — columbus-5 Open/ALPHA leftovers stay on #636. ### Ran - `VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634` → **5/5 PASS** (Vitest + M634 docs grep + LocalTerra live). - Instantiated a factory-listed mintable that already had a CL8Y pair; honest adopt did **not** `RegisterListedPair`. - After adopt the CL8Y pair was F6-frozen; ops `RefreshPairAssetCodeIds` (not the retail page) then register listed **only** that factory pair. - Non-factory register rejected. Terraport factory probe on LocalTerra invented no rows. Mintable with no CL8Y pair is a valid empty inventory. - Fix during verify: LocalTerra `cw20-mintable` writes cw2 `crates.io:cw20-base` (10184 analogue), not `cw20-mintable`. Assertion + playbook updated. ### Checklist (issue body + comments) - [x] LocalTerra: factory-listed mintable with an existing CL8Y pair named for governance-refresh - [x] Adopt does not register (M626-10 / M634-4) - [x] After ops Refresh, register tool / LCD register lists **only** that factory pair - [x] Terraport probe does not invent LocalTerra rows; GDEX stays instruction-only - [x] No-pair mintable is valid empty inventory - [x] Non-factory register rejected - [x] Grep: migrate page never emits Refresh / pause / whitelist (`make verify-issue-634`) - [ ] `make verify-issue-626` not re-run in this session - [ ] columbus-5 Open `terra1qz56v…` LCD walkthrough - [ ] columbus-5 ALPHA `terra1x6e64…` LCD walkthrough - [ ] Pin full Open Terraport pair bech32 if LCD confirms it ### Close decision **Leave closed.** LocalTerra M634 leftover from the !1138 merge note is now proven. Columbus-5 inventory walkthroughs remain on #636. No M634 invariant was wrong. How to re-run: `make setup-cloud-localterra` (or `make deploy-local` on a healthy chain), then `VERIFY634_REQUIRE_CHAIN=1 make verify-issue-634`.
PlasticDigits commented 2026-08-25 05:24:08 +00:00 (Migrated from gitlab.com)

Columbus-5 leftover verify #636 is closed (Open/ALPHA live inventory + full Open Terraport bech32). Do not reopen this issue unless an M634 invariant is wrong.

Columbus-5 leftover verify [#636](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/636) is closed (Open/ALPHA live inventory + full Open Terraport bech32). Do not reopen this issue unless an **M634** invariant is wrong.
PlasticDigits commented 2026-08-25 05:51:00 +00:00 (Migrated from gitlab.com)

mentioned in issue #603

mentioned in issue #603
PlasticDigits commented 2026-08-25 06:07:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #614

mentioned in issue #614
PlasticDigits commented 2026-08-25 06:12:02 +00:00 (Migrated from gitlab.com)

mentioned in issue #628

mentioned in issue #628
PlasticDigits commented 2026-08-26 04:20:43 +00:00 (Migrated from gitlab.com)

mentioned in issue #670

mentioned in issue #670
PlasticDigits commented 2026-08-26 04:20:44 +00:00 (Migrated from gitlab.com)

marked as related to #670

marked as related to #670
PlasticDigits commented 2026-08-26 07:15:03 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1168

mentioned in merge request !1168
PlasticDigits commented 2026-08-27 11:52:21 +00:00 (Migrated from gitlab.com)

mentioned in issue #690

mentioned in issue #690
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#634
No description provided.