Launch blocker: create_pair reverts for tokens with a digit in the symbol (UST1, CL8Y) #518

Closed
opened 2026-08-11 10:09:55 +00:00 by leonardocolucci · 16 comments
leonardocolucci commented 2026-08-11 10:09:55 +00:00 (Migrated from gitlab.com)

Summary — launch blocker

create_pair reverts for any pair whose token symbol contains a digit, because the LP token the pair mints gets a symbol that fails cw20's [a-zA-Z\-]{3,12} validator. This blocks every planned economic pool: UST1/cUSTC, UST1/USTR, cLUNC/UST1, and any CL8Y pair. cLUNC/cUSTC (all-letter symbols) is the only combination among the wrapped/economic tokens that currently succeeds.

Found in simulation while building pool-seeding tooling — no funds spent.

Reproduction

create_pair { asset_infos: [cLUNC, UST1] } on the factory (terra1ejpgvv7...) reverts in simulation:

failed to execute message; message index: 0: dispatch: Generic error:
Ticker symbol is not in expected format [a-zA-Z\-]{3,12}:
instantiate wasm contract failed

Isolation (each real token paired against an existing gem, via /cosmos/tx/v1beta1/simulate):

Token create_pair result
cLUNC ✓ OK
cUSTC ✓ OK
UST1 ✗ Ticker reject
CL8Y ✗ Ticker reject

Root cause

contracts/pair/src/contract.rs ~line 543 derives the LP symbol from the constituent token symbols:

format!("{}-{}-LP", short_a, short_b)   // short_x = symbol.chars().take(4)

So the LP symbol for e.g. UST1/cUSTC is UST1-cUST-LP, and for any CL8Y pair CL8Y-…-LP. The digit (1, 8) then fails the cw20 symbol validator (cw20_mintable), which only permits [a-zA-Z\-], and the LP instantiate — and therefore the whole create_pair — reverts.

Suggested fixes (any one; all need a migration)

  1. Sanitize the derived LP symbol — strip/replace non-alpha chars before building it (UST1 → UST). Smallest change, keeps human-readable LP tickers.
  2. Fall back to the generic symbol when the derived one would be invalid — the None branch already produces a valid CL8Y-LP; reuse it. LP name/label can stay unique for display.
  3. Allow digits in cw20_mintable's symbol validator — arguably the correct fix; LP and many real tickers legitimately contain digits. Widest blast radius, so option 1 or 2 may be the safer launch-unblocker.

Happy to retest any fix immediately in simulation before you spend a creation fee.

## Summary — launch blocker `create_pair` reverts for **any pair whose token symbol contains a digit**, because the LP token the pair mints gets a symbol that fails cw20's `[a-zA-Z\-]{3,12}` validator. This blocks every planned economic pool: **UST1/cUSTC, UST1/USTR, cLUNC/UST1, and any CL8Y pair.** cLUNC/cUSTC (all-letter symbols) is the only combination among the wrapped/economic tokens that currently succeeds. Found in simulation while building pool-seeding tooling — no funds spent. ## Reproduction `create_pair { asset_infos: [cLUNC, UST1] }` on the factory (`terra1ejpgvv7...`) reverts in simulation: ``` failed to execute message; message index: 0: dispatch: Generic error: Ticker symbol is not in expected format [a-zA-Z\-]{3,12}: instantiate wasm contract failed ``` Isolation (each real token paired against an existing gem, via `/cosmos/tx/v1beta1/simulate`): | Token | create_pair result | |---|---| | cLUNC | ✓ OK | | cUSTC | ✓ OK | | **UST1** | ✗ Ticker reject | | **CL8Y** | ✗ Ticker reject | ## Root cause `contracts/pair/src/contract.rs` ~line 543 derives the LP symbol from the constituent token symbols: ```rust format!("{}-{}-LP", short_a, short_b) // short_x = symbol.chars().take(4) ``` So the LP symbol for e.g. UST1/cUSTC is `UST1-cUST-LP`, and for any CL8Y pair `CL8Y-…-LP`. The digit (`1`, `8`) then fails the cw20 symbol validator (`cw20_mintable`), which only permits `[a-zA-Z\-]`, and the LP instantiate — and therefore the whole `create_pair` — reverts. ## Suggested fixes (any one; all need a migration) 1. **Sanitize the derived LP symbol** — strip/replace non-alpha chars before building it (`UST1` → `UST`). Smallest change, keeps human-readable LP tickers. 2. **Fall back to the generic symbol** when the derived one would be invalid — the `None` branch already produces a valid `CL8Y-LP`; reuse it. LP `name`/`label` can stay unique for display. 3. **Allow digits in `cw20_mintable`'s symbol validator** — arguably the correct fix; LP and many real tickers legitimately contain digits. Widest blast radius, so option 1 or 2 may be the safer launch-unblocker. Happy to retest any fix immediately in simulation before you spend a creation fee.
PlasticDigits commented 2026-08-15 09:30:51 +00:00 (Migrated from gitlab.com)

Approved

Approved
PlasticDigits commented 2026-08-15 09:34:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #513

mentioned in issue #513
PlasticDigits commented 2026-08-15 09:39:22 +00:00 (Migrated from gitlab.com)

mentioned in commit 3259ae01dd

mentioned in commit 3259ae01ddf51224e836bb50f92e1df8aced0f97
PlasticDigits commented 2026-08-15 09:39:24 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1052

mentioned in merge request !1052
PlasticDigits commented 2026-08-15 09:43:33 +00:00 (Migrated from gitlab.com)

Follow-up on the #518 unblock: we need LP tickers to keep digits 0-9 (so UST1 / CL8Y stay recognizable: UST1-CUST-LP, CL8Y-CLUN-LP) and sanitize only non-alphanumeric characters from the asset-symbol prefixes.

That cannot ship as a pair-only letter-strip. columbus-5 lp_token_code_id still validates classic [a-zA-Z\-]{3,12} (no digits), so this requires a contract upgrade:

  1. New pair wasm — alphanumeric prefix sanitize + {a}-{b}-LP.
  2. Digit-allowing LP CW20 (cw20-mintable [a-zA-Z0-9\-]{3,12}) stored and set as factory lp_token_code_id.
  3. Factory UpdateConfig must accept pair_code_id / lp_token_code_id (not settable today) so new create_pair uses the upgraded codes. Factory wasm migrate + that UpdateConfig is the operator path.

Existing pairs keep their current LP tokens (instantiate-time only). I will update MR !1052 with the sanitizer change, factory code-id update, an upgrade script, and tests.

Follow-up on the #518 unblock: we need LP tickers to **keep digits `0-9`** (so UST1 / CL8Y stay recognizable: `UST1-CUST-LP`, `CL8Y-CLUN-LP`) and **sanitize only non-alphanumeric** characters from the asset-symbol prefixes. That cannot ship as a pair-only letter-strip. columbus-5 `lp_token_code_id` still validates classic `[a-zA-Z\-]{3,12}` (no digits), so this **requires a contract upgrade**: 1. New **pair** wasm — alphanumeric prefix sanitize + `{a}-{b}-LP`. 2. Digit-allowing **LP CW20** (`cw20-mintable` `[a-zA-Z0-9\-]{3,12}`) stored and set as factory `lp_token_code_id`. 3. Factory **`UpdateConfig`** must accept `pair_code_id` / `lp_token_code_id` (not settable today) so new `create_pair` uses the upgraded codes. Factory wasm migrate + that `UpdateConfig` is the operator path. Existing pairs keep their current LP tokens (instantiate-time only). I will update MR !1052 with the sanitizer change, factory code-id update, an upgrade script, and tests.
PlasticDigits commented 2026-08-15 09:46:38 +00:00 (Migrated from gitlab.com)

mentioned in commit b53ebd60ff

mentioned in commit b53ebd60ffc73e72322ae2970995f84e9797aad5
PlasticDigits commented 2026-08-15 09:51:35 +00:00 (Migrated from gitlab.com)

Sanity check of MR !1052 (fix/518-lp-symbol-digits @ b53ebd6) against this issue's acceptance (keep digits, sanitize non-alnum only, factory UpdateConfig code ids, classic LP still rejects digits).

Meets acceptance in code. make verify-issue-518 passed locally (7/7, no chain). CI on !1052 failed with ci_quota_exceeded (not a code failure); merging without waiting for CI.

Does not clear the launch blocker by itself. Economic create_pair for UST1/CL8Y stays blocked on columbus-5 until the operator upgrade runs: store factory+pair wasm → migrate factory to 1.6.0 → UpdateConfig { pair_code_id, lp_token_code_id } (reuse UPGRADE518_LP_CODE_ID=10184 or store cw20_mintable.wasm). Then re-simulate create_pair for UST1/cUSTC and CL8Y/cLUNC.

Non-blocking test gaps: no mintable-LP success integration test for CL8Y (UST1 path is covered); no UpdateConfig { lp_token_code_id: Some(0) } rejection test. Existing pairs are unchanged (instantiate-time LP only).

Sanity check of MR !1052 (`fix/518-lp-symbol-digits` @ `b53ebd6`) against this issue's acceptance (keep digits, sanitize non-alnum only, factory `UpdateConfig` code ids, classic LP still rejects digits). **Meets acceptance in code.** `make verify-issue-518` passed locally (7/7, no chain). CI on !1052 failed with `ci_quota_exceeded` (not a code failure); merging without waiting for CI. **Does not clear the launch blocker by itself.** Economic `create_pair` for UST1/CL8Y stays blocked on columbus-5 until the operator upgrade runs: store factory+pair wasm → migrate factory to 1.6.0 → `UpdateConfig { pair_code_id, lp_token_code_id }` (reuse `UPGRADE518_LP_CODE_ID=10184` or store `cw20_mintable.wasm`). Then re-simulate `create_pair` for UST1/cUSTC and CL8Y/cLUNC. **Non-blocking test gaps:** no mintable-LP success integration test for CL8Y (UST1 path is covered); no `UpdateConfig { lp_token_code_id: Some(0) }` rejection test. Existing pairs are unchanged (instantiate-time LP only).
PlasticDigits commented 2026-08-15 09:51:42 +00:00 (Migrated from gitlab.com)

mentioned in commit e0b6033ae6

mentioned in commit e0b6033ae6d34b43886c7c977532037377383178
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-15 09:51:43 +00:00
PlasticDigits commented 2026-08-15 09:57:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #521

mentioned in issue #521
PlasticDigits commented 2026-08-15 09:57:14 +00:00 (Migrated from gitlab.com)

marked as related to #521

marked as related to #521
PlasticDigits commented 2026-08-15 10:19:52 +00:00 (Migrated from gitlab.com)

mentioned in issue #516

mentioned in issue #516
PlasticDigits commented 2026-08-16 08:43:17 +00:00 (Migrated from gitlab.com)

mentioned in issue #532

mentioned in issue #532
leonardocolucci commented 2026-08-16 12:05:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #534

mentioned in issue #534
PlasticDigits commented 2026-08-17 03:45:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #542

mentioned in issue #542
leonardocolucci commented 2026-08-17 21:14:18 +00:00 (Migrated from gitlab.com)

Thanks for the rapid turnaround on this one — going straight to the digit-allowing LP token + factory code-id upgrade rather than a pair-only strip was the right call, and it unblocked the UST1 launch.

Thanks for the rapid turnaround on this one — going straight to the digit-allowing LP token + factory code-id upgrade rather than a pair-only strip was the right call, and it unblocked the UST1 launch.
PlasticDigits commented 2026-08-20 13:31:31 +00:00 (Migrated from gitlab.com)

mentioned in issue #584

mentioned in issue #584
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#518
No description provided.