Stage 6.1: CRA staking pool, SPARK balance token with mint/burn
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58dd93eca6
commit
98e80412e6
12 files changed
+371
-9
No files matched your search
@@ -808,6 +808,47 @@ internal static class Program
|
||||
Check(!ChainAddress.Valid("0x12345") && !ChainAddress.Valid("0xzzzzzzzz") && !ChainAddress.WellFormed("12345678ab"), "格式不对的地址不合法");
|
||||
});
|
||||
|
||||
Test("CRA 质押池:计息、解锁期、污点随币、螺旋", () =>
|
||||
{
|
||||
Func<string, double> price = a => a == Assets.PSC ? 100 : 1;
|
||||
var w = new Wallet { Address = "0xa" }; w.Add(Assets.CRA, 1000); w.Add(Assets.PSC, 10); w.Taint = 400; w.Basis = 600;
|
||||
var st = new Staking();
|
||||
Check(!st.Stake(w, 2000, price), "余额不足不能质押");
|
||||
Check(st.Stake(w, 500, price) && Math.Abs(w.Get(Assets.CRA) - 500) < 1e-9, "质押 500,钱包剩 500");
|
||||
double lotTaint = st.Of("0xa").Taint;
|
||||
Check(Math.Abs(lotTaint - 400 * 500.0 / 2000) < 1e-6 && Math.Abs(w.Taint - (400 - lotTaint)) < 1e-6, $"污点按价值比例进仓位:{lotTaint}");
|
||||
var e1 = st.Night(1, Tuning.CraRate, _ => w);
|
||||
Check(Math.Abs(st.Of("0xa").Amount - 500 * (1 + Tuning.CraRate)) < 1e-9 && e1.Count == 1, "每晚计息并入本金");
|
||||
Check(!st.RequestUnstake("0xa", 9999, 1) && st.RequestUnstake("0xa", 200, 1), "申请取出 200");
|
||||
double a0 = st.Of("0xa").Amount;
|
||||
st.Night(2, Tuning.CraRate, _ => w);
|
||||
Check(Math.Abs(st.Of("0xa").Amount - a0 * (1 + Tuning.CraRate)) < 1e-9, "排队的部分不计息");
|
||||
Check(w.Get(Assets.CRA) < 501, "解锁期没到不能取");
|
||||
for (int d = 3; d <= 1 + Tuning.CraUnlockDays; d++) st.Night(d, Tuning.CraRate, _ => w);
|
||||
Check(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}");
|
||||
Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来");
|
||||
// 螺旋:质押的 CRA 取回后只值当时的价格
|
||||
var s = new Stablecoins(); s.CraSpiralDay = 5;
|
||||
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
|
||||
Check(s.Cra < 0.05 && s.Spark < Tuning.SparkStart * 0.1, $"螺旋后 CRA {s.Cra},SPARK {s.Spark:0.00}");
|
||||
});
|
||||
|
||||
Test("SPARK:随机游走有界,铸销来回只损手续费,事件冲击", () =>
|
||||
{
|
||||
double lo = 99, hi = 0;
|
||||
for (ulong seed = 1; seed <= 20; seed++)
|
||||
{
|
||||
var s = new Stablecoins(); var rng = new Rng(seed);
|
||||
for (int d = 1; d <= 150 && s.CraWarnDay < 0; d++) { s.Night(d, rng, 0); lo = Math.Min(lo, s.Spark); hi = Math.Max(hi, s.Spark); } // 螺旋前
|
||||
}
|
||||
Check(lo >= Tuning.SparkStart * Tuning.SparkMinMult - 1e-9 && hi <= Tuning.SparkStart * Tuning.SparkMaxMult + 1e-9 && hi / lo > 1.5, $"螺旋前的范围 {lo:0.0}–{hi:0.0}");
|
||||
var s2 = new Stablecoins(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRA, 100);
|
||||
double sp = s2.Mint(w, 100), back = s2.Burn(w, sp);
|
||||
Check(Math.Abs(back - 100 * Math.Pow(1 - Tuning.SparkFee, 2)) < 1e-6 && s2.Mint(w, 1e6) < 0, $"来回 100 → {back:0.00},余额不足返回 -1");
|
||||
double before = s2.Spark; s2.OnEventStart(MarketEvent.RevRaidUpper, 1, new Rng(1));
|
||||
Check(Math.Abs(s2.Spark - before * Tuning.SparkRaidShock) < 1e-9, "袭击上层 +15%");
|
||||
});
|
||||
|
||||
Test("相似地址、手续费、确认数", () =>
|
||||
{
|
||||
var rng = new Rng(21);
|
||||
|
||||
Reference in new issue
Block a user