feat: DEFI-2845: add FDUSD as an independent third USD stablecoin anchor#318
Draft
mbjorkqvist wants to merge 4 commits into
Draft
feat: DEFI-2845: add FDUSD as an independent third USD stablecoin anchor#318mbjorkqvist wants to merge 4 commits into
mbjorkqvist wants to merge 4 commits into
Conversation
The XRC anchors USDT->USD using stablecoin proxies. Until now only two symbols (USDS, USDC) were used, which has two weaknesses: with exactly two symbols the median-of-medians selector has no true middle, so a single off/stale symbol can be selected and bias every crypto/USD rate; and USDS is effectively a single point of failure (if it is unavailable across all exchanges the whole request errors). USDS is also partly USDC-collateralized, so it does not provide real independence from a USDC de-peg. Add FDUSD (First Digital USD) as a third base. With three symbols the selector returns a true middle and rejects a single outlier, and losing any one symbol still leaves two. FDUSD is independently reserved (not USDC-collateralized), and is queried only on MEXC and Gate.io - the two configured exchanges with a liquid FDUSD-USDT market. MIN_NUM_STABLECOIN_RATES is unchanged (2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adding FDUSD to STABLECOIN_BASES means the canister now also fetches an FDUSD/USDT rate, so the api unit-test mocks and cache fixtures must supply it: add an FDUSD entry (rate = RATE_UNIT, matching USDS/USDC) to each get_stablecoin_rates mock map, and insert FDUSD into the cache in the 'asset and stablecoins in cache' scenario so it stays a cache hit. Because FDUSD = 1.0 the selected stablecoin multiplier is unchanged, so no rate assertions change. All xrc unit tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands XRC’s USD-stablecoin anchoring set by adding FDUSD as a third independent USD-pegged proxy, improving robustness of the stablecoin median selection and reducing single-point-of-failure risk when deriving crypto/USD (and downstream crypto/fiat) rates.
Changes:
- Introduces the
FDUSDsymbol constant and includes it in the stablecoin base set used for USD anchoring. - Queries
FDUSD/USDTonly on Gate.io and MEXC via exchange-specificsupported_stablecoin_pairsoverrides. - Updates unit/integration tests and metrics e2e assertions to reflect the new three-stablecoin behavior and updated expected outputs.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/xrc/src/lib.rs |
Adds the FDUSD stablecoin symbol constant. |
src/xrc/src/exchanges.rs |
Extends Gate.io/MEXC stablecoin pair support to include FDUSD/USDT and updates related tests. |
src/xrc/src/api.rs |
Adds FDUSD to STABLECOIN_BASES, enabling it as an anchor in stablecoin selection. |
src/xrc/src/api/test.rs |
Updates API unit tests/mocks to provide FDUSD stablecoin responses and cached entries where required. |
src/xrc-tests/src/tests/misbehavior.rs |
Updates expected e2e outputs impacted by the third stablecoin anchor. |
src/xrc-tests/src/tests/metrics_endpoint.rs |
Asserts metrics exposure for the FDUSD per-symbol stablecoin counter. |
src/xrc-tests/src/tests/get_icp_xdr_rate.rs |
Updates expected e2e values reflecting the revised anchoring set. |
src/xrc-tests/src/tests/basic_exchange_rates.rs |
Updates expected e2e values reflecting the revised anchoring set. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…et refs Order the stablecoin symbol arrays as USDC, USDS, FDUSD everywhere (STABLECOIN_BASES, the per-exchange supported_stablecoin_pairs, and the test walk-throughs). For the two-symbol exchanges this makes the deep, robust USDC the tie-winner of median_in_set, so a USDS depeg is avoided on the common path; with three symbols a true middle exists and the order is otherwise cosmetic but kept consistent. Also drop the "(see DEFI-2845)" references from the FDUSD code comments now that the rationale lives in the comments themselves. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
get_stablecoin_rate built the cached QueriedExchangeRate with num_queried_sources = exchanges.len(), but a symbol is only queried on the exchanges that list a supported pair for it. With FDUSD added to a subset of exchanges this overstated *_num_queried_sources and could mislead monitoring. Use the number of futures actually issued instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mbjorkqvist
added a commit
that referenced
this pull request
Jun 4, 2026
…S]) (#320) ## Purpose A zero-cost interim mitigation for the two-symbol stablecoin selection (DEFI-2845). With exactly two stablecoin symbols, `median_in_set` has no true middle: the two per-symbol medians are equidistant from their midpoint, so the (almost-always) tie is broken toward the **first** entry. Listing `USDS` first therefore made the thin, depeg-prone USDS the **default USD anchor** — and a USDS depeg would be silently baked into every crypto/USD rate (see the worked 15% scenario in DEFI-2845). Reordering to `[USDC, USDS]` makes the robust, deep USDC the default tie-winner, so a USDS depeg is avoided on the common path. ## Caveats / scope - This only **shifts** which coin's depeg propagates (USDC-first means a USDC depeg is always selected); it's an improvement only because USDC is far more reliable and liquid than USDS. It is **not** a fix. - It is **superseded by the FDUSD PR (#318)**: with an odd set (3 symbols) `median_in_set` returns the true middle by value and order no longer matters, so this change becomes inert. ## Merge order Merge this **before** #318 if there's any gap before FDUSD ships — that's the only window in which it adds value. The two touch the same line (`STABLECOIN_BASES`), so #318 should rebase on top to `[USDC, USDS, FDUSD]`. If #318 is going out imminently, this PR can simply be closed as superseded. No behaviour change in the e2e scenarios (their median sums are odd, so the lower value already wins regardless of order); all unit and e2e tests pass unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
The XRC converts crypto/USDT rates to crypto/USD using USD-pegged stablecoins as proxies. Until now only two stablecoin symbols were used — USDS and USDC — which has two structural weaknesses:
MIN_NUM_STABLECOIN_RATES = 2). USDS is also partly USDC-collateralized, so it offers little independence from a USDC de-peg.This adds FDUSD (First Digital USD) as a third base:
median_in_setreturns a genuine middle and an outlier (stale-high or stale-low) can never be selected.FDUSD-USDTmarket (a survey of all nine XRC exchanges found no other liquid venue).MIN_NUM_STABLECOIN_RATESis unchanged at 2.Per the analysis in DEFI-2845. The e2e rate/standard-deviation expectations were recomputed against the three-symbol set; the metrics e2e test now also asserts the FDUSD per-symbol counter.
🤖 Generated with Claude Code