feat(frontend): live UST1 mint/burn/circ, cLUNC/cUSTC supply, and CR from UST1 circulating #11

Closed
opened 2026-08-15 09:34:25 +00:00 by PlasticDigits · 12 comments
PlasticDigits commented 2026-08-15 09:34:25 +00:00 (Migrated from gitlab.com)

Summary

Replace the UST1 Issuance Coming Soon placeholder with live mint / burn / circulating, plus a finder link. Add cLUNC and cUSTC circulating supply. Fix Key Ratios so collateralization (and related liability ratios) use UST1 circulating supply — not a hardcoded 0 that forces ∞, and not the stub that would become 0% the moment supply is non-zero.

Depends on priced treasury assets (including vFDUSD once #10 lands). This issue owns the liability side and the ratio math.


Current codebase

Component Path Behavior today
UST1 card frontend/src/pages/TreasuryPage.tsx notLaunched={true} → Coming Soon badge; no explorerUrl; zeros for mint/burn/supply.
Issuance UI frontend/src/components/treasury/IssuanceCard.tsx Supports minted / burned / circulating + optional finder link. Coming Soon replaces the link.
Data hook frontend/src/hooks/useTreasury.ts USTR: token_info.total_supply as minted and supply; burned hardcoded 0. UST1: ust1Supply = BigInt(0) with comment “Currently no UST1 issued”.
Ratio stub same file, ratios hasUst1Issued ? 0 : Infinity for collateralization, ustcPerUst1, assetsToLiabilities. When supply is 0 → ∞ (OK). When supply > 0 → 0 — it never computes a real CR.
Ratio UI frontend/src/components/treasury/RatiosCard.tsx Shows %, USTC per UST1, assets/liabilities x, USTR backing. ∞ → emerald. Color bands (>=100 / >=50) do not match ECONOMICS tiers (190 / 110 / 95).
Types frontend/src/types/treasury.ts TokenIssuance { minted, burned, supply }; TreasuryRatios.collateralization documented as percent (150 = 150% backed).
Token registry tokenlist.json, CONTRACTS No UST1, cLUNC, or cUSTC. USTR address only.
CW20 queries contractService.getTokenInfo { token_info: {} } → name, symbol, decimals, total_supply. No lifetime minted/burned counters (standard cw20-mintable).
Window stats ust1-window QueryMsg (out of repo) Config + EffectiveSwap only — no cumulative mint/burn stats.
Wrap mapper contracts/contracts/wrap-mapper No lifetime wrap/unwrap counters; outstanding wrap = CW20 total_supply.
Economics SSoT docs/ECONOMICS.md, docs/CONTRACTS.md CR = collateral USD / UST1 liabilities at $1 each. Normalize decimals before dividing. Tiers: RED <95%, YELLOW 95–110%, GREEN 110–190%, BLUE >190%.
Docs docs/ARCHITECTURE.md UST1 still described as “Phase 2” / not launched. Mainnet is live (see pins).

Mainnet pins (do not invent addresses):

Name Code Address Decimals
UST1 10184 terra1f0eqgy9w7e5e7up97vjudqwx38tesf8ylx75x2lv3nwm0clry0pqmgfy72 6
cLUNC 10184 terra1437qslye72t7qmmahn4t5chz50r8a62g45phwkquwpyu2l62u6ksqssgdg 6
cUSTC 10184 terra1nap4dxh9tv35v0ynd9m4k6zt6c0dq6weszc4j5m564kjls56hu7qcr56ch 6
ust1-window 11566 terra1zxwpzpzpleatqn39r00grau4yt29sld8pw78s7ktvjafnj5nsaxq0h3rh2 —
Finder — https://finder.terraclassic.community/columbus-5 —

UST1 is minted/burned by ust1-window (vFDUSD deposit → mint; redeem → burn). cLUNC/cUSTC outstanding = wrapped native (treasury keeps native custody).


Why this is needed

  1. UST1 is live. The Coming Soon badge and zeroed issuance are false. Users need mint / burn / circ and a contract link — same as USTR.
  2. cLUNC/cUSTC are the public wrap surface (docs/DEPLOYMENT.md Phase 4 frontend checkbox still open). Showing supply (not treasury CW20 dust) proves how much native is wrapped.
  3. Key Ratios are unsafe as implemented:
    • Hardcoded ust1Supply = 0 always prints ∞ (looks maximally healthy).
    • The hasUst1Issued ? 0 : Infinity branch would flip to 0% if someone only un-hardcodes supply — still not a CR.
  4. CR must use circulating / outstanding UST1 (token_info.total_supply), i.e. unburned liabilities, not “Coming Soon zeros” and not USTR supply.

Constraints / guardrails

  • Denominator for CR / USTC-per-UST1 / assets-to-liabilities = UST1 CW20 token_info.total_supply (outstanding = minted − burned on this token). Do not use USTR supply. Do not use window 24h volume.
  • ∞ only if UST1 token_info succeeded and total_supply === 0. Query failure → N/A / loading / last good — never ∞ (that hides undercollateralization).
  • When supply > 0, compute ratios. Never return the stub 0.
  • Liability unit: 1 UST1 = $1 target (ECONOMICS). collateralization % = (sum of priced treasury assets in USD / UST1_outstanding_in_whole_tokens) * 100.
  • Decimal hygiene: UST1 6 dp, USTC/LUNC 6, USTR 18, vFDUSD 6. Normalize before dividing (docs/CONTRACTS.md). Do not Number(bigint) huge values unsafely — use decimal-adjusted floats only after scaling to whole tokens, or integer math then scale.
  • Do not double-count wraps: do not add cLUNC/cUSTC as treasury assets for CR (native LUNC/USTC already counted). Supply cards are informational only.
  • Do not add UST1 to tokenlist as a treasury holding (it is the liability, not collateral).
  • Do not scan LCD txs / paginate all_accounts to reconstruct lifetime mint/burn (quota + abuse).
  • Lifetime mint/burn: cw20-mintable has no cumulative counters; window has no stats query. Required: circulating = total_supply. Minted / burned: keep the three-field card; use minted = supply, burned = 0 only if you cannot get lifetime totals — and tooltip that these are not lifetime counters. Prefer minted − burned = supply if a later window stats query appears. Do not invent burns.
  • Finder link on UST1 and keep/repurpose Coming Soon: remove notLaunched once live numbers show. Link: {scanner}/address/{TERRA_UST1}.
  • cLUNC/cUSTC: show circulating supply (and minted/burned only if you use the same honest supply / burned=0 pattern). Include finder links. Do not imply they back UST1 as extra collateral.
  • Reuse contractService LCD rate limits; batch/dedupe token_info queries; do not add a new poll faster than existing treasury 30s.
  • Color tiers: if touched, align with ECONOMICS (95 / 110 / 190), not the current 50 / 100. In scope if you edit RatiosCard; do not expand into a full SSoT dashboard.
  • Incomplete prices: CR must not treat missing USD as $0 without a visible incomplete state (understates backing) or as $1 (overstates). Document which assets entered the sum.

Relevant files

File Role
frontend/src/pages/TreasuryPage.tsx Drop notLaunched; pass explorer URL; add cLUNC/cUSTC supply UI
frontend/src/components/treasury/IssuanceCard.tsx Reuse for UST1 + wrap supplies (or a thin supply variant)
frontend/src/components/treasury/RatiosCard.tsx Render computed CR; N/A vs ∞; optional tier colors
frontend/src/hooks/useTreasury.ts Fetch UST1 / cLUNC / cUSTC token_info; real ratio math
frontend/src/types/treasury.ts Optional wrap-supply fields; ratio NaN/incomplete flag
frontend/src/utils/constants.ts ust1Token, cLunc, cUstc (and window if needed)
frontend/src/services/contract.ts Already has getTokenInfo
frontend/src/hooks/usePrices.ts Asset USD for CR numerator (vFDUSD via #10)
frontend/public/assets/tokens/{UST1,CLUNC,CUSTC}.png Icons
docs/DEPLOYMENT.md, README.md Tick Phase 4 frontend address wiring

  1. Add mainnet addresses to CONTRACTS (testnet empty/TODO). Do not put UST1/cLUNC/cUSTC on the treasury-balance tokenlist loop.
  2. In fetchTreasuryData:
    • ust1Info = getTokenInfo(ust1Token) → supply = total_supply.
    • ustrIssuance unchanged.
    • cLuncSupply / cUstcSupply from their token_info.
    • ust1Issuance: supply live; minted/burned per guardrail above.
  3. Ratios (only after successful UST1 supply read):
    • S = whole UST1 (supply / 10^6).
    • If S == 0: collateralization = ustcPerUst1 = assetsToLiabilities = Infinity.
    • If S > 0:
      • assetsUsd = Σ (whole_balance * usd_price) for treasury assets with valid prices (LUNC, USTC, ALPHA, …, vFDUSD when #10 ready). Skip unpriced assets and flag incomplete.
      • collateralization = (assetsUsd / S) * 100
      • ustcPerUst1 = whole_USTC / S
      • assetsToLiabilities = assetsUsd / S (same ratio as CR, x not % — keep current labels).
    • ustrBacking unchanged (USTC / USTR).
  4. UI: UST1 card live + finder. Add two supply cards (or a wrap-supply row) for cLUNC/cUSTC with finder links. Ratios consume the new numbers.
  5. Cross-check #10: once vFDUSD USD exists, it must enter assetsUsd. Ship CR without it only with incomplete-data UX.

Acceptance criteria

  • UST1 card: no Coming Soon; minted / burned / circ shown; circ matches on-chain token_info.total_supply.
  • UST1 “View Token” → finder columbus-5 address terra1f0eq…fy72.
  • minted - burned === supply when both lifetime fields are known; if burned is unknown, UI does not claim historical burns.
  • cLUNC and cUSTC supplies match their token_info.total_supply; finder links correct; not listed as extra treasury collateral rows solely because of this issue.
  • UST1 supply 0 (successful query) → ratios ∞.
  • UST1 supply > 0 → CR = priced assets USD / outstanding UST1 × 100 (not 0, not ∞, not USTR-based).
  • UST1 token_info failure → ratios N/A (or last good), not ∞.
  • Decimals: 6 for UST1/cLUNC/cUSTC; USTR backing still 18-vs-6 safe.
  • Unpriced assets do not silently zero or inflate CR; incomplete state visible.
  • Existing USTR issuance + treasury asset grid still work.

Test plan (all paths)

UST1 issuance

  • Live total_supply = 0 → circ 0; ratios ∞; no Coming Soon.
  • Live total_supply > 0 → circ formatted (6 dp); finder works.
  • token_info fail → issuance loading/error; ratios not ∞.
  • notLaunched removed; USTR card still has its finder link.
  • Minted/burned: consistent with guardrail; no LCD tx-scan in network panel.

cLUNC / cUSTC

  • Each supply matches chain; 0 supply still shown (these are supply infos, not dust-hidden treasury rows).
  • Query fail for one wrap token does not blank UST1 or the other wrap.
  • Not added to CR numerator.

Key ratios — happy

  • Fixture: 1,000,000 UST1 (raw 1e12 at 6 dp), $2,000,000 priced assets → CR 200%, A/L 2.00x.
  • USTC-per-UST1 = whole USTC / whole UST1.
  • USTR backing unchanged when UST1 supply changes.
  • After #10: adding vFDUSD USD increases CR; removing it (price fail) drops CR and marks incomplete.

Key ratios — edges

  • Supply 0 → ∞ / ∞ / ∞x.
  • Supply query fail → N/A, not ∞ or 0%.
  • All asset prices fail, supply > 0 → do not print a fake 0% CR as “known empty”; show incomplete.
  • Only USTC priced → CR uses USTC USD only + incomplete if other balances exist.
  • Huge supplies: no Infinity from float overflow; no negative ratios.
  • Loading skeletons then settle without flicker to ∞ then 200%.

Integration

  • Treasury 30s refetch updates circ + CR; LCD rate limits hold (3× token_info + existing balances).
  • Testnet empty addresses: no thrown spam; mainnet default still works.

Test plan (attack, hack, abuse)

Vector Risk Test / guard
Hardcoded 0 supply Always-∞ CR hides insolvency Grep: no ust1Supply = BigInt(0) leftover; live query used
Failed supply → ∞ LCD outage looks like BLUE / infinite backing Fail path is N/A; only success+zero is ∞
Stub hasUst1Issued ? 0 Any non-zero supply shows 0% CR (panic / false RED) Non-zero fixture must compute, not return 0
Wrong denominator CR uses USTR or minted-including-burned Denominator is UST1 total_supply only
Wrap double-count cLUNC + uluna both in assetsUsd Wrap tokens not in treasury asset loop / CR sum
UST1 as asset Counting the liability as collateral UST1 not in tokenlist balance fetch
Missing vFDUSD price CR understated after window deposits Incomplete flag until #10; never invent $1/vFDUSD here
Decimal attack Treat 6 dp as 18 (or reverse) → 10^12 CR error Unit tests for 6-vs-18; whole-token conversion
Number(bigint) precision Supplies > 2^53 lie Convert via decimal split (see formatAmount) before JS number
LCD tx / all_accounts scrape Browser pagination looks like a crawl No holder enumeration for issuance
Unpriced = $0 Attacker (or outage) drops ALPHA/LUNC quotes → fake low CR Incomplete state; do not present partial sum as full CR
Unpriced = skip + still “full” CR Same outage looks fully backed Label which symbols are included
Finder / address spoof Wrong explorerUrl → phishing Pin addresses; rel="noopener noreferrer" already on links
Coming Soon left on Social-engineer “not launched” while minting notLaunched false on mainnet once data wired
Tier color mismatch 99% shown emerald (>=100 old band) vs ECONOMICS RED/YELLOW If colors touched, 95/110/190; else document leftover

Verification criteria

  1. Mainnet: UST1 circ on the card equals {"token_info":{}} total_supply for terra1f0eq…fy72.
  2. Finder “View Token” opens that contract on columbus-5.
  3. cLUNC / cUSTC supplies equal their token_info.total_supply (terra1437…ssgdg, terra1nap4…r56ch).
  4. With known fixtures (or a calculator on live balances × #10 prices): on-screen CR matches assetsUsd / whole_UST1 * 100 within rounding.
  5. Airplane-mode / LCD kill after first UST1 success: stale/last-good or N/A — not a flip to ∞.
  6. Grep clean: no Currently no UST1 issued, no hasUst1Issued ? 0 : Infinity.
  7. docs/DEPLOYMENT.md Phase 4 frontend address checkbox can be ticked for UST1 + wrap tokens (vFDUSD UI is #10).
## Summary Replace the UST1 Issuance **Coming Soon** placeholder with **live mint / burn / circulating**, plus a finder link. Add **cLUNC and cUSTC circulating supply**. Fix **Key Ratios** so collateralization (and related liability ratios) use **UST1 circulating supply** — not a hardcoded `0` that forces `∞`, and not the stub that would become `0%` the moment supply is non-zero. Depends on priced treasury assets (including vFDUSD once [#10](https://gitlab.com/PlasticDigits2/ustr-cmm/-/issues/10) lands). This issue owns the **liability** side and the ratio math. --- ## Current codebase | Component | Path | Behavior today | |-----------|------|----------------| | UST1 card | `frontend/src/pages/TreasuryPage.tsx` | `notLaunched={true}` → **Coming Soon** badge; **no** `explorerUrl`; zeros for mint/burn/supply. | | Issuance UI | `frontend/src/components/treasury/IssuanceCard.tsx` | Supports minted / burned / circulating + optional finder link. Coming Soon **replaces** the link. | | Data hook | `frontend/src/hooks/useTreasury.ts` | USTR: `token_info.total_supply` as minted **and** supply; burned hardcoded `0`. **UST1: `ust1Supply = BigInt(0)` with comment “Currently no UST1 issued”.** | | Ratio stub | same file, `ratios` | `hasUst1Issued ? 0 : Infinity` for `collateralization`, `ustcPerUst1`, `assetsToLiabilities`. When supply is 0 → `∞` (OK). **When supply > 0 → `0` — it never computes a real CR.** | | Ratio UI | `frontend/src/components/treasury/RatiosCard.tsx` | Shows `%`, USTC per UST1, assets/liabilities `x`, USTR backing. `∞` → emerald. Color bands (`>=100` / `>=50`) do **not** match ECONOMICS tiers (190 / 110 / 95). | | Types | `frontend/src/types/treasury.ts` | `TokenIssuance { minted, burned, supply }`; `TreasuryRatios.collateralization` documented as percent (150 = 150% backed). | | Token registry | `tokenlist.json`, `CONTRACTS` | **No UST1, cLUNC, or cUSTC.** USTR address only. | | CW20 queries | `contractService.getTokenInfo` | `{ token_info: {} }` → `name, symbol, decimals, total_supply`. **No lifetime minted/burned counters** (standard cw20-mintable). | | Window stats | ust1-window `QueryMsg` (out of repo) | `Config` + `EffectiveSwap` only — **no** cumulative mint/burn stats. | | Wrap mapper | `contracts/contracts/wrap-mapper` | No lifetime wrap/unwrap counters; outstanding wrap = CW20 `total_supply`. | | Economics SSoT | `docs/ECONOMICS.md`, `docs/CONTRACTS.md` | CR = collateral USD / UST1 liabilities at $1 each. Normalize decimals before dividing. Tiers: RED `<95%`, YELLOW `95–110%`, GREEN `110–190%`, BLUE `>190%`. | | Docs | `docs/ARCHITECTURE.md` | UST1 still described as “Phase 2” / not launched. Mainnet **is** live (see pins). | **Mainnet pins (do not invent addresses):** | Name | Code | Address | Decimals | |------|------|---------|----------| | UST1 | `10184` | `terra1f0eqgy9w7e5e7up97vjudqwx38tesf8ylx75x2lv3nwm0clry0pqmgfy72` | 6 | | cLUNC | `10184` | `terra1437qslye72t7qmmahn4t5chz50r8a62g45phwkquwpyu2l62u6ksqssgdg` | 6 | | cUSTC | `10184` | `terra1nap4dxh9tv35v0ynd9m4k6zt6c0dq6weszc4j5m564kjls56hu7qcr56ch` | 6 | | ust1-window | `11566` | `terra1zxwpzpzpleatqn39r00grau4yt29sld8pw78s7ktvjafnj5nsaxq0h3rh2` | — | | Finder | — | `https://finder.terraclassic.community/columbus-5` | — | UST1 is minted/burned by `ust1-window` (vFDUSD deposit → mint; redeem → burn). cLUNC/cUSTC outstanding = wrapped native (treasury keeps native custody). --- ## Why this is needed 1. UST1 **is live**. The Coming Soon badge and zeroed issuance are false. Users need mint / burn / circ and a contract link — same as USTR. 2. cLUNC/cUSTC are the public wrap surface (`docs/DEPLOYMENT.md` Phase 4 frontend checkbox still open). Showing **supply** (not treasury CW20 dust) proves how much native is wrapped. 3. Key Ratios are **unsafe as implemented**: - Hardcoded `ust1Supply = 0` always prints `∞` (looks maximally healthy). - The `hasUst1Issued ? 0 : Infinity` branch would flip to **0%** if someone only un-hardcodes supply — still not a CR. 4. CR must use **circulating / outstanding UST1** (`token_info.total_supply`), i.e. unburned liabilities, not “Coming Soon zeros” and not USTR supply. --- ## Constraints / guardrails - **Denominator for CR / USTC-per-UST1 / assets-to-liabilities** = UST1 CW20 `token_info.total_supply` (outstanding = minted − burned on this token). Do not use USTR supply. Do not use window 24h volume. - **`∞` only if UST1 `token_info` succeeded and `total_supply === 0`.** Query failure → `N/A` / loading / last good — **never** `∞` (that hides undercollateralization). - When supply `> 0`, **compute** ratios. Never return the stub `0`. - **Liability unit:** 1 UST1 = **$1** target (ECONOMICS). `collateralization % = (sum of priced treasury assets in USD / UST1_outstanding_in_whole_tokens) * 100`. - **Decimal hygiene:** UST1 6 dp, USTC/LUNC 6, USTR 18, vFDUSD 6. Normalize before dividing (`docs/CONTRACTS.md`). Do not `Number(bigint)` huge values unsafely — use decimal-adjusted floats only after scaling to whole tokens, or integer math then scale. - **Do not double-count wraps:** do **not** add cLUNC/cUSTC as treasury *assets* for CR (native LUNC/USTC already counted). Supply cards are informational only. - **Do not** add UST1 to `tokenlist` as a treasury holding (it is the liability, not collateral). - **Do not** scan LCD txs / paginate `all_accounts` to reconstruct lifetime mint/burn (quota + abuse). - Lifetime mint/burn: cw20-mintable has **no** cumulative counters; window has **no** stats query. **Required:** circulating = `total_supply`. **Minted / burned:** keep the three-field card; use `minted = supply`, `burned = 0` **only if** you cannot get lifetime totals — and tooltip that these are not lifetime counters. Prefer `minted − burned = supply` if a later window stats query appears. Do not invent burns. - Finder link on UST1 **and** keep/repurpose Coming Soon: **remove** `notLaunched` once live numbers show. Link: `{scanner}/address/{TERRA_UST1}`. - cLUNC/cUSTC: show **circulating supply** (and minted/burned only if you use the same honest `supply` / `burned=0` pattern). Include finder links. Do not imply they back UST1 as extra collateral. - Reuse `contractService` LCD rate limits; batch/dedupe `token_info` queries; do not add a new poll faster than existing treasury 30s. - Color tiers: if touched, align with ECONOMICS (95 / 110 / 190), not the current 50 / 100. In scope if you edit `RatiosCard`; do not expand into a full SSoT dashboard. - Incomplete prices: CR must not treat missing USD as `$0` without a visible **incomplete** state (understates backing) **or** as `$1` (overstates). Document which assets entered the sum. --- ## Relevant files | File | Role | |------|------| | `frontend/src/pages/TreasuryPage.tsx` | Drop `notLaunched`; pass explorer URL; add cLUNC/cUSTC supply UI | | `frontend/src/components/treasury/IssuanceCard.tsx` | Reuse for UST1 + wrap supplies (or a thin supply variant) | | `frontend/src/components/treasury/RatiosCard.tsx` | Render computed CR; `N/A` vs `∞`; optional tier colors | | `frontend/src/hooks/useTreasury.ts` | Fetch UST1 / cLUNC / cUSTC `token_info`; **real** ratio math | | `frontend/src/types/treasury.ts` | Optional wrap-supply fields; ratio `NaN`/incomplete flag | | `frontend/src/utils/constants.ts` | `ust1Token`, `cLunc`, `cUstc` (and window if needed) | | `frontend/src/services/contract.ts` | Already has `getTokenInfo` | | `frontend/src/hooks/usePrices.ts` | Asset USD for CR numerator (vFDUSD via #10) | | `frontend/public/assets/tokens/{UST1,CLUNC,CUSTC}.png` | Icons | | `docs/DEPLOYMENT.md`, `README.md` | Tick Phase 4 frontend address wiring | --- ## Recommended direction 1. Add mainnet addresses to `CONTRACTS` (testnet empty/TODO). Do **not** put UST1/cLUNC/cUSTC on the treasury-balance tokenlist loop. 2. In `fetchTreasuryData`: - `ust1Info = getTokenInfo(ust1Token)` → `supply = total_supply`. - `ustrIssuance` unchanged. - `cLuncSupply` / `cUstcSupply` from their `token_info`. - `ust1Issuance`: `supply` live; minted/burned per guardrail above. 3. Ratios (only after successful UST1 supply read): - `S = whole UST1` (`supply / 10^6`). - If `S == 0`: `collateralization = ustcPerUst1 = assetsToLiabilities = Infinity`. - If `S > 0`: - `assetsUsd = Σ (whole_balance * usd_price)` for treasury assets with **valid** prices (LUNC, USTC, ALPHA, …, vFDUSD when #10 ready). Skip unpriced assets and flag incomplete. - `collateralization = (assetsUsd / S) * 100` - `ustcPerUst1 = whole_USTC / S` - `assetsToLiabilities = assetsUsd / S` (same ratio as CR, `x` not `%` — keep current labels). - `ustrBacking` unchanged (USTC / USTR). 4. UI: UST1 card live + finder. Add two supply cards (or a wrap-supply row) for cLUNC/cUSTC with finder links. Ratios consume the new numbers. 5. Cross-check #10: once vFDUSD USD exists, it **must** enter `assetsUsd`. Ship CR without it only with incomplete-data UX. --- ## Acceptance criteria - [ ] UST1 card: no Coming Soon; minted / burned / circ shown; circ matches on-chain `token_info.total_supply`. - [ ] UST1 “View Token” → finder `columbus-5` address `terra1f0eq…fy72`. - [ ] `minted - burned === supply` when both lifetime fields are known; if burned is unknown, UI does not claim historical burns. - [ ] cLUNC and cUSTC supplies match their `token_info.total_supply`; finder links correct; **not** listed as extra treasury collateral rows solely because of this issue. - [ ] UST1 supply `0` (successful query) → ratios `∞`. - [ ] UST1 supply `> 0` → CR = priced assets USD / outstanding UST1 × 100 (not `0`, not `∞`, not USTR-based). - [ ] UST1 `token_info` failure → ratios `N/A` (or last good), **not** `∞`. - [ ] Decimals: 6 for UST1/cLUNC/cUSTC; USTR backing still 18-vs-6 safe. - [ ] Unpriced assets do not silently zero or inflate CR; incomplete state visible. - [ ] Existing USTR issuance + treasury asset grid still work. --- ## Test plan (all paths) **UST1 issuance** - [ ] Live `total_supply = 0` → circ `0`; ratios `∞`; no Coming Soon. - [ ] Live `total_supply > 0` → circ formatted (6 dp); finder works. - [ ] `token_info` fail → issuance loading/error; ratios not `∞`. - [ ] `notLaunched` removed; USTR card still has its finder link. - [ ] Minted/burned: consistent with guardrail; no LCD tx-scan in network panel. **cLUNC / cUSTC** - [ ] Each supply matches chain; `0` supply still shown (these are supply infos, not dust-hidden treasury rows). - [ ] Query fail for one wrap token does not blank UST1 or the other wrap. - [ ] Not added to CR numerator. **Key ratios — happy** - [ ] Fixture: 1,000,000 UST1 (raw `1e12` at 6 dp), $2,000,000 priced assets → CR `200%`, A/L `2.00x`. - [ ] USTC-per-UST1 = whole USTC / whole UST1. - [ ] USTR backing unchanged when UST1 supply changes. - [ ] After #10: adding vFDUSD USD increases CR; removing it (price fail) drops CR and marks incomplete. **Key ratios — edges** - [ ] Supply `0` → `∞` / `∞` / `∞x`. - [ ] Supply query fail → `N/A`, not `∞` or `0%`. - [ ] All asset prices fail, supply `> 0` → do not print a fake 0% CR as “known empty”; show incomplete. - [ ] Only USTC priced → CR uses USTC USD only + incomplete if other balances exist. - [ ] Huge supplies: no `Infinity` from float overflow; no negative ratios. - [ ] Loading skeletons then settle without flicker to `∞` then `200%`. **Integration** - [ ] Treasury 30s refetch updates circ + CR; LCD rate limits hold (3× `token_info` + existing balances). - [ ] Testnet empty addresses: no thrown spam; mainnet default still works. --- ## Test plan (attack, hack, abuse) | Vector | Risk | Test / guard | |--------|------|----------------| | **Hardcoded 0 supply** | Always-`∞` CR hides insolvency | Grep: no `ust1Supply = BigInt(0)` leftover; live query used | | **Failed supply → `∞`** | LCD outage looks like BLUE / infinite backing | Fail path is `N/A`; only success+zero is `∞` | | **Stub `hasUst1Issued ? 0`** | Any non-zero supply shows 0% CR (panic / false RED) | Non-zero fixture must compute, not return `0` | | **Wrong denominator** | CR uses USTR or minted-including-burned | Denominator is UST1 `total_supply` only | | **Wrap double-count** | cLUNC + uluna both in `assetsUsd` | Wrap tokens not in treasury asset loop / CR sum | | **UST1 as asset** | Counting the liability as collateral | UST1 not in `tokenlist` balance fetch | | **Missing vFDUSD price** | CR understated after window deposits | Incomplete flag until #10; never invent `$1/vFDUSD` here | | **Decimal attack** | Treat 6 dp as 18 (or reverse) → 10^12 CR error | Unit tests for 6-vs-18; whole-token conversion | | **`Number(bigint)` precision** | Supplies > 2^53 lie | Convert via decimal split (see `formatAmount`) before JS number | | **LCD tx / `all_accounts` scrape** | Browser pagination looks like a crawl | No holder enumeration for issuance | | **Unpriced = $0** | Attacker (or outage) drops ALPHA/LUNC quotes → fake low CR | Incomplete state; do not present partial sum as full CR | | **Unpriced = skip + still “full” CR** | Same outage looks fully backed | Label which symbols are included | | **Finder / address spoof** | Wrong `explorerUrl` → phishing | Pin addresses; `rel="noopener noreferrer"` already on links | | **Coming Soon left on** | Social-engineer “not launched” while minting | `notLaunched` false on mainnet once data wired | | **Tier color mismatch** | 99% shown emerald (`>=100` old band) vs ECONOMICS RED/YELLOW | If colors touched, 95/110/190; else document leftover | --- ## Verification criteria 1. Mainnet: UST1 circ on the card equals `{"token_info":{}}` `total_supply` for `terra1f0eq…fy72`. 2. Finder “View Token” opens that contract on columbus-5. 3. cLUNC / cUSTC supplies equal their `token_info.total_supply` (`terra1437…ssgdg`, `terra1nap4…r56ch`). 4. With known fixtures (or a calculator on live balances × #10 prices): on-screen CR matches `assetsUsd / whole_UST1 * 100` within rounding. 5. Airplane-mode / LCD kill after first UST1 success: stale/last-good or `N/A` — **not** a flip to `∞`. 6. Grep clean: no `Currently no UST1 issued`, no `hasUst1Issued ? 0 : Infinity`. 7. `docs/DEPLOYMENT.md` Phase 4 frontend address checkbox can be ticked for UST1 + wrap tokens (vFDUSD UI is #10).
PlasticDigits commented 2026-08-15 09:34:30 +00:00 (Migrated from gitlab.com)

mentioned in issue #10

mentioned in issue #10
PlasticDigits commented 2026-08-15 09:49:56 +00:00 (Migrated from gitlab.com)

mentioned in commit 737f560578

mentioned in commit 737f5605783feb36f3e1acd6d8d5e5a57a689ad6
PlasticDigits commented 2026-08-15 09:49:58 +00:00 (Migrated from gitlab.com)

mentioned in merge request !32

mentioned in merge request !32
PlasticDigits commented 2026-08-15 09:50:05 +00:00 (Migrated from gitlab.com)

Implemented on !32 (depends on #10 vFDUSD USD in the CR numerator).

Shipped: live UST1 token_info.total_supply (Coming Soon removed), cLUNC/cUSTC supply cards (not CR assets), real CR math, ∞ only on successful zero supply, N/A on query failure, incomplete-price banner, ECONOMICS 95/110/190 colors, getTokenInfoStrict so swallowed 0 cannot fake ∞. Tests: frontend/src/utils/treasuryRatios.test.ts. Playbook: skills/frontend-ust1-ratios/SKILL.md.

Implemented on !32 (depends on #10 vFDUSD USD in the CR numerator). Shipped: live UST1 `token_info.total_supply` (Coming Soon removed), cLUNC/cUSTC supply cards (not CR assets), real CR math, `∞` only on successful zero supply, `N/A` on query failure, incomplete-price banner, ECONOMICS 95/110/190 colors, `getTokenInfoStrict` so swallowed `0` cannot fake `∞`. Tests: `frontend/src/utils/treasuryRatios.test.ts`. Playbook: `skills/frontend-ust1-ratios/SKILL.md`.
PlasticDigits commented 2026-08-15 10:23:19 +00:00 (Migrated from gitlab.com)

mentioned in commit 09a54333aa

mentioned in commit 09a54333aaaaf58423d04efe6a209b08e54d5cd7
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-15 10:23:19 +00:00
PlasticDigits commented 2026-08-15 12:41:07 +00:00 (Migrated from gitlab.com)

mentioned in issue #14

mentioned in issue #14
PlasticDigits commented 2026-08-17 01:06:21 +00:00 (Migrated from gitlab.com)

mentioned in issue #16

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

marked as related to #16

marked as related to #16
PlasticDigits commented 2026-08-24 00:18:42 +00:00 (Migrated from gitlab.com)

mentioned in merge request !34

mentioned in merge request !34
PlasticDigits commented 2026-08-24 00:19:07 +00:00 (Migrated from gitlab.com)

mentioned in merge request !35

mentioned in merge request !35
PlasticDigits commented 2026-08-24 06:12:59 +00:00 (Migrated from gitlab.com)

mentioned in issue #19

mentioned in issue #19
PlasticDigits commented 2026-08-24 06:13:00 +00:00 (Migrated from gitlab.com)

marked as related to #19

marked as related to #19
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/ustr-cmm#11
No description provided.