bug: indexer oracle reports CEX FDUSD as vFDUSD/USD in logs and API #580
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#580
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
Indexer logs and
GET /api/v1/oracle/price/vfdusdpresent CEX FDUSD/USD (~$0.998, typically within 1% of $1) as vFDUSD/USD. On-chain vFDUSD is a distinct asset (Venus FDUSD bridged CW20), not First Digital USD. This issue is the indexer identity / operator-API slice. Protocol tab copy + Venus redeem rate is already specified in #571 / #572 — do not re-implement that product surface here.Observed indexer lines (columbus-5). Same ticks also show CoinGecko HTTP 403 “add a descriptive User-Agent” for
lunc/vfdusd— companion #579.Related: #515 (ticker-scoped CEX oracle), #550 (added
vfdusdtab and P550-9), #522 / #556 (P522-Q / hub USD — must not start pricing vFDUSD from this CEX print).Current codebase
#550/ P550-9 intentionally wired the third external ticker as “wrapped FDUSD CEX reference”: poll MEXCFDUSDUSDT+ CoinGeckofirst-digital-usd, skip KuCoin, expose pathvfdusd, and label the print vFDUSD/USD. Tests and docs lock that mapping in as correct. Tokenlist identity disagrees.indexer/src/indexer/oracle.rsOracleTicker::Vfdusd:mexc_symbol() = "FDUSDUSDT",coingecko_id() = "first-digital-usd",kucoin_symbol() = None.display_name()returnsvFDUSD/USD.poll_tickerlogsOracle: {} avg ${:.8} from {}/{} sourceswith that string. Operators therefore see FDUSD ~$0.998 as vFDUSD.indexer/src/api/oracle.rsORACLE_CATALOG_METADATA:vfdusd = wrapped FDUSD CEX/USD reference (polls FDUSD, not a $1 peg).GET /api/v1/oracle/price/vfdusdJSONtickeris"vfdusd";price_usdis the CEX FDUSD average. Pathfdusdis 400 (no alias).oracle_prices.ticker = 'vfdusd'stores CEX FDUSD samples +average.tokenlist/tokenlist.json: symbolvFDUSD, name Venus FDUSD (bridged), 6 decimals,terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3. Not CEX FDUSD.ProtocolOracleCard.tsxheading`${label} / USD`→ vFDUSD / USD. Product fix (FDUSD reference + Venus 1 vFDUSD rate) is #571 / #572, not this issue.pair_price_usd.rsquote_usd_kindhas UST1 / USTC / LUNC / USTR only. vFDUSD is unknown →price_usd/volume_usdNULL for vFDUSD-quoted swaps. X4 / P550-10 forbid converting DEX volume with vFDUSD/FDUSD. Hub tickers arecustc|ust1|ustronly.ust1Window.tsuses on-chain windoweffective_swap— not this CEX feed.vfdusd_polls_fdusd_not_ustc_or_lunc_and_not_hardcoded_pegasserts MEXC/CG FDUSD ids onOracleTicker::Vfdusd.fetch_coingecko_parses_vfdusd_idparsesfirst-digital-usd.api_oracle.rs+ Protocol RTL/e2e assert tickervfdusdand headingvFDUSD / USD.make verify-issue-515/verify-issue-550document P550-9.docs/runbooks/indexer-external-oracle.md,docs/indexer-invariants.mdX2/X3,skills/AGENTS_INDEXER_EXTERNAL_ORACLE.md,docs/frontend.mdP550-9.Downstream today: Protocol retail copy (misleading), integrator JSON (
ticker: "vfdusd"+ ~$1), operator logs. Charts/tape USD for vFDUSD quotes is missing, not silently$1— unless a later change wires this ticker into P522-Q.Why this is needed
exchangeRateStored, not 1:1, and is not “usually within 1% of $1”. Logging$0.998as vFDUSD/USD is the same class of mix-up #515 fixed for USTC vs LUNC.display_name()is the only signal inindexer::oracleinfo lines. A 1-source MEXC FDUSD print looks like a healthy vFDUSD oracle.tickerfield is an identity. Integrators that treat/price/vfdusdas USD of 1 human CW20 vFDUSD will be off by the Venus exchange-rate factor (and any Terra vs BSC decimal mismatch). Catalog metadata currently teaches that lie.OracleTicker::Vfdusd, Charts Price (USD), overviewvolume_usd, trader volume, and portfolio USD would systematically mis-mark vFDUSD legs. This issue must close that footgun in code comments, skills, and tests.Constraints / guardrails
quote_asset/display_name), tests/docs that claim CEX FDUSD is vFDUSD/USD. Out of scope: Venus BSC poller, Protocol 1 vFDUSD Price section, CSP — those stay on #571 / #572.vfdusdunless a breaking-change ADR says otherwise.#571keeps/api/v1/oracle/price/vfdusdfor the CEX FDUSD snapshot (no silent/price/fdusdalias — still 400). Identity fix is labels and metadata, not a surprise ticker rename that breaksgetOraclePrice('vfdusd')./priceand/historyremain catalogs. Unknown ticker → 400. Distinct CEX ids (USTC ≠ LUNC ≠ FDUSD). X4: do not convertvolume_usdwith FDUSD or vFDUSD. Overviewustc_price_usdstays USTC. Advisory only (X5). Non-finite f64 still safe-default (X6).oracle.rateinto this feed.usd_per_humanfor symbolVFDUSD.OracleTicker::parsestays ASCII allowlist. Homoglyphs,../,javascript:,fdusd→None/ 400. Parameterized SQL. No interpolating raw path segments into CEX URLs beyond the enum’s fixed symbols.vfdusd. Coordinate wording with #571 so verify-issue-550 heading asserts do not fight this change./ust1math, swap settlement, or factory/router audit rows.Relevant files
indexer/src/indexer/oracle.rsdisplay_name(), comments, tests that assert FDUSD ids and the vFDUSD/USD log labelindexer/src/api/oracle.rsORACLE_CATALOG_METADATA; optionalquote_asset/display_nameon snapshotindexer/src/db/queries/oracle.rsvfdusdunless ADRindexer/tests/api_oracle.rs/price/fdusd400 + snapshot tickerdocs/runbooks/indexer-external-oracle.mddocs/indexer-invariants.mdskills/AGENTS_INDEXER_EXTERNAL_ORACLE.mdskills/AGENTS_INDEXER_PAIR_PRICE_USD.mddocs/frontend.md/skills/AGENTS_FRONTEND_PROTOCOL_STATS.mdscripts/qa/verify-issue-515.shscripts/qa/verify-issue-<iid>.shRecommended direction
OracleTicker::Vfdusd.display_name()toFDUSD/USD(orFDUSD/USD (CEX)). Info lines must not sayvFDUSD/USD avg $0.998. Keepas_str() = "vfdusd"for DB/path.vfdusdreturns CEX FDUSD/USD (MEXCFDUSDUSDT, CoinGeckofirst-digital-usd); it is not USD of Terra CW20 vFDUSD. Point Protocol Venus UI to #571./price/vfdusd: e.g.quote_asset: "FDUSD",display_name: "FDUSD/USD"so clients do not infer identity from the path alone. USTC/LUNC get matching fields. Do not add pathfdusd.display_namecontainsFDUSDand does not equalvFDUSD/USD. Catalog metadata must not claim the print is vFDUSD/USD.OracleTicker::Vfdusdasusd_per_humanforVFDUSDinquote_usd_kind. Keep X4.make verify-issue-<iid>greps display_name / catalog / skill lines. Do not require live CEX.Acceptance criteria
vFDUSD/USD avg $…. Path/DB ticker remainsvfdusdunless an approved breaking change.GET /api/v1/oracle/pricemetadata states thevfdusdsnapshot is CEX FDUSD, not Terra vFDUSD USD./price/fdusdremains 400.$1hardcode; they must not requiredisplay_name() == "vFDUSD/USD".volume_usd/ hub USD unchanged: vFDUSD quotes stay unpriced (NULL), not CEX FDUSD × size.make verify-issue-<iid>plusmake verify-issue-515(and #550 if still applicable) pass without live CEX.Test plan (all paths)
OracleTicker::Vfdusd.display_name()vFDUSD/USDFDUSDUSDT, CGfirst-digital-usd, KuCoin skippedparse("vfdusd")/parse("fdusd")/..//javascript:Some(Vfdusd)/None/None/NoneGET /api/v1/oracle/pricevfdusdGET /api/v1/oracle/price/vfdusdticker=vfdusd;price_usdis CEX cache (or null); optionalquote_asset= FDUSDGET /price/fdusd,/price/btcGET /history/vfdusdUSTC/USD/LUNC/USD; no FDUSD copy$1hardcode0.87quote_usd_kind("VFDUSD", None)/ volume helperNone; no FDUSD oracle multiplyHubTicker::parse("vfdusd")/"fdusd"Nonemake verify-issue-515(and 550 after copy sync)make setup-indexer-postgres; no live MEXC requiredapi_oracletests passTest plan (attack, hack, abuse)
/price/../../vfdusd,/price/%00vfdusd/price/<script>, queryjavascript:/price/fdusdhoping for vFDUSDvfdusd'; DROPvolume_usd_for_swapon a VFDUSD quote$1vFDUSDquote_asset); must not only sayticker: vfdusd/ust1rate vs this snapshotvfdusdlookalikesparse→ NoneVerification criteria
Ship is done when AC1–AC6 pass, T1–T15 and A1–A10 are recorded (or waived with reason), and no code path multiplies CEX FDUSD into vFDUSD
volume_usd/price_usd.marked as related to #571
marked as related to #572
marked as related to #579
marked as related to #515
marked as related to #550
marked as related to #522
marked as related to #556
mentioned in commit
54fb99372cmentioned in merge request !1103
mentioned in merge request !1104
mentioned in commit
b179d1c99bMerged via !1104 (before !1105).
make verify-issue-580passed. Indexer pathvfdusdlogs/JSON FDUSD/USD /quote_asset=FDUSD;/price/fdusdstays 400. Protocol UI relabel (FDUSD reference + Venus) is #571 (!1105), not this issue.mentioned in issue #583
marked as related to #583
mentioned in issue #589
mentioned in issue #614
mentioned in issue #653
mentioned in issue #682
mentioned in issue #683
mentioned in issue #691