fix: /protocol fee USD omit CL8Y and other economic tokens #682
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#682
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
On
/protocol, treasury fees taken in CL8Y (live token-mix ticker may show as CL8Y-cb / CL8Y-CB) render USD blank even when the human amount is non-zero (report: > 1.298 received). Trailing Last 24h / 7d / 30d fees omit those rows because rollupSUMs only non-nullfee_usd.Bundle into one issue: extend fee USD pricing to all factory-listed economic tokens (CL8Y first; same path for later listed non-gems). Do not split “token-row em-dash” vs “headline undercount” vs “backfill NULL
fee_usd” vs “Llama inherited fees.”Related: #586 (fee panel), #556 / #570 (hub USD — no CL8Y mark), #522 / #548 (P522-Q catalog), #568 (do not rewrite stamped USD), #577 (window decay), #631 (DeFiLlama daily fees reuse
fee_usd), #580 (do not price Terra vFDUSD from CEX FDUSD), #562 / #534 (economic vs gem).Current codebase
/protocolProtocol fees (protocol-fee-stats) already exists after #586 / #613 / #614. Headlines and the token table are USD-or-em-dash. The hole is the P522-Q catalog, not missing UI.ProtocolFeeStats.tsx: 24h/7d/30d viaformatProtocolUsd(overview.total_fees_*_usd). Token table showsamount_human(so 1.298 CL8Y is visible) andformatProtocolUsd(row.amount_usd)—null/""→ em-dash (—), which operators read as blank. XSS symbols render as text (PFee-4).GET /overviewoverview_fee_usd_field: idle (event_count=0) →"0"; activity + no priced USD →null(UI—). Partial priced + unpriced → priced SUM only — unpriced CL8Y is dropped, not listed as a remainder.refresh_protocol_fees:SUM(fee_usd) FILTER (WHERE fee_usd IS NOT NULL). Token mixORDER BY amount_usd DESC NULLS LAST, top 8 +other.clamp_usddrops≤0/ overflow. GET/overviewand/protocol/feesstay O(1) / 60s cache (PFee-8).ingest_protocol_fee→fee_usd_for_raw→catalog_usd_per_human_identity. AMM / book take commission is the ask asset (ask_asset_id). Buying CL8Y with UST1 therefore stores the fee in CL8Y. Limit place uses offer-side (offer_asset_id_for_side). Insert isON CONFLICT DO NOTHING— a later catalog fix does not fill oldNULLfee_usd.uusd, LUNC/cLUNC/uluna, UST1, USTR. Unit test is explicit:quote_usd_kind("CL8Y", None) == None.HubQuoteUsdhas onlyust1/ustr.load_quote_usdignores every otherhub_pricesticker.hub_usd.rs: cUSTC ← USTC oracle; LUNC ← LUNC oracle; UST1 ← max-TVL cUSTC/UST1 pair; USTR ← max-TVL vs already-priced cUSTC or UST1. No CL8Y pin, no walk of other listed CW20s. Protocol hub card stays four columns (H11).volume_usdvia the catalogued UST1 offer/quote (volume_usd_for_swap). TVL of a one-sided catalog pair 2× the priced leg (P569-5). Operators therefore see volume/TVL move while fees in CL8Y stay unpriced.defillama.rsdaily feesSUM(fee_usd)with gem-pair exclude. Unpriced economic fees undercount Llama the same way they undercount Protocol.terra16wtml2q66g82fdkx66tap0qjkahqwp4lwq3ngtygacg5q0kzycgqvhpax3(VITE_CL8Y_TOKEN_ADDRESS/CL8Y_TOKEN_ADDRESS). Fee-discount I12 already notes wallets may label a bridged asset CL8Y-cb — Protocol must key contract/denom (A1), not the display ticker. LocalTerra TCL8Y is the 18-dec proxy (#383).pairCatalogRank.ts). Gems (EMBER… / columbus-5 gem addrs) are test. vFDUSD is economic for discovery but must not be USD-priced from CEX FDUSD (X4 / #580).make verify-issue-586·613·614·556·569·631. No test that a CL8Y (or uncatalogued economic) ask-side commission stampsfee_usd.Why the new implementation is needed
amount_human≈ 1.298). Blank USD is not “no fee” — it is unpriced catalog. Operators and CMM cannot read protocol take from/protocol.SUMskipsNULLfee_usd. CL8Y (and any later listed economic ask asset) never enters the tiles, source mix USD, or Llama daily fees, even when volume for the same swap is priced off UST1.ceramicliberty-comis BSC-only today (#629 / listings). Do not poll CG / invent a Classic platform price for ingest.Constraints / guardrails
/overviewand/protocol/feesstay O(1) rollup / 60s cache. Do notSUM protocol_fee_eventson GET. Do not add a fifth Protocol hub column or a CEXcl8ytab. Do not rewrite non-null historicalfee_usdfrom the live mark.HUB_CL8Y_ADDRESS/VITE_CL8Y_TOKEN_ADDRESS). Do not pricesymbol=CL8Y/CL8Y-cb/TCL8Yon a spoof native or random CW20. Homoglyph /javascript:/../tickers stay rejected.HUB_USD_TVL_FLOOR, stale/dust/same-asset skip). Never$1CL8Y. Neverceramicliberty-com. Never vFDUSD/FDUSD / Venus into fee USD.—, not$0). All activity unpriced → stillnull/—. Idle →$0. NeverInfinity.protocol_fee_events.fee_usd IS NULLusing current economic marks. NeverUPDATEa non-null stamp. Thenrefresh_protocol_fees. Document as as-of backfill, not historical mark-to-market.hub_pricesextra rows or a sibling table.GET /api/v1/hub-pricesallowlist stayscustc|lunc|ust1|ustrunless product later asks for a CL8Y column (out of scope).load_quote_usd/fee_usd_for_rawmust actually read the new marks.indexer/into root Docker for cargo (workspace rule). Hostcargo test/make verify-issue-*.Relevant files
indexer/src/indexer/pair_price_usd.rsquote_usd_kind("CL8Y")isNone; extend lookup after catalogindexer/src/indexer/protocol_fees.rsfee_usd_for_raw/overview_fee_usd_fieldindexer/src/indexer/parser.rsingest_protocol_fee(ask-asset AMM; offer-side place)indexer/src/indexer/hub_usd.rsindexer/src/db/queries/hub_prices.rsload_quote_usdtoday only copies ust1/ustrindexer/src/db/queries/protocol_fees.rsSUM(fee_usd); NULL-only backfill hookindexer/src/config.rsHUB_CL8Y_ADDRESS(columbus-5 default + LocalTerra override)indexer/src/db/queries/defillama.rsindexer/tests/indexer_protocol_fees.rsfrontend-dapp/src/components/protocol/ProtocolFeeStats.tsxfrontend-dapp/src/pages/ProtocolPage.test.tsxfrontend-dapp/src/utils/pairCatalogRank.tsskills/AGENTS_FRONTEND_PROTOCOL_STATS.mdskills/AGENTS_INDEXER_HUB_USD.mddocs/indexer-invariants.mddocs/runbooks/overview-global-stats-brin.mdscripts/qa/verify-issue-586.shRecommended direction
pair_reservesfor pairs whose one leg is already priced and the other is a factory-listed economic CW20 (CL8Y pin required; then other non-gem listed contracts). Winner = max humanized USD-TVL, then lex pair address. Persistusd_per_human+source_pair+asset_id.fee_usd_for_rawsees (todayHubQuoteUsd+ oracles). Lookup order: P522-Q identity → economic mark by contract/denom →None. Humanize × mark; overflow /≤0/ missing pair →None.fee_usd IS NULLonly; refreshglobal_stats_24h+ source/token tables. Coolify: set LocalTerra / prod CL8Y pin; no Vite-only pin.GET /hub-prices/cl8yunless a later issue asks. Frontend needs no new tiles if JSONamount_usd/total_fees_*_usdbecome decimal strings.$1/ stamp at ingest / NULL-only backfill.”Acceptance criteria
fee_usdwhen a qualifying CL8Y↔priced-hub pair exists above the TVL floor and hub/oracle for the other leg are up.$(not—) for CL8Y / CL8Y-cb display symbols. XSS /javascript:symbols stay text.total_fees_{24h,7d,30d}_usdincludes those CL8Y (and other priced economic) amounts. A window that is only unpriced gems staysnull. Idle stays"0".if symbol == "CL8Y".symbol=CL8Ynative / wrong contract stays unpriced.fee_usdis unchanged. Prior NULL rows are filled once marks exist (NULL-only)./overviewand/protocol/feesstill do not scanprotocol_fee_events.window=allowlist unchanged. Hub JSON allowlist unchanged. Protocol hub card still four cells.make verify-issue-586/613/614/556/569/631stay green. Newmake verify-issue-<this>covers catalog + ingest + rollup + UI.Test plan (all paths)
Indexer unit / lib
quote_usd_kind/ catalog identity: CL8Y symbol alone stillNone; pinned contract resolves via the new mark helper.fee_usd_for_raw: CL8Y raw × mark → USD; missing mark / stale pair / below TVL floor / overflow →None; UST1/USTR/cUSTC/LUNC unchanged.symbol=CL8Y/CL8Y-cbwith no pin contract →None.Nonefor fee USD.None.Indexer integration (Postgres;
make setup-indexer-postgres)protocol_fee_events.fee_usdset; rollup 24h/7d/30d includes it;GET /protocol/fees?window=24htoken row hasamount_human+amount_usd.fee_usdNULL; headlinenullif nothing else priced; token row human + USDnull.ON CONFLICTreplay does not double-count.GET /protocol/fees?window=javascript:/ust1-window/ empty → 400. Cache key still allowlisted window only.Frontend
ProtocolPage.test.tsx: token rowsymbol: 'CL8Y-cb',amount_human: '1.298',amount_usd: '12.34'→ visible$(not only human).amount_usd: nullstill em-dash.img/innerHTML.card-glassstill forbidden.LocalTerra (optional, not a skip if Postgres tests pass)
make setup-cloud-localterra, seed a TCL8Y/UST1 (or CL8Y pin) pair above dust, swap so commission is TCL8Y, wait aggregator:/protocoltoken USD and 24h tile include it.Test plan (attack, hack, and abuse)
symbol=CL8Y/CL8Y-cb/TCL8Ymust not mint fee USD. Contract pin + factory provenance (P1) win.None, not$1.hub_prices.ticker(cl8y,../ustr,javascript:) must not appear onGET /hub-prices/{ticker}(still 400) and must not expand CEX tabs.fee_usdwhen the live CL8Y mark jumps (wash the source pool). NULL-only backfill only.book_commission_amount.SUMof 60dprotocol_fee_events. Economic walk is aggregator / hub-refresh only, bounded by pair count + floor. Token mix still top 8 +other./protocol/feesmust not bypass the 60s allowlisted-window cache.eval/innerHTML/javascript:hrefs.ceramicliberty-comon the fee path (#579 / BSC-only).exchangeRateCurrentasusd(vFDUSD).token_info.symbol=UST1is already a hide-by-address rule on the dApp; indexer USD must use gem addr set, not symbol.Verification criteria
Pass when: (1) a CL8Y ask-side commission with a qualifying hub pair stamps
fee_usdand appears in 24h/7d/30d + token$; (2) gems / vFDUSD / spoof symbols stay unpriced; (3) GET paths stay rollup-only; (4) hub card still four cells; (5) existing #586 semantics (idle$0, all-unpriced—, no Inf) hold.Notes
mentioned in issue #686
mentioned in issue #683
Duplicate of #683. The fix landed in !1186 (
82ae5b9b) onmain36d64528.make verify-issue-683PASS. Coolify migrate +HUB_CL8Y_ADDRESSleftover is on #683 / #686. Closing as duplicate.