Poinbase 只收 PSC、CRC、SPARK,新增 SPARK/CRC;DEX 稳定币对改为 StableSwap

- 钱包拦下往 Poinbase 充值地址转 CRT、CRA;资金页按上架币种列出
- 现货交易对跟着行情图选中的币(PSC/CRC、SPARK/CRC)
- CRT/CRC、CRA/CRC 用 StableSwap:手续费 0.04%、A=200;脱锚 A=20,崩盘 A=1 且深度四分之一
- 旧存档读档时补 SPARK/CRC、升级稳定币池

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Opus 5.5 committed 2026-11-07 23:03:59 +08:00
1 parent 6d8b05215c
commit fe82395d32
19 files changed
+192 -26

No files matched your search

+36 -1
View File
@@ -342,7 +342,7 @@ internal static class Program
var twoHop = m.Quote(Assets.CRA, Assets.PSC, 100);
Check(oneHop != null && oneHop.Hops == 1 && twoHop != null && twoHop.Hops == 2, "CRC 在一端走一个池,否则两个池");
Check(m.Quote(Assets.PSC, Assets.PSC, 1) == null && m.Quote(Assets.CRC, Assets.CRC, 1) == null && m.Quote(Assets.CRC, Assets.Ponero, 1) == null, "同币、没有池没有路由");
Check(twoHop.Impact > oneHop.Impact && twoHop.Impact > Tuning.DexFee * 1.9, $"两跳损失更大:{oneHop.Impact:P2} 对 {twoHop.Impact:P2}");
Check(twoHop.Impact > oneHop.Impact && twoHop.Impact > Tuning.DexFee + Tuning.StableFee - 1e-9, $"两跳损失更大(稳定币池一跳 + PSC 池一跳):{oneHop.Impact:P2} 对 {twoHop.Impact:P2}");
double expect = m.DexPool(Assets.PSC).BaseOut(m.DexPool(Assets.CRA).QuoteOut(100));
Check(Near(twoHop.Out, expect, 1e-9), "两跳的数量 = 先卖成 CRC 再买");
double got = m.Swap(Assets.CRA, Assets.PSC, 100);
@@ -1319,6 +1319,41 @@ internal static class Program
Check(double.IsPositiveInfinity(dex.QuoteIn(dex.BaseReserve)) && dex.QuoteIn(0) == 0, "DEX 恒定乘积池:超出储备为无穷,0 个为 0");
});
Test("稳定币池(StableSwap):挂钩附近几乎没有滑点,脱锚变差,崩盘被抽干", () =>
{
var m = Market.CreateDefault(38);
var crt = m.DexPool(Assets.CRT);
Check(crt.Stable && m.DexPool(Assets.CRA).Stable && !m.DexPool(Assets.PSC).Stable, "CRT、CRA 对 CRC 是稳定币池,PSC 不是");
Check(Near(crt.Price, 1, 1e-9), "平衡时价格等于挂钩价");
double small = m.Quote(Assets.CRT, Assets.CRC, 998).Impact, big = m.Quote(Assets.CRT, Assets.CRC, 50000).Impact;
Check(small < Tuning.StableFee + 0.0002 && big < 0.002, $"998 CRT 损耗 {small * 100:0.000}%,5 万 {big * 100:0.000}%");
double got = crt.SellBase(998), back = crt.BuyBase(got);
Check(back < 998 && back > 998 * (1 - 2 * Tuning.StableFee) - 0.01 && Near(crt.Price, 1, 1e-6), $"来回成交只损失两次手续费:{back:0.000}");
m.Night(new MarketEvent[0], new Rng(1), 38, a => a == Assets.CRT ? 0.92 : a == Assets.CRA ? 0.30 : a == Assets.SPARK ? 10 : 1);
Check(m.DexPool(Assets.CRT).Amp == Tuning.StableAmpDepeg && m.DexPool(Assets.CRA).Amp == Tuning.StableAmpBroken, "偏离 8% 是脱锚,偏离 70% 是崩盘");
double dep = m.Quote(Assets.CRT, Assets.CRC, 50000).Impact, brk = m.Quote(Assets.CRA, Assets.CRC, 50000).Impact;
Check(dep > big && brk > dep * 5, $"5 万的损耗:脱锚 {dep * 100:0.00}%,崩盘 {brk * 100:0.00}%");
// 旧存档的恒定乘积池按当前价换成稳定币池
var old = Market.CreateDefault(38);
int i = old.Pools.FindIndex(x => x.Venue == Venue.Dex && x.Base == Assets.CRT);
old.Pools[i] = Pool.Create(Venue.Dex, Assets.CRT, Assets.CRC, 0.95, 1000, Tuning.DexFee);
old.UpgradeStablePools(38);
Check(old.DexPool(Assets.CRT).Stable && Near(old.DexPool(Assets.CRT).Price, 0.95, 1e-9), "旧存档的池子升级后保持当前价");
});
Test("Poinbase 上架的币:PSC、CRC、SPARK;SPARK/CRC 订单簿", () =>
{
Check(Exchange.Listed.SequenceEqual(new[] { Assets.PSC, Assets.CRC, Assets.SPARK }), "只收 PSC、CRC、SPARK");
var m = Market.CreateDefault(38);
var sp = m.Find(Venue.Exchange, Assets.SPARK, Assets.CRC);
Check(sp != null && sp.Book && Near(sp.Price, Tuning.SparkStart, 1e-9), "SPARK/CRC 是订单簿,起始价同 SPARK");
m.Pools.Remove(sp); m.AddPoinSpark(12, 38); m.AddPoinSpark(13, 38);
Check(m.Pools.Count(x => x.Venue == Venue.Exchange && x.Base == Assets.SPARK) == 1 && Near(m.Find(Venue.Exchange, Assets.SPARK, Assets.CRC).Price, 12, 1e-9), "旧存档补上一次,按当前价");
m.Night(new MarketEvent[0], new Rng(1), 38, a => a == Assets.SPARK ? 20 : 1);
double ps = m.Find(Venue.Exchange, Assets.SPARK, Assets.CRC).Price;
Check(ps > 12 && ps < 20, $"夜里向 SPARK 参考价靠拢:{ps:0.00}");
});
Test("收黑币:事件对应币种、报价、收下后的污点", () =>
{
var rng = new Rng(3);