Compare commits
7
Commits
0f26d88c03
...
685762d110
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
685762d110 | ||
|
|
67df561a5f | ||
|
|
34b70023c9 | ||
|
|
f0a6051591 | ||
|
|
8afdfa606c | ||
|
|
e88fab3f1b | ||
|
|
a37dd4ca7c |
No files matched your search
+37
-8
@@ -1,12 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 未发布
|
## 2.0.0
|
||||||
|
|
||||||
### 第十一阶段 stage 1:污点代替没收、挖矿去上限
|
污点规则重做(按币种记脏币,只有干净的币能进 Poinbase 和银行,出金审查删除)、OTC Desk 场外换币台、自营混币器、Tumbler 支线扩展、挖矿去模块上限。存档兼容,读旧存档时自动升级。
|
||||||
|
|
||||||
- 预测市场的内幕单不再按概率查处、没收:结算或卖出时照常兑付,内幕份额对应的兑付记为收款钱包的污点,夜间日志写明“警方怀疑这是内幕交易”。原来“内幕持仓达到上限的 40%、70% 概率被查”的规则(`PredictInsiderShare`、`PredictInsiderCatch`)删除,每一份内幕份额都记污点,先买后卖也一样。
|
### 内幕与操纵、挖矿
|
||||||
- 操纵检出:被查的概率不变,被查后照常兑付,预测盘的这笔兑付记钱包污点,永续的这笔盈利记 Poinbase 账户污点;永续账户不再冻结 3 天(`ManipFreezeDays` 删除)。报纸的调查新闻改为“涉事账户已被标记”。
|
|
||||||
- 污点上限:加污点时不超过钱包当时的价值,超出的部分按 50% 记诈骗罪证,每次最多 400(沿用 `PredictFraudShare`、`PredictFraudCap`),日志显示超出的污点额。
|
- 预测市场的内幕单不再按概率查处、没收:结算或卖出时照常兑付,内幕份额对应的兑付算脏币,夜间日志写明“警方怀疑这是内幕交易”。原来“内幕持仓达到上限的 40%、70% 概率被查”的规则(`PredictInsiderShare`、`PredictInsiderCatch`)删除,每一份内幕份额都算脏币,先买后卖也一样。
|
||||||
|
- 操纵检出:被查的概率不变,被查后照常兑付,预测盘的这笔兑付算脏币,永续的这笔盈利记诈骗罪证(见下面的污点一节);永续账户不再冻结 3 天(`ManipFreezeDays` 删除)。报纸的调查新闻改为“涉事账户已被标记”。
|
||||||
- 矿架、矿机的模块效果不设上限(原来算力最多 +20%、省电最多 25%、损耗最多 −30%,以及耗电最多 ×2 的隐含限制):9 个无限制神经核心算力 ×5.5、耗电 ×3.25、暴毙率 ×5.5。只保留防出错的下限:算力乘数 ≥ 0、耗电乘数 ≥ 0.2、损耗乘数 ≥ 0。
|
- 矿架、矿机的模块效果不设上限(原来算力最多 +20%、省电最多 25%、损耗最多 −30%,以及耗电最多 ×2 的隐含限制):9 个无限制神经核心算力 ×5.5、耗电 ×3.25、暴毙率 ×5.5。只保留防出错的下限:算力乘数 ≥ 0、耗电乘数 ≥ 0.2、损耗乘数 ≥ 0。
|
||||||
- 出块奖励 100 → 1000 PSC,NPC 初始算力 360 → 3600:均衡时每 H 收入不变(开局 1 H 每晚仍约 26.9 信用点),全网算力放大,玩家算力占比变低。模拟:普通玩法第 30 天挖矿占比 19% → 21%,第 120 天玩家算力占比 33% → 约 2%;大矿工收入明显变高。
|
- 出块奖励 100 → 1000 PSC,NPC 初始算力 360 → 3600:均衡时每 H 收入不变(开局 1 H 每晚仍约 26.9 信用点),全网算力放大,玩家算力占比变低。模拟:普通玩法第 30 天挖矿占比 19% → 21%,第 120 天玩家算力占比 33% → 约 2%;大矿工收入明显变高。
|
||||||
- 修正:内幕卖出的日志原来写“只退本金”,实际是全部没收。
|
- 修正:内幕卖出的日志原来写“只退本金”,实际是全部没收。
|
||||||
@@ -14,17 +15,17 @@
|
|||||||
|
|
||||||
- 涡轮增压器可以对矿架和矿机用(原来被挡掉),规则和原版机器一样:用一次就多跑一轮,也就是立刻挖一晚——扣一晚的电,产出按当前全网算力计算、发到这台机器的收款地址,同样算一次损耗和暴毙判定,不影响当晚照常挖矿。增压器本身的消耗、充电、可用次数照原版。
|
- 涡轮增压器可以对矿架和矿机用(原来被挡掉),规则和原版机器一样:用一次就多跑一轮,也就是立刻挖一晚——扣一晚的电,产出按当前全网算力计算、发到这台机器的收款地址,同样算一次损耗和暴毙判定,不影响当晚照常挖矿。增压器本身的消耗、充电、可用次数照原版。
|
||||||
|
|
||||||
### 第十一阶段 stage 2:场外换币台
|
### OTC Desk 场外换币台
|
||||||
|
|
||||||
- 新人脉升级“场外换币台”(500,前提是 Web3 治理社区),附赠一盏暗灯。原版暗灯双击切换目标时多一个“换币客户”(解锁后才有),放进展示柜亮黄绿色的光;招客概率、顾客面板、灯的提示都沿用原版暗灯(每盏 15% + 黑市声望的一半,封顶 95%)。
|
- 新人脉升级“场外换币台”(500,前提是 Web3 治理社区),附赠一盏暗灯。原版暗灯双击切换目标时多一个“换币客户”(解锁后才有),放进展示柜亮黄绿色的光;招客概率、顾客面板、灯的提示都沿用原版暗灯(每盏 15% + 黑市声望的一半,封顶 95%)。
|
||||||
- 换币客户一半来卖币、一半来买币,都用现金。客户说明来意后选“到终端上谈”,交易终端打开柜台交易页(标签“柜台”),客户在柜台前等着;可以按 25% / 50% / 75% / 100% 或手输数量只成交一部分,现金按比例折算,客户要的数量随房租增长。选“放弃”或把客户打发走就作废。
|
- 换币客户一半来卖币、一半来买币,都用现金。客户说明来意后选“到终端上谈”,交易终端打开柜台交易页(标签“柜台”),客户在柜台前等着;可以按 25% / 50% / 75% / 100% 或手输数量只成交一部分,现金按比例折算,客户要的数量随房租增长。选“放弃”或把客户打发走就作废。
|
||||||
- 卖币(原来的收黑币并进来,不再单独上门):成交后付现金,币直接进已连接的钱包。帮派火并、镇压期间多是 CRT,袭击上层、下层动荡期间多是 PSC,这类币全额污点;平时在 PSC、CRT、CRA 里随机,污点占市值 20%–90%,要价从市值的 80% 降到 45%。交易页上有客户地址,“查地址”打开浏览器看它的来历(混币器、黑市平台、骗局地址或 Poinbase、DEX);污点同样不超过钱包价值。Ponero 兑换处开放后偶尔有人出手 Ponero;便衣规则不变。
|
- 卖币(原来的收黑币并进来,不再单独上门):成交后付现金,币直接进已连接的钱包。帮派火并、镇压期间多是 CRT,袭击上层、下层动荡期间多是 PSC,这类币全额污点;平时在 PSC、CRT、CRA 里随机,污点占市值 20%–90%,要价从市值的 80% 降到 45%。交易页上有客户地址,“查地址”打开浏览器看它的来历(混币器、黑市平台、骗局地址或 Poinbase、DEX)。Ponero 兑换处开放后偶尔有人出手 Ponero;便衣规则不变。
|
||||||
- 买币:什么币都可能要,数量按房租 2–8 倍,出价是市价加一个随机溢价(−5% 到 +30%),成不成交由玩家决定。成交后 PLEDGER 弹出,收款地址和数量已填好,签名确认后客户付现金离开。卖出的币不追查污点。换币账单不独占终端的 Web3、灰网页,也不会被换币、混币这些终端账单覆盖,可以先在 DEX 换出客户要的币再成交。
|
- 买币:什么币都可能要,数量按房租 2–8 倍,出价是市价加一个随机溢价(−5% 到 +30%),成不成交由玩家决定。成交后 PLEDGER 弹出,收款地址和数量已填好,签名确认后客户付现金离开。卖出的币不追查污点。换币账单不独占终端的 Web3、灰网页,也不会被换币、混币这些终端账单覆盖,可以先在 DEX 换出客户要的币再成交。
|
||||||
- 浏览器里换币客户的地址显示为“换币客户”。
|
- 浏览器里换币客户的地址显示为“换币客户”。
|
||||||
- 存档数据版本 4:读旧存档时出块奖励和 NPC 算力按 stage 1 的新数值放大 10 倍(保留减半进度)。
|
- 存档数据版本 4:读旧存档时出块奖励和 NPC 算力按 stage 1 的新数值放大 10 倍(保留减半进度)。
|
||||||
- 手册“收黑币”一节改写为“换币客户”,8 种语言。
|
- 手册“收黑币”一节改写为“换币客户”,8 种语言。
|
||||||
|
|
||||||
### 第十一阶段 stage 3:自营混币器
|
### 自营混币器
|
||||||
|
|
||||||
- 买下场外换币台就开放,灰网页多一个“自营混币器”标签。注资(PSC、CRC、CRT、CRA,账单转账)后开张,NPC 客户把带污点的币存进来,几天后出款,你收手续费;费率可选 1% / 2% / 3% / 5% / 8% / 12%,可以暂停营业。
|
- 买下场外换币台就开放,灰网页多一个“自营混币器”标签。注资(PSC、CRC、CRT、CRA,账单转账)后开张,NPC 客户把带污点的币存进来,几天后出款,你收手续费;费率可选 1% / 2% / 3% / 5% / 8% / 12%,可以暂停营业。
|
||||||
- 和普通混币器一样,每一轮按匿名集洗掉一部分污点;匿名集主要是你的本金和没取走的收入(客户在途的币按 25% 算),每轮清洗率 = 35% × 匿名集 / (匿名集 + 20,000)。客户拿“费率 + 出款剩下的污点 × 0.1”和 Tumbler 的混币器比,便宜就多来,黑市声望越高客人越多(Tumbler 关停或被制裁时客人更多)。
|
- 和普通混币器一样,每一轮按匿名集洗掉一部分污点;匿名集主要是你的本金和没取走的收入(客户在途的币按 25% 算),每轮清洗率 = 35% × 匿名集 / (匿名集 + 20,000)。客户拿“费率 + 出款剩下的污点 × 0.1”和 Tumbler 的混币器比,便宜就多来,黑市声望越高客人越多(Tumbler 关停或被制裁时客人更多)。
|
||||||
@@ -34,6 +35,34 @@
|
|||||||
- 手册“换币客户”一节加一段自营混币器,8 种语言;夜间日志和报纸新闻。
|
- 手册“换币客户”一节加一段自营混币器,8 种语言;夜间日志和报纸新闻。
|
||||||
|
|
||||||
|
|
||||||
|
### Tumbler 支线扩展
|
||||||
|
|
||||||
|
- 治安部探员:Tumbler 第 2 次上门之后的第二天起来店里问一次,他来过之后 Tumbler 才来第 3 次。承认 Tumbler 来过:治安部声望 +5;否认:没有影响。承认过又帮他藏了密钥盘的,探员在 Tumbler 来取的前一天上门搜查,搜到就没收、记违禁品罪证 300,Tumbler 第 4 次来时说他听说了。
|
||||||
|
- 密钥落到治安部(举报、被搜走、Tumbler 来取时盘不在手上):混币记录被还原,按最近 30 天混币器出款洗掉的污点记诈骗罪证(× 50%,单次最多 400);夜间日志和报纸。卖给黑市不算。
|
||||||
|
- 举报之后有审判:第 2 天开一个“Tumbler 被判有罪”的预测盘(先验 70%),第 7 天宣判;报纸每天登一条庭审进展,偏向控方或辩方,七成偏向真实判决,盘口的价格跟着新闻走,线索列出两边各占上风几天。无罪获释的话,3 天后他会报复。
|
||||||
|
- 卖给黑市的:黑市在 10–20 天后卷款跑路,混币器里在途的币全部丢失,混币器关停;3 天后 Tumbler 报复。
|
||||||
|
- 报复:门缝里塞进来一张纸条,之后一半可能是当前钱包被植入木马(和商城的投毒钱包一样:剪贴板劫持,钱够多以后被转空),否则每个钱包都会收到伪装成最近转账对象的 0 币转入(地址投毒)。
|
||||||
|
- 帮他藏好并还给他:Tumbler 成为长期联系人,治安部镇压开始的前一晚在夜间日志里报信。
|
||||||
|
- 混币器关停 15 天后换名字(Vortex)、换地址重新上线,费率和跑路概率回到原样;有 25% 是治安部的钓鱼混币器,从它提回的币整笔算脏币,费率只有一半。
|
||||||
|
- 卖给黑市那笔 CRT 的污点比例收进配置(`TumblerSellTaint`)。
|
||||||
|
- 修正:Tumbler 每次上门的外观原来是随机的,现在第一次上门定下后一直不变。
|
||||||
|
- 手册剧情联动一节补一段,8 种语言。
|
||||||
|
|
||||||
|
### 污点:按币种记脏币,删除出金审查
|
||||||
|
|
||||||
|
- 污点只在 Web3 钱包里,每种币分别记脏币数量,钱包页、PLEDGER 的余额里能看到;钱包总表的“脏币”列按现价显示。原来整个钱包记一笔信用点的污点不再使用。
|
||||||
|
- 花掉、转出、付手续费时按这种币的脏币比例带走脏币;兑换成别的币时脏币比例跟过去(60% 是脏币的 CRT 换成 PSC,PSC 也是 60% 脏币);兑入 Ponero 时脏币消失,Ponero 是干净的。
|
||||||
|
- Poinbase 只收干净的币:钱包往充值地址每种币最多转干净的部分,超出时 PLEDGER 拦下并写明能充多少;资金页“从钱包入金”也列出每种币能充多少。Poinbase 账户和银行没有污点。
|
||||||
|
- 出金审查整套删除:出金到银行不再有被查概率、没收和销赃罪证,只收手续费 0.1%、对超出成本的部分征税 8%。从 Ponero 兑出、刚从混币器提出的币也不再“出金加重”。
|
||||||
|
- 带污点的收入都改成“收到的这批币里有多少脏币”:换币客户卖来的币、用币付款的顾客(按赃物热度)、灰网卖赃物的货款、预测盘内幕单和操纵的兑付、理财卷款、自营混币器的收入和卷款、卖密钥盘换来的 CRT。“加污点不能超过钱包价值、超出部分记诈骗罪证”的规则随之删除。
|
||||||
|
- 永续被判操纵:盈利照常留在账户,只记诈骗罪证(盈利 × 50%,单次最多 400),不再加污点。
|
||||||
|
- 混币器:存入时带走这种币的脏币,每轮减少;制裁期间到期的出款、从钓鱼混币器提出的币不洗,整笔算脏币。
|
||||||
|
- Tumbler 的密钥泄露:不再往钱包里加回污点,改为按最近 30 天混币器出款洗掉的污点记诈骗罪证(× 50%,单次最多 400)。
|
||||||
|
- 剧情联动:塞尔皮科的证据交给治安部,原来的“出金审查更严”换成 30 天内混币器每轮清洗率 ×0.7;伦警官被捕,原来的“出金审查更严”换成 14 天内换币客户里的便衣 ×1.3。
|
||||||
|
- 存档数据版本 5:读旧档时,每个钱包原来的污点按当前价格摊成各币的脏币;Poinbase 账户和永续仓位的污点挪到 1 号钱包一起摊(超出的作废);混币器、黑市订单、质押、空投池、预测持仓、自营混币器本金里托管的污点换成对应币的脏币。
|
||||||
|
- 模拟(research/launder):混币器小额 1–3 轮洗钱成本 10%–15%,Ponero 约 12%、每天约 500,买币的换币客户是负成本但受客流限制;数值都不用改。
|
||||||
|
- 手册“出金审查”一节改写为“污点”,相关段落 8 种语言同步改。
|
||||||
|
|
||||||
## 1.1.0
|
## 1.1.0
|
||||||
|
|
||||||
市场与洗钱的平衡调整:Poinbase 改为订单簿、DEX 稳定币对改为稳定币池、保险基金和爆仓新闻、预测市场流动性、收黑币、浏览器记录钱包的每一笔进出。存档兼容,读旧存档时自动升级。
|
市场与洗钱的平衡调整:Poinbase 改为订单簿、DEX 稳定币对改为稳定币池、保险基金和爆仓新闻、预测市场流动性、收黑币、浏览器记录钱包的每一笔进出。存档兼容,读旧存档时自动升级。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Probably Decentralized
|
# Probably Decentralized
|
||||||
|
|
||||||
A mod for *Probably Stolen*: crypto mining, a fictional coin market, stablecoins, laundering and its risks, a Web3 black market, built on the game's own power, events and law systems. Current version: 1.1.0.
|
A mod for *Probably Stolen*: crypto mining, a fictional coin market, stablecoins, laundering and its risks, a Web3 black market, built on the game's own power, events and law systems. Current version: 2.0.0.
|
||||||
|
|
||||||
All coins, exchanges and events are fictional and have no real-world value.
|
All coins, exchanges and events are fictional and have no real-world value.
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace Decentralized.Domain
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>买一件:付 asset 币。钱包里按价值比例带走的污点和成本留在卖家那边。成功返回 true,库存减一。</summary>
|
/// <summary>买一件:付 asset 币。付出的币按它的脏比例带走脏枚数,成本按价值比例留在卖家那边。成功返回 true,库存减一。</summary>
|
||||||
public bool Buy(BmOffer o, Wallet w, string asset, Func<string, double> price)
|
public bool Buy(BmOffer o, Wallet w, string asset, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (o == null || o.Qty <= 0 || asset == Assets.CRC) return false;
|
if (o == null || o.Qty <= 0 || asset == Assets.CRC) return false;
|
||||||
@@ -126,7 +126,6 @@ namespace Decentralized.Domain
|
|||||||
if (w.Avail(asset) + 1e-9 < qty) return false;
|
if (w.Avail(asset) + 1e-9 < qty) return false;
|
||||||
double total = w.Value(price);
|
double total = w.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, o.Price / total) : 0;
|
double share = total > 0 ? Math.Min(1, o.Price / total) : 0;
|
||||||
w.Taint -= w.Taint * share;
|
|
||||||
w.Basis -= w.Basis * share;
|
w.Basis -= w.Basis * share;
|
||||||
w.Add(asset, -qty);
|
w.Add(asset, -qty);
|
||||||
o.Qty--;
|
o.Qty--;
|
||||||
@@ -139,14 +138,11 @@ namespace Decentralized.Domain
|
|||||||
|
|
||||||
public double DeskLeft(int day) => Math.Max(0, Tuning.PoneroDailyCap - (DeskDay == day ? DeskToday : 0));
|
public double DeskLeft(int day) => Math.Max(0, Tuning.PoneroDailyCap - (DeskDay == day ? DeskToday : 0));
|
||||||
|
|
||||||
/// <summary>兑入 Ponero:from 币 amount 个,扣手续费后按 Ponero 价到账;这部分价值带的污点被清除(不跟着 Ponero)。返回到账数量,额度或余额不足返回 -1。</summary>
|
/// <summary>兑入 Ponero:from 币 amount 个,扣手续费后按 Ponero 价到账;兑掉的币连同其中的脏枚数一起消失,换来的 Ponero 是干净的。返回到账数量,额度或余额不足返回 -1。</summary>
|
||||||
public double ToPonero(Wallet w, string from, double amount, int day, Func<string, double> price)
|
public double ToPonero(Wallet w, string from, double amount, int day, Func<string, double> price)
|
||||||
{
|
{
|
||||||
double value = amount * price(from);
|
double value = amount * price(from);
|
||||||
if (from == Assets.Ponero || amount <= 0 || value <= 0 || w.Avail(from) + 1e-9 < amount || value > DeskLeft(day) + 1e-9) return -1;
|
if (from == Assets.Ponero || amount <= 0 || value <= 0 || w.Avail(from) + 1e-9 < amount || value > DeskLeft(day) + 1e-9) return -1;
|
||||||
double total = w.Value(price);
|
|
||||||
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
|
||||||
w.Taint -= w.Taint * share;
|
|
||||||
w.Add(from, -amount);
|
w.Add(from, -amount);
|
||||||
double got = value * (1 - Tuning.PoneroFee) / price(Assets.Ponero);
|
double got = value * (1 - Tuning.PoneroFee) / price(Assets.Ponero);
|
||||||
w.Add(Assets.Ponero, got);
|
w.Add(Assets.Ponero, got);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -46,8 +47,10 @@ namespace Decentralized.Domain
|
|||||||
public double Qty;
|
public double Qty;
|
||||||
/// <summary>付款的钱包地址:退款回这里。</summary>
|
/// <summary>付款的钱包地址:退款回这里。</summary>
|
||||||
public string Wallet;
|
public string Wallet;
|
||||||
/// <summary>付款时留在卖家那边的污点与成本:退款时一并还回,免得"付脏币再退款"洗钱。</summary>
|
/// <summary>付款的币里脏的枚数和成本:退款时一并还回,免得"付脏币再退款"洗钱。</summary>
|
||||||
public double Taint, Basis;
|
public double Dirty, Basis;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
public int PlacedDay, DueDay;
|
public int PlacedDay, DueDay;
|
||||||
/// <summary>被截获后执法选择了上门:到货时快递员是执法人员,签收即记罪证。</summary>
|
/// <summary>被截获后执法选择了上门:到货时快递员是执法人员,签收即记罪证。</summary>
|
||||||
public bool Controlled;
|
public bool Controlled;
|
||||||
@@ -238,7 +241,7 @@ namespace Decentralized.Domain
|
|||||||
/// <summary>目录里全部货按订单价算的总值(信用点),用来核对每周周转量。</summary>
|
/// <summary>目录里全部货按订单价算的总值(信用点),用来核对每周周转量。</summary>
|
||||||
public double CatalogValue => Catalog.Sum(l => (double)l.Price * l.Qty);
|
public double CatalogValue => Catalog.Sum(l => (double)l.Price * l.Qty);
|
||||||
|
|
||||||
/// <summary>下单:钱包里的币按实付折算扣除,污点与成本按比例留在卖家那边(记在订单上)。成功返回订单。</summary>
|
/// <summary>下单:钱包里的币按实付折算扣除,脏枚数与成本按比例留在卖家那边(记在订单上)。成功返回订单。</summary>
|
||||||
public BmOrder Place(BmListing l, int count, PayMode mode, Wallet w, string asset, int day, Func<string, double> price)
|
public BmOrder Place(BmListing l, int count, PayMode mode, Wallet w, string asset, int day, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (l == null || count < 1 || count > l.Qty || asset == Assets.CRC || Closed(day)) return null;
|
if (l == null || count < 1 || count > l.Qty || asset == Assets.CRC || Closed(day)) return null;
|
||||||
@@ -251,13 +254,13 @@ namespace Decentralized.Domain
|
|||||||
if (w.Avail(asset) + 1e-9 < qty) return null;
|
if (w.Avail(asset) + 1e-9 < qty) return null;
|
||||||
double total = w.Value(price);
|
double total = w.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, credits / total) : 0;
|
double share = total > 0 ? Math.Min(1, credits / total) : 0;
|
||||||
double taint = w.Taint * share, basis = w.Basis * share;
|
double dirty = qty * w.DirtyRatio(asset), basis = w.Basis * share;
|
||||||
w.Taint -= taint; w.Basis -= basis;
|
w.Basis -= basis;
|
||||||
w.Add(asset, -qty);
|
w.Add(asset, -qty);
|
||||||
var o = new BmOrder
|
var o = new BmOrder
|
||||||
{
|
{
|
||||||
Id = NextOrderId++, Item = l.Item, Seller = seller.Name, SellerScam = seller.Scam, Mode = mode, Count = count, Model = l.Model, FakeOf = l.FakeOf, Health = l.Health, Price = credits, Asset = asset, Qty = qty,
|
Id = NextOrderId++, Item = l.Item, Seller = seller.Name, SellerScam = seller.Scam, Mode = mode, Count = count, Model = l.Model, FakeOf = l.FakeOf, Health = l.Health, Price = credits, Asset = asset, Qty = qty,
|
||||||
Taint = taint, Basis = basis, PlacedDay = day, DueDay = day + seller.Days, Wallet = w.Address,
|
Dirty = dirty, Basis = basis, PlacedDay = day, DueDay = day + seller.Days, Wallet = w.Address,
|
||||||
};
|
};
|
||||||
l.Qty -= count;
|
l.Qty -= count;
|
||||||
if (l.Qty <= 0) Catalog.Remove(l);
|
if (l.Qty <= 0) Catalog.Remove(l);
|
||||||
@@ -268,8 +271,8 @@ namespace Decentralized.Domain
|
|||||||
|
|
||||||
private static void Refund(Wallet w, BmOrder o)
|
private static void Refund(Wallet w, BmOrder o)
|
||||||
{
|
{
|
||||||
w.Add(o.Asset, o.Qty);
|
w.AddDirty(o.Asset, o.Qty, o.Dirty);
|
||||||
w.Taint += o.Taint; w.Basis += o.Basis;
|
w.Basis += o.Basis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>每晚推进订单:平台跑路、到期的订单(卖家跑路、被截获、死投被挖走)、转入可取状态。镇压期间到期顺延一天。</summary>
|
/// <summary>每晚推进订单:平台跑路、到期的订单(卖家跑路、被截获、死投被挖走)、转入可取状态。镇压期间到期顺延一天。</summary>
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace Decentralized.Domain
|
|||||||
if (w.Avail(feeAsset) + 1e-9 < qty) return null;
|
if (w.Avail(feeAsset) + 1e-9 < qty) return null;
|
||||||
double total = w.Value(price);
|
double total = w.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, ListFee(listPrice) / total) : 0;
|
double share = total > 0 ? Math.Min(1, ListFee(listPrice) / total) : 0;
|
||||||
w.Taint -= w.Taint * share; w.Basis -= w.Basis * share;
|
w.Basis -= w.Basis * share;
|
||||||
w.Add(feeAsset, -qty);
|
w.Add(feeAsset, -qty);
|
||||||
var s = new BmSale { Item = item, Model = model, FakeOf = fakeOf, Health = health, Ref = refValue, Mult = m, ListPrice = listPrice, ListedDay = day, Wallet = w.Address, Heat = Math.Max(0, Math.Min(100, heat)) };
|
var s = new BmSale { Item = item, Model = model, FakeOf = fakeOf, Health = health, Ref = refValue, Mult = m, ListPrice = listPrice, ListedDay = day, Wallet = w.Address, Heat = Math.Max(0, Math.Min(100, heat)) };
|
||||||
Sales.Add(s);
|
Sales.Add(s);
|
||||||
@@ -163,8 +163,9 @@ namespace Decentralized.Domain
|
|||||||
double p = price(pa);
|
double p = price(pa);
|
||||||
if (p <= 0) continue;
|
if (p <= 0) continue;
|
||||||
var w = wallet(s.Wallet);
|
var w = wallet(s.Wallet);
|
||||||
w.Add(pa, s.Proceeds / p);
|
// 回款的币按 污点 / 回款额 的比例是脏的
|
||||||
w.Taint += s.Taint;
|
double got = s.Proceeds / p;
|
||||||
|
w.AddDirty(pa, got, s.Proceeds > 0 ? got * Math.Min(1, s.Taint / s.Proceeds) : 0);
|
||||||
w.Basis += s.Proceeds;
|
w.Basis += s.Proceeds;
|
||||||
s.State = SaleState.Paid;
|
s.State = SaleState.Paid;
|
||||||
ev.Add(new BmEvent { Kind = "sale_paid", Sale = s, Amount = s.Proceeds });
|
ev.Add(new BmEvent { Kind = "sale_paid", Sale = s, Amount = s.Proceeds });
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ namespace Decentralized.Domain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>收款:返回收到的币数。heatPct 是物品的赃物热度(0–100)。多付的溢价是顾客给的额外收入,不带污点。</summary>
|
/// <summary>收款:返回收到的币数。heatPct 是物品的赃物热度(0–100):按货值 × 热度那部分的币是脏的;多付的溢价是顾客给的额外收入,干净。</summary>
|
||||||
public static double Receive(Wallet w, string asset, double credits, double price, double heatPct)
|
public static double Receive(Wallet w, string asset, double credits, double price, double heatPct)
|
||||||
{
|
{
|
||||||
if (credits <= 0 || price <= 0) return 0;
|
if (credits <= 0 || price <= 0) return 0;
|
||||||
double qty = credits * (1 + Tuning.CoinPayPremium) / price; // 溢价只加在币数上,污点与成本仍按货值算
|
double qty = credits * (1 + Tuning.CoinPayPremium) / price; // 溢价只加在币数上,污点与成本仍按货值算
|
||||||
w.Add(asset, qty);
|
w.AddDirty(asset, qty, credits * Math.Max(0, Math.Min(100, heatPct)) / 100.0 / price);
|
||||||
w.Taint += credits * Math.Max(0, Math.Min(100, heatPct)) / 100.0;
|
|
||||||
w.Basis += credits;
|
w.Basis += credits;
|
||||||
return qty;
|
return qty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,49 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
public enum AmlOutcome { Clear, Light, Heavy }
|
/// <summary>一次出金到银行的结果。</summary>
|
||||||
|
|
||||||
/// <summary>一次合规出金的结果。罪证由接入层记进游戏的罪证账本(销赃)。</summary>
|
|
||||||
public sealed class CashoutResult
|
public sealed class CashoutResult
|
||||||
{
|
{
|
||||||
public double Requested;
|
public double Requested;
|
||||||
public double Received;
|
public double Received;
|
||||||
public double Confiscated;
|
|
||||||
public double Crime;
|
|
||||||
public double Tax;
|
public double Tax;
|
||||||
public double HitChance;
|
|
||||||
public AmlOutcome Outcome;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 合规交易所出金:CRC 兑回信用点,过 AML。审查按单笔金额、7 天累计金额、污点比例、是否来自混币器或被标记地址判定。
|
/// 合规交易所 Poinbase:只收干净的币(钱包往充值地址最多转“价值 − 污点”,见 <see cref="Wallet.TransferClean"/>),账户没有污点。
|
||||||
/// 轻度命中(污点 < 30%)没收污点部分、不记罪证;重度命中没收污点部分,并把污点额记为销赃罪证。
|
/// 出金到银行把 CRC 兑回信用点,扣手续费,只对超出成本的部分计税,不做审查。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Exchange
|
public sealed class Exchange
|
||||||
{
|
{
|
||||||
/// <summary>Poinbase 上架的币:只有这些能充值、能在现货交易。黑市的 CRT、革命军的 CRA 合规交易所不收。</summary>
|
/// <summary>Poinbase 上架的币:只有这些能充值、能在现货交易。黑市的 CRT、革命军的 CRA 合规交易所不收。</summary>
|
||||||
public static readonly string[] Listed = { Assets.PSC, Assets.CRC, Assets.SPARK };
|
public static readonly string[] Listed = { Assets.PSC, Assets.CRC, Assets.SPARK };
|
||||||
|
|
||||||
/// <summary>最近的出金记录:(天, 金额)。</summary>
|
/// <summary>存档迁移(数据版本 5):旧存档里 Poinbase 账户和永续仓位带的污点额(信用点),清零后返回总数,由调用方挪到 1 号钱包一起摊。</summary>
|
||||||
public List<KeyValuePair<int, double>> History = new List<KeyValuePair<int, double>>();
|
public static double TakeLegacyTaint(Wallet account, System.Collections.Generic.IEnumerable<PerpPosition> positions)
|
||||||
|
|
||||||
public static double HitChance(double amount, double taint, double recentTotal, double rent, bool fromMixerOrFlagged)
|
|
||||||
{
|
{
|
||||||
if (amount <= 0) return 0;
|
double t = account.LegacyTaint;
|
||||||
double ratio = taint / amount;
|
account.LegacyTaint = 0;
|
||||||
double big = Tuning.AmlBigRents * rent, cum = Tuning.AmlCumRents * rent;
|
foreach (var p in positions) { t += p.LegacyTaint; p.LegacyTaint = 0; }
|
||||||
double p = 0;
|
return t;
|
||||||
if (ratio >= Tuning.AmlTaintRatio) p += ratio * Tuning.AmlTaintMult;
|
|
||||||
p += Math.Max(0, (amount - big) / big) * Tuning.AmlExcessWeight;
|
|
||||||
p += Math.Max(0, (recentTotal + amount - cum) / cum) * Tuning.AmlExcessWeight;
|
|
||||||
if (fromMixerOrFlagged) p += Tuning.AmlMixerBonus;
|
|
||||||
return Math.Min(Tuning.AmlMaxChance, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从地址里取出 amount 个 CRC 兑成信用点(按 CRC 当前价格,平时为 1;脱锚期间按市价),扣手续费。污点与成本按比例随取出部分计算;
|
/// 从账户里取出 amount 个 CRC 兑成信用点(按 CRC 当前价格,平时为 1;脱锚期间按市价),扣手续费。成本按取出部分的价值比例带走,
|
||||||
/// 只对超出成本的部分计税。
|
/// 只对超出成本的部分计税。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CashoutResult Cashout(Wallet wallet, double amount, Func<string, double> price, int day, double rent, bool fromMixer, Rng rng)
|
public CashoutResult Cashout(Wallet account, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
amount = Math.Min(amount, wallet.Get(Assets.CRC));
|
amount = Math.Min(amount, account.Get(Assets.CRC));
|
||||||
var r = new CashoutResult { Requested = amount };
|
var r = new CashoutResult { Requested = amount };
|
||||||
if (amount <= 0) return r;
|
if (amount <= 0) return r;
|
||||||
double total = wallet.Value(price);
|
double total = account.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, amount * price(Assets.CRC) / total) : 0;
|
|
||||||
double taint = wallet.Taint * share, basis = wallet.Basis * share;
|
|
||||||
History.RemoveAll(h => h.Key <= day - Tuning.AmlWindowDays);
|
|
||||||
double recent = History.Sum(h => h.Value);
|
|
||||||
double value = amount * price(Assets.CRC);
|
double value = amount * price(Assets.CRC);
|
||||||
r.HitChance = Math.Min(1, HitChance(value, taint, recent, rent, fromMixer || wallet.Flagged) * StoryMods.Current.Aml(day));
|
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
||||||
wallet.Add(Assets.CRC, -amount);
|
double basis = account.Basis * share;
|
||||||
wallet.Taint -= taint;
|
account.Add(Assets.CRC, -amount);
|
||||||
wallet.Basis -= basis;
|
account.Basis -= basis;
|
||||||
History.Add(new KeyValuePair<int, double>(day, value));
|
|
||||||
double got = value * (1 - Tuning.ExchangeFee);
|
double got = value * (1 - Tuning.ExchangeFee);
|
||||||
if (rng.Chance(r.HitChance))
|
|
||||||
{
|
|
||||||
r.Outcome = taint / value >= Tuning.AmlHeavyRatio ? AmlOutcome.Heavy : AmlOutcome.Light;
|
|
||||||
r.Confiscated = Math.Min(got, taint);
|
|
||||||
got -= r.Confiscated;
|
|
||||||
if (r.Outcome == AmlOutcome.Heavy) r.Crime = taint;
|
|
||||||
}
|
|
||||||
r.Tax = Math.Max(0, got - basis) * Tuning.TaxRate;
|
r.Tax = Math.Max(0, got - basis) * Tuning.TaxRate;
|
||||||
r.Received = got;
|
r.Received = got;
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,20 +10,38 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
public string Asset;
|
public string Asset;
|
||||||
public double Amount;
|
public double Amount;
|
||||||
/// <summary>存入时一并带走的污点与成本(信用点)。</summary>
|
/// <summary>存入的币里脏的枚数,和一并带走的成本(信用点)。</summary>
|
||||||
public double Taint, Basis;
|
public double Dirty, Basis;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
public int Rounds;
|
public int Rounds;
|
||||||
public int ReadyDay;
|
public int ReadyDay;
|
||||||
/// <summary>存入的钱包地址:到期提回这里。</summary>
|
/// <summary>存入的钱包地址:到期提回这里。</summary>
|
||||||
public string Wallet;
|
public string Wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>一笔到期提回的出款记录(泄露时按它记罪证):Cleaned 是这笔洗掉的污点,按提回时的价格折成信用点。</summary>
|
||||||
|
public sealed class MixReturn
|
||||||
|
{
|
||||||
|
public int Day;
|
||||||
|
public string Wallet, Asset;
|
||||||
|
public double Amount, Cleaned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>泄露的结果:最近几笔出款,一共洗掉了多少污点(信用点),折成的诈骗罪证。</summary>
|
||||||
|
public sealed class MixLeak
|
||||||
|
{
|
||||||
|
public int Count;
|
||||||
|
public double Cleaned, Fraud;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>一笔混币结束时的结果,供夜间日志使用。</summary>
|
/// <summary>一笔混币结束时的结果,供夜间日志使用。</summary>
|
||||||
public sealed class MixResult
|
public sealed class MixResult
|
||||||
{
|
{
|
||||||
public bool Rugged;
|
public bool Rugged;
|
||||||
public string Asset;
|
public string Asset;
|
||||||
public double Amount, TaintBefore, TaintAfter;
|
public double Amount, TaintBefore, TaintAfter;
|
||||||
|
/// <summary>被标记(制裁期间提出、从钓鱼混币器提出):不洗,整笔都是脏的。</summary>
|
||||||
public bool Flagged;
|
public bool Flagged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,21 +54,44 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
public List<MixDeposit> Pending = new List<MixDeposit>();
|
public List<MixDeposit> Pending = new List<MixDeposit>();
|
||||||
public int SanctionedUntil = -1;
|
public int SanctionedUntil = -1;
|
||||||
/// <summary>提回的币最近一次从混币器出来的天数,用来给出金审查加重。</summary>
|
/// <summary>最近的出款记录(Tumbler 的密钥落到治安部时用来还原)。</summary>
|
||||||
public int LastReturnDay = -999;
|
public List<MixReturn> Returns = new List<MixReturn>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 泄露:最近 <see cref="Tuning.TumblerLeakDays"/> 天的出款被还原,按这些出款洗掉的污点记诈骗罪证(<see cref="Wallet.FraudFor"/>)。记录清空。
|
||||||
|
/// </summary>
|
||||||
|
public MixLeak Leak(int day)
|
||||||
|
{
|
||||||
|
var recent = Returns.Where(x => day - x.Day <= Tuning.TumblerLeakDays).ToList();
|
||||||
|
double cleaned = recent.Sum(x => x.Cleaned);
|
||||||
|
Returns.Clear();
|
||||||
|
return new MixLeak { Count = recent.Count, Cleaned = cleaned, Fraud = Wallet.FraudFor(cleaned) };
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Remember(MixReturn ret)
|
||||||
|
{
|
||||||
|
Returns.Add(ret);
|
||||||
|
Returns.RemoveAll(x => ret.Day - x.Day > Tuning.TumblerLeakDays);
|
||||||
|
while (Returns.Count > Tuning.TumblerReturnsMax) Returns.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>黑市卷款跑路:在途的存入全部丢失。</summary>
|
||||||
|
public List<MixResult> RugAll()
|
||||||
|
{
|
||||||
|
var list = Pending.Select(p => new MixResult { Rugged = true, Asset = p.Asset, Amount = p.Amount }).ToList();
|
||||||
|
Pending.Clear();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Sanctioned(int day) => day <= SanctionedUntil;
|
public bool Sanctioned(int day) => day <= SanctionedUntil;
|
||||||
|
|
||||||
/// <summary>资金来自混币器:最近 AML 窗口内提回过币,或者被标记。</summary>
|
|
||||||
public bool RecentlyMixed(int day) => day - LastReturnDay <= Tuning.AmlWindowDays;
|
|
||||||
|
|
||||||
/// <summary>一轮的清洗率:基准 × 匿名集系数。</summary>
|
/// <summary>一轮的清洗率:基准 × 匿名集系数。</summary>
|
||||||
/// <summary>每轮手续费(剧情可能改动)。</summary>
|
/// <summary>每轮手续费(剧情可能改动)。</summary>
|
||||||
public static double Fee => Math.Min(0.5, Tuning.MixerFee * StoryMods.Current.MixerFee);
|
public static double Fee => Math.Min(0.5, Tuning.MixerFee * StoryMods.Current.MixerFee);
|
||||||
|
|
||||||
public static double RoundRate(double depositValue) => Tuning.MixerCleanRate * Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume / (Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume + Math.Max(0, depositValue));
|
public static double RoundRate(double depositValue, int day = -1) => Tuning.MixerCleanRate * (day >= 0 ? StoryMods.Current.MixClean(day) : 1) * Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume / (Tuning.MixerNpcVolume * StoryMods.Current.MixerVolume + Math.Max(0, depositValue));
|
||||||
|
|
||||||
/// <summary>存入:从钱包按价值比例带走污点与成本。轮数超出范围或余额不足返回 null。</summary>
|
/// <summary>存入:按这种币的脏比例带走脏枚数,按价值比例带走成本。轮数超出范围或余额不足返回 null。</summary>
|
||||||
public MixDeposit Deposit(Wallet w, string asset, double amount, int rounds, int day, Func<string, double> price)
|
public MixDeposit Deposit(Wallet w, string asset, double amount, int rounds, int day, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (rounds < 1 || rounds > Tuning.MixerMaxRounds || amount <= 0 || w.Avail(asset) + 1e-9 < amount) return null;
|
if (rounds < 1 || rounds > Tuning.MixerMaxRounds || amount <= 0 || w.Avail(asset) + 1e-9 < amount) return null;
|
||||||
@@ -57,11 +99,10 @@ namespace Decentralized.Domain
|
|||||||
if (value < Tuning.MixerMin) return null;
|
if (value < Tuning.MixerMin) return null;
|
||||||
double total = w.Value(price);
|
double total = w.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
double share = total > 0 ? Math.Min(1, value / total) : 0;
|
||||||
double taint = w.Taint * share, basis = w.Basis * share;
|
double dirty = amount * w.DirtyRatio(asset), basis = w.Basis * share;
|
||||||
w.Add(asset, -amount);
|
w.Add(asset, -amount);
|
||||||
w.Taint -= taint;
|
|
||||||
w.Basis -= basis;
|
w.Basis -= basis;
|
||||||
var d = new MixDeposit { Asset = asset, Amount = amount, Taint = taint, Basis = basis, Rounds = rounds, ReadyDay = day + rounds, Wallet = w.Address };
|
var d = new MixDeposit { Asset = asset, Amount = amount, Dirty = dirty, Basis = basis, Rounds = rounds, ReadyDay = day + rounds, Wallet = w.Address };
|
||||||
Pending.Add(d);
|
Pending.Add(d);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -89,17 +130,17 @@ namespace Decentralized.Domain
|
|||||||
}
|
}
|
||||||
if (day < d.ReadyDay) continue;
|
if (day < d.ReadyDay) continue;
|
||||||
Pending.Remove(d);
|
Pending.Remove(d);
|
||||||
double rate = RoundRate(d.Amount * price(d.Asset));
|
// 制裁期间提出的、从治安部的钓鱼混币器提出的,都被标记:不洗,这笔币按全额污点带回
|
||||||
double taint = d.Taint * Math.Pow(1 - rate, d.Rounds);
|
bool flagged = Sanctioned(day) || StoryMods.Current.MixerHoneypot;
|
||||||
|
double rate = flagged ? 0 : RoundRate(d.Amount * price(d.Asset), day);
|
||||||
double amount = d.Amount * Math.Pow(1 - Fee, d.Rounds);
|
double amount = d.Amount * Math.Pow(1 - Fee, d.Rounds);
|
||||||
bool flagged = Sanctioned(day);
|
double dirty = flagged ? amount : Math.Min(amount, d.Dirty * Math.Pow(1 - rate, d.Rounds));
|
||||||
var w = wallet(d.Wallet);
|
var w = wallet(d.Wallet);
|
||||||
w.Add(d.Asset, amount);
|
w.AddDirty(d.Asset, amount, dirty);
|
||||||
w.Taint += taint;
|
|
||||||
w.Basis += d.Basis;
|
w.Basis += d.Basis;
|
||||||
if (flagged) w.Flagged = true;
|
double p = price(d.Asset);
|
||||||
LastReturnDay = day;
|
Remember(new MixReturn { Day = day, Wallet = d.Wallet, Asset = d.Asset, Amount = amount, Cleaned = Math.Max(0, d.Dirty - dirty) * p });
|
||||||
results.Add(new MixResult { Asset = d.Asset, Amount = amount, TaintBefore = d.Taint, TaintAfter = taint, Flagged = flagged });
|
results.Add(new MixResult { Asset = d.Asset, Amount = amount, TaintBefore = d.Dirty * p, TaintAfter = dirty * p, Flagged = flagged });
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace Decentralized.Domain
|
|||||||
/// 否则在 PSC、CRT、CRA 里随机,污点比例在 OtcTaintMin–OtcTaintMax 之间。市值 = 房租 × 区间;现金价 = 市值 × 折扣,折扣按污点比例从 OtcCutClean 线性降到 OtcCutDirty。
|
/// 否则在 PSC、CRT、CRA 里随机,污点比例在 OtcTaintMin–OtcTaintMax 之间。市值 = 房租 × 区间;现金价 = 市值 × 折扣,折扣按污点比例从 OtcCutClean 线性降到 OtcCutDirty。
|
||||||
/// crackdown:镇压期间便衣更多。
|
/// crackdown:镇压期间便衣更多。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static OtcOffer MakeSell(ICollection<MarketEvent> active, bool poneroOpen, Func<string, double> price, double rent, Rng rng)
|
public static OtcOffer MakeSell(ICollection<MarketEvent> active, bool poneroOpen, Func<string, double> price, double rent, Rng rng, double stingMult = 1)
|
||||||
{
|
{
|
||||||
if (rent <= 0) return null;
|
if (rent <= 0) return null;
|
||||||
string asset = null; double ratio;
|
string asset = null; double ratio;
|
||||||
@@ -75,7 +75,7 @@ namespace Decentralized.Domain
|
|||||||
return new OtcOffer
|
return new OtcOffer
|
||||||
{
|
{
|
||||||
Side = OtcSide.Sell, Asset = asset, Qty = value / p, Value = value, TaintRatio = ratio, Cash = (int)Math.Round(value * cut),
|
Side = OtcSide.Sell, Asset = asset, Qty = value / p, Value = value, TaintRatio = ratio, Cash = (int)Math.Round(value * cut),
|
||||||
Sting = rng.Chance(Tuning.OtcSting + (crackdown ? Tuning.OtcStingCrackdown : 0)),
|
Sting = rng.Chance(Math.Min(1, (Tuning.OtcSting + (crackdown ? Tuning.OtcStingCrackdown : 0)) * stingMult)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +101,11 @@ namespace Decentralized.Domain
|
|||||||
return new OtcOffer { Side = o.Side, Asset = o.Asset, Qty = o.Qty * f, Value = o.Value * f, TaintRatio = o.TaintRatio, Cash = (int)Math.Round(o.Cash * f), Sting = o.Sting };
|
return new OtcOffer { Side = o.Side, Asset = o.Asset, Qty = o.Qty * f, Value = o.Value * f, TaintRatio = o.TaintRatio, Cash = (int)Math.Round(o.Cash * f), Sting = o.Sting };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>收下卖币客户的币:币进钱包,成本是付出的现金;污点 = 市值 × 污点比例(带上限)。返回超出钱包价值、没加进去的污点。</summary>
|
/// <summary>收下卖币客户的币:币进钱包,其中 数量 × 污点比例 枚是脏的;成本是付出的现金。</summary>
|
||||||
public static double Receive(Wallet w, OtcOffer o, Func<string, double> price)
|
public static void Receive(Wallet w, OtcOffer o)
|
||||||
{
|
{
|
||||||
w.Add(o.Asset, o.Qty);
|
w.AddDirty(o.Asset, o.Qty, o.Qty * o.TaintRatio);
|
||||||
w.Basis += o.Cash;
|
w.Basis += o.Cash;
|
||||||
return o.TaintRatio > 0 ? w.AddTaintCapped(o.Value * o.TaintRatio, price) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
/// <summary>自营混币器里一种币:玩家的本金(数量、污点额)和还没取走的手续费收入(取走时全额带污点)。</summary>
|
/// <summary>自营混币器里一种币:玩家的本金(数量、其中脏的枚数)和还没取走的手续费收入(取走时整笔是脏的)。</summary>
|
||||||
public sealed class MixPool
|
public sealed class MixPool
|
||||||
{
|
{
|
||||||
public double Capital, CapTaint, Earned;
|
public double Capital, CapDirty, Earned;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)本金的污点额(信用点),读档迁移时换成 <see cref="CapDirty"/>。</summary>
|
||||||
|
[JsonProperty("CapTaint")] public double LegacyCapTaint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>NPC 客户的一笔存入:扣掉手续费后的数量、存入时的污点额(信用点)、轮数、到期日。</summary>
|
/// <summary>NPC 客户的一笔存入:扣掉手续费后的数量、存入时的污点额(信用点)、轮数、到期日。</summary>
|
||||||
@@ -81,43 +84,39 @@ namespace Decentralized.Domain
|
|||||||
Rating = Remain(RoundRate(Anonymity(price)));
|
Rating = Remain(RoundRate(Anonymity(price)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>注资:币从钱包进本金,污点按价值比例随币走。</summary>
|
/// <summary>注资:币从钱包进本金,按这种币的脏比例带上脏枚数。</summary>
|
||||||
public bool Inject(Wallet w, string asset, double amount, Func<string, double> price)
|
public bool Inject(Wallet w, string asset, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (amount <= 0 || w.Avail(asset) + 1e-9 < amount || !AssetsList.Contains(asset)) return false;
|
if (amount <= 0 || w.Avail(asset) + 1e-9 < amount || !AssetsList.Contains(asset)) return false;
|
||||||
double total = w.Value(price), share = total > 0 ? Math.Min(1, amount * price(asset) / total) : 0;
|
double total = w.Value(price), share = total > 0 ? Math.Min(1, amount * price(asset) / total) : 0;
|
||||||
double taint = w.Taint * share, basis = w.Basis * share;
|
double dirty = amount * w.DirtyRatio(asset), basis = w.Basis * share;
|
||||||
w.Add(asset, -amount); w.Taint -= taint; w.Basis -= basis;
|
w.Add(asset, -amount); w.Basis -= basis;
|
||||||
var p = Pool(asset);
|
var p = Pool(asset);
|
||||||
p.Capital += amount; p.CapTaint += taint;
|
p.Capital += amount; p.CapDirty += dirty;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>取回:不超过 <see cref="Free"/>。先取手续费收入(全额带污点),再取本金(按本金的污点比例)。over 是超出钱包价值、没加进去的污点。</summary>
|
/// <summary>取回:不超过 <see cref="Free"/>。先取手续费收入(整笔是脏的),再取本金(按本金的脏比例)。</summary>
|
||||||
public bool Withdraw(Wallet w, string asset, double amount, Func<string, double> price, out double over)
|
public bool Withdraw(Wallet w, string asset, double amount)
|
||||||
{
|
{
|
||||||
over = 0;
|
|
||||||
var p = Pool(asset);
|
var p = Pool(asset);
|
||||||
if (amount <= 0 || amount > Free(asset) + 1e-9) return false;
|
if (amount <= 0 || amount > Free(asset) + 1e-9) return false;
|
||||||
double fromFees = Math.Min(amount, p.Earned), fromCap = Math.Min(p.Capital, amount - fromFees);
|
double fromFees = Math.Min(amount, p.Earned), fromCap = Math.Min(p.Capital, amount - fromFees);
|
||||||
double capTaint = p.Capital > 1e-12 ? p.CapTaint * fromCap / p.Capital : 0;
|
double capDirty = p.Capital > 1e-12 ? p.CapDirty * fromCap / p.Capital : 0;
|
||||||
p.Earned -= fromFees; p.Capital -= fromCap; p.CapTaint -= capTaint;
|
p.Earned -= fromFees; p.Capital -= fromCap; p.CapDirty -= capDirty;
|
||||||
w.Add(asset, fromFees + fromCap);
|
w.AddDirty(asset, fromFees + fromCap, fromFees + capDirty);
|
||||||
over = w.AddTaintCapped(fromFees * price(asset) + capTaint, price);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>卷款跑路:本金、收入和客户在途的币全部进钱包、全额带污点,永久关闭。返回 (币种, 数量);over 是超出钱包价值的污点。</summary>
|
/// <summary>卷款跑路:本金、收入和客户在途的币全部进钱包,整笔是脏的,永久关闭。返回 (币种, 数量)。</summary>
|
||||||
public List<KeyValuePair<string, double>> Rug(Wallet w, Func<string, double> price, out double over)
|
public List<KeyValuePair<string, double>> Rug(Wallet w)
|
||||||
{
|
{
|
||||||
over = 0;
|
|
||||||
var got = new List<KeyValuePair<string, double>>();
|
var got = new List<KeyValuePair<string, double>>();
|
||||||
foreach (var a in AssetsList)
|
foreach (var a in AssetsList)
|
||||||
{
|
{
|
||||||
double amt = Total(a);
|
double amt = Total(a);
|
||||||
if (amt <= 1e-9) continue;
|
if (amt <= 1e-9) continue;
|
||||||
w.Add(a, amt);
|
w.AddDirty(a, amt, amt);
|
||||||
over += w.AddTaintCapped(amt * price(a), price);
|
|
||||||
got.Add(new KeyValuePair<string, double>(a, amt));
|
got.Add(new KeyValuePair<string, double>(a, amt));
|
||||||
}
|
}
|
||||||
Pools.Clear(); Pending.Clear();
|
Pools.Clear(); Pending.Clear();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,7 +10,9 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
public string Product;
|
public string Product;
|
||||||
public bool Long;
|
public bool Long;
|
||||||
public double Size, Entry, Margin, Taint, Basis;
|
public double Size, Entry, Margin, Basis;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)保证金带的污点额:读档迁移时挪到 1 号钱包,之后为 0(Poinbase 没有污点)。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
|
|
||||||
public double Notional(double price) => Size * price;
|
public double Notional(double price) => Size * price;
|
||||||
public double Pnl(double price) => (Long ? 1 : -1) * Size * (price - Entry);
|
public double Pnl(double price) => (Long ? 1 : -1) * Size * (price - Entry);
|
||||||
@@ -97,13 +100,13 @@ namespace Decentralized.Domain
|
|||||||
double eq0 = (pos?.Margin ?? 0) + margin + (isLong ? 1 : -1) * sizeAll * (spot - entryAll);
|
double eq0 = (pos?.Margin ?? 0) + margin + (isLong ? 1 : -1) * sizeAll * (spot - entryAll);
|
||||||
if (eq0 < (Tuning.PerpMaint + Tuning.PerpOpenBuffer) * sizeAll * spot) return PerpResult.Thin;
|
if (eq0 < (Tuning.PerpMaint + Tuning.PerpOpenBuffer) * sizeAll * spot) return PerpResult.Thin;
|
||||||
double share = Share(acct, margin, pr);
|
double share = Share(acct, margin, pr);
|
||||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
double basis = acct.Basis * share;
|
||||||
acct.Add(Assets.CRC, -(margin + fee)); acct.Taint -= taint; acct.Basis -= basis;
|
acct.Add(Assets.CRC, -(margin + fee)); acct.Basis -= basis;
|
||||||
InsuranceFund += fee * Tuning.PerpFeeToFund;
|
InsuranceFund += fee * Tuning.PerpFeeToFund;
|
||||||
if (pos == null) Positions.Add(pos = new PerpPosition { Product = product, Long = isLong, Entry = price });
|
if (pos == null) Positions.Add(pos = new PerpPosition { Product = product, Long = isLong, Entry = price });
|
||||||
double size = notional / price;
|
double size = notional / price;
|
||||||
pos.Entry = (pos.Size * pos.Entry + size * price) / (pos.Size + size);
|
pos.Entry = (pos.Size * pos.Entry + size * price) / (pos.Size + size);
|
||||||
pos.Size += size; pos.Margin += margin; pos.Taint += taint; pos.Basis += basis;
|
pos.Size += size; pos.Margin += margin; pos.Basis += basis;
|
||||||
return PerpResult.Ok;
|
return PerpResult.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,13 +118,13 @@ namespace Decentralized.Domain
|
|||||||
if (amount <= 0) return PerpResult.Margin;
|
if (amount <= 0) return PerpResult.Margin;
|
||||||
if (acct.Avail(Assets.CRC) + 1e-9 < amount) return PerpResult.Funds;
|
if (acct.Avail(Assets.CRC) + 1e-9 < amount) return PerpResult.Funds;
|
||||||
double share = Share(acct, amount, pr);
|
double share = Share(acct, amount, pr);
|
||||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
double basis = acct.Basis * share;
|
||||||
acct.Add(Assets.CRC, -amount); acct.Taint -= taint; acct.Basis -= basis;
|
acct.Add(Assets.CRC, -amount); acct.Basis -= basis;
|
||||||
pos.Margin += amount; pos.Taint += taint; pos.Basis += basis;
|
pos.Margin += amount; pos.Basis += basis;
|
||||||
return PerpResult.Ok;
|
return PerpResult.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>平仓(按白天的现价):权益减手续费回到账户,污点按剩下的比例退回,盈利是干净的新币。权益不够付时缺口按穿仓处理。返回回到账户的 CRC。</summary>
|
/// <summary>平仓(按白天的现价):权益减手续费回到账户,成本按剩下的比例退回。权益不够付时缺口按穿仓处理。返回回到账户的 CRC。</summary>
|
||||||
public double Close(Wallet acct, string product, double price, int day, out double deficit)
|
public double Close(Wallet acct, string product, double price, int day, out double deficit)
|
||||||
{
|
{
|
||||||
deficit = 0;
|
deficit = 0;
|
||||||
@@ -140,7 +143,7 @@ namespace Decentralized.Domain
|
|||||||
private void Return(Wallet acct, PerpPosition pos, double payout)
|
private void Return(Wallet acct, PerpPosition pos, double payout)
|
||||||
{
|
{
|
||||||
double keep = pos.Margin > 0 ? Math.Min(1, payout / pos.Margin) : 0;
|
double keep = pos.Margin > 0 ? Math.Min(1, payout / pos.Margin) : 0;
|
||||||
acct.Add(Assets.CRC, payout); acct.Taint += pos.Taint * keep; acct.Basis += pos.Basis * keep;
|
acct.Add(Assets.CRC, payout); acct.Basis += pos.Basis * keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>穿仓缺口:保险基金先垫,不够的记成欠款。</summary>
|
/// <summary>穿仓缺口:保险基金先垫,不够的记成欠款。</summary>
|
||||||
@@ -223,8 +226,8 @@ namespace Decentralized.Domain
|
|||||||
if (repay > 1e-9)
|
if (repay > 1e-9)
|
||||||
{
|
{
|
||||||
double share = Share(acct, repay, pr);
|
double share = Share(acct, repay, pr);
|
||||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
double basis = acct.Basis * share;
|
||||||
acct.Add(Assets.CRC, -repay); acct.Taint -= taint; acct.Basis -= basis;
|
acct.Add(Assets.CRC, -repay); acct.Basis -= basis;
|
||||||
Debt -= repay;
|
Debt -= repay;
|
||||||
evs.Add(new PerpEvent { Kind = "repaid", Amount = repay });
|
evs.Add(new PerpEvent { Kind = "repaid", Amount = repay });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
if (!Open) return 0;
|
if (!Open) return 0;
|
||||||
double take = Pool;
|
double take = Pool;
|
||||||
acct.Add(Assets.CRC, take); acct.Taint += take;
|
acct.AddDirty(Assets.CRC, take, take);
|
||||||
Open = false; Done = true; Pool = 0;
|
Open = false; Done = true; Pool = 0;
|
||||||
return take;
|
return take;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
public enum PredictKind { Event, Faction, Purity, Price, Gas, Cra, Era }
|
public enum PredictKind { Event, Faction, Purity, Price, Gas, Cra, Era, Trial }
|
||||||
|
|
||||||
public enum PredictResult { Ok, Closed, Amount, Funds, Cap, Opposite, NoPosition }
|
public enum PredictResult { Ok, Closed, Amount, Funds, Cap, Opposite, NoPosition }
|
||||||
|
|
||||||
@@ -77,7 +78,10 @@ namespace Decentralized.Domain
|
|||||||
/// <summary>持仓所在的钱包地址(下注签名的钱包,结算和卖出都回到它)。</summary>
|
/// <summary>持仓所在的钱包地址(下注签名的钱包,结算和卖出都回到它)。</summary>
|
||||||
public string Wallet;
|
public string Wallet;
|
||||||
public bool Yes;
|
public bool Yes;
|
||||||
public double Shares, Cost, Taint, Basis, Insider;
|
/// <summary>Dirty:下注付出的 CRC 里脏的枚数(兑付时按比例带回)。</summary>
|
||||||
|
public double Shares, Cost, Dirty, Basis, Insider;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>情报贩子卖的内幕消息:对某个盘口给出"是 / 否"的说法,三档准确率,可能是假的(与真相相反)。</summary>
|
/// <summary>情报贩子卖的内幕消息:对某个盘口给出"是 / 否"的说法,三档准确率,可能是假的(与真相相反)。</summary>
|
||||||
@@ -113,13 +117,13 @@ namespace Decentralized.Domain
|
|||||||
public bool Held;
|
public bool Held;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>夜间结算发生的事。Kind:win / lose / void / insider(内幕份额记了污点)/ manip(被判操纵,整笔兑付记了污点)。
|
/// <summary>夜间结算发生的事。Kind:win / lose / void / insider(内幕份额对应的兑付记成脏币)/ manip(被判操纵,整笔兑付记成脏币)。
|
||||||
/// Amount 是兑付或本金;Taint 是实际加上的污点,Over 是超出钱包价值、折成罪证的部分,Fraud 是罪证。</summary>
|
/// Amount 是兑付或本金;Taint 是因此记成脏的 CRC 枚数。</summary>
|
||||||
public sealed class PredictEvent
|
public sealed class PredictEvent
|
||||||
{
|
{
|
||||||
public string Kind, Title;
|
public string Kind, Title;
|
||||||
public PredictMarket Market;
|
public PredictMarket Market;
|
||||||
public double Amount, Taint, Over, Fraud;
|
public double Amount, Taint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>候选盘口(接入层按游戏当前状态给出):先验概率按窗口算。</summary>
|
/// <summary>候选盘口(接入层按游戏当前状态给出):先验概率按窗口算。</summary>
|
||||||
@@ -157,7 +161,7 @@ namespace Decentralized.Domain
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 买入:花 spend(含手续费)的 CRC。污点与成本按花掉的价值比例随资金进持仓。insider:这笔单下单时玩家已经知道答案(传闻纸条、派系特权)。
|
/// 买入:花 spend(含手续费)的 CRC。CRC 的脏枚数按比例、成本按花掉的价值比例随资金进持仓。insider:这笔单下单时玩家已经知道答案(传闻纸条、派系特权)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PredictResult Buy(Wallet acct, PredictMarket m, bool yes, double spend, int day, Func<string, double> pr, bool insider, out double shares)
|
public PredictResult Buy(Wallet acct, PredictMarket m, bool yes, double spend, int day, Func<string, double> pr, bool insider, out double shares)
|
||||||
{
|
{
|
||||||
@@ -172,25 +176,24 @@ namespace Decentralized.Domain
|
|||||||
shares = m.SharesFor(yes, cost);
|
shares = m.SharesFor(yes, cost);
|
||||||
if (all.Sum(x => x.Shares) + shares > m.ShareCap + 1e-9) { shares = 0; return PredictResult.Cap; }
|
if (all.Sum(x => x.Shares) + shares > m.ShareCap + 1e-9) { shares = 0; return PredictResult.Cap; }
|
||||||
double share = Share(acct, spend, pr);
|
double share = Share(acct, spend, pr);
|
||||||
double taint = acct.Taint * share, basis = acct.Basis * share;
|
double dirty = spend * acct.DirtyRatio(Assets.CRC), basis = acct.Basis * share;
|
||||||
acct.Add(Assets.CRC, -spend); acct.Taint -= taint; acct.Basis -= basis;
|
acct.Add(Assets.CRC, -spend); acct.Basis -= basis;
|
||||||
if (yes) m.QYes += shares; else m.QNo += shares;
|
if (yes) m.QYes += shares; else m.QNo += shares;
|
||||||
if (pos == null) Positions.Add(pos = new PredictPos { Market = m.Id, Yes = yes, Wallet = acct.Address });
|
if (pos == null) Positions.Add(pos = new PredictPos { Market = m.Id, Yes = yes, Wallet = acct.Address });
|
||||||
pos.Shares += shares; pos.Cost += cost; pos.Taint += taint; pos.Basis += basis;
|
pos.Shares += shares; pos.Cost += cost; pos.Dirty += dirty; pos.Basis += basis;
|
||||||
if (insider) pos.Insider += shares;
|
if (insider) pos.Insider += shares;
|
||||||
return PredictResult.Ok;
|
return PredictResult.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>全部卖出这个钱包在盘口里的持仓(盘口关闭前):收回 LMSR 的卖价减手续费,污点按比例退回,赚的部分是干净的。返回收回的 CRC。</summary>
|
/// <summary>全部卖出这个钱包在盘口里的持仓(盘口关闭前):收回 LMSR 的卖价减手续费,脏枚数按比例带回,赚的部分是干净的。返回收回的 CRC。</summary>
|
||||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got) => SellAll(acct, m, day, price, out got, out _, out _);
|
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got) => SellAll(acct, m, day, price, out got, out _);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全部卖出;持仓里的内幕份额(下单时已经知道答案)对应的那部分卖出所得记污点(带上限,见 <see cref="Wallet.AddTaintCapped"/>),
|
/// 全部卖出;持仓里的内幕份额(下单时已经知道答案)对应的那部分卖出所得记成脏的 CRC,taint 是记成脏的枚数。先买后卖、赶在结算前离场也一样。
|
||||||
/// taint 是实际加上的污点,over 是超出钱包价值、没加进去的部分(由调用方按 <see cref="Wallet.OverflowFraud"/> 折成罪证)。先买后卖、赶在结算前离场也一样。
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got, out double taint, out double over)
|
public PredictResult SellAll(Wallet acct, PredictMarket m, int day, Func<string, double> price, out double got, out double taint)
|
||||||
{
|
{
|
||||||
got = 0; taint = 0; over = 0;
|
got = 0; taint = 0;
|
||||||
var pos = PosOf(m.Id, acct.Address);
|
var pos = PosOf(m.Id, acct.Address);
|
||||||
if (pos == null) return PredictResult.NoPosition;
|
if (pos == null) return PredictResult.NoPosition;
|
||||||
if (!m.IsOpen(day)) return PredictResult.Closed;
|
if (!m.IsOpen(day)) return PredictResult.Closed;
|
||||||
@@ -198,31 +201,37 @@ namespace Decentralized.Domain
|
|||||||
got = value * (1 - Tuning.PredictFee);
|
got = value * (1 - Tuning.PredictFee);
|
||||||
if (pos.Yes) m.QYes -= pos.Shares; else m.QNo -= pos.Shares;
|
if (pos.Yes) m.QYes -= pos.Shares; else m.QNo -= pos.Shares;
|
||||||
Positions.Remove(pos);
|
Positions.Remove(pos);
|
||||||
Pay(acct, pos, got);
|
double back = Pay(acct, pos, got);
|
||||||
over = MarkInsider(acct, pos, got, price, out taint);
|
taint = MarkInsider(acct, pos, got, back);
|
||||||
return PredictResult.Ok;
|
return PredictResult.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Pay(Wallet acct, PredictPos pos, double payout)
|
/// <summary>兑付进钱包:下注时带进来的脏枚数按兑付占成本的比例带回(不超过兑付)。返回带回的脏枚数。</summary>
|
||||||
|
private static double Pay(Wallet acct, PredictPos pos, double payout)
|
||||||
{
|
{
|
||||||
double keep = pos.Cost > 0 ? Math.Min(1, payout / pos.Cost) : 0;
|
double keep = pos.Cost > 0 ? Math.Min(1, payout / pos.Cost) : 0;
|
||||||
acct.Add(Assets.CRC, payout); acct.Taint += pos.Taint * keep; acct.Basis += pos.Basis * keep;
|
double dirty = Math.Min(payout, pos.Dirty * keep);
|
||||||
|
acct.AddDirty(Assets.CRC, payout, dirty); acct.Basis += pos.Basis * keep;
|
||||||
|
return dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>内幕份额对应的兑付记污点(带上限)。taint 是实际加上的污点,返回超出钱包价值、没加进去的部分。</summary>
|
/// <summary>这笔兑付里还干净的部分(兑付 − 已经带回的脏枚数)里,再记 qty 枚为脏的。返回记上的枚数。</summary>
|
||||||
private static double MarkInsider(Wallet acct, PredictPos pos, double payout, Func<string, double> price, out double taint)
|
private static double MarkPayout(Wallet acct, double payout, double alreadyDirty, double qty)
|
||||||
|
{
|
||||||
|
double mark = Math.Max(0, Math.Min(qty, payout - alreadyDirty));
|
||||||
|
return mark - acct.MarkDirty(Assets.CRC, mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>内幕份额对应的兑付记成脏的 CRC。返回记上的枚数。</summary>
|
||||||
|
private static double MarkInsider(Wallet acct, PredictPos pos, double payout, double alreadyDirty)
|
||||||
{
|
{
|
||||||
taint = 0;
|
|
||||||
if (pos.Insider <= 0 || pos.Shares <= 0 || payout <= 0) return 0;
|
if (pos.Insider <= 0 || pos.Shares <= 0 || payout <= 0) return 0;
|
||||||
double amount = payout * Math.Min(1, pos.Insider / pos.Shares);
|
return MarkPayout(acct, payout, alreadyDirty, payout * Math.Min(1, pos.Insider / pos.Shares));
|
||||||
double over = acct.AddTaintCapped(amount, price);
|
|
||||||
taint = amount - over;
|
|
||||||
return over;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 夜间:先登记今晚的观测,再结算 ToDay 到了的盘口(赢的钱回到下注的钱包,wallet 按地址找)。outcome 由接入层给出(事件 / 派系读观测,纯度和行情读游戏数值),null 表示拿不到数据。
|
/// 夜间:先登记今晚的观测,再结算 ToDay 到了的盘口(赢的钱回到下注的钱包,wallet 按地址找)。outcome 由接入层给出(事件 / 派系读观测,纯度和行情读游戏数值),null 表示拿不到数据。
|
||||||
/// 赢家每份兑付 1 信用点,照常兑付;内幕份额对应的兑付记污点,行情盘被判操纵时整笔兑付记污点(都带上限,超出钱包价值的部分折成罪证)。
|
/// 赢家每份兑付 1 信用点,照常兑付;内幕份额对应的兑付记成脏的 CRC,行情盘被判操纵时整笔兑付都记成脏的。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<PredictEvent> Night(int day, IEnumerable<string> activeNow, Func<PredictMarket, bool?> outcome, Func<string, Wallet> wallet, Func<string, double> price, Rng rng, double push = 0)
|
public List<PredictEvent> Night(int day, IEnumerable<string> activeNow, Func<PredictMarket, bool?> outcome, Func<string, Wallet> wallet, Func<string, double> price, Rng rng, double push = 0)
|
||||||
{
|
{
|
||||||
@@ -258,27 +267,20 @@ namespace Decentralized.Domain
|
|||||||
else if (winners.Count > 0)
|
else if (winners.Count > 0)
|
||||||
{
|
{
|
||||||
double payout = winners.Sum(x => x.Shares), profit = payout - cost;
|
double payout = winners.Sum(x => x.Shares), profit = payout - cost;
|
||||||
// 操纵:行情盘上,赢家的方向和玩家推价的方向一致时按推价幅度被查——照常兑付,整笔兑付记污点
|
// 操纵:行情盘上,赢家的方向和玩家推价的方向一致时按推价幅度被查——照常兑付,整笔兑付记成脏的
|
||||||
bool manip = m.Kind == PredictKind.Price && winners.Any(x => x.Yes ? push > 0 : push < 0) && rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(day)));
|
bool manip = m.Kind == PredictKind.Price && winners.Any(x => x.Yes ? push > 0 : push < 0) && rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(day)));
|
||||||
double taint = 0, over = 0;
|
double taint = 0;
|
||||||
|
bool insider = false;
|
||||||
foreach (var pos in winners)
|
foreach (var pos in winners)
|
||||||
{
|
{
|
||||||
var w = wallet(pos.Wallet);
|
var w = wallet(pos.Wallet);
|
||||||
Pay(w, pos, pos.Shares);
|
double back = Pay(w, pos, pos.Shares);
|
||||||
if (manip)
|
// 内幕份额(下单时已经知道答案)对应的兑付记成脏的,每个钱包各算各的
|
||||||
{
|
if (manip) taint += MarkPayout(w, pos.Shares, back, pos.Shares);
|
||||||
double o = w.AddTaintCapped(pos.Shares, price);
|
else if (pos.Insider > 0) { insider = true; taint += MarkInsider(w, pos, pos.Shares, back); }
|
||||||
taint += pos.Shares - o; over += o;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 内幕份额(下单时已经知道答案)对应的兑付记污点,每个钱包各算各的
|
|
||||||
over += MarkInsider(w, pos, pos.Shares, price, out double t);
|
|
||||||
taint += t;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
string kind = manip ? "manip" : taint + over > 1e-9 ? "insider" : "win";
|
string kind = manip ? "manip" : insider ? "insider" : "win";
|
||||||
evs.Add(new PredictEvent { Kind = kind, Title = m.Title, Market = m, Amount = payout, Taint = taint, Over = over, Fraud = Wallet.OverflowFraud(over) });
|
evs.Add(new PredictEvent { Kind = kind, Title = m.Title, Market = m, Amount = payout, Taint = taint });
|
||||||
Record(day, m, m.Outcome, profit, true);
|
Record(day, m, m.Outcome, profit, true);
|
||||||
}
|
}
|
||||||
else Record(day, m, m.Outcome, 0, false);
|
else Record(day, m, m.Outcome, 0, false);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -34,14 +35,22 @@ namespace Decentralized.Domain
|
|||||||
public double Rate, Reserve, Cap;
|
public double Rate, Reserve, Cap;
|
||||||
public bool Timelock, Audited, Scam, Closed;
|
public bool Timelock, Audited, Scam, Closed;
|
||||||
public Dictionary<string, double> Deposits = new Dictionary<string, double>();
|
public Dictionary<string, double> Deposits = new Dictionary<string, double>();
|
||||||
public Dictionary<string, double> Taint = new Dictionary<string, double>(), Basis = new Dictionary<string, double>();
|
/// <summary>每个钱包存入的 CRC 里脏的枚数、成本:取出时带回。</summary>
|
||||||
|
public Dictionary<string, double> Dirty = new Dictionary<string, double>(), Basis = new Dictionary<string, double>();
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public Dictionary<string, double> LegacyTaint = new Dictionary<string, double>();
|
||||||
/// <summary>时间锁池子的取款队列:钱包 → (到账日, 数额)。</summary>
|
/// <summary>时间锁池子的取款队列:钱包 → (到账日, 数额)。</summary>
|
||||||
public List<YieldWithdraw> Pending = new List<YieldWithdraw>();
|
public List<YieldWithdraw> Pending = new List<YieldWithdraw>();
|
||||||
public double Total => Deposits.Values.Sum();
|
public double Total => Deposits.Values.Sum();
|
||||||
public double Of(string wallet) => Deposits.TryGetValue(wallet, out var v) ? v : 0;
|
public double Of(string wallet) => Deposits.TryGetValue(wallet, out var v) ? v : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class YieldWithdraw { public string Wallet; public int Day; public double Amount, Taint, Basis; }
|
public sealed class YieldWithdraw
|
||||||
|
{
|
||||||
|
public string Wallet; public int Day; public double Amount, Dirty, Basis;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>夜间发生的事。Kind:drain(钓鱼授权转走)/ rug(收益池跑路)/ dry(正规池储备耗尽,退本金)/ paid(取款到账)/ wickback(插针回去了)。</summary>
|
/// <summary>夜间发生的事。Kind:drain(钓鱼授权转走)/ rug(收益池跑路)/ dry(正规池储备耗尽,退本金)/ paid(取款到账)/ wickback(插针回去了)。</summary>
|
||||||
public sealed class ScamEvent
|
public sealed class ScamEvent
|
||||||
@@ -151,10 +160,10 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
if (p.Closed || amount <= 0 || w.Avail(Assets.CRC) + 1e-9 < amount || p.Total + amount > p.Cap + 1e-9) return false;
|
if (p.Closed || amount <= 0 || w.Avail(Assets.CRC) + 1e-9 < amount || p.Total + amount > p.Cap + 1e-9) return false;
|
||||||
double total = w.Value(pr), share = total > 0 ? Math.Min(1, amount * pr(Assets.CRC) / total) : 0;
|
double total = w.Value(pr), share = total > 0 ? Math.Min(1, amount * pr(Assets.CRC) / total) : 0;
|
||||||
double taint = w.Taint * share, basis = w.Basis * share;
|
double dirty = amount * w.DirtyRatio(Assets.CRC), basis = w.Basis * share;
|
||||||
w.Add(Assets.CRC, -amount); w.Taint -= taint; w.Basis -= basis;
|
w.Add(Assets.CRC, -amount); w.Basis -= basis;
|
||||||
p.Deposits[w.Address] = p.Of(w.Address) + amount;
|
p.Deposits[w.Address] = p.Of(w.Address) + amount;
|
||||||
p.Taint[w.Address] = (p.Taint.TryGetValue(w.Address, out var t) ? t : 0) + taint;
|
p.Dirty[w.Address] = (p.Dirty.TryGetValue(w.Address, out var t) ? t : 0) + dirty;
|
||||||
p.Basis[w.Address] = (p.Basis.TryGetValue(w.Address, out var b) ? b : 0) + basis;
|
p.Basis[w.Address] = (p.Basis.TryGetValue(w.Address, out var b) ? b : 0) + basis;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -164,16 +173,16 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
double amt = p.Of(w.Address);
|
double amt = p.Of(w.Address);
|
||||||
if (amt <= 0 || p.Closed) return 0;
|
if (amt <= 0 || p.Closed) return 0;
|
||||||
double taint = p.Taint.TryGetValue(w.Address, out var t) ? t : 0, basis = p.Basis.TryGetValue(w.Address, out var b) ? b : 0;
|
double dirty = p.Dirty.TryGetValue(w.Address, out var t) ? t : 0, basis = p.Basis.TryGetValue(w.Address, out var b) ? b : 0;
|
||||||
p.Deposits.Remove(w.Address); p.Taint.Remove(w.Address); p.Basis.Remove(w.Address);
|
p.Deposits.Remove(w.Address); p.Dirty.Remove(w.Address); p.Basis.Remove(w.Address);
|
||||||
if (p.Timelock) { p.Pending.Add(new YieldWithdraw { Wallet = w.Address, Day = day + Tuning.YieldLockDays, Amount = amt, Taint = taint, Basis = basis }); return 0; }
|
if (p.Timelock) { p.Pending.Add(new YieldWithdraw { Wallet = w.Address, Day = day + Tuning.YieldLockDays, Amount = amt, Dirty = dirty, Basis = basis }); return 0; }
|
||||||
Pay(w, amt, taint, basis);
|
Pay(w, amt, dirty, basis);
|
||||||
return amt;
|
return amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Pay(Wallet w, double amt, double taint, double basis)
|
private static void Pay(Wallet w, double amt, double dirty, double basis)
|
||||||
{
|
{
|
||||||
w.Add(Assets.CRC, amt); w.Taint += taint; w.Basis += basis;
|
w.AddDirty(Assets.CRC, amt, dirty); w.Basis += basis;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ——— 夜间 ———
|
// ——— 夜间 ———
|
||||||
@@ -209,7 +218,7 @@ namespace Decentralized.Domain
|
|||||||
foreach (var kv in p.Deposits.ToList())
|
foreach (var kv in p.Deposits.ToList())
|
||||||
{
|
{
|
||||||
var w = own(kv.Key);
|
var w = own(kv.Key);
|
||||||
if (w != null) Pay(w, kv.Value, p.Taint.TryGetValue(kv.Key, out var t) ? t : 0, p.Basis.TryGetValue(kv.Key, out var b) ? b : 0);
|
if (w != null) Pay(w, kv.Value, p.Dirty.TryGetValue(kv.Key, out var t) ? t : 0, p.Basis.TryGetValue(kv.Key, out var b) ? b : 0);
|
||||||
evs.Add(new ScamEvent { Kind = "dry", Name = p.Name, Wallet = kv.Key, Asset = Assets.CRC, Amount = kv.Value });
|
evs.Add(new ScamEvent { Kind = "dry", Name = p.Name, Wallet = kv.Key, Asset = Assets.CRC, Amount = kv.Value });
|
||||||
}
|
}
|
||||||
p.Deposits.Clear(); p.Closed = true;
|
p.Deposits.Clear(); p.Closed = true;
|
||||||
@@ -223,7 +232,7 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
p.Pending.Remove(q);
|
p.Pending.Remove(q);
|
||||||
var w = own(q.Wallet);
|
var w = own(q.Wallet);
|
||||||
if (w != null) Pay(w, q.Amount, q.Taint, q.Basis);
|
if (w != null) Pay(w, q.Amount, q.Dirty, q.Basis);
|
||||||
evs.Add(new ScamEvent { Kind = "paid", Name = p.Name, Wallet = q.Wallet, Asset = Assets.CRC, Amount = q.Amount });
|
evs.Add(new ScamEvent { Kind = "paid", Name = p.Name, Wallet = q.Wallet, Asset = Assets.CRC, Amount = q.Amount });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace Decentralized.Domain
|
|||||||
public string Wallet;
|
public string Wallet;
|
||||||
public bool Mint;
|
public bool Mint;
|
||||||
public double Cra, Crc, Spark, C;
|
public double Cra, Crc, Spark, C;
|
||||||
|
/// <summary>付出去的币的脏比例(按价值加权):到期换回的币按这个比例是脏的。</summary>
|
||||||
|
public double DirtyRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CraOrderEvent
|
public sealed class CraOrderEvent
|
||||||
@@ -114,8 +116,10 @@ namespace Decentralized.Domain
|
|||||||
if (cra <= 0) return null;
|
if (cra <= 0) return null;
|
||||||
Collateral(cra, out double crc, out double spark);
|
Collateral(cra, out double crc, out double spark);
|
||||||
if (w.Avail(Assets.CRC) + 1e-9 < crc || w.Avail(Assets.SPARK) + 1e-9 < spark) return null;
|
if (w.Avail(Assets.CRC) + 1e-9 < crc || w.Avail(Assets.SPARK) + 1e-9 < spark) return null;
|
||||||
|
double sv = spark * Spark, total = crc + sv;
|
||||||
|
double ratio = total > 0 ? (crc * w.DirtyRatio(Assets.CRC) + sv * w.DirtyRatio(Assets.SPARK)) / total : 0;
|
||||||
w.Add(Assets.CRC, -crc); w.Add(Assets.SPARK, -spark);
|
w.Add(Assets.CRC, -crc); w.Add(Assets.SPARK, -spark);
|
||||||
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = true, Cra = cra, Crc = crc, Spark = spark, C = C, Due = day + rng.Range(Tuning.CraMintDaysMin, Tuning.CraMintDaysMax) };
|
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = true, Cra = cra, Crc = crc, Spark = spark, C = C, DirtyRatio = ratio, Due = day + rng.Range(Tuning.CraMintDaysMin, Tuning.CraMintDaysMax) };
|
||||||
Orders.Add(o);
|
Orders.Add(o);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -124,8 +128,9 @@ namespace Decentralized.Domain
|
|||||||
public CraOrder RequestBurn(Wallet w, double cra, int day)
|
public CraOrder RequestBurn(Wallet w, double cra, int day)
|
||||||
{
|
{
|
||||||
if (cra <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return null;
|
if (cra <= 0 || w.Avail(Assets.CRA) + 1e-9 < cra) return null;
|
||||||
|
double ratio = w.DirtyRatio(Assets.CRA);
|
||||||
w.Add(Assets.CRA, -cra);
|
w.Add(Assets.CRA, -cra);
|
||||||
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = false, Cra = cra, C = C, Due = day + Tuning.CraUnlockDays };
|
var o = new CraOrder { Id = ++OrderSeq, Wallet = w.Address, Mint = false, Cra = cra, C = C, DirtyRatio = ratio, Due = day + Tuning.CraUnlockDays };
|
||||||
Orders.Add(o);
|
Orders.Add(o);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
/// <summary>一个钱包在革命军质押池里的仓位:计息的本金、排队等解锁的部分,以及存入时带来的污点与成本。</summary>
|
/// <summary>一个钱包在革命军质押池里的仓位:计息的本金、排队等解锁的部分,以及存入时带来的脏枚数与成本(利息是干净的)。</summary>
|
||||||
public sealed class StakeLot
|
public sealed class StakeLot
|
||||||
{
|
{
|
||||||
public string Wallet;
|
public string Wallet;
|
||||||
public double Amount;
|
public double Amount;
|
||||||
public List<KeyValuePair<int, double>> Unlocking = new List<KeyValuePair<int, double>>();
|
public List<KeyValuePair<int, double>> Unlocking = new List<KeyValuePair<int, double>>();
|
||||||
public double Taint, Basis;
|
public double Dirty, Basis;
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)的污点额(信用点),读档迁移时换成 <see cref="Dirty"/>。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
|
|
||||||
public double Total => Amount + Unlocking.Sum(u => u.Value);
|
public double Total => Amount + Unlocking.Sum(u => u.Value);
|
||||||
}
|
}
|
||||||
@@ -36,16 +39,16 @@ namespace Decentralized.Domain
|
|||||||
/// <summary>全部计息中的质押量,补贴池按它算支出。</summary>
|
/// <summary>全部计息中的质押量,补贴池按它算支出。</summary>
|
||||||
public double Earning => Lots.Sum(l => l.Amount);
|
public double Earning => Lots.Sum(l => l.Amount);
|
||||||
|
|
||||||
/// <summary>质押:从钱包取出 CRA,污点与成本按价值比例随币留在仓位里。余额不足返回 false。</summary>
|
/// <summary>质押:从钱包取出 CRA,脏枚数按 CRA 的脏比例、成本按价值比例随币留在仓位里。余额不足返回 false。</summary>
|
||||||
public bool Stake(Wallet w, double amount, Func<string, double> price)
|
public bool Stake(Wallet w, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (amount <= 0 || w.Avail(Assets.CRA) + 1e-9 < amount) return false;
|
if (amount <= 0 || w.Avail(Assets.CRA) + 1e-9 < amount) return false;
|
||||||
double total = w.Value(price);
|
double total = w.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1, amount * price(Assets.CRA) / total) : 0;
|
double share = total > 0 ? Math.Min(1, amount * price(Assets.CRA) / total) : 0;
|
||||||
double taint = w.Taint * share, basis = w.Basis * share;
|
double dirty = amount * w.DirtyRatio(Assets.CRA), basis = w.Basis * share;
|
||||||
w.Add(Assets.CRA, -amount); w.Taint -= taint; w.Basis -= basis;
|
w.Add(Assets.CRA, -amount); w.Basis -= basis;
|
||||||
var lot = Of(w.Address) ?? AddLot(w.Address);
|
var lot = Of(w.Address) ?? AddLot(w.Address);
|
||||||
lot.Amount += amount; lot.Taint += taint; lot.Basis += basis;
|
lot.Amount += amount; lot.Dirty += dirty; lot.Basis += basis;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +77,11 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
double total = lot.Total;
|
double total = lot.Total;
|
||||||
double share = total > 0 ? Math.Min(1, u.Value / total) : 0;
|
double share = total > 0 ? Math.Min(1, u.Value / total) : 0;
|
||||||
double taint = lot.Taint * share, basis = lot.Basis * share;
|
double dirty = lot.Dirty * share, basis = lot.Basis * share;
|
||||||
lot.Taint -= taint; lot.Basis -= basis;
|
lot.Dirty -= dirty; lot.Basis -= basis;
|
||||||
lot.Unlocking.Remove(u);
|
lot.Unlocking.Remove(u);
|
||||||
var w = wallet(lot.Wallet);
|
var w = wallet(lot.Wallet);
|
||||||
w.Add(Assets.CRA, u.Value); w.Taint += taint; w.Basis += basis;
|
w.AddDirty(Assets.CRA, u.Value, dirty); w.Basis += basis;
|
||||||
ev.Released += u.Value;
|
ev.Released += u.Value;
|
||||||
}
|
}
|
||||||
if (lot.Total < 1e-9) Lots.Remove(lot);
|
if (lot.Total < 1e-9) Lots.Remove(lot);
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ namespace Decentralized.Domain
|
|||||||
public double CrcDepeg = 1, CrcHaircut = 1, CrtDepeg = 1, CrtFreeze = 1;
|
public double CrcDepeg = 1, CrcHaircut = 1, CrtDepeg = 1, CrtFreeze = 1;
|
||||||
/// <summary>到这一天之前 CRA 螺旋概率减半。</summary>
|
/// <summary>到这一天之前 CRA 螺旋概率减半。</summary>
|
||||||
public int CraSafeUntil = -1;
|
public int CraSafeUntil = -1;
|
||||||
/// <summary>治安部整顿到这一天:出金审查命中率、混币器制裁概率、操纵与内幕查处概率上调。</summary>
|
/// <summary>治安部整顿到这一天:混币器清洗变差,制裁概率、操纵查处概率上调。</summary>
|
||||||
public int SecUntil = -1;
|
public int SecUntil = -1;
|
||||||
/// <summary>伦警官被捕后的立威期到这一天:出金审查、操纵、内幕查处概率上调。</summary>
|
/// <summary>伦警官被捕后的立威期到这一天:操纵查处概率、换币客户里便衣的概率上调。</summary>
|
||||||
public int LunUntil = -1;
|
public int LunUntil = -1;
|
||||||
/// <summary>SPARK 每晚额外乘的倍数,还剩几晚。</summary>
|
/// <summary>SPARK 每晚额外乘的倍数,还剩几晚。</summary>
|
||||||
public double SparkPush = 1;
|
public double SparkPush = 1;
|
||||||
@@ -27,13 +27,20 @@ namespace Decentralized.Domain
|
|||||||
/// <summary>混币器:手续费、匿名集(NPC 混币量)、跑路概率的倍率;被举报后永久关闭(在途的照常提回,不能再存)。</summary>
|
/// <summary>混币器:手续费、匿名集(NPC 混币量)、跑路概率的倍率;被举报后永久关闭(在途的照常提回,不能再存)。</summary>
|
||||||
public double MixerFee = 1, MixerVolume = 1, MixerRug = 1;
|
public double MixerFee = 1, MixerVolume = 1, MixerRug = 1;
|
||||||
public bool MixerClosed;
|
public bool MixerClosed;
|
||||||
|
/// <summary>混币器换皮重开过(换了名字、地址);重开的是治安部的钓鱼混币器(提回的币一律被标记)。</summary>
|
||||||
|
public bool MixerRebranded, MixerHoneypot;
|
||||||
/// <summary>本 mod 自己的剧情线:混币器运营者 Tumbler。</summary>
|
/// <summary>本 mod 自己的剧情线:混币器运营者 Tumbler。</summary>
|
||||||
public Tumbler Tumbler = new Tumbler();
|
public Tumbler Tumbler = new Tumbler();
|
||||||
|
/// <summary>Tumbler 四次上门之后的剧情:探员、泄露、审判、黑市跑路、报复、长期联系人、换皮重开。</summary>
|
||||||
|
public TumblerAfter After = new TumblerAfter();
|
||||||
|
|
||||||
public bool Has(string key) => Applied.Contains(key);
|
public bool Has(string key) => Applied.Contains(key);
|
||||||
|
|
||||||
public double CraSpiral(int day) => day < CraSafeUntil ? Tuning.StoryCraSpiralMult : 1;
|
public double CraSpiral(int day) => day < CraSafeUntil ? Tuning.StoryCraSpiralMult : 1;
|
||||||
public double Aml(int day) => (day < SecUntil ? Tuning.StorySecAmlMult : 1) * (day < LunUntil ? Tuning.StoryLunMult : 1);
|
/// <summary>混币器每轮清洗率的倍率(治安部监控资金流向期间洗得更差)。</summary>
|
||||||
|
public double MixClean(int day) => day < SecUntil ? Tuning.StorySecMixClean : 1;
|
||||||
|
/// <summary>换币客户里便衣概率的倍率(伦警官被捕后的立威期)。</summary>
|
||||||
|
public double OtcSting(int day) => day < LunUntil ? Tuning.StoryLunMult : 1;
|
||||||
public double Sanction(int day) => day < SecUntil ? Tuning.StorySecSanctionMult : 1;
|
public double Sanction(int day) => day < SecUntil ? Tuning.StorySecSanctionMult : 1;
|
||||||
/// <summary>操纵检出、内幕查处的概率倍率。</summary>
|
/// <summary>操纵检出、内幕查处的概率倍率。</summary>
|
||||||
public double Enforce(int day) => (day < SecUntil ? Tuning.StorySecEnforceMult : 1) * (day < LunUntil ? Tuning.StoryLunMult : 1);
|
public double Enforce(int day) => (day < SecUntil ? Tuning.StorySecEnforceMult : 1) * (day < LunUntil ? Tuning.StoryLunMult : 1);
|
||||||
@@ -85,10 +92,23 @@ namespace Decentralized.Domain
|
|||||||
case "tumbler_sold":
|
case "tumbler_sold":
|
||||||
MixerFee *= Tuning.TumblerSoldFee; MixerRug *= Tuning.TumblerSoldRug;
|
MixerFee *= Tuning.TumblerSoldFee; MixerRug *= Tuning.TumblerSoldRug;
|
||||||
break;
|
break;
|
||||||
|
case "tumbler_bm_rug":
|
||||||
|
MixerClosed = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>混币器换皮重开:重新开放,费率、匿名集、跑路倍率回到 1;钓鱼混币器的费率打折(引人上钩)。</summary>
|
||||||
|
public void Rebrand(bool honeypot)
|
||||||
|
{
|
||||||
|
MixerClosed = false;
|
||||||
|
MixerRebranded = true;
|
||||||
|
MixerHoneypot = honeypot;
|
||||||
|
MixerFee = honeypot ? Tuning.TumblerHoneypotFee : 1;
|
||||||
|
MixerVolume = 1; MixerRug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>SPARK 在接下来几晚里一共涨到 total 倍(每晚乘相同的倍数)。</summary>
|
/// <summary>SPARK 在接下来几晚里一共涨到 total 倍(每晚乘相同的倍数)。</summary>
|
||||||
private void PushSpark(double total)
|
private void PushSpark(double total)
|
||||||
{
|
{
|
||||||
@@ -110,6 +130,8 @@ namespace Decentralized.Domain
|
|||||||
public const int Hide = 1, Report = 2, Sell = 3;
|
public const int Hide = 1, Report = 2, Sell = 3;
|
||||||
public int StartDay = -1, Stage, Choice, VisitedDay = -1;
|
public int StartDay = -1, Stage, Choice, VisitedDay = -1;
|
||||||
public bool Done;
|
public bool Done;
|
||||||
|
/// <summary>Tumbler 的外观(第一次上门时随机定下,之后每次都一样)。</summary>
|
||||||
|
public string Sprite;
|
||||||
|
|
||||||
/// <summary>第几次上门在哪一天(相对开始日)。</summary>
|
/// <summary>第几次上门在哪一天(相对开始日)。</summary>
|
||||||
public static readonly int[] Offsets = { 0, 3, 5, 9 };
|
public static readonly int[] Offsets = { 0, 3, 5, 9 };
|
||||||
@@ -124,11 +146,16 @@ namespace Decentralized.Domain
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>今天该上门的是第几次(1–4),没有就返回 0(第 4 次举报过的话由接入层改成新闻:他被抓了)。</summary>
|
/// <summary>
|
||||||
public int Due(int day)
|
/// 今天该上门的是第几次(1–4),没有就返回 0(第 4 次举报过的话由接入层改成新闻:他被抓了)。
|
||||||
|
/// after 不为空时:第 3 次要等治安部探员来过(第二天起),配合过探员又选了藏的,第 4 次要等搜查过(第二天起)。
|
||||||
|
/// </summary>
|
||||||
|
public int Due(int day, TumblerAfter after = null)
|
||||||
{
|
{
|
||||||
if (Done || StartDay < 0 || Stage >= Offsets.Length || VisitedDay == day) return 0;
|
if (Done || StartDay < 0 || Stage >= Offsets.Length || VisitedDay == day) return 0;
|
||||||
if (day < NextVisitDay) return 0;
|
if (day < NextVisitDay) return 0;
|
||||||
|
if (after != null && Stage == 2 && (after.Agent == 0 || day <= after.AgentDay)) return 0;
|
||||||
|
if (after != null && Stage == 3 && after.NeedSearch(this) && (!after.Searched || day <= after.SearchDay)) return 0;
|
||||||
return Stage + 1;
|
return Stage + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,4 +167,95 @@ namespace Decentralized.Domain
|
|||||||
Done = Stage >= Offsets.Length;
|
Done = Stage >= Offsets.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tumbler 四次上门之后的剧情(原来的进度类不动):
|
||||||
|
/// 治安部探员在第 2、3 次上门之间来一次(配合 / 否认);配合过又选了藏的,第 4 次前一天来搜查;
|
||||||
|
/// 举报、被搜走、第 4 次盘不在手上 → 密钥落到治安部,混币记录泄露;举报 → 审判盘;卖给黑市 → 黑市跑路;
|
||||||
|
/// 无罪获释、黑市跑路 → Tumbler 报复;藏好归还 → 长期联系人;混币器关停若干天后换皮重开。只记进度,对话、物品、夜间效果在接入层。
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TumblerAfter
|
||||||
|
{
|
||||||
|
public const int Cooperate = 1, Deny = 2;
|
||||||
|
/// <summary>探员上门的结果(0 = 还没来)和那一天。</summary>
|
||||||
|
public int Agent, AgentDay = -1;
|
||||||
|
/// <summary>探员的外观(问话和搜查是同一个人)。</summary>
|
||||||
|
public string AgentSprite;
|
||||||
|
/// <summary>搜查过(不管有没有搜到)、搜走了密钥盘、哪一天。</summary>
|
||||||
|
public bool Searched, Seized;
|
||||||
|
public int SearchDay = -1;
|
||||||
|
/// <summary>哪一晚泄露(-1 = 没安排);已经泄露过(整局一次)。</summary>
|
||||||
|
public int LeakDay = -1;
|
||||||
|
public bool Leaked;
|
||||||
|
/// <summary>藏好并归还:成为长期联系人;已经提示过的镇压开始日。</summary>
|
||||||
|
public bool Contact;
|
||||||
|
public List<int> Tipped = new List<int>();
|
||||||
|
/// <summary>审判:开盘日、宣判日、判决(1 定罪,0 无罪,-1 没有审判);每晚的庭审新闻偏向(true = 控方占上风);最后一条新闻是哪晚。</summary>
|
||||||
|
public int TrialOpenDay = -1, TrialDay = -1, Verdict = -1, HintDay = -1;
|
||||||
|
public List<bool> Hints = new List<bool>();
|
||||||
|
public bool TrialMarket, TrialDone;
|
||||||
|
/// <summary>报复在哪一晚(-1 = 没有)、已经报复过。</summary>
|
||||||
|
public int RevengeDay = -1;
|
||||||
|
public bool Revenged;
|
||||||
|
/// <summary>黑市卷款跑路在哪一晚(-1 = 没有)、已经跑路。</summary>
|
||||||
|
public int BmRugDay = -1;
|
||||||
|
public bool BmRugged;
|
||||||
|
/// <summary>混币器关停的那天(-1 = 没关停);换皮重开过。</summary>
|
||||||
|
public int ClosedDay = -1;
|
||||||
|
public bool Rebranded;
|
||||||
|
|
||||||
|
/// <summary>探员今天该不该来:第 2 次上门之后的第二天起,还没来过。</summary>
|
||||||
|
public bool AgentDue(Tumbler t, int day) => !t.Done && t.Stage == 2 && Agent == 0 && day > t.VisitedDay;
|
||||||
|
|
||||||
|
/// <summary>配合过探员、又选了藏,第 4 次上门前要先来搜查。</summary>
|
||||||
|
public bool NeedSearch(Tumbler t) => Agent == Cooperate && t.Choice == Tumbler.Hide;
|
||||||
|
|
||||||
|
/// <summary>搜查今天该不该来:第 4 次上门的前一天起(第 3 次之后的第二天起)。</summary>
|
||||||
|
public bool SearchDue(Tumbler t, int day) => !t.Done && t.Stage == 3 && NeedSearch(t) && !Searched && day >= t.NextVisitDay - 1 && day > t.VisitedDay;
|
||||||
|
|
||||||
|
/// <summary>安排今晚泄露(整局一次)。</summary>
|
||||||
|
public void LeakTonight(int day)
|
||||||
|
{
|
||||||
|
if (!Leaked && LeakDay < 0) LeakDay = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>举报:掷出判决,安排开盘和宣判;混币器从今天起关停。</summary>
|
||||||
|
public void StartTrial(int day, Rng rng)
|
||||||
|
{
|
||||||
|
if (Verdict >= 0) return;
|
||||||
|
Verdict = rng.Chance(Tuning.TumblerTrialConvict) ? 1 : 0;
|
||||||
|
TrialOpenDay = day + Tuning.TumblerTrialOpen;
|
||||||
|
TrialDay = day + Tuning.TumblerTrialDays;
|
||||||
|
ClosedDay = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>今晚的庭审新闻(开盘前一晚起到宣判前一晚,每晚一条):偏向真实判决的概率 HintAcc。没有就返回 null。</summary>
|
||||||
|
public bool? Hint(int day, Rng rng)
|
||||||
|
{
|
||||||
|
if (Verdict < 0 || TrialDone || day < TrialOpenDay - 1 || day >= TrialDay || HintDay >= day) return null;
|
||||||
|
HintDay = day;
|
||||||
|
bool truth = Verdict == 1;
|
||||||
|
bool h = rng.Chance(Tuning.TumblerTrialHintAcc) ? truth : !truth;
|
||||||
|
Hints.Add(h);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>公开信息下的定罪概率:先验按已经登出的庭审新闻做贝叶斯更新。</summary>
|
||||||
|
public double TrialPublic()
|
||||||
|
{
|
||||||
|
double acc = Tuning.TumblerTrialHintAcc, lr = Math.Log(acc / (1 - acc)), p0 = Tuning.TumblerTrialConvict;
|
||||||
|
double l = Math.Log(p0 / (1 - p0));
|
||||||
|
foreach (var h in Hints) l += h ? lr : -lr;
|
||||||
|
return 1 / (1 + Math.Exp(-l));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>卖给黑市:安排黑市卷款跑路的那一晚。</summary>
|
||||||
|
public void StartSold(int day, Rng rng)
|
||||||
|
{
|
||||||
|
if (BmRugDay < 0) BmRugDay = day + rng.Range(Tuning.TumblerBmRugMin, Tuning.TumblerBmRugMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>今晚该不该换皮重开:关停满 RebrandDays 天,只一次。</summary>
|
||||||
|
public bool RebrandDue(int day) => !Rebranded && ClosedDay >= 0 && day >= ClosedDay + Tuning.TumblerRebrandDays;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Decentralized.Domain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 存档迁移(数据版本 5):旧存档的污点是一笔信用点(整个钱包、托管里各一笔),换成按币种记的脏枚数。
|
||||||
|
/// 钱包:按当前价格摊到各种可追踪的币上(<see cref="Wallet.MigrateTaint"/>);Poinbase 账户和永续仓位的污点先挪到 1 号钱包一起摊(超出的作废)。
|
||||||
|
/// 托管(混币器在途、黑市订单、质押、空投池、预测持仓、自营混币器本金):按当前价格换成那种币的脏枚数,不超过数量。旧字段清零。
|
||||||
|
/// </summary>
|
||||||
|
public static class TaintMigration
|
||||||
|
{
|
||||||
|
private static double Qty(Func<string, double> price, string asset, double amount, double legacy)
|
||||||
|
{
|
||||||
|
double p = price(asset);
|
||||||
|
return legacy > 0 && p > 0 ? Math.Min(Math.Max(0, amount), legacy / p) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>迁移全部,返回旧存档里的污点总额(信用点,日志用)。</summary>
|
||||||
|
public static double Run(IList<Wallet> wallets, Wallet poinbase, IEnumerable<PerpPosition> perps, Mixer mixer, BlackMarket black,
|
||||||
|
Staking staking, Scams scams, PredictBook predict, OwnMixer own, Func<string, double> price)
|
||||||
|
{
|
||||||
|
double total = wallets.Sum(w => w.LegacyTaint) + poinbase.LegacyTaint + perps.Sum(p => p.LegacyTaint);
|
||||||
|
double extra = Exchange.TakeLegacyTaint(poinbase, perps);
|
||||||
|
for (int i = 0; i < wallets.Count; i++) wallets[i].MigrateTaint(price, i == 0 ? extra : 0);
|
||||||
|
foreach (var d in mixer.Pending) { total += d.LegacyTaint; d.Dirty += Qty(price, d.Asset, d.Amount, d.LegacyTaint); d.LegacyTaint = 0; }
|
||||||
|
foreach (var o in black.Orders) { total += o.LegacyTaint; o.Dirty += Qty(price, o.Asset, o.Qty, o.LegacyTaint); o.LegacyTaint = 0; }
|
||||||
|
foreach (var l in staking.Lots) { total += l.LegacyTaint; l.Dirty += Qty(price, Assets.CRA, l.Total, l.LegacyTaint); l.LegacyTaint = 0; }
|
||||||
|
foreach (var p in scams.Pools)
|
||||||
|
{
|
||||||
|
foreach (var kv in p.LegacyTaint)
|
||||||
|
{
|
||||||
|
total += kv.Value;
|
||||||
|
p.Dirty[kv.Key] = (p.Dirty.TryGetValue(kv.Key, out var d) ? d : 0) + Qty(price, Assets.CRC, p.Of(kv.Key), kv.Value);
|
||||||
|
}
|
||||||
|
p.LegacyTaint.Clear();
|
||||||
|
foreach (var q in p.Pending) { total += q.LegacyTaint; q.Dirty += Qty(price, Assets.CRC, q.Amount, q.LegacyTaint); q.LegacyTaint = 0; }
|
||||||
|
}
|
||||||
|
foreach (var p in predict.Positions) { total += p.LegacyTaint; p.Dirty += Qty(price, Assets.CRC, p.Cost * (1 + Tuning.PredictFee), p.LegacyTaint); p.LegacyTaint = 0; }
|
||||||
|
foreach (var kv in own.Pools) { total += kv.Value.LegacyCapTaint; kv.Value.CapDirty += Qty(price, kv.Key, kv.Value.Capital, kv.Value.LegacyCapTaint); kv.Value.LegacyCapTaint = 0; }
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -83,12 +83,7 @@ namespace Decentralized.Domain
|
|||||||
public const double SparkRaidShock = 1.15, SparkUnrestShock = 0.90;
|
public const double SparkRaidShock = 1.15, SparkUnrestShock = 0.90;
|
||||||
public static readonly double[] SparkSpiralPath = { 0.8, 0.3, 0.05 };
|
public static readonly double[] SparkSpiralPath = { 0.8, 0.3, 0.05 };
|
||||||
|
|
||||||
// 合规出金与 AML(阈值以当前房租为单位)
|
/// <summary>出金到银行:超出成本的部分征税。</summary>
|
||||||
public const double AmlBigRents = 5, AmlCumRents = 15;
|
|
||||||
/// <summary>出金审查命中概率:污点占比达标后每占一分加 AmlTaintMult 倍;超出单笔 / 累计额度的部分按 AmlExcessWeight 加。</summary>
|
|
||||||
public const double AmlTaintMult = 1.5, AmlExcessWeight = 0.2;
|
|
||||||
public const int AmlWindowDays = 7;
|
|
||||||
public const double AmlTaintRatio = 0.10, AmlHeavyRatio = 0.30, AmlMixerBonus = 0.30, AmlMaxChance = 0.9;
|
|
||||||
public const double TaxRate = 0.08;
|
public const double TaxRate = 0.08;
|
||||||
/// <summary>混币器:每轮手续费、基准清洗率、NPC 背景量(信用点)、最大轮数、最小存入、制裁概率与天数、每晚跑路概率。</summary>
|
/// <summary>混币器:每轮手续费、基准清洗率、NPC 背景量(信用点)、最大轮数、最小存入、制裁概率与天数、每晚跑路概率。</summary>
|
||||||
public const double MixerFee = 0.03, MixerCleanRate = 0.35, MixerNpcVolume = 20000, MixerMin = 100, MixerSanctionChance = 0.5, MixerRugChance = 0.004;
|
public const double MixerFee = 0.03, MixerCleanRate = 0.35, MixerNpcVolume = 20000, MixerMin = 100, MixerSanctionChance = 0.5, MixerRugChance = 0.004;
|
||||||
@@ -246,7 +241,7 @@ namespace Decentralized.Domain
|
|||||||
public const double EraKjMult = 0.5;
|
public const double EraKjMult = 0.5;
|
||||||
|
|
||||||
/// <summary>预测市场:游戏第几天起开放;手续费;单盘额度 = 基础 + 每天增量 × 天数;所有钱包在单盘合计的份额上限(额度的倍数);
|
/// <summary>预测市场:游戏第几天起开放;手续费;单盘额度 = 基础 + 每天增量 × 天数;所有钱包在单盘合计的份额上限(额度的倍数);
|
||||||
/// 同时开放的盘口数量范围、每天最多新开几个;污点超出钱包价值的部分折成诈骗罪证的比例与单次上限(内幕、操纵记污点时通用);
|
/// 同时开放的盘口数量范围、每天最多新开几个;按信用点额折诈骗罪证的比例与单次上限(永续被判操纵、Tumbler 泄露用);
|
||||||
/// 派系行动的日均开始概率(先验);先验概率的夹紧范围;结算记录保留条数。</summary>
|
/// 派系行动的日均开始概率(先验);先验概率的夹紧范围;结算记录保留条数。</summary>
|
||||||
public const int PredictUnlockDay = 8;
|
public const int PredictUnlockDay = 8;
|
||||||
public const double PredictFee = 0.01, PredictLoss0 = 800, PredictLossPerDay = 25, PredictCap = 2;
|
public const double PredictFee = 0.01, PredictLoss0 = 800, PredictLossPerDay = 25, PredictCap = 2;
|
||||||
@@ -328,12 +323,12 @@ namespace Decentralized.Domain
|
|||||||
public const double BmAutoSwapSlip = 0.08;
|
public const double BmAutoSwapSlip = 0.08;
|
||||||
|
|
||||||
/// <summary>剧情联动:塞尔皮科证据交给革命军(CRA 补贴池注资、螺旋概率倍率与期限、SPARK 几晚内涨到的倍数)、交给黑市(CRT 脱锚与被出卖的倍率)、
|
/// <summary>剧情联动:塞尔皮科证据交给革命军(CRA 补贴池注资、螺旋概率倍率与期限、SPARK 几晚内涨到的倍数)、交给黑市(CRT 脱锚与被出卖的倍率)、
|
||||||
/// 交给治安部(期限内出金审查命中、混币器制裁、操纵与内幕查处的倍率);埃莉诺泄露数据盘(CRC 托管减记倍率、SPARK 涨幅)、交回(CRC 脱锚倍率);
|
/// 交给治安部(期限内混币器每轮清洗率、制裁、操纵查处的倍率);埃莉诺泄露数据盘(CRC 托管减记倍率、SPARK 涨幅)、交回(CRC 脱锚倍率);
|
||||||
/// 伦警官被捕(期限与查处倍率);SPARK 推涨分几晚走完。</summary>
|
/// 伦警官被捕(期限与倍率:操纵查处、换币客户里的便衣);SPARK 推涨分几晚走完。</summary>
|
||||||
public const double StoryRevSubsidy = 10000, StoryCraSpiralMult = 0.5, StorySerpicoSpark = 1.2;
|
public const double StoryRevSubsidy = 10000, StoryCraSpiralMult = 0.5, StorySerpicoSpark = 1.2;
|
||||||
public const double StoryBmCrtMult = 0.5;
|
public const double StoryBmCrtMult = 0.5;
|
||||||
public const int StorySecDays = 30;
|
public const int StorySecDays = 30;
|
||||||
public const double StorySecAmlMult = 1.5, StorySecSanctionMult = 1.5, StorySecEnforceMult = 1.3;
|
public const double StorySecMixClean = 0.7, StorySecSanctionMult = 1.5, StorySecEnforceMult = 1.3;
|
||||||
public const double StoryLeakHaircutMult = 2, StoryLeakSpark = 1.15, StoryReturnCrcMult = 0.5;
|
public const double StoryLeakHaircutMult = 2, StoryLeakSpark = 1.15, StoryReturnCrcMult = 0.5;
|
||||||
public const int StoryLunDays = 14, StorySparkNights = 5;
|
public const int StoryLunDays = 14, StorySparkNights = 5;
|
||||||
/// <summary>混币器运营者 Tumbler:第几天起开始;帮他藏好密钥盘后的混币器手续费、匿名集倍率和谢礼(CRT);举报的赏金(信用点)和治安部声望;
|
/// <summary>混币器运营者 Tumbler:第几天起开始;帮他藏好密钥盘后的混币器手续费、匿名集倍率和谢礼(CRT);举报的赏金(信用点)和治安部声望;
|
||||||
@@ -343,6 +338,22 @@ namespace Decentralized.Domain
|
|||||||
public const int TumblerBounty = 1200, TumblerSecRep = 8, TumblerBmRep = 5;
|
public const int TumblerBounty = 1200, TumblerSecRep = 8, TumblerBmRep = 5;
|
||||||
public const double TumblerSellCrt = 3000, TumblerSoldFee = 1.5, TumblerSoldRug = 4;
|
public const double TumblerSellCrt = 3000, TumblerSoldFee = 1.5, TumblerSoldRug = 4;
|
||||||
public const int TumblerDriveValue = 600;
|
public const int TumblerDriveValue = 600;
|
||||||
|
/// <summary>卖给黑市得的 CRT 里带污点的比例。</summary>
|
||||||
|
public const double TumblerSellTaint = 0.5;
|
||||||
|
/// <summary>Tumbler 的后续剧情:混币器出款记录保留几天、最多几条(泄露时这些出款洗掉的污点加回原钱包);
|
||||||
|
/// 治安部探员:配合时的治安部声望,之后搜走密钥盘记的违禁品罪证。</summary>
|
||||||
|
public const int TumblerLeakDays = 30, TumblerReturnsMax = 300, TumblerAgentSecRep = 5, TumblerSearchCrime = 300;
|
||||||
|
/// <summary>审判盘:举报后第几天开盘、第几天宣判;定罪的概率(举报时掷出);每晚庭审新闻偏向真实判决的概率。</summary>
|
||||||
|
public const int TumblerTrialOpen = 2, TumblerTrialDays = 7;
|
||||||
|
public const double TumblerTrialConvict = 0.7, TumblerTrialHintAcc = 0.7;
|
||||||
|
/// <summary>报复:获释或黑市跑路后几天动手;给当前钱包植入木马(否则地址投毒)的概率;地址投毒每个钱包最多几笔。</summary>
|
||||||
|
public const int TumblerRevengeDelay = 3, TumblerRevengePoison = 3;
|
||||||
|
public const double TumblerRevengeWalletShare = 0.5;
|
||||||
|
/// <summary>卖给黑市后,黑市卷款跑路在第几天(随机,含两端)。</summary>
|
||||||
|
public const int TumblerBmRugMin = 10, TumblerBmRugMax = 20;
|
||||||
|
/// <summary>换皮重开:混币器关停后几天;是治安部钓鱼混币器的概率;钓鱼混币器的费率倍率。</summary>
|
||||||
|
public const int TumblerRebrandDays = 15;
|
||||||
|
public const double TumblerHoneypot = 0.25, TumblerHoneypotFee = 0.5;
|
||||||
public const double StoryLunMult = 1.3;
|
public const double StoryLunMult = 1.3;
|
||||||
|
|
||||||
/// <summary>行情图的 NPC 成交量:每天的基础量占主池深度的比例(按币种),价格波动越大成交越多(|涨跌幅| × 倍数),再乘 0.6–1.4 的随机。</summary>
|
/// <summary>行情图的 NPC 成交量:每天的基础量占主池深度的比例(按币种),价格波动越大成交越多(|涨跌幅| × 倍数),再乘 0.6–1.4 的随机。</summary>
|
||||||
|
|||||||
@@ -16,15 +16,6 @@ namespace Decentralized.Domain
|
|||||||
["AirdropRewardMax"] = Tuning.AirdropRewardMax,
|
["AirdropRewardMax"] = Tuning.AirdropRewardMax,
|
||||||
["AirdropRewardMin"] = Tuning.AirdropRewardMin,
|
["AirdropRewardMin"] = Tuning.AirdropRewardMin,
|
||||||
["AirdropScam"] = Tuning.AirdropScam,
|
["AirdropScam"] = Tuning.AirdropScam,
|
||||||
["AmlBigRents"] = Tuning.AmlBigRents,
|
|
||||||
["AmlCumRents"] = Tuning.AmlCumRents,
|
|
||||||
["AmlExcessWeight"] = Tuning.AmlExcessWeight,
|
|
||||||
["AmlHeavyRatio"] = Tuning.AmlHeavyRatio,
|
|
||||||
["AmlMaxChance"] = Tuning.AmlMaxChance,
|
|
||||||
["AmlMixerBonus"] = Tuning.AmlMixerBonus,
|
|
||||||
["AmlTaintMult"] = Tuning.AmlTaintMult,
|
|
||||||
["AmlTaintRatio"] = Tuning.AmlTaintRatio,
|
|
||||||
["AmlWindowDays"] = Tuning.AmlWindowDays,
|
|
||||||
["AsicChance"] = Tuning.AsicChance,
|
["AsicChance"] = Tuning.AsicChance,
|
||||||
["AsicDeadValue"] = Tuning.AsicDeadValue,
|
["AsicDeadValue"] = Tuning.AsicDeadValue,
|
||||||
["AsicNewShare"] = Tuning.AsicNewShare,
|
["AsicNewShare"] = Tuning.AsicNewShare,
|
||||||
@@ -428,25 +419,42 @@ namespace Decentralized.Domain
|
|||||||
["StoryLunMult"] = Tuning.StoryLunMult,
|
["StoryLunMult"] = Tuning.StoryLunMult,
|
||||||
["StoryReturnCrcMult"] = Tuning.StoryReturnCrcMult,
|
["StoryReturnCrcMult"] = Tuning.StoryReturnCrcMult,
|
||||||
["StoryRevSubsidy"] = Tuning.StoryRevSubsidy,
|
["StoryRevSubsidy"] = Tuning.StoryRevSubsidy,
|
||||||
["StorySecAmlMult"] = Tuning.StorySecAmlMult,
|
|
||||||
["StorySecDays"] = Tuning.StorySecDays,
|
["StorySecDays"] = Tuning.StorySecDays,
|
||||||
["StorySecEnforceMult"] = Tuning.StorySecEnforceMult,
|
["StorySecEnforceMult"] = Tuning.StorySecEnforceMult,
|
||||||
|
["StorySecMixClean"] = Tuning.StorySecMixClean,
|
||||||
["StorySecSanctionMult"] = Tuning.StorySecSanctionMult,
|
["StorySecSanctionMult"] = Tuning.StorySecSanctionMult,
|
||||||
["StorySerpicoSpark"] = Tuning.StorySerpicoSpark,
|
["StorySerpicoSpark"] = Tuning.StorySerpicoSpark,
|
||||||
["StorySparkNights"] = Tuning.StorySparkNights,
|
["StorySparkNights"] = Tuning.StorySparkNights,
|
||||||
["SupplyAdjust"] = Tuning.SupplyAdjust,
|
["SupplyAdjust"] = Tuning.SupplyAdjust,
|
||||||
["TaxRate"] = Tuning.TaxRate,
|
["TaxRate"] = Tuning.TaxRate,
|
||||||
|
["TumblerAgentSecRep"] = Tuning.TumblerAgentSecRep,
|
||||||
["TumblerBmRep"] = Tuning.TumblerBmRep,
|
["TumblerBmRep"] = Tuning.TumblerBmRep,
|
||||||
|
["TumblerBmRugMax"] = Tuning.TumblerBmRugMax,
|
||||||
|
["TumblerBmRugMin"] = Tuning.TumblerBmRugMin,
|
||||||
["TumblerBounty"] = Tuning.TumblerBounty,
|
["TumblerBounty"] = Tuning.TumblerBounty,
|
||||||
["TumblerDriveValue"] = Tuning.TumblerDriveValue,
|
["TumblerDriveValue"] = Tuning.TumblerDriveValue,
|
||||||
["TumblerGift"] = Tuning.TumblerGift,
|
["TumblerGift"] = Tuning.TumblerGift,
|
||||||
|
["TumblerHoneypot"] = Tuning.TumblerHoneypot,
|
||||||
|
["TumblerHoneypotFee"] = Tuning.TumblerHoneypotFee,
|
||||||
["TumblerKeptFee"] = Tuning.TumblerKeptFee,
|
["TumblerKeptFee"] = Tuning.TumblerKeptFee,
|
||||||
["TumblerKeptVolume"] = Tuning.TumblerKeptVolume,
|
["TumblerKeptVolume"] = Tuning.TumblerKeptVolume,
|
||||||
|
["TumblerLeakDays"] = Tuning.TumblerLeakDays,
|
||||||
["TumblerMinDay"] = Tuning.TumblerMinDay,
|
["TumblerMinDay"] = Tuning.TumblerMinDay,
|
||||||
|
["TumblerRebrandDays"] = Tuning.TumblerRebrandDays,
|
||||||
|
["TumblerReturnsMax"] = Tuning.TumblerReturnsMax,
|
||||||
|
["TumblerRevengeDelay"] = Tuning.TumblerRevengeDelay,
|
||||||
|
["TumblerRevengePoison"] = Tuning.TumblerRevengePoison,
|
||||||
|
["TumblerRevengeWalletShare"] = Tuning.TumblerRevengeWalletShare,
|
||||||
|
["TumblerSearchCrime"] = Tuning.TumblerSearchCrime,
|
||||||
["TumblerSecRep"] = Tuning.TumblerSecRep,
|
["TumblerSecRep"] = Tuning.TumblerSecRep,
|
||||||
["TumblerSellCrt"] = Tuning.TumblerSellCrt,
|
["TumblerSellCrt"] = Tuning.TumblerSellCrt,
|
||||||
|
["TumblerSellTaint"] = Tuning.TumblerSellTaint,
|
||||||
["TumblerSoldFee"] = Tuning.TumblerSoldFee,
|
["TumblerSoldFee"] = Tuning.TumblerSoldFee,
|
||||||
["TumblerSoldRug"] = Tuning.TumblerSoldRug,
|
["TumblerSoldRug"] = Tuning.TumblerSoldRug,
|
||||||
|
["TumblerTrialConvict"] = Tuning.TumblerTrialConvict,
|
||||||
|
["TumblerTrialDays"] = Tuning.TumblerTrialDays,
|
||||||
|
["TumblerTrialHintAcc"] = Tuning.TumblerTrialHintAcc,
|
||||||
|
["TumblerTrialOpen"] = Tuning.TumblerTrialOpen,
|
||||||
["TxConfirmBase"] = Tuning.TxConfirmBase,
|
["TxConfirmBase"] = Tuning.TxConfirmBase,
|
||||||
["TxConfirmBig"] = Tuning.TxConfirmBig,
|
["TxConfirmBig"] = Tuning.TxConfirmBig,
|
||||||
["TxConfirmBigValue"] = Tuning.TxConfirmBigValue,
|
["TxConfirmBigValue"] = Tuning.TxConfirmBigValue,
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Decentralized.Domain
|
namespace Decentralized.Domain
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 一个链上地址:各币种余额,加上整个地址的污点额与成本(信用点等值)。
|
/// 一个链上地址:各币种余额,每种币里有几枚是脏的(<see cref="Dirty"/>),加上整个地址的成本(信用点)。
|
||||||
/// 污点和成本按转出的价值比例随币走。
|
/// 污点随具体的币进出:收到带污点的币时记下其中几枚脏;花掉、转出这种币时按它的脏比例带走;兑换成别的币时脏比例跟过去。
|
||||||
|
/// 成本按转出的价值比例随币走。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Wallet
|
public sealed class Wallet
|
||||||
{
|
{
|
||||||
public string Address;
|
public string Address;
|
||||||
public Dictionary<string, double> Balances = new Dictionary<string, double>();
|
public Dictionary<string, double> Balances = new Dictionary<string, double>();
|
||||||
/// <summary>污点额(信用点等值)。</summary>
|
/// <summary>每种币里脏的枚数(0 ≤ 脏 ≤ 余额)。</summary>
|
||||||
public double Taint;
|
public Dictionary<string, double> Dirty = new Dictionary<string, double>();
|
||||||
|
/// <summary>旧存档(数据版本 5 之前)整个钱包的污点额(信用点):只在读档迁移时读一次,之后为 0。</summary>
|
||||||
|
[JsonProperty("Taint")] public double LegacyTaint;
|
||||||
/// <summary>成本(信用点):出金时只对超出成本的部分征税。</summary>
|
/// <summary>成本(信用点):出金时只对超出成本的部分征税。</summary>
|
||||||
public double Basis;
|
public double Basis;
|
||||||
/// <summary>被执法标记。</summary>
|
|
||||||
public bool Flagged;
|
|
||||||
/// <summary>钱包编号("钱包 n"),添加时定下,销毁别的钱包也不变。</summary>
|
/// <summary>钱包编号("钱包 n"),添加时定下,销毁别的钱包也不变。</summary>
|
||||||
public string Name;
|
public string Name;
|
||||||
/// <summary>玩家起的名字;空时用默认名。</summary>
|
/// <summary>玩家起的名字;空时用默认名。</summary>
|
||||||
@@ -43,7 +45,7 @@ namespace Decentralized.Domain
|
|||||||
{
|
{
|
||||||
double v = Value(price);
|
double v = Value(price);
|
||||||
Balances.Clear(); Frozen.Clear(); FrozenUntil.Clear(); BuyQty.Clear(); BuyCost.Clear();
|
Balances.Clear(); Frozen.Clear(); FrozenUntil.Clear(); BuyQty.Clear(); BuyCost.Clear();
|
||||||
Taint = 0; Basis = 0;
|
Dirty.Clear(); Basis = 0;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,55 +103,131 @@ namespace Decentralized.Domain
|
|||||||
BuyQty[asset] = bq * keep; BuyCost[asset] *= keep;
|
BuyQty[asset] = bq * keep; BuyCost[asset] *= keep;
|
||||||
if (BuyQty[asset] < 1e-9) { BuyQty.Remove(asset); BuyCost.Remove(asset); }
|
if (BuyQty[asset] < 1e-9) { BuyQty.Remove(asset); BuyCost.Remove(asset); }
|
||||||
}
|
}
|
||||||
double v = Get(asset) + amount;
|
double had = Get(asset), v = had + amount;
|
||||||
if (v < -1e-9) throw new InvalidOperationException($"{Address}: {asset} 余额不足");
|
if (v < -1e-9) throw new InvalidOperationException($"{Address}: {asset} 余额不足");
|
||||||
if (Math.Abs(v) < 1e-12) Balances.Remove(asset);
|
if (Math.Abs(v) < 1e-12) Balances.Remove(asset);
|
||||||
else Balances[asset] = v;
|
else Balances[asset] = v;
|
||||||
|
// 拿走的币按这种币的脏比例带走脏枚数
|
||||||
|
if (amount < 0 && Dirty.TryGetValue(asset, out var d)) SetDirty(asset, had > 1e-12 ? d * Math.Max(0, v) / had : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>按价格表估值(信用点)。</summary>
|
/// <summary>这种币里脏的枚数(不超过余额)。</summary>
|
||||||
/// <summary>花掉(销毁)一笔币:污点与成本按这笔币占钱包总价值的比例一起带走。</summary>
|
public double DirtyOf(string asset) => Dirty.TryGetValue(asset, out var d) ? Math.Max(0, Math.Min(d, Get(asset))) : 0;
|
||||||
|
|
||||||
|
/// <summary>这种币的脏比例(0–1)。</summary>
|
||||||
|
public double DirtyRatio(string asset) { double g = Get(asset); return g > 1e-12 ? DirtyOf(asset) / g : 0; }
|
||||||
|
|
||||||
|
/// <summary>这种币里干净的、能动用的枚数(不超过可动用余额)。钱包往 Poinbase 最多只能充这么多。</summary>
|
||||||
|
public double CleanAvail(string asset) => Math.Max(0, Math.Min(Avail(asset), Get(asset) - DirtyOf(asset)));
|
||||||
|
|
||||||
|
/// <summary>按现价算的脏币总价值(信用点):钱包总表、日志用。</summary>
|
||||||
|
public double Taint(Func<string, double> price) => Balances.Keys.Sum(a => DirtyOf(a) * price(a));
|
||||||
|
|
||||||
|
private void SetDirty(string asset, double d)
|
||||||
|
{
|
||||||
|
d = Math.Max(0, Math.Min(d, Get(asset)));
|
||||||
|
if (d < 1e-9) Dirty.Remove(asset); else Dirty[asset] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>收到 amount 枚币,其中 dirty 枚是脏的(不超过 amount)。</summary>
|
||||||
|
public void AddDirty(string asset, double amount, double dirty)
|
||||||
|
{
|
||||||
|
if (amount <= 0) return;
|
||||||
|
Add(asset, amount);
|
||||||
|
if (dirty > 0) SetDirty(asset, DirtyOf(asset) + Math.Min(dirty, amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>把这种币里干净的 qty 枚记成脏的(刚收到的兑付被判内幕、操纵时用);不够的部分不记,返回没记上的枚数。</summary>
|
||||||
|
public double MarkDirty(string asset, double qty)
|
||||||
|
{
|
||||||
|
if (qty <= 0) return 0;
|
||||||
|
double clean = Math.Max(0, Get(asset) - DirtyOf(asset)), mark = Math.Min(qty, clean);
|
||||||
|
SetDirty(asset, DirtyOf(asset) + mark);
|
||||||
|
return qty - mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>余额按比例缩水(CRC 托管银行减记):脏枚数同比例缩水。</summary>
|
||||||
|
public void Scale(string asset, double factor)
|
||||||
|
{
|
||||||
|
double g = Get(asset);
|
||||||
|
if (g <= 0) return;
|
||||||
|
double d = DirtyOf(asset);
|
||||||
|
Add(asset, g * Math.Max(0, factor) - g);
|
||||||
|
SetDirty(asset, d * Math.Max(0, factor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>兑换:付出 amount 枚 from(按它的脏比例带走脏枚数),收到 got 枚 to,脏比例跟过去;clean 为真时(兑入 Ponero)收到的是干净的。</summary>
|
||||||
|
public void Convert(string from, double amount, string to, double got, bool clean = false)
|
||||||
|
{
|
||||||
|
double r = DirtyRatio(from);
|
||||||
|
Add(from, -amount);
|
||||||
|
AddDirty(to, got, clean ? 0 : got * r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>花掉(销毁)一笔币:脏枚数按这种币的脏比例带走,成本按这笔币占钱包总价值的比例带走。</summary>
|
||||||
public void Spend(string asset, double amount, Func<string, double> price)
|
public void Spend(string asset, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
double total = Value(price), share = total > 0 ? Math.Min(1, amount * price(asset) / total) : 0;
|
double total = Value(price), share = total > 0 ? Math.Min(1, amount * price(asset) / total) : 0;
|
||||||
double taint = Taint * share, basis = Basis * share;
|
double basis = Basis * share;
|
||||||
Add(asset, -amount); Taint -= taint; Basis -= basis;
|
Add(asset, -amount); Basis -= basis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>按价格表估值(信用点)。</summary>
|
||||||
|
|
||||||
public double Value(Func<string, double> price) => Balances.Sum(kv => kv.Value * price(kv.Key));
|
public double Value(Func<string, double> price) => Balances.Sum(kv => kv.Value * price(kv.Key));
|
||||||
|
|
||||||
|
/// <summary>按信用点额折成的诈骗罪证:额 × <see cref="Tuning.PredictFraudShare"/>,单次封顶 <see cref="Tuning.PredictFraudCap"/>(永续被判操纵、Tumbler 泄露用)。</summary>
|
||||||
|
public static double FraudFor(double credits) => Math.Min(Tuning.PredictFraudCap, Math.Max(0, credits) * Tuning.PredictFraudShare);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加污点,加完不超过钱包当时的价值(只在加的这一刻检查,之后币价涨跌不再调整)。
|
/// 只转干净的币(往 Poinbase 充值):脏枚数全部留在原钱包,成本按价值比例带走。数量超过 <see cref="CleanAvail"/> 的部分不转,返回实际转的数量。
|
||||||
/// 返回加不进去的部分(超出额),由调用方按 <see cref="OverflowFraud"/> 折成罪证。
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double AddTaintCapped(double amount, Func<string, double> price)
|
public static double TransferClean(Wallet from, Wallet to, string asset, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
|
amount = Math.Min(amount, from.CleanAvail(asset));
|
||||||
if (amount <= 0) return 0;
|
if (amount <= 0) return 0;
|
||||||
double add = Math.Min(amount, Math.Max(0, Value(price) - Taint));
|
double total = from.Value(price);
|
||||||
Taint += add;
|
double share = total > 0 ? Math.Min(1.0, amount * price(asset) / total) : 0;
|
||||||
return amount - add;
|
double basis = from.Basis * share, dirty = from.DirtyOf(asset);
|
||||||
|
from.Add(asset, -amount);
|
||||||
|
from.SetDirty(asset, dirty);
|
||||||
|
from.Basis -= basis;
|
||||||
|
to.Add(asset, amount);
|
||||||
|
to.Basis += basis;
|
||||||
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>污点超出钱包价值的部分折成的诈骗罪证:超出额 × <see cref="Tuning.PredictFraudShare"/>,单次封顶 <see cref="Tuning.PredictFraudCap"/>。</summary>
|
|
||||||
public static double OverflowFraud(double overflow) => Math.Min(Tuning.PredictFraudCap, Math.Max(0, overflow) * Tuning.PredictFraudShare);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转出:taint 和 basis 按转出价值占地址总价值的比例带走;被标记的地址转出可追踪的币,收款地址也被标记。
|
/// 转出:这种币按它的脏比例把脏枚数带过去,成本按转出价值占地址总价值的比例带走。
|
||||||
/// Ponero 等不可追踪资产转入时,污点和标记都不随之进入目标地址。
|
/// Ponero 等不可追踪资产转入时,不带脏枚数。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void Transfer(Wallet from, Wallet to, string asset, double amount, Func<string, double> price)
|
public static void Transfer(Wallet from, Wallet to, string asset, double amount, Func<string, double> price)
|
||||||
{
|
{
|
||||||
if (amount <= 0) return;
|
if (amount <= 0) return;
|
||||||
double total = from.Value(price);
|
double total = from.Value(price);
|
||||||
double share = total > 0 ? Math.Min(1.0, amount * price(asset) / total) : 0;
|
double share = total > 0 ? Math.Min(1.0, amount * price(asset) / total) : 0;
|
||||||
double taint = from.Taint * share, basis = from.Basis * share;
|
double basis = from.Basis * share, dirty = amount * from.DirtyRatio(asset);
|
||||||
from.Add(asset, -amount);
|
from.Add(asset, -amount);
|
||||||
from.Taint -= taint;
|
|
||||||
from.Basis -= basis;
|
from.Basis -= basis;
|
||||||
to.Add(asset, amount);
|
|
||||||
var spec = Assets.Get(asset);
|
var spec = Assets.Get(asset);
|
||||||
if (spec == null || spec.Traceable) { to.Taint += taint; if (from.Flagged) to.Flagged = true; }
|
to.AddDirty(asset, amount, spec == null || spec.Traceable ? dirty : 0);
|
||||||
to.Basis += basis;
|
to.Basis += basis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存档迁移:旧的整钱包污点额(信用点)按当前价格摊成各币的脏枚数:脏比例 = min(1, 污点 / 可追踪币的价值),每种可追踪的币按这个比例记脏。
|
||||||
|
/// extra 是另外挪进来的旧污点(Poinbase 账户、永续仓位),一起摊;超出的部分作废。旧字段清零。
|
||||||
|
/// </summary>
|
||||||
|
public void MigrateTaint(Func<string, double> price, double extra = 0)
|
||||||
|
{
|
||||||
|
double t = LegacyTaint + extra;
|
||||||
|
LegacyTaint = 0;
|
||||||
|
if (t <= 0) return;
|
||||||
|
var traceable = Balances.Keys.Where(a => Assets.Get(a) == null || Assets.Get(a).Traceable).ToList();
|
||||||
|
double v = traceable.Sum(a => Get(a) * price(a));
|
||||||
|
if (v <= 0) return;
|
||||||
|
double r = Math.Min(1, t / v);
|
||||||
|
foreach (var a in traceable) SetDirty(a, DirtyOf(a) + Get(a) * r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,8 +44,8 @@ namespace Decentralized
|
|||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tainted wallet (test)", () => Log.Guard("带污点的钱包(测试)", () =>
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tainted wallet (test)", () => Log.Guard("带污点的钱包(测试)", () =>
|
||||||
{
|
{
|
||||||
var w = Session.Data.Hot;
|
var w = Session.Data.Hot;
|
||||||
w.Add(Assets.PSC, 100); w.Add(Assets.CRT, 1000); w.Taint += 3000; w.Basis += 2000;
|
w.AddDirty(Assets.PSC, 100, 30); w.AddDirty(Assets.CRT, 1000, 1000); w.Basis += 2000;
|
||||||
Log.Info($"钱包:PSC {w.Get(Assets.PSC):0.##},污点 {w.Taint:0}");
|
Log.Info($"钱包:PSC {w.Get(Assets.PSC):0.##}(脏 {w.DirtyOf(Assets.PSC):0.##}),CRT {w.Get(Assets.CRT):0}(脏 {w.DirtyOf(Assets.CRT):0})");
|
||||||
}));
|
}));
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Terminal (test)", () => Log.Guard("终端(测试)", TerminalWindow.Open));
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Terminal (test)", () => Log.Guard("终端(测试)", TerminalWindow.Open));
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market +50 rep, restock (test)", () => Log.Guard("黑市(测试)", () =>
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Black market +50 rep, restock (test)", () => Log.Guard("黑市(测试)", () =>
|
||||||
@@ -55,7 +55,7 @@ namespace Decentralized
|
|||||||
if (!Unlock.BlackUnlocked) ModHelper.GetNetworkUpgrade(Unlock.BlackId)?.Unlock();
|
if (!Unlock.BlackUnlocked) ModHelper.GetNetworkUpgrade(Unlock.BlackId)?.Unlock();
|
||||||
if (!Unlock.MixerUnlocked) ModHelper.GetNetworkUpgrade(Unlock.MixerId)?.Unlock();
|
if (!Unlock.MixerUnlocked) ModHelper.GetNetworkUpgrade(Unlock.MixerId)?.Unlock();
|
||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
d.Hot.Add(Assets.PSC, 20); d.Hot.Add(Assets.CRT, 3000); d.Hot.Taint += 2000; d.Hot.Basis += 1000;
|
d.Hot.Add(Assets.PSC, 20); d.Hot.AddDirty(Assets.CRT, 3000, 2000); d.Hot.Basis += 1000;
|
||||||
BlackDelivery.Restock(d, StoreStation.GetDayCounter(), true);
|
BlackDelivery.Restock(d, StoreStation.GetDayCounter(), true);
|
||||||
Log.Info($"黑市:声望 {StoreReputation.GetBMReputation()},上架 {d.Black.Offers.Count} 种:{string.Join(", ", d.Black.Offers.Select(o => o.Item + "×" + o.Qty + "@" + o.Price))},解锁 {Unlock.BlackUnlocked}");
|
Log.Info($"黑市:声望 {StoreReputation.GetBMReputation()},上架 {d.Black.Offers.Count} 种:{string.Join(", ", d.Black.Offers.Select(o => o.Item + "×" + o.Qty + "@" + o.Price))},解锁 {Unlock.BlackUnlocked}");
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
public const string Id = "probably_decentralized";
|
public const string Id = "probably_decentralized";
|
||||||
public const string Name = "Probably Decentralized";
|
public const string Name = "Probably Decentralized";
|
||||||
public const string Version = "1.1.0";
|
public const string Version = "2.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>本地化:游戏的 mod 本地化表(ModFiles/Localization/*.csv),当前语言缺失时回退英文。</summary>
|
/// <summary>本地化:游戏的 mod 本地化表(ModFiles/Localization/*.csv),当前语言缺失时回退英文。</summary>
|
||||||
@@ -47,18 +47,4 @@ namespace Decentralized
|
|||||||
public static string Num(double v) => Math.Abs(v) >= 100 ? v.ToString("N0") : Math.Abs(v) >= 1 ? v.ToString("0.##") : v.ToString("0.####");
|
public static string Num(double v) => Math.Abs(v) >= 100 ? v.ToString("N0") : Math.Abs(v) >= 1 ? v.ToString("0.##") : v.ToString("0.####");
|
||||||
public static string Credits(double v) => v.ToString("N0");
|
public static string Credits(double v) => v.ToString("N0");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>污点超出钱包价值的部分:按 <see cref="Decentralized.Domain.Wallet.OverflowFraud"/> 记诈骗罪证,返回接在消息后面的一句(没有超出返回空串)。</summary>
|
|
||||||
public static class TaintCrime
|
|
||||||
{
|
|
||||||
public static string Commit(double over)
|
|
||||||
{
|
|
||||||
if (over <= 1e-9) return "";
|
|
||||||
int fraud = (int)Math.Round(Decentralized.Domain.Wallet.OverflowFraud(over));
|
|
||||||
if (fraud > 0) PlayerStore.Instance.secData.CommitCrime("FRAUD", fraud);
|
|
||||||
// 接在上一句后面:中日文不加空格,其他语言隔一个空格
|
|
||||||
string sep = L.Code.StartsWith("zh") || L.Code.StartsWith("ja") ? "" : " ";
|
|
||||||
return sep + L.T("taint.overflow", Fmt.Credits(over));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -144,11 +144,74 @@ namespace Decentralized
|
|||||||
var t = Session.Data.Story.Tumbler; int day = StoreStation.GetDayCounter();
|
var t = Session.Data.Story.Tumbler; int day = StoreStation.GetDayCounter();
|
||||||
if (t.StartDay < 0) t.StartDay = day;
|
if (t.StartDay < 0) t.StartDay = day;
|
||||||
t.StartDay = day - Tumbler.Offsets[System.Math.Min(t.Stage, Tumbler.Offsets.Length - 1)]; t.VisitedDay = -1;
|
t.StartDay = day - Tumbler.Offsets[System.Math.Min(t.Stage, Tumbler.Offsets.Length - 1)]; t.VisitedDay = -1;
|
||||||
|
var af = Session.Data.Story.After;
|
||||||
|
if (af.AgentDay >= day) af.AgentDay = day - 1;
|
||||||
|
if (af.SearchDay >= day) af.SearchDay = day - 1;
|
||||||
PlayerStore.Instance.currentClientInstance = null;
|
PlayerStore.Instance.currentClientInstance = null;
|
||||||
var m = PlayerStore.Instance.storeClientManager;
|
var m = PlayerStore.Instance.storeClientManager;
|
||||||
TumblerStory.ForceVisit(m);
|
TumblerStory.ForceVisit(m);
|
||||||
PlayerStore.Instance.TryCallNextClient();
|
PlayerStore.Instance.TryCallNextClient();
|
||||||
}));
|
}));
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: restart story (test)", () =>
|
||||||
|
{
|
||||||
|
var st = Session.Data.Story;
|
||||||
|
Log.Info($"测试:Tumbler 剧情重来(原进度 {st.Tumbler.Stage},选择 {st.Tumbler.Choice},结束 {st.Tumbler.Done})");
|
||||||
|
st.Tumbler = new Tumbler(); st.After = new TumblerAfter();
|
||||||
|
st.Applied.RemoveAll(k => k.StartsWith("tumbler_"));
|
||||||
|
st.MixerClosed = st.MixerRebranded = st.MixerHoneypot = false; st.MixerFee = st.MixerVolume = st.MixerRug = 1;
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Hot wallet +2000 CRC (test)", () =>
|
||||||
|
{
|
||||||
|
var w = Session.Data.Hot; w.Add(Assets.CRC, 2000); w.Basis += 2000;
|
||||||
|
Log.Info($"测试:钱包 CRC {w.Get(Assets.CRC):0},污点 {w.Taint:0}");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "My mixer: max heat (test)", () =>
|
||||||
|
{
|
||||||
|
var m = Session.Data.OwnMix; m.Heat = 1e4;
|
||||||
|
Log.Info($"测试:自营混币器风声拉满,今晚查封概率 {m.SeizeChance(1, false):P0}");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Mixer: honeypot now (test)", () =>
|
||||||
|
{
|
||||||
|
var d = Session.Data;
|
||||||
|
d.Story.Rebrand(true); d.Story.After.Rebranded = true;
|
||||||
|
d.Addresses["mixer_old"] = d.Address("mixer"); d.Addresses["mixer"] = ChainAddress.Make(d.Rng.NextUInt());
|
||||||
|
Log.Info($"测试:混币器换成钓鱼混币器,费率 {Mixer.Fee:P1}");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: contact, crackdown tomorrow (test)", () => Log.Guard("联系人测试", () =>
|
||||||
|
{
|
||||||
|
Session.Data.Story.After.Contact = true;
|
||||||
|
StoreStation.Instance.storeEventManager.QueueFuturEvent(OperationListSec.Crackdown(), 1, false);
|
||||||
|
Log.Info("测试:Tumbler 成为联系人,镇压排到明天(玩家不知道)");
|
||||||
|
}));
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: leak tonight (test)", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After; a.Leaked = false; a.LeakDay = StoreStation.GetDayCounter();
|
||||||
|
Log.Info($"测试:今晚泄露,出款记录 {Session.Data.Mixer.Returns.Count} 条");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: trial market now (test)", () => Log.Guard("审判盘测试", () =>
|
||||||
|
{
|
||||||
|
var d = Session.Data; var a = d.Story.After; int day = StoreStation.GetDayCounter();
|
||||||
|
a.Verdict = -1; a.TrialMarket = a.TrialDone = false; a.Hints.Clear(); a.HintDay = -1;
|
||||||
|
a.StartTrial(day - Tuning.TumblerTrialOpen, d.Rng);
|
||||||
|
PredictGame.OpenTrial(d, day);
|
||||||
|
Log.Info($"测试:审判盘开盘,第 {a.TrialDay} 天宣判,判决 {a.Verdict}");
|
||||||
|
Session.Save();
|
||||||
|
}));
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: revenge tonight (test)", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After; a.Revenged = false; a.RevengeDay = StoreStation.GetDayCounter();
|
||||||
|
Log.Info("测试:今晚报复");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Tumbler: BM rug tonight (test)", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After; a.BmRugged = false; a.BmRugDay = StoreStation.GetDayCounter();
|
||||||
|
Log.Info($"测试:今晚黑市跑路,在途 {Session.Data.Mixer.Pending.Count} 笔");
|
||||||
|
});
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Mixer: rebrand tonight (test)", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After; a.Rebranded = false; a.ClosedDay = StoreStation.GetDayCounter() - Tuning.TumblerRebrandDays;
|
||||||
|
Log.Info("测试:今晚换皮重开");
|
||||||
|
});
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Lower-level rep +30 (test)", () => StoreReputation.ModReputation(StoreReputation.FACTION_LOWER_LEVEL, 30));
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Lower-level rep +30 (test)", () => StoreReputation.ModReputation(StoreReputation.FACTION_LOWER_LEVEL, 30));
|
||||||
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dump crimes and reputation (test)", () => Log.Guard("罪证与声望", () =>
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dump crimes and reputation (test)", () => Log.Guard("罪证与声望", () =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ tab.report,Bericht
|
|||||||
wallet.line,{0}: {1} (ca. {2} Credits)
|
wallet.line,{0}: {1} (ca. {2} Credits)
|
||||||
wallet.empty,Die Wallet ist leer.
|
wallet.empty,Die Wallet ist leer.
|
||||||
wallet.total,Gesamtwert: {0} Credits
|
wallet.total,Gesamtwert: {0} Credits
|
||||||
wallet.taint,Kontaminierter Wert: {0} Credits
|
wallet.taint,Kontaminierte Coins: {0} Credits
|
||||||
trade.amount,Betrag
|
trade.amount,Betrag
|
||||||
trade.deposit,Credits als CRC einzahlen
|
trade.deposit,Credits als CRC einzahlen
|
||||||
trade.withdraw,CRC als Credits auszahlen
|
trade.withdraw,CRC als Credits auszahlen
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Nicht genügend Guthaben.
|
|||||||
msg.trade,"{0} {1} gezahlt, {2} {3} erhalten."
|
msg.trade,"{0} {1} gezahlt, {2} {3} erhalten."
|
||||||
msg.deposit,{0} Credits als CRC eingezahlt.
|
msg.deposit,{0} Credits als CRC eingezahlt.
|
||||||
msg.cashout,{0} Credits erhalten. Steuer: {1} Credits.
|
msg.cashout,{0} Credits erhalten. Steuer: {1} Credits.
|
||||||
msg.aml_light,Compliance-Prüfung: {0} Credits an kontaminierten Geldern wurden einbehalten.
|
|
||||||
msg.aml_heavy,Compliance-Prüfung: {0} Credits an kontaminierten Geldern wurden beschlagnahmt und an Security gemeldet.
|
|
||||||
report.none,Noch kein Mining-Bericht vorhanden.
|
report.none,Noch kein Mining-Bericht vorhanden.
|
||||||
report.day,Nacht von Tag {0}
|
report.day,Nacht von Tag {0}
|
||||||
report.rigs,Rigs mit Strom: {0} von {1}
|
report.rigs,Rigs mit Strom: {0} von {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Asset
|
|||||||
col.amount,Betrag
|
col.amount,Betrag
|
||||||
col.value,Wert
|
col.value,Wert
|
||||||
col.avg,Ø-Kauf
|
col.avg,Ø-Kauf
|
||||||
|
col.dirty,Kontaminiert
|
||||||
bank.cash.k,Credits
|
bank.cash.k,Credits
|
||||||
bank.rent.k,Miete
|
bank.rent.k,Miete
|
||||||
bank.rent.v,"{0}, fällig in {1} Tg."
|
bank.rent.v,"{0}, fällig in {1} Tg."
|
||||||
@@ -152,13 +151,12 @@ stable.ok,Gekoppelt
|
|||||||
stable.depeg,Entkoppelt
|
stable.depeg,Entkoppelt
|
||||||
stable.warn,Warnung: Staking-Reservedeckung knapp
|
stable.warn,Warnung: Staking-Reservedeckung knapp
|
||||||
stable.spiral,Kollaps
|
stable.spiral,Kollaps
|
||||||
aml.taint,Konto-Kontaminationsanteil: {0}%
|
|
||||||
mixer.h,Mixer
|
mixer.h,Mixer
|
||||||
mixer.ok,Status: Normalbetrieb
|
mixer.ok,Status: Normalbetrieb
|
||||||
mixer.sanctioned,Status: sanktioniert (noch {0} Tag(e)). Währenddessen abgehobene Coins werden markiert.
|
mixer.sanctioned,Status: Sanktioniert (noch {0} T.). Währenddessen fällige Auszahlungen werden nicht gewaschen und kommen vollständig kontaminiert zurück.
|
||||||
mixer.pending,Ausstehende Einzahlungen
|
mixer.pending,Ausstehende Einzahlungen
|
||||||
mixer.none,Keine ausstehenden Einzahlungen.
|
mixer.none,Keine ausstehenden Einzahlungen.
|
||||||
mixer.col.taint,Kontamination
|
mixer.col.taint,Kontaminiert
|
||||||
mixer.col.ready,Fällig
|
mixer.col.ready,Fällig
|
||||||
mixer.day,Tag {0}
|
mixer.day,Tag {0}
|
||||||
mixer.deposit,Einzahlung
|
mixer.deposit,Einzahlung
|
||||||
@@ -169,11 +167,12 @@ mixer.go,In Mixer einzahlen
|
|||||||
mixer.min,Einzahlungen müssen mindestens {0} Credits wert sein.
|
mixer.min,Einzahlungen müssen mindestens {0} Credits wert sein.
|
||||||
mixer.done,{0} {1} eingezahlt; Rückerhalt an Tag {2}.
|
mixer.done,{0} {1} eingezahlt; Rückerhalt an Tag {2}.
|
||||||
mixer.upgrade.title,Mixer
|
mixer.upgrade.title,Mixer
|
||||||
mixer.upgrade.desc,Schaltet den Mixer auf der Graunetz-Seite des Terminals frei: Kontaminierte Coins einzahlen und Tage später mit reduzierter Kontamination zurückerhalten. Auszahlungen frisch gemixter Coins werden strenger geprüft; bei Razzien kann der Mixer sanktioniert werden und währenddessen abgehobene Coins werden markiert.
|
mixer.upgrade.desc,"Schaltet den Mixer auf der Graunetz-Seite des Terminals frei: Kontaminierte Coins einzahlen und Tage später zurückerhalten, wobei weniger davon kontaminiert sind. Während Razzien kann der Mixer sanktioniert werden; in dieser Zeit fällige Auszahlungen kommen vollständig kontaminiert zurück."
|
||||||
news.sanction.title,Mixer auf Sanktionsliste gesetzt
|
news.sanction.title,Mixer auf Sanktionsliste gesetzt
|
||||||
news.sanction.desc,Security hat eine Reihe von Mixing-Diensten sanktioniert. In den nächsten Tagen aus Mixern abgehobene Gelder gelten als verdächtig.
|
news.sanction.desc,Security hat eine Reihe von Mixing-Diensten sanktioniert. In den kommenden Tagen aus Mixern abgehobene Gelder werden als kontaminierte Gelder behandelt.
|
||||||
nightlog.mixer,Mixer zahlte {0} {1} zurück; Kontamination {2} -> {3}.
|
nightlog.mixer,Mixer zahlte {0} {1} zurück; Kontamination {2} -> {3}.
|
||||||
nightlog.mixer_flag," (während Sanktionen abgehoben; Adresse markiert)"
|
nightlog.mixer_flag," (während der Sanktionen abgehoben; vollständig als kontaminiert markiert)"
|
||||||
|
nightlog.mixer_flag.trap," (Security markiert die abgehobenen Coins als kontaminiert)"
|
||||||
nightlog.mixer_rug,Der Mixer-Betreiber ist untergetaucht: {0} {1} kehrten nie zurück.
|
nightlog.mixer_rug,Der Mixer-Betreiber ist untergetaucht: {0} {1} kehrten nie zurück.
|
||||||
web3.sub.trade,Handel
|
web3.sub.trade,Handel
|
||||||
gray.sub.mixer,Mixer
|
gray.sub.mixer,Mixer
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Schmuggelware (hoch)
|
|||||||
black.kind.Tech,Hightech (Aufpreis)
|
black.kind.Tech,Hightech (Aufpreis)
|
||||||
nightlog.bm.ready,"Schwarzmarkt: {0} eingetroffen; sobald du öffnest, kommt ein Kurier vorbei."
|
nightlog.bm.ready,"Schwarzmarkt: {0} eingetroffen; sobald du öffnest, kommt ein Kurier vorbei."
|
||||||
guide.web3.title,Web3-Handbuch
|
guide.web3.title,Web3-Handbuch
|
||||||
guide.web3.text,"Bank und Handel: Die Bankseite ist nur lesbar und zeigt Bargeld, Miete und das CRC auf dem Poinbase-Konto. Die Seite „Guthaben“ von Poinbase regelt Ein- und Auszahlungen; zuerst wird der Coin gewählt: CRC geht über das Bankkonto oder die Wallet, alle anderen Coins nur über die Wallet. Eine Einzahlung von der Bank wandelt Credits in CRC auf deinem Poinbase-Konto um; eine Auszahlung auf die Bank wandelt CRC zurück in Credits um und durchläuft eine Compliance-Prüfung, die die Kontamination des Poinbase-Kontos bewertet. Eine Auszahlung auf eine Wallet braucht die Zieladresse und mehrere Bestätigungen bis zur Gutschrift; die Gasgebühr ist fest auf Normal gesetzt und wird vom abgehenden Coin abgezogen. Ist das Adressformat oder die Prüfziffer falsch, wird abgelehnt; bei einer formal gültigen Adresse, die niemand nutzt, sind die Coins nach der Überweisung weg.¶Handel: PSC steht für Probably Stolen Coin, den durch Grafikkarten und Miner geschürften Coin. Der Poinbase-Spotmarkt hat zwei Paare, PSC/CRC und SPARK/CRC, je nach dem im Chart gewählten Coin. Käufe und Verkäufe werden beide als Menge des gehandelten Coins eingegeben; die Vorschau zeigt den gezahlten oder erhaltenen Notierungs-Coin, der Durchschnittspreis enthält die Gebühr, die Slippage nicht.¶Auf der Web3-Handelsseite lassen sich beliebige zwei Coins tauschen, stets über CRC als Zwischenschritt: Ist CRC eine Seite, läuft der Tausch über einen Pool, sonst über zwei Pools mit zwei Gebühren und sich addierender Slippage; die Vorschau zeigt Menge, Anzahl der Pools und Verlust. Stablecoin-Tausch (CRT oder CRA gegen CRC) läuft über Stable-Pools: {StableFee:%} Gebühr und kaum Slippage nahe der Bindung; beim Depeg wird die Liquidität dünner, beim Zusammenbruch wird sie abgezogen und die Slippage springt.§Hardware-Wallets: On-Chain-Coins liegen auf PLEDGER-Hardware-Wallets, jede mit eigenem Guthaben und eigener Kontamination. Eine Wallet ist ein Gegenstand: Ziehe sie auf das Handelsterminal, um sie zu laden. Öffne sie auf der Wallets-Seite des Terminals; verbinde und trenne sie oben rechts im Terminal. Der Handel der Web3-Seite sowie Shop und Mixer der Graunetz-Seite nutzen die verbundene Wallet; ohne Wallet oder ohne Verbindung sind sie nur lesbar und alle Guthaben zeigen 0. Kunden, die in Coins zahlen, zahlen auf die verbundene Wallet.¶Zahlungen (Shop, Mixer, Ponero-Schalter, Einstellgebühren) beginnen als Rechnung auf dem Handelsterminal; gib die Empfängeradresse auf der Wallet ein und halte zum Signieren ✓ gedrückt. Die letzten beiden Zeichen einer Adresse bilden eine Prüfsumme, sodass ein einzelner Tippfehler meist abgefangen wird; gelegentlich ist die Eingabe dennoch gültig und die Coins gehen an eine ungenutzte Adresse. Auch DEX-Swaps erfordern eine Signatur auf der Wallet.¶Poinbase ist ein Verwahrkonto; Einzahlungen erfolgen von der Wallet an die Einzahlungsadresse von Poinbase (nur PSC, CRC und SPARK; die regulierte Börse nimmt weder das CRT des Schwarzmarkts noch das CRA der Revolution, und die Wallet blockiert Überweisungen dieser Coins an die Einzahlungsadresse), Auszahlungen werden auf der Seite „Guthaben“ von Poinbase gestartet. Der Explorer auf der Wallets-Seite zeigt Überweisungen nach Adresse, ausschließlich tatsächlich erfolgte: jede Bewegung in und aus deinen Wallets (Überweisungen, DEX-Tausch und andere Vertragsaufrufe, Miner-Erträge, Auszahlungen, Coins, die andere dir schicken); Ponero ist ein Privacy Coin und erscheint nie. Weitere Hardware-Wallets verkauft Dr. Jackson; ziehe eine auf das Handelsterminal, um sie hinzuzufügen, bis zu {WalletMax}. Im Shop gibt es günstigere Exemplare. Eine nicht mehr benötigte Wallet kann auf der Wallets-Seite zerstört werden; ihre Coins sind dauerhaft verloren, ebenso alles, was danach an ihre Adresse gesendet wird.¶Überweisungen kosten Gasgebühren: langsam, normal oder schnell, und die Gas-Preise steigen und fallen im Wochenverlauf; bei Netzwerküberlastung steigen die Gasgebühren und langsame Transaktionen können aus dem Mempool fliegen. Vor dem Senden die vollständige Adresse prüfen.§Staking: Im Revolution-Pool gestakte CRA erzielen einen Tageszinssatz, der dem Einsatz zugeschlagen wird; eine Auszahlung erfordert einen vorherigen Antrag und vier Tage Wartezeit – ohne Zinsen während des Wartens und ohne vorzeitige Entnahme. CRA ist teilbesichert: Jedes CRA wird von CRC-Reserven der Revolution und vom Ausgleichstoken SPARK gedeckt; Reservedeckung und Besicherungsquote stehen auf der Staking-Seite. Zinsen werden in neuem, unbesichertem CRA gezahlt, das die Reservedeckung verwässert, umso schneller, je mehr gestakt ist; bei zu niedriger Deckung senkt die Revolution den Zinssatz. Die Revolution greift manchmal in die Reserve; zuvor gibt es Gerüchte, das ist das Vorzeichen. Fällt die Deckung danach unter {CraCrashRatio:%}, bricht das System zusammen: CRA ist binnen drei Tagen wertlos und vier Tage Entsperrung sind zu langLine truncated
|
guide.web3.text,"Bank und Handel: Die Bank-Seite ist schreibgeschützt und zeigt Bargeld, Miete und die CRC auf deinem Poinbase-Konto an. Die Guthaben-Seite von Poinbase wickelt Ein- und Auszahlungen ab; wähle zuerst den Coin: CRC kann über das Bankkonto oder eine Wallet laufen, jeder andere Coin nur über eine Wallet. Einzahlungen von der Bank wandeln Credits in CRC auf deinem Poinbase-Konto um; Auszahlungen auf das Bankkonto wandeln CRC ohne Prüfung wieder in Credits um (das Poinbase-Konto hält ausschließlich sauberes Geld). Auszahlungen an eine Wallet erfordern eine Empfängeradresse und einige Bestätigungen, bevor sie ankommen; die Gas-Gebühr ist fest auf der normalen Stufe und wird vom gesendeten Coin abgezogen. Ein falsches Adressformat oder eine fehlerhafte Prüfsumme wird abgelehnt; eine korrekt formatierte Adresse, die niemand nutzt, bedeutet, dass die Coins verloren sind.¶Handel: PSC steht für Probably Stolen Coin, den von Grafikkarten und Minern geschürften Coin. Der Poinbase-Spotmarkt hat zwei Handelspaare, PSC/CRC und SPARK/CRC, die dem im Chart ausgewählten Coin folgen. Käufe und Verkäufe werden jeweils als Betrag des gehandelten Coins eingegeben; die Vorschau zeigt die gezahlte oder erhaltene Notierungswährung, der Durchschnittspreis enthält die Gebühr, die Slippage nicht.¶Die Web3-Handelsseite kann zwei beliebige Coins tauschen, immer über CRC: Liegt CRC auf einer Seite, nutzt sie einen Pool, andernfalls zwei Pools mit doppelten Gebühren und gestapelter Slippage; die Vorschau zeigt den erhaltenen Betrag, die durchlaufenen Pools und den Verlust. Stablecoin-Swaps (CRT oder CRA gegen CRC) nutzen Stable-Pools: eine Gebühr von {StableFee:%} und nahezu keine Slippage nahe der Bindung; bei einer Entkopplung wird die Liquidität dünner, und bei einem Kollaps wird sie abgezogen und die Slippage springt in die Höhe.§Hardware-Wallets: On-Chain-Coins liegen in PLEDGER-Hardware-Wallets, jede mit eigenen Guthaben und kontaminierten Coins (bei jedem Coin wird erfasst, wie viele davon kontaminiert sind; siehe Kontamination). Eine Wallet ist ein Gegenstand: Ziehe sie auf das Handelsterminal, um sie zu laden. Öffne sie auf der Wallets-Seite des Terminals; das Verbinden und Trennen erfolgt oben rechts am Terminal. Der Handel auf der Web3-Seite sowie der Shop und Mixer auf der Graunetz-Seite nutzen die verbundene Wallet; ohne Wallet oder Verbindung sind sie schreibgeschützt und jedes Guthaben steht bei 0. Kunden, die mit Coins zahlen, zahlen auf die verbundene Wallet ein.¶Zahlungen (Shop, Mixer, Ponero-Schalter, Listungsgebühren) beginnen als Rechnung auf dem Terminal; tippe die Empfängeradresse auf der Wallet ein und halte ✓ gedrückt, um zu signieren. Die letzten beiden Zeichen einer Adresse sind eine Prüfsumme, sodass ein Tippfehler um ein Zeichen meistens abgefangen wird; gelegentlich ist sie zufällig gültig und die Coins gehen an eine Adresse, die niemand nutzt. DEX-Swaps erfordern ebenfalls eine Signatur auf der Wallet.¶Poinbase ist ein verwahrtes Konto; Einzahlungen werden von einer Wallet an die Einzahlungsadresse von Poinbase gesendet (nur PSC, CRC und SPARK; die konforme Börse akzeptiert weder das CRT des Schwarzmarkts noch das CRA der Revolution, und die Wallet blockiert das Senden an die Einzahlungsadresse; es können nur saubere Coins eingezahlt werden, siehe Kontamination) und Auszahlungen werden auf der Guthaben-Seite von Poinbase veranlasst. Der Explorer auf der Wallets-Seite sucht Überweisungen nach Adresse und zeigt nur tatsächlich erfolgte Überweisungen an: jede Bewegung in und aus deinen Wallets (Überweisungen, DEX-Swaps und andere Contract-Aufrufe, Miner-Auszahlungen, Auszahlungen, von anderen gesendete Coins); Ponero ist ein Privacy Coin und wird nie angezeigt. Weitere Hardware-Wallets werden von Dr. Jackson verkauft; ziehe eine auf das Handelsterminal, um sie hinzuzufügen, bis zu maximal {WalletMax}. Der Shop bietet günstigere an. Eine Wallet, die du nicht mehr benötigst, kann auf der Wallets-Seite zerstört werden; ihre Coins sind unwiderruflich verloren, und alles, was danach an ihre Adresse gesendet wird, ist ebenfalls verloren.¶Überweisungen zahlen eine Gas-Gebühr: langsam, normal oder schnell, und die Gas-Preise steigen und fallen über etwa eine Woche hinweg; bei Netzwerküberlastung steigen die Gas-Gebühren und langsame Transaktionen können aus dem Mempool verworfen werden. Prüfe vor dem Absenden die vollständige Adresse.§Staking: Im Revolution-Pool gestakte CRA erzielen einen Tageszinssatz, der dem Einsatz zugeschlagen wird; eine Auszahlung erfordert einen vorherigen Antrag und vier Tage Wartezeit – ohne Zinsen während des Wartens und ohne vorzeitige Entnahme. CRA ist teilbesichert: Jedes CRA wird von CRC-Reserven der Revolution und vom Ausgleichstoken SPARK gedeckt; Reservedeckung und Besicherungsquote stehen auf der Staking-Seite. Zinsen werden in neuem, unbesichertem CRA gezahlt, das die Reservedeckung verwässert, umso schnLine truncated
|
||||||
courier.odd1,...Paket ist da.
|
courier.odd1,...Paket ist da.
|
||||||
courier.odd2,(Seine Hand bleibt in der Tasche.) Hier unterschreiben.
|
courier.odd2,(Seine Hand bleibt in der Tasche.) Hier unterschreiben.
|
||||||
courier.sign,Unterschreiben
|
courier.sign,Unterschreiben
|
||||||
@@ -361,10 +360,11 @@ hw.wallet.n,Wallet {0}
|
|||||||
hw.review.own,Eigene Wallet: {0}
|
hw.review.own,Eigene Wallet: {0}
|
||||||
hw.review.poinbase,Poinbase-Einzahlungsadresse
|
hw.review.poinbase,Poinbase-Einzahlungsadresse
|
||||||
poin.deposit,Einzahlungsadresse: {0}
|
poin.deposit,Einzahlungsadresse: {0}
|
||||||
|
poin.deposit.clean,In {0} einzahlbare saubere Coins: {1}
|
||||||
wallets.count,Wallets {0}/{1}
|
wallets.count,Wallets {0}/{1}
|
||||||
wallets.col.name,Name
|
wallets.col.name,Name
|
||||||
wallets.col.addr,Adresse
|
wallets.col.addr,Adresse
|
||||||
wallets.col.taint,Kontamination
|
wallets.col.taint,Kontaminiert
|
||||||
wallets.open,Öffnen
|
wallets.open,Öffnen
|
||||||
wallets.use,Verbinden
|
wallets.use,Verbinden
|
||||||
wallets.current,Verbunden
|
wallets.current,Verbunden
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Einfügen
|
|||||||
hw.copied,Adresse kopiert.
|
hw.copied,Adresse kopiert.
|
||||||
hw.copied.addr,{0} kopiert
|
hw.copied.addr,{0} kopiert
|
||||||
hw.balance.frozen," (gefroren {0})"
|
hw.balance.frozen," (gefroren {0})"
|
||||||
|
hw.balance.dirty," ({0} kontaminiert)"
|
||||||
wallets.destroy,Zerstören
|
wallets.destroy,Zerstören
|
||||||
wallets.destroy.sure,Bestätigen
|
wallets.destroy.sure,Bestätigen
|
||||||
wallets.destroyed,{0} zerstört: {1}
|
wallets.destroyed,{0} zerstört: {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Wasser (Obere Ebene)
|
|||||||
nightlog.predict.win,"Prognose richtig: „{0}“, {1} ausgezahlt."
|
nightlog.predict.win,"Prognose richtig: „{0}“, {1} ausgezahlt."
|
||||||
nightlog.predict.lose,"Prognose falsch: „{0}“, Einsatz {1} verloren."
|
nightlog.predict.lose,"Prognose falsch: „{0}“, Einsatz {1} verloren."
|
||||||
nightlog.predict.void,"Prognose ungültig: „{0}“, Einsatz {1} erstattet."
|
nightlog.predict.void,"Prognose ungültig: „{0}“, Einsatz {1} erstattet."
|
||||||
nightlog.predict.insider,"""{0}"" mit {1} abgerechnet. Die Polizei vermutet Insiderhandel; die Auszahlung wird markiert und die Kontamination der Wallet steigt um {2}."
|
nightlog.predict.insider,"""{0}"" für {1} abgerechnet. Die Polizei vermutet Insiderhandel; {2} CRC davon werden als kontaminiert markiert."
|
||||||
predict.tab.markets,Märkte
|
predict.tab.markets,Märkte
|
||||||
predict.tab.intel,Informationen
|
predict.tab.intel,Informationen
|
||||||
predict.acct.crt,{0}: CRT {1}
|
predict.acct.crt,{0}: CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}: Operation geplant
|
|||||||
predict.brief.none,{0}: Keine Operation möglich
|
predict.brief.none,{0}: Keine Operation möglich
|
||||||
predict.brief.can,{0}: Kann {1} starten
|
predict.brief.can,{0}: Kann {1} starten
|
||||||
predict.clue.push,Preis um {0}% bewegt: hohes Manipulationsrisiko
|
predict.clue.push,Preis um {0}% bewegt: hohes Manipulationsrisiko
|
||||||
nightlog.predict.manip,"""{0}"" mit {1} abgerechnet. Die Aufsichtsbehörden vermuten Marktmanipulation; die Auszahlung wird markiert und die Kontamination der Wallet steigt um {2}."
|
nightlog.predict.manip,"""{0}"" für {1} abgerechnet. Die Aufsichtsbehörden vermuten, dass du den Preis manipuliert hast; {2} CRC davon werden als kontaminiert markiert."
|
||||||
news.manip.title,Börse untersucht ungewöhnlichen Handel
|
news.manip.title,Börse untersucht ungewöhnlichen Handel
|
||||||
news.manip.desc,"Die Aufsichtsbehörden melden, dass jemand den Preis mit großen Spot-Orders bewegt und aus Derivaten sowie Prognosen profitiert hat; die betroffenen Konten wurden markiert."
|
news.manip.desc,"Die Aufsichtsbehörden melden, dass jemand den Preis mit großen Spot-Orders bewegt und aus Derivaten sowie Prognosen profitiert hat; die betroffenen Konten wurden markiert."
|
||||||
taint.overflow,Die Kontamination übersteigt nun den Wert der Wallet; der Überschuss von {0} wird als Betrug erfasst.
|
perp.manip,Mit Gewinn von {0} geschlossen. Die Aufsichtsbehörden vermuten Marktmanipulation; Betrugsbeweise in deiner Akte: {1}.
|
||||||
perp.manip,Mit Gewinn von {0} geschlossen. Die Aufsichtsbehörden vermuten Marktmanipulation; der Gewinn wird markiert und die Kontamination des Poinbase-Kontos steigt um {1}.
|
|
||||||
web3.sub.ponzi,Rendite
|
web3.sub.ponzi,Rendite
|
||||||
ponzi.h,Schneeballsystem
|
ponzi.h,Schneeballsystem
|
||||||
ponzi.acct,Emittenten-Wallet {0}: CRC {1}
|
ponzi.acct,Emittenten-Wallet {0}: CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Poinbase-Support
|
|||||||
scam.support.1,"Hallo, hier ist der Poinbase-Support. Wir haben eine ungewöhnliche Anmeldung in Ihrem Konto festgestellt und es wurde markiert."
|
scam.support.1,"Hallo, hier ist der Poinbase-Support. Wir haben eine ungewöhnliche Anmeldung in Ihrem Konto festgestellt und es wurde markiert."
|
||||||
scam.support.2,Bitte senden Sie heute {0} CRC zur Verifizierung an die sichere Adresse {1}; der Betrag wird direkt im Anschluss zurückerstattet.
|
scam.support.2,Bitte senden Sie heute {0} CRC zur Verifizierung an die sichere Adresse {1}; der Betrag wird direkt im Anschluss zurückerstattet.
|
||||||
scam.support.3,"Andernfalls wird das Konto dauerhaft gefroren. Ich muss los, denken Sie an die Überweisung."
|
scam.support.3,"Andernfalls wird das Konto dauerhaft gefroren. Ich muss los, denken Sie an die Überweisung."
|
||||||
predict.sold.caught,"Verkauft, {0} erhalten. Die Polizei vermutet Insiderhandel; der Erlös wird markiert und die Kontamination der Wallet steigt um {1}."
|
predict.sold.caught,"Verkauft, {0} erhalten. Die Polizei vermutet Insiderhandel; {1} CRC davon werden als kontaminiert markiert."
|
||||||
predict.row.move," (letzte Nacht {0} {1})"
|
predict.row.move," (letzte Nacht {0} {1})"
|
||||||
predict.stats.h,Verlauf (durchschnittl. Eröffnungskurs / tatsächliche Quote)
|
predict.stats.h,Verlauf (durchschnittl. Eröffnungskurs / tatsächliche Quote)
|
||||||
predict.stats.row,"{0}: {1} Märkte, Eröffnungsschnitt {2}, eingetreten {3}%"
|
predict.stats.row,"{0}: {1} Märkte, Eröffnungsschnitt {2}, eingetreten {3}%"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,PSC-Preis
|
|||||||
predict.kind.Gas,Gas
|
predict.kind.Gas,Gas
|
||||||
predict.kind.Cra,CRA-Warnung
|
predict.kind.Cra,CRA-Warnung
|
||||||
predict.kind.Era,Miner-Ära
|
predict.kind.Era,Miner-Ära
|
||||||
|
predict.kind.Trial,Tumbler-Prozess
|
||||||
nightlog.predict.move,Prognose „{0}“ geändert: {1} -> {2}
|
nightlog.predict.move,Prognose „{0}“ geändert: {1} -> {2}
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,{0}-Tageschart: Noch keine Historie; Aufzeichnung beginnt heute.
|
chart.empty,{0}-Tageschart: Noch keine Historie; Aufzeichnung beginnt heute.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"Die Revolution hat Berichten zufolge Beweise für i
|
|||||||
news.story.serpico_bm.title,Schwarzmarkt trifft stille Vereinbarung
|
news.story.serpico_bm.title,Schwarzmarkt trifft stille Vereinbarung
|
||||||
news.story.serpico_bm.desc,"Ein internes Security-Dokument wechselte auf dem Schwarzmarkt den Besitzer. Die Abrechnung im Darknet läuft seither spürbar stabiler, und CRT-Einlösungen liefen ausnahmslos reibungslos."
|
news.story.serpico_bm.desc,"Ein internes Security-Dokument wechselte auf dem Schwarzmarkt den Besitzer. Die Abrechnung im Darknet läuft seither spürbar stabiler, und CRT-Einlösungen liefen ausnahmslos reibungslos."
|
||||||
news.story.serpico_sec.title,Security leitet interne Säuberung ein
|
news.story.serpico_sec.title,Security leitet interne Säuberung ein
|
||||||
news.story.serpico_sec.desc,"Die Security kündigte eine umfassende Untersuchung interner Korruption und eine strengere Überwachung von Geldflüssen an. Poinbase verschärft Auszahlungsprüfungen, und Mixer-Dienste wurden namentlich genannt."
|
news.story.serpico_sec.desc,Security kündigte eine umfassende Untersuchung interner Korruption und eine strengere Überwachung der Geldströme an; Mixer-Dienste wurden namentlich genannt.
|
||||||
news.story.eleanor_leak.title,Zuchtdaten der Nährfrucht durchgesickert
|
news.story.eleanor_leak.title,Zuchtdaten der Nährfrucht durchgesickert
|
||||||
news.story.eleanor_leak.desc,"Die Zeitung der Unteren Ebene veröffentlichte Forschungsergebnisse, mit denen die Nährfrucht wieder Samen bilden kann; Pastelle-Aktien stürzten ab. Die Depotbank für Gelder der Oberen Ebene meldet faule Kredite, und die Revolution gewinnt an Auftrieb."
|
news.story.eleanor_leak.desc,"Die Zeitung der Unteren Ebene veröffentlichte Forschungsergebnisse, mit denen die Nährfrucht wieder Samen bilden kann; Pastelle-Aktien stürzten ab. Die Depotbank für Gelder der Oberen Ebene meldet faule Kredite, und die Revolution gewinnt an Auftrieb."
|
||||||
news.story.eleanor_return.title,Pastelle stellt gestohlene Daten sicher
|
news.story.eleanor_return.title,Pastelle stellt gestohlene Daten sicher
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,Der als Tumbler bekannte Mixer-Betreiber wurde in der U
|
|||||||
news.tumbler.sold.title,Mixer-Dienst wechselt den Besitzer
|
news.tumbler.sold.title,Mixer-Dienst wechselt den Besitzer
|
||||||
news.tumbler.sold.desc,"Es heißt, die Signaturschlüssel eines Mixer-Dienstes der Unteren Ebene seien in die Hände des Schwarzmarkts gefallen, und die Gebühren stiegen sofort. Nutzer fürchten um ihre Gelder."
|
news.tumbler.sold.desc,"Es heißt, die Signaturschlüssel eines Mixer-Dienstes der Unteren Ebene seien in die Hände des Schwarzmarkts gefallen, und die Gebühren stiegen sofort. Nutzer fürchten um ihre Gelder."
|
||||||
nightlog.tumbler.gift,Tumbler nahm das Key-Drive zurück und hinterließ {0} CRT als Dank (gesendet an {1}); Mixer-Gebühren halbiert.
|
nightlog.tumbler.gift,Tumbler nahm das Key-Drive zurück und hinterließ {0} CRT als Dank (gesendet an {1}); Mixer-Gebühren halbiert.
|
||||||
|
agent.name,Sicherheitsagent
|
||||||
|
agent.v1.1,Security. Entschuldigung für die Störung.
|
||||||
|
agent.v1.2,Wir suchen jemanden namens Tumbler. Er betreibt einen On-Chain-Mixerdienst.
|
||||||
|
agent.v1.3,Er wurde in dieser Gegend gesehen.
|
||||||
|
agent.ask,War er in deinem Laden?
|
||||||
|
agent.choice.yes,[Sagen: Ein paar Mal]
|
||||||
|
agent.choice.no,[Sagen: Nie gesehen]
|
||||||
|
agent.yes1,Danke für die Kooperation. Die Security wird sich das merken.
|
||||||
|
agent.no1,"So ist das also. Falls dir noch etwas einfällt, weißt du, wo du uns findest."
|
||||||
|
agent.search.1,"Wir sehen uns wieder. Wir haben gehört, dass du etwas für diesen Mann aufbewahrst."
|
||||||
|
agent.search.2,Routinedurchsuchung. Bitte kooperieren.
|
||||||
|
agent.search.found,Gefunden. Das nehmen wir mit.
|
||||||
|
agent.search.none,... Nichts. Entschuldigung für die Störung.
|
||||||
|
tumbler.v4.seized.1,"Ich habe gehört, die Security hat deinen Laden durchsucht."
|
||||||
|
tumbler.v4.seized.2,Sie haben jetzt den Schlüssel. Die Aufzeichnungen aller Nutzer werden aufgedeckt.
|
||||||
|
tumbler.v4.seized.3,"Was auch immer du ihnen erzählt hast, ich will es gar nicht mehr wissen."
|
||||||
|
nightlog.tumbler.leak,Security nutzte Tumblers Signaturschlüssel zur Rekonstruktion der Mixer-Aufzeichnungen: Auszahlungen: {0} ({1} Kontamination reingewaschen); Betrugsbeweise in deiner Akte: {2}.
|
||||||
|
nightlog.tumbler.leak.none,"Security hat Tumblers Signaturschlüssel verwendet, um die Mixer-Aufzeichnungen zu rekonstruieren. Du hast in letzter Zeit nichts aus dem Mixer abgehoben."
|
||||||
|
nightlog.tumbler.note,"Ein Zettel wurde unter der Tür durchgeschoben: ""Du schuldest mir was, und ich hole es mir zurück. —T"""
|
||||||
|
nightlog.tumbler.tip,Nachricht von Tumbler: Die Security geht morgen womöglich gegen die Mixer-Dienste vor.
|
||||||
|
news.tumbler.leak.title,Security rekonstruiert Mixer-Aufzeichnungen
|
||||||
|
news.tumbler.leak.desc,"Die Security gibt an, den Signaturschlüssel eines Mixer-Dienstes erhalten zu haben, und will damit Gelder zurückverfolgen, die im vergangenen Monat über diesen Dienst gewaschen wurden."
|
||||||
|
news.trial.pro.title,"Tumbler-Prozess, Tag {0}: Anklage gewinnt an Boden"
|
||||||
|
news.trial.def.title,"Tumbler-Prozess, Tag {0}: Verteidigung gewinnt an Boden"
|
||||||
|
news.trial.pro.desc1,"Die Anklage legte Server-Logs des Mixer-Knotens vor und gab an, sie stimmten eins zu eins mit den Signaturen des Angeklagten überein."
|
||||||
|
news.trial.pro.desc2,"Ein ehemaliger Partner sagte aus, der Angeklagte habe gewusst, dass die Kundengelder vom Schwarzmarkt stammten."
|
||||||
|
news.trial.pro.desc3,Die Anklage zeigte Überweisungen zwischen der Wallet des Angeklagten und mehreren Betrugsadressen.
|
||||||
|
news.trial.def.desc1,Die Verteidigung verwies auf Mängel bei der Beweissicherung während der Beschlagnahmung des Knotens; einige Logs könnten manipuliert worden sein.
|
||||||
|
news.trial.def.desc2,"Ein Gutachter der Verteidigung sagte aus, der Mixer-Contract sei Open-Source-Code und der Angeklagte könne nicht kontrollieren, wer ihn nutze."
|
||||||
|
news.trial.def.desc3,"Der Hauptzeuge der Anklage änderte seine Aussage im Zeugenstand und erklärte, er könne sich nicht erinnern, ob der Angeklagte davon wusste."
|
||||||
|
news.trial.convict.title,Tumbler schuldig gesprochen
|
||||||
|
news.trial.convict.desc,"Das Gericht sprach den als Tumbler bekannten Mixer-Betreiber der Geldwäsche schuldig. Die Security erklärte, der Mixer-Dienst werde nicht wieder öffnen."
|
||||||
|
news.trial.acquit.title,Tumbler freigesprochen
|
||||||
|
news.trial.acquit.desc,"Aus Mangel an Beweisen sprach das Gericht den als Tumbler bekannten Mixer-Betreiber frei und entließ ihn. Er verließ das Gerichtsgebäude, ohne Fragen von Reportern zu beantworten."
|
||||||
|
news.tumbler.bmrug.title,Mixer-Dienst verschwindet mit Geldern
|
||||||
|
news.tumbler.bmrug.desc,"Ein vom Schwarzmarkt übernommener Mixer-Dienst stoppte plötzlich die Auszahlungen, und die Gelder im Contract wurden abgezogen. Nutzer in den Foren berichten von einem Totalverlust."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,Neuer Mixer-Dienst {0} geht live
|
||||||
|
news.mixer.rebrand.desc,"Ein Mixer-Dienst namens {0} ging kürzlich live und behauptet, keine Logs und keine Hintertüren zu haben. Einige haben bemerkt, dass sein Contract dem zuvor geschlossenen Dienst stark ähnelt."
|
||||||
|
predict.q.trial,{0}: Tumbler schuldig gesprochen
|
||||||
|
predict.clue.trial,"Prozessberichte: Anklage im Vorteil ({0} d), Verteidigung im Vorteil ({1} d)"
|
||||||
mixer.status.closed,Status: Abgeschaltet
|
mixer.status.closed,Status: Abgeschaltet
|
||||||
yield.sub.pools,Rendite-Pools
|
yield.sub.pools,Rendite-Pools
|
||||||
yield.sub.mine,System auflegen
|
yield.sub.mine,System auflegen
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Passen
|
|||||||
otc.msg.gone,Der Kunde ist gegangen.
|
otc.msg.gone,Der Kunde ist gegangen.
|
||||||
otc.msg.cash,Nicht genug Bargeld.
|
otc.msg.cash,Nicht genug Bargeld.
|
||||||
otc.msg.sting,"Der Kunde war ein verdeckter Ermittler: {0} Bargeld beschlagnahmt, Hehlerei erfasst."
|
otc.msg.sting,"Der Kunde war ein verdeckter Ermittler: {0} Bargeld beschlagnahmt, Hehlerei erfasst."
|
||||||
otc.msg.bought,"{0} {1} erhalten, {2} Bargeld gezahlt."
|
otc.msg.bought,"{0} {1} erhalten ({3} davon kontaminiert), {2} in bar gezahlt."
|
||||||
otc.msg.sold,"{0} {1} gesendet, {2} Bargeld erhalten."
|
otc.msg.sold,"{0} {1} gesendet, {2} Bargeld erhalten."
|
||||||
gray.sub.own,Eigener Mixer
|
gray.sub.own,Eigener Mixer
|
||||||
ownmix.h,Eigener Mixer
|
ownmix.h,Eigener Mixer
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,Du hast nicht mal das Bargeld? Vergiss es.
|
|||||||
otc.nowallet,"Keine Wallet verbunden, wohin sollen die Coins? Vergiss es."
|
otc.nowallet,"Keine Wallet verbunden, wohin sollen die Coins? Vergiss es."
|
||||||
otc.sting,"Keine Bewegung. Security. Ankauf gestohlener Gelder: Das Bargeld wird beschlagnahmt, und das kommt in deine Akte."
|
otc.sting,"Keine Bewegung. Security. Ankauf gestohlener Gelder: Das Bargeld wird beschlagnahmt, und das kommt in deine Akte."
|
||||||
hw.err.poinbase,Poinbase nimmt kein {0} an.
|
hw.err.poinbase,Poinbase nimmt kein {0} an.
|
||||||
|
hw.err.tainted,{0} der {1} dieser Wallet sind kontaminiert und Poinbase akzeptiert nur saubere Coins: maximal {2} {1}.
|
||||||
@@ -22,7 +22,7 @@ tab.report,Report
|
|||||||
wallet.line,{0}: {1} (about {2} credits)
|
wallet.line,{0}: {1} (about {2} credits)
|
||||||
wallet.empty,The wallet is empty.
|
wallet.empty,The wallet is empty.
|
||||||
wallet.total,Total value: {0} credits
|
wallet.total,Total value: {0} credits
|
||||||
wallet.taint,Tainted value: {0} credits
|
wallet.taint,Dirty coins: {0} credits
|
||||||
trade.amount,Amount
|
trade.amount,Amount
|
||||||
trade.deposit,Deposit credits as CRC
|
trade.deposit,Deposit credits as CRC
|
||||||
trade.withdraw,Withdraw CRC as credits
|
trade.withdraw,Withdraw CRC as credits
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Not enough balance.
|
|||||||
msg.trade,"Paid {0} {1}, received {2} {3}."
|
msg.trade,"Paid {0} {1}, received {2} {3}."
|
||||||
msg.deposit,Deposited {0} credits as CRC.
|
msg.deposit,Deposited {0} credits as CRC.
|
||||||
msg.cashout,Received {0} credits. Tax {1} credits.
|
msg.cashout,Received {0} credits. Tax {1} credits.
|
||||||
msg.aml_light,Compliance review: {0} credits of tainted funds were withheld.
|
|
||||||
msg.aml_heavy,Compliance review: {0} credits of tainted funds were seized and reported to Security.
|
|
||||||
report.none,No mining report yet.
|
report.none,No mining report yet.
|
||||||
report.day,Night of day {0}
|
report.day,Night of day {0}
|
||||||
report.rigs,Rigs with power: {0} of {1}
|
report.rigs,Rigs with power: {0} of {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Asset
|
|||||||
col.amount,Amount
|
col.amount,Amount
|
||||||
col.value,Value
|
col.value,Value
|
||||||
col.avg,Avg. buy
|
col.avg,Avg. buy
|
||||||
|
col.dirty,Dirty
|
||||||
bank.cash.k,Credits
|
bank.cash.k,Credits
|
||||||
bank.rent.k,Rent
|
bank.rent.k,Rent
|
||||||
bank.rent.v,"{0}, due in {1} days"
|
bank.rent.v,"{0}, due in {1} days"
|
||||||
@@ -152,13 +151,12 @@ stable.ok,Pegged
|
|||||||
stable.depeg,Depegged
|
stable.depeg,Depegged
|
||||||
stable.warn,Warning: staking reserve coverage low
|
stable.warn,Warning: staking reserve coverage low
|
||||||
stable.spiral,Collapsing
|
stable.spiral,Collapsing
|
||||||
aml.taint,Account taint share: {0}%
|
|
||||||
mixer.h,Mixer
|
mixer.h,Mixer
|
||||||
mixer.ok,Status: operating normally
|
mixer.ok,Status: operating normally
|
||||||
mixer.sanctioned,Status: sanctioned ({0} more day(s)). Coins withdrawn meanwhile are flagged.
|
mixer.sanctioned,Status: sanctioned ({0} more day(s)). Payouts due meanwhile are not cleaned and come back all dirty.
|
||||||
mixer.pending,Pending deposits
|
mixer.pending,Pending deposits
|
||||||
mixer.none,No pending deposits.
|
mixer.none,No pending deposits.
|
||||||
mixer.col.taint,Taint
|
mixer.col.taint,Dirty
|
||||||
mixer.col.ready,Ready
|
mixer.col.ready,Ready
|
||||||
mixer.day,Day {0}
|
mixer.day,Day {0}
|
||||||
mixer.deposit,Deposit
|
mixer.deposit,Deposit
|
||||||
@@ -169,11 +167,12 @@ mixer.go,Deposit to mixer
|
|||||||
mixer.min,Deposits must be worth at least {0} credits.
|
mixer.min,Deposits must be worth at least {0} credits.
|
||||||
mixer.done,Deposited {0} {1}; back on day {2}.
|
mixer.done,Deposited {0} {1}; back on day {2}.
|
||||||
mixer.upgrade.title,Mixer
|
mixer.upgrade.title,Mixer
|
||||||
mixer.upgrade.desc,"Unlocks the mixer in the terminal's Gray Net page: deposit tainted coins, get them back days later with less taint. Cash-outs of freshly mixed coins are screened harder; during crackdowns the mixer may be sanctioned and coins withdrawn meanwhile are flagged."
|
mixer.upgrade.desc,"Unlocks the mixer in the terminal's Gray Net page: deposit dirty coins, get them back days later with fewer of them dirty. During crackdowns the mixer may be sanctioned, and payouts due meanwhile come back all dirty."
|
||||||
news.sanction.title,Mixer put on sanctions list
|
news.sanction.title,Mixer put on sanctions list
|
||||||
news.sanction.desc,Security has sanctioned a batch of mixing services. Funds withdrawn from mixers in the next few days will be treated as suspicious.
|
news.sanction.desc,Security has sanctioned a batch of mixing services. Funds withdrawn from mixers in the next few days will be treated as dirty money.
|
||||||
nightlog.mixer,Mixer returned {0} {1}; taint {2} -> {3}.
|
nightlog.mixer,Mixer returned {0} {1}; taint {2} -> {3}.
|
||||||
nightlog.mixer_flag," (withdrawn during sanctions; address flagged)"
|
nightlog.mixer_flag," (withdrawn during sanctions; all of it marked dirty)"
|
||||||
|
nightlog.mixer_flag.trap," (Security marks the withdrawn coins as dirty)"
|
||||||
nightlog.mixer_rug,The mixer's operator ran off with it: {0} {1} never came back.
|
nightlog.mixer_rug,The mixer's operator ran off with it: {0} {1} never came back.
|
||||||
web3.sub.trade,Trade
|
web3.sub.trade,Trade
|
||||||
gray.sub.mixer,Mixer
|
gray.sub.mixer,Mixer
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Contraband (high)
|
|||||||
black.kind.Tech,High-tech (markup)
|
black.kind.Tech,High-tech (markup)
|
||||||
nightlog.bm.ready,Black market: {0} arrived; a courier will come by once you open.
|
nightlog.bm.ready,Black market: {0} arrived; a courier will come by once you open.
|
||||||
guide.web3.title,Web3 Handbook
|
guide.web3.title,Web3 Handbook
|
||||||
guide.web3.text,"Bank and trading: the Bank page is read-only and shows cash, rent and the CRC in your Poinbase account. Poinbase's Funds page handles deposits and withdrawals; pick the coin first: CRC can go through the bank account or a wallet, every other coin only through a wallet. Depositing from the bank turns credits into CRC in your Poinbase account; withdrawing to the bank turns CRC back into credits and goes through compliance screening, which looks at the Poinbase account's taint. Withdrawing to a wallet needs a payee address and a few confirmations before it arrives; the gas fee is fixed at the normal tier and taken from the coin sent. A wrong address format or checksum is rejected; a correctly formatted address nobody uses means the coins are gone.¶Trading: PSC stands for Probably Stolen Coin, the coin mined by GPUs and miners. Poinbase spot has two pairs, PSC/CRC and SPARK/CRC, following the coin picked on the chart. Buys and sells are both entered as an amount of the traded coin; the preview shows the quote coin paid or received, the average price includes the fee and the slippage does not.¶The Web3 trade page can swap any two coins, always through CRC: with CRC on one side it uses one pool, otherwise two pools, with two fees and stacked slippage; the preview shows the amount received, the pools crossed and the loss. Stablecoin swaps (CRT or CRA against CRC) use stable pools: a {StableFee:%} fee and almost no slippage near the peg; during a depeg liquidity thins, and in a collapse it is pulled and slippage jumps.§Hardware wallets: on-chain coins sit in PLEDGER hardware wallets, each with its own balances and taint. A wallet is an item: drag it onto the trading terminal to load it. Open it on the terminal's Wallets page; connect and disconnect at the top right of the terminal. Trading on the Web3 page and the shop and mixer on the Gray Net page use the connected wallet; with no wallet or no connection they are view-only and every balance reads 0. Coin-paying customers pay into the connected wallet.¶Payments (shop, mixer, Ponero desk, listing fees) start as an invoice on the terminal; type the payee address on the wallet and hold ✓ to sign. The last two characters of an address are a checksum, so a one-character typo is usually caught; once in a while it happens to be valid and the coins go to an address nobody uses. DEX swaps also need a signature on the wallet.¶Poinbase is a custodial account; deposits are sent from a wallet to Poinbase's deposit address (only PSC, CRC and SPARK; the compliant exchange takes neither the black market's CRT nor the Revolution's CRA, and the wallet blocks sending them to the deposit address) and withdrawals are started on Poinbase's Funds page. The Explorer on the Wallets page looks up transfers by address and shows only transfers that really happened: every movement in and out of your wallets (transfers, DEX swaps and other contract calls, miner payouts, withdrawals, coins others send you); Ponero is a privacy coin and never shows. More hardware wallets are sold by Dr. Jackson; drag one onto the trading terminal to add it, up to {WalletMax}. The shop has cheaper ones. A wallet you no longer want can be destroyed on the Wallets page; its coins are lost for good, and anything sent to its address afterwards is lost too.¶Transfers pay a gas fee: slow, normal or fast, and gas prices rise and fall over roughly a week; when the network is congested gas fees rise and slow transactions may be dropped from the mempool. Check the full address before sending.§Staking: CRA staked in the Revolution pool earns a daily rate that compounds into the stake; withdrawing means requesting first and waiting four days, with no interest while waiting and no way to take it early. CRA is partly collateralized: each CRA is backed by the CRC reserve the Revolution holds and by the balance token SPARK; reserve coverage and the collateral ratio are shown on the staking page. Interest is paid in new uncollateralized CRA, which dilutes reserve coverage, faster the more is staked; when coverage is too low the Revolution cuts the rate. The Revolution sometimes diverts the reserve, preceded by rumors: that is the warning. If coverage then falls below {CraCrashRatio:%} it collapses: CRA is worthless within three days and four days of unlocking is too slow; above that there is only a discount, and money from raiding the upper class slowly refills the reserve.¶Official minting: deposit CRC and SPARK (ratio per the current collateral ratio; the preview shows what is needed) to mint CRA, queued {CraMintDaysMin}-{CraMintDaysMax} days; the minted CRA goes straight into staking. Burning turns CRA back into CRC and SPARK, waiting as long as the unlock period; when the reserve is short the CRC share is cut by coverage. Queued mints and burns may be dishonored in full by the Revolution: the nightly chance is how far the CRA price is below 1 times {CraRugPerDepeg}; if the price is not below 1 it cLine truncated
|
guide.web3.text,"Bank and trading: the Bank page is read-only and shows cash, rent and the CRC in your Poinbase account. Poinbase's Funds page handles deposits and withdrawals; pick the coin first: CRC can go through the bank account or a wallet, every other coin only through a wallet. Depositing from the bank turns credits into CRC in your Poinbase account; withdrawing to the bank turns CRC back into credits with no screening (the Poinbase account only ever holds clean money). Withdrawing to a wallet needs a payee address and a few confirmations before it arrives; the gas fee is fixed at the normal tier and taken from the coin sent. A wrong address format or checksum is rejected; a correctly formatted address nobody uses means the coins are gone.¶Trading: PSC stands for Probably Stolen Coin, the coin mined by GPUs and miners. Poinbase spot has two pairs, PSC/CRC and SPARK/CRC, following the coin picked on the chart. Buys and sells are both entered as an amount of the traded coin; the preview shows the quote coin paid or received, the average price includes the fee and the slippage does not.¶The Web3 trade page can swap any two coins, always through CRC: with CRC on one side it uses one pool, otherwise two pools, with two fees and stacked slippage; the preview shows the amount received, the pools crossed and the loss. Stablecoin swaps (CRT or CRA against CRC) use stable pools: a {StableFee:%} fee and almost no slippage near the peg; during a depeg liquidity thins, and in a collapse it is pulled and slippage jumps.§Hardware wallets: on-chain coins sit in PLEDGER hardware wallets, each with its own balances and dirty coins (each coin tracks how many of it are dirty; see Taint). A wallet is an item: drag it onto the trading terminal to load it. Open it on the terminal's Wallets page; connect and disconnect at the top right of the terminal. Trading on the Web3 page and the shop and mixer on the Gray Net page use the connected wallet; with no wallet or no connection they are view-only and every balance reads 0. Coin-paying customers pay into the connected wallet.¶Payments (shop, mixer, Ponero desk, listing fees) start as an invoice on the terminal; type the payee address on the wallet and hold ✓ to sign. The last two characters of an address are a checksum, so a one-character typo is usually caught; once in a while it happens to be valid and the coins go to an address nobody uses. DEX swaps also need a signature on the wallet.¶Poinbase is a custodial account; deposits are sent from a wallet to Poinbase's deposit address (only PSC, CRC and SPARK; the compliant exchange takes neither the black market's CRT nor the Revolution's CRA, and the wallet blocks sending them to the deposit address; only clean coins can be deposited, see Taint) and withdrawals are started on Poinbase's Funds page. The Explorer on the Wallets page looks up transfers by address and shows only transfers that really happened: every movement in and out of your wallets (transfers, DEX swaps and other contract calls, miner payouts, withdrawals, coins others send you); Ponero is a privacy coin and never shows. More hardware wallets are sold by Dr. Jackson; drag one onto the trading terminal to add it, up to {WalletMax}. The shop has cheaper ones. A wallet you no longer want can be destroyed on the Wallets page; its coins are lost for good, and anything sent to its address afterwards is lost too.¶Transfers pay a gas fee: slow, normal or fast, and gas prices rise and fall over roughly a week; when the network is congested gas fees rise and slow transactions may be dropped from the mempool. Check the full address before sending.§Staking: CRA staked in the Revolution pool earns a daily rate that compounds into the stake; withdrawing means requesting first and waiting four days, with no interest while waiting and no way to take it early. CRA is partly collateralized: each CRA is backed by the CRC reserve the Revolution holds and by the balance token SPARK; reserve coverage and the collateral ratio are shown on the staking page. Interest is paid in new uncollateralized CRA, which dilutes reserve coverage, faster the more is staked; when coverage is too low the Revolution cuts the rate. The Revolution sometimes diverts the reserve, preceded by rumors: that is the warning. If coverage then falls below {CraCrashRatio:%} it collapses: CRA is worthless within three days and four days of unlocking is too slow; above that there is only a discount, and money from raiding the upper class slowly refills the reserve.¶Official minting: deposit CRC and SPARK (ratio per the current collateral ratio; the preview shows what is needed) to mint CRA, queued {CraMintDaysMin}-{CraMintDaysMax} days; the minted CRA goes straight into staking. Burning turns CRA back into CRC and SPARK, waiting as long as the unlock period; when the reserve is short the CRC share is cut by coverage. Queued mints and burns may be dishonored in full by the Revolution: the nightly chanceLine truncated
|
||||||
courier.odd1,...Package is here.
|
courier.odd1,...Package is here.
|
||||||
courier.odd2,(His hand stays in his pocket.) Sign here.
|
courier.odd2,(His hand stays in his pocket.) Sign here.
|
||||||
courier.sign,Sign
|
courier.sign,Sign
|
||||||
@@ -361,10 +360,11 @@ hw.wallet.n,Wallet {0}
|
|||||||
hw.review.own,Own wallet: {0}
|
hw.review.own,Own wallet: {0}
|
||||||
hw.review.poinbase,Poinbase deposit address
|
hw.review.poinbase,Poinbase deposit address
|
||||||
poin.deposit,Deposit address: {0}
|
poin.deposit,Deposit address: {0}
|
||||||
|
poin.deposit.clean,Clean coins {0} can deposit: {1}
|
||||||
wallets.count,Wallets {0}/{1}
|
wallets.count,Wallets {0}/{1}
|
||||||
wallets.col.name,Name
|
wallets.col.name,Name
|
||||||
wallets.col.addr,Address
|
wallets.col.addr,Address
|
||||||
wallets.col.taint,Taint
|
wallets.col.taint,Dirty
|
||||||
wallets.open,Open
|
wallets.open,Open
|
||||||
wallets.use,Connect
|
wallets.use,Connect
|
||||||
wallets.current,Connected
|
wallets.current,Connected
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Paste
|
|||||||
hw.copied,Address copied.
|
hw.copied,Address copied.
|
||||||
hw.copied.addr,Copied {0}
|
hw.copied.addr,Copied {0}
|
||||||
hw.balance.frozen," (frozen {0})"
|
hw.balance.frozen," (frozen {0})"
|
||||||
|
hw.balance.dirty," ({0} dirty)"
|
||||||
wallets.destroy,Destroy
|
wallets.destroy,Destroy
|
||||||
wallets.destroy.sure,Confirm
|
wallets.destroy.sure,Confirm
|
||||||
wallets.destroyed,Destroyed {0}: {1}
|
wallets.destroyed,Destroyed {0}: {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Upper water
|
|||||||
nightlog.predict.win,"Prediction right: ""{0}"", paid out {1}."
|
nightlog.predict.win,"Prediction right: ""{0}"", paid out {1}."
|
||||||
nightlog.predict.lose,"Prediction wrong: ""{0}"", stake {1} lost."
|
nightlog.predict.lose,"Prediction wrong: ""{0}"", stake {1} lost."
|
||||||
nightlog.predict.void,"Prediction void: ""{0}"", stake {1} refunded."
|
nightlog.predict.void,"Prediction void: ""{0}"", stake {1} refunded."
|
||||||
nightlog.predict.insider,"""{0}"" settled for {1}. Police suspect insider trading; the payout is marked and the wallet's taint rises by {2}."
|
nightlog.predict.insider,"""{0}"" settled for {1}. Police suspect insider trading; {2} CRC of it is marked as dirty."
|
||||||
predict.tab.markets,Markets
|
predict.tab.markets,Markets
|
||||||
predict.tab.intel,Intel
|
predict.tab.intel,Intel
|
||||||
predict.acct.crt,{0}: CRT {1}
|
predict.acct.crt,{0}: CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}: operation scheduled
|
|||||||
predict.brief.none,{0}: nothing to launch
|
predict.brief.none,{0}: nothing to launch
|
||||||
predict.brief.can,{0}: can launch {1}
|
predict.brief.can,{0}: can launch {1}
|
||||||
predict.clue.push,You moved the price {0}%: risky
|
predict.clue.push,You moved the price {0}%: risky
|
||||||
nightlog.predict.manip,"""{0}"" settled for {1}. Regulators suspect you manipulated the price; the payout is marked and the wallet's taint rises by {2}."
|
nightlog.predict.manip,"""{0}"" settled for {1}. Regulators suspect you manipulated the price; {2} CRC of it is marked as dirty."
|
||||||
news.manip.title,Exchange probes unusual trading
|
news.manip.title,Exchange probes unusual trading
|
||||||
news.manip.desc,Regulators report that someone moved the price with large spot orders and profited from derivatives and predictions; the accounts involved have been flagged.
|
news.manip.desc,Regulators report that someone moved the price with large spot orders and profited from derivatives and predictions; the accounts involved have been flagged.
|
||||||
taint.overflow,Taint now exceeds the wallet's value; the excess {0} goes on record as fraud.
|
perp.manip,Closed with profit {0}. Regulators suspect price manipulation; {1} fraud goes on your record.
|
||||||
perp.manip,Closed with profit {0}. Regulators suspect price manipulation; the profit is marked and the Poinbase account's taint rises by {1}.
|
|
||||||
web3.sub.ponzi,Yield
|
web3.sub.ponzi,Yield
|
||||||
ponzi.h,High-yield scheme
|
ponzi.h,High-yield scheme
|
||||||
ponzi.acct,Issuer wallet {0}: CRC {1}
|
ponzi.acct,Issuer wallet {0}: CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Poinbase Support
|
|||||||
scam.support.1,"Hello, Poinbase support here. We detected an unusual login on your account and it has been flagged."
|
scam.support.1,"Hello, Poinbase support here. We detected an unusual login on your account and it has been flagged."
|
||||||
scam.support.2,Please send {0} CRC to the safe address {1} today for verification; it will be returned right after.
|
scam.support.2,Please send {0} CRC to the safe address {1} today for verification; it will be returned right after.
|
||||||
scam.support.3,"Otherwise the account will be frozen for good. I have to go, remember to send it."
|
scam.support.3,"Otherwise the account will be frozen for good. I have to go, remember to send it."
|
||||||
predict.sold.caught,"Sold, received {0}. Police suspect insider trading; the proceeds are marked and the wallet's taint rises by {1}."
|
predict.sold.caught,"Sold, received {0}. Police suspect insider trading; {1} CRC of it is marked as dirty."
|
||||||
predict.row.move," (last night {0} {1})"
|
predict.row.move," (last night {0} {1})"
|
||||||
predict.stats.h,History (avg opening price / actual rate)
|
predict.stats.h,History (avg opening price / actual rate)
|
||||||
predict.stats.row,"{0}: {1} markets, avg open {2}, happened {3}%"
|
predict.stats.row,"{0}: {1} markets, avg open {2}, happened {3}%"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,PSC price
|
|||||||
predict.kind.Gas,Gas
|
predict.kind.Gas,Gas
|
||||||
predict.kind.Cra,CRA warning
|
predict.kind.Cra,CRA warning
|
||||||
predict.kind.Era,ASIC era
|
predict.kind.Era,ASIC era
|
||||||
|
predict.kind.Trial,Tumbler trial
|
||||||
nightlog.predict.move,"Prediction ""{0}"" moved {1} -> {2}"
|
nightlog.predict.move,"Prediction ""{0}"" moved {1} -> {2}"
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,{0} daily chart: no history yet; recording from today.
|
chart.empty,{0} daily chart: no history yet; recording from today.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"The Revolution reportedly obtained evidence of corr
|
|||||||
news.story.serpico_bm.title,Black market strikes a quiet deal
|
news.story.serpico_bm.title,Black market strikes a quiet deal
|
||||||
news.story.serpico_bm.desc,"An internal Security document changed hands on the black market. Darknet settlement has been noticeably steadier since, and CRT redemptions have not slipped once."
|
news.story.serpico_bm.desc,"An internal Security document changed hands on the black market. Darknet settlement has been noticeably steadier since, and CRT redemptions have not slipped once."
|
||||||
news.story.serpico_sec.title,Security launches internal purge
|
news.story.serpico_sec.title,Security launches internal purge
|
||||||
news.story.serpico_sec.desc,Security announced a full investigation into internal corruption and tighter monitoring of money flows. Poinbase is tightening cash-out screening and mixing services have been named.
|
news.story.serpico_sec.desc,Security announced a full investigation into internal corruption and tighter monitoring of money flows; mixing services have been named.
|
||||||
news.story.eleanor_leak.title,Nutrifruit breeding data leaked
|
news.story.eleanor_leak.title,Nutrifruit breeding data leaked
|
||||||
news.story.eleanor_leak.desc,"The lower-level paper published research that lets nutrifruit set seed again; Pastelle shares plunged. The bank custodying upper-level funds reports bad debts, and the Revolution is gaining ground."
|
news.story.eleanor_leak.desc,"The lower-level paper published research that lets nutrifruit set seed again; Pastelle shares plunged. The bank custodying upper-level funds reports bad debts, and the Revolution is gaining ground."
|
||||||
news.story.eleanor_return.title,Pastelle recovers stolen data
|
news.story.eleanor_return.title,Pastelle recovers stolen data
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,The mixer operator known as Tumbler was arrested in the
|
|||||||
news.tumbler.sold.title,Mixing service changes hands
|
news.tumbler.sold.title,Mixing service changes hands
|
||||||
news.tumbler.sold.desc,"Word is the signing keys of a lower-level mixing service have fallen into black-market hands, and fees went up at once. Users fear for their funds."
|
news.tumbler.sold.desc,"Word is the signing keys of a lower-level mixing service have fallen into black-market hands, and fees went up at once. Users fear for their funds."
|
||||||
nightlog.tumbler.gift,Tumbler took back the key drive and left {0} CRT as thanks (sent to {1}); mixer fees halved.
|
nightlog.tumbler.gift,Tumbler took back the key drive and left {0} CRT as thanks (sent to {1}); mixer fees halved.
|
||||||
|
agent.name,Security Agent
|
||||||
|
agent.v1.1,Security. Sorry to bother you.
|
||||||
|
agent.v1.2,We're looking for someone who goes by Tumbler. He runs a mixing service on chain.
|
||||||
|
agent.v1.3,He's been seen around this area.
|
||||||
|
agent.ask,Has he been to your shop?
|
||||||
|
agent.choice.yes,[Tell him: a few times]
|
||||||
|
agent.choice.no,[Tell him: never seen him]
|
||||||
|
agent.yes1,Thanks for your cooperation. Security will remember it.
|
||||||
|
agent.no1,"Is that so. If anything comes to mind, you know where to find us."
|
||||||
|
agent.search.1,We meet again. We hear you're keeping something for that man.
|
||||||
|
agent.search.2,Routine search. Please cooperate.
|
||||||
|
agent.search.found,Found it. We're taking this.
|
||||||
|
agent.search.none,...Nothing. Sorry for the trouble.
|
||||||
|
tumbler.v4.seized.1,I heard Security searched your shop.
|
||||||
|
tumbler.v4.seized.2,They have the key now. Every user's records will be dug up.
|
||||||
|
tumbler.v4.seized.3,"Whatever you told them, I don't want to know anymore."
|
||||||
|
nightlog.tumbler.leak,Security used Tumbler's signing key to rebuild the mixing records: {0} payouts had {1} of taint washed off; {2} fraud goes on your record.
|
||||||
|
nightlog.tumbler.leak.none,Security used Tumbler's signing key to rebuild the mixing records. You have not withdrawn anything from the mixer recently.
|
||||||
|
nightlog.tumbler.note,"A note was slipped under the door: ""You owe me, and I'll take it back. —T"""
|
||||||
|
nightlog.tumbler.tip,Message from Tumbler: Security may go after the mixing services tomorrow.
|
||||||
|
news.tumbler.leak.title,Security rebuilds mixer records
|
||||||
|
news.tumbler.leak.desc,Security says it has obtained the signing key of a mixing service and will use it to trace funds laundered through the service over the past month.
|
||||||
|
news.trial.pro.title,"Tumbler trial, day {0}: prosecution gains ground"
|
||||||
|
news.trial.def.title,"Tumbler trial, day {0}: defense gains ground"
|
||||||
|
news.trial.pro.desc1,"The prosecution presented server logs from the mixing node, saying they match the defendant's signatures one by one."
|
||||||
|
news.trial.pro.desc2,A former partner testified that the defendant knew clients' funds came from the black market.
|
||||||
|
news.trial.pro.desc3,The prosecution showed transfers between the defendant's wallet and several scam addresses.
|
||||||
|
news.trial.def.desc1,"The defense pointed to flaws in how evidence was collected when the node was seized, saying some logs may have been altered."
|
||||||
|
news.trial.def.desc2,A defense expert testified that the mixing contract is open-source code and the defendant cannot control who uses it.
|
||||||
|
news.trial.def.desc3,"The prosecution's key witness changed his story on the stand, saying he could not remember whether the defendant knew."
|
||||||
|
news.trial.convict.title,Tumbler found guilty
|
||||||
|
news.trial.convict.desc,The court found the mixer operator known as Tumbler guilty of money laundering. Security says the mixing service will not reopen.
|
||||||
|
news.trial.acquit.title,Tumbler acquitted
|
||||||
|
news.trial.acquit.desc,"Citing insufficient evidence, the court acquitted the mixer operator known as Tumbler and released him. He left the courthouse without answering reporters' questions."
|
||||||
|
news.tumbler.bmrug.title,Mixing service vanishes with funds
|
||||||
|
news.tumbler.bmrug.desc,"A mixing service taken over by the black market suddenly stopped paying out, and the funds in its contract were moved away. Users on the forums say they lost everything."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,New mixing service {0} goes live
|
||||||
|
news.mixer.rebrand.desc,"A mixing service called {0} went live recently, claiming no logs and no backdoors. Some have noticed that its contract looks very much like the service shut down earlier."
|
||||||
|
predict.q.trial,{0}: Tumbler found guilty
|
||||||
|
predict.clue.trial,"Trial reports: prosecution ahead {0} days, defense ahead {1} days"
|
||||||
mixer.status.closed,Status: shut down
|
mixer.status.closed,Status: shut down
|
||||||
yield.sub.pools,Yield pools
|
yield.sub.pools,Yield pools
|
||||||
yield.sub.mine,Issue scheme
|
yield.sub.mine,Issue scheme
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Pass
|
|||||||
otc.msg.gone,The client has left.
|
otc.msg.gone,The client has left.
|
||||||
otc.msg.cash,Not enough cash.
|
otc.msg.cash,Not enough cash.
|
||||||
otc.msg.sting,"The client was undercover: {0} cash confiscated, fencing on record."
|
otc.msg.sting,"The client was undercover: {0} cash confiscated, fencing on record."
|
||||||
otc.msg.bought,"Received {0} {1}, paid {2} cash."
|
otc.msg.bought,"Received {0} {1} ({3} of them dirty), paid {2} cash."
|
||||||
otc.msg.sold,"Sent {0} {1}, received {2} cash."
|
otc.msg.sold,"Sent {0} {1}, received {2} cash."
|
||||||
gray.sub.own,My mixer
|
gray.sub.own,My mixer
|
||||||
ownmix.h,My mixer
|
ownmix.h,My mixer
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,You can't even put up the cash? Forget it.
|
|||||||
otc.nowallet,"No wallet connected, so where would the coins go? Forget it."
|
otc.nowallet,"No wallet connected, so where would the coins go? Forget it."
|
||||||
otc.sting,Don't move. Security. Buying stolen funds: the cash is confiscated and this goes on your record.
|
otc.sting,Don't move. Security. Buying stolen funds: the cash is confiscated and this goes on your record.
|
||||||
hw.err.poinbase,Poinbase does not accept {0}.
|
hw.err.poinbase,Poinbase does not accept {0}.
|
||||||
|
hw.err.tainted,{0} of this wallet's {1} are dirty and Poinbase takes only clean coins: at most {2} {1}.
|
||||||
@@ -22,7 +22,7 @@ tab.report,Reporte
|
|||||||
wallet.line,{0}: {1} (aprox. {2} créditos)
|
wallet.line,{0}: {1} (aprox. {2} créditos)
|
||||||
wallet.empty,La billetera está vacía.
|
wallet.empty,La billetera está vacía.
|
||||||
wallet.total,Valor total: {0} créditos
|
wallet.total,Valor total: {0} créditos
|
||||||
wallet.taint,Valor contaminado: {0} créditos
|
wallet.taint,Monedas contaminadas: {0} créditos
|
||||||
trade.amount,Cantidad
|
trade.amount,Cantidad
|
||||||
trade.deposit,Depositar créditos como CRC
|
trade.deposit,Depositar créditos como CRC
|
||||||
trade.withdraw,Retirar CRC como créditos
|
trade.withdraw,Retirar CRC como créditos
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Saldo insuficiente.
|
|||||||
msg.trade,Pagado: {0} {1}; recibido: {2} {3}.
|
msg.trade,Pagado: {0} {1}; recibido: {2} {3}.
|
||||||
msg.deposit,Se depositaron {0} créditos como CRC.
|
msg.deposit,Se depositaron {0} créditos como CRC.
|
||||||
msg.cashout,Se recibieron {0} créditos. Impuesto: {1} créditos.
|
msg.cashout,Se recibieron {0} créditos. Impuesto: {1} créditos.
|
||||||
msg.aml_light,Revisión de cumplimiento: se retuvieron {0} créditos de fondos contaminados.
|
|
||||||
msg.aml_heavy,Revisión de cumplimiento: se confiscaron {0} créditos de fondos contaminados y se reportó a Seguridad.
|
|
||||||
report.none,Aún no hay reporte de minería.
|
report.none,Aún no hay reporte de minería.
|
||||||
report.day,Noche del día {0}
|
report.day,Noche del día {0}
|
||||||
report.rigs,Plataformas con energía: {0} de {1}
|
report.rigs,Plataformas con energía: {0} de {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Activo
|
|||||||
col.amount,Cantidad
|
col.amount,Cantidad
|
||||||
col.value,Valor
|
col.value,Valor
|
||||||
col.avg,Prom. compra
|
col.avg,Prom. compra
|
||||||
|
col.dirty,Contaminadas
|
||||||
bank.cash.k,Créditos
|
bank.cash.k,Créditos
|
||||||
bank.rent.k,Renta
|
bank.rent.k,Renta
|
||||||
bank.rent.v,"{0}, vence en {1} día(s)"
|
bank.rent.v,"{0}, vence en {1} día(s)"
|
||||||
@@ -152,13 +151,12 @@ stable.ok,Anclado
|
|||||||
stable.depeg,Desanclado
|
stable.depeg,Desanclado
|
||||||
stable.warn,Advertencia: cobertura de reserva del staking baja
|
stable.warn,Advertencia: cobertura de reserva del staking baja
|
||||||
stable.spiral,En colapso
|
stable.spiral,En colapso
|
||||||
aml.taint,Porcentaje de contaminación de la cuenta: {0}%
|
|
||||||
mixer.h,Mezclador
|
mixer.h,Mezclador
|
||||||
mixer.ok,Estado: en funcionamiento normal
|
mixer.ok,Estado: en funcionamiento normal
|
||||||
mixer.sanctioned,Estado: sancionado (días restantes: {0}). Las monedas retiradas mientras tanto se marcarán.
|
mixer.sanctioned,Estado: bajo sanción (días restantes: {0}). Los pagos que venzan en este período no se limpian y se devuelven todos como contaminados.
|
||||||
mixer.pending,Depósitos pendientes
|
mixer.pending,Depósitos pendientes
|
||||||
mixer.none,No hay depósitos pendientes.
|
mixer.none,No hay depósitos pendientes.
|
||||||
mixer.col.taint,Contaminación
|
mixer.col.taint,Contaminadas
|
||||||
mixer.col.ready,Listo
|
mixer.col.ready,Listo
|
||||||
mixer.day,Día {0}
|
mixer.day,Día {0}
|
||||||
mixer.deposit,Depósito
|
mixer.deposit,Depósito
|
||||||
@@ -169,11 +167,12 @@ mixer.go,Depositar en el mezclador
|
|||||||
mixer.min,Los depósitos deben valer al menos {0} créditos.
|
mixer.min,Los depósitos deben valer al menos {0} créditos.
|
||||||
mixer.done,Se depositaron {0} {1}; retorno el día {2}.
|
mixer.done,Se depositaron {0} {1}; retorno el día {2}.
|
||||||
mixer.upgrade.title,Mezclador
|
mixer.upgrade.title,Mezclador
|
||||||
mixer.upgrade.desc,"Desbloquea el mezclador en la página Red gris de la terminal: deposita monedas contaminadas y recupéralas días después con menos contaminación. El retiro de monedas recién mezcladas pasa por una revisión más estricta; durante las represiones, el mezclador puede ser sancionado y las monedas retiradas mientras tanto quedarán marcadas."
|
mixer.upgrade.desc,"Desbloquea el mezclador en la página de la Red gris de la terminal: deposita monedas contaminadas y recupéralas días después con menos unidades contaminadas. Durante las redadas el mezclador puede ser sancionado, y los pagos que venzan en ese período volverán totalmente contaminados."
|
||||||
news.sanction.title,Mezclador incluido en la lista de sanciones
|
news.sanction.title,Mezclador incluido en la lista de sanciones
|
||||||
news.sanction.desc,Seguridad sancionó un lote de servicios de mezcla. Los fondos retirados de mezcladores en los próximos días se tratarán como sospechosos.
|
news.sanction.desc,Seguridad ha sancionado varios servicios de mezcla. Los fondos retirados de mezcladores en los próximos días se considerarán fondos contaminados.
|
||||||
nightlog.mixer,El mezclador devolvió {0} {1}; contaminación {2} -> {3}.
|
nightlog.mixer,El mezclador devolvió {0} {1}; contaminación {2} -> {3}.
|
||||||
nightlog.mixer_flag," (retirado durante las sanciones; dirección marcada)"
|
nightlog.mixer_flag," (retirado durante las sanciones; todo marcado como contaminado)"
|
||||||
|
nightlog.mixer_flag.trap," (Seguridad marca las monedas retiradas como contaminadas)"
|
||||||
nightlog.mixer_rug,El operador del mezclador se fugó con el dinero: {0} {1} nunca regresaron.
|
nightlog.mixer_rug,El operador del mezclador se fugó con el dinero: {0} {1} nunca regresaron.
|
||||||
web3.sub.trade,Comercio
|
web3.sub.trade,Comercio
|
||||||
gray.sub.mixer,Mezclador
|
gray.sub.mixer,Mezclador
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Contrabando (alto)
|
|||||||
black.kind.Tech,Alta tecnología (con sobreprecio)
|
black.kind.Tech,Alta tecnología (con sobreprecio)
|
||||||
nightlog.bm.ready,Mercado negro: {0} ha llegado; un mensajero pasará en cuanto abras.
|
nightlog.bm.ready,Mercado negro: {0} ha llegado; un mensajero pasará en cuanto abras.
|
||||||
guide.web3.title,Manual de Web3
|
guide.web3.title,Manual de Web3
|
||||||
guide.web3.text,"Banco y comercio: la página del banco es de solo lectura y muestra efectivo, alquiler y el CRC de la cuenta de Poinbase. La página Fondos de Poinbase gestiona depósitos y retiros; primero se elige la moneda: el CRC puede ir por la cuenta bancaria o la billetera, las demás monedas solo por la billetera. Depositar desde el banco convierte créditos en CRC en tu cuenta de Poinbase; retirar al banco convierte CRC nuevamente en créditos y pasa por una revisión de cumplimiento que evalúa la contaminación de la cuenta de Poinbase. Retirar a una billetera exige la dirección de destino y varias confirmaciones hasta acreditarse; la comisión de gas es fija, nivel normal, y se descuenta de la moneda enviada. Si el formato de la dirección o el dígito de control es incorrecto, se rechaza; si el formato es válido pero nadie usa esa dirección, las monedas enviadas se pierden.¶Comercio: PSC significa Probably Stolen Coin, la moneda minada por tarjetas gráficas y mineros (máquinas). El mercado spot de Poinbase tiene dos pares, PSC/CRC y SPARK/CRC, según la moneda elegida en el gráfico. Tanto las compras como las ventas se introducen como cantidad de la moneda negociada; la vista previa muestra la moneda de cotización pagada o recibida, el precio medio incluye la comisión y el deslizamiento no.¶La página de comercio de Web3 permite intercambiar cualquier par de monedas, siempre a través de CRC: si CRC está en un extremo se usa un fondo, si no, dos fondos, con dos comisiones y deslizamiento acumulado; la vista previa muestra la cantidad obtenida, los fondos recorridos y la pérdida. Los canjes entre stablecoins (CRT o CRA contra CRC) usan fondos estables: comisión de {StableFee:%} y casi sin deslizamiento cerca de la paridad; durante una pérdida de paridad la liquidez se reduce, y en un colapso se retira y el deslizamiento se dispara.§Billeteras de hardware: las monedas en cadena residen en billeteras de hardware PLEDGER, cada una con sus propios saldos y contaminación. Una billetera es un objeto: arrástrala a la terminal de comercio para cargarla. Ábrela en la página Billeteras de la terminal; conéctala y desconéctala arriba a la derecha de la terminal. El comercio de la página Web3, la tienda y el mezclador de la página Red gris usan la billetera conectada; sin billetera o sin conexión, son solo de lectura y todos los saldos marcan 0. Los clientes que pagan con monedas pagan a la billetera conectada.¶Los pagos (tienda, mezclador, mostrador de Ponero, tarifas de publicación) comienzan como una factura en la terminal; ingresa la dirección del destinatario en la billetera y mantén presionado ✓ para firmar. Los dos últimos caracteres de una dirección son una suma de verificación, por lo que un error tipográfico de un carácter suele detectarse; de vez en cuando resulta válido y las monedas van a una dirección que nadie usa. Los intercambios en DEX también requieren firmar en la billetera.¶Poinbase es una cuenta de custodia; los depósitos se envían desde la billetera a la dirección de depósito de Poinbase (solo PSC, CRC y SPARK; la plataforma regulada no acepta el CRT del mercado negro ni el CRA de la Revolución, y la billetera bloquea su envío a la dirección de depósito) y los retiros se inician en la página Fondos de Poinbase. El Explorador de la página Billeteras permite consultar transferencias por dirección y solo muestra transferencias realmente ocurridas: cada entrada y salida de tus billeteras (transferencias, canjes en DEX y otras llamadas a contratos, ingresos de mineros, retiros, monedas que otros te envían); Ponero es una moneda de privacidad y nunca aparece. El Dr. Jackson vende más billeteras de hardware; arrastra una a la terminal de comercio para agregarla, hasta {WalletMax}. La tienda tiene opciones más baratas. Una billetera que ya no desees puede destruirse en la página Billeteras; sus monedas se pierden para siempre, y todo lo que se envíe después a su dirección también.¶Las transferencias pagan una comisión de gas: lenta, normal o rápida, y los precios del gas suben y bajan en aproximadamente una semana; cuando la red se congestiona, las comisiones de gas suben y las transacciones lentas pueden ser descartadas del mempool. Verifica la dirección completa antes de enviar.§Staking: el CRA en staking en el fondo de la Revolución genera una tasa diaria que se capitaliza en el monto; retirar implica solicitarlo primero y esperar cuatro días, sin intereses durante la espera y sin forma de retirarlo antes. CRA está parcialmente colateralizado: cada CRA está respaldado por la reserva de CRC de la Revolución y por el token de balance SPARK; la cobertura de la reserva y la tasa de colateralización aparecen en la página de staking. Los intereses se pagan con CRA nuevo sin colateral, lo que diluye la cobertura de la reserva, más rápido cuanto más staking haya; si la cobertura es demasiado baja, la Revolución recorta la Line truncated
|
guide.web3.text,"Banco y comercio: la página del Banco es de solo lectura y muestra el efectivo, el alquiler y el CRC en tu cuenta de Poinbase. La página de Fondos de Poinbase gestiona depósitos y retiros; primero elige la moneda: CRC puede operar mediante cuenta bancaria o billetera, mientras que cualquier otra moneda solo puede hacerlo mediante billetera. Depositar desde el banco convierte créditos en CRC dentro de tu cuenta de Poinbase; retirar al banco vuelve a convertir CRC en créditos sin revisión (la cuenta de Poinbase solo contiene dinero limpio). Retirar a una billetera requiere una dirección de destinatario y varias confirmaciones antes de llegar; la tarifa de Gas es fija en nivel normal y se descuenta de la moneda enviada. Un formato de dirección o suma de verificación incorrecto se rechaza; si la dirección tiene el formato correcto pero nadie la usa, las monedas se pierden.¶Comercio: PSC son las siglas de Probably Stolen Coin, la moneda extraída por tarjetas gráficas y mineros. El mercado spot de Poinbase tiene dos pares, PSC/CRC y SPARK/CRC, según la moneda seleccionada en el gráfico. Las compras y ventas se ingresan como una cantidad de la moneda negociada; la vista previa muestra la moneda de cotización pagada o recibida, el precio promedio incluye la comisión y el deslizamiento no.¶La página de comercio Web3 permite intercambiar cualquier par de monedas, siempre a través de CRC: con CRC en un extremo se usa un pool; de lo contrario, dos pools, con dos comisiones y deslizamiento acumulado; la vista previa muestra la cantidad recibida, los pools cruzados y la pérdida. Los intercambios entre monedas estables (CRT o CRA frente a CRC) utilizan pools estables: comisión del {StableFee:%} y casi nulo deslizamiento cerca de la paridad; durante una pérdida de paridad la liquidez disminuye, y ante un colapso se retira por completo disparando el deslizamiento.§Billeteras de hardware: las monedas en cadena residen en billeteras de hardware PLEDGER, cada una con sus propios saldos y monedas contaminadas (cada moneda registra cuántas unidades están contaminadas; consulta Contaminación). Una billetera es un objeto: arrástrala a la terminal de comercio para cargarla. Ábrela en la página de Billeteras de la terminal; conéctala y desconéctala en la esquina superior derecha de la terminal. El comercio en la página Web3 y la tienda y el mezclador en la página de la Red gris usan la billetera conectada; sin billetera o sin conexión son de solo lectura y todos los saldos marcan 0. Los clientes que pagan con monedas depositan en la billetera conectada.¶Los pagos (tienda, mezclador, mostrador de Ponero, tarifas de listado) comienzan como una factura en la terminal; ingresa la dirección del destinatario en la billetera y mantén presionado ✓ para firmar. Los dos últimos caracteres de una dirección corresponden a una suma de verificación, por lo que un error de un solo carácter suele detectarse; de vez en cuando resulta ser válido por casualidad y las monedas van a una dirección que nadie usa. Los intercambios en DEX también requieren una firma en la billetera.¶Poinbase es una cuenta de custodia; los depósitos se envían desde una billetera a la dirección de depósito de Poinbase (solo PSC, CRC y SPARK; el intercambio regulado no acepta el CRT del Mercado negro ni el CRA de la Revolución, y la billetera bloquea su envío a la dirección de depósito; solo pueden depositarse monedas limpias, consulta Contaminación) y los retiros se inician en la página de Fondos de Poinbase. El Explorador en la página de Billeteras consulta transferencias por dirección y solo muestra las transacciones reales: cada movimiento entrante y saliente de tus billeteras (transferencias, intercambios en DEX y otras llamadas de contrato, pagos de mineros, retiros, monedas enviadas por otros); Ponero es una moneda de privacidad y nunca se muestra. El Dr. Jackson vende más billeteras de hardware; arrastra una a la terminal de comercio para agregarla, hasta un máximo de {WalletMax}. La tienda tiene opciones más económicas. Una billetera que ya no desees puede destruirse en la página de Billeteras; sus monedas se perderán para siempre, y todo lo que se envíe a su dirección después también se perderá.¶Las transferencias pagan una tarifa de Gas: lenta, normal o rápida, y los precios del Gas suben y bajan en ciclos de aproximadamente una semana; cuando la red está congestionada las tarifas de Gas aumentan y las transacciones lentas pueden ser eliminadas de la mempool. Revisa la dirección completa antes de enviar.§Staking: el CRA en staking en el fondo de la Revolución genera una tasa diaria que se capitaliza en el monto; retirar implica solicitarlo primero y esperar cuatro días, sin intereses durante la espera y sin forma de retirarlo antes. CRA está parcialmente colateralizado: cada CRA está respaldado por la reserva de CRC de la Revolución y por el token de balance SPARK; la Line truncated
|
||||||
courier.odd1,...Llegó el paquete.
|
courier.odd1,...Llegó el paquete.
|
||||||
courier.odd2,(Mantiene la mano en el bolsillo). Firma aquí.
|
courier.odd2,(Mantiene la mano en el bolsillo). Firma aquí.
|
||||||
courier.sign,Firmar
|
courier.sign,Firmar
|
||||||
@@ -361,10 +360,11 @@ hw.wallet.n,Billetera {0}
|
|||||||
hw.review.own,Billetera propia: {0}
|
hw.review.own,Billetera propia: {0}
|
||||||
hw.review.poinbase,Dirección de depósito de Poinbase
|
hw.review.poinbase,Dirección de depósito de Poinbase
|
||||||
poin.deposit,Dirección de depósito: {0}
|
poin.deposit,Dirección de depósito: {0}
|
||||||
|
poin.deposit.clean,Monedas limpias que {0} puede depositar: {1}
|
||||||
wallets.count,Billeteras {0}/{1}
|
wallets.count,Billeteras {0}/{1}
|
||||||
wallets.col.name,Nombre
|
wallets.col.name,Nombre
|
||||||
wallets.col.addr,Dirección
|
wallets.col.addr,Dirección
|
||||||
wallets.col.taint,Contaminación
|
wallets.col.taint,Sucias
|
||||||
wallets.open,Abrir
|
wallets.open,Abrir
|
||||||
wallets.use,Conectar
|
wallets.use,Conectar
|
||||||
wallets.current,Conectada
|
wallets.current,Conectada
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Pegar
|
|||||||
hw.copied,Dirección copiada.
|
hw.copied,Dirección copiada.
|
||||||
hw.copied.addr,Copiado: {0}
|
hw.copied.addr,Copiado: {0}
|
||||||
hw.balance.frozen," (congelado: {0})"
|
hw.balance.frozen," (congelado: {0})"
|
||||||
|
hw.balance.dirty," (sucias: {0})"
|
||||||
wallets.destroy,Destruir
|
wallets.destroy,Destruir
|
||||||
wallets.destroy.sure,Confirmar
|
wallets.destroy.sure,Confirmar
|
||||||
wallets.destroyed,Se destruyó {0}: {1}
|
wallets.destroyed,Se destruyó {0}: {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Agua del nivel superior
|
|||||||
nightlog.predict.win,"Predicción acertada: ""{0}""; se pagaron {1}."
|
nightlog.predict.win,"Predicción acertada: ""{0}""; se pagaron {1}."
|
||||||
nightlog.predict.lose,"Predicción fallida: ""{0}""; perdiste la apuesta de {1}."
|
nightlog.predict.lose,"Predicción fallida: ""{0}""; perdiste la apuesta de {1}."
|
||||||
nightlog.predict.void,"Predicción anulada: ""{0}""; se reembolsó la apuesta de {1}."
|
nightlog.predict.void,"Predicción anulada: ""{0}""; se reembolsó la apuesta de {1}."
|
||||||
nightlog.predict.insider,"""{0}"" se liquidó por {1}. La policía sospecha de información privilegiada; el pago queda marcado y los fondos contaminados de la billetera aumentan en {2}."
|
nightlog.predict.insider,"""{0}"" se liquidó por {1}. La policía sospecha información privilegiada; {2} CRC de esa cantidad se marcaron como sucios."
|
||||||
predict.tab.markets,Mercados
|
predict.tab.markets,Mercados
|
||||||
predict.tab.intel,Información
|
predict.tab.intel,Información
|
||||||
predict.acct.crt,{0}: CRT {1}
|
predict.acct.crt,{0}: CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}: operación programada
|
|||||||
predict.brief.none,{0}: nada que iniciar
|
predict.brief.none,{0}: nada que iniciar
|
||||||
predict.brief.can,{0}: puede iniciar {1}
|
predict.brief.can,{0}: puede iniciar {1}
|
||||||
predict.clue.push,Moviste el precio un {0}%: riesgoso
|
predict.clue.push,Moviste el precio un {0}%: riesgoso
|
||||||
nightlog.predict.manip,"""{0}"" se liquidó por {1}. Los reguladores sospechan que manipulaste el precio; el pago queda marcado y los fondos contaminados de la billetera aumentan en {2}."
|
nightlog.predict.manip,"""{0}"" se liquidó por {1}. Los reguladores sospechan manipulación de precio; {2} CRC de esa cantidad se marcaron como sucios."
|
||||||
news.manip.title,El exchange investiga operaciones inusuales
|
news.manip.title,El exchange investiga operaciones inusuales
|
||||||
news.manip.desc,Los reguladores informan que alguien movió el precio con grandes órdenes al contado y obtuvo ganancias con derivados y predicciones; las cuentas involucradas han sido marcadas.
|
news.manip.desc,Los reguladores informan que alguien movió el precio con grandes órdenes al contado y obtuvo ganancias con derivados y predicciones; las cuentas involucradas han sido marcadas.
|
||||||
taint.overflow,Los fondos contaminados superan ahora el valor de la billetera; el exceso de {0} se registra como fraude.
|
perp.manip,Cierre con ganancia de {0}. Los reguladores sospechan manipulación de precio; se registra {1} de fraude en tu expediente.
|
||||||
perp.manip,Cierre con ganancias de {0}. Los reguladores sospechan de manipulación de precio; la ganancia queda marcada y los fondos contaminados de la cuenta de Poinbase aumentan en {1}.
|
|
||||||
web3.sub.ponzi,Rendimiento
|
web3.sub.ponzi,Rendimiento
|
||||||
ponzi.h,Esquema Ponzi
|
ponzi.h,Esquema Ponzi
|
||||||
ponzi.acct,Billetera emisora {0}: CRC {1}
|
ponzi.acct,Billetera emisora {0}: CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Soporte de Poinbase
|
|||||||
scam.support.1,"Hola, soporte de Poinbase por aquí. Detectamos un inicio de sesión inusual en tu cuenta y fue marcada."
|
scam.support.1,"Hola, soporte de Poinbase por aquí. Detectamos un inicio de sesión inusual en tu cuenta y fue marcada."
|
||||||
scam.support.2,Envía {0} CRC hoy a la dirección segura {1} para verificación; se devolverá inmediatamente después.
|
scam.support.2,Envía {0} CRC hoy a la dirección segura {1} para verificación; se devolverá inmediatamente después.
|
||||||
scam.support.3,"De lo contrario, la cuenta quedará congelada para siempre. Me tengo que ir, no olvides enviarlo."
|
scam.support.3,"De lo contrario, la cuenta quedará congelada para siempre. Me tengo que ir, no olvides enviarlo."
|
||||||
predict.sold.caught,"Vendido, se recibieron {0}. La policía sospecha de información privilegiada; los ingresos quedan marcados y los fondos contaminados de la billetera aumentan en {1}."
|
predict.sold.caught,"Vendido, recibiste {0}. La policía sospecha información privilegiada; {1} CRC de esa cantidad se marcaron como sucios."
|
||||||
predict.row.move," (anoche {0} {1})"
|
predict.row.move," (anoche {0} {1})"
|
||||||
predict.stats.h,Historial (precio prom. apertura / tasa real)
|
predict.stats.h,Historial (precio prom. apertura / tasa real)
|
||||||
predict.stats.row,"{0}: {1} mercados, prom. apertura {2}, ocurrió {3}%"
|
predict.stats.row,"{0}: {1} mercados, prom. apertura {2}, ocurrió {3}%"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,Precio de PSC
|
|||||||
predict.kind.Gas,Gas
|
predict.kind.Gas,Gas
|
||||||
predict.kind.Cra,Alerta de CRA
|
predict.kind.Cra,Alerta de CRA
|
||||||
predict.kind.Era,Era ASIC
|
predict.kind.Era,Era ASIC
|
||||||
|
predict.kind.Trial,Juicio a Tumbler
|
||||||
nightlog.predict.move,"Predicción ""{0}"" cambió {1} -> {2}"
|
nightlog.predict.move,"Predicción ""{0}"" cambió {1} -> {2}"
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,Gráfico diario de {0}: sin historial aún; registrando desde hoy.
|
chart.empty,Gráfico diario de {0}: sin historial aún; registrando desde hoy.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"Según se informa, la Revolución obtuvo pruebas de
|
|||||||
news.story.serpico_bm.title,El Mercado negro llega a un acuerdo discreto
|
news.story.serpico_bm.title,El Mercado negro llega a un acuerdo discreto
|
||||||
news.story.serpico_bm.desc,"Un documento interno de Seguridad cambió de manos en el Mercado negro. La liquidación en la Darknet ha sido notablemente más estable desde entonces, y los canjes de CRT no han fallado ni una sola vez."
|
news.story.serpico_bm.desc,"Un documento interno de Seguridad cambió de manos en el Mercado negro. La liquidación en la Darknet ha sido notablemente más estable desde entonces, y los canjes de CRT no han fallado ni una sola vez."
|
||||||
news.story.serpico_sec.title,Seguridad inicia una purga interna
|
news.story.serpico_sec.title,Seguridad inicia una purga interna
|
||||||
news.story.serpico_sec.desc,Seguridad anunció una investigación exhaustiva sobre corrupción interna y mayor control del flujo de dinero. Poinbase endurece la revisión de retiros y se han señalado los servicios de mezcla.
|
news.story.serpico_sec.desc,Seguridad anunció una investigación exhaustiva sobre la corrupción interna y un mayor control del flujo de dinero; los servicios de mezclador fueron señalados.
|
||||||
news.story.eleanor_leak.title,Se filtran datos de cultivo de nutrifrutas
|
news.story.eleanor_leak.title,Se filtran datos de cultivo de nutrifrutas
|
||||||
news.story.eleanor_leak.desc,El periódico del Nivel inferior publicó una investigación que permite a la nutrifruta volver a dar semillas; las acciones de Pastelle se desplomaron. El banco custodio de fondos del Nivel superior reporta deudas incobrables y la Revolución gana terreno.
|
news.story.eleanor_leak.desc,El periódico del Nivel inferior publicó una investigación que permite a la nutrifruta volver a dar semillas; las acciones de Pastelle se desplomaron. El banco custodio de fondos del Nivel superior reporta deudas incobrables y la Revolución gana terreno.
|
||||||
news.story.eleanor_return.title,Pastelle recupera datos robados
|
news.story.eleanor_return.title,Pastelle recupera datos robados
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,El operador del mezclador conocido como Tumbler fue arr
|
|||||||
news.tumbler.sold.title,Servicio de mezcla cambia de manos
|
news.tumbler.sold.title,Servicio de mezcla cambia de manos
|
||||||
news.tumbler.sold.desc,Se dice que las claves de firma de un servicio de mezcla del nivel inferior han caído en manos del mercado negro y las tarifas subieron de inmediato. Los usuarios temen por sus fondos.
|
news.tumbler.sold.desc,Se dice que las claves de firma de un servicio de mezcla del nivel inferior han caído en manos del mercado negro y las tarifas subieron de inmediato. Los usuarios temen por sus fondos.
|
||||||
nightlog.tumbler.gift,Tumbler recuperó la unidad de claves y dejó {0} CRT como agradecimiento (enviados a {1}); las tarifas del mezclador se redujeron a la mitad.
|
nightlog.tumbler.gift,Tumbler recuperó la unidad de claves y dejó {0} CRT como agradecimiento (enviados a {1}); las tarifas del mezclador se redujeron a la mitad.
|
||||||
|
agent.name,Agente de Seguridad
|
||||||
|
agent.v1.1,Seguridad. Perdón por la molestia.
|
||||||
|
agent.v1.2,Buscamos a alguien conocido como Tumbler. Opera un servicio de mezclador en la cadena.
|
||||||
|
agent.v1.3,Se le ha visto por esta zona.
|
||||||
|
agent.ask,¿Ha estado en tu tienda?
|
||||||
|
agent.choice.yes,[Decirle: varias veces]
|
||||||
|
agent.choice.no,[Decirle: nunca lo vi]
|
||||||
|
agent.yes1,Gracias por cooperar. Seguridad lo recordará.
|
||||||
|
agent.no1,"¿Ah, sí? Si recuerdas algo, ya sabes dónde encontrarnos."
|
||||||
|
agent.search.1,Nos volvemos a ver. Nos enteramos de que le estás guardando algo a ese sujeto.
|
||||||
|
agent.search.2,"Registro de rutina. Coopera, por favor."
|
||||||
|
agent.search.found,Lo encontramos. Nos llevamos esto.
|
||||||
|
agent.search.none,...Nada. Perdón por la molestia.
|
||||||
|
tumbler.v4.seized.1,Me enteré de que Seguridad registró tu tienda.
|
||||||
|
tumbler.v4.seized.2,Ahora tienen la clave. Van a desenterrar los registros de todos los usuarios.
|
||||||
|
tumbler.v4.seized.3,"Lo que sea que les hayas dicho, ya no quiero saberlo."
|
||||||
|
nightlog.tumbler.leak,"Seguridad usó la clave de firma de Tumbler para reconstruir los registros de mezcla: pagos: {0}, con {1} de contaminación lavada; se registra {2} de fraude en tu expediente."
|
||||||
|
nightlog.tumbler.leak.none,Seguridad usó la clave de firma de Tumbler para reconstruir los registros de mezcla. No has retirado nada del mezclador recientemente.
|
||||||
|
nightlog.tumbler.note,"Deslizaron una nota por debajo de la puerta: ""Me debes, y lo voy a recuperar. —T"""
|
||||||
|
nightlog.tumbler.tip,Mensaje de Tumbler: puede que Seguridad inspeccione los servicios de mezclador mañana.
|
||||||
|
news.tumbler.leak.title,Seguridad reconstruye registros del mezclador
|
||||||
|
news.tumbler.leak.desc,Seguridad afirma haber obtenido la clave de firma de un servicio de mezclador y la usará para rastrear los fondos lavados mediante este durante el último mes.
|
||||||
|
news.trial.pro.title,"Juicio a Tumbler, día {0}: la fiscalía gana terreno"
|
||||||
|
news.trial.def.title,"Juicio a Tumbler, día {0}: la defensa gana terreno"
|
||||||
|
news.trial.pro.desc1,"La fiscalía presentó registros del servidor del nodo del mezclador, asegurando que coinciden una a una con las firmas del acusado."
|
||||||
|
news.trial.pro.desc2,Un antiguo socio testificó que el acusado sabía que los fondos de los clientes provenían del Mercado negro.
|
||||||
|
news.trial.pro.desc3,La fiscalía mostró transferencias entre la billetera del acusado y varias direcciones de estafas.
|
||||||
|
news.trial.def.desc1,"La defensa señaló irregularidades en la recolección de pruebas durante la incautación del nodo, alegando que algunos registros pudieron haber sido alterados."
|
||||||
|
news.trial.def.desc2,Un perito de la defensa testificó que el contrato del mezclador es de código abierto y que el acusado no puede controlar quién lo utiliza.
|
||||||
|
news.trial.def.desc3,"El testigo clave de la fiscalía cambió su versión en el estrado, declarando que no recordaba si el acusado estaba al tanto."
|
||||||
|
news.trial.convict.title,Tumbler declarado culpable
|
||||||
|
news.trial.convict.desc,El tribunal declaró culpable de lavado de dinero al operador del mezclador conocido como Tumbler. Seguridad asegura que el servicio de mezclador no volverá a operar.
|
||||||
|
news.trial.acquit.title,Tumbler absuelto
|
||||||
|
news.trial.acquit.desc,"Alegando falta de pruebas, el tribunal absolvió y puso en libertad al operador del mezclador conocido como Tumbler. Se retiró del juzgado sin responder a las preguntas de la prensa."
|
||||||
|
news.tumbler.bmrug.title,Servicio de mezclador desaparece con los fondos
|
||||||
|
news.tumbler.bmrug.desc,"Un servicio de mezclador tomado por el Mercado negro detuvo repentinamente los pagos y los fondos de su contrato fueron retirados. En los foros, los usuarios denuncian haberlo perdido todo."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,Nuevo servicio de mezclador {0} en línea
|
||||||
|
news.mixer.rebrand.desc,"Un servicio de mezclador llamado {0} entró en línea recientemente, afirmando no tener registros ni puertas traseras. Varios notaron que su contrato es muy similar al del servicio clausurado anteriormente."
|
||||||
|
predict.q.trial,{0}: Tumbler declarado culpable
|
||||||
|
predict.clue.trial,"Informes del juicio: fiscalía en ventaja: {0} d, defensa en ventaja: {1} d"
|
||||||
mixer.status.closed,Estado: cerrado
|
mixer.status.closed,Estado: cerrado
|
||||||
yield.sub.pools,Fondos de rendimiento
|
yield.sub.pools,Fondos de rendimiento
|
||||||
yield.sub.mine,Emitir esquema
|
yield.sub.mine,Emitir esquema
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Pasar
|
|||||||
otc.msg.gone,El cliente se fue.
|
otc.msg.gone,El cliente se fue.
|
||||||
otc.msg.cash,Efectivo insuficiente.
|
otc.msg.cash,Efectivo insuficiente.
|
||||||
otc.msg.sting,"El cliente era un agente encubierto: {0} en efectivo confiscado, receptación registrada."
|
otc.msg.sting,"El cliente era un agente encubierto: {0} en efectivo confiscado, receptación registrada."
|
||||||
otc.msg.bought,"Recibiste {0} {1}, pagaste {2} en efectivo."
|
otc.msg.bought,"Recibiste {0} {1} (sucias: {3}), pagaste {2} en efectivo."
|
||||||
otc.msg.sold,"Enviaste {0} {1}, recibiste {2} en efectivo."
|
otc.msg.sold,"Enviaste {0} {1}, recibiste {2} en efectivo."
|
||||||
gray.sub.own,Mi mezclador
|
gray.sub.own,Mi mezclador
|
||||||
ownmix.h,Mi mezclador
|
ownmix.h,Mi mezclador
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,¿Ni siquiera tienes el efectivo? Olvídalo.
|
|||||||
otc.nowallet,"No hay billetera conectada, ¿adónde mando las monedas? Olvídalo."
|
otc.nowallet,"No hay billetera conectada, ¿adónde mando las monedas? Olvídalo."
|
||||||
otc.sting,Quieto. Seguridad. Compra de fondos robados: el efectivo queda confiscado y esto va a tu expediente.
|
otc.sting,Quieto. Seguridad. Compra de fondos robados: el efectivo queda confiscado y esto va a tu expediente.
|
||||||
hw.err.poinbase,Poinbase no acepta {0}.
|
hw.err.poinbase,Poinbase no acepta {0}.
|
||||||
|
hw.err.tainted,Esta billetera tiene {0} {1} de saldo sucio y Poinbase solo acepta monedas limpias: máximo {2} {1}.
|
||||||
@@ -22,7 +22,7 @@ tab.report,Rapport
|
|||||||
wallet.line,{0} : {1} (environ {2} crédits)
|
wallet.line,{0} : {1} (environ {2} crédits)
|
||||||
wallet.empty,Le portefeuille est vide.
|
wallet.empty,Le portefeuille est vide.
|
||||||
wallet.total,Valeur totale : {0} crédits
|
wallet.total,Valeur totale : {0} crédits
|
||||||
wallet.taint,Valeur contaminée : {0} crédits
|
wallet.taint,Pièces contaminées (crédits) : {0}
|
||||||
trade.amount,Montant
|
trade.amount,Montant
|
||||||
trade.deposit,Déposer des crédits en CRC
|
trade.deposit,Déposer des crédits en CRC
|
||||||
trade.withdraw,Retirer des CRC en crédits
|
trade.withdraw,Retirer des CRC en crédits
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Solde insuffisant.
|
|||||||
msg.trade,"Payé {0} {1}, reçu {2} {3}."
|
msg.trade,"Payé {0} {1}, reçu {2} {3}."
|
||||||
msg.deposit,{0} crédits déposés en CRC.
|
msg.deposit,{0} crédits déposés en CRC.
|
||||||
msg.cashout,{0} crédits reçus. Taxe : {1} crédits.
|
msg.cashout,{0} crédits reçus. Taxe : {1} crédits.
|
||||||
msg.aml_light,Contrôle de conformité : {0} crédits de fonds contaminés ont été retenus.
|
|
||||||
msg.aml_heavy,Contrôle de conformité : {0} crédits de fonds contaminés ont été saisis et signalés à la Sécurité.
|
|
||||||
report.none,Aucun rapport de minage pour le moment.
|
report.none,Aucun rapport de minage pour le moment.
|
||||||
report.day,Nuit du jour {0}
|
report.day,Nuit du jour {0}
|
||||||
report.rigs,Plateformes alimentées : {0} sur {1}
|
report.rigs,Plateformes alimentées : {0} sur {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Actif
|
|||||||
col.amount,Montant
|
col.amount,Montant
|
||||||
col.value,Valeur
|
col.value,Valeur
|
||||||
col.avg,Achat moy.
|
col.avg,Achat moy.
|
||||||
|
col.dirty,Contaminé
|
||||||
bank.cash.k,Crédits
|
bank.cash.k,Crédits
|
||||||
bank.rent.k,Loyer
|
bank.rent.k,Loyer
|
||||||
bank.rent.v,"{0}, échéance dans {1} jour(s)"
|
bank.rent.v,"{0}, échéance dans {1} jour(s)"
|
||||||
@@ -152,13 +151,12 @@ stable.ok,Arrimé
|
|||||||
stable.depeg,Désarrimé
|
stable.depeg,Désarrimé
|
||||||
stable.warn,Attention : couverture de réserve du staking au plus bas
|
stable.warn,Attention : couverture de réserve du staking au plus bas
|
||||||
stable.spiral,Effondrement en cours
|
stable.spiral,Effondrement en cours
|
||||||
aml.taint,Part de contamination du compte : {0} %
|
|
||||||
mixer.h,Mixeur
|
mixer.h,Mixeur
|
||||||
mixer.ok,Statut : fonctionnement normal
|
mixer.ok,Statut : fonctionnement normal
|
||||||
mixer.sanctioned,Statut : sanctionné (encore {0} jour(s)). Les pièces retirées pendant cette période sont signalées.
|
mixer.sanctioned,Statut : sanctionné (encore {0} j). Les versements dus pendant cette période ne sont pas nettoyés et reviennent entièrement contaminés.
|
||||||
mixer.pending,Dépôts en attente
|
mixer.pending,Dépôts en attente
|
||||||
mixer.none,Aucun dépôt en attente.
|
mixer.none,Aucun dépôt en attente.
|
||||||
mixer.col.taint,Contamination
|
mixer.col.taint,Contaminé
|
||||||
mixer.col.ready,Échéance
|
mixer.col.ready,Échéance
|
||||||
mixer.day,Jour {0}
|
mixer.day,Jour {0}
|
||||||
mixer.deposit,Dépôt
|
mixer.deposit,Dépôt
|
||||||
@@ -169,11 +167,12 @@ mixer.go,Déposer au mixeur
|
|||||||
mixer.min,Les dépôts doivent valoir au moins {0} crédits.
|
mixer.min,Les dépôts doivent valoir au moins {0} crédits.
|
||||||
mixer.done,{0} {1} déposés ; retour au jour {2}.
|
mixer.done,{0} {1} déposés ; retour au jour {2}.
|
||||||
mixer.upgrade.title,Mixeur
|
mixer.upgrade.title,Mixeur
|
||||||
mixer.upgrade.desc,"Débloque le mixeur sur la page Réseau gris du terminal : déposez des pièces contaminées pour les récupérer quelques jours plus tard avec une contamination réduite. Les retraits de pièces fraîchement mixées font l'objet d'un contrôle plus strict ; en période de répression, le mixeur peut être sanctionné et les pièces retirées pendant cette période sont signalées."
|
mixer.upgrade.desc,"Débloque le mixeur sur la page Réseau gris du terminal : déposez des pièces contaminées, récupérez-les quelques jours plus tard avec moins de pièces contaminées. En période de répression, le mixeur peut être sanctionné, et les versements dus pendant cette période reviennent entièrement contaminés."
|
||||||
news.sanction.title,Mixeur placé sur la liste des sanctions
|
news.sanction.title,Mixeur placé sur la liste des sanctions
|
||||||
news.sanction.desc,La Sécurité a sanctionné plusieurs services de mixage. Les fonds retirés des mixeurs au cours des prochains jours seront considérés comme suspects.
|
news.sanction.desc,La Sécurité a sanctionné une série de services de mixage. Les fonds retirés des mixeurs au cours des prochains jours seront traités comme des fonds contaminés.
|
||||||
nightlog.mixer,Le mixeur a restitué {0} {1} ; contamination {2} -> {3}.
|
nightlog.mixer,Le mixeur a restitué {0} {1} ; contamination {2} -> {3}.
|
||||||
nightlog.mixer_flag," (retiré pendant les sanctions ; adresse signalée)"
|
nightlog.mixer_flag," (retiré pendant les sanctions ; intégralité marquée comme contaminée)"
|
||||||
|
nightlog.mixer_flag.trap," (la Sécurité marque les pièces retirées comme contaminées)"
|
||||||
nightlog.mixer_rug,L'opérateur du mixeur a pris la fuite : {0} {1} ne sont jamais revenus.
|
nightlog.mixer_rug,L'opérateur du mixeur a pris la fuite : {0} {1} ne sont jamais revenus.
|
||||||
web3.sub.trade,Trading
|
web3.sub.trade,Trading
|
||||||
gray.sub.mixer,Mixeur
|
gray.sub.mixer,Mixeur
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Contrebande (élevée)
|
|||||||
black.kind.Tech,High-tech (majoration)
|
black.kind.Tech,High-tech (majoration)
|
||||||
nightlog.bm.ready,Marché noir : {0} est arrivé ; un livreur passera dès l'ouverture.
|
nightlog.bm.ready,Marché noir : {0} est arrivé ; un livreur passera dès l'ouverture.
|
||||||
guide.web3.title,Manuel Web3
|
guide.web3.title,Manuel Web3
|
||||||
guide.web3.text,"Banque et trading : la page Banque est en lecture seule et affiche les espèces, le loyer et les CRC du compte Poinbase. La page Fonds de Poinbase gère dépôts et retraits ; on choisit d'abord la pièce : le CRC passe par le compte bancaire ou le portefeuille, les autres pièces uniquement par le portefeuille. Le dépôt depuis la banque convertit les crédits en CRC sur votre compte Poinbase ; le retrait vers la banque reconvertit les CRC en crédits et passe par un contrôle de conformité, qui évalue la contamination du compte Poinbase. Un retrait vers un portefeuille demande l'adresse du destinataire et plusieurs confirmations avant d'arriver ; les frais de gas sont fixés au niveau normal et prélevés sur la pièce envoyée. Un format d'adresse ou un chiffre de contrôle incorrect est refusé ; une adresse au format valide mais que personne n'utilise fait perdre les pièces envoyées.¶Trading : PSC signifie Probably Stolen Coin, la pièce minée par les cartes graphiques et les mineurs (machines). Le spot de Poinbase propose deux paires, PSC/CRC et SPARK/CRC, selon la pièce choisie sur le graphique. Les achats comme les ventes se saisissent en quantité de la monnaie échangée ; l'aperçu indique la monnaie de cotation payée ou reçue, le prix moyen inclut les frais et le glissement non.¶La page de trading Web3 permet d'échanger deux pièces au choix, toujours via le CRC : si le CRC est d'un côté, un seul pool est utilisé, sinon deux pools, avec deux frais et un glissement cumulé ; l'aperçu indique le montant obtenu, le nombre de pools traversés et la perte. Les échanges entre stablecoins (CRT ou CRA contre CRC) passent par des pools stables : {StableFee:%} de frais et quasiment aucun glissement près de l'ancrage ; en cas de désancrage la liquidité s'amincit, et en cas d'effondrement elle est retirée et le glissement s'envole.§Portefeuilles matériels : les pièces sur la blockchain sont conservées dans des portefeuilles matériels PLEDGER, chacun avec ses propres soldes et sa contamination. Un portefeuille est un objet : glissez-le sur le terminal de trading pour le charger. Ouvrez-le sur la page Portefeuilles du terminal ; connectez et déconnectez-le en haut à droite du terminal. Le trading de la page Web3, la boutique et le mixeur de la page Réseau gris utilisent le portefeuille connecté ; sans portefeuille ou sans connexion, ils sont en lecture seule et tous les soldes affichent 0. Les clients qui paient en pièces paient sur le portefeuille connecté.¶Les paiements (boutique, mixeur, comptoir Ponero, frais de mise en vente) débutent par une facture sur le terminal ; saisissez l'adresse du destinataire sur le portefeuille et maintenez ✓ pour signer. Les deux derniers caractères d'une adresse sont une somme de contrôle, de sorte qu'une faute de frappe d'un caractère est généralement interceptée ; il arrive parfois qu'elle soit valide par hasard et les pièces partent alors vers une adresse inutilisée. Les échanges sur le DEX nécessitent également une signature sur le portefeuille.¶Poinbase est un compte dépositaire ; le dépôt s'effectue depuis le portefeuille vers l'adresse de dépôt de Poinbase (uniquement PSC, CRC et SPARK ; la plateforme réglementée n'accepte ni le CRT du Marché noir ni le CRA de la Révolution, et le portefeuille bloque leur envoi vers l'adresse de dépôt), le retrait se lance depuis la page Fonds de Poinbase. L'Explorateur de la page Portefeuilles permet de consulter les transferts par adresse, en n'affichant que les transferts réellement effectués : chaque entrée et sortie de vos portefeuilles (transferts, échanges DEX et autres appels de contrat, gains des mineurs, retraits, pièces que d'autres vous envoient) ; Ponero est une monnaie de confidentialité et n'apparaît jamais. D'autres portefeuilles matériels sont vendus par le Pr Jackson ; glissez-en un sur le terminal de trading pour l'ajouter, jusqu'à {WalletMax} au total. La boutique en propose des moins chers. Un portefeuille devenu inutile peut être détruit sur la page Portefeuilles ; ses pièces sont perdues définitivement, et tout ce qui est envoyé ensuite à son adresse l'est aussi.¶Les transferts sont soumis à des frais de gas : lent, normal ou rapide, et le prix du gas monte et descend sur environ une semaine ; lorsque le réseau est saturé, les frais de gas augmentent et les transactions lentes peuvent être évincées de la mempool. Vérifiez l'adresse complète avant d'envoyer.§Staking : le CRA staké dans le pool de la Révolution rapporte un taux quotidien capitalisé dans le montant staké ; retirer nécessite d'en faire la demande préalable et d'attendre quatre jours, sans intérêt durant cette période ni moyen de récupérer les fonds plus tôt. Le CRA est partiellement collatéralisé : chaque CRA est soutenu par la réserve de CRC détenue par la Révolution et par le jeton d'équilibre SPARK ; le taux de couverture de laLine truncated
|
guide.web3.text,"Banque et trading : la page Banque est en lecture seule et affiche les liquidités, le loyer et les CRC de votre compte Poinbase. La page Fonds de Poinbase gère les dépôts et les retraits ; choisissez d'abord la cryptomonnaie : le CRC peut passer par le compte bancaire ou un portefeuille, toutes les autres uniquement par un portefeuille. Déposer depuis la banque convertit des crédits en CRC sur votre compte Poinbase ; retirer vers la banque retransforme les CRC en crédits sans contrôle (le compte Poinbase ne contient que des fonds propres). Retirer vers un portefeuille nécessite une adresse de destinataire et quelques confirmations avant d'arriver ; les frais de gas sont fixés au niveau normal et prélevés sur la monnaie envoyée. Un format d'adresse ou une somme de contrôle incorrect est rejeté ; si l'adresse est valide mais que personne ne l'utilise, les pièces sont perdues.¶Trading : PSC signifie Probably Stolen Coin, la monnaie minée par les cartes graphiques et les mineurs. Le marché au comptant de Poinbase propose deux paires, PSC/CRC et SPARK/CRC, qui suivent la monnaie sélectionnée sur le graphique. Les achats et les ventes sont tous deux saisis sous forme de montant de la monnaie échangée ; l'aperçu indique la monnaie de cotation payée ou reçue, le prix moyen inclut les frais et le glissement non.¶La page d'échange Web3 permet de convertir deux monnaies quelconques, toujours via le CRC : avec le CRC d'un côté, elle utilise un seul pool, sinon deux pools, avec deux fois des frais et un glissement cumulé ; l'aperçu affiche le montant reçu, les pools traversés et la perte. Les échanges de stablecoins (CRT ou CRA contre CRC) utilisent des pools stables : des frais de {StableFee:%} et presque aucun glissement près de l'ancrage ; lors d'un décrochage, la liquidité se tarit, et en cas d'effondrement, elle est retirée et le glissement explose.§Portefeuilles matériels : les pièces sur la chaîne sont stockées dans des portefeuilles matériels PLEDGER, chacun ayant ses propres soldes et pièces contaminées (chaque monnaie comptabilise combien d'unités sont contaminées ; voir Contamination). Un portefeuille est un objet : faites-le glisser sur le terminal de trading pour le charger. Ouvrez-le sur la page Portefeuilles du terminal ; connectez-le et déconnectez-le en haut à droite du terminal. Le trading sur la page Web3 ainsi que la boutique et le mixeur sur la page Réseau gris utilisent le portefeuille connecté ; sans portefeuille ou sans connexion, ils sont en lecture seule et chaque solde affiche 0. Les clients payant en pièces versent leurs fonds sur le portefeuille connecté.¶Les paiements (boutique, mixeur, comptoir Ponero, frais de mise en vente) débutent sous la forme d'une facture sur le terminal ; saisissez l'adresse du destinataire sur le portefeuille et maintenez ✓ enfoncé pour signer. Les deux derniers caractères d'une adresse constituent une somme de contrôle, de sorte qu'une faute de frappe d'un seul caractère est généralement détectée ; il arrive parfois qu'elle soit valide par hasard, et les pièces sont alors envoyées à une adresse que personne n'utilise. Les échanges sur le DEX nécessitent également une signature sur le portefeuille.¶Poinbase est un compte dépositaire ; les dépôts sont envoyés depuis un portefeuille vers l'adresse de dépôt de Poinbase (uniquement PSC, CRC et SPARK ; la plateforme conforme n'accepte ni le CRT du Marché noir ni le CRA de la Révolution, et le portefeuille bloque leur envoi vers l'adresse de dépôt ; seules les pièces propres peuvent être déposées, voir Contamination) et les retraits sont initiés sur la page Fonds de Poinbase. L'Explorateur sur la page Portefeuilles recherche les transferts par adresse et n'affiche que ceux qui ont réellement eu lieu : chaque mouvement entrant et sortant de vos portefeuilles (transferts, échanges DEX et autres appels de contrat, gains des mineurs, retraits, pièces reçues d'autrui) ; Ponero est une monnaie de confidentialité et n'apparaît jamais. Des portefeuilles matériels supplémentaires sont vendus par le Pr Jackson ; faites-en glisser un sur le terminal de trading pour l'ajouter, jusqu'à {WalletMax}. La boutique en propose des moins chers. Un portefeuille dont vous ne voulez plus peut être détruit sur la page Portefeuilles ; ses pièces sont définitivement perdues, et tout ce qui sera envoyé à son adresse par la suite le sera également.¶Les transferts paient des frais de gas : lent, normal ou rapide, et le prix du gas monte et descend sur environ une semaine ; lorsque le réseau est congestionné, les frais de gas augmentent et les transactions lentes peuvent être éjectées du mempool. Vérifiez l'adresse complète avant d'envoyer.§Staking : le CRA staké dans le pool de la Révolution rapporte un taux quotidien capitalisé dans le montant staké ; retirer nécessite d'en faire la demande préalable et d'attendLine truncated
|
||||||
courier.odd1,...Le colis est là.
|
courier.odd1,...Le colis est là.
|
||||||
courier.odd2,(Sa main reste dans sa poche.) Signez ici.
|
courier.odd2,(Sa main reste dans sa poche.) Signez ici.
|
||||||
courier.sign,Signer
|
courier.sign,Signer
|
||||||
@@ -361,10 +360,11 @@ hw.wallet.n,Portefeuille {0}
|
|||||||
hw.review.own,Portefeuille personnel : {0}
|
hw.review.own,Portefeuille personnel : {0}
|
||||||
hw.review.poinbase,Adresse de dépôt Poinbase
|
hw.review.poinbase,Adresse de dépôt Poinbase
|
||||||
poin.deposit,Adresse de dépôt : {0}
|
poin.deposit,Adresse de dépôt : {0}
|
||||||
|
poin.deposit.clean,Pièces propres déposables depuis {0} : {1}
|
||||||
wallets.count,Portefeuilles {0}/{1}
|
wallets.count,Portefeuilles {0}/{1}
|
||||||
wallets.col.name,Nom
|
wallets.col.name,Nom
|
||||||
wallets.col.addr,Adresse
|
wallets.col.addr,Adresse
|
||||||
wallets.col.taint,Contamination
|
wallets.col.taint,Sale
|
||||||
wallets.open,Ouvrir
|
wallets.open,Ouvrir
|
||||||
wallets.use,Connecter
|
wallets.use,Connecter
|
||||||
wallets.current,Connecté
|
wallets.current,Connecté
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Coller
|
|||||||
hw.copied,Adresse copiée.
|
hw.copied,Adresse copiée.
|
||||||
hw.copied.addr,{0} copié
|
hw.copied.addr,{0} copié
|
||||||
hw.balance.frozen," (gelé {0})"
|
hw.balance.frozen," (gelé {0})"
|
||||||
|
hw.balance.dirty," (sale : {0})"
|
||||||
wallets.destroy,Détruire
|
wallets.destroy,Détruire
|
||||||
wallets.destroy.sure,Confirmer
|
wallets.destroy.sure,Confirmer
|
||||||
wallets.destroyed,{0} détruit : {1}
|
wallets.destroyed,{0} détruit : {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Eau du niveau supérieur
|
|||||||
nightlog.predict.win,"Prédiction correcte : ""{0}"", {1} versés."
|
nightlog.predict.win,"Prédiction correcte : ""{0}"", {1} versés."
|
||||||
nightlog.predict.lose,"Prédiction incorrecte : ""{0}"", mise de {1} perdue."
|
nightlog.predict.lose,"Prédiction incorrecte : ""{0}"", mise de {1} perdue."
|
||||||
nightlog.predict.void,"Prédiction annulée : ""{0}"", mise de {1} remboursée."
|
nightlog.predict.void,"Prédiction annulée : ""{0}"", mise de {1} remboursée."
|
||||||
nightlog.predict.insider,« {0} » réglé pour {1}. La police soupçonne un délit d'initié ; le paiement est marqué et les fonds contaminés du portefeuille augmentent de {2}.
|
nightlog.predict.insider,"""{0}"" a été réglé pour {1}. La police soupçonne un délit d'initié ; {2} CRC sont marqués comme sales."
|
||||||
predict.tab.markets,Marchés
|
predict.tab.markets,Marchés
|
||||||
predict.tab.intel,Infos secrètes
|
predict.tab.intel,Infos secrètes
|
||||||
predict.acct.crt,{0} : CRT {1}
|
predict.acct.crt,{0} : CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0} : opération programmée
|
|||||||
predict.brief.none,{0} : rien à lancer
|
predict.brief.none,{0} : rien à lancer
|
||||||
predict.brief.can,{0} : peut lancer {1}
|
predict.brief.can,{0} : peut lancer {1}
|
||||||
predict.clue.push,Vous avez fait bouger le prix de {0} % : risqué
|
predict.clue.push,Vous avez fait bouger le prix de {0} % : risqué
|
||||||
nightlog.predict.manip,« {0} » réglé pour {1}. Les régulateurs vous soupçonnent d'avoir manipulé le cours ; le paiement est marqué et les fonds contaminés du portefeuille augmentent de {2}.
|
nightlog.predict.manip,"""{0}"" a été réglé pour {1}. Les régulateurs vous soupçonnent d'avoir manipulé le cours ; {2} CRC sont marqués comme sales."
|
||||||
news.manip.title,La bourse enquête sur des transactions inhabituelles
|
news.manip.title,La bourse enquête sur des transactions inhabituelles
|
||||||
news.manip.desc,Les régulateurs indiquent qu'un acteur a fait bouger le cours avec de gros ordres spot pour tirer profit des dérivés et des prédictions ; les comptes impliqués ont été signalés.
|
news.manip.desc,Les régulateurs indiquent qu'un acteur a fait bouger le cours avec de gros ordres spot pour tirer profit des dérivés et des prédictions ; les comptes impliqués ont été signalés.
|
||||||
taint.overflow,Les fonds contaminés dépassent désormais la valeur du portefeuille ; l'excédent de {0} est enregistré comme fraude.
|
perp.manip,Position clôturée avec un profit de {0}. Les régulateurs soupçonnent une manipulation de marché ; fraude inscrite à votre dossier : {1}.
|
||||||
perp.manip,Clôturé avec un gain de {0}. Les régulateurs soupçonnent une manipulation de marché ; le profit est marqué et les fonds contaminés du compte Poinbase augmentent de {1}.
|
|
||||||
web3.sub.ponzi,Rendement
|
web3.sub.ponzi,Rendement
|
||||||
ponzi.h,Système de Ponzi
|
ponzi.h,Système de Ponzi
|
||||||
ponzi.acct,Portefeuille émetteur {0} : CRC {1}
|
ponzi.acct,Portefeuille émetteur {0} : CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Support Poinbase
|
|||||||
scam.support.1,"Bonjour, ici le support Poinbase. Nous avons détecté une connexion anormale sur votre compte et celui-ci a été signalé."
|
scam.support.1,"Bonjour, ici le support Poinbase. Nous avons détecté une connexion anormale sur votre compte et celui-ci a été signalé."
|
||||||
scam.support.2,Veuillez envoyer aujourd'hui {0} CRC à l'adresse sécurisée {1} pour vérification ; ils seront restitués immédiatement après.
|
scam.support.2,Veuillez envoyer aujourd'hui {0} CRC à l'adresse sécurisée {1} pour vérification ; ils seront restitués immédiatement après.
|
||||||
scam.support.3,"Sinon, le compte sera gelé définitivement. Je dois filer, n'oubliez pas d'effectuer l'envoi."
|
scam.support.3,"Sinon, le compte sera gelé définitivement. Je dois filer, n'oubliez pas d'effectuer l'envoi."
|
||||||
predict.sold.caught,"Vendu, reçu {0}. La police soupçonne un délit d'initié ; le produit de la vente est marqué et les fonds contaminés du portefeuille augmentent de {1}."
|
predict.sold.caught,"Vendu, reçu {0}. La police soupçonne un délit d'initié ; {1} CRC sont marqués comme sales."
|
||||||
predict.row.move," (la nuit dernière {0} {1})"
|
predict.row.move," (la nuit dernière {0} {1})"
|
||||||
predict.stats.h,Historique (prix ouv. moy. / taux réel)
|
predict.stats.h,Historique (prix ouv. moy. / taux réel)
|
||||||
predict.stats.row,"{0} : {1} marchés, ouv. moy. {2}, survenu {3} %"
|
predict.stats.row,"{0} : {1} marchés, ouv. moy. {2}, survenu {3} %"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,Prix du PSC
|
|||||||
predict.kind.Gas,Gas
|
predict.kind.Gas,Gas
|
||||||
predict.kind.Cra,Alerte CRA
|
predict.kind.Cra,Alerte CRA
|
||||||
predict.kind.Era,Ère ASIC
|
predict.kind.Era,Ère ASIC
|
||||||
|
predict.kind.Trial,Procès de Tumbler
|
||||||
nightlog.predict.move,"Prédiction ""{0}"" : {1} -> {2}"
|
nightlog.predict.move,"Prédiction ""{0}"" : {1} -> {2}"
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,Graphique journalier {0} : aucun historique ; enregistrement à partir d'aujourd'hui.
|
chart.empty,Graphique journalier {0} : aucun historique ; enregistrement à partir d'aujourd'hui.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"La Révolution aurait obtenu des preuves de corrupt
|
|||||||
news.story.serpico_bm.title,Le Marché noir conclut un accord discret
|
news.story.serpico_bm.title,Le Marché noir conclut un accord discret
|
||||||
news.story.serpico_bm.desc,"Un document interne de la Sécurité a changé de mains sur le Marché noir. Les règlements sur le Darknet sont nettement plus stables depuis, et les remboursements en CRT n'ont pas failli une seule fois."
|
news.story.serpico_bm.desc,"Un document interne de la Sécurité a changé de mains sur le Marché noir. Les règlements sur le Darknet sont nettement plus stables depuis, et les remboursements en CRT n'ont pas failli une seule fois."
|
||||||
news.story.serpico_sec.title,La Sécurité lance une purge interne
|
news.story.serpico_sec.title,La Sécurité lance une purge interne
|
||||||
news.story.serpico_sec.desc,La Sécurité a annoncé une enquête approfondie sur la corruption interne et une surveillance accrue des flux financiers. Poinbase durcit l'examen des retraits et les services de mixeur ont été ciblés.
|
news.story.serpico_sec.desc,La Sécurité a annoncé une enquête approfondie sur la corruption interne et une surveillance accrue des flux financiers ; les services de mixage ont été cités.
|
||||||
news.story.eleanor_leak.title,Fuite des données de sélection de Nutrifruit
|
news.story.eleanor_leak.title,Fuite des données de sélection de Nutrifruit
|
||||||
news.story.eleanor_leak.desc,"Le journal du Niveau inférieur a publié des recherches permettant au Nutrifruit de donner à nouveau des graines ; l'action Pastelle s'est effondrée. La banque dépositaire des fonds du Niveau supérieur signale des créances douteuses, et la Révolution gagne du terrain."
|
news.story.eleanor_leak.desc,"Le journal du Niveau inférieur a publié des recherches permettant au Nutrifruit de donner à nouveau des graines ; l'action Pastelle s'est effondrée. La banque dépositaire des fonds du Niveau supérieur signale des créances douteuses, et la Révolution gagne du terrain."
|
||||||
news.story.eleanor_return.title,Pastelle récupère les données dérobées
|
news.story.eleanor_return.title,Pastelle récupère les données dérobées
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,L'opérateur du mixeur connu sous le nom de Tumbler a
|
|||||||
news.tumbler.sold.title,Le service de mixeur change de mains
|
news.tumbler.sold.title,Le service de mixeur change de mains
|
||||||
news.tumbler.sold.desc,"Selon certaines sources, les clés de signature d'un service de mixeur du Niveau inférieur sont tombées aux mains du Marché noir, et les frais ont aussitôt augmenté. Les utilisateurs craignent pour leurs fonds."
|
news.tumbler.sold.desc,"Selon certaines sources, les clés de signature d'un service de mixeur du Niveau inférieur sont tombées aux mains du Marché noir, et les frais ont aussitôt augmenté. Les utilisateurs craignent pour leurs fonds."
|
||||||
nightlog.tumbler.gift,Tumbler a récupéré le disque de clés et a laissé {0} CRT en remerciement (envoyés à {1}) ; frais du mixeur réduits de moitié.
|
nightlog.tumbler.gift,Tumbler a récupéré le disque de clés et a laissé {0} CRT en remerciement (envoyés à {1}) ; frais du mixeur réduits de moitié.
|
||||||
|
agent.name,Agent de la Sécurité
|
||||||
|
agent.v1.1,Sécurité. Désolé de vous déranger.
|
||||||
|
agent.v1.2,Nous recherchons un individu qui se fait appeler Tumbler. Il gère un service de mixage sur la chaîne.
|
||||||
|
agent.v1.3,Il a été aperçu dans le secteur.
|
||||||
|
agent.ask,Est-il passé dans votre boutique ?
|
||||||
|
agent.choice.yes,[Lui dire : plusieurs fois]
|
||||||
|
agent.choice.no,[Lui dire : jamais vu]
|
||||||
|
agent.yes1,Merci de votre coopération. La Sécurité s'en souviendra.
|
||||||
|
agent.no1,"Vraiment. Si quelque chose vous revient, vous savez où nous trouver."
|
||||||
|
agent.search.1,Nous nous retrouvons. Nous avons appris que vous gardez quelque chose pour cet homme.
|
||||||
|
agent.search.2,Fouille de routine. Veuillez coopérer.
|
||||||
|
agent.search.found,Trouvé. Nous prenons ceci.
|
||||||
|
agent.search.none,... Rien. Désolé pour le dérangement.
|
||||||
|
tumbler.v4.seized.1,J'ai appris que la Sécurité a fouillé ta boutique.
|
||||||
|
tumbler.v4.seized.2,Ils ont la clé désormais. Les registres de chaque utilisateur vont être déterrés.
|
||||||
|
tumbler.v4.seized.3,"Peu importe ce que tu leur as dit, je ne veux plus le savoir."
|
||||||
|
nightlog.tumbler.leak,La Sécurité a utilisé la clé de signature de Tumbler pour reconstituer les registres de mixage : {0} paiements avaient blanchi {1} de contamination ; fraude inscrite à votre dossier : {2}.
|
||||||
|
nightlog.tumbler.leak.none,La Sécurité a utilisé la clé de signature de Tumbler pour reconstituer les registres de mixage. Vous n'avez rien retiré du mixeur récemment.
|
||||||
|
nightlog.tumbler.note,"Un mot a été glissé sous la porte : ""Tu me dois ça, et je viendrai le reprendre. — T"""
|
||||||
|
nightlog.tumbler.tip,Message de Tumbler : la Sécurité pourrait cibler les services de mixage demain.
|
||||||
|
news.tumbler.leak.title,Sécurité : registres du mixeur reconstitués
|
||||||
|
news.tumbler.leak.desc,La Sécurité affirme avoir obtenu la clé de signature d'un service de mixage et l'utilisera pour retracer les fonds blanchis via ce service au cours du mois écoulé.
|
||||||
|
news.trial.pro.title,"Procès de Tumbler, jour {0} : l'accusation gagne du terrain"
|
||||||
|
news.trial.def.title,"Procès de Tumbler, jour {0} : la défense gagne du terrain"
|
||||||
|
news.trial.pro.desc1,"L'accusation a présenté les journaux du serveur du nœud de mixage, affirmant qu'ils correspondent une à une aux signatures de l'accusé."
|
||||||
|
news.trial.pro.desc2,Un ancien associé a témoigné que l'accusé savait que les fonds des clients provenaient du Marché noir.
|
||||||
|
news.trial.pro.desc3,L'accusation a montré des transferts entre le portefeuille de l'accusé et plusieurs adresses d'arnaques.
|
||||||
|
news.trial.def.desc1,"La défense a souligné des failles dans la collecte des preuves lors de la saisie du nœud, affirmant que certains journaux auraient pu être altérés."
|
||||||
|
news.trial.def.desc2,Un expert de la défense a témoigné que le contrat de mixage est un code open-source et que l'accusé ne peut contrôler qui l'utilise.
|
||||||
|
news.trial.def.desc3,"Le témoin clé de l'accusation est revenu sur ses déclarations à la barre, affirmant ne plus se souvenir si l'accusé était au courant."
|
||||||
|
news.trial.convict.title,Tumbler reconnu coupable
|
||||||
|
news.trial.convict.desc,Le tribunal a reconnu l'opérateur du mixeur connu sous le nom de Tumbler coupable de blanchiment d'argent. La Sécurité affirme que le service de mixage ne rouvrira pas.
|
||||||
|
news.trial.acquit.title,Tumbler acquitté
|
||||||
|
news.trial.acquit.desc,"Invoquant l'insuffisance de preuves, le tribunal a acquitté l'opérateur du mixeur connu sous le nom de Tumbler et l'a libéré. Il a quitté le palais de justice sans répondre aux questions des journalistes."
|
||||||
|
news.tumbler.bmrug.title,Un service de mixage s'enfuit avec les fonds
|
||||||
|
news.tumbler.bmrug.desc,"Un service de mixage repris par le Marché noir a soudainement cessé ses versements, et les fonds de son contrat ont été transférés. Sur les forums, les utilisateurs disent avoir tout perdu."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,Nouveau service de mixage {0} en ligne
|
||||||
|
news.mixer.rebrand.desc,"Un service de mixage nommé {0} a récemment été lancé, affirmant ne conserver aucun journal ni porte dérobée. Certains ont remarqué que son contrat ressemble fortement à celui du service fermé plus tôt."
|
||||||
|
predict.q.trial,{0} : Tumbler reconnu coupable
|
||||||
|
predict.clue.trial,"Rapports du procès : accusation en tête {0} j, défense en tête {1} j"
|
||||||
mixer.status.closed,Statut : arrêté
|
mixer.status.closed,Statut : arrêté
|
||||||
yield.sub.pools,Pools de rendement
|
yield.sub.pools,Pools de rendement
|
||||||
yield.sub.mine,Lancer un Ponzi
|
yield.sub.mine,Lancer un Ponzi
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Passer
|
|||||||
otc.msg.gone,Le client est parti.
|
otc.msg.gone,Le client est parti.
|
||||||
otc.msg.cash,Espèces insuffisantes.
|
otc.msg.cash,Espèces insuffisantes.
|
||||||
otc.msg.sting,"Le client était sous couverture : {0} en espèces confisqués, recel consigné."
|
otc.msg.sting,"Le client était sous couverture : {0} en espèces confisqués, recel consigné."
|
||||||
otc.msg.bought,"Reçu {0} {1}, payé {2} en espèces."
|
otc.msg.bought,"Reçu {0} {1} (dont sale : {3}), payé {2} en liquide."
|
||||||
otc.msg.sold,"Envoyé {0} {1}, reçu {2} en espèces."
|
otc.msg.sold,"Envoyé {0} {1}, reçu {2} en espèces."
|
||||||
gray.sub.own,Mon mixeur
|
gray.sub.own,Mon mixeur
|
||||||
ownmix.h,Mon mixeur
|
ownmix.h,Mon mixeur
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,Vous n'avez même pas le liquide ? Laissez tomber.
|
|||||||
otc.nowallet,"Aucun portefeuille connecté, où envoyer les pièces ? Laissez tomber."
|
otc.nowallet,"Aucun portefeuille connecté, où envoyer les pièces ? Laissez tomber."
|
||||||
otc.sting,Pas un geste. Sécurité. Achat de fonds volés : le liquide est confisqué et ce sera inscrit à votre dossier.
|
otc.sting,Pas un geste. Sécurité. Achat de fonds volés : le liquide est confisqué et ce sera inscrit à votre dossier.
|
||||||
hw.err.poinbase,Poinbase n'accepte pas le {0}.
|
hw.err.poinbase,Poinbase n'accepte pas le {0}.
|
||||||
|
hw.err.tainted,{0} des {1} de ce portefeuille sont sales et Poinbase n'accepte que les pièces propres : {2} {1} au maximum.
|
||||||
@@ -22,7 +22,7 @@ tab.report,レポート
|
|||||||
wallet.line,{0}:{1}(約{2}クレジット)
|
wallet.line,{0}:{1}(約{2}クレジット)
|
||||||
wallet.empty,ウォレットは空です。
|
wallet.empty,ウォレットは空です。
|
||||||
wallet.total,総額:{0}クレジット
|
wallet.total,総額:{0}クレジット
|
||||||
wallet.taint,汚染額:{0}クレジット
|
wallet.taint,汚染コイン: {0} クレジット
|
||||||
trade.amount,数量
|
trade.amount,数量
|
||||||
trade.deposit,クレジットを入金してCRCに交換
|
trade.deposit,クレジットを入金してCRCに交換
|
||||||
trade.withdraw,CRCを出金してクレジットに交換
|
trade.withdraw,CRCを出金してクレジットに交換
|
||||||
@@ -38,8 +38,6 @@ msg.balance,残高が不足しています。
|
|||||||
msg.trade,{0} {1}を支払い、{2} {3}を受け取りました。
|
msg.trade,{0} {1}を支払い、{2} {3}を受け取りました。
|
||||||
msg.deposit,{0}クレジットを入金し、CRCに変換しました。
|
msg.deposit,{0}クレジットを入金し、CRCに変換しました。
|
||||||
msg.cashout,{0}クレジットを受け取りました。税:{1}クレジット。
|
msg.cashout,{0}クレジットを受け取りました。税:{1}クレジット。
|
||||||
msg.aml_light,コンプライアンス審査:{0}クレジットの汚染資金が保留されました。
|
|
||||||
msg.aml_heavy,コンプライアンス審査:{0}クレジットの汚染資金が没収され、警察に通報されました。
|
|
||||||
report.none,マイニングレポートはまだありません。
|
report.none,マイニングレポートはまだありません。
|
||||||
report.day,{0}日目の夜
|
report.day,{0}日目の夜
|
||||||
report.rigs,稼働リグ:{0}/{1}
|
report.rigs,稼働リグ:{0}/{1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,資産
|
|||||||
col.amount,数量
|
col.amount,数量
|
||||||
col.value,評価額
|
col.value,評価額
|
||||||
col.avg,平均単価
|
col.avg,平均単価
|
||||||
|
col.dirty,汚染分
|
||||||
bank.cash.k,クレジット
|
bank.cash.k,クレジット
|
||||||
bank.rent.k,家賃
|
bank.rent.k,家賃
|
||||||
bank.rent.v,{0}、期日:{1}日後
|
bank.rent.v,{0}、期日:{1}日後
|
||||||
@@ -152,13 +151,12 @@ stable.ok,ペグ正常
|
|||||||
stable.depeg,デペグ
|
stable.depeg,デペグ
|
||||||
stable.warn,警告:ステーキング準備率低下
|
stable.warn,警告:ステーキング準備率低下
|
||||||
stable.spiral,崩壊中
|
stable.spiral,崩壊中
|
||||||
aml.taint,アカウント汚染率:{0}%
|
|
||||||
mixer.h,ミキサー
|
mixer.h,ミキサー
|
||||||
mixer.ok,状態:正常稼働
|
mixer.ok,状態:正常稼働
|
||||||
mixer.sanctioned,状態:制裁中(残り{0}日)。この間に出金されたコインはフラグ付きとなる。
|
mixer.sanctioned,状態: 制裁中(残り{0}日)。この間に期日を迎える出金は洗浄されず、全額が汚染コインとして戻る。
|
||||||
mixer.pending,入金処理中
|
mixer.pending,入金処理中
|
||||||
mixer.none,処理中の入金はありません。
|
mixer.none,処理中の入金はありません。
|
||||||
mixer.col.taint,汚染
|
mixer.col.taint,汚染分
|
||||||
mixer.col.ready,完了
|
mixer.col.ready,完了
|
||||||
mixer.day,{0}日目
|
mixer.day,{0}日目
|
||||||
mixer.deposit,入金
|
mixer.deposit,入金
|
||||||
@@ -169,11 +167,12 @@ mixer.go,ミキサーに入金
|
|||||||
mixer.min,入金には最低{0}クレジット相当が必要です。
|
mixer.min,入金には最低{0}クレジット相当が必要です。
|
||||||
mixer.done,{0} {1} を入金。{2}日目に受取可能。
|
mixer.done,{0} {1} を入金。{2}日目に受取可能。
|
||||||
mixer.upgrade.title,ミキサー
|
mixer.upgrade.title,ミキサー
|
||||||
mixer.upgrade.desc,ターミナルのグレーネットページにあるミキサーをアンロック:汚染コインを入金し、数日後に汚染を減らして回収する。ミックス直後のコインは出金審査がより厳格化される。取締期間中はミキサーが制裁対象となる可能性があり、その間に出金されたコインはフラグ付きとなる。
|
mixer.upgrade.desc,ターミナルのグレーネットページでミキサーをアンロック: 汚染コインを入金すると、数日後に汚染分が減少して戻る。鎮圧期間中はミキサーが制裁を受ける可能性があり、その間に期日を迎える出金は全額が汚染コインとして戻る。
|
||||||
news.sanction.title,ミキサーを制裁リストに追加
|
news.sanction.title,ミキサーを制裁リストに追加
|
||||||
news.sanction.desc,警察が複数のミキシングサービスに制裁を実施。今後数日間にミキサーから出金された資金は不審として扱われる。
|
news.sanction.desc,警察が複数のミキサーサービスに制裁を科した。今後数日間にミキサーから出金された資金は汚染資金として扱われる。
|
||||||
nightlog.mixer,ミキサーから {0} {1} を回収。汚染 {2} → {3}。
|
nightlog.mixer,ミキサーから {0} {1} を回収。汚染 {2} → {3}。
|
||||||
nightlog.mixer_flag,(制裁期間中に出金。アドレスはフラグ付き)
|
nightlog.mixer_flag,(制裁期間中の出金。全額が汚染コインとして記録)
|
||||||
|
nightlog.mixer_flag.trap,(出金したコインは警察により全額汚染コインとして記録)
|
||||||
nightlog.mixer_rug,ミキサーの運営者が持ち逃げした:{0} {1} は戻ってこなかった。
|
nightlog.mixer_rug,ミキサーの運営者が持ち逃げした:{0} {1} は戻ってこなかった。
|
||||||
web3.sub.trade,取引
|
web3.sub.trade,取引
|
||||||
gray.sub.mixer,ミキサー
|
gray.sub.mixer,ミキサー
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,禁制品(高)
|
|||||||
black.kind.Tech,ハイテク品(割増)
|
black.kind.Tech,ハイテク品(割増)
|
||||||
nightlog.bm.ready,闇市場:{0} が到着。開店後に配達人が届けてくれる。
|
nightlog.bm.ready,闇市場:{0} が到着。開店後に配達人が届けてくれる。
|
||||||
guide.web3.title,Web3ハンドブック
|
guide.web3.title,Web3ハンドブック
|
||||||
guide.web3.text,銀行と取引:銀行ページは閲覧専用で、現金、家賃、Poinbase口座のCRCを表示する。入金と出金はPoinbaseの資金ページで行い、先にコインを選ぶ。CRCは銀行口座とウォレットのどちらでも可能で、他のコインはウォレットのみ。銀行からの入金はクレジットをPoinbase口座のCRCに変換し、銀行への出金はCRCをクレジットに戻すが、Poinbase口座の汚染を対象としたコンプライアンス審査が行われる。ウォレットへの出金は受取アドレスの入力が必要で、数回の承認を経て着金する。ガス代は通常の段階で固定され、送るコインから差し引かれる。アドレスの形式やチェックディジットが誤っていると拒否される。形式が正しくても誰も使っていないアドレスに送ったコインは失われる。¶取引:PSCは Probably Stolen Coin の略称で、グラフィックボードや専用採掘機で採掘されるコイン。Poinbaseの現物にはPSC/CRCとSPARK/CRCの2つのペアがあり、チャートで選んだコインに合わせて切り替わる。買いも売りも取引対象のコインの数量で入力する。プレビューには支払う・受け取る決済通貨が表示され、平均価格は手数料込み、スリッページは手数料を含まない。¶Web3の取引ページでは任意の2種類のコインを交換でき、必ずCRCを経由する。CRCが片側なら1つのプール、そうでなければ2つのプールを通り、手数料は2回、スリッページは重なる。プレビューに受取数量、経由するプール数、損失が表示される。ステーブルコイン同士(CRT・CRAとCRC)はステーブルプールを使い、手数料は{StableFee:%}、ペッグ付近ではスリッページがほぼない。ペッグが外れると流動性が薄くなり、崩壊時には流動性が引き揚げられてスリッページが急増する。§ハードウェアウォレット:チェーン上のコインはPLEDGERハードウェアウォレットに保管され、ウォレットごとに残高と汚染が個別に管理される。ウォレットはアイテムで、取引ターミナルにドラッグして読み込む。ターミナルのウォレットページで開き、ターミナル右上で接続・切断する。Web3ページの取引とグレーネットページのショップ、ミキサーは接続されたウォレットを使用する。ウォレットがない、または接続していないときは閲覧のみで、残高はすべて0になる。コイン決済の客は接続されたウォレットに支払う。¶支払い(ショップ、ミキサー、Ponero窓口、出品手数料)はまずターミナルで請求書を発行し、ウォレット側で送金先アドレスを入力して✓を長押しして署名する。アドレスの末尾2文字はチェックサムのため、1文字の誤入力なら通常は検出されるが、偶然有効なアドレスに一致した場合は誰も使っていないアドレスにコインが送られてしまう。DEXでのスワップもウォレットでの署名が必要となる。¶Poinbaseはカストディ口座で、入金はウォレットからPoinbaseの入金アドレスへ送金し(受け付けるのはPSC、CRC、SPARKのみ。規制下の取引所なので闇市場のCRTと革命軍のCRAは受け付けず、入金アドレスへの送金はウォレットが止める)、出金はPoinbaseの資金ページで行う。ウォレットページのエクスプローラーではアドレスで送金履歴を検索でき、実際に行われた送金のみが表示される:自分のウォレットのすべての入出金(送金、DEXスワップなどのコントラクト呼び出し、採掘機の収益、出金、他人から送られたコイン)。Poneroはプライバシーコインのため表示されない。追加のハードウェアウォレットはジャックソン博士から購入し、取引ターミナルにドラッグして追加する(最大{WalletMax}個)。ショップにはより安価なものもある。不要になったウォレットは、ウォレットページで破棄できる。中のコインは永久に失われ、その後このアドレスに送られたものも失われる。¶送金にはガス代が必要で、低速・通常・高速の3段階があり、ガス価格は約1週間周期で上下する。ネットワーク混雑時はガス代が高騰し、低速のトランザクションはメムプールから除外されることがある。送金前にアドレス全体を必ず確認すること。§ステーキング:革命家のプールにCRAをステーキングすると日利が付与され、利息は元本に複利で組み入れられる。出金するにはまず申請しLine truncated
|
guide.web3.text,"銀行と取引: 銀行ページは閲覧専用で、現金、家賃、Poinbaseアカウント内のCRCを表示する。Poinbaseの資金ページで入出金を管理し、まず通貨を選択する。CRCは銀行口座またはウォレットを経由できるが、他の通貨はウォレット経由のみとなる。銀行から入金するとクレジットがPoinbaseアカウント内のCRCに変換され、銀行へ出金すると審査なしでCRCがクレジットに戻る(Poinbaseアカウントにはクリーンな資金しか入らない)。ウォレットへ出金する場合は送金先アドレスが必要で、数回の承認を経て着金する。ガス代は「標準」に固定され、送金する通貨から差し引かれる。アドレスの形式やチェックサムに誤りがあると拒否されるが、形式が正しくても誰も使っていないアドレスに送金した場合、そのコインは失われる。¶取引: PSCの正式名称はProbably Stolen Coinで、グラフィックボードや専用採掘機で採掘される通貨。Poinbase現物にはチャートで選択した通貨に応じてPSC/CRCとSPARK/CRCの2つの取引ペアがある。買い・売りともに取引する通貨の数量を入力し、プレビューには支払うまたは受け取る決済通貨が表示される。平均価格には手数料が含まれるが、スリッページは含まれない。¶Web3取引ページでは任意の2通貨をスワップできるが、常にCRCを経由する。一方がCRCなら1つのプール、それ以外は2つのプールを経由し、2回の手数料とスリッページの重複が発生する。プレビューには受取数量、経由するプール数、損失が表示される。ステーブルコイン同士のスワップ(CRTまたはCRA対CRC)はステーブルプールを使用し、手数料は{StableFee:%}で、ペッグ付近ではスリッページがほぼ発生しない。デペッグ時は流動性が薄れ、崩壊時には流動性が引き抜かれてスリッページが急増する。§ハードウェアウォレット: オンチェーンの通貨はPLEDGERハードウェアウォレットに保管され、残高と汚染コインはウォレットごとに個別に管理される(各通貨で何枚が汚染されているかを記録。「汚染」を参照)。ウォレットはアイテムであり、取引ターミナルにドラッグして読み込ませる。ターミナルのウォレットページで開き、ターミナル右上から接続・切断を行う。Web3ページの取引やグレーネットページのショップ、ミキサーは接続中のウォレットを使用する。ウォレットがない、または未接続の場合は閲覧専用となり、全残高が0と表示される。通貨で支払う客の代金も接続中のウォレットに入る。¶支払い(ショップ、ミキサー、Poneroデスク、出品手数料)はターミナルで請求書を発行し、ウォレットで送金先アドレスを入力して✓を長押しして署名する。アドレスの末尾2文字はチェックサムのため、1文字の入力ミスは大半が検知されるが、偶然有効なアドレスに一致すると誰も使っていないアドレスに送金されてしまう。DEXでのスワップにもウォレットでの署名が必要。¶Poinbaseはカストディ型アカウントであり、入金はウォレットからPoinbaseの入金用アドレスへ送金して行う(PSC、CRC、SPARKのみ受付。規制準拠の取引所は闇市場のCRTや革命家のCRAを取り扱っておらず、入金用アドレスへの送金はウォレット側で遮断される。入金できるのはクリーンなコインのみ。「汚染」を参照)。出金はPoinbaseの資金ページから開始する。ウォレットページのエクスプローラーではアドレスごとに送金履歴を照会でき、実際に成立した取引のみが表示される。ウォレットのあらゆる入出金(送金、DEXスワップやその他のコントラクト呼出、採掘機の収益、出金、第三者からの送金)が対象。Poneroはプライバシーコインのため表示されない。追加のハードウェアウォレットはジャックソン博士から購入でき、取引ターミナルにドラッグして追加する(最大{WalletMax}個)。ショップにはより安価なものもある。不要になったウォレットはウォレットページで破棄できるが、中のコインは永久に失われ、破棄後にそのアドレスへ送金されたものも消失する。¶送金にはガス代がかかり、「低速」「標準」「高速」の3段階がある。ガス価格はおよそ1週間の周期で上下する。ネットワーク混雑時はガス代が高騰し、低速の取引はメムプLine truncated
|
||||||
courier.odd1,……荷物が届いた。
|
courier.odd1,……荷物が届いた。
|
||||||
courier.odd2,(ポケットに手を入れたままだ)ここにサインを。
|
courier.odd2,(ポケットに手を入れたままだ)ここにサインを。
|
||||||
courier.sign,サイン
|
courier.sign,サイン
|
||||||
@@ -361,6 +360,7 @@ hw.wallet.n,ウォレット {0}
|
|||||||
hw.review.own,自身のウォレット:{0}
|
hw.review.own,自身のウォレット:{0}
|
||||||
hw.review.poinbase,Poinbase入金アドレス
|
hw.review.poinbase,Poinbase入金アドレス
|
||||||
poin.deposit,入金アドレス:{0}
|
poin.deposit,入金アドレス:{0}
|
||||||
|
poin.deposit.clean,{0}から入金可能なクリーンコイン: {1}
|
||||||
wallets.count,ウォレット {0}/{1}
|
wallets.count,ウォレット {0}/{1}
|
||||||
wallets.col.name,名前
|
wallets.col.name,名前
|
||||||
wallets.col.addr,アドレス
|
wallets.col.addr,アドレス
|
||||||
@@ -378,6 +378,7 @@ hw.paste,貼り付け
|
|||||||
hw.copied,アドレスをコピーしました。
|
hw.copied,アドレスをコピーしました。
|
||||||
hw.copied.addr,{0} をコピーしました
|
hw.copied.addr,{0} をコピーしました
|
||||||
hw.balance.frozen,(凍結 {0})
|
hw.balance.frozen,(凍結 {0})
|
||||||
|
hw.balance.dirty,(汚染 {0})
|
||||||
wallets.destroy,破棄
|
wallets.destroy,破棄
|
||||||
wallets.destroy.sure,破棄の確認
|
wallets.destroy.sure,破棄の確認
|
||||||
wallets.destroyed,{0} を破棄しました:{1}
|
wallets.destroyed,{0} を破棄しました:{1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,上層水
|
|||||||
nightlog.predict.win,予測的中:「{0}」、{1}が払い戻された。
|
nightlog.predict.win,予測的中:「{0}」、{1}が払い戻された。
|
||||||
nightlog.predict.lose,予測不的中:「{0}」、賭け金{1}を失った。
|
nightlog.predict.lose,予測不的中:「{0}」、賭け金{1}を失った。
|
||||||
nightlog.predict.void,予測無効:「{0}」、賭け金{1}が返還された。
|
nightlog.predict.void,予測無効:「{0}」、賭け金{1}が返還された。
|
||||||
nightlog.predict.insider,「{0}」が {1} で決済。警察はインサイダー取引を疑っており、払戻金がマークされウォレットの汚染が {2} 増加した。
|
nightlog.predict.insider,「{0}」が{1}で決済された。警察はインサイダー取引を疑っており、そのうち {2} CRC が汚染コインとして記録された。
|
||||||
predict.tab.markets,市場
|
predict.tab.markets,市場
|
||||||
predict.tab.intel,情報
|
predict.tab.intel,情報
|
||||||
predict.acct.crt,{0}:CRT {1}
|
predict.acct.crt,{0}:CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}:作戦予定あり
|
|||||||
predict.brief.none,{0}:発動可能な作戦なし
|
predict.brief.none,{0}:発動可能な作戦なし
|
||||||
predict.brief.can,{0}:{1}を発動可能
|
predict.brief.can,{0}:{1}を発動可能
|
||||||
predict.clue.push,プレイヤーの価格誘導 {0}%: 操縦リスク高
|
predict.clue.push,プレイヤーの価格誘導 {0}%: 操縦リスク高
|
||||||
nightlog.predict.manip,「{0}」が {1} で決済。規制当局は価格操縦を疑っており、払戻金がマークされウォレットの汚染が {2} 増加した。
|
nightlog.predict.manip,「{0}」が{1}で決済された。規制当局は価格操縦を疑っており、そのうち {2} CRC が汚染コインとして記録された。
|
||||||
news.manip.title,取引所が不審な取引を調査
|
news.manip.title,取引所が不審な取引を調査
|
||||||
news.manip.desc,規制当局の発表によると、大口の現物注文で価格を動かし、デリバティブや予測市場から利益を得た者が存在し、関係口座はフラグ付きとなった。
|
news.manip.desc,規制当局の発表によると、大口の現物注文で価格を動かし、デリバティブや予測市場から利益を得た者が存在し、関係口座はフラグ付きとなった。
|
||||||
taint.overflow,汚染がウォレットの価値を超過。超過した {0} は詐欺の罪状として記録される。
|
perp.manip,利益 {0} で決済。規制当局は価格操縦を疑っており、犯罪記録に詐欺が{1}件追加された。
|
||||||
perp.manip,決済利益 {0}。規制当局は価格操縦を疑っており、利益がマークされPoinbaseアカウントの汚染が {1} 増加した。
|
|
||||||
web3.sub.ponzi,利回り
|
web3.sub.ponzi,利回り
|
||||||
ponzi.h,ポンジ・スキーム
|
ponzi.h,ポンジ・スキーム
|
||||||
ponzi.acct,発行者ウォレット {0}:CRC {1}
|
ponzi.acct,発行者ウォレット {0}:CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Poinbaseサポート
|
|||||||
scam.support.1,こんにちは、Poinbaseサポートです。お客様のアカウントで異常なログインが検出され、フラグ付きとなりました。
|
scam.support.1,こんにちは、Poinbaseサポートです。お客様のアカウントで異常なログインが検出され、フラグ付きとなりました。
|
||||||
scam.support.2,本日中に確認のため安全アドレス {1} へ {0} CRC を送金してください。確認後すぐに返金されます。
|
scam.support.2,本日中に確認のため安全アドレス {1} へ {0} CRC を送金してください。確認後すぐに返金されます。
|
||||||
scam.support.3,対応いただけない場合、アカウントは永久に凍結されます。では失礼します、送金を忘れずに。
|
scam.support.3,対応いただけない場合、アカウントは永久に凍結されます。では失礼します、送金を忘れずに。
|
||||||
predict.sold.caught,売却完了、{0} を受領。警察はインサイダー取引を疑っており、受取金がマークされウォレットの汚染が {1} 増加した。
|
predict.sold.caught,売却し、{0}を回収。警察はインサイダー取引を疑っており、そのうち {1} CRC が汚染コインとして記録された。
|
||||||
predict.row.move,(昨晩 {0} {1})
|
predict.row.move,(昨晩 {0} {1})
|
||||||
predict.stats.h,履歴(始値平均 / 実際の発生率)
|
predict.stats.h,履歴(始値平均 / 実際の発生率)
|
||||||
predict.stats.row,{0}:{1}件、始値平均 {2}、発生率 {3}%
|
predict.stats.row,{0}:{1}件、始値平均 {2}、発生率 {3}%
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,PSC 価格
|
|||||||
predict.kind.Gas,ガス
|
predict.kind.Gas,ガス
|
||||||
predict.kind.Cra,CRA 警戒警報
|
predict.kind.Cra,CRA 警戒警報
|
||||||
predict.kind.Era,専用採掘機時代
|
predict.kind.Era,専用採掘機時代
|
||||||
|
predict.kind.Trial,タンブラー裁判
|
||||||
nightlog.predict.move,予測市場「{0}」が変動 {1} → {2}
|
nightlog.predict.move,予測市場「{0}」が変動 {1} → {2}
|
||||||
nightlog.predict.why,({0})
|
nightlog.predict.why,({0})
|
||||||
chart.empty,{0}日足チャート:履歴なし。本日より記録開始。
|
chart.empty,{0}日足チャート:履歴なし。本日より記録開始。
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,革命家が警察内部の汚職証拠を入手し
|
|||||||
news.story.serpico_bm.title,闇市場が密約を交わす
|
news.story.serpico_bm.title,闇市場が密約を交わす
|
||||||
news.story.serpico_bm.desc,警察の内部文書が闇市場で取引された。以降、ダークネット決済は著しく安定し、CRTの償還に滞りは一切起きていない。
|
news.story.serpico_bm.desc,警察の内部文書が闇市場で取引された。以降、ダークネット決済は著しく安定し、CRTの償還に滞りは一切起きていない。
|
||||||
news.story.serpico_sec.title,警察が内部粛清を開始
|
news.story.serpico_sec.title,警察が内部粛清を開始
|
||||||
news.story.serpico_sec.desc,警察は内部汚職の徹底調査と資金の流れの監視強化を発表した。Poinbaseは出金審査を厳格化し、ミキサーサービスが名指しされた。
|
news.story.serpico_sec.desc,警察は内部腐敗の徹底調査と資金フローの監視強化を発表し、ミキサーサービスが名指しされた。
|
||||||
news.story.eleanor_leak.title,栄養フルーツの育種データが流出
|
news.story.eleanor_leak.title,栄養フルーツの育種データが流出
|
||||||
news.story.eleanor_leak.desc,下層の新聞社が栄養フルーツを再び結実させる研究データを公開し、パステルの株価が急落した。上層の資金を管理する保管銀行で焦げ付きが発生し、革命家が勢力を拡大している。
|
news.story.eleanor_leak.desc,下層の新聞社が栄養フルーツを再び結実させる研究データを公開し、パステルの株価が急落した。上層の資金を管理する保管銀行で焦げ付きが発生し、革命家が勢力を拡大している。
|
||||||
news.story.eleanor_return.title,パステルが盗難データを回収
|
news.story.eleanor_return.title,パステルが盗難データを回収
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,タンブラーとして知られるミキサー運営
|
|||||||
news.tumbler.sold.title,ミキサーサービスが別人の手に渡る
|
news.tumbler.sold.title,ミキサーサービスが別人の手に渡る
|
||||||
news.tumbler.sold.desc,下層のミキサーサービスの署名鍵が闇市場の手に渡り、手数料が即座に引き上げられたとの情報がある。ユーザーは資金の安全を懸念している。
|
news.tumbler.sold.desc,下層のミキサーサービスの署名鍵が闇市場の手に渡り、手数料が即座に引き上げられたとの情報がある。ユーザーは資金の安全を懸念している。
|
||||||
nightlog.tumbler.gift,タンブラーはキードライブを回収し、お礼として {0} CRT を残した({1} に送金済み)。ミキサー手数料が半減した。
|
nightlog.tumbler.gift,タンブラーはキードライブを回収し、お礼として {0} CRT を残した({1} に送金済み)。ミキサー手数料が半減した。
|
||||||
|
agent.name,警察の捜査官
|
||||||
|
agent.v1.1,警察だ。邪魔するぞ。
|
||||||
|
agent.v1.2,タンブラーと名乗る人物を探している。オンチェーンでミキサーサービスを運営している男だ。
|
||||||
|
agent.v1.3,この近辺で目撃されている。
|
||||||
|
agent.ask,この店に来たことはあるか?
|
||||||
|
agent.choice.yes,[数回来たと伝える]
|
||||||
|
agent.choice.no,[見たことがないと伝える]
|
||||||
|
agent.yes1,協力に感謝する。警察は覚えているぞ。
|
||||||
|
agent.no1,そうか。何か思い出したら、いつでも連絡してくれ。
|
||||||
|
agent.search.1,また会ったな。あの男から何か預かっているそうだな。
|
||||||
|
agent.search.2,定例の捜索だ。協力してもらおう。
|
||||||
|
agent.search.found,見つけたぞ。これは押収する。
|
||||||
|
agent.search.none,……何もないな。邪魔した。
|
||||||
|
tumbler.v4.seized.1,警察が店を捜索したと聞いた。
|
||||||
|
tumbler.v4.seized.2,鍵は奴らの手に渡った。全ユーザーの記録が洗い出される。
|
||||||
|
tumbler.v4.seized.3,あんたが奴らに何を話したか、もう知りたくもない。
|
||||||
|
nightlog.tumbler.leak,警察はタンブラーの署名鍵を使ってミキサー記録を復元した:{0}件の出金で{1}の汚染が洗い落とされており、犯罪記録に詐欺が{2}件追加された。
|
||||||
|
nightlog.tumbler.leak.none,警察はタンブラーの署名鍵を使ってミキシング記録を復元した。最近ミキサーから何も出金していない。
|
||||||
|
nightlog.tumbler.note,ドアの隙間からメモが差し入れられていた:「借りは必ず取り戻す。—T」
|
||||||
|
nightlog.tumbler.tip,タンブラーからのメッセージ:明日、警察がミキサーサービスの取り締まりに動くかもしれない。
|
||||||
|
news.tumbler.leak.title,警察、ミキサー記録を復元
|
||||||
|
news.tumbler.leak.desc,警察はミキサーサービスの署名鍵を取得したと発表し、過去1か月間に同サービスを通じて洗浄された資金の追跡を進めるとしている。
|
||||||
|
news.trial.pro.title,タンブラー裁判 {0} 日目:検察側が優勢
|
||||||
|
news.trial.def.title,タンブラー裁判 {0} 日目:弁護側が優勢
|
||||||
|
news.trial.pro.desc1,検察側はミキサーノードのサーバーログを提出し、被告の署名と1件ずつ一致すると主張した。
|
||||||
|
news.trial.pro.desc2,元パートナーが出廷し、被告は顧客の资金が闇市場由来であると知っていたと証言した。
|
||||||
|
news.trial.pro.desc3,検察側は、被告のウォレットと複数の詐欺アドレスとの間の送金記録を提示した。
|
||||||
|
news.trial.def.desc1,弁護側はノード押収時の証拠保全手続きに瑕疵があったと指摘し、一部のログが改ざんされた可能性があると主張した。
|
||||||
|
news.trial.def.desc2,弁護側の専門家が証言し、ミキサーコントラクトはオープンソースであり、被告が利用者を制御することは不可能であると述べた。
|
||||||
|
news.trial.def.desc3,検察側の重要証人が法廷で証言を覆し、被告が知っていたかどうかは覚えていないと述べた。
|
||||||
|
news.trial.convict.title,タンブラーに有罪判決
|
||||||
|
news.trial.convict.desc,裁判所はタンブラーと名乗るミキサー運営者に対し、マネーロンダリングの有罪判決を下した。警察は、該当のミキサーサービスが再開されることはないと述べている。
|
||||||
|
news.trial.acquit.title,タンブラーに無罪判決
|
||||||
|
news.trial.acquit.desc,裁判所は証拠不十分を理由に、タンブラーと名乗るミキサー運営者に無罪を言い渡し釈放した。被告は記者団の質問に答えることなく裁判所を後にした。
|
||||||
|
news.tumbler.bmrug.title,ミキサーサービスが資金を持ち逃げ
|
||||||
|
news.tumbler.bmrug.desc,闇市場に引き継がれたミキサーサービスが突如出金を停止し、コントラクト内の資金が移動された。フォーラム上では全資産を失ったと訴えるユーザーが続出している。
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,新ミキサーサービス {0} が稼働開始
|
||||||
|
news.mixer.rebrand.desc,{0} と呼ばれるミキサーサービスが先日公開され、ログなし・バックドアなしを謳っている。そのコントラクトが以前閉鎖されたサービスと酷似しているとの指摘も上がっている。
|
||||||
|
predict.q.trial,{0}:タンブラーに有罪判決
|
||||||
|
predict.clue.trial,裁判報道:検察側優勢 {0} 日、弁護側優勢 {1} 日
|
||||||
mixer.status.closed,状態:停止中
|
mixer.status.closed,状態:停止中
|
||||||
yield.sub.pools,収益プール
|
yield.sub.pools,収益プール
|
||||||
yield.sub.mine,スキーム発行
|
yield.sub.mine,スキーム発行
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,見送り
|
|||||||
otc.msg.gone,客はすでに立ち去った。
|
otc.msg.gone,客はすでに立ち去った。
|
||||||
otc.msg.cash,現金が足りない。
|
otc.msg.cash,現金が足りない。
|
||||||
otc.msg.sting,相手は潜入捜査官だった:現金{0}が没収され、盗品売買が記録された。
|
otc.msg.sting,相手は潜入捜査官だった:現金{0}が没収され、盗品売買が記録された。
|
||||||
otc.msg.bought,{0} {1}を受け取り、現金{2}を支払った。
|
otc.msg.bought,{0} {1}(うち汚染 {3})を受け取り、現金 {2} を支払った。
|
||||||
otc.msg.sold,{0} {1}を送金し、現金{2}を受け取った。
|
otc.msg.sold,{0} {1}を送金し、現金{2}を受け取った。
|
||||||
gray.sub.own,自営ミキサー
|
gray.sub.own,自営ミキサー
|
||||||
ownmix.h,自営ミキサー
|
ownmix.h,自営ミキサー
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,現金も用意できないのか?ならやめだ。
|
|||||||
otc.nowallet,ウォレットがつながっていない。コインをどこに送れと?やめだ。
|
otc.nowallet,ウォレットがつながっていない。コインをどこに送れと?やめだ。
|
||||||
otc.sting,動くな、警察だ。盗まれた資金の買い取りだな。現金は没収、記録にも残る。
|
otc.sting,動くな、警察だ。盗まれた資金の買い取りだな。現金は没収、記録にも残る。
|
||||||
hw.err.poinbase,Poinbaseは{0}を受け付けない。
|
hw.err.poinbase,Poinbaseは{0}を受け付けない。
|
||||||
|
hw.err.tainted,このウォレットの{1}のうち{0}が汚染されており、Poinbaseが受け付けるのはクリーンなコインのみ:最大 {2} {1}。
|
||||||
@@ -22,7 +22,7 @@ tab.report,Raport
|
|||||||
wallet.line,{0}: {1} (ok. {2} kredytów)
|
wallet.line,{0}: {1} (ok. {2} kredytów)
|
||||||
wallet.empty,Portfel jest pusty.
|
wallet.empty,Portfel jest pusty.
|
||||||
wallet.total,Wartość łączna: {0} kredytów
|
wallet.total,Wartość łączna: {0} kredytów
|
||||||
wallet.taint,Wartość skażona: {0} kredytów
|
wallet.taint,Skażone monety: {0} kred.
|
||||||
trade.amount,Kwota
|
trade.amount,Kwota
|
||||||
trade.deposit,Wpłata kredytów jako CRC
|
trade.deposit,Wpłata kredytów jako CRC
|
||||||
trade.withdraw,Wypłata CRC jako kredyty
|
trade.withdraw,Wypłata CRC jako kredyty
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Niewystarczające saldo.
|
|||||||
msg.trade,"Zapłacono {0} {1}, otrzymano {2} {3}."
|
msg.trade,"Zapłacono {0} {1}, otrzymano {2} {3}."
|
||||||
msg.deposit,Wpłacono {0} kredytów jako CRC.
|
msg.deposit,Wpłacono {0} kredytów jako CRC.
|
||||||
msg.cashout,Otrzymano {0} kredytów. Podatek: {1} kredytów.
|
msg.cashout,Otrzymano {0} kredytów. Podatek: {1} kredytów.
|
||||||
msg.aml_light,Kontrola zgodności: wstrzymano {0} kredytów skażonych środków.
|
|
||||||
msg.aml_heavy,Kontrola zgodności: skonfiskowano {0} kredytów skażonych środków i zgłoszono do Ochrony.
|
|
||||||
report.none,Brak raportu wydobycia.
|
report.none,Brak raportu wydobycia.
|
||||||
report.day,Noc dnia {0}
|
report.day,Noc dnia {0}
|
||||||
report.rigs,Zasilane koparki: {0} z {1}
|
report.rigs,Zasilane koparki: {0} z {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Aktywo
|
|||||||
col.amount,Kwota
|
col.amount,Kwota
|
||||||
col.value,Wartość
|
col.value,Wartość
|
||||||
col.avg,Śr. zakup
|
col.avg,Śr. zakup
|
||||||
|
col.dirty,Skażone
|
||||||
bank.cash.k,Kredyty
|
bank.cash.k,Kredyty
|
||||||
bank.rent.k,Czynsz
|
bank.rent.k,Czynsz
|
||||||
bank.rent.v,"{0}, termin: {1} d."
|
bank.rent.v,"{0}, termin: {1} d."
|
||||||
@@ -152,13 +151,12 @@ stable.ok,W parytecie
|
|||||||
stable.depeg,Utrata parytetu
|
stable.depeg,Utrata parytetu
|
||||||
stable.warn,Ostrzeżenie: niskie pokrycie rezerwy stakingu
|
stable.warn,Ostrzeżenie: niskie pokrycie rezerwy stakingu
|
||||||
stable.spiral,Zapaść
|
stable.spiral,Zapaść
|
||||||
aml.taint,Udział skażenia konta: {0}%
|
|
||||||
mixer.h,Mikser
|
mixer.h,Mikser
|
||||||
mixer.ok,Status: działa normalnie
|
mixer.ok,Status: działa normalnie
|
||||||
mixer.sanctioned,Status: objęty sankcjami (pozostałe dni: {0}). Wypłacone w tym czasie monety zostaną oznaczone.
|
mixer.sanctioned,Status: objęty sankcjami (dni: {0}). Wypłaty przypadające w tym czasie nie są czyszczone i wracają w całości skażone.
|
||||||
mixer.pending,Oczekujące wpłaty
|
mixer.pending,Oczekujące wpłaty
|
||||||
mixer.none,Brak oczekujących wpłat.
|
mixer.none,Brak oczekujących wpłat.
|
||||||
mixer.col.taint,Skażenie
|
mixer.col.taint,Skażone
|
||||||
mixer.col.ready,Gotowe
|
mixer.col.ready,Gotowe
|
||||||
mixer.day,Dzień {0}
|
mixer.day,Dzień {0}
|
||||||
mixer.deposit,Wpłata
|
mixer.deposit,Wpłata
|
||||||
@@ -169,11 +167,12 @@ mixer.go,Wpłać do miksera
|
|||||||
mixer.min,Minimalna wartość wpłaty: {0} kredytów.
|
mixer.min,Minimalna wartość wpłaty: {0} kredytów.
|
||||||
mixer.done,Wpłacono {0} {1}; zwrot w dniu {2}.
|
mixer.done,Wpłacono {0} {1}; zwrot w dniu {2}.
|
||||||
mixer.upgrade.title,Mikser
|
mixer.upgrade.title,Mikser
|
||||||
mixer.upgrade.desc,"Odblokowuje mikser w zakładce Szara sieć terminala: wpłacaj skażone monety i odbieraj je po kilku dniach z mniejszym skażeniem. Wypłata świeżo zmiksowanych monet podlega surowszej kontroli; podczas obławy mikser może zostać objęty sankcjami, a wypłacone w tym czasie monety zostaną oznaczone."
|
mixer.upgrade.desc,"Odblokowuje mikser na stronie Szara sieć w terminalu: wpłacaj skażone monety i odbieraj je kilka dni później z mniejszą liczbą skażonych. Podczas obław mikser może zostać objęty sankcjami, a wypłaty przypadające w tym czasie wracają w całości skażone."
|
||||||
news.sanction.title,Mikser wpisany na listę sankcyjną
|
news.sanction.title,Mikser wpisany na listę sankcyjną
|
||||||
news.sanction.desc,Ochrona objęła sankcjami grupę usług miksujących. Środki wypłacone z mikserów w ciągu najbliższych kilku dni będą traktowane jako podejrzane.
|
news.sanction.desc,Ochrona nałożyła sankcje na grupę mikserów. Środki wypłacone z mikserów w ciągu najbliższych kilku dni będą traktowane jako skażone środki.
|
||||||
nightlog.mixer,Mikser zwrócił {0} {1}; skażenie {2} -> {3}.
|
nightlog.mixer,Mikser zwrócił {0} {1}; skażenie {2} -> {3}.
|
||||||
nightlog.mixer_flag," (wypłacono w trakcie sankcji; adres oznaczony)"
|
nightlog.mixer_flag," (wypłacono podczas sankcji; całość oznaczona jako skażona)"
|
||||||
|
nightlog.mixer_flag.trap," (Ochrona oznacza wypłacone monety jako skażone)"
|
||||||
nightlog.mixer_rug,Operator miksera uciekł ze środkami: {0} {1} nigdy nie wróciło.
|
nightlog.mixer_rug,Operator miksera uciekł ze środkami: {0} {1} nigdy nie wróciło.
|
||||||
web3.sub.trade,Handel
|
web3.sub.trade,Handel
|
||||||
gray.sub.mixer,Mikser
|
gray.sub.mixer,Mikser
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Kontrabanda (wysoki poziom)
|
|||||||
black.kind.Tech,Zaawansowana technologia (marża)
|
black.kind.Tech,Zaawansowana technologia (marża)
|
||||||
nightlog.bm.ready,Czarny Rynek: {0} na miejscu; kurier pojawi się po otwarciu lokalu.
|
nightlog.bm.ready,Czarny Rynek: {0} na miejscu; kurier pojawi się po otwarciu lokalu.
|
||||||
guide.web3.title,Podręcznik Web3
|
guide.web3.title,Podręcznik Web3
|
||||||
guide.web3.text,"Bank i handel: strona banku jest tylko do odczytu i pokazuje gotówkę, czynsz oraz CRC na koncie Poinbase. Strona Środki w Poinbase obsługuje wpłaty i wypłaty; najpierw wybiera się monetę: CRC może iść przez konto bankowe lub portfel, pozostałe monety tylko przez portfel. Wpłata z banku zamienia kredyty na CRC na koncie Poinbase; wypłata do banku zamienia CRC z powrotem na kredyty i podlega kontroli zgodności, sprawdzającej skażenie konta Poinbase. Wypłata do portfela wymaga podania adresu odbiorcy i kilku potwierdzeń do zaksięgowania; opłata gas jest stała, na poziomie normalnym, i pobierana z wysyłanej monety. Błędny format adresu lub cyfra kontrolna powoduje odrzucenie; adres o poprawnym formacie, którego nikt nie używa, oznacza utratę wysłanych monet.¶Handel: PSC to skrót od Probably Stolen Coin, monety wydobywanej przez karty graficzne i koparki. Rynek spot Poinbase ma dwie pary, PSC/CRC i SPARK/CRC, zależnie od monety wybranej na wykresie. Zarówno zakup, jak i sprzedaż wpisuje się jako ilość monety bazowej; podgląd pokazuje zapłaconą lub otrzymaną monetę kwotowaną, średnia cena zawiera prowizję, a poślizg nie.¶Strona handlu Web3 pozwala wymienić dowolne dwie monety, zawsze przez CRC: gdy CRC jest po jednej stronie, używana jest jedna pula, w przeciwnym razie dwie, z dwiema opłatami i sumującym się poślizgiem; podgląd pokazuje otrzymaną ilość, liczbę pul i stratę. Wymiany między stablecoinami (CRT lub CRA na CRC) idą przez pule stabilne: prowizja {StableFee:%} i prawie zerowy poślizg blisko powiązania; przy utracie powiązania płynność maleje, a przy krachu zostaje wycofana i poślizg gwałtownie rośnie.§Portfele sprzętowe: monety w łańcuchu znajdują się w portfelach sprzętowych PLEDGER, a każdy z nich ma własne saldo i poziom skażenia. Portfel jest przedmiotem: przeciągnij go na terminal handlowy, aby go załadować. Otwórz go na stronie Portfele w terminalu; połącz i odłącz w prawym górnym rogu terminala. Handel na stronie Web3 oraz sklep i mikser na stronie Szara sieć korzystają z połączonego portfela; bez portfela lub bez połączenia są tylko do odczytu, a wszystkie salda wynoszą 0. Klienci płacący monetami płacą na połączony portfel.¶Płatności (sklep, mikser, kantor Ponero, opłaty za wystawienie) zaczynają się od rachunku w terminalu; wpisz adres odbiorcy w portfelu i przytrzymaj ✓, aby podpisać. Dwa ostatnie znaki adresu to suma kontrolna, więc pomyłka o jeden znak jest zwykle wychwytywana; sporadycznie zdarza się, że okazuje się poprawny i monety trafiają pod adres, z którego nikt nie korzysta. Wymiany na DEX również wymagają podpisu na portfelu.¶Poinbase to konto powiernicze; wpłaty wysyła się z portfela na adres wpłat Poinbase (tylko PSC, CRC i SPARK; regulowana giełda nie przyjmuje CRT Czarnego Rynku ani CRA Rewolucji, a portfel blokuje wysłanie ich na adres wpłat), a wypłaty zleca się na stronie Środki w Poinbase. Eksplorator na stronie Portfele pozwala sprawdzać przelewy według adresu i pokazuje wyłącznie przelewy, które faktycznie miały miejsce: każdy ruch do i z twoich portfeli (przelewy, wymiany na DEX i inne wywołania kontraktów, zyski koparek, wypłaty, monety wysyłane ci przez innych); Ponero to moneta prywatności i nigdy się nie pojawia. Więcej portfeli sprzętowych sprzedaje Dr Jackson; przeciągnij portfel na terminal handlowy, aby go dodać – maksymalnie do {WalletMax}. W sklepie dostępne są tańsze. Niepotrzebny portfel można zniszczyć na stronie Portfele; jego monety przepadają na zawsze, podobnie jak wszystko, co zostanie później wysłane na jego adres.¶Przelewy wymagają opłaty gas: wolnej, normalnej lub szybkiej, a ceny gasu rosną i spadają w cyklu około tygodnia; gdy sieć jest przeciążona, opłaty gas rosną, a powolne transakcje mogą zostać usunięte z mempoola. Przed wysłaniem sprawdź pełny adres.§Staking: CRA ulokowane w puli Rewolucji przynosi dzienny zysk według stawki dziennej, doliczany do wkładu; wypłata wymaga wcześniejszego złożenia wniosku i odczekania czterech dni, bez naliczania odsetek w okresie oczekiwania i bez możliwości wcześniejszego odbioru. CRA jest częściowo zabezpieczone: każde CRA wspierają rezerwa CRC należąca do Rewolucji oraz token równoważący SPARK; pokrycie rezerwy i stopa zabezpieczenia widnieją na stronie stakingu. Odsetki wypłacane są w nowych, niezabezpieczonych CRA, co rozwadnia pokrycie rezerwy, tym szybciej, im więcej w stakingu; przy zbyt niskim pokryciu Rewolucja obniża stawkę. Rewolucja czasem sięga po rezerwę, a wcześniej krążą pogłoski: to zapowiedź. Jeśli potem pokrycie spadnie poniżej {CraCrashRatio:%}, następuje krach: CRA staje się bezwartościowe w ciągu trzech dni, a cztery dni na odblokowanie to za wolno; powyżej tego progu jest tylko dyskonto, a środki z grabieży Górnego poziomu stopniowo odbudowują rezerwę.Line truncated
|
guide.web3.text,"Bank i handel: strona Bank jest tylko do odczytu i pokazuje gotówkę, czynsz oraz CRC na koncie Poinbase. Strona Środki w Poinbase obsługuje wpłaty i wypłaty; najpierw wybierz monetę: CRC może przejść przez konto bankowe lub portfel, każda inna moneta wyłącznie przez portfel. Wpłata z banku zamienia kredyty na CRC na koncie Poinbase; wypłata do banku zamienia CRC z powrotem na kredyty bez kontroli (konto Poinbase przechowuje wyłącznie czyste środki). Wypłata do portfela wymaga adresu odbiorcy i kilku potwierdzeń przed zaksięgowaniem; opłata gas jest stała na poziomie normalnym i pobierana z wysyłanej monety. Błędny format adresu lub sumy kontrolnej jest odrzucany; poprawnie sformatowany adres, którego nikt nie używa, oznacza utratę monet.¶Handel: PSC oznacza Probably Stolen Coin – monetę wydobywaną przez karty graficzne i koparki. Rynek spot Poinbase ma dwie pary: PSC/CRC i SPARK/CRC, zależnie od monety wybranej na wykresie. Zlecenia kupna i sprzedaży wprowadza się jako kwotę handlowanej monety; podgląd pokazuje płaconą lub otrzymywaną walutę kwotowaną, średnia cena uwzględnia prowizję, a poślizg nie.¶Strona handlu Web3 pozwala na wymianę dowolnych dwóch monet, zawsze za pośrednictwem CRC: z CRC po jednej stronie korzysta z jednej puli, w przeciwnym razie z dwóch pul, z dwiema prowizjami i sumującym się poślizgiem; podgląd pokazuje otrzymaną kwotę, przebyte pule i stratę. Wymiana stablecoinów (CRT lub CRA na CRC) korzysta ze stabilnych pul: prowizja {StableFee:%} i prawie zerowy poślizg w pobliżu parytetu; przy odkotwiczeniu płynność spada, a przy krachu zostaje wycofana i poślizg gwałtownie rośnie.§Portfele sprzętowe: monety w łańcuchu znajdują się w portfelach sprzętowych PLEDGER, z osobnymi saldami i skażonymi monetami dla każdego z nich (dla każdej monety rejestrowana jest liczba skażonych sztuk; patrz: Skażenie). Portfel jest przedmiotem: przeciągnij go na terminal handlowy, aby go załadować. Otwórz go na stronie Portfele w terminalu; łącz i rozłączaj w prawym górnym rogu terminala. Handel na stronie Web3 oraz sklep i mikser na stronie Szara sieć korzystają z połączonego portfela; bez portfela lub połączenia są one tylko do odczytu, a każde saldo wynosi 0. Klienci płacący monetami wpłacają do połączonego portfela.¶Płatności (sklep, mikser, punkt Ponero, opłaty za wystawienie) zaczynają się od rachunku w terminalu; wpisz adres odbiorcy na portfelu i przytrzymaj ✓, aby podpisać. Ostatnie dwa znaki adresu to suma kontrolna, więc literówka o jeden znak jest zwykle wychwytywana; sporadycznie okazuje się poprawna i monety trafiają pod adres, którego nikt nie używa. Wymiany na DEX również wymagają podpisu na portfelu.¶Poinbase to konto powiernicze; wpłaty wysyła się z portfela na adres depozytowy Poinbase (tylko PSC, CRC i SPARK; giełda zgodna z przepisami nie przyjmuje ani CRT z Czarnego Rynku, ani CRA od Rewolucji, a portfel blokuje ich wysłanie na adres depozytowy; wpłacać można tylko czyste monety, patrz: Skażenie), a wypłaty zleca się na stronie Środki w Poinbase. Eksplorator na stronie Portfele wyszukuje transfery według adresu i pokazuje tylko transakcje, które rzeczywiście miały miejsce: każdy przepływ do i z Twoich portfeli (przelewy, wymiany DEX i inne wywołania kontraktów, wypłaty z koparek, wypłaty, monety przesłane przez innych); Ponero to moneta prywatności i nigdy się nie wyświetla. Więcej portfeli sprzętowych sprzedaje Dr Jackson; przeciągnij taki na terminal handlowy, aby go dodać, maksymalnie do {WalletMax}. W sklepie dostępne są tańsze. Niepotrzebny portfel można zniszczyć na stronie Portfele; znajdujące się w nim monety przepadają na zawsze, a wszystko wysłane później na jego adres również zostanie utracone.¶Za przelewy płaci się opłatę gas: wolną, normalną lub szybką, a ceny gasu rosną i spadają w cyklu około tygodniowym; gdy sieć jest przeciążona, opłaty gas rosną, a wolne transakcje mogą zostać usunięte z mempoola. Przed wysłaniem sprawdź pełny adres.§Staking: CRA ulokowane w puli Rewolucji przynosi dzienny zysk według stawki dziennej, doliczany do wkładu; wypłata wymaga wcześniejszego złożenia wniosku i odczekania czterech dni, bez naliczania odsetek w okresie oczekiwania i bez możliwości wcześniejszego odbioru. CRA jest częściowo zabezpieczone: każde CRA wspierają rezerwa CRC należąca do Rewolucji oraz token równoważący SPARK; pokrycie rezerwy i stopa zabezpieczenia widnieją na stronie stakingu. Odsetki wypłacane są w nowych, niezabezpieczonych CRA, co rozwadnia pokrycie rezerwy, tym szybciej, im więcej w stakingu; przy zbyt niskim pokryciu Rewolucja obniża stawkę. Rewolucja czasem sięga po rezerwę, a wcześniej krążą pogłoski: to zapowiedź. Jeśli potem pokrycie spadnie poniżej {CraCrashRatio:%}, następuje krach: CRA staje się bezwartościowe w ciLine truncated
|
||||||
courier.odd1,...Paczka dotarła.
|
courier.odd1,...Paczka dotarła.
|
||||||
courier.odd2,(Trzyma rękę w kieszeni.) Podpisz tutaj.
|
courier.odd2,(Trzyma rękę w kieszeni.) Podpisz tutaj.
|
||||||
courier.sign,Podpisz
|
courier.sign,Podpisz
|
||||||
@@ -361,6 +360,7 @@ hw.wallet.n,Portfel {0}
|
|||||||
hw.review.own,Własny portfel: {0}
|
hw.review.own,Własny portfel: {0}
|
||||||
hw.review.poinbase,Adres wpłaty Poinbase
|
hw.review.poinbase,Adres wpłaty Poinbase
|
||||||
poin.deposit,Adres wpłaty: {0}
|
poin.deposit,Adres wpłaty: {0}
|
||||||
|
poin.deposit.clean,Czyste monety do wpłaty ({0}): {1}
|
||||||
wallets.count,Portfele {0}/{1}
|
wallets.count,Portfele {0}/{1}
|
||||||
wallets.col.name,Nazwa
|
wallets.col.name,Nazwa
|
||||||
wallets.col.addr,Adres
|
wallets.col.addr,Adres
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Wklej
|
|||||||
hw.copied,Skopiowano adres.
|
hw.copied,Skopiowano adres.
|
||||||
hw.copied.addr,Skopiowano {0}
|
hw.copied.addr,Skopiowano {0}
|
||||||
hw.balance.frozen," (zamrożone {0})"
|
hw.balance.frozen," (zamrożone {0})"
|
||||||
|
hw.balance.dirty," (skażone: {0})"
|
||||||
wallets.destroy,Zniszcz
|
wallets.destroy,Zniszcz
|
||||||
wallets.destroy.sure,Potwierdź
|
wallets.destroy.sure,Potwierdź
|
||||||
wallets.destroyed,Zniszczono {0}: {1}
|
wallets.destroyed,Zniszczono {0}: {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Woda z Górnego poziomu
|
|||||||
nightlog.predict.win,"Trafna predykcja: „{0}”, wypłacono {1}."
|
nightlog.predict.win,"Trafna predykcja: „{0}”, wypłacono {1}."
|
||||||
nightlog.predict.lose,"Błędna predykcja: „{0}”, utracono stawkę {1}."
|
nightlog.predict.lose,"Błędna predykcja: „{0}”, utracono stawkę {1}."
|
||||||
nightlog.predict.void,"Predykcja unieważniona: „{0}”, zwrócono stawkę {1}."
|
nightlog.predict.void,"Predykcja unieważniona: „{0}”, zwrócono stawkę {1}."
|
||||||
nightlog.predict.insider,"""{0}"" rozliczono na {1}. Policja podejrzewa transakcje poufne; wypłata została oznaczona, a skażenie portfela wzrasta o {2}."
|
nightlog.predict.insider,"""{0}"" rozliczono na {1}. Policja podejrzewa transakcje poufne; {2} CRC z tego oznaczono jako skażone."
|
||||||
predict.tab.markets,Rynki
|
predict.tab.markets,Rynki
|
||||||
predict.tab.intel,Informacje
|
predict.tab.intel,Informacje
|
||||||
predict.acct.crt,{0}: CRT {1}
|
predict.acct.crt,{0}: CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}: operacja zaplanowana
|
|||||||
predict.brief.none,{0}: brak operacji do rozpoczęcia
|
predict.brief.none,{0}: brak operacji do rozpoczęcia
|
||||||
predict.brief.can,{0}: można rozpocząć {1}
|
predict.brief.can,{0}: można rozpocząć {1}
|
||||||
predict.clue.push,Przesunięcie ceny o {0}%: wysokie ryzyko
|
predict.clue.push,Przesunięcie ceny o {0}%: wysokie ryzyko
|
||||||
nightlog.predict.manip,"""{0}"" rozliczono na {1}. Regulatorzy podejrzewają manipulację rynkową; wypłata została oznaczona, a skażenie portfela wzrasta o {2}."
|
nightlog.predict.manip,"""{0}"" rozliczono na {1}. Organy nadzorcze podejrzewają manipulację ceną; {2} CRC z tego oznaczono jako skażone."
|
||||||
news.manip.title,Giełda bada nietypowe transakcje
|
news.manip.title,Giełda bada nietypowe transakcje
|
||||||
news.manip.desc,"Regulatorzy donoszą, że ktoś wpłynął na cenę dużymi zleceniami spot, czerpiąc zyski z instrumentów pochodnych i rynków predykcyjnych; powiązane konta zostały oznaczone."
|
news.manip.desc,"Regulatorzy donoszą, że ktoś wpłynął na cenę dużymi zleceniami spot, czerpiąc zyski z instrumentów pochodnych i rynków predykcyjnych; powiązane konta zostały oznaczone."
|
||||||
taint.overflow,Skażenie przekracza obecnie wartość portfela; nadwyżka {0} zostaje odnotowana jako oszustwo.
|
perp.manip,Zamknięto z zyskiem {0}. Organy nadzorcze podejrzewają manipulację rynkową; do twojej kartoteki trafia oszustwo: {1}.
|
||||||
perp.manip,"Zamknięto z zyskiem: {0}. Regulatorzy podejrzewają manipulację rynkową; zysk został oznaczony, a skażenie konta Poinbase wzrasta o {1}."
|
|
||||||
web3.sub.ponzi,Lokaty
|
web3.sub.ponzi,Lokaty
|
||||||
ponzi.h,Piramida finansowa
|
ponzi.h,Piramida finansowa
|
||||||
ponzi.acct,Portfel emitenta {0}: CRC {1}
|
ponzi.acct,Portfel emitenta {0}: CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Wsparcie Poinbase
|
|||||||
scam.support.1,"Dzień dobry, tutaj wsparcie Poinbase. Wykryliśmy nietypowe logowanie na twoim koncie i zostało ono oznaczone."
|
scam.support.1,"Dzień dobry, tutaj wsparcie Poinbase. Wykryliśmy nietypowe logowanie na twoim koncie i zostało ono oznaczone."
|
||||||
scam.support.2,Prześlij dzisiaj {0} CRC na bezpieczny adres {1} w celu weryfikacji; zostaną zwrócone zaraz potem.
|
scam.support.2,Prześlij dzisiaj {0} CRC na bezpieczny adres {1} w celu weryfikacji; zostaną zwrócone zaraz potem.
|
||||||
scam.support.3,"W przeciwnym razie konto zostanie trwale zamrożone. Muszę lecieć, pamiętaj o przelewie."
|
scam.support.3,"W przeciwnym razie konto zostanie trwale zamrożone. Muszę lecieć, pamiętaj o przelewie."
|
||||||
predict.sold.caught,"Sprzedano, otrzymano {0}. Policja podejrzewa transakcje poufne; uzyskane środki zostały oznaczone, a skażenie portfela wzrasta o {1}."
|
predict.sold.caught,"Sprzedano, otrzymano {0}. Policja podejrzewa transakcje poufne; {1} CRC z tego oznaczono jako skażone."
|
||||||
predict.row.move," (ubiegłej nocy {0} {1})"
|
predict.row.move," (ubiegłej nocy {0} {1})"
|
||||||
predict.stats.h,Historia (śr. cena otwarcia / wskaźnik rzeczywisty)
|
predict.stats.h,Historia (śr. cena otwarcia / wskaźnik rzeczywisty)
|
||||||
predict.stats.row,"{0}: rynki: {1}, śr. otwarcie {2}, wystąpienie: {3}%"
|
predict.stats.row,"{0}: rynki: {1}, śr. otwarcie {2}, wystąpienie: {3}%"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,Cena PSC
|
|||||||
predict.kind.Gas,Gas
|
predict.kind.Gas,Gas
|
||||||
predict.kind.Cra,Ostrzeżenie CRA
|
predict.kind.Cra,Ostrzeżenie CRA
|
||||||
predict.kind.Era,Era koparek
|
predict.kind.Era,Era koparek
|
||||||
|
predict.kind.Trial,Proces Tumblera
|
||||||
nightlog.predict.move,Predykcja „{0}”: zmiana {1} -> {2}
|
nightlog.predict.move,Predykcja „{0}”: zmiana {1} -> {2}
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,Wykres dzienny {0}: brak historii; zapis od dzisiaj.
|
chart.empty,Wykres dzienny {0}: brak historii; zapis od dzisiaj.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"Rewolucja rzekomo zdobyła dowody korupcji wewnątr
|
|||||||
news.story.serpico_bm.title,Czarny Rynek zawiera ciche porozumienie
|
news.story.serpico_bm.title,Czarny Rynek zawiera ciche porozumienie
|
||||||
news.story.serpico_bm.desc,"Wewnętrzny dokument Ochrony zmienił właściciela na Czarnym Rynku. Od tamtej pory rozliczenia w Darknecie są zauważalnie stabilniejsze, a realizacja CRT ani razu nie zawiodła."
|
news.story.serpico_bm.desc,"Wewnętrzny dokument Ochrony zmienił właściciela na Czarnym Rynku. Od tamtej pory rozliczenia w Darknecie są zauważalnie stabilniejsze, a realizacja CRT ani razu nie zawiodła."
|
||||||
news.story.serpico_sec.title,Ochrona rozpoczyna wewnętrzną czystkę
|
news.story.serpico_sec.title,Ochrona rozpoczyna wewnętrzną czystkę
|
||||||
news.story.serpico_sec.desc,"Ochrona zapowiedziała pełne śledztwo w sprawie wewnętrznej korupcji i zaostrzenie monitorowania przepływów finansowych. Poinbase zaostrza kontrolę wypłat, a miksery zostały wymienione z nazwy."
|
news.story.serpico_sec.desc,Ochrona ogłosiła pełne śledztwo w sprawie wewnętrznej korupcji oraz ściślejsze monitorowanie przepływów finansowych; wymieniono usługi mikserów.
|
||||||
news.story.eleanor_leak.title,Wyciek danych o hodowli nutriowoców
|
news.story.eleanor_leak.title,Wyciek danych o hodowli nutriowoców
|
||||||
news.story.eleanor_leak.desc,"Gazeta z Dolnego poziomu opublikowała badania pozwalające nutriowocom na ponowne wytwarzanie nasion; akcje Pastelle runęły. Bank powierniczy przechowujący fundusze Górnego poziomu zgłasza złe długi, a Rewolucja rośnie w siłę."
|
news.story.eleanor_leak.desc,"Gazeta z Dolnego poziomu opublikowała badania pozwalające nutriowocom na ponowne wytwarzanie nasion; akcje Pastelle runęły. Bank powierniczy przechowujący fundusze Górnego poziomu zgłasza złe długi, a Rewolucja rośnie w siłę."
|
||||||
news.story.eleanor_return.title,Pastelle odzyskuje skradzione dane
|
news.story.eleanor_return.title,Pastelle odzyskuje skradzione dane
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,"Operator miksera znany jako Tumbler został aresztowan
|
|||||||
news.tumbler.sold.title,Usługa miksera zmienia właściciela
|
news.tumbler.sold.title,Usługa miksera zmienia właściciela
|
||||||
news.tumbler.sold.desc,"Krążą słuchy, że klucze do podpisywania usługi miksera z Dolnego poziomu trafiły w ręce Czarnego Rynku, a opłaty natychmiast wzrosły. Użytkownicy obawiają się o swoje środki."
|
news.tumbler.sold.desc,"Krążą słuchy, że klucze do podpisywania usługi miksera z Dolnego poziomu trafiły w ręce Czarnego Rynku, a opłaty natychmiast wzrosły. Użytkownicy obawiają się o swoje środki."
|
||||||
nightlog.tumbler.gift,Tumbler odebrał dysk z kluczem i w podziękowaniu zostawił {0} CRT (wysłano na {1}); opłaty miksera zmniejszono o połowę.
|
nightlog.tumbler.gift,Tumbler odebrał dysk z kluczem i w podziękowaniu zostawił {0} CRT (wysłano na {1}); opłaty miksera zmniejszono o połowę.
|
||||||
|
agent.name,Agent Bezpieczeństwa
|
||||||
|
agent.v1.1,"Ochrona. Przepraszam, że przeszkadzam."
|
||||||
|
agent.v1.2,Szukamy kogoś posługującego się pseudonimem Tumbler. Prowadzi usługę miksowania na łańcuchu.
|
||||||
|
agent.v1.3,Był widziany w tej okolicy.
|
||||||
|
agent.ask,Był u ciebie w sklepie?
|
||||||
|
agent.choice.yes,[Powiedz: kilka razy]
|
||||||
|
agent.choice.no,[Powiedz: nigdy go nie widziałem]
|
||||||
|
agent.yes1,Dziękuję za współpracę. Ochrona to zapamięta.
|
||||||
|
agent.no1,"Tak? Jeśli coś ci się przypomni, wiesz, gdzie nas znaleźć."
|
||||||
|
agent.search.1,"Znowu się spotykamy. Słyszeliśmy, że przechowujesz coś dla tego człowieka."
|
||||||
|
agent.search.2,Rutynowe przeszukanie. Proszę o współpracę.
|
||||||
|
agent.search.found,Mamy to. Zabieramy to.
|
||||||
|
agent.search.none,...Nic. Przepraszam za kłopot.
|
||||||
|
tumbler.v4.seized.1,"Słyszałem, że Ochrona przeszukała twój sklep."
|
||||||
|
tumbler.v4.seized.2,Mają teraz klucz. Wyciągną rejestry każdego użytkownika.
|
||||||
|
tumbler.v4.seized.3,"Cokolwiek im powiedziałeś, nie chcę już wiedzieć."
|
||||||
|
nightlog.tumbler.leak,Ochrona użyła klucza podpisu Tumblera do odtworzenia historii miksowania: w ramach wypłat ({0}) usunięto {1} skażenia; do twojej kartoteki trafia oszustwo: {2}.
|
||||||
|
nightlog.tumbler.leak.none,Ochrona użyła klucza podpisu Tumblera do odtworzenia rejestrów miksowania. Ostatnio nie wypłacono niczego z miksera.
|
||||||
|
nightlog.tumbler.note,"Pod drzwi wsunięto liścik: ""Jesteś mi coś winien i odbiorę to. —T"""
|
||||||
|
nightlog.tumbler.tip,Wiadomość od Tumblera: Ochrona może jutro wziąć na cel usługi mikserów.
|
||||||
|
news.tumbler.leak.title,Ochrona odtwarza rejestry miksera
|
||||||
|
news.tumbler.leak.desc,"Ochrona podaje, że zdobyła klucz podpisu usługi miksera i użyje go do namierzenia środków wypranych za jej pośrednictwem w minionym miesiącu."
|
||||||
|
news.trial.pro.title,"Proces Tumblera, dzień {0}: oskarżenie zyskuje przewagę"
|
||||||
|
news.trial.def.title,"Proces Tumblera, dzień {0}: obrona zyskuje przewagę"
|
||||||
|
news.trial.pro.desc1,"Oskarżenie przedstawiło logi serwera z węzła miksera, twierdząc, że pokrywają się one jeden do jednego z podpisami oskarżonego."
|
||||||
|
news.trial.pro.desc2,"Były wspólnik zeznał, że oskarżony wiedział o pochodzeniu środków klientów z Czarnego Rynku."
|
||||||
|
news.trial.pro.desc3,Oskarżenie ujawniło transfery między portfelem oskarżonego a kilkoma adresami powiązanymi z oszustwami.
|
||||||
|
news.trial.def.desc1,"Obrona wytknęła uchybienia w procedurze zabezpieczania dowodów podczas zajęcia węzła, twierdząc, że część logów mogła zostać zmodyfikowana."
|
||||||
|
news.trial.def.desc2,"Biegły powołany przez obronę zeznał, że kontrakt miksera jest kodem open source, a oskarżony nie ma wpływu na to, kto go używa."
|
||||||
|
news.trial.def.desc3,"Kluczowy świadek oskarżenia zmienił zeznania na sali sądowej, twierdząc, że nie pamięta, czy oskarżony miał tego świadomość."
|
||||||
|
news.trial.convict.title,Tumbler uznany za winnego
|
||||||
|
news.trial.convict.desc,"Sąd uznał operatora miksera znanego jako Tumbler za winnego prania brudnych pieniędzy. Ochrona informuje, że usługa miksera nie zostanie wznowiona."
|
||||||
|
news.trial.acquit.title,Tumbler uniewinniony
|
||||||
|
news.trial.acquit.desc,"Powołując się na brak wystarczających dowodów, sąd uniewinnił operatora miksera znanego jako Tumbler i nakazał jego zwolnienie. Opuścił gmach sądu bez odpowiedzi na pytania dziennikarzy."
|
||||||
|
news.tumbler.bmrug.title,Usługa miksera znika ze środkami
|
||||||
|
news.tumbler.bmrug.desc,"Usługa miksera przejęta przez Czarny Rynek niespodziewanie wstrzymała wypłaty, a środki z jej kontraktu zostały wyprowadzone. Użytkownicy na forach donoszą o utracie całego majątku."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,Nowa usługa miksera {0} trafia do sieci
|
||||||
|
news.mixer.rebrand.desc,"Usługa miksera o nazwie {0} ruszyła niedawno w sieci, deklarując brak logów i backdoorów. Niektórzy zauważyli jednak, że jej kontrakt łudząco przypomina wcześniej zamkniętą usługę."
|
||||||
|
predict.q.trial,{0}: Tumbler uznany za winnego
|
||||||
|
predict.clue.trial,"Relacje z procesu: przewaga oskarżenia (dni: {0}), przewaga obrony (dni: {1})"
|
||||||
mixer.status.closed,Status: wyłączony
|
mixer.status.closed,Status: wyłączony
|
||||||
yield.sub.pools,Pule zysku
|
yield.sub.pools,Pule zysku
|
||||||
yield.sub.mine,Emisja piramidy
|
yield.sub.mine,Emisja piramidy
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Pas
|
|||||||
otc.msg.gone,Klient odszedł.
|
otc.msg.gone,Klient odszedł.
|
||||||
otc.msg.cash,Za mało gotówki.
|
otc.msg.cash,Za mało gotówki.
|
||||||
otc.msg.sting,"Klient był tajniakiem: skonfiskowano {0} w gotówce, odnotowano paserstwo."
|
otc.msg.sting,"Klient był tajniakiem: skonfiskowano {0} w gotówce, odnotowano paserstwo."
|
||||||
otc.msg.bought,"Otrzymano {0} {1}, zapłacono {2} w gotówce."
|
otc.msg.bought,"Otrzymano {0} {1} (w tym skażone: {3}), zapłacono gotówką: {2}."
|
||||||
otc.msg.sold,"Wysłano {0} {1}, otrzymano {2} w gotówce."
|
otc.msg.sold,"Wysłano {0} {1}, otrzymano {2} w gotówce."
|
||||||
gray.sub.own,Mój mikser
|
gray.sub.own,Mój mikser
|
||||||
ownmix.h,Mój mikser
|
ownmix.h,Mój mikser
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,Nie masz nawet gotówki? Daj spokój.
|
|||||||
otc.nowallet,"Brak podłączonego portfela, gdzie mam wysłać monety? Daj spokój."
|
otc.nowallet,"Brak podłączonego portfela, gdzie mam wysłać monety? Daj spokój."
|
||||||
otc.sting,"Nie ruszaj się. Ochrona. Skup kradzionych środków: gotówka zostaje skonfiskowana, a to trafi do twoich akt."
|
otc.sting,"Nie ruszaj się. Ochrona. Skup kradzionych środków: gotówka zostaje skonfiskowana, a to trafi do twoich akt."
|
||||||
hw.err.poinbase,Poinbase nie przyjmuje {0}.
|
hw.err.poinbase,Poinbase nie przyjmuje {0}.
|
||||||
|
hw.err.tainted,W tym portfelu skażone {1}: {0}. Poinbase przyjmuje tylko czyste monety: maksymalnie {2} {1}.
|
||||||
@@ -22,7 +22,7 @@ tab.report,Отчёт
|
|||||||
wallet.line,{0}: {1} (около {2} кредитов)
|
wallet.line,{0}: {1} (около {2} кредитов)
|
||||||
wallet.empty,Кошелёк пуст.
|
wallet.empty,Кошелёк пуст.
|
||||||
wallet.total,Общая стоимость: {0} кредитов
|
wallet.total,Общая стоимость: {0} кредитов
|
||||||
wallet.taint,«Грязные» средства: {0} кредитов
|
wallet.taint,Грязные монеты (кредиты): {0}
|
||||||
trade.amount,Сумма
|
trade.amount,Сумма
|
||||||
trade.deposit,Депозит кредитов в CRC
|
trade.deposit,Депозит кредитов в CRC
|
||||||
trade.withdraw,Вывод CRC в кредиты
|
trade.withdraw,Вывод CRC в кредиты
|
||||||
@@ -38,8 +38,6 @@ msg.balance,Недостаточно средств.
|
|||||||
msg.trade,"Оплачено {0} {1}, получено {2} {3}."
|
msg.trade,"Оплачено {0} {1}, получено {2} {3}."
|
||||||
msg.deposit,Внесено {0} кредитов в CRC.
|
msg.deposit,Внесено {0} кредитов в CRC.
|
||||||
msg.cashout,Получено {0} кредитов. Налог {1} кредитов.
|
msg.cashout,Получено {0} кредитов. Налог {1} кредитов.
|
||||||
msg.aml_light,Проверка соответствия: удержаны «грязные» средства на сумму {0} кредитов.
|
|
||||||
msg.aml_heavy,"Проверка соответствия: изъяты «грязные» средства на сумму {0} кредитов, направлен отчёт в Службу безопасности."
|
|
||||||
report.none,Отчётов о майнинге пока нет.
|
report.none,Отчётов о майнинге пока нет.
|
||||||
report.day,Ночь дня {0}
|
report.day,Ночь дня {0}
|
||||||
report.rigs,Фермы с питанием: {0} из {1}
|
report.rigs,Фермы с питанием: {0} из {1}
|
||||||
@@ -141,6 +139,7 @@ col.asset,Актив
|
|||||||
col.amount,Количество
|
col.amount,Количество
|
||||||
col.value,Оценка
|
col.value,Оценка
|
||||||
col.avg,Ср. покупка
|
col.avg,Ср. покупка
|
||||||
|
col.dirty,Грязные
|
||||||
bank.cash.k,Кредиты
|
bank.cash.k,Кредиты
|
||||||
bank.rent.k,Аренда
|
bank.rent.k,Аренда
|
||||||
bank.rent.v,"{0}, оплата через {1} дн."
|
bank.rent.v,"{0}, оплата через {1} дн."
|
||||||
@@ -152,13 +151,12 @@ stable.ok,Привязан
|
|||||||
stable.depeg,Отвязан
|
stable.depeg,Отвязан
|
||||||
stable.warn,Внимание: покрытие резерва стейкинга на исходе
|
stable.warn,Внимание: покрытие резерва стейкинга на исходе
|
||||||
stable.spiral,Крах
|
stable.spiral,Крах
|
||||||
aml.taint,Доля загрязнения счёта: {0}%
|
|
||||||
mixer.h,Миксер
|
mixer.h,Миксер
|
||||||
mixer.ok,Статус: работает нормально
|
mixer.ok,Статус: работает нормально
|
||||||
mixer.sanctioned,Статус: под санкциями (дней до снятия: {0}). Выведенные в этот период монеты помечаются.
|
mixer.sanctioned,"Статус: под санкциями (ещё {0} дн.). Выплаты, приходящиеся на этот период, не очищаются и возвращаются полностью «грязными»."
|
||||||
mixer.pending,Депозиты в обработке
|
mixer.pending,Депозиты в обработке
|
||||||
mixer.none,Нет депозитов в обработке.
|
mixer.none,Нет депозитов в обработке.
|
||||||
mixer.col.taint,Загрязнение
|
mixer.col.taint,Грязные
|
||||||
mixer.col.ready,Готовность
|
mixer.col.ready,Готовность
|
||||||
mixer.day,День {0}
|
mixer.day,День {0}
|
||||||
mixer.deposit,Депозит
|
mixer.deposit,Депозит
|
||||||
@@ -169,11 +167,12 @@ mixer.go,Депозит в миксер
|
|||||||
mixer.min,Депозит должен составлять не менее {0} кредитов.
|
mixer.min,Депозит должен составлять не менее {0} кредитов.
|
||||||
mixer.done,Внесено {0} {1}; возврат в день {2}.
|
mixer.done,Внесено {0} {1}; возврат в день {2}.
|
||||||
mixer.upgrade.title,Миксер
|
mixer.upgrade.title,Миксер
|
||||||
mixer.upgrade.desc,"Разблокирует миксер на странице «Серая сеть» в терминале: вносите «грязные» монеты и забирайте их через несколько дней с меньшим загрязнением. Вывод недавно смешанных монет проверяется строже; во время зачисток миксер может попасть под санкции, а выведенные в этот период монеты помечаются."
|
mixer.upgrade.desc,"Разблокирует миксер на странице терминала «Серая сеть»: внесите «грязные» монеты и заберите их через несколько дней — «грязных» станет меньше. Во время зачисток миксер может попасть под санкции, а выплаты, приходящиеся на этот период, возвращаются полностью «грязными»."
|
||||||
news.sanction.title,Миксер внесён в санкционный список
|
news.sanction.title,Миксер внесён в санкционный список
|
||||||
news.sanction.desc,"Служба безопасности ввела санкции против ряда миксер-сервисов. Средства, выведенные из миксеров в ближайшие дни, будут считаться подозрительными."
|
news.sanction.desc,"Служба безопасности ввела санкции против ряда сервисов микширования. Средства, выведенные из миксеров в ближайшие дни, будут считаться «грязными» средствами."
|
||||||
nightlog.mixer,Миксер вернул {0} {1}; загрязнение: {2} -> {3}.
|
nightlog.mixer,Миксер вернул {0} {1}; загрязнение: {2} -> {3}.
|
||||||
nightlog.mixer_flag," (выведено во время санкций; адрес помечен)"
|
nightlog.mixer_flag," (выведено во время санкций; всё помечено как «грязное»)"
|
||||||
|
nightlog.mixer_flag.trap," (Служба безопасности помечает выведенные монеты как «грязные»)"
|
||||||
nightlog.mixer_rug,Оператор миксера сбежал с деньгами: {0} {1} не вернулись.
|
nightlog.mixer_rug,Оператор миксера сбежал с деньгами: {0} {1} не вернулись.
|
||||||
web3.sub.trade,Торговля
|
web3.sub.trade,Торговля
|
||||||
gray.sub.mixer,Миксер
|
gray.sub.mixer,Миксер
|
||||||
@@ -248,7 +247,7 @@ black.kind.Contraband.3,Контрабанда (высок.)
|
|||||||
black.kind.Tech,Высокие технологии (наценка)
|
black.kind.Tech,Высокие технологии (наценка)
|
||||||
nightlog.bm.ready,Чёрный рынок: доставлен товар «{0}»; курьер заглянет после открытия.
|
nightlog.bm.ready,Чёрный рынок: доставлен товар «{0}»; курьер заглянет после открытия.
|
||||||
guide.web3.title,Руководство по Web3
|
guide.web3.title,Руководство по Web3
|
||||||
guide.web3.text,"Банк и торговля: страница банка только для чтения и показывает наличные, аренду и CRC на счёте Poinbase. Страница «Средства» в Poinbase отвечает за ввод и вывод; сначала выбирается монета: CRC можно вводить и выводить через банковский счёт или кошелёк, остальные монеты только через кошелёк. Депозит из банка конвертирует кредиты в CRC на счёте Poinbase; вывод в банк меняет CRC обратно на кредиты и проходит проверку соответствия, оценивающую загрязнение счёта Poinbase. Вывод на кошелёк требует адрес получателя и нескольких подтверждений до зачисления; комиссия за газ фиксирована на обычном уровне и списывается с отправляемой монеты. Неверный формат адреса или контрольная сумма приводят к отказу; адрес с верным форматом, которым никто не пользуется, означает потерю отправленных монет.¶Торговля: PSC означает Probably Stolen Coin — это монета, которую добывают видеокарты и асик-майнеры. На спотовом рынке Poinbase две пары, PSC/CRC и SPARK/CRC, по монете, выбранной на графике. И покупка, и продажа вводятся как количество торгуемой монеты; в предпросмотре видно, сколько котируемой монеты уйдёт или придёт, средняя цена включает комиссию, проскальзывание — нет.¶На торговой странице Web3 можно обменять любые две монеты, всегда через CRC: если CRC с одной стороны, используется один пул, иначе два пула, две комиссии и суммирующееся проскальзывание; предпросмотр показывает получаемое количество, число пулов и потери. Обмен стейблкоинов (CRT или CRA на CRC) идёт через стабильные пулы: комиссия {StableFee:%} и почти нулевое проскальзывание возле привязки; при отвязке ликвидность редеет, при обвале её выводят, и проскальзывание резко растёт.§Аппаратные кошельки: ончейн-монеты хранятся на аппаратных кошельках PLEDGER, баланс и загрязнение у каждого свои. Кошелёк — это предмет: перетащите его на торговый терминал, чтобы загрузить. Открывайте его на странице «Кошельки» терминала; подключайте и отключайте в правом верхнем углу терминала. Торговля на странице Web3, магазин и миксер на странице «Серая сеть» используют подключённый кошелёк; без кошелька или без подключения они доступны только для просмотра, а все балансы равны 0. Покупатели, платящие монетами, платят на подключённый кошелёк.¶Платежи (магазин, миксер, пункт обмена Ponero, комиссия за размещение) начинаются со счёта на терминале; введите адрес получателя на кошельке и удерживайте ✓, чтобы подписать. Последние два символа адреса — контрольная сумма, поэтому опечатка в один символ обычно отсекается; изредка адрес случайно оказывается валидным, и монеты уходят на адрес, которым никто не пользуется. Для обмена на DEX также требуется подпись на кошельке.¶Poinbase — кастодиальный аккаунт; депозит отправляется с кошелька на адрес депозита Poinbase (только PSC, CRC и SPARK; регулируемая биржа не принимает ни CRT чёрного рынLine truncated
|
guide.web3.text,"Банк и торговля: страница «Банк» доступна только для чтения и отображает наличные, аренду и CRC на счёте Poinbase. Страница Poinbase «Средства» управляет депозитом и выводом; сначала выберите монету: CRC можно переводить через банковский счёт или кошелёк, все остальные монеты — только через кошелёк. Депозит с банковского счёта конвертирует кредиты в CRC на счёте Poinbase; вывод на банковский счёт конвертирует CRC обратно в кредиты без проверки (на счёте Poinbase хранятся исключительно чистые деньги). Для вывода на кошелёк требуется адрес получателя и несколько подтверждений сети; комиссия за газ фиксирована по обычному тарифу и списывается из отправляемой монеты. Неверный формат адреса или контрольная сумма отклоняются; если адрес отформатирован верно, но никем не используется, монеты будут потеряны навсегда.¶Торговля: PSC расшифровывается как Probably Stolen Coin — это монета, добываемая видеокартами и асик-майнерами. На спотовом рынке Poinbase есть две пары: PSC/CRC и SPARK/CRC, переключающиеся вслед за монетой, выбранной на графике. Покупка и продажа задаются как количество торгуемой монеты; в предпросмотре отображается отдаваемая или получаемая котируемая монета, средняя цена включает комиссию, а проскальзывание — нет.¶Страница торговли Web3 позволяет обменивать любые две монеты, всегда через CRC: если CRC находится на одной из сторон, используется один пул, иначе — два пула с двумя комиссиями и суммирующимся проскальзыванием; в предпросмотре отображаются полученная сумма, пройденные пулы и потери. Обмен стейблкоинов (CRT или CRA к CRC) использует стабильные пулы: комиссия {StableFee:%} и почти нулевое проскальзывание вблизи привязки; при потере привязки ликвидность падает, а при крахе она полностью изымается, и проскальзывание резко возрастает.§Аппаратные кошельки: монеты в блокчейне хранятся на аппаратных кошельках PLEDGER, на каждом из которых ведутся свои балансы и учёт «грязных» монет (для каждой монеты отслеживается, сколько из них «грязные»; см. «Загрязнение»). Кошелёк — это предмет: перетащите его на торговый терминал, чтобы загрузить. Открывайте его на странице терминала «Кошельки»; подключение и отключение выполняются в правом верхнем углу терминала. Торговля на странице Web3, а также магазин и миксер на странице «Серая сеть» используют подключённый кошелёк; без кошелька или подключения они доступны только для просмотра, и все балансы показывают 0. Покупатели, расплачивающиеся монетами, переводят оплату на подключённый кошелёк.¶Платежи (магазин, миксер, стойка Ponero, плата за листинг) начинаются со счёта на терминале; введите адрес получателя на кошельке и удерживайте ✓, чтобы подписать. Последние два символа адреса — контрольная сумма, поэтому опечатка в один символ обычно отслеживается; изредка адрес случайно оказLine truncated
|
||||||
courier.odd1,...Посылка пришла.
|
courier.odd1,...Посылка пришла.
|
||||||
courier.odd2,(Его рука остаётся в кармане.) Подпиши здесь.
|
courier.odd2,(Его рука остаётся в кармане.) Подпиши здесь.
|
||||||
courier.sign,Подписать
|
courier.sign,Подписать
|
||||||
@@ -361,6 +360,7 @@ hw.wallet.n,Кошелёк {0}
|
|||||||
hw.review.own,Свой кошелёк: {0}
|
hw.review.own,Свой кошелёк: {0}
|
||||||
hw.review.poinbase,Адрес депозита Poinbase
|
hw.review.poinbase,Адрес депозита Poinbase
|
||||||
poin.deposit,Адрес депозита: {0}
|
poin.deposit,Адрес депозита: {0}
|
||||||
|
poin.deposit.clean,Чистые монеты {0} для депозита: {1}
|
||||||
wallets.count,Кошельки {0}/{1}
|
wallets.count,Кошельки {0}/{1}
|
||||||
wallets.col.name,Название
|
wallets.col.name,Название
|
||||||
wallets.col.addr,Адрес
|
wallets.col.addr,Адрес
|
||||||
@@ -378,6 +378,7 @@ hw.paste,Вставить
|
|||||||
hw.copied,Адрес скопирован.
|
hw.copied,Адрес скопирован.
|
||||||
hw.copied.addr,Скопировано: {0}
|
hw.copied.addr,Скопировано: {0}
|
||||||
hw.balance.frozen," (заморожено {0})"
|
hw.balance.frozen," (заморожено {0})"
|
||||||
|
hw.balance.dirty," (грязных: {0})"
|
||||||
wallets.destroy,Уничтожить
|
wallets.destroy,Уничтожить
|
||||||
wallets.destroy.sure,Подтвердить
|
wallets.destroy.sure,Подтвердить
|
||||||
wallets.destroyed,Уничтожен {0}: {1}
|
wallets.destroyed,Уничтожен {0}: {1}
|
||||||
@@ -549,7 +550,7 @@ predict.purity.rust,Вода верхнего уровня
|
|||||||
nightlog.predict.win,"Прогноз сбылся: «{0}», выплачено {1}."
|
nightlog.predict.win,"Прогноз сбылся: «{0}», выплачено {1}."
|
||||||
nightlog.predict.lose,"Прогноз не оправдался: «{0}», ставка {1} потеряна."
|
nightlog.predict.lose,"Прогноз не оправдался: «{0}», ставка {1} потеряна."
|
||||||
nightlog.predict.void,"Прогноз аннулирован: «{0}», ставка {1} возвращена."
|
nightlog.predict.void,"Прогноз аннулирован: «{0}», ставка {1} возвращена."
|
||||||
nightlog.predict.insider,"«{0}»: расчёт на {1}. Полиция подозревает инсайдерскую сделку; выплата помечена, «грязные» средства кошелька выросли на {2}."
|
nightlog.predict.insider,«{0}»: расчёт {1}. Полиция подозревает инсайдерскую сделку; {2} CRC помечено как «грязные».
|
||||||
predict.tab.markets,Рынки
|
predict.tab.markets,Рынки
|
||||||
predict.tab.intel,Информация
|
predict.tab.intel,Информация
|
||||||
predict.acct.crt,{0}: CRT {1}
|
predict.acct.crt,{0}: CRT {1}
|
||||||
@@ -592,11 +593,10 @@ predict.brief.queued,{0}: операция запланирована
|
|||||||
predict.brief.none,{0}: нечего запускать
|
predict.brief.none,{0}: нечего запускать
|
||||||
predict.brief.can,{0}: можно начать {1}
|
predict.brief.can,{0}: можно начать {1}
|
||||||
predict.clue.push,Вы сдвинули цену на {0}%: рискованно
|
predict.clue.push,Вы сдвинули цену на {0}%: рискованно
|
||||||
nightlog.predict.manip,"«{0}»: расчёт на {1}. Регуляторы подозревают манипуляцию ценой; выплата помечена, «грязные» средства кошелька выросли на {2}."
|
nightlog.predict.manip,«{0}»: расчёт {1}. Регуляторы подозревают манипуляцию ценой; {2} CRC помечено как «грязные».
|
||||||
news.manip.title,Биржа расследует подозрительные сделки
|
news.manip.title,Биржа расследует подозрительные сделки
|
||||||
news.manip.desc,Регуляторы сообщают: кто-то сдвинул цену крупными спотовыми ордерами и получил прибыль на деривативах и предсказаниях; причастные счета помечены.
|
news.manip.desc,Регуляторы сообщают: кто-то сдвинул цену крупными спотовыми ордерами и получил прибыль на деривативах и предсказаниях; причастные счета помечены.
|
||||||
taint.overflow,«Грязные» средства превысили стоимость кошелька; излишек {0} занесён в дело как мошенничество.
|
perp.manip,Позиция закрыта с прибылью {0}. Регуляторы подозревают манипуляцию ценой; в досье занесены улики мошенничества: {1}.
|
||||||
perp.manip,"Закрыто с прибылью {0}. Регуляторы подозревают манипуляцию ценой; прибыль помечена, «грязные» средства на счёте Poinbase выросли на {1}."
|
|
||||||
web3.sub.ponzi,Доходность
|
web3.sub.ponzi,Доходность
|
||||||
ponzi.h,Схема Понци
|
ponzi.h,Схема Понци
|
||||||
ponzi.acct,Кошелёк эмитента {0}: CRC {1}
|
ponzi.acct,Кошелёк эмитента {0}: CRC {1}
|
||||||
@@ -687,7 +687,7 @@ scam.support.name,Поддержка Poinbase
|
|||||||
scam.support.1,"Здравствуйте, служба поддержки Poinbase. Мы зафиксировали подозрительный вход в ваш аккаунт, он был помечен."
|
scam.support.1,"Здравствуйте, служба поддержки Poinbase. Мы зафиксировали подозрительный вход в ваш аккаунт, он был помечен."
|
||||||
scam.support.2,"Пожалуйста, переведите сегодня {0} CRC на безопасный адрес {1} для проверки; средства вернут сразу после неё."
|
scam.support.2,"Пожалуйста, переведите сегодня {0} CRC на безопасный адрес {1} для проверки; средства вернут сразу после неё."
|
||||||
scam.support.3,"Иначе аккаунт будет заморожен навсегда. Мне пора, не забудьте перевести."
|
scam.support.3,"Иначе аккаунт будет заморожен навсегда. Мне пора, не забудьте перевести."
|
||||||
predict.sold.caught,"Продано, получено {0}. Полиция подозревает инсайдерскую сделку; выручка помечена, «грязные» средства кошелька выросли на {1}."
|
predict.sold.caught,"Продано, получено {0}. Полиция подозревает инсайдерскую сделку; {1} CRC помечено как «грязные»."
|
||||||
predict.row.move," (прошлой ночью {0} {1})"
|
predict.row.move," (прошлой ночью {0} {1})"
|
||||||
predict.stats.h,История (ср. цена открытия / факт. частота)
|
predict.stats.h,История (ср. цена открытия / факт. частота)
|
||||||
predict.stats.row,"{0}: рынков: {1}, ср. открытие {2}, сбылось {3}%"
|
predict.stats.row,"{0}: рынков: {1}, ср. открытие {2}, сбылось {3}%"
|
||||||
@@ -698,6 +698,7 @@ predict.kind.Price,Цена PSC
|
|||||||
predict.kind.Gas,Газ
|
predict.kind.Gas,Газ
|
||||||
predict.kind.Cra,Предупреждение CRA
|
predict.kind.Cra,Предупреждение CRA
|
||||||
predict.kind.Era,Эра асик-майнеров
|
predict.kind.Era,Эра асик-майнеров
|
||||||
|
predict.kind.Trial,Суд над Тумблером
|
||||||
nightlog.predict.move,Прогноз «{0}» изменился: {1} -> {2}
|
nightlog.predict.move,Прогноз «{0}» изменился: {1} -> {2}
|
||||||
nightlog.predict.why," ({0})"
|
nightlog.predict.why," ({0})"
|
||||||
chart.empty,Дневной график {0}: истории пока нет; запись с сегодняшнего дня.
|
chart.empty,Дневной график {0}: истории пока нет; запись с сегодняшнего дня.
|
||||||
@@ -709,7 +710,7 @@ news.story.serpico_rev.desc,"Сообщается, что Революционе
|
|||||||
news.story.serpico_bm.title,Чёрный рынок заключил негласную сделку
|
news.story.serpico_bm.title,Чёрный рынок заключил негласную сделку
|
||||||
news.story.serpico_bm.desc,"Внутренний документ Службы безопасности перешёл из рук в руки на Чёрном рынке. С тех пор расчёты в Даркнете заметно стабилизировались, а погашение CRT проходит без сбоев."
|
news.story.serpico_bm.desc,"Внутренний документ Службы безопасности перешёл из рук в руки на Чёрном рынке. С тех пор расчёты в Даркнете заметно стабилизировались, а погашение CRT проходит без сбоев."
|
||||||
news.story.serpico_sec.title,Служба безопасности начинает внутреннюю чистку
|
news.story.serpico_sec.title,Служба безопасности начинает внутреннюю чистку
|
||||||
news.story.serpico_sec.desc,"Служба безопасности объявила о масштабном расследовании внутренней коррупции и усилении контроля за денежными потоками. Poinbase ужесточает проверку вывода средств, а миксеры были названы напрямую."
|
news.story.serpico_sec.desc,Служба безопасности объявила о полном расследовании внутренней коррупции и усилении контроля за денежными потоками; отдельно упомянуты миксеры.
|
||||||
news.story.eleanor_leak.title,Утечка данных о селекции нутрифруктов
|
news.story.eleanor_leak.title,Утечка данных о селекции нутрифруктов
|
||||||
news.story.eleanor_leak.desc,"Газета Нижнего уровня опубликовала данные исследования, позволяющего нутрифруктам снова давать семена; акции Пастель рухнули. Банк, хранящий средства Верхнего уровня, сообщил о безнадёжных долгах, а влияние Революционеров растёт."
|
news.story.eleanor_leak.desc,"Газета Нижнего уровня опубликовала данные исследования, позволяющего нутрифруктам снова давать семена; акции Пастель рухнули. Банк, хранящий средства Верхнего уровня, сообщил о безнадёжных долгах, а влияние Революционеров растёт."
|
||||||
news.story.eleanor_return.title,Пастель возвращает украденные данные
|
news.story.eleanor_return.title,Пастель возвращает украденные данные
|
||||||
@@ -754,6 +755,47 @@ news.tumbler.caught.desc,"Оператор миксера, известный к
|
|||||||
news.tumbler.sold.title,Миксер сменил владельца
|
news.tumbler.sold.title,Миксер сменил владельца
|
||||||
news.tumbler.sold.desc,"По слухам, ключи подписи миксера с Нижнего уровня попали в руки Чёрного рынка, и комиссии тут же выросли. Пользователи опасаются за свои средства."
|
news.tumbler.sold.desc,"По слухам, ключи подписи миксера с Нижнего уровня попали в руки Чёрного рынка, и комиссии тут же выросли. Пользователи опасаются за свои средства."
|
||||||
nightlog.tumbler.gift,Тумблер забрал ключ-накопитель и оставил {0} CRT в знак благодарности (отправлено на {1}); комиссии миксера снижены вдвое.
|
nightlog.tumbler.gift,Тумблер забрал ключ-накопитель и оставил {0} CRT в знак благодарности (отправлено на {1}); комиссии миксера снижены вдвое.
|
||||||
|
agent.name,Агент безопасности
|
||||||
|
agent.v1.1,Служба безопасности. Извините за беспокойство.
|
||||||
|
agent.v1.2,Мы ищем человека по кличке Тумблер. Он держит миксер в сети.
|
||||||
|
agent.v1.3,Его видели в этом районе.
|
||||||
|
agent.ask,Он заходил к вам в магазин?
|
||||||
|
agent.choice.yes,[Сказать: заходил пару раз]
|
||||||
|
agent.choice.no,[Сказать: никогда не видел]
|
||||||
|
agent.yes1,Спасибо за содействие. Служба безопасности этого не забудет.
|
||||||
|
agent.no1,"Вот как. Если что-нибудь вспомните, вы знаете, где нас найти."
|
||||||
|
agent.search.1,"Снова здравствуйте. До нас дошли слухи, что вы кое-что храните для того человека."
|
||||||
|
agent.search.2,Плановый обыск. Просьба сотрудничать.
|
||||||
|
agent.search.found,Нашли. Мы это забираем.
|
||||||
|
agent.search.none,...Ничего. Извините за беспокойство.
|
||||||
|
tumbler.v4.seized.1,"Слышал, Служба безопасности обыскала твой магазин."
|
||||||
|
tumbler.v4.seized.2,Ключ теперь у них. Они поднимут записи каждого пользователя.
|
||||||
|
tumbler.v4.seized.3,Что ты им сказал — знать больше не хочу.
|
||||||
|
nightlog.tumbler.leak,"Служба безопасности использовала ключ подписи Тумблера для восстановления записей миксера: выплат: {0}, отмыто загрязнения: {1}; в досье занесены улики мошенничества: {2}."
|
||||||
|
nightlog.tumbler.leak.none,"Служба безопасности использовала ключ подписи Тумблера, чтобы восстановить записи микширования. В последнее время вы ничего не выводили из миксера."
|
||||||
|
nightlog.tumbler.note,"Под дверь подсунули записку: «Ты мне задолжал, и я своё заберу. — Т»"
|
||||||
|
nightlog.tumbler.tip,Сообщение от Тумблера: завтра Служба безопасности может взяться за миксеры.
|
||||||
|
news.tumbler.leak.title,Служба безопасности восстановила записи миксера
|
||||||
|
news.tumbler.leak.desc,"Служба безопасности заявляет о получении ключа подписи миксера. С его помощью будут отслежены средства, отмытые через сервис за последний месяц."
|
||||||
|
news.trial.pro.title,"Суд над Тумблером, день {0}: перевес обвинения"
|
||||||
|
news.trial.def.title,"Суд над Тумблером, день {0}: перевес защиты"
|
||||||
|
news.trial.pro.desc1,"Обвинение предъявило серверные логи узла миксера, заявив, что они по транзакциям совпадают с подписями подсудимого."
|
||||||
|
news.trial.pro.desc2,"Бывший партнёр дал показания, заявив, что подсудимый заведомо знал о происхождении средств клиентов с Чёрного рынка."
|
||||||
|
news.trial.pro.desc3,Обвинение продемонстрировало переводы между кошельком подсудимого и несколькими адресами мошенников.
|
||||||
|
news.trial.def.desc1,"Защита указала на нарушения при изъятии узла и сборе улик, заявив, что часть логов могла быть изменена."
|
||||||
|
news.trial.def.desc2,"Эксперт защиты дал показания: контракт миксера — это открытый исходный код, и подсудимый не контролирует его пользователей."
|
||||||
|
news.trial.def.desc3,"Ключевой свидетель обвинения изменил показания в суде, заявив, что не помнит, знал ли подсудимый."
|
||||||
|
news.trial.convict.title,Тумблер признан виновным
|
||||||
|
news.trial.convict.desc,"Суд признал оператора миксера по кличке Тумблер виновным в отмывании денег. Служба безопасности заявляет, что сервис микширования больше не откроется."
|
||||||
|
news.trial.acquit.title,Тумблер оправдан
|
||||||
|
news.trial.acquit.desc,"За недостатком улик суд оправдал оператора миксера по кличке Тумблер и освободил его из-под стражи. Он покинул здание суда, не ответив на вопросы журналистов."
|
||||||
|
news.tumbler.bmrug.title,Сервис микширования скрылся со средствами
|
||||||
|
news.tumbler.bmrug.desc,"Сервис микширования, перешедший под контроль Чёрного рынка, внезапно прекратил выплаты, а средства из контракта были выведены. Пользователи на форумах жалуются на потерю всех средств."
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,Новый сервис микширования {0} начал работу
|
||||||
|
news.mixer.rebrand.desc,"Недавно начал работу сервис микширования под названием {0}, заявляющий об отсутствии логов и бэкдоров. Некоторые заметили, что его контракт подозрительно похож на ранее закрытый сервис."
|
||||||
|
predict.q.trial,{0}: Тумблер признан виновным
|
||||||
|
predict.clue.trial,"Сводки суда: перевес обвинения — {0} дн., перевес защиты — {1} дн."
|
||||||
mixer.status.closed,Статус: закрыт
|
mixer.status.closed,Статус: закрыт
|
||||||
yield.sub.pools,Доходные пулы
|
yield.sub.pools,Доходные пулы
|
||||||
yield.sub.mine,Запуск схемы
|
yield.sub.mine,Запуск схемы
|
||||||
@@ -995,7 +1037,7 @@ otc.cancel,Отказ
|
|||||||
otc.msg.gone,Клиент ушёл.
|
otc.msg.gone,Клиент ушёл.
|
||||||
otc.msg.cash,Недостаточно наличных.
|
otc.msg.cash,Недостаточно наличных.
|
||||||
otc.msg.sting,"Клиент был под прикрытием: конфисковано {0} наличными, зафиксирован сбыт краденого."
|
otc.msg.sting,"Клиент был под прикрытием: конфисковано {0} наличными, зафиксирован сбыт краденого."
|
||||||
otc.msg.bought,"Получено {0} {1}, выплачено {2} наличными."
|
otc.msg.bought,"Получено {0} {1} (из них грязных: {3}), выплачено наличными: {2}."
|
||||||
otc.msg.sold,"Отправлено {0} {1}, получено {2} наличными."
|
otc.msg.sold,"Отправлено {0} {1}, получено {2} наличными."
|
||||||
gray.sub.own,Мой миксер
|
gray.sub.own,Мой миксер
|
||||||
ownmix.h,Мой миксер
|
ownmix.h,Мой миксер
|
||||||
@@ -1045,3 +1087,4 @@ otc.nocash,Даже наличных нет? Забудьте.
|
|||||||
otc.nowallet,"Кошелёк не подключён, куда слать монеты? Забудьте."
|
otc.nowallet,"Кошелёк не подключён, куда слать монеты? Забудьте."
|
||||||
otc.sting,"Не двигаться. Служба безопасности. Скупка краденых средств: наличные изъяты, это пойдёт в ваше досье."
|
otc.sting,"Не двигаться. Служба безопасности. Скупка краденых средств: наличные изъяты, это пойдёт в ваше досье."
|
||||||
hw.err.poinbase,Poinbase не принимает {0}.
|
hw.err.poinbase,Poinbase не принимает {0}.
|
||||||
|
hw.err.tainted,"В этом кошельке грязных {1}: {0}, а Poinbase принимает только чистые монеты: максимум {2} {1}."
|
||||||
@@ -21,7 +21,7 @@ tab.report,报告
|
|||||||
wallet.line,{0}:{1}(约 {2} 信用点)
|
wallet.line,{0}:{1}(约 {2} 信用点)
|
||||||
wallet.empty,钱包为空。
|
wallet.empty,钱包为空。
|
||||||
wallet.total,总值:{0} 信用点
|
wallet.total,总值:{0} 信用点
|
||||||
wallet.taint,污点:{0} 信用点
|
wallet.taint,脏币:{0} 信用点
|
||||||
trade.amount,数量
|
trade.amount,数量
|
||||||
trade.deposit,存入信用点
|
trade.deposit,存入信用点
|
||||||
trade.withdraw,提取 CRC
|
trade.withdraw,提取 CRC
|
||||||
@@ -37,8 +37,6 @@ msg.balance,余额不足。
|
|||||||
msg.trade,支付 {0} {1},获得 {2} {3}。
|
msg.trade,支付 {0} {1},获得 {2} {3}。
|
||||||
msg.deposit,已存入 {0} 信用点,兑换为 CRC。
|
msg.deposit,已存入 {0} 信用点,兑换为 CRC。
|
||||||
msg.cashout,到账 {0} 信用点。税 {1} 信用点。
|
msg.cashout,到账 {0} 信用点。税 {1} 信用点。
|
||||||
msg.aml_light,合规审查:{0} 信用点的污点资金被扣留。
|
|
||||||
msg.aml_heavy,合规审查:{0} 信用点的污点资金被没收,并已上报治安部。
|
|
||||||
report.none,暂无挖矿报告。
|
report.none,暂无挖矿报告。
|
||||||
report.day,第 {0} 天夜间
|
report.day,第 {0} 天夜间
|
||||||
report.rigs,供电矿架:{0} / {1}
|
report.rigs,供电矿架:{0} / {1}
|
||||||
@@ -140,6 +138,7 @@ col.asset,"币种"
|
|||||||
col.amount,"数量"
|
col.amount,"数量"
|
||||||
col.value,"估值"
|
col.value,"估值"
|
||||||
col.avg,"买入均价"
|
col.avg,"买入均价"
|
||||||
|
col.dirty,脏币
|
||||||
bank.cash.k,"信用点"
|
bank.cash.k,"信用点"
|
||||||
bank.rent.k,"房租"
|
bank.rent.k,"房租"
|
||||||
bank.rent.v,"{0},{1} 天后支付"
|
bank.rent.v,"{0},{1} 天后支付"
|
||||||
@@ -151,13 +150,12 @@ stable.ok,"锚定正常"
|
|||||||
stable.depeg,"脱锚"
|
stable.depeg,"脱锚"
|
||||||
stable.warn,"预兆:储备覆盖率告急"
|
stable.warn,"预兆:储备覆盖率告急"
|
||||||
stable.spiral,"崩盘中"
|
stable.spiral,"崩盘中"
|
||||||
aml.taint,"账户污点比例:{0}%"
|
|
||||||
mixer.h,混币器
|
mixer.h,混币器
|
||||||
mixer.ok,状态:运行正常
|
mixer.ok,状态:运行正常
|
||||||
mixer.sanctioned,状态:已被制裁(还有 {0} 天),此期间提出的币视为被标记。
|
mixer.sanctioned,状态:已被制裁(还有 {0} 天),此期间到期的出款不洗,整笔算脏币。
|
||||||
mixer.pending,在途存入
|
mixer.pending,在途存入
|
||||||
mixer.none,暂无在途存入。
|
mixer.none,暂无在途存入。
|
||||||
mixer.col.taint,污点
|
mixer.col.taint,脏币
|
||||||
mixer.col.ready,到期
|
mixer.col.ready,到期
|
||||||
mixer.day,第 {0} 天
|
mixer.day,第 {0} 天
|
||||||
mixer.deposit,存入
|
mixer.deposit,存入
|
||||||
@@ -168,11 +166,12 @@ mixer.go,存入混币器
|
|||||||
mixer.min,存入价值不得低于 {0} 信用点。
|
mixer.min,存入价值不得低于 {0} 信用点。
|
||||||
mixer.done,已存入 {0} {1},第 {2} 天提回。
|
mixer.done,已存入 {0} {1},第 {2} 天提回。
|
||||||
mixer.upgrade.title,混币器
|
mixer.upgrade.title,混币器
|
||||||
mixer.upgrade.desc,"解锁终端灰网页里的混币器:把带污点的币存进去,几天后提回,污点降低。出金审查对刚从混币器出来的币更严格;镇压期间混币器可能被制裁,期间提出的币会被标记。"
|
mixer.upgrade.desc,解锁终端灰网页里的混币器:把脏币存进去,几天后提回,脏币变少。镇压期间混币器可能被制裁,制裁期间到期的出款整笔算脏币。
|
||||||
news.sanction.title,混币器被列入制裁名单
|
news.sanction.title,混币器被列入制裁名单
|
||||||
news.sanction.desc,"安保部门宣布制裁一批混币服务。此后几天从混币器提出的资金将被视为可疑。"
|
news.sanction.desc,安保部门宣布制裁一批混币服务。此后几天从混币器提出的资金将被视为赃款。
|
||||||
nightlog.mixer,混币器提回 {0} {1},污点 {2} → {3}。
|
nightlog.mixer,混币器提回 {0} {1},污点 {2} → {3}。
|
||||||
nightlog.mixer_flag,(制裁期间提出,地址被标记)
|
nightlog.mixer_flag,(制裁期间提出,整笔算脏币)
|
||||||
|
nightlog.mixer_flag.trap,(提出的币被治安部整笔算作脏币)
|
||||||
nightlog.mixer_rug,混币器的运营者卷款跑路了:{0} {1} 没有提回。
|
nightlog.mixer_rug,混币器的运营者卷款跑路了:{0} {1} 没有提回。
|
||||||
web3.sub.trade,交易
|
web3.sub.trade,交易
|
||||||
gray.sub.mixer,混币器
|
gray.sub.mixer,混币器
|
||||||
@@ -247,7 +246,7 @@ black.kind.Contraband.3,违禁品(高)
|
|||||||
black.kind.Tech,高科技物品(加价)
|
black.kind.Tech,高科技物品(加价)
|
||||||
nightlog.bm.ready,商店:{0} 到货,开店后会有快递员上门。
|
nightlog.bm.ready,商店:{0} 到货,开店后会有快递员上门。
|
||||||
guide.web3.title,Web3 手册
|
guide.web3.title,Web3 手册
|
||||||
guide.web3.text,"银行与交易:银行页只读,显示现金、房租和 Poinbase 账户里的 CRC。Poinbase 的资金页管入金和出金,先选币种:CRC 可以走银行账户或钱包,其他币只能走钱包。从银行入金把信用点换成 Poinbase 账户里的 CRC;出金到银行把 CRC 换回信用点,要过合规审查,审查看 Poinbase 账户的污点。出金到钱包要填收款地址,等几次确认才到账,Gas 费固定按普通档、从转出的币里扣;地址格式或校验位不对会被拒绝,格式对但没人用的地址,币转过去就没了。¶交易:PSC 全称 Probably Stolen Coin,是显卡和矿机挖出的币。Poinbase 现货有 PSC/CRC 和 SPARK/CRC 两个交易对,跟着行情图选中的币切换。买入和卖出都填所交易币的数量,预览显示要付或能得到的计价币,均价含手续费,滑点不含。¶Web3 交易页可以任选两种币互换,实际都经 CRC 中转:CRC 在一端走一个池,否则走两个池,付两次手续费、滑点叠加,预览里会显示得到的数量、经过的池数和损耗。稳定币之间(CRT、CRA 对 CRC)走稳定币池:手续费 {StableFee:%},挂钩附近几乎没有滑点;脱锚时流动性变差,崩盘时流动性被撤走,滑点急剧变大。§硬件钱包:链上的币放在 PLEDGER 硬件钱包里,每个钱包的余额和污点分别计算。钱包是一件物品,拖到交易终端上加载;在终端的钱包页打开,在终端右上角连接或断开。Web3 页的交易和灰网页的商店、混币器用已连接的钱包,没有钱包或没有连接时只能看,余额都是 0;用币付款的顾客也进已连接的钱包。¶付款(商店、混币器、Ponero 兑换处、上架费)先在终端开账单,再在钱包里手输收款地址、按住 ✓ 签名;地址末尾两位是校验位,输错一位多半会被拦下,偶尔碰巧合法,币就转进了没人用的地址。DEX 兑换也要在钱包上签名。¶Poinbase 是托管账户,入金要从钱包转到它的充值地址(只收 PSC、CRC、SPARK;黑市的 CRT、革命军的 CRA 合规交易所不收,往充值地址转会被钱包拦下),出金在 Poinbase 的资金页发起。钱包页的浏览器可以按地址查转账记录,只显示真实发生的转账:你的钱包的每一笔进出(转账、DEX 兑换和其他合约调用、矿机收益、出金、别人转来的币);Ponero 是隐私币,不显示。更多硬件钱包向杰克逊博士购买,拖到交易终端上添加,最多 {WalletMax} 个;商店里也有更便宜的。不要的钱包可以在钱包页销毁,里面的币永久丢失,之后发到这个地址的币也丢了。¶转账要付 Gas 费,分慢、普通、快三档,Gas 价格大约一周一个起落;网络拥堵时 Gas 费变贵,慢档可能被挤出内存池。转账前核对完整地址。§质押:把 CRA 质押进革命军质押池每天有日息,利息并入本金;取出要先申请,等四天才到账,等待期间没有利息,也不能提前拿。CRA 是部分抵押的:每份 CRA 由革命军持有的 CRC 储备和平衡代币 SPARK 共同支撑,储备覆盖率和抵押率显示在质押页。质押利息以没有抵押的新 CRA 付出,会稀释储备覆盖率,质押的人越多稀释越快;覆盖率太低革命军会降息。革命军有时会挪用储备,先有风声,那是预兆;挪用后覆盖率跌破 {CraCrashRatio:%} 就崩盘:三天内 CRA 归零,四天的解锁期来不及;没跌破只是折价,劫掠上层带来的资金会慢慢把储备补回来。¶官方铸造:存入 CRC 和 SPARK(比例按当前抵押率,界面预览需要多少)铸造 CRA,排 {CraMintDaysMin}~{CraMintDaysMax} 天,铸出的 CRA 直接进质押;销毁把 CRA 换回 CRC 和 SPARK,等待和解锁期一样长,储备不足时 CRC 份额按覆盖率打折。排队的铸造和销毁,官方可能整笔不兑现:每晚的概率是 CRA 价格低于 1 的幅度乘以 {CraRugPerDepeg},价格不低于 1 就不会。¶质押可以存 CRA、CRC、CRT、SPARK:后三种先在二级市场按市价换成 CRA(经 CRC 中转,付手续费和滑点)再质押。SPARK 价格波动很大,崩盘时会跟着暴跌。质押、铸造、销毁都是合约调用,要在钱包上签名。§矿机:RatDigg 矿机(M1 / M2 / M3)是独立的机器,算力比显卡大得多、耗电更省,要放电池才挖,可以放模块,不占矿架槽位;只在商店的矿机商那里有,要黑市声望(M1 {AsicRepM1}、M2 {AsicRepM2}、M3 {AsicRepM3}),偶尔有二手的。烧毁后须按顺序把电子元件拖到它身上修复,修复后健康降低 {AsicRepairHealthCut}。第 {EraMin} 到 {EraMax} 天之间会有一次""矿机时代"",提前几天上报纸预告,之后大矿场的耗电成本砍半,全网算力涨上去,显卡矿工的收益被摊薄,低档显卡Line truncated
|
guide.web3.text,"银行与交易:银行页只读,显示现金、房租和 Poinbase 账户里的 CRC。Poinbase 的资金页管入金和出金,先选币种:CRC 可以走银行账户或钱包,其他币只能走钱包。从银行入金把信用点换成 Poinbase 账户里的 CRC;出金到银行把 CRC 换回信用点,不做审查(Poinbase 账户里只有干净的钱)。出金到钱包要填收款地址,等几次确认才到账,Gas 费固定按普通档、从转出的币里扣;地址格式或校验位不对会被拒绝,格式对但没人用的地址,币转过去就没了。¶交易:PSC 全称 Probably Stolen Coin,是显卡和矿机挖出的币。Poinbase 现货有 PSC/CRC 和 SPARK/CRC 两个交易对,跟着行情图选中的币切换。买入和卖出都填所交易币的数量,预览显示要付或能得到的计价币,均价含手续费,滑点不含。¶Web3 交易页可以任选两种币互换,实际都经 CRC 中转:CRC 在一端走一个池,否则走两个池,付两次手续费、滑点叠加,预览里会显示得到的数量、经过的池数和损耗。稳定币之间(CRT、CRA 对 CRC)走稳定币池:手续费 {StableFee:%},挂钩附近几乎没有滑点;脱锚时流动性变差,崩盘时流动性被撤走,滑点急剧变大。§硬件钱包:链上的币放在 PLEDGER 硬件钱包里,每个钱包的余额和脏币分别计算(每种币分别记脏币数量,见“污点”一节)。钱包是一件物品,拖到交易终端上加载;在终端的钱包页打开,在终端右上角连接或断开。Web3 页的交易和灰网页的商店、混币器用已连接的钱包,没有钱包或没有连接时只能看,余额都是 0;用币付款的顾客也进已连接的钱包。¶付款(商店、混币器、Ponero 兑换处、上架费)先在终端开账单,再在钱包里手输收款地址、按住 ✓ 签名;地址末尾两位是校验位,输错一位多半会被拦下,偶尔碰巧合法,币就转进了没人用的地址。DEX 兑换也要在钱包上签名。¶Poinbase 是托管账户,入金要从钱包转到它的充值地址(只收 PSC、CRC、SPARK;黑市的 CRT、革命军的 CRA 合规交易所不收,往充值地址转会被钱包拦下;每种币只收干净的枚数,见“污点”一节),出金在 Poinbase 的资金页发起。钱包页的浏览器可以按地址查转账记录,只显示真实发生的转账:你的钱包的每一笔进出(转账、DEX 兑换和其他合约调用、矿机收益、出金、别人转来的币);Ponero 是隐私币,不显示。更多硬件钱包向杰克逊博士购买,拖到交易终端上添加,最多 {WalletMax} 个;商店里也有更便宜的。不要的钱包可以在钱包页销毁,里面的币永久丢失,之后发到这个地址的币也丢了。¶转账要付 Gas 费,分慢、普通、快三档,Gas 价格大约一周一个起落;网络拥堵时 Gas 费变贵,慢档可能被挤出内存池。转账前核对完整地址。§质押:把 CRA 质押进革命军质押池每天有日息,利息并入本金;取出要先申请,等四天才到账,等待期间没有利息,也不能提前拿。CRA 是部分抵押的:每份 CRA 由革命军持有的 CRC 储备和平衡代币 SPARK 共同支撑,储备覆盖率和抵押率显示在质押页。质押利息以没有抵押的新 CRA 付出,会稀释储备覆盖率,质押的人越多稀释越快;覆盖率太低革命军会降息。革命军有时会挪用储备,先有风声,那是预兆;挪用后覆盖率跌破 {CraCrashRatio:%} 就崩盘:三天内 CRA 归零,四天的解锁期来不及;没跌破只是折价,劫掠上层带来的资金会慢慢把储备补回来。¶官方铸造:存入 CRC 和 SPARK(比例按当前抵押率,界面预览需要多少)铸造 CRA,排 {CraMintDaysMin}~{CraMintDaysMax} 天,铸出的 CRA 直接进质押;销毁把 CRA 换回 CRC 和 SPARK,等待和解锁期一样长,储备不足时 CRC 份额按覆盖率打折。排队的铸造和销毁,官方可能整笔不兑现:每晚的概率是 CRA 价格低于 1 的幅度乘以 {CraRugPerDepeg},价格不低于 1 就不会。¶质押可以存 CRA、CRC、CRT、SPARK:后三种先在二级市场按市价换成 CRA(经 CRC 中转,付手续费和滑点)再质押。SPARK 价格波动很大,崩盘时会跟着暴跌。质押、铸造、销毁都是合约调用,要在钱包上签名。§矿机:RatDigg 矿机(M1 / M2 / M3)是独立的机器,算力比显卡大得多、耗电更省,要放电池才挖,可以放模块,不占矿架槽位;只在商店的矿机商那里有,要黑市声望(M1 {AsicRepM1}、M2 {AsicRepM2}、M3 {AsicRepM3}),偶尔有二手的。烧毁后须按顺序把电子元件拖到它身上修复,修复后健康降低 {AsicRepairHealthCut}。第 {EraMin} 到 {EraMax} 天之间会有一次""矿机时代"",提前几天上报纸预Line truncated
|
||||||
courier.odd1,……东西到了。
|
courier.odd1,……东西到了。
|
||||||
courier.odd2,"(他的手一直放在口袋里)在这儿签个字。"
|
courier.odd2,"(他的手一直放在口袋里)在这儿签个字。"
|
||||||
courier.sign,签收
|
courier.sign,签收
|
||||||
@@ -360,10 +359,11 @@ hw.wallet.n,"钱包 {0}"
|
|||||||
hw.review.own,"自己的钱包:{0}"
|
hw.review.own,"自己的钱包:{0}"
|
||||||
hw.review.poinbase,Poinbase 充值地址
|
hw.review.poinbase,Poinbase 充值地址
|
||||||
poin.deposit,"充值地址:{0}"
|
poin.deposit,"充值地址:{0}"
|
||||||
|
poin.deposit.clean,{0} 里能充值的干净币:{1}
|
||||||
wallets.count,"钱包 {0}/{1}"
|
wallets.count,"钱包 {0}/{1}"
|
||||||
wallets.col.name,名称
|
wallets.col.name,名称
|
||||||
wallets.col.addr,地址
|
wallets.col.addr,地址
|
||||||
wallets.col.taint,污点
|
wallets.col.taint,脏币
|
||||||
wallets.open,打开
|
wallets.open,打开
|
||||||
wallets.use,连接
|
wallets.use,连接
|
||||||
wallets.current,已连接
|
wallets.current,已连接
|
||||||
@@ -377,6 +377,7 @@ hw.paste,粘贴
|
|||||||
hw.copied,地址已复制。
|
hw.copied,地址已复制。
|
||||||
hw.copied.addr,"已复制 {0}"
|
hw.copied.addr,"已复制 {0}"
|
||||||
hw.balance.frozen,"(冻结 {0})"
|
hw.balance.frozen,"(冻结 {0})"
|
||||||
|
hw.balance.dirty,(脏币 {0})
|
||||||
wallets.destroy,销毁
|
wallets.destroy,销毁
|
||||||
wallets.destroy.sure,确认销毁
|
wallets.destroy.sure,确认销毁
|
||||||
wallets.destroyed,"已销毁{0}:{1}"
|
wallets.destroyed,"已销毁{0}:{1}"
|
||||||
@@ -548,7 +549,7 @@ predict.purity.rust,上层水
|
|||||||
nightlog.predict.win,预测押中:「{0}」,兑付 {1}。
|
nightlog.predict.win,预测押中:「{0}」,兑付 {1}。
|
||||||
nightlog.predict.lose,预测押错:「{0}」,本金 {1} 没了。
|
nightlog.predict.lose,预测押错:「{0}」,本金 {1} 没了。
|
||||||
nightlog.predict.void,预测作废:「{0}」,退回本金 {1}。
|
nightlog.predict.void,预测作废:「{0}」,退回本金 {1}。
|
||||||
nightlog.predict.insider,「{0}」结算 {1}。警方怀疑这是内幕交易,这笔收益被标记,钱包污点增加 {2}。
|
nightlog.predict.insider,「{0}」结算 {1}。警方怀疑这是内幕交易,其中 {2} CRC 记为脏币。
|
||||||
predict.tab.markets,盘口
|
predict.tab.markets,盘口
|
||||||
predict.tab.intel,情报
|
predict.tab.intel,情报
|
||||||
predict.acct.crt,链上钱包 {0}:CRT {1}
|
predict.acct.crt,链上钱包 {0}:CRT {1}
|
||||||
@@ -591,11 +592,10 @@ predict.brief.queued,{0}:行动已排期
|
|||||||
predict.brief.none,{0}:暂时发起不了
|
predict.brief.none,{0}:暂时发起不了
|
||||||
predict.brief.can,{0}:可发起 {1}
|
predict.brief.can,{0}:可发起 {1}
|
||||||
predict.clue.push,玩家推价 {0}%,操纵风险高
|
predict.clue.push,玩家推价 {0}%,操纵风险高
|
||||||
nightlog.predict.manip,「{0}」结算 {1}。监管部门怀疑你操纵了价格,这笔兑付被标记,钱包污点增加 {2}。
|
nightlog.predict.manip,「{0}」结算 {1}。监管部门怀疑你操纵了价格,其中 {2} CRC 记为脏币。
|
||||||
news.manip.title,交易所调查异常交易
|
news.manip.title,交易所调查异常交易
|
||||||
news.manip.desc,监管部门通报,有人用大额现货单推动价格,从合约和预测里获利,涉事账户已被标记。
|
news.manip.desc,监管部门通报,有人用大额现货单推动价格,从合约和预测里获利,涉事账户已被标记。
|
||||||
taint.overflow,污点已超过钱包价值,超出的 {0} 记为诈骗罪证。
|
perp.manip,平仓盈利 {0}。监管部门怀疑你操纵了价格,记诈骗罪证 {1}。
|
||||||
perp.manip,平仓盈利 {0}。监管部门怀疑你操纵了价格,这笔盈利被标记,Poinbase 账户污点增加 {1}。
|
|
||||||
web3.sub.ponzi,理财
|
web3.sub.ponzi,理财
|
||||||
ponzi.h,高息理财
|
ponzi.h,高息理财
|
||||||
ponzi.acct,发行钱包 {0}:CRC {1}
|
ponzi.acct,发行钱包 {0}:CRC {1}
|
||||||
@@ -686,7 +686,7 @@ scam.support.name,Poinbase 客服
|
|||||||
scam.support.1,您好,我是 Poinbase 客服。系统检测到您的账户有异常登录,已经被风控了。
|
scam.support.1,您好,我是 Poinbase 客服。系统检测到您的账户有异常登录,已经被风控了。
|
||||||
scam.support.2,请在今天内把 {0} CRC 转到安全地址 {1} 做验证,验证完马上退回。
|
scam.support.2,请在今天内把 {0} CRC 转到安全地址 {1} 做验证,验证完马上退回。
|
||||||
scam.support.3,不处理的话账户会被永久冻结。我先走了,记得转。
|
scam.support.3,不处理的话账户会被永久冻结。我先走了,记得转。
|
||||||
predict.sold.caught,卖出,收回 {0}。警方怀疑这是内幕交易,这笔收益被标记,钱包污点增加 {1}。
|
predict.sold.caught,卖出,收回 {0}。警方怀疑这是内幕交易,其中 {1} CRC 记为脏币。
|
||||||
predict.row.move,(昨晚 {0} {1})
|
predict.row.move,(昨晚 {0} {1})
|
||||||
predict.stats.h,历史(开盘均价 / 实际发生)
|
predict.stats.h,历史(开盘均价 / 实际发生)
|
||||||
predict.stats.row,{0}:{1} 个,开盘均价 {2},发生 {3}%
|
predict.stats.row,{0}:{1} 个,开盘均价 {2},发生 {3}%
|
||||||
@@ -697,6 +697,7 @@ predict.kind.Price,PSC 价格
|
|||||||
predict.kind.Gas,gas
|
predict.kind.Gas,gas
|
||||||
predict.kind.Cra,CRA 预警
|
predict.kind.Cra,CRA 预警
|
||||||
predict.kind.Era,矿机时代
|
predict.kind.Era,矿机时代
|
||||||
|
predict.kind.Trial,Tumbler 审判
|
||||||
nightlog.predict.move,预测盘「{0}」价格 {1} → {2}
|
nightlog.predict.move,预测盘「{0}」价格 {1} → {2}
|
||||||
nightlog.predict.why,({0})
|
nightlog.predict.why,({0})
|
||||||
chart.empty,{0} 日K:暂无历史,自今日起记录。
|
chart.empty,{0} 日K:暂无历史,自今日起记录。
|
||||||
@@ -708,7 +709,7 @@ news.story.serpico_rev.desc,据传革命军拿到了治安部内部腐败的证
|
|||||||
news.story.serpico_bm.title,黑市与治安部达成默契
|
news.story.serpico_bm.title,黑市与治安部达成默契
|
||||||
news.story.serpico_bm.desc,一份治安部内部文件在黑市易手。此后暗网结算通道明显稳定,CRT 的兑付没再出过岔子。
|
news.story.serpico_bm.desc,一份治安部内部文件在黑市易手。此后暗网结算通道明显稳定,CRT 的兑付没再出过岔子。
|
||||||
news.story.serpico_sec.title,治安部启动内部整顿
|
news.story.serpico_sec.title,治安部启动内部整顿
|
||||||
news.story.serpico_sec.desc,治安部宣布彻查内部腐败,同时加强对资金流向的监控。Poinbase 收紧出金审查,混币服务被点名。
|
news.story.serpico_sec.desc,治安部宣布彻查内部腐败,同时加强对资金流向的监控,混币服务被点名。
|
||||||
news.story.eleanor_leak.title,营养果育种数据曝光
|
news.story.eleanor_leak.title,营养果育种数据曝光
|
||||||
news.story.eleanor_leak.desc,下层报社公开了一份营养果重新结籽的研究数据,帕斯泰尔公司股价重挫。托管上层资金的银行传出坏账,革命军声势上涨。
|
news.story.eleanor_leak.desc,下层报社公开了一份营养果重新结籽的研究数据,帕斯泰尔公司股价重挫。托管上层资金的银行传出坏账,革命军声势上涨。
|
||||||
news.story.eleanor_return.title,帕斯泰尔追回失窃数据
|
news.story.eleanor_return.title,帕斯泰尔追回失窃数据
|
||||||
@@ -753,6 +754,47 @@ news.tumbler.caught.desc,化名 Tumbler 的混币器运营者在下层区被捕
|
|||||||
news.tumbler.sold.title,混币服务易主
|
news.tumbler.sold.title,混币服务易主
|
||||||
news.tumbler.sold.desc,有消息称,下层区一家混币服务的签名密钥已落入黑市之手,费用随即上调。用户担心资金安全。
|
news.tumbler.sold.desc,有消息称,下层区一家混币服务的签名密钥已落入黑市之手,费用随即上调。用户担心资金安全。
|
||||||
nightlog.tumbler.gift,Tumbler 取回了密钥盘,留下 {0} CRT 谢礼(已转入 {1}),混币器手续费减半。
|
nightlog.tumbler.gift,Tumbler 取回了密钥盘,留下 {0} CRT 谢礼(已转入 {1}),混币器手续费减半。
|
||||||
|
agent.name,治安部探员
|
||||||
|
agent.v1.1,治安部的。打扰一下。
|
||||||
|
agent.v1.2,我们在找一个化名 Tumbler 的人,他在链上开混币服务。
|
||||||
|
agent.v1.3,有人看见他在这一带走动。
|
||||||
|
agent.ask,他来过你店里吗?
|
||||||
|
agent.choice.yes,[告诉他:来过几次]
|
||||||
|
agent.choice.no,[告诉他:没见过这个人]
|
||||||
|
agent.yes1,谢谢配合。治安部会记住的。
|
||||||
|
agent.no1,是吗。要是想起什么,随时找我们。
|
||||||
|
agent.search.1,又见面了。我们收到消息,你替那个人保管了一样东西。
|
||||||
|
agent.search.2,例行搜查,配合一下。
|
||||||
|
agent.search.found,找到了。这个我们带走。
|
||||||
|
agent.search.none,……没有。打扰了。
|
||||||
|
tumbler.v4.seized.1,我听说治安部搜了你的店。
|
||||||
|
tumbler.v4.seized.2,密钥在他们手里,所有用户的记录都会被翻出来。
|
||||||
|
tumbler.v4.seized.3,你跟他们说过什么,我不想知道了。
|
||||||
|
nightlog.tumbler.leak,治安部用 Tumbler 的签名密钥还原了混币记录:{0} 笔出款洗掉了 {1} 的污点,记诈骗罪证 {2}。
|
||||||
|
nightlog.tumbler.leak.none,治安部用 Tumbler 的签名密钥还原了混币记录。你最近没有从混币器提回过币。
|
||||||
|
nightlog.tumbler.note,门缝里塞进来一张纸条:“欠我的,我会拿回来。——T”
|
||||||
|
nightlog.tumbler.tip,Tumbler 发来消息:明天治安部可能要查混币服务。
|
||||||
|
news.tumbler.leak.title,治安部还原混币记录
|
||||||
|
news.tumbler.leak.desc,治安部称已取得一家混币服务的签名密钥,将据此追查过去一个月经该服务洗白的资金。
|
||||||
|
news.trial.pro.title,Tumbler 案庭审第 {0} 天:控方占上风
|
||||||
|
news.trial.def.title,Tumbler 案庭审第 {0} 天:辩方占上风
|
||||||
|
news.trial.pro.desc1,控方出示了混币节点的服务器日志,称能逐笔对上被告的签名。
|
||||||
|
news.trial.pro.desc2,一名前合伙人出庭作证,称被告明知客户的资金来自黑市。
|
||||||
|
news.trial.pro.desc3,控方展示了被告钱包与多起诈骗地址之间的转账记录。
|
||||||
|
news.trial.def.desc1,辩方指出,查封节点时的取证程序存在瑕疵,部分日志可能被改动过。
|
||||||
|
news.trial.def.desc2,辩方专家作证:混币合约是开源代码,被告无法控制谁在使用。
|
||||||
|
news.trial.def.desc3,控方的关键证人当庭改口,称记不清被告是否知情。
|
||||||
|
news.trial.convict.title,Tumbler 被判有罪
|
||||||
|
news.trial.convict.desc,法院认定化名 Tumbler 的混币器运营者洗钱罪名成立。治安部表示,相关混币服务不会再开放。
|
||||||
|
news.trial.acquit.title,Tumbler 无罪获释
|
||||||
|
news.trial.acquit.desc,法院以证据不足为由,判化名 Tumbler 的混币器运营者无罪,当庭释放。他离开法院时没有回答记者的提问。
|
||||||
|
news.tumbler.bmrug.title,混币服务卷款跑路
|
||||||
|
news.tumbler.bmrug.desc,被黑市接手的一家混币服务突然停止出款,合约里的资金被转走。用户在论坛上抱怨血本无归。
|
||||||
|
mixer.brand,Vortex
|
||||||
|
news.mixer.rebrand.title,新混币服务 {0} 上线
|
||||||
|
news.mixer.rebrand.desc,一家名为 {0} 的混币服务近日上线,自称无日志、无后门。有人注意到,它的合约和此前关停的服务十分相似。
|
||||||
|
predict.q.trial,{0}:Tumbler 被判有罪
|
||||||
|
predict.clue.trial,庭审报道:控方占上风 {0} 天,辩方占上风 {1} 天
|
||||||
mixer.status.closed,状态:已关停
|
mixer.status.closed,状态:已关停
|
||||||
yield.sub.pools,收益池
|
yield.sub.pools,收益池
|
||||||
yield.sub.mine,发行理财
|
yield.sub.mine,发行理财
|
||||||
@@ -994,7 +1036,7 @@ otc.cancel,放弃
|
|||||||
otc.msg.gone,客户已经走了。
|
otc.msg.gone,客户已经走了。
|
||||||
otc.msg.cash,现金不够。
|
otc.msg.cash,现金不够。
|
||||||
otc.msg.sting,对方是便衣:现金 {0} 被没收,记销赃罪证。
|
otc.msg.sting,对方是便衣:现金 {0} 被没收,记销赃罪证。
|
||||||
otc.msg.bought,收到 {0} {1},付现金 {2}。
|
otc.msg.bought,收到 {0} {1}(脏币 {3}),付现金 {2}。
|
||||||
otc.msg.sold,转出 {0} {1},收现金 {2}。
|
otc.msg.sold,转出 {0} {1},收现金 {2}。
|
||||||
gray.sub.own,自营混币器
|
gray.sub.own,自营混币器
|
||||||
ownmix.h,自营混币器
|
ownmix.h,自营混币器
|
||||||
@@ -1044,3 +1086,4 @@ otc.nocash,现金都拿不出来?那算了。
|
|||||||
otc.nowallet,钱包都没连上,币往哪儿转?算了。
|
otc.nowallet,钱包都没连上,币往哪儿转?算了。
|
||||||
otc.sting,别动,治安部。收购赃款,现金没收,这笔会记进你的档案。
|
otc.sting,别动,治安部。收购赃款,现金没收,这笔会记进你的档案。
|
||||||
hw.err.poinbase,Poinbase 不收 {0}。
|
hw.err.poinbase,Poinbase 不收 {0}。
|
||||||
|
hw.err.tainted,钱包里的 {1} 有脏币 {0},Poinbase 只收干净的币:最多 {2} {1}。
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<ID>probably_decentralized</ID>
|
<ID>probably_decentralized</ID>
|
||||||
<Name>Probably Decentralized</Name>
|
<Name>Probably Decentralized</Name>
|
||||||
<Author>edward</Author>
|
<Author>edward</Author>
|
||||||
<ModVersion>1.1.0</ModVersion>
|
<ModVersion>2.0.0</ModVersion>
|
||||||
<Description>Mine PSC with graphics cards, trade it on a fictional exchange, and cash it out past the compliance desk. Work in progress. All coins, exchanges and events are fictional and have no real-world value.</Description>
|
<Description>Mine PSC with graphics cards, trade it on a fictional exchange, and cash it out past the compliance desk. Work in progress. All coins, exchanges and events are fictional and have no real-world value.</Description>
|
||||||
<GameVersions>
|
<GameVersions>
|
||||||
<Version>0.46</Version>
|
<Version>0.46</Version>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
var m = d.OwnMix;
|
var m = d.OwnMix;
|
||||||
bool rivalOpen = !d.Story.MixerClosed && !d.Mixer.Sanctioned(day);
|
bool rivalOpen = !d.Story.MixerClosed && !d.Mixer.Sanctioned(day);
|
||||||
double rivalRemain = Math.Pow(1 - Mixer.RoundRate(Tuning.OwnMixTicket), Tuning.OwnMixAvgRounds);
|
double rivalRemain = Math.Pow(1 - Mixer.RoundRate(Tuning.OwnMixTicket, day), Tuning.OwnMixAvgRounds);
|
||||||
var evs = m.Night(day, Session.Price, StoreReputation.GetBMReputation(), Mixer.Fee, rivalRemain, rivalOpen, StoryMods.Current.Sanction(day), ActiveEvents().Contains(MarketEvent.Crackdown), d.Rng);
|
var evs = m.Night(day, Session.Price, StoreReputation.GetBMReputation(), Mixer.Fee, rivalRemain, rivalOpen, StoryMods.Current.Sanction(day), ActiveEvents().Contains(MarketEvent.Crackdown), d.Rng);
|
||||||
foreach (var e in evs)
|
foreach (var e in evs)
|
||||||
{
|
{
|
||||||
@@ -276,13 +276,13 @@ namespace Decentralized
|
|||||||
var ow = d.WalletAt(oe.Order.Wallet);
|
var ow = d.WalletAt(oe.Order.Wallet);
|
||||||
if (oe.Kind == CraOrderKind.Minted)
|
if (oe.Kind == CraOrderKind.Minted)
|
||||||
{
|
{
|
||||||
ow.Add(Assets.CRA, oe.Cra); d.Staking.Stake(ow, oe.Cra, Session.Price);
|
ow.AddDirty(Assets.CRA, oe.Cra, oe.Cra * oe.Order.DirtyRatio); d.Staking.Stake(ow, oe.Cra, Session.Price);
|
||||||
d.Chain(d.Address("cra"), ow.Address, Assets.CRA, oe.Cra);
|
d.Chain(d.Address("cra"), ow.Address, Assets.CRA, oe.Cra);
|
||||||
d.Chain(ow.Address, d.Address("staking"), Assets.CRA, oe.Cra);
|
d.Chain(ow.Address, d.Address("staking"), Assets.CRA, oe.Cra);
|
||||||
}
|
}
|
||||||
else if (oe.Kind == CraOrderKind.Burned)
|
else if (oe.Kind == CraOrderKind.Burned)
|
||||||
{
|
{
|
||||||
ow.Add(Assets.CRC, oe.Crc); ow.Add(Assets.SPARK, oe.Spark);
|
ow.AddDirty(Assets.CRC, oe.Crc, oe.Crc * oe.Order.DirtyRatio); ow.AddDirty(Assets.SPARK, oe.Spark, oe.Spark * oe.Order.DirtyRatio);
|
||||||
d.Chain(d.Address("cra"), ow.Address, Assets.CRC, oe.Crc);
|
d.Chain(d.Address("cra"), ow.Address, Assets.CRC, oe.Crc);
|
||||||
d.Chain(d.Address("cra"), ow.Address, Assets.SPARK, oe.Spark);
|
d.Chain(d.Address("cra"), ow.Address, Assets.SPARK, oe.Spark);
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,9 @@ namespace Decentralized
|
|||||||
if (m.Rugged) ps.AddNightLog(L.T("nightlog.mixer_rug", Fmt.Num(m.Amount), m.Asset), "cc7755");
|
if (m.Rugged) ps.AddNightLog(L.T("nightlog.mixer_rug", Fmt.Num(m.Amount), m.Asset), "cc7755");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string line = L.T("nightlog.mixer", Fmt.Num(m.Amount), m.Asset, Fmt.Credits(m.TaintBefore), Fmt.Credits(m.TaintAfter)) + (m.Flagged ? L.T("nightlog.mixer_flag") : "");
|
// 被标记的不洗、按全额污点带回:制裁期间提出的写明制裁;不在制裁期却被标记的是治安部的钓鱼混币器
|
||||||
|
string flag = !m.Flagged ? "" : (d.Mixer.Sanctioned(day) ? L.T("nightlog.mixer_flag") : L.T("nightlog.mixer_flag.trap"));
|
||||||
|
string line = L.T("nightlog.mixer", Fmt.Num(m.Amount), m.Asset, Fmt.Credits(m.TaintBefore), Fmt.Credits(m.TaintAfter)) + flag;
|
||||||
if (m.Flagged) ps.AddNightLog(line, "cc7755"); else ps.AddNightLog(line);
|
if (m.Flagged) ps.AddNightLog(line, "cc7755"); else ps.AddNightLog(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,11 +376,11 @@ namespace Decentralized
|
|||||||
else if (e.Kind == "void") ps.AddNightLog(L.T("nightlog.predict.void", PredictGame.Question(e.Market), Fmt.Credits(e.Amount)));
|
else if (e.Kind == "void") ps.AddNightLog(L.T("nightlog.predict.void", PredictGame.Question(e.Market), Fmt.Credits(e.Amount)));
|
||||||
else if (e.Kind == "manip")
|
else if (e.Kind == "manip")
|
||||||
{
|
{
|
||||||
ps.AddNightLog(L.T("nightlog.predict.manip", PredictGame.Question(e.Market), Fmt.Credits(e.Amount), Fmt.Credits(e.Taint)) + TaintCrime.Commit(e.Over), "cc7755");
|
ps.AddNightLog(L.T("nightlog.predict.manip", PredictGame.Question(e.Market), Fmt.Credits(e.Amount), Fmt.Num(e.Taint)), "cc7755");
|
||||||
News.Show("pd_news_manip_" + day, L.T("news.manip.title"), L.T("news.manip.desc"), 3);
|
News.Show("pd_news_manip_" + day, L.T("news.manip.title"), L.T("news.manip.desc"), 3);
|
||||||
}
|
}
|
||||||
else if (e.Kind == "insider")
|
else if (e.Kind == "insider")
|
||||||
ps.AddNightLog(L.T("nightlog.predict.insider", PredictGame.Question(e.Market), Fmt.Credits(e.Amount), Fmt.Credits(e.Taint)) + TaintCrime.Commit(e.Over), "cc7755");
|
ps.AddNightLog(L.T("nightlog.predict.insider", PredictGame.Question(e.Market), Fmt.Credits(e.Amount), Fmt.Num(e.Taint)), "cc7755");
|
||||||
}
|
}
|
||||||
foreach (var e in perpEvents)
|
foreach (var e in perpEvents)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ namespace Decentralized
|
|||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
var side = Otc.PickSide(d.Rng);
|
var side = Otc.PickSide(d.Rng);
|
||||||
bool ponero = Unlock.BlackUnlocked && BlackMarket.DeskOpen(StoreReputation.GetBMReputation());
|
bool ponero = Unlock.BlackUnlocked && BlackMarket.DeskOpen(StoreReputation.GetBMReputation());
|
||||||
var o = side == OtcSide.Sell ? Otc.MakeSell(Night.ActiveEvents(), ponero, Session.Price, Session.Rent(), d.Rng) : Otc.MakeBuy(Session.Price, Session.Rent(), d.Rng);
|
var o = side == OtcSide.Sell ? Otc.MakeSell(Night.ActiveEvents(), ponero, Session.Price, Session.Rent(), d.Rng, StoryMods.Current.OtcSting(StoreStation.GetDayCounter())) : Otc.MakeBuy(Session.Price, Session.Rent(), d.Rng);
|
||||||
if (o == null) return null;
|
if (o == null) return null;
|
||||||
string addr = d.Address("otc:" + (++d.Otc.Seq));
|
string addr = d.Address("otc:" + (++d.Otc.Seq));
|
||||||
var c = Base();
|
var c = Base();
|
||||||
@@ -186,12 +186,12 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double over = Otc.Receive(d.Hot, o, Session.Price);
|
Otc.Receive(d.Hot, o);
|
||||||
d.Chain(ActiveAddress, d.Hot.Address, o.Asset, o.Qty);
|
d.Chain(ActiveAddress, d.Hot.Address, o.Asset, o.Qty);
|
||||||
d.Otc.Record(o.Cash);
|
d.Otc.Record(o.Cash);
|
||||||
msg = L.T("otc.msg.bought", Fmt.Num(o.Qty), o.Asset, Fmt.Credits(o.Cash)) + TaintCrime.Commit(over);
|
msg = L.T("otc.msg.bought", Fmt.Num(o.Qty), o.Asset, Fmt.Credits(o.Cash), Fmt.Num(o.Qty * o.TaintRatio));
|
||||||
Say(L.T("otc.done"));
|
Say(L.T("otc.done"));
|
||||||
Log.Info($"换币客户:{o.Qty:0.##} {o.Asset} 进 {WalletWindow.NameOf(d.Hot)},付现金 {o.Cash},钱包污点 {d.Hot.Taint:0},超出 {over:0}");
|
Log.Info($"换币客户:{o.Qty:0.##} {o.Asset} 进 {WalletWindow.NameOf(d.Hot)},付现金 {o.Cash},其中脏的 {o.Qty * o.TaintRatio:0.##},钱包里 {o.Asset} 脏 {d.Hot.DirtyOf(o.Asset):0.##}");
|
||||||
}
|
}
|
||||||
Drop();
|
Drop();
|
||||||
Session.Save();
|
Session.Save();
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
if (!Available(day)) return;
|
if (!Available(day)) return;
|
||||||
ForceKnown(d, day);
|
ForceKnown(d, day);
|
||||||
|
OpenTrial(d, day);
|
||||||
var made = d.Predict.Refill(day, d.Rng, Candidates(day));
|
var made = d.Predict.Refill(day, d.Rng, Candidates(day));
|
||||||
foreach (var m in made) Log.Info($"预测盘口 #{m.Id}:{m.Kind} {m.Key} {m.Title} 阈值 {m.Param} 窗口 {m.FromDay}-{m.ToDay} 先验 {m.P0:0.000}");
|
foreach (var m in made) Log.Info($"预测盘口 #{m.Id}:{m.Kind} {m.Key} {m.Title} 阈值 {m.Param} 窗口 {m.FromDay}-{m.ToDay} 先验 {m.P0:0.000}");
|
||||||
}
|
}
|
||||||
@@ -172,6 +173,18 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>举报 Tumbler 后的审判盘:开盘日起强制开(不进候选池),宣判那天结算,先验 = 定罪概率。</summary>
|
||||||
|
public static void OpenTrial(SaveData d, int day)
|
||||||
|
{
|
||||||
|
var a = d.Story.After;
|
||||||
|
if (a.Verdict < 0 || a.TrialMarket || day < a.TrialOpenDay || day >= a.TrialDay) return;
|
||||||
|
a.TrialMarket = true;
|
||||||
|
var bk = d.Predict;
|
||||||
|
var m = PredictMarket.Create(++bk.Seq, PredictKind.Trial, "tumbler", "Tumbler", 0, day, a.TrialDay, a.TrialDay, Tuning.TumblerTrialConvict);
|
||||||
|
bk.Markets.Add(m);
|
||||||
|
Log.Info($"审判盘开盘 #{m.Id}:第 {a.TrialDay} 天宣判");
|
||||||
|
}
|
||||||
|
|
||||||
// ——— 公开信息下的合理概率(盘口夜里向它靠拢) ———
|
// ——— 公开信息下的合理概率(盘口夜里向它靠拢) ———
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -203,6 +216,8 @@ namespace Decentralized
|
|||||||
return PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard);
|
return PredictMath.CraWarnProb(d.Stable.Cushion, CraDrain(d), day + 1, m.FromDay, m.ToDay, CraHazard);
|
||||||
case PredictKind.Era:
|
case PredictKind.Era:
|
||||||
return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1);
|
return PredictMath.EraProb(day, m.FromDay, m.ToDay, d.Network.EraWarned ? d.Network.EraWarnDay : -1);
|
||||||
|
case PredictKind.Trial:
|
||||||
|
return d.Story.After.TrialPublic();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -222,6 +237,7 @@ namespace Decentralized
|
|||||||
case PredictKind.Gas: return CloseGas >= m.Param;
|
case PredictKind.Gas: return CloseGas >= m.Param;
|
||||||
case PredictKind.Cra: return d.Stable.CraWarnDay >= m.FromDay && d.Stable.CraWarnDay <= m.ToDay;
|
case PredictKind.Cra: return d.Stable.CraWarnDay >= m.FromDay && d.Stable.CraWarnDay <= m.ToDay;
|
||||||
case PredictKind.Era: return d.Network.EraDay < 0 ? (bool?)null : d.Network.EraDay >= m.FromDay && d.Network.EraDay <= m.ToDay;
|
case PredictKind.Era: return d.Network.EraDay < 0 ? (bool?)null : d.Network.EraDay >= m.FromDay && d.Network.EraDay <= m.ToDay;
|
||||||
|
case PredictKind.Trial: return d.Story.After.Verdict < 0 ? (bool?)null : d.Story.After.Verdict == 1;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -234,6 +250,7 @@ namespace Decentralized
|
|||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
if (m.Kind == PredictKind.Faction) return QueuedStart(m, false) != null;
|
if (m.Kind == PredictKind.Faction) return QueuedStart(m, false) != null;
|
||||||
if (m.Kind == PredictKind.Era) return d.Network.EraDay > 0 ? d.Network.EraDay >= m.FromDay && d.Network.EraDay <= m.ToDay : (bool?)null;
|
if (m.Kind == PredictKind.Era) return d.Network.EraDay > 0 ? d.Network.EraDay >= m.FromDay && d.Network.EraDay <= m.ToDay : (bool?)null;
|
||||||
|
if (m.Kind == PredictKind.Trial) return d.Story.After.Verdict < 0 ? (bool?)null : d.Story.After.Verdict == 1;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,6 +275,7 @@ namespace Decentralized
|
|||||||
case PredictKind.Gas: return L.T("predict.q.gas", win, Fmt.Num(m.Param));
|
case PredictKind.Gas: return L.T("predict.q.gas", win, Fmt.Num(m.Param));
|
||||||
case PredictKind.Cra: return L.T("predict.q.cra", win);
|
case PredictKind.Cra: return L.T("predict.q.cra", win);
|
||||||
case PredictKind.Era: return L.T("predict.q.era", win);
|
case PredictKind.Era: return L.T("predict.q.era", win);
|
||||||
|
case PredictKind.Trial: return L.T("predict.q.trial", win);
|
||||||
default: return L.T("predict.q.price", win, m.Title, Fmt.Num(m.Param));
|
default: return L.T("predict.q.price", win, m.Title, Fmt.Num(m.Param));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,6 +330,12 @@ namespace Decentralized
|
|||||||
list.Add(L.T("predict.clue.subsidy", (d.Stable.Cushion / Stablecoins.Cushion0 * 100).ToString("0")));
|
list.Add(L.T("predict.clue.subsidy", (d.Stable.Cushion / Stablecoins.Cushion0 * 100).ToString("0")));
|
||||||
list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d))));
|
list.Add(L.T("predict.clue.drain", Fmt.Num(CraDrain(d))));
|
||||||
break;
|
break;
|
||||||
|
case PredictKind.Trial:
|
||||||
|
{
|
||||||
|
var a = d.Story.After;
|
||||||
|
if (a.Hints.Count > 0) list.Add(L.T("predict.clue.trial", a.Hints.Count(h => h), a.Hints.Count(h => !h)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PredictKind.Era:
|
case PredictKind.Era:
|
||||||
list.Add(d.Network.EraWarned ? L.T("predict.clue.era.warned", d.Network.EraWarnDay + Tuning.EraWarnMin, d.Network.EraWarnDay + Tuning.EraWarnMax) : L.T("predict.clue.era", Tuning.EraMin, Tuning.EraMax));
|
list.Add(d.Network.EraWarned ? L.T("predict.clue.era.warned", d.Network.EraWarnDay + Tuning.EraWarnMin, d.Network.EraWarnDay + Tuning.EraWarnMax) : L.T("predict.clue.era", Tuning.EraMin, Tuning.EraMax));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ namespace Decentralized
|
|||||||
/// <summary>一局的 mod 状态。整体序列化成 JSON 存进游戏的 mod 存档数据;显卡的健康度等存在显卡物品的标签上。</summary>
|
/// <summary>一局的 mod 状态。整体序列化成 JSON 存进游戏的 mod 存档数据;显卡的健康度等存在显卡物品的标签上。</summary>
|
||||||
public sealed class SaveData
|
public sealed class SaveData
|
||||||
{
|
{
|
||||||
/// <summary>存档数据的版本:2 起保险基金用新的数值,3 起 Poinbase 主池是订单簿,4 起出块奖励和 NPC 算力 ×10(第十一阶段)。</summary>
|
/// <summary>存档数据的版本:2 起保险基金用新的数值,3 起 Poinbase 主池是订单簿,4 起出块奖励和 NPC 算力 ×10(第十一阶段),5 起 Poinbase 没有污点。</summary>
|
||||||
public int Version = 4;
|
public int Version = 5;
|
||||||
public int Day;
|
public int Day;
|
||||||
public Rng Rng = new Rng((ulong)DateTime.UtcNow.Ticks);
|
public Rng Rng = new Rng((ulong)DateTime.UtcNow.Ticks);
|
||||||
public Market Market;
|
public Market Market;
|
||||||
@@ -201,6 +201,13 @@ namespace Decentralized
|
|||||||
Data.Version = 4;
|
Data.Version = 4;
|
||||||
Log.Info($"存档数据升级到版本 4:出块奖励 {Data.Network.Reward:0}、NPC 算力 {Data.Network.NpcHash:0}");
|
Log.Info($"存档数据升级到版本 4:出块奖励 {Data.Network.Reward:0}、NPC 算力 {Data.Network.NpcHash:0}");
|
||||||
}
|
}
|
||||||
|
// 第十一阶段 stage 5:污点按币种记脏枚数、只在钱包里。旧的污点额按当前价格摊成脏枚数;Poinbase 账户和永续仓位的挪到 1 号钱包
|
||||||
|
if (Data.Version < 5)
|
||||||
|
{
|
||||||
|
double was = TaintMigration.Run(Data.Wallets, Data.Poinbase, Data.Perps.Positions, Data.Mixer, Data.Black, Data.Staking, Data.Scams, Data.Predict, Data.OwnMix ?? new OwnMixer(), Price);
|
||||||
|
Data.Version = 5;
|
||||||
|
Log.Info($"存档数据升级到版本 5:旧污点 {was:0} 摊成各币的脏枚数,现在按现价共 {Data.Wallets.Sum(w => w.Taint(Price)):0}");
|
||||||
|
}
|
||||||
if (Data.Otc == null) Data.Otc = new OtcDesk();
|
if (Data.Otc == null) Data.Otc = new OtcDesk();
|
||||||
if (Data.OwnMix == null) Data.OwnMix = new OwnMixer();
|
if (Data.OwnMix == null) Data.OwnMix = new OwnMixer();
|
||||||
if (Data.Story == null) Data.Story = new StoryMods();
|
if (Data.Story == null) Data.Story = new StoryMods();
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ namespace Decentralized
|
|||||||
Summary = L.T("ownmix.withdraw.sum", Fmt.Num(v), asset),
|
Summary = L.T("ownmix.withdraw.sum", Fmt.Num(v), asset),
|
||||||
Execute = pw =>
|
Execute = pw =>
|
||||||
{
|
{
|
||||||
if (!m.Withdraw(pw, asset, v, Session.Price, out double over)) { _message = L.T("ownmix.err"); Open(); return; }
|
if (!m.Withdraw(pw, asset, v)) { _message = L.T("ownmix.err"); Open(); return; }
|
||||||
_message = L.T("ownmix.withdrawn", Fmt.Num(v), asset) + TaintCrime.Commit(over);
|
_message = L.T("ownmix.withdrawn", Fmt.Num(v), asset);
|
||||||
Log.Info($"自营混币器取回 {v} {asset},钱包污点 {pw.Taint:0},超出 {over:0}");
|
Log.Info($"自营混币器取回 {v} {asset},钱包里 {asset} 脏 {pw.DirtyOf(asset):0.##}");
|
||||||
Session.Save(); Open();
|
Session.Save(); Open();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -123,11 +123,11 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
if (m.Closed) return;
|
if (m.Closed) return;
|
||||||
double value = OwnMixer.AssetsList.Sum(a => m.Total(a) * Session.Price(a));
|
double value = OwnMixer.AssetsList.Sum(a => m.Total(a) * Session.Price(a));
|
||||||
m.Rug(pw, Session.Price, out double over);
|
m.Rug(pw);
|
||||||
PlayerStore.Instance.secData.CommitCrime("FRAUD", (int)Tuning.OwnMixRugCrime);
|
PlayerStore.Instance.secData.CommitCrime("FRAUD", (int)Tuning.OwnMixRugCrime);
|
||||||
StoreReputation.ModReputation(StoreReputation.FACTION_BLACK_MARKET, -Tuning.OwnMixRugRep);
|
StoreReputation.ModReputation(StoreReputation.FACTION_BLACK_MARKET, -Tuning.OwnMixRugRep);
|
||||||
News.Show("pd_news_ownmix_rug_" + StoreStation.GetDayCounter(), L.T("news.ownmix.rug.title"), L.T("news.ownmix.rug.desc"), 4);
|
News.Show("pd_news_ownmix_rug_" + StoreStation.GetDayCounter(), L.T("news.ownmix.rug.title"), L.T("news.ownmix.rug.desc"), 4);
|
||||||
_message = L.T("ownmix.rugged", Fmt.Credits(value)) + TaintCrime.Commit(over);
|
_message = L.T("ownmix.rugged", Fmt.Credits(value));
|
||||||
Log.Info($"自营混币器卷款跑路:{value:0},钱包 {pw.Address}");
|
Log.Info($"自营混币器卷款跑路:{value:0},钱包 {pw.Address}");
|
||||||
Session.Save(); Open();
|
Session.Save(); Open();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -391,16 +391,6 @@ namespace Decentralized
|
|||||||
TableRow(b, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Poinbase.Get(Assets.CRC)));
|
TableRow(b, w, L.T("bank.crc.k"), Fmt.Num(Session.Data.Poinbase.Get(Assets.CRC)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>提取前的合规审查提示:仅保留账户污点比例(额度与命中概率按设计不公开)。</summary>
|
|
||||||
private static void AmlPreview(CustomUIBuilder b)
|
|
||||||
{
|
|
||||||
var pb = Session.Data.Poinbase;
|
|
||||||
double total = pb.Value(Session.Price);
|
|
||||||
double taintRatio = total > 0 ? pb.Taint / total : 0;
|
|
||||||
b.AddSeparator();
|
|
||||||
b.AddLabel(L.T("aml.taint", (int)Math.Round(taintRatio * 100)), taintRatio > 0.05 ? "aml_note" : "aml_dim");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string StableStatus(Stablecoins st, string asset, int day)
|
private static string StableStatus(Stablecoins st, string asset, int day)
|
||||||
{
|
{
|
||||||
double p = st.Price(asset);
|
double p = st.Price(asset);
|
||||||
@@ -476,8 +466,8 @@ namespace Decentralized
|
|||||||
if (got <= 0) { _message = L.T("swap.same"); Open(); return; }
|
if (got <= 0) { _message = L.T("swap.same"); Open(); return; }
|
||||||
double spent = v * Session.Price(from);
|
double spent = v * Session.Price(from);
|
||||||
CandleChart.Trade(from, spent); CandleChart.Trade(to, spent);
|
CandleChart.Trade(from, spent); CandleChart.Trade(to, spent);
|
||||||
w.Add(from, -v);
|
// 换来的币继承付出那种币的脏比例
|
||||||
w.Add(to, got);
|
w.Convert(from, v, to, got);
|
||||||
w.RecordBuy(to, got, spent);
|
w.RecordBuy(to, got, spent);
|
||||||
_message = L.T("msg.trade", Fmt.Num(v), from, Fmt.Num(got), to);
|
_message = L.T("msg.trade", Fmt.Num(v), from, Fmt.Num(got), to);
|
||||||
Session.Save();
|
Session.Save();
|
||||||
@@ -513,18 +503,27 @@ namespace Decentralized
|
|||||||
private static readonly float[] HoldWBase = new[] { 80f, 100f, 110f, 110f };
|
private static readonly float[] HoldWBase = new[] { 80f, 100f, 110f, 110f };
|
||||||
private static float[] HoldW => Sc(HoldWBase);
|
private static float[] HoldW => Sc(HoldWBase);
|
||||||
private static readonly TextAnchor[] HoldAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
private static readonly TextAnchor[] HoldAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||||
|
/// <summary>钱包的持仓表多一列“其中脏的”(Poinbase 没有污点,不显示)。</summary>
|
||||||
|
private static readonly float[] HoldDWBase = new[] { 60f, 85f, 75f, 90f, 90f };
|
||||||
|
private static float[] HoldDW => Sc(HoldDWBase);
|
||||||
|
private static readonly TextAnchor[] HoldDAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||||
|
|
||||||
private static void Holdings(CustomUIBuilder b, Wallet w, Func<string, bool> show)
|
private static void Holdings(CustomUIBuilder b, Wallet w, Func<string, bool> show)
|
||||||
{
|
{
|
||||||
TableHeader(b, HoldW.Sum() + 8f, HoldW, HoldAligns, L.T("col.asset"), L.T("col.amount"), L.T("col.value"), L.T("col.avg"));
|
bool dirtyCol = w != Session.Data.Poinbase;
|
||||||
|
var hw = dirtyCol ? HoldDW : HoldW; var ha = dirtyCol ? HoldDAligns : HoldAligns;
|
||||||
|
if (dirtyCol) TableHeader(b, hw.Sum() + 8f, hw, ha, L.T("col.asset"), L.T("col.amount"), L.T("col.dirty"), L.T("col.value"), L.T("col.avg"));
|
||||||
|
else TableHeader(b, hw.Sum() + 8f, hw, ha, L.T("col.asset"), L.T("col.amount"), L.T("col.value"), L.T("col.avg"));
|
||||||
bool any = false;
|
bool any = false;
|
||||||
foreach (var kv in w.Balances.OrderBy(k => k.Key).Where(k => show(k.Key)))
|
foreach (var kv in w.Balances.OrderBy(k => k.Key).Where(k => show(k.Key)))
|
||||||
{
|
{
|
||||||
any = true;
|
any = true;
|
||||||
string asset = kv.Key;
|
string asset = kv.Key;
|
||||||
bool selected = (_page == Page.Poinbase && _poinTab == PoinTab.Funds && asset == _fundsAsset);
|
bool selected = (_page == Page.Poinbase && _poinTab == PoinTab.Funds && asset == _fundsAsset);
|
||||||
TableRow(b, HoldW.Sum() + 8f, HoldW, HoldAligns,
|
double dirty = w.DirtyOf(asset);
|
||||||
new[] { kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key) },
|
TableRow(b, hw.Sum() + 8f, hw, ha,
|
||||||
|
dirtyCol ? new[] { kv.Key, Fmt.Num(kv.Value), dirty > 1e-9 ? Fmt.Num(dirty) : "—", Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key) }
|
||||||
|
: new[] { kv.Key, Fmt.Num(kv.Value), Fmt.Credits(kv.Value * Session.Price(kv.Key)), AvgText(w, kv.Key) },
|
||||||
selected,
|
selected,
|
||||||
() => { if (_page == Page.Poinbase && _poinTab == PoinTab.Funds) { _fundsAsset = asset; if (asset != Assets.CRC) _fundsBank = false; Open(); } });
|
() => { if (_page == Page.Poinbase && _poinTab == PoinTab.Funds) { _fundsAsset = asset; if (asset != Assets.CRC) _fundsBank = false; Open(); } });
|
||||||
}
|
}
|
||||||
@@ -557,7 +556,6 @@ namespace Decentralized
|
|||||||
l.AddSeparator();
|
l.AddSeparator();
|
||||||
l.AddHeader(L.T("poin.account.h"));
|
l.AddHeader(L.T("poin.account.h"));
|
||||||
Holdings(l, w, a => true);
|
Holdings(l, w, a => true);
|
||||||
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
|
|
||||||
}, r =>
|
}, r =>
|
||||||
{
|
{
|
||||||
// 交易对跟着行情图选中的币(CRC 本身没有交易对,显示 PSC/CRC)
|
// 交易对跟着行情图选中的币(CRC 本身没有交易对,显示 PSC/CRC)
|
||||||
@@ -584,7 +582,6 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
l.AddHeader(L.T("poin.account.h"));
|
l.AddHeader(L.T("poin.account.h"));
|
||||||
Holdings(l, w, a => true);
|
Holdings(l, w, a => true);
|
||||||
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
|
|
||||||
}, r =>
|
}, r =>
|
||||||
{
|
{
|
||||||
r.BeginRow(4f);
|
r.BeginRow(4f);
|
||||||
@@ -622,6 +619,9 @@ namespace Decentralized
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
r.AddLabel(L.T("poin.deposit", d.Address("poinbase")), "deposit_dim");
|
r.AddLabel(L.T("poin.deposit", d.Address("poinbase")), "deposit_dim");
|
||||||
|
// 只收干净的币:连着的钱包里有脏币时,写明每种币能充多少
|
||||||
|
if (d.Connected && Exchange.Listed.Any(a => d.Hot.DirtyOf(a) > 1e-9))
|
||||||
|
r.AddLabel(L.T("poin.deposit.clean", WalletWindow.NameOf(d.Hot), string.Join(" ", Exchange.Listed.Where(a => d.Hot.Get(a) > 1e-9).Select(a => Fmt.Num(d.Hot.CleanAvail(a)) + " " + a))), "taint_note");
|
||||||
r.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(d.Address("poinbase")); _message = L.T("hw.copied.addr", d.Address("poinbase")); Open(); });
|
r.AddButton(L.T("hw.copy"), () => { Clipboard.Copy(d.Address("poinbase")); _message = L.T("hw.copied.addr", d.Address("poinbase")); Open(); });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -629,7 +629,6 @@ namespace Decentralized
|
|||||||
if (_fundsBank)
|
if (_fundsBank)
|
||||||
{
|
{
|
||||||
AmountRow(r);
|
AmountRow(r);
|
||||||
AmlPreview(r);
|
|
||||||
r.AddButton(L.T("trade.withdraw"), Withdraw);
|
r.AddButton(L.T("trade.withdraw"), Withdraw);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1309,12 +1308,12 @@ namespace Decentralized
|
|||||||
Summary = L.T("predict.sum.sell", PredictGame.Question(m)),
|
Summary = L.T("predict.sum.sell", PredictGame.Question(m)),
|
||||||
Execute = pw =>
|
Execute = pw =>
|
||||||
{
|
{
|
||||||
var res = d.Predict.SellAll(pw, m, StoreStation.GetDayCounter(), Session.Price, out double got, out double taint, out double over);
|
var res = d.Predict.SellAll(pw, m, StoreStation.GetDayCounter(), Session.Price, out double got, out double taint);
|
||||||
_message = res == PredictResult.Ok ? L.T("predict.sold", Fmt.Num(got)) : L.T("predict.err." + res);
|
_message = res == PredictResult.Ok ? L.T("predict.sold", Fmt.Num(got)) : L.T("predict.err." + res);
|
||||||
if (res == PredictResult.Ok && taint + over > 1e-9)
|
if (res == PredictResult.Ok && taint > 1e-9)
|
||||||
{
|
{
|
||||||
_message = L.T("predict.sold.caught", Fmt.Num(got), Fmt.Credits(taint)) + TaintCrime.Commit(over);
|
_message = L.T("predict.sold.caught", Fmt.Num(got), Fmt.Num(taint));
|
||||||
Log.Info($"内幕卖出:收回 {got:0},污点 +{taint:0},超出 {over:0}");
|
Log.Info($"内幕卖出:收回 {got:0},其中 {taint:0.##} CRC 记为脏的");
|
||||||
}
|
}
|
||||||
if (res == PredictResult.Ok) Session.Save();
|
if (res == PredictResult.Ok) Session.Save();
|
||||||
Open();
|
Open();
|
||||||
@@ -1353,16 +1352,17 @@ namespace Decentralized
|
|||||||
double margin = pos.Margin;
|
double margin = pos.Margin;
|
||||||
CandleChart.Trade(_perpProduct, pos.Notional(PerpSpot(_perpProduct)));
|
CandleChart.Trade(_perpProduct, pos.Notional(PerpSpot(_perpProduct)));
|
||||||
double paid = d.Perps.Close(d.Poinbase, _perpProduct, PerpSpot(_perpProduct), StoreStation.GetDayCounter(), out double deficit);
|
double paid = d.Perps.Close(d.Poinbase, _perpProduct, PerpSpot(_perpProduct), StoreStation.GetDayCounter(), out double deficit);
|
||||||
// 操纵:平仓盈利,而且盈利方向和玩家自己推价的方向一致,按推价幅度被查:盈利照常留在 Poinbase 账户,这笔盈利记污点(带上限)
|
// 操纵:平仓盈利,而且盈利方向和玩家自己推价的方向一致,按推价幅度被查:盈利照常留在 Poinbase 账户,只记诈骗罪证
|
||||||
double push = d.Market.PlayerPush, profit = paid - margin;
|
double push = d.Market.PlayerPush, profit = paid - margin;
|
||||||
bool aligned = _perpProduct == "PSC" && profit > 0 && (pos.Long ? push > 0 : push < 0);
|
bool aligned = _perpProduct == "PSC" && profit > 0 && (pos.Long ? push > 0 : push < 0);
|
||||||
if (aligned && d.Rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(StoreStation.GetDayCounter()))))
|
if (aligned && d.Rng.Chance(Math.Min(1, Market.ManipChance(push) * StoryMods.Current.Enforce(StoreStation.GetDayCounter()))))
|
||||||
{
|
{
|
||||||
int day = StoreStation.GetDayCounter();
|
int day = StoreStation.GetDayCounter();
|
||||||
double over = d.Poinbase.AddTaintCapped(profit, Session.Price);
|
int fraud = (int)Math.Round(Wallet.FraudFor(profit));
|
||||||
|
if (fraud > 0) PlayerStore.Instance.secData.CommitCrime("FRAUD", fraud);
|
||||||
News.Show("pd_news_manip_" + day, L.T("news.manip.title"), L.T("news.manip.desc"), 3);
|
News.Show("pd_news_manip_" + day, L.T("news.manip.title"), L.T("news.manip.desc"), 3);
|
||||||
_message = L.T("perp.manip", Fmt.Credits(profit), Fmt.Credits(profit - over)) + TaintCrime.Commit(over);
|
_message = L.T("perp.manip", Fmt.Credits(profit), fraud);
|
||||||
Log.Info($"永续操纵被查:盈利 {profit:0} 记污点 {profit - over:0},超出 {over:0},推价 {push:0.000}");
|
Log.Info($"永续操纵被查:盈利 {profit:0},记诈骗罪证 {fraud},推价 {push:0.000}");
|
||||||
Session.Save();
|
Session.Save();
|
||||||
Open();
|
Open();
|
||||||
return;
|
return;
|
||||||
@@ -1410,7 +1410,7 @@ namespace Decentralized
|
|||||||
Cell(b, cols[0], (isCurrent ? "● " : "") + WalletWindow.NameOf(w), false, TextAnchor.MiddleLeft);
|
Cell(b, cols[0], (isCurrent ? "● " : "") + WalletWindow.NameOf(w), false, TextAnchor.MiddleLeft);
|
||||||
Cell(b, cols[1], w.Address, false, TextAnchor.MiddleLeft);
|
Cell(b, cols[1], w.Address, false, TextAnchor.MiddleLeft);
|
||||||
Cell(b, cols[2], Fmt.Credits(w.Value(Session.Price)), false, TextAnchor.MiddleRight);
|
Cell(b, cols[2], Fmt.Credits(w.Value(Session.Price)), false, TextAnchor.MiddleRight);
|
||||||
Cell(b, cols[3], Fmt.Credits(w.Taint), false, TextAnchor.MiddleRight);
|
Cell(b, cols[3], Fmt.Credits(w.Taint(Session.Price)), false, TextAnchor.MiddleRight);
|
||||||
b.End();
|
b.End();
|
||||||
b.End();
|
b.End();
|
||||||
b.BeginPanel(cols[4] - btnCut * k, 32f * F, TextAnchor.MiddleLeft, 0f, 0f);
|
b.BeginPanel(cols[4] - btnCut * k, 32f * F, TextAnchor.MiddleLeft, 0f, 0f);
|
||||||
@@ -1573,7 +1573,7 @@ namespace Decentralized
|
|||||||
Holdings(l, w, a => true);
|
Holdings(l, w, a => true);
|
||||||
l.AddSeparator();
|
l.AddSeparator();
|
||||||
l.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price))));
|
l.AddLabel(L.T("wallet.total", Fmt.Credits(w.Value(Session.Price))));
|
||||||
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
|
if (w.Taint(Session.Price) > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint(Session.Price))), "taint_note");
|
||||||
PriceTable(l);
|
PriceTable(l);
|
||||||
l.AddSeparator();
|
l.AddSeparator();
|
||||||
CandleChart.AddPicker(l, "web3", Assets.PSC, Open, _picked);
|
CandleChart.AddPicker(l, "web3", Assets.PSC, Open, _picked);
|
||||||
@@ -1643,7 +1643,8 @@ namespace Decentralized
|
|||||||
if (key.StartsWith("otc:")) return L.T("otc.name");
|
if (key.StartsWith("otc:")) return L.T("otc.name");
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case "mixer": return L.T("explorer.mixer");
|
case "mixer": return d.Story.MixerRebranded ? L.T("mixer.brand") : L.T("explorer.mixer");
|
||||||
|
case "mixer_old": return L.T("explorer.mixer");
|
||||||
case "platform": return L.T("merchant.Platform");
|
case "platform": return L.T("merchant.Platform");
|
||||||
case "desk": return L.T("explorer.desk");
|
case "desk": return L.T("explorer.desk");
|
||||||
case "dex": return "DEX";
|
case "dex": return "DEX";
|
||||||
@@ -1766,7 +1767,7 @@ namespace Decentralized
|
|||||||
var sellers = d.Black.Sellers;
|
var sellers = d.Black.Sellers;
|
||||||
if (_merchant >= sellers.Count) _merchant = -1;
|
if (_merchant >= sellers.Count) _merchant = -1;
|
||||||
bool platform = _merchant < 0;
|
bool platform = _merchant < 0;
|
||||||
b.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)) + (w.Taint > 0.5 ? " " + L.T("wallet.taint", Fmt.Credits(w.Taint)) : ""), "black_rep_dim");
|
b.AddLabel(L.T("black.rep", rep, BlackMarket.MaxLevel(rep)) + (w.Taint(Session.Price) > 0.5 ? " " + L.T("wallet.taint", Fmt.Credits(w.Taint(Session.Price))) : ""), "black_rep_dim");
|
||||||
b.BeginRow(8f, TextAnchor.UpperLeft);
|
b.BeginRow(8f, TextAnchor.UpperLeft);
|
||||||
b.BeginPanel(SellerW + 8f, -1f, TextAnchor.UpperLeft, 0f, 2f);
|
b.BeginPanel(SellerW + 8f, -1f, TextAnchor.UpperLeft, 0f, 2f);
|
||||||
_clear.Add(b.Last.image);
|
_clear.Add(b.Last.image);
|
||||||
@@ -2277,7 +2278,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
if (pw.Avail(src) + 1e-9 < needSrc) { Finish(L.T("msg.balance")); return; }
|
if (pw.Avail(src) + 1e-9 < needSrc) { Finish(L.T("msg.balance")); return; }
|
||||||
double got = credits / Session.Price(coin) * 1.002;
|
double got = credits / Session.Price(coin) * 1.002;
|
||||||
pw.Add(src, -needSrc); pw.Add(coin, got); pw.RecordBuy(coin, got, credits);
|
pw.Convert(src, needSrc, coin, got); pw.RecordBuy(coin, got, credits);
|
||||||
CandleChart.Trade(src, credits); CandleChart.Trade(coin, credits);
|
CandleChart.Trade(src, credits); CandleChart.Trade(coin, credits);
|
||||||
Log.Info($"自动换币:{needSrc:0.####} {src} → {got:0.####} {coin}({credits:0} 信用点等值)");
|
Log.Info($"自动换币:{needSrc:0.####} {src} → {got:0.####} {coin}({credits:0} 信用点等值)");
|
||||||
// 一次签名两步:经 DEX 换币,再付给这家商家;分别记账
|
// 一次签名两步:经 DEX 换币,再付给这家商家;分别记账
|
||||||
@@ -2511,8 +2512,6 @@ namespace Decentralized
|
|||||||
double got = _deskIn ? d.Black.ToPonero(pw, _deskAsset, v, day, Session.Price) : d.Black.FromPonero(pw, _deskAsset, v, day, Session.Price);
|
double got = _deskIn ? d.Black.ToPonero(pw, _deskAsset, v, day, Session.Price) : d.Black.FromPonero(pw, _deskAsset, v, day, Session.Price);
|
||||||
if (got < 0) { _message = L.T("black.desk.fail"); Open(); return; }
|
if (got < 0) { _message = L.T("black.desk.fail"); Open(); return; }
|
||||||
{ double cr = v * Session.Price(_deskIn ? _deskAsset : Assets.Ponero); CandleChart.Trade(Assets.Ponero, cr); CandleChart.Trade(_deskAsset, cr); }
|
{ double cr = v * Session.Price(_deskIn ? _deskAsset : Assets.Ponero); CandleChart.Trade(Assets.Ponero, cr); CandleChart.Trade(_deskAsset, cr); }
|
||||||
// 从 Ponero 出来的币来源不明:出金审查按"来自混币器"加重
|
|
||||||
if (!_deskIn) d.Mixer.LastReturnDay = day;
|
|
||||||
_message = _deskIn ? L.T("msg.trade", Fmt.Num(v), _deskAsset, Fmt.Num(got), Assets.Ponero) : L.T("msg.trade", Fmt.Num(v), Assets.Ponero, Fmt.Num(got), _deskAsset);
|
_message = _deskIn ? L.T("msg.trade", Fmt.Num(v), _deskAsset, Fmt.Num(got), Assets.Ponero) : L.T("msg.trade", Fmt.Num(v), Assets.Ponero, Fmt.Num(got), _deskAsset);
|
||||||
Session.Save();
|
Session.Save();
|
||||||
Open();
|
Open();
|
||||||
@@ -2534,9 +2533,9 @@ namespace Decentralized
|
|||||||
int day = StoreStation.GetDayCounter();
|
int day = StoreStation.GetDayCounter();
|
||||||
Columns(b, l =>
|
Columns(b, l =>
|
||||||
{
|
{
|
||||||
l.AddHeader(L.T("mixer.h"));
|
l.AddHeader(d.Story.MixerRebranded ? L.T("mixer.brand") : L.T("mixer.h"));
|
||||||
l.AddLabel(d.Story.MixerClosed ? L.T("mixer.status.closed") : d.Mixer.Sanctioned(day) ? L.T("mixer.sanctioned", d.Mixer.SanctionedUntil - day + 1) : L.T("mixer.ok"), d.Story.MixerClosed || d.Mixer.Sanctioned(day) ? "mixer_status_note" : "mixer_status_dim");
|
l.AddLabel(d.Story.MixerClosed ? L.T("mixer.status.closed") : d.Mixer.Sanctioned(day) ? L.T("mixer.sanctioned", d.Mixer.SanctionedUntil - day + 1) : L.T("mixer.ok"), d.Story.MixerClosed || d.Mixer.Sanctioned(day) ? "mixer_status_note" : "mixer_status_dim");
|
||||||
if (w.Taint > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)), "taint_note");
|
if (w.Taint(Session.Price) > 0.5) l.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint(Session.Price))), "taint_note");
|
||||||
l.AddSeparator();
|
l.AddSeparator();
|
||||||
l.AddHeader(L.T("mixer.pending"));
|
l.AddHeader(L.T("mixer.pending"));
|
||||||
if (d.Mixer.Pending.Count == 0) l.AddLabel(L.T("mixer.none"), "mixer_none_dim");
|
if (d.Mixer.Pending.Count == 0) l.AddLabel(L.T("mixer.none"), "mixer_none_dim");
|
||||||
@@ -2544,7 +2543,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
TableHeader(l, MixW.Sum() + 8f, MixW, MixAligns, L.T("col.asset"), L.T("col.amount"), L.T("mixer.col.taint"), L.T("mixer.col.ready"));
|
TableHeader(l, MixW.Sum() + 8f, MixW, MixAligns, L.T("col.asset"), L.T("col.amount"), L.T("mixer.col.taint"), L.T("mixer.col.ready"));
|
||||||
foreach (var p in d.Mixer.Pending)
|
foreach (var p in d.Mixer.Pending)
|
||||||
TableRow(l, MixW.Sum() + 8f, MixW, MixAligns, new[] { p.Asset, Fmt.Num(p.Amount), Fmt.Credits(p.Taint), L.T("mixer.day", p.ReadyDay) });
|
TableRow(l, MixW.Sum() + 8f, MixW, MixAligns, new[] { p.Asset, Fmt.Num(p.Amount), p.Dirty > 1e-9 ? Fmt.Num(p.Dirty) : "—", L.T("mixer.day", p.ReadyDay) });
|
||||||
}
|
}
|
||||||
}, r =>
|
}, r =>
|
||||||
{
|
{
|
||||||
@@ -2569,7 +2568,7 @@ namespace Decentralized
|
|||||||
r.End();
|
r.End();
|
||||||
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double v) && v > 0)
|
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double v) && v > 0)
|
||||||
{
|
{
|
||||||
double rate = Mixer.RoundRate(v * Session.Price(_mixAsset));
|
double rate = Mixer.RoundRate(v * Session.Price(_mixAsset), day);
|
||||||
r.AddLabel(L.T("mixer.preview", Fmt.Num(v * Math.Pow(1 - Mixer.Fee, _mixRounds)), _mixAsset, (int)Math.Round((1 - Math.Pow(1 - rate, _mixRounds)) * 100), day + _mixRounds), "mixer_preview_dim");
|
r.AddLabel(L.T("mixer.preview", Fmt.Num(v * Math.Pow(1 - Mixer.Fee, _mixRounds)), _mixAsset, (int)Math.Round((1 - Math.Pow(1 - rate, _mixRounds)) * 100), day + _mixRounds), "mixer_preview_dim");
|
||||||
}
|
}
|
||||||
r.AddButton(L.T("mixer.go"), () =>
|
r.AddButton(L.T("mixer.go"), () =>
|
||||||
@@ -2694,7 +2693,7 @@ namespace Decentralized
|
|||||||
if (pw.Avail(coin) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
if (pw.Avail(coin) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||||
double spent = v * Session.Price(coin);
|
double spent = v * Session.Price(coin);
|
||||||
cra = d.Market.Swap(coin, Assets.CRA, v);
|
cra = d.Market.Swap(coin, Assets.CRA, v);
|
||||||
pw.Add(coin, -v); pw.Add(Assets.CRA, cra); pw.RecordBuy(Assets.CRA, cra, spent);
|
pw.Convert(coin, v, Assets.CRA, cra); pw.RecordBuy(Assets.CRA, cra, spent);
|
||||||
CandleChart.Trade(coin, spent); CandleChart.Trade(Assets.CRA, spent);
|
CandleChart.Trade(coin, spent); CandleChart.Trade(Assets.CRA, spent);
|
||||||
}
|
}
|
||||||
bool ok = into ? d.Staking.Stake(pw, cra, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
bool ok = into ? d.Staking.Stake(pw, cra, Session.Price) : d.Staking.RequestUnstake(pw.Address, v, day);
|
||||||
@@ -2783,16 +2782,10 @@ namespace Decentralized
|
|||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
if (d.Perps.Debt > 0) { _message = L.T("perp.debt.block"); Open(); return; }
|
if (d.Perps.Debt > 0) { _message = L.T("perp.debt.block"); Open(); return; }
|
||||||
if (d.Poinbase.Avail(Assets.CRC) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
if (d.Poinbase.Avail(Assets.CRC) + 1e-9 < v) { _message = L.T("msg.balance"); Open(); return; }
|
||||||
var r = d.Exchange.Cashout(d.Poinbase, v, Session.Price, StoreStation.GetDayCounter(), Session.Rent(), d.Mixer.RecentlyMixed(StoreStation.GetDayCounter()), d.Rng);
|
var r = d.Exchange.Cashout(d.Poinbase, v, Session.Price);
|
||||||
int got = (int)Math.Floor(r.Received - r.Tax);
|
int got = (int)Math.Floor(r.Received - r.Tax);
|
||||||
ModHelper.AddCredit(got, true);
|
ModHelper.AddCredit(got, true);
|
||||||
_message = L.T("msg.cashout", got, Fmt.Credits(r.Tax));
|
_message = L.T("msg.cashout", got, Fmt.Credits(r.Tax));
|
||||||
if (r.Outcome == AmlOutcome.Light) _message += "\n" + L.T("msg.aml_light", Fmt.Credits(r.Confiscated));
|
|
||||||
if (r.Outcome == AmlOutcome.Heavy)
|
|
||||||
{
|
|
||||||
_message += "\n" + L.T("msg.aml_heavy", Fmt.Credits(r.Confiscated));
|
|
||||||
PlayerStore.Instance.secData.CommitCrime("FENCING", (int)Math.Round(r.Crime));
|
|
||||||
}
|
|
||||||
Session.Save();
|
Session.Save();
|
||||||
Open();
|
Open();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Decentralized.Domain;
|
using Decentralized.Domain;
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ namespace Decentralized
|
|||||||
/// 本 mod 自己的剧情线:混币器运营者 Tumbler。解锁混币器、第 30 天起,四次上门(游戏的对话顾客):
|
/// 本 mod 自己的剧情线:混币器运营者 Tumbler。解锁混币器、第 30 天起,四次上门(游戏的对话顾客):
|
||||||
/// 1 自我介绍;2 说治安部在查混币服务(当晚混币器被制裁几天);3 求你藏密钥盘,三选一(藏 / 举报 / 卖给黑市);4 结局。
|
/// 1 自我介绍;2 说治安部在查混币服务(当晚混币器被制裁几天);3 求你藏密钥盘,三选一(藏 / 举报 / 卖给黑市);4 结局。
|
||||||
/// 进度存在 <see cref="StoryMods.Tumbler"/>,结果改动混币器(见 <see cref="StoryMods.Apply"/>)。
|
/// 进度存在 <see cref="StoryMods.Tumbler"/>,结果改动混币器(见 <see cref="StoryMods.Apply"/>)。
|
||||||
|
/// 之后的剧情(<see cref="TumblerAfter"/>):治安部探员、搜查、密钥泄露、审判盘、黑市跑路、报复、长期联系人、换皮重开。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class TumblerStory
|
public static class TumblerStory
|
||||||
{
|
{
|
||||||
@@ -24,7 +26,16 @@ namespace Decentralized
|
|||||||
int day = StoreStation.GetDayCounter();
|
int day = StoreStation.GetDayCounter();
|
||||||
var t = d.Story.Tumbler;
|
var t = d.Story.Tumbler;
|
||||||
if (t.TryStart(day, Unlock.MixerUnlocked)) Log.Info($"Tumbler 剧情开始:第 {t.StartDay} 天第一次上门");
|
if (t.TryStart(day, Unlock.MixerUnlocked)) Log.Info($"Tumbler 剧情开始:第 {t.StartDay} 天第一次上门");
|
||||||
int due = t.Due(day);
|
var a = d.Story.After;
|
||||||
|
if (a.AgentDue(t, day) || a.SearchDue(t, day))
|
||||||
|
{
|
||||||
|
bool search = a.SearchDue(t, day);
|
||||||
|
manager.AddNextClient(search ? Search() : Agent());
|
||||||
|
Log.Info($"治安部探员上门({(search ? "搜查" : "问话")})");
|
||||||
|
Session.Save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int due = t.Due(day, a);
|
||||||
if (due == 0) return;
|
if (due == 0) return;
|
||||||
// 举报之后第 4 次不上门;其余的上门要等对话真正走完才算数(当天没聊完、被清场或读档重来,明天照样来)
|
// 举报之后第 4 次不上门;其余的上门要等对话真正走完才算数(当天没聊完、被清场或读档重来,明天照样来)
|
||||||
if (due == 4 && t.Choice == Tumbler.Report) { t.Visited(day); Log.Info("Tumbler 已被举报,不再上门"); Session.Save(); return; }
|
if (due == 4 && t.Choice == Tumbler.Report) { t.Visited(day); Log.Info("Tumbler 已被举报,不再上门"); Session.Save(); return; }
|
||||||
@@ -45,19 +56,206 @@ namespace Decentralized
|
|||||||
d.Mixer.SanctionedUntil = System.Math.Max(d.Mixer.SanctionedUntil, day + 4);
|
d.Mixer.SanctionedUntil = System.Math.Max(d.Mixer.SanctionedUntil, day + 4);
|
||||||
News.Show("pd_news_tumbler_sanction", L.T("news.tumbler.sanction.title"), L.T("news.tumbler.sanction.desc"), 3, 8);
|
News.Show("pd_news_tumbler_sanction", L.T("news.tumbler.sanction.title"), L.T("news.tumbler.sanction.desc"), 3, 8);
|
||||||
}
|
}
|
||||||
|
After(d, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>四次上门之后的夜间:泄露、庭审新闻与宣判、黑市跑路、报复、联系人的镇压提示、换皮重开。</summary>
|
||||||
|
private static void After(SaveData d, int day)
|
||||||
|
{
|
||||||
|
var a = d.Story.After;
|
||||||
|
var ps = PlayerStore.Instance;
|
||||||
|
if (a.LeakDay >= 0 && day >= a.LeakDay && !a.Leaked)
|
||||||
|
{
|
||||||
|
a.Leaked = true;
|
||||||
|
var r = d.Mixer.Leak(day);
|
||||||
|
int fraud = (int)Math.Round(r.Fraud);
|
||||||
|
if (fraud > 0) ps.secData.CommitCrime("FRAUD", fraud);
|
||||||
|
if (r.Count == 0) ps.AddNightLog(L.T("nightlog.tumbler.leak.none"));
|
||||||
|
else ps.AddNightLog(L.T("nightlog.tumbler.leak", r.Count, Fmt.Credits(r.Cleaned), fraud), "cc7755");
|
||||||
|
News.Show("pd_news_tumbler_leak", L.T("news.tumbler.leak.title"), L.T("news.tumbler.leak.desc"), 3, 8);
|
||||||
|
Log.Info($"Tumbler 密钥泄露:还原 {r.Count} 笔出款,洗掉的污点 {r.Cleaned:0},记诈骗罪证 {fraud}");
|
||||||
|
}
|
||||||
|
bool? hint = a.Hint(day, d.Rng);
|
||||||
|
if (hint != null)
|
||||||
|
{
|
||||||
|
int n = a.Hints.Count, v = (n - 1) % 3 + 1;
|
||||||
|
string side = hint.Value ? "pro" : "def";
|
||||||
|
News.Show("pd_news_trial_" + day, L.T("news.trial." + side + ".title", n), L.T("news.trial." + side + ".desc" + v), 1, 7);
|
||||||
|
Log.Info($"庭审第 {n} 天:{(hint.Value ? "控方" : "辩方")}占上风,公开定罪概率 {a.TrialPublic():0.00}(判决 {a.Verdict})");
|
||||||
|
}
|
||||||
|
if (a.Verdict >= 0 && !a.TrialDone && day >= a.TrialDay)
|
||||||
|
{
|
||||||
|
a.TrialDone = true;
|
||||||
|
if (a.Verdict == 1) News.Show("pd_news_trial_verdict", L.T("news.trial.convict.title"), L.T("news.trial.convict.desc"), 3, 8);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a.RevengeDay = day + Tuning.TumblerRevengeDelay;
|
||||||
|
News.Show("pd_news_trial_verdict", L.T("news.trial.acquit.title"), L.T("news.trial.acquit.desc"), 3, 8);
|
||||||
|
}
|
||||||
|
Log.Info($"Tumbler 宣判:{(a.Verdict == 1 ? "定罪" : "无罪")}");
|
||||||
|
}
|
||||||
|
if (a.BmRugDay >= 0 && day >= a.BmRugDay && !a.BmRugged)
|
||||||
|
{
|
||||||
|
a.BmRugged = true;
|
||||||
|
foreach (var m in d.Mixer.RugAll()) ps.AddNightLog(L.T("nightlog.mixer_rug", Fmt.Num(m.Amount), m.Asset), "cc7755");
|
||||||
|
d.Story.Apply("tumbler_bm_rug", day);
|
||||||
|
a.ClosedDay = day;
|
||||||
|
a.RevengeDay = day + Tuning.TumblerRevengeDelay;
|
||||||
|
News.Show("pd_news_tumbler_bmrug", L.T("news.tumbler.bmrug.title"), L.T("news.tumbler.bmrug.desc"), 4, 8);
|
||||||
|
Log.Info("黑市接手的混币器卷款跑路");
|
||||||
|
}
|
||||||
|
if (a.RevengeDay >= 0 && day >= a.RevengeDay && !a.Revenged)
|
||||||
|
{
|
||||||
|
a.Revenged = true;
|
||||||
|
Revenge(d, day);
|
||||||
|
}
|
||||||
|
if (a.Contact) Tip(d, day, a);
|
||||||
|
if (a.RebrandDue(day))
|
||||||
|
{
|
||||||
|
a.Rebranded = true;
|
||||||
|
bool honeypot = d.Rng.Chance(Tuning.TumblerHoneypot);
|
||||||
|
d.Story.Rebrand(honeypot);
|
||||||
|
d.Addresses["mixer_old"] = d.Address("mixer");
|
||||||
|
d.Addresses["mixer"] = ChainAddress.Make(d.Rng.NextUInt());
|
||||||
|
News.Show("pd_news_mixer_rebrand", L.T("news.mixer.rebrand.title", L.T("mixer.brand")), L.T("news.mixer.rebrand.desc", L.T("mixer.brand")), 4);
|
||||||
|
Log.Info($"混币器换皮重开:{L.T("mixer.brand")},钓鱼 {honeypot},费率 {Mixer.Fee:P1}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tumbler 报复:先留一张纸条。按概率给当前钱包植入木马(剪贴板劫持、钱够多后被转空,和商城的投毒钱包一样);
|
||||||
|
/// 否则每个钱包对最近的转出对象各收到一笔来自相似地址的 0 币转入(地址投毒)。
|
||||||
|
/// </summary>
|
||||||
|
private static void Revenge(SaveData d, int day)
|
||||||
|
{
|
||||||
|
var ps = PlayerStore.Instance;
|
||||||
|
ps.AddNightLog(L.T("nightlog.tumbler.note"), "cc7755");
|
||||||
|
if (d.Connected && !d.Hot.Poisoned && d.Rng.Chance(Tuning.TumblerRevengeWalletShare))
|
||||||
|
{
|
||||||
|
d.Hot.Poisoned = true;
|
||||||
|
Log.Info($"Tumbler 报复:钱包 {d.Hot.Address} 被植入木马");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int n = 0;
|
||||||
|
foreach (var w in d.Wallets)
|
||||||
|
{
|
||||||
|
var targets = w.History.Where(h => !h.In && h.Amount > 0 && d.Own(h.Addr) == null).Select(h => h.Addr).Distinct().Take(Tuning.TumblerRevengePoison).ToList();
|
||||||
|
if (targets.Count == 0) targets.Add(d.Address("poinbase"));
|
||||||
|
foreach (var t in targets) { d.PoisonPlans.Add(new PoisonPlan { Wallet = w.Address, Target = t, Day = day + d.Rng.Range(1, Tuning.TxPoisonDelayMax) }); n++; }
|
||||||
|
}
|
||||||
|
Log.Info($"Tumbler 报复:安排 {n} 笔地址投毒");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>长期联系人:游戏排期里明天开始的镇压(玩家知不知道都算),提前一晚提示,每个只提示一次。</summary>
|
||||||
|
private static void Tip(SaveData d, int day, TumblerAfter a)
|
||||||
|
{
|
||||||
|
var mgr = StoreStation.Instance?.storeEventManager;
|
||||||
|
if (mgr == null) return;
|
||||||
|
for (int i = 0; i < mgr.futurEvents.Count && i < mgr.futurEventsDay.Count; i++)
|
||||||
|
{
|
||||||
|
var e = mgr.futurEvents[i];
|
||||||
|
int start = day + mgr.futurEventsDay[i];
|
||||||
|
if (start != day + 1 || (e.identifier != "crackdown" && e.identifier != "sec_martial_law") || a.Tipped.Contains(start)) continue;
|
||||||
|
a.Tipped.Add(start);
|
||||||
|
PlayerStore.Instance.AddNightLog(L.T("nightlog.tumbler.tip"));
|
||||||
|
Log.Info($"Tumbler 提示:第 {start} 天开始 {e.identifier}");
|
||||||
|
}
|
||||||
|
a.Tipped.RemoveAll(x => x < day - 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StoreClient New()
|
private static StoreClient New()
|
||||||
{
|
{
|
||||||
|
// 每次上门是同一个人:外观第一次上门时定下来
|
||||||
|
var t = Session.Data.Story.Tumbler;
|
||||||
|
if (string.IsNullOrEmpty(t.Sprite)) t.Sprite = SpriteDict.GetRandomShadySpriteName();
|
||||||
var c = new StoreClient
|
var c = new StoreClient
|
||||||
{
|
{
|
||||||
identifier = "pd_tumbler", displayName = L.T("tumbler.name"), spriteName = SpriteDict.GetRandomShadySpriteName(),
|
identifier = "pd_tumbler", displayName = L.T("tumbler.name"), spriteName = t.Sprite,
|
||||||
clientIntent = StoreClient.ClientIntent.DIALOGUE, nonShootable = true, dismissable = false,
|
clientIntent = StoreClient.ClientIntent.DIALOGUE, nonShootable = true, dismissable = false,
|
||||||
};
|
};
|
||||||
ModHelper.SetClientSource(c, ModInfo.Id);
|
ModHelper.SetClientSource(c, ModInfo.Id);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>治安部探员(问话和搜查是同一个人)。</summary>
|
||||||
|
private static StoreClient NewAgent()
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After;
|
||||||
|
if (string.IsNullOrEmpty(a.AgentSprite)) a.AgentSprite = SpriteDict.GetRandomSecSpriteName();
|
||||||
|
var c = new StoreClient
|
||||||
|
{
|
||||||
|
identifier = "pd_sec_agent", displayName = L.T("agent.name"), spriteName = a.AgentSprite,
|
||||||
|
clientIntent = StoreClient.ClientIntent.DIALOGUE, nonShootable = true, dismissable = false,
|
||||||
|
};
|
||||||
|
ModHelper.SetClientSource(c, ModInfo.Id);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>第 2、3 次上门之间:探员来问 Tumbler 有没有来过。配合:治安部声望 +;否认:没有影响。</summary>
|
||||||
|
private static StoreClient Agent()
|
||||||
|
{
|
||||||
|
var c = NewAgent();
|
||||||
|
var ask = new Dialogue(); var yes = new Dialogue(); var no = new Dialogue();
|
||||||
|
yes.SetText("PLAYER", L.T("agent.choice.yes")).NextDialogue().SetText(c.displayName, L.T("agent.yes1")).SetEndAction(() => AgentDone(TumblerAfter.Cooperate));
|
||||||
|
no.SetText("PLAYER", L.T("agent.choice.no")).NextDialogue().SetText(c.displayName, L.T("agent.no1")).SetEndAction(() => AgentDone(TumblerAfter.Deny));
|
||||||
|
Lines(c, c.mainDialogue, "agent.v1.", 3).SetNextDialogue(ask);
|
||||||
|
ask.SetText(c.displayName, L.T("agent.ask"))
|
||||||
|
.AddChoice(DirectoryMaster.Item("$"), "-", "", yes, () => { })
|
||||||
|
.AddChoice(DirectoryMaster.Item("$"), "-", "", no, () => { });
|
||||||
|
c.AddBasicDialog();
|
||||||
|
c.CompleteClientCreation();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AgentDone(int choice)
|
||||||
|
{
|
||||||
|
Log.Guard("探员问话结束", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After;
|
||||||
|
if (a.Agent == 0)
|
||||||
|
{
|
||||||
|
a.Agent = choice; a.AgentDay = StoreStation.GetDayCounter();
|
||||||
|
if (choice == TumblerAfter.Cooperate) StoreReputation.ModSecReputation(Tuning.TumblerAgentSecRep);
|
||||||
|
}
|
||||||
|
Log.Info($"探员问话:{(choice == TumblerAfter.Cooperate ? "配合" : "否认")}");
|
||||||
|
Session.Save();
|
||||||
|
});
|
||||||
|
Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GameItem FindDrive() => EmporiumEntry.Instance?.GetAllOwnedItems().FirstOrDefault(i => i != null && i.identifier == Items.KeyDrive);
|
||||||
|
|
||||||
|
/// <summary>配合过探员、又帮 Tumbler 藏了密钥盘:第 4 次上门前一天来搜查,搜到就没收(记违禁品罪证),当晚泄露。</summary>
|
||||||
|
private static StoreClient Search()
|
||||||
|
{
|
||||||
|
var c = NewAgent();
|
||||||
|
bool found = FindDrive() != null;
|
||||||
|
Lines(c, c.mainDialogue, "agent.search.", 2).NextDialogue().SetText(c.displayName, L.T(found ? "agent.search.found" : "agent.search.none")).SetEndAction(() =>
|
||||||
|
{
|
||||||
|
Log.Guard("探员搜查", () =>
|
||||||
|
{
|
||||||
|
var a = Session.Data.Story.After;
|
||||||
|
int day = StoreStation.GetDayCounter();
|
||||||
|
if (a.Searched) return;
|
||||||
|
a.Searched = true; a.SearchDay = day;
|
||||||
|
var drive = FindDrive();
|
||||||
|
if (drive != null)
|
||||||
|
{
|
||||||
|
drive.Destroy();
|
||||||
|
a.Seized = true;
|
||||||
|
PlayerStore.Instance.secData.CommitCrime("CONTRABAND_TRAFFICKING", Tuning.TumblerSearchCrime);
|
||||||
|
a.LeakTonight(day);
|
||||||
|
}
|
||||||
|
Log.Info($"探员搜查:{(drive != null ? "搜走了密钥盘" : "没搜到")}");
|
||||||
|
Session.Save();
|
||||||
|
});
|
||||||
|
Leave();
|
||||||
|
});
|
||||||
|
c.AddBasicDialog();
|
||||||
|
c.CompleteClientCreation();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
private static Dialogue Lines(StoreClient c, Dialogue first, string prefix, int n)
|
private static Dialogue Lines(StoreClient c, Dialogue first, string prefix, int n)
|
||||||
{
|
{
|
||||||
var dl = first.SetText(c.displayName, L.T(prefix + "1"));
|
var dl = first.SetText(c.displayName, L.T(prefix + "1"));
|
||||||
@@ -90,9 +288,11 @@ namespace Decentralized
|
|||||||
case 4:
|
case 4:
|
||||||
if (choice == Tumbler.Hide)
|
if (choice == Tumbler.Hide)
|
||||||
{
|
{
|
||||||
bool has = EmporiumEntry.Instance != null && EmporiumEntry.Instance.GetAllOwnedItems().Any(i => i != null && i.identifier == Items.KeyDrive);
|
bool has = FindDrive() != null;
|
||||||
if (has) Lines(c, c.mainDialogue, "tumbler.v4.back.", 3).SetEndAction(() => { Returned(); Finish(4); });
|
if (d.Story.After.Seized) Lines(c, c.mainDialogue, "tumbler.v4.seized.", 3).SetEndAction(() => Finish(4));
|
||||||
else Lines(c, c.mainDialogue, "tumbler.v4.lost.", 3).SetEndAction(() => Finish(4));
|
else if (has) Lines(c, c.mainDialogue, "tumbler.v4.back.", 3).SetEndAction(() => { Returned(); Finish(4); });
|
||||||
|
// 盘不在手上:按落到治安部算,当晚泄露
|
||||||
|
else Lines(c, c.mainDialogue, "tumbler.v4.lost.", 3).SetEndAction(() => { Session.Data.Story.After.LeakTonight(StoreStation.GetDayCounter()); Finish(4); });
|
||||||
}
|
}
|
||||||
else if (choice == Tumbler.Sell) Lines(c, c.mainDialogue, "tumbler.v4.sold.", 3).SetEndAction(() => Finish(4));
|
else if (choice == Tumbler.Sell) Lines(c, c.mainDialogue, "tumbler.v4.sold.", 3).SetEndAction(() => Finish(4));
|
||||||
else Lines(c, c.mainDialogue, "tumbler.v4.none.", 1).SetEndAction(() => Finish(4));
|
else Lines(c, c.mainDialogue, "tumbler.v4.none.", 1).SetEndAction(() => Finish(4));
|
||||||
@@ -134,13 +334,16 @@ namespace Decentralized
|
|||||||
break;
|
break;
|
||||||
case Tumbler.Report:
|
case Tumbler.Report:
|
||||||
d.Story.Apply("tumbler_reported", day);
|
d.Story.Apply("tumbler_reported", day);
|
||||||
|
d.Story.After.LeakTonight(day);
|
||||||
|
d.Story.After.StartTrial(day, d.Rng);
|
||||||
ModHelper.AddCredit(Tuning.TumblerBounty, true);
|
ModHelper.AddCredit(Tuning.TumblerBounty, true);
|
||||||
StoreReputation.ModSecReputation(Tuning.TumblerSecRep);
|
StoreReputation.ModSecReputation(Tuning.TumblerSecRep);
|
||||||
News.Show("pd_news_tumbler_caught", L.T("news.tumbler.caught.title"), L.T("news.tumbler.caught.desc"), 4, 8);
|
News.Show("pd_news_tumbler_caught", L.T("news.tumbler.caught.title"), L.T("news.tumbler.caught.desc"), 4, 8);
|
||||||
break;
|
break;
|
||||||
case Tumbler.Sell:
|
case Tumbler.Sell:
|
||||||
d.Story.Apply("tumbler_sold", day);
|
d.Story.Apply("tumbler_sold", day);
|
||||||
d.Hot.Add(Assets.CRT, Tuning.TumblerSellCrt); d.Hot.Taint += Tuning.TumblerSellCrt * 0.5; d.Hot.Basis += Tuning.TumblerSellCrt;
|
d.Story.After.StartSold(day, d.Rng);
|
||||||
|
d.Hot.AddDirty(Assets.CRT, Tuning.TumblerSellCrt, Tuning.TumblerSellCrt * Tuning.TumblerSellTaint); d.Hot.Basis += Tuning.TumblerSellCrt;
|
||||||
d.Chain(d.Address("platform"), d.Hot.Address, Assets.CRT, Tuning.TumblerSellCrt);
|
d.Chain(d.Address("platform"), d.Hot.Address, Assets.CRT, Tuning.TumblerSellCrt);
|
||||||
StoreReputation.ModReputation(StoreReputation.FACTION_BLACK_MARKET, Tuning.TumblerBmRep);
|
StoreReputation.ModReputation(StoreReputation.FACTION_BLACK_MARKET, Tuning.TumblerBmRep);
|
||||||
News.Show("pd_news_tumbler_sold", L.T("news.tumbler.sold.title"), L.T("news.tumbler.sold.desc"), 4, 8);
|
News.Show("pd_news_tumbler_sold", L.T("news.tumbler.sold.title"), L.T("news.tumbler.sold.desc"), 4, 8);
|
||||||
@@ -157,10 +360,11 @@ namespace Decentralized
|
|||||||
Log.Guard("Tumbler 取回密钥盘", () =>
|
Log.Guard("Tumbler 取回密钥盘", () =>
|
||||||
{
|
{
|
||||||
var d = Session.Data;
|
var d = Session.Data;
|
||||||
var drive = EmporiumEntry.Instance?.GetAllOwnedItems().FirstOrDefault(i => i != null && i.identifier == Items.KeyDrive);
|
var drive = FindDrive();
|
||||||
if (drive == null) return;
|
if (drive == null) return;
|
||||||
drive.Destroy();
|
drive.Destroy();
|
||||||
d.Story.Apply("tumbler_kept", StoreStation.GetDayCounter());
|
d.Story.Apply("tumbler_kept", StoreStation.GetDayCounter());
|
||||||
|
d.Story.After.Contact = true;
|
||||||
d.Hot.Add(Assets.CRT, Tuning.TumblerGift); d.Hot.Basis += Tuning.TumblerGift;
|
d.Hot.Add(Assets.CRT, Tuning.TumblerGift); d.Hot.Basis += Tuning.TumblerGift;
|
||||||
d.Chain(d.Address("tumbler"), d.Hot.Address, Assets.CRT, Tuning.TumblerGift);
|
d.Chain(d.Address("tumbler"), d.Hot.Address, Assets.CRT, Tuning.TumblerGift);
|
||||||
PlayerStore.Instance.AddNightLog(L.T("nightlog.tumbler.gift", Fmt.Num(Tuning.TumblerGift), WalletWindow.NameOf(d.Hot)));
|
PlayerStore.Instance.AddNightLog(L.T("nightlog.tumbler.gift", Fmt.Num(Tuning.TumblerGift), WalletWindow.NameOf(d.Hot)));
|
||||||
|
|||||||
@@ -255,7 +255,8 @@ namespace Decentralized
|
|||||||
b.End();
|
b.End();
|
||||||
b.BeginPanel(130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
b.BeginPanel(130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
||||||
_clear.Add(b.Last.image);
|
_clear.Add(b.Last.image);
|
||||||
b.AddLabel(Amt(q) + (w.Frozen.TryGetValue(a, out var fz) && fz > 0 ? L.T("hw.balance.frozen", Amt(fz)) : ""));
|
double dq = w.DirtyOf(a);
|
||||||
|
b.AddLabel(Amt(q) + (w.Frozen.TryGetValue(a, out var fz) && fz > 0 ? L.T("hw.balance.frozen", Amt(fz)) : "") + (dq > 1e-9 ? L.T("hw.balance.dirty", Amt(dq)) : ""));
|
||||||
b.End();
|
b.End();
|
||||||
b.BeginPanel(RowW - 12f - 90f - 130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
b.BeginPanel(RowW - 12f - 90f - 130f, 26f, TextAnchor.MiddleRight, 0f, 0f);
|
||||||
_clear.Add(b.Last.image);
|
_clear.Add(b.Last.image);
|
||||||
@@ -266,7 +267,7 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
b.AddSeparator();
|
b.AddSeparator();
|
||||||
b.AddLabel(L.T("hw.total", Fmt.Credits(w.Value(Session.Price))));
|
b.AddLabel(L.T("hw.total", Fmt.Credits(w.Value(Session.Price))));
|
||||||
if (w.Taint > 0.5) b.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint)));
|
if (w.Taint(Session.Price) > 0.5) b.AddLabel(L.T("wallet.taint", Fmt.Credits(w.Taint(Session.Price))));
|
||||||
if (Pending != null) b.AddLabel(Pending.Contract ? L.T("hw.pending.sign", Pending.Summary) : L.T("hw.pending.bill", Pending.Summary));
|
if (Pending != null) b.AddLabel(Pending.Contract ? L.T("hw.pending.sign", Pending.Summary) : L.T("hw.pending.bill", Pending.Summary));
|
||||||
if (Congested) b.AddLabel(L.T("hw.congested"), "congest_note");
|
if (Congested) b.AddLabel(L.T("hw.congested"), "congest_note");
|
||||||
b.AddSpace(6f);
|
b.AddSpace(6f);
|
||||||
@@ -345,11 +346,24 @@ namespace Decentralized
|
|||||||
if (bill.Asset != dev.Asset) return L.T("hw.err.asset", bill.Asset);
|
if (bill.Asset != dev.Asset) return L.T("hw.err.asset", bill.Asset);
|
||||||
if (v + 1e-9 < bill.Amount) return L.T("hw.err.short", Amt(bill.Amount), bill.Asset);
|
if (v + 1e-9 < bill.Amount) return L.T("hw.err.short", Amt(bill.Amount), bill.Asset);
|
||||||
}
|
}
|
||||||
else if (IsPoinbase(to)) { if (!Exchange.Listed.Contains(dev.Asset)) return L.T("hw.err.poinbase", dev.Asset); }
|
else if (IsPoinbase(to))
|
||||||
|
{
|
||||||
|
if (!Exchange.Listed.Contains(dev.Asset)) return L.T("hw.err.poinbase", dev.Asset);
|
||||||
|
// Poinbase 只收干净的币:这种币最多充干净的枚数(手续费同币种时先扣掉)
|
||||||
|
double clean = CleanAfterFee(w, dev.Asset, dev.Asset == FeeAssetOf(dev) ? FeeIn(dev.Asset, dev.Tier) : 0);
|
||||||
|
if (v > clean + 1e-6) return L.T("hw.err.tainted", Amt(w.DirtyOf(dev.Asset)), dev.Asset, Amt(clean));
|
||||||
|
}
|
||||||
else if (Session.Data.Own(to) == null && Known(to)) return L.T("hw.err.nobill");
|
else if (Session.Data.Own(to) == null && Known(to)) return L.T("hw.err.nobill");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>扣掉同币种的手续费(按脏比例带走一点脏的)之后,这种币干净、能动用的枚数。</summary>
|
||||||
|
private static double CleanAfterFee(Wallet w, string asset, double fee)
|
||||||
|
{
|
||||||
|
double r = w.DirtyRatio(asset);
|
||||||
|
return Math.Max(0, Math.Min(w.Avail(asset) - fee, (w.Get(asset) - fee) * (1 - r)));
|
||||||
|
}
|
||||||
|
|
||||||
private static Bill Match(string to) => Pending != null && !Pending.Contract && ChainAddress.Same(Pending.Address, to) ? Pending : null;
|
private static Bill Match(string to) => Pending != null && !Pending.Contract && ChainAddress.Same(Pending.Address, to) ? Pending : null;
|
||||||
|
|
||||||
/// <summary>有过往来的地址(平台、商家、混币器、兑换处):没有账单时对方不收。</summary>
|
/// <summary>有过往来的地址(平台、商家、混币器、兑换处):没有账单时对方不收。</summary>
|
||||||
@@ -539,7 +553,7 @@ namespace Decentralized
|
|||||||
Open(dev);
|
Open(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>动画走完(或点了跳过):交易落地。付账单的执行终端那边的动作;转给自己的钱包或 Poinbase 的按比例带上污点;没人用的地址,币就没了。</summary>
|
/// <summary>动画走完(或点了跳过):交易落地。付账单的执行终端那边的动作;转给自己的钱包的按比例带上污点,转给 Poinbase 的只转干净的、污点留在钱包;没人用的地址,币就没了。</summary>
|
||||||
private static void Finish(Device dev)
|
private static void Finish(Device dev)
|
||||||
{
|
{
|
||||||
var tx = dev.Tx;
|
var tx = dev.Tx;
|
||||||
@@ -562,6 +576,8 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
int day = StoreStation.GetDayCounter();
|
int day = StoreStation.GetDayCounter();
|
||||||
double amt = tx.To != null ? Math.Min(tx.Amount, w.Avail(tx.Asset)) : 0;
|
double amt = tx.To != null ? Math.Min(tx.Amount, w.Avail(tx.Asset)) : 0;
|
||||||
|
// Poinbase 只收干净的币:落地时价格可能变了,超出干净部分的不转(留在钱包)
|
||||||
|
if (tx.To != null && tx.Bill == null && IsPoinbase(tx.To)) amt = Math.Min(amt, w.CleanAvail(tx.Asset));
|
||||||
if (tx.To != null)
|
if (tx.To != null)
|
||||||
{
|
{
|
||||||
d.Chain(w.Address, tx.To, tx.Asset, amt, tx.FeeAsset == tx.Asset ? tx.Fee : 0, tx.Block);
|
d.Chain(w.Address, tx.To, tx.Asset, amt, tx.FeeAsset == tx.Asset ? tx.Fee : 0, tx.Block);
|
||||||
@@ -586,7 +602,9 @@ namespace Decentralized
|
|||||||
if (tx.To == null) return;
|
if (tx.To == null) return;
|
||||||
var own = d.Own(tx.To);
|
var own = d.Own(tx.To);
|
||||||
Wallet target = own ?? (IsPoinbase(tx.To) ? d.Poinbase : new Wallet());
|
Wallet target = own ?? (IsPoinbase(tx.To) ? d.Poinbase : new Wallet());
|
||||||
Wallet.Transfer(w, target, tx.Asset, amt, Session.Price);
|
// Poinbase 只收干净的币:污点留在钱包里
|
||||||
|
if (target == d.Poinbase) Wallet.TransferClean(w, target, tx.Asset, amt, Session.Price);
|
||||||
|
else Wallet.Transfer(w, target, tx.Asset, amt, Session.Price);
|
||||||
if (own == null && target != d.Poinbase) Log.Info($"转进没人用的地址 {tx.To}:{amt} {tx.Asset}");
|
if (own == null && target != d.Poinbase) Log.Info($"转进没人用的地址 {tx.To}:{amt} {tx.Asset}");
|
||||||
if (own == null && d.Scams.ScamAddrs.Any(a => ChainAddress.Same(a, tx.To))) PlayerStore.Instance.AddNightLog(L.T("nightlog.scam.sent", Fmt.Num(amt), tx.Asset), "cc7755");
|
if (own == null && d.Scams.ScamAddrs.Any(a => ChainAddress.Same(a, tx.To))) PlayerStore.Instance.AddNightLog(L.T("nightlog.scam.sent", Fmt.Num(amt), tx.Asset), "cc7755");
|
||||||
TerminalWindow.Refresh(null);
|
TerminalWindow.Refresh(null);
|
||||||
|
|||||||
@@ -106,19 +106,29 @@ internal static class Program
|
|||||||
Check(Near(pool.QuoteReserve, 60000, 1e-9), "深度重设");
|
Check(Near(pool.QuoteReserve, 60000, 1e-9), "深度重设");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("地址:污点和成本按价值比例随币走;Ponero 换入时污点停止传播", () =>
|
Test("地址:每种币记脏枚数,转出、花掉、兑换按这种币的脏比例带走;成本按价值比例;Ponero 不带污点", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> px = a => a == Assets.PSC ? 100 : 1;
|
Func<string, double> px = a => a == Assets.PSC ? 100 : 1;
|
||||||
var a = new Wallet { Address = "A", Taint = 300, Basis = 1000 };
|
var a = new Wallet { Address = "A", Basis = 1000 };
|
||||||
a.Add(Assets.CRT, 1000);
|
a.AddDirty(Assets.CRT, 1000, 300);
|
||||||
var b = new Wallet { Address = "B" };
|
var b = new Wallet { Address = "B" };
|
||||||
Wallet.Transfer(a, b, Assets.CRT, 250, px);
|
Wallet.Transfer(a, b, Assets.CRT, 250, px);
|
||||||
Check(Near(b.Taint, 75, 1e-9) && Near(a.Taint, 225, 1e-9), $"转出 1/4,污点带走 1/4:{b.Taint}");
|
Check(Near(b.DirtyOf(Assets.CRT), 75, 1e-9) && Near(a.DirtyOf(Assets.CRT), 225, 1e-9), $"转出 1/4,脏枚数带走 1/4:{b.DirtyOf(Assets.CRT)}");
|
||||||
Check(Near(b.Basis, 250, 1e-9), "成本带走 1/4");
|
Check(Near(b.Basis, 250, 1e-9), "成本带走 1/4");
|
||||||
|
a.Add(Assets.PSC, 5);
|
||||||
|
a.Add(Assets.CRT, -150);
|
||||||
|
Check(Near(a.DirtyOf(Assets.CRT), 180, 1e-9) && a.DirtyOf(Assets.PSC) == 0 && Near(a.Taint(px), 180, 1e-9), "花掉 150 CRT:按 30% 带走 45 枚脏的;干净的 PSC 不受影响;按现价的脏币价值 180");
|
||||||
|
a.Convert(Assets.CRT, 100, Assets.PSC, 1);
|
||||||
|
Check(Near(a.DirtyOf(Assets.PSC), 0.3, 1e-9) && Near(a.DirtyOf(Assets.CRT), 150, 1e-9), "兑换:30% 脏的 CRT 换来的 PSC 也是 30% 脏");
|
||||||
|
a.Convert(Assets.CRT, 100, Assets.Ponero, 50, clean: true);
|
||||||
|
Check(a.DirtyOf(Assets.Ponero) == 0 && Near(a.DirtyOf(Assets.CRT), 120, 1e-9), "兑入 Ponero:兑掉的脏币消失,Ponero 是干净的");
|
||||||
|
var sc = new Wallet(); sc.AddDirty(Assets.CRC, 1000, 400); sc.Scale(Assets.CRC, 0.5);
|
||||||
|
Check(Near(sc.Get(Assets.CRC), 500, 1e-9) && Near(sc.DirtyOf(Assets.CRC), 200, 1e-9), "CRC 减记:脏枚数同比例缩水");
|
||||||
|
Check(Near(sc.MarkDirty(Assets.CRC, 400), 100, 1e-9) && Near(sc.DirtyOf(Assets.CRC), 500, 1e-9), "补记脏币不超过干净的枚数,返回没记上的");
|
||||||
var c = new Wallet { Address = "C" };
|
var c = new Wallet { Address = "C" };
|
||||||
b.Add(Assets.Ponero, 10);
|
b.Add(Assets.Ponero, 10);
|
||||||
Wallet.Transfer(b, c, Assets.Ponero, 10, px);
|
Wallet.Transfer(b, c, Assets.Ponero, 10, px);
|
||||||
Check(c.Taint == 0, "Ponero 转入的地址不带污点");
|
Check(c.Taint(px) == 0, "Ponero 转入的地址不带污点");
|
||||||
bool threw = false;
|
bool threw = false;
|
||||||
try { a.Add(Assets.CRT, -10000); } catch (InvalidOperationException) { threw = true; }
|
try { a.Add(Assets.CRT, -10000); } catch (InvalidOperationException) { threw = true; }
|
||||||
Check(threw, "余额不足时拒绝");
|
Check(threw, "余额不足时拒绝");
|
||||||
@@ -499,45 +509,46 @@ internal static class Program
|
|||||||
Check(Math.Abs(lost / (double)n - 0.1) < 0.03, $"命中率 {lost / (double)n:P1}");
|
Check(Math.Abs(lost / (double)n - 0.1) < 0.03, $"命中率 {lost / (double)n:P1}");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("合规出金:干净小额不查;污点高时重度命中记罪证;轻度命中只没收污点部分;只对收益计税", () =>
|
Test("Poinbase 只收干净的币:每种币最多充干净的枚数、脏的留在钱包;出金不审查、只对收益计税", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> px = a => 1;
|
Func<string, double> px = a => 1;
|
||||||
Check(Exchange.HitChance(500, 0, 0, 200, false) == 0, "干净、低于 5 倍房租:不查");
|
var w = new Wallet { Address = "w", Basis = 800 };
|
||||||
Check(Near(Exchange.HitChance(2000, 0, 0, 200, false), 0.2, 1e-9), "单笔为大额阈值 2 倍:20%");
|
w.AddDirty(Assets.CRC, 1000, 500);
|
||||||
Check(Near(Exchange.HitChance(1000, 500, 0, 200, false), 0.75, 1e-9), "污点 50%:75%");
|
Check(Near(w.CleanAvail(Assets.CRC), 500, 1e-9), "1000 CRC、500 枚脏:能充 500");
|
||||||
Check(Exchange.HitChance(100000, 100000, 1e6, 200, true) == Tuning.AmlMaxChance, "上限 90%");
|
var pb = new Wallet { Address = "pb" };
|
||||||
int heavy = 0;
|
double moved = Wallet.TransferClean(w, pb, Assets.CRC, 800, px);
|
||||||
double crime = 0;
|
Check(Near(moved, 500, 1e-9) && Near(w.DirtyOf(Assets.CRC), 500, 1e-9) && Near(w.Get(Assets.CRC), 500, 1e-9) && pb.Taint(px) == 0 && Near(pb.Basis, 400, 1e-9) && Near(w.Basis, 400, 1e-9),
|
||||||
for (int i = 0; i < 1000; i++)
|
"要充 800 只转了干净的 500:脏的留在钱包(剩 500 CRC 全脏),成本按价值比例带走");
|
||||||
{
|
Check(w.CleanAvail(Assets.CRC) == 0, "剩下的全是脏的,一枚也充不进去");
|
||||||
var w = new Wallet { Taint = 500, Basis = 1000 };
|
w.Add(Assets.CRC, 300);
|
||||||
w.Add(Assets.CRC, 1000);
|
Check(Near(w.CleanAvail(Assets.CRC), 300, 1e-9), "转进干净的 300 只能再充 300");
|
||||||
var r = new Exchange().Cashout(w, 1000, px, 1, 200, false, new Rng((ulong)i));
|
var two = new Wallet(); two.AddDirty(Assets.CRT, 100, 100); two.Add(Assets.PSC, 2);
|
||||||
if (r.Outcome == AmlOutcome.Heavy) { heavy++; crime = r.Crime; Check(Near(r.Received, 1000 * (1 - Tuning.ExchangeFee) - 500, 1e-6), "重度:没收污点部分"); }
|
Check(Near(two.CleanAvail(Assets.PSC), 2, 1e-9) && two.CleanAvail(Assets.CRT) == 0, "按币种分开:CRT 全脏不影响干净的 PSC");
|
||||||
else Check(Near(r.Received, 1000 * (1 - Tuning.ExchangeFee), 1e-6) && r.Tax == 0, "未命中:全额到账;本金不计税");
|
var fz = new Wallet(); fz.AddDirty(Assets.CRT, 1000, 600); fz.Freeze(Assets.CRT, 0.5, 9);
|
||||||
}
|
Check(Near(fz.CleanAvail(Assets.CRT), 400, 1e-9), "冻结的不能充:取可动用和干净的较小者");
|
||||||
Check(Near(heavy / 1000.0, 0.75, 0.04) && crime == 500, $"污点 50% 时约 75% 重度命中,罪证 = 污点额:{heavy / 1000.0:P0}");
|
var acct = new Wallet { Basis = 1000 };
|
||||||
var light = new Wallet { Taint = 150 };
|
acct.Add(Assets.CRC, 1000);
|
||||||
light.Add(Assets.CRC, 1000);
|
var r = new Exchange().Cashout(acct, 1000, px);
|
||||||
CashoutResult lr = null;
|
Check(Near(r.Received, 1000 * (1 - Tuning.ExchangeFee), 1e-6) && r.Tax == 0, "出金全额到账(扣手续费),本金不计税");
|
||||||
for (ulong i = 0; lr == null || lr.Outcome == AmlOutcome.Clear; i++)
|
var gain = new Wallet { Basis = 600 }; gain.Add(Assets.CRC, 1000);
|
||||||
{
|
var g = new Exchange().Cashout(gain, 1000, px);
|
||||||
var w = new Wallet { Taint = 150 };
|
Check(Near(g.Tax, (1000 * (1 - Tuning.ExchangeFee) - 600) * Tuning.TaxRate, 1e-6), "超出成本的部分计税");
|
||||||
w.Add(Assets.CRC, 1000);
|
|
||||||
lr = new Exchange().Cashout(w, 1000, px, 1, 200, false, new Rng(i));
|
|
||||||
}
|
|
||||||
Check(lr.Outcome == AmlOutcome.Light && lr.Crime == 0 && Near(lr.Confiscated, 150, 1e-6), "污点 15%:轻度命中,没收 150、不记罪证");
|
|
||||||
Check(Near(lr.Tax, (1000 * (1 - Tuning.ExchangeFee) - 150) * Tuning.TaxRate, 1e-6), "成本为 0 时到账部分全额计税");
|
|
||||||
var ex = new Exchange();
|
|
||||||
var big = new Wallet();
|
|
||||||
big.Add(Assets.CRC, 4000);
|
|
||||||
ex.Cashout(big, 2000, px, 1, 200, false, new Rng(1));
|
|
||||||
Check(Near(Exchange.HitChance(2000, 0, ex.History.Sum(h => h.Value), 200, false), 0.2 + 0.2 * 1000 / 3000.0, 1e-9),
|
|
||||||
"7 天内累计超过 15 倍房租也会提高命中率");
|
|
||||||
var dep = new Wallet { Basis = 1000 };
|
var dep = new Wallet { Basis = 1000 };
|
||||||
dep.Add(Assets.CRC, 1000);
|
dep.Add(Assets.CRC, 1000);
|
||||||
var dr = new Exchange().Cashout(dep, 1000, a => 0.9, 1, 200, false, new Rng(1));
|
Check(Near(new Exchange().Cashout(dep, 1000, a => 0.9).Received, 900 * (1 - Tuning.ExchangeFee), 1e-6), "CRC 脱锚时按市价兑出");
|
||||||
Check(Near(dr.Received, 900 * (1 - Tuning.ExchangeFee), 1e-6), "CRC 脱锚时按市价兑出");
|
// 存档迁移:旧的整钱包污点额按现价摊成各币脏枚数;Poinbase 和永续仓位的挪到 1 号钱包一起摊,超出的作废
|
||||||
|
Func<string, double> px2 = a => a == Assets.PSC ? 100 : 1;
|
||||||
|
var old = new Wallet { LegacyTaint = 300 }; old.Add(Assets.CRC, 1000);
|
||||||
|
var pos = new List<PerpPosition> { new PerpPosition { Product = "PSC", LegacyTaint = 200 } };
|
||||||
|
var w1 = new Wallet { Address = "w1", LegacyTaint = 100 }; w1.Add(Assets.CRC, 400); w1.Add(Assets.PSC, 2); w1.Add(Assets.Ponero, 50);
|
||||||
|
var w2 = new Wallet { Address = "w2", LegacyTaint = 50 }; w2.Add(Assets.CRT, 100);
|
||||||
|
var mixer = new Mixer(); mixer.Pending.Add(new MixDeposit { Asset = Assets.PSC, Amount = 3, LegacyTaint = 150 });
|
||||||
|
var book = new PredictBook(); book.Positions.Add(new PredictPos { Cost = 100, LegacyTaint = 40 });
|
||||||
|
double was = TaintMigration.Run(new List<Wallet> { w1, w2 }, old, pos, mixer, new BlackMarket(), new Staking(), new Scams(), book, new OwnMixer(), px2);
|
||||||
|
Check(old.LegacyTaint == 0 && pos[0].LegacyTaint == 0 && w1.LegacyTaint == 0 && Near(w1.DirtyOf(Assets.CRC), 400, 1e-9) && Near(w1.DirtyOf(Assets.PSC), 2, 1e-9) && w1.DirtyOf(Assets.Ponero) == 0,
|
||||||
|
"1 号钱包:自己 100 + Poinbase 300 + 永续 200 = 600,超过可追踪币的价值 600 封顶,全部记脏;Ponero 不摊");
|
||||||
|
Check(Near(w2.DirtyOf(Assets.CRT), 50, 1e-9), "2 号钱包:污点 50 / 价值 100 → CRT 一半脏");
|
||||||
|
Check(Near(mixer.Pending[0].Dirty, 1.5, 1e-9) && Near(book.Positions[0].Dirty, 40, 1e-9) && Near(was, 840, 1e-9), "托管:混币器在途按价格换成脏枚数,预测持仓同理;日志总额 840");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("二手贩子:老实人不报价;中间商加价;骗子夹带假卡;指出问题按维度扣价、拆穿假货按真实芯片算", () =>
|
Test("二手贩子:老实人不报价;中间商加价;骗子夹带假卡;指出问题按维度扣价、拆穿假货按真实芯片算", () =>
|
||||||
@@ -696,18 +707,16 @@ internal static class Program
|
|||||||
var m = Market.CreateDefault(3);
|
var m = Market.CreateDefault(3);
|
||||||
var st = new Stablecoins();
|
var st = new Stablecoins();
|
||||||
var net = new Network();
|
var net = new Network();
|
||||||
var w = new Wallet { Address = "hot", Taint = 12, Basis = 34 };
|
var w = new Wallet { Address = "hot", Basis = 34 };
|
||||||
w.Add(Assets.PSC, 5);
|
w.AddDirty(Assets.PSC, 5, 1.5);
|
||||||
var ex = new Exchange();
|
var ex = new Exchange();
|
||||||
ex.History.Add(new KeyValuePair<int, double>(2, 100));
|
|
||||||
var rng = new Rng(77);
|
var rng = new Rng(77);
|
||||||
for (int d = 1; d <= 5; d++) { m.Night(new MarketEvent[0], rng, d, a => 1); st.Night(d, rng, 0); net.Night(d, m.Price, 10); }
|
for (int d = 1; d <= 5; d++) { m.Night(new MarketEvent[0], rng, d, a => 1); st.Night(d, rng, 0); net.Night(d, m.Price, 10); }
|
||||||
var bundle = new SaveBundle { Market = m, Stable = st, Network = net, Hot = w, Exchange = ex, Rng = rng };
|
var bundle = new SaveBundle { Market = m, Stable = st, Network = net, Hot = w, Exchange = ex, Rng = rng };
|
||||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject(bundle);
|
string json = Newtonsoft.Json.JsonConvert.SerializeObject(bundle);
|
||||||
var back = Newtonsoft.Json.JsonConvert.DeserializeObject<SaveBundle>(json);
|
var back = Newtonsoft.Json.JsonConvert.DeserializeObject<SaveBundle>(json);
|
||||||
Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格");
|
Check(Near(back.Market.Price, m.Price, 1e-9) && back.Market.Pools.Count == m.Pools.Count && back.Market.Pools[1].Id == m.Pools[1].Id, "交易对与价格");
|
||||||
Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.Taint == 12 && back.Hot.Basis == 34, "钱包余额、污点、成本");
|
Check(back.Hot.Get(Assets.PSC) == 5 && back.Hot.DirtyOf(Assets.PSC) == 1.5 && back.Hot.Basis == 34, "钱包余额、脏枚数、成本");
|
||||||
Check(back.Exchange.History.Count == 1 && back.Exchange.History[0].Value == 100, "出金记录");
|
|
||||||
Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.Reserve, st.Reserve, 1e-9), "全网算力、CRA 储备");
|
Check(Near(back.Network.NpcHash, net.NpcHash, 1e-9) && Near(back.Stable.Reserve, st.Reserve, 1e-9), "全网算力、CRA 储备");
|
||||||
for (int d = 6; d <= 10; d++)
|
for (int d = 6; d <= 10; d++)
|
||||||
{
|
{
|
||||||
@@ -723,20 +732,20 @@ internal static class Program
|
|||||||
Check(CoinPayment.AssetFor("FACTION_BLACK_MARKET") == Assets.CRT && CoinPayment.AssetFor("FACTION_SECURITY") == null, "派系对应的币");
|
Check(CoinPayment.AssetFor("FACTION_BLACK_MARKET") == Assets.CRT && CoinPayment.AssetFor("FACTION_SECURITY") == null, "派系对应的币");
|
||||||
double q = CoinPayment.Receive(w, Assets.CRT, 200, 0.5, 40);
|
double q = CoinPayment.Receive(w, Assets.CRT, 200, 0.5, 40);
|
||||||
Check(Near(q, 400 * (1 + Tuning.CoinPayPremium), 1e-9) && Near(w.Get(Assets.CRT), q, 1e-9), "按币价换算数量,含溢价");
|
Check(Near(q, 400 * (1 + Tuning.CoinPayPremium), 1e-9) && Near(w.Get(Assets.CRT), q, 1e-9), "按币价换算数量,含溢价");
|
||||||
Check(Near(w.Taint, 80, 1e-9) && Near(w.Basis, 200, 1e-9), "污点 = 货值 × 热度%,成本 = 货值(溢价不带污点)");
|
Check(Near(w.DirtyOf(Assets.CRT), 80 / 0.5, 1e-9) && Near(w.Basis, 200, 1e-9), "脏的 = 货值 × 热度% 那部分的币(160 枚),成本 = 货值(溢价干净)");
|
||||||
Check(CoinPayment.Receive(w, Assets.CRC, 0, 1, 10) == 0, "零金额不收");
|
Check(CoinPayment.Receive(w, Assets.CRC, 0, 1, 10) == 0, "零金额不收");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("混币器:按价值比例带走污点、轮数即天数、手续费与清洗、匿名集、制裁标记", () =>
|
Test("混币器:按这种币的脏比例带走脏枚数、轮数即天数、手续费与清洗、匿名集、制裁期间整笔脏", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> px = a => a == Assets.PSC ? 10 : 1;
|
Func<string, double> px = a => a == Assets.PSC ? 10 : 1;
|
||||||
var w = new Wallet { Address = "t" };
|
var w = new Wallet { Address = "t" };
|
||||||
w.Add(Assets.CRC, 1000); w.Add(Assets.PSC, 100); // 总价值 2000
|
w.AddDirty(Assets.CRC, 1000, 200); w.AddDirty(Assets.PSC, 100, 20); // 总价值 2000,各 20% 脏
|
||||||
w.Taint = 400; w.Basis = 1000;
|
w.Basis = 1000;
|
||||||
var m = new Mixer();
|
var m = new Mixer();
|
||||||
Check(m.Deposit(w, Assets.CRC, 1000, 9, 1, px) == null && m.Deposit(w, Assets.CRC, 50, 1, 1, px) == null, "轮数超限、低于最小额不收");
|
Check(m.Deposit(w, Assets.CRC, 1000, 9, 1, px) == null && m.Deposit(w, Assets.CRC, 50, 1, 1, px) == null, "轮数超限、低于最小额不收");
|
||||||
var d = m.Deposit(w, Assets.CRC, 1000, 2, 1, px);
|
var d = m.Deposit(w, Assets.CRC, 1000, 2, 1, px);
|
||||||
Check(d != null && Near(d.Taint, 200, 1e-9) && Near(w.Taint, 200, 1e-9) && Near(w.Get(Assets.CRC), 0, 1e-9), "存入 1000 / 2000:带走一半污点");
|
Check(d != null && Near(d.Dirty, 200, 1e-9) && w.DirtyOf(Assets.CRC) == 0 && Near(w.DirtyOf(Assets.PSC), 20, 1e-9) && Near(w.Get(Assets.CRC), 0, 1e-9), "存入 1000 CRC:带走 200 枚脏的,PSC 不受影响");
|
||||||
var rng = new Rng(3);
|
var rng = new Rng(3);
|
||||||
Check(m.Night(w, 2, px, rng).Count == 0, "未到期不提回");
|
Check(m.Night(w, 2, px, rng).Count == 0, "未到期不提回");
|
||||||
var res = m.Night(w, 3, px, rng);
|
var res = m.Night(w, 3, px, rng);
|
||||||
@@ -744,15 +753,14 @@ internal static class Program
|
|||||||
double rate = Mixer.RoundRate(1000);
|
double rate = Mixer.RoundRate(1000);
|
||||||
Check(Near(w.Get(Assets.CRC), 1000 * (1 - Tuning.MixerFee) * (1 - Tuning.MixerFee), 1e-6) && Near(res[0].TaintAfter, 200 * (1 - rate) * (1 - rate), 1e-6), "两轮:手续费与污点按轮数递减");
|
Check(Near(w.Get(Assets.CRC), 1000 * (1 - Tuning.MixerFee) * (1 - Tuning.MixerFee), 1e-6) && Near(res[0].TaintAfter, 200 * (1 - rate) * (1 - rate), 1e-6), "两轮:手续费与污点按轮数递减");
|
||||||
Check(Mixer.RoundRate(100000) < Mixer.RoundRate(1000) / 3, "存入越大匿名集占比越大,清洗越差");
|
Check(Mixer.RoundRate(100000) < Mixer.RoundRate(1000) / 3, "存入越大匿名集占比越大,清洗越差");
|
||||||
Check(m.RecentlyMixed(3) && !m.RecentlyMixed(3 + Tuning.AmlWindowDays + 1), "提回后一段时间内出金按混币来源加重");
|
|
||||||
m.OnEvent(MarketEvent.Crackdown, 5, new Rng(1));
|
m.OnEvent(MarketEvent.Crackdown, 5, new Rng(1));
|
||||||
int hit = 0; for (int i = 0; i < 400; i++) { var t = new Mixer(); t.OnEvent(MarketEvent.Crackdown, 1, new Rng((ulong)i + 1)); if (t.Sanctioned(2)) hit++; }
|
int hit = 0; for (int i = 0; i < 400; i++) { var t = new Mixer(); t.OnEvent(MarketEvent.Crackdown, 1, new Rng((ulong)i + 1)); if (t.Sanctioned(2)) hit++; }
|
||||||
Check(hit > 150 && hit < 250, $"镇压时约一半概率被制裁:{hit}/400");
|
Check(hit > 150 && hit < 250, $"镇压时约一半概率被制裁:{hit}/400");
|
||||||
var w2 = new Wallet { Address = "u" }; w2.Add(Assets.CRC, 500);
|
var w2 = new Wallet { Address = "u" }; w2.Add(Assets.CRC, 500);
|
||||||
var m2 = new Mixer { SanctionedUntil = 10 };
|
var m2 = new Mixer { SanctionedUntil = 10 };
|
||||||
m2.Deposit(w2, Assets.CRC, 500, 1, 1, px);
|
m2.Deposit(w2, Assets.CRC, 500, 1, 1, px);
|
||||||
m2.Night(w2, 2, px, new Rng(5));
|
var fr = m2.Night(w2, 2, px, new Rng(5)).Single();
|
||||||
Check(w2.Flagged, "制裁期间提出的币被标记");
|
Check(fr.Flagged && Near(w2.DirtyOf(Assets.CRC), w2.Get(Assets.CRC), 1e-6), $"制裁期间提出:不洗,整笔都是脏的({w2.DirtyOf(Assets.CRC):0} / {w2.Get(Assets.CRC):0})");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("CRT 冻结:冻一半、可动用余额减少、到期解冻;声望越高越不容易被冻", () =>
|
Test("CRT 冻结:冻一半、可动用余额减少、到期解冻;声望越高越不容易被冻", () =>
|
||||||
@@ -777,15 +785,15 @@ internal static class Program
|
|||||||
Check(bm.Refresh(10, 45, new Rng(1), id => 100) && bm.Offers.Count > 0 && bm.Offers.Where(o => o.Kind == GoodKind.Contraband).All(o => o.Level <= 2 && o.Price == 130), "声望 45 开放中档,溢价 30%");
|
Check(bm.Refresh(10, 45, new Rng(1), id => 100) && bm.Offers.Count > 0 && bm.Offers.Where(o => o.Kind == GoodKind.Contraband).All(o => o.Level <= 2 && o.Price == 130), "声望 45 开放中档,溢价 30%");
|
||||||
Check(!bm.Refresh(12, 45, new Rng(2), id => 100) && bm.Refresh(17, 45, new Rng(2), id => 100), "每周刷新");
|
Check(!bm.Refresh(12, 45, new Rng(2), id => 100) && bm.Refresh(17, 45, new Rng(2), id => 100), "每周刷新");
|
||||||
var w = new Wallet { Address = "t" };
|
var w = new Wallet { Address = "t" };
|
||||||
w.Add(Assets.PSC, 10); w.Add(Assets.CRT, 1000); w.Taint = 400; w.Basis = 800; // 总价值 2000
|
w.Add(Assets.PSC, 10); w.AddDirty(Assets.CRT, 1000, 400); w.Basis = 800; // 总价值 2000
|
||||||
var offer = new BmOffer { Item = "x", Qty = 1, Price = 500, Level = 1 };
|
var offer = new BmOffer { Item = "x", Qty = 1, Price = 500, Level = 1 };
|
||||||
bm.Offers.Add(offer);
|
bm.Offers.Add(offer);
|
||||||
Check(!bm.Buy(offer, w, Assets.CRC, price), "不收 CRC");
|
Check(!bm.Buy(offer, w, Assets.CRC, price), "不收 CRC");
|
||||||
Check(bm.Buy(offer, w, Assets.CRT, price) && Near(w.Get(Assets.CRT), 500, 1e-9) && Near(w.Taint, 300, 1e-6) && Near(w.Basis, 600, 1e-6) && !bm.Offers.Contains(offer), "付币:污点与成本按比例留给卖家,卖完下架");
|
Check(bm.Buy(offer, w, Assets.CRT, price) && Near(w.Get(Assets.CRT), 500, 1e-9) && Near(w.DirtyOf(Assets.CRT), 200, 1e-6) && Near(w.Basis, 600, 1e-6) && !bm.Offers.Contains(offer), "付币:付出的 CRT 按 40% 带走脏的,成本按比例留给卖家,卖完下架");
|
||||||
w = new Wallet { Address = "t" };
|
w = new Wallet { Address = "t" };
|
||||||
w.Add(Assets.PSC, 10); w.Taint = 500; w.Basis = 1000; // 总价值 1000,PSC 价 100
|
w.AddDirty(Assets.PSC, 10, 5); w.Basis = 1000; // 总价值 1000,PSC 价 100,一半脏
|
||||||
double got = bm.ToPonero(w, Assets.PSC, 5, 20, price); // 价值 500
|
double got = bm.ToPonero(w, Assets.PSC, 5, 20, price); // 价值 500
|
||||||
Check(Near(got, 500 * (1 - Tuning.PoneroFee) / 50, 1e-9) && Near(w.Taint, 250, 1e-6) && Near(w.Get(Assets.PSC), 5, 1e-9), "兑入 Ponero:扣手续费,这部分污点留在原地");
|
Check(Near(got, 500 * (1 - Tuning.PoneroFee) / 50, 1e-9) && Near(w.DirtyOf(Assets.PSC), 2.5, 1e-6) && w.DirtyOf(Assets.Ponero) == 0 && Near(w.Get(Assets.PSC), 5, 1e-9), "兑入 Ponero:扣手续费,兑掉的脏币消失,Ponero 干净");
|
||||||
Check(bm.ToPonero(w, Assets.PSC, 5.1, 20, price) < 0, "超过每日额度不能兑");
|
Check(bm.ToPonero(w, Assets.PSC, 5.1, 20, price) < 0, "超过每日额度不能兑");
|
||||||
Check(bm.ToPonero(w, Assets.PSC, 5, 21, price) >= 0, "第二天额度恢复");
|
Check(bm.ToPonero(w, Assets.PSC, 5, 21, price) >= 0, "第二天额度恢复");
|
||||||
double back = bm.FromPonero(w, Assets.CRT, 10, 22, price);
|
double back = bm.FromPonero(w, Assets.CRT, 10, 22, price);
|
||||||
@@ -806,12 +814,12 @@ internal static class Program
|
|||||||
var lg = new BmListing { Qty = 99, Seller = 0, Item = "x", Price = 1000 };
|
var lg = new BmListing { Qty = 99, Seller = 0, Item = "x", Price = 1000 };
|
||||||
var lb = new BmListing { Qty = 99, Seller = 1, Item = "x", Price = 1000 };
|
var lb = new BmListing { Qty = 99, Seller = 1, Item = "x", Price = 1000 };
|
||||||
var w = new Wallet { Address = "t" };
|
var w = new Wallet { Address = "t" };
|
||||||
w.Add(Assets.CRT, 10000); w.Taint = 4000; w.Basis = 5000;
|
w.AddDirty(Assets.CRT, 10000, 4000); w.Basis = 5000;
|
||||||
var o = bm.Place(lb, 1, PayMode.Escrow, w, Assets.CRT, 10, price);
|
var o = bm.Place(lb, 1, PayMode.Escrow, w, Assets.CRT, 10, price);
|
||||||
Check(o != null && Near(w.Get(Assets.CRT), 10000 - 1050, 1e-9) && w.Taint < 4000 && bm.Place(lg, 1, PayMode.Escrow, w, Assets.CRC, 10, price) == null, "托管下单:扣币、污点留在订单上;不收 CRC");
|
Check(o != null && Near(w.Get(Assets.CRT), 10000 - 1050, 1e-9) && Near(o.Dirty, 420, 1e-6) && w.DirtyOf(Assets.CRT) < 4000 && bm.Place(lg, 1, PayMode.Escrow, w, Assets.CRC, 10, price) == null, "托管下单:扣币、脏的 420 枚留在订单上;不收 CRC");
|
||||||
double tBefore = 4000;
|
double tBefore = 4000;
|
||||||
var ev = bm.Night(13, false, w, new Rng(1));
|
var ev = bm.Night(13, false, w, new Rng(1));
|
||||||
Check(ev.Any(e => e.Kind == "scam_refund") && Near(w.Get(Assets.CRT), 10000, 1e-6) && Near(w.Taint, tBefore, 1e-6) && Near(w.Basis, 5000, 1e-6), "骗子卖家 + 托管:退款,污点与成本一并还回(不能借退款洗钱)");
|
Check(ev.Any(e => e.Kind == "scam_refund") && Near(w.Get(Assets.CRT), 10000, 1e-6) && Near(w.DirtyOf(Assets.CRT), tBefore, 1e-6) && Near(w.Basis, 5000, 1e-6), "骗子卖家 + 托管:退款,脏枚数与成本一并还回(不能借退款洗钱)");
|
||||||
var o2 = bm.Place(lb, 1, PayMode.Advance, w, Assets.CRT, 20, price);
|
var o2 = bm.Place(lb, 1, PayMode.Advance, w, Assets.CRT, 20, price);
|
||||||
var ev2 = bm.Night(23, false, w, new Rng(2));
|
var ev2 = bm.Night(23, false, w, new Rng(2));
|
||||||
Check(o2.State == OrderState.Lost && Near(w.Get(Assets.CRT), 10000 - 900, 1e-6), "骗子卖家 + 提前放款:钱没了");
|
Check(o2.State == OrderState.Lost && Near(w.Get(Assets.CRT), 10000 - 900, 1e-6), "骗子卖家 + 提前放款:钱没了");
|
||||||
@@ -893,7 +901,7 @@ internal static class Program
|
|||||||
b2.Night(4, false, w2, new Rng(8), 0, price);
|
b2.Night(4, false, w2, new Rng(8), 0, price);
|
||||||
Check(s2.State == SaleState.Sold, "没到放款日不动");
|
Check(s2.State == SaleState.Sold, "没到放款日不动");
|
||||||
b2.Night(5, false, w2, new Rng(9), 0, price);
|
b2.Night(5, false, w2, new Rng(9), 0, price);
|
||||||
Check(s2.State == SaleState.Paid && Near(w2.Get(Assets.CRT), crt0 + s2.Proceeds, 1e-9) && Near(w2.Taint, s2.Taint, 1e-9) && (s2.Taint == 0 || Near(s2.Taint, s2.Proceeds * BlackMarket.TaintRatio(0.8), 1e-6)), "放款:货款进钱包,污点按比例");
|
Check(s2.State == SaleState.Paid && Near(w2.Get(Assets.CRT), crt0 + s2.Proceeds, 1e-9) && Near(w2.DirtyOf(Assets.CRT), s2.Taint, 1e-9) && (s2.Taint == 0 || Near(s2.Taint, s2.Proceeds * BlackMarket.TaintRatio(0.8), 1e-6)), "放款:货款进钱包,按污点比例记脏的(CRT 价 1)");
|
||||||
// 赃物:货款按热度带污点,不走随机
|
// 赃物:货款按热度带污点,不走随机
|
||||||
var bh = new BlackMarket();
|
var bh = new BlackMarket();
|
||||||
var wh = new Wallet(); wh.Add(Assets.CRT, 1000);
|
var wh = new Wallet(); wh.Add(Assets.CRT, 1000);
|
||||||
@@ -1100,7 +1108,7 @@ internal static class Program
|
|||||||
Test("永续合约:开平仓、强平、基金与欠款、自动减仓、没收", () =>
|
Test("永续合约:开平仓、强平、基金与欠款、自动减仓、没收", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> pr = a => a == Assets.PSC ? 100 : 1;
|
Func<string, double> pr = a => a == Assets.PSC ? 100 : 1;
|
||||||
Wallet NewAcct(double crc, double taint = 0) { var w = new Wallet { Address = "pb" }; w.Add(Assets.CRC, crc); w.Taint = taint; w.Basis = crc; return w; }
|
Wallet NewAcct(double crc) { var w = new Wallet { Address = "pb" }; w.Add(Assets.CRC, crc); w.Basis = crc; return w; }
|
||||||
// 滑点:名义价值占永续深度的比例,买入往上、卖出往下
|
// 滑点:名义价值占永续深度的比例,买入往上、卖出往下
|
||||||
var bs = new PerpBook();
|
var bs = new PerpBook();
|
||||||
double pool = Tuning.PerpDepth(1);
|
double pool = Tuning.PerpDepth(1);
|
||||||
@@ -1108,25 +1116,25 @@ internal static class Program
|
|||||||
// 滑点吃掉了强平线之间的空间:开仓被拒
|
// 滑点吃掉了强平线之间的空间:开仓被拒
|
||||||
var bt = new PerpBook { DepthMult = 0.05 }; var at = NewAcct(5000);
|
var bt = new PerpBook { DepthMult = 0.05 }; var at = NewAcct(5000);
|
||||||
Check(bt.Open(at, "PSC", true, 1000, 5, 100, 1, pr) == PerpResult.Thin && bt.Positions.Count == 0 && at.Get(Assets.CRC) == 5000, "滑点大到一开就被强平的单子被拒,不扣钱");
|
Check(bt.Open(at, "PSC", true, 1000, 5, 100, 1, pr) == PerpResult.Thin && bt.Positions.Count == 0 && at.Get(Assets.CRC) == 5000, "滑点大到一开就被强平的单子被拒,不扣钱");
|
||||||
// 开仓与手续费、保证金、污点
|
// 开仓与手续费、保证金(Poinbase 没有污点)
|
||||||
var b = new PerpBook { DepthMult = 1e12 }; var a = NewAcct(2000, 1000);
|
var b = new PerpBook { DepthMult = 1e12 }; var a = NewAcct(2000);
|
||||||
Check(b.Open(a, "PSC", true, 1000, 6, 100, 1, pr) == PerpResult.Leverage && b.Open(a, "PSC", true, 3000, 3, 100, 1, pr) == PerpResult.Funds, "杠杆超限、余额不足被拒");
|
Check(b.Open(a, "PSC", true, 1000, 6, 100, 1, pr) == PerpResult.Leverage && b.Open(a, "PSC", true, 3000, 3, 100, 1, pr) == PerpResult.Funds, "杠杆超限、余额不足被拒");
|
||||||
Check(b.Open(a, "PSC", true, 1000, 5, 100, 1, pr) == PerpResult.Ok, "开 5× 多头");
|
Check(b.Open(a, "PSC", true, 1000, 5, 100, 1, pr) == PerpResult.Ok, "开 5× 多头");
|
||||||
var pos = b.Of("PSC");
|
var pos = b.Of("PSC");
|
||||||
double fee = 5000 * Tuning.PerpFee;
|
double fee = 5000 * Tuning.PerpFee;
|
||||||
Check(Math.Abs(pos.Size - 50) < 1e-9 && Math.Abs(a.Get(Assets.CRC) - (1000 - fee)) < 1e-9 && Math.Abs(pos.Taint - 500) < 1e-9, $"名义 5000,手续费 {fee},污点 500 随保证金进仓位");
|
Check(Math.Abs(pos.Size - 50) < 1e-9 && Math.Abs(a.Get(Assets.CRC) - (1000 - fee)) < 1e-9 && Math.Abs(pos.Basis - 1000) < 1e-9, $"名义 5000,手续费 {fee},成本 1000 随保证金进仓位");
|
||||||
Check(b.Open(a, "PSC", false, 100, 2, 100, 1, pr) == PerpResult.Opposite, "不能同时多空");
|
Check(b.Open(a, "PSC", false, 100, 2, 100, 1, pr) == PerpResult.Opposite, "不能同时多空");
|
||||||
Check(b.Open(a, "PSC", true, 100, 2, 100, 1, pr) == PerpResult.Single && b.Open(a, "SPARK", true, 100, 1, 10, 1, pr) == PerpResult.Single && b.Positions.Count == 1, "只有一个仓位:加仓、开别的标的都被拒,只能追加保证金");
|
Check(b.Open(a, "PSC", true, 100, 2, 100, 1, pr) == PerpResult.Single && b.Open(a, "SPARK", true, 100, 1, 10, 1, pr) == PerpResult.Single && b.Positions.Count == 1, "只有一个仓位:加仓、开别的标的都被拒,只能追加保证金");
|
||||||
Check(Math.Abs(pos.LiqPrice - (50 * 100 - 1000) / (50 * (1 - Tuning.PerpMaint))) < 1e-9 && pos.LiqPrice > 85 && pos.LiqPrice < 90, $"强平价 {pos.LiqPrice:0.0}(约 −11%)");
|
Check(Math.Abs(pos.LiqPrice - (50 * 100 - 1000) / (50 * (1 - Tuning.PerpMaint))) < 1e-9 && pos.LiqPrice > 85 && pos.LiqPrice < 90, $"强平价 {pos.LiqPrice:0.0}(约 −11%)");
|
||||||
// 平仓盈利:干净的新币,污点原额退回
|
// 平仓盈利:成本原额退回
|
||||||
double paid = b.Close(a, "PSC", 110, 2, out double d0);
|
double paid = b.Close(a, "PSC", 110, 2, out double d0);
|
||||||
double expect = 1000 + 50 * 10 - 50 * 110 * Tuning.PerpFee;
|
double expect = 1000 + 50 * 10 - 50 * 110 * Tuning.PerpFee;
|
||||||
Check(Math.Abs(paid - expect) < 1e-6 && d0 == 0 && Math.Abs(a.Taint - 1000) < 1e-6 && b.Positions.Count == 0, $"盈利平仓 {paid:0.00},污点全额退回");
|
Check(Math.Abs(paid - expect) < 1e-6 && d0 == 0 && Math.Abs(a.Basis - 2000) < 1e-6 && b.Positions.Count == 0, $"盈利平仓 {paid:0.00},成本全额退回");
|
||||||
// 平仓亏损:污点按剩下的比例退回
|
// 平仓亏损:成本按剩下的比例退回
|
||||||
var a2 = NewAcct(2000, 1000); var b2 = new PerpBook { DepthMult = 1e12 };
|
var a2 = NewAcct(2000); var b2 = new PerpBook { DepthMult = 1e12 };
|
||||||
b2.Open(a2, "PSC", true, 1000, 5, 100, 1, pr);
|
b2.Open(a2, "PSC", true, 1000, 5, 100, 1, pr);
|
||||||
double paid2 = b2.Close(a2, "PSC", 95, 2, out _);
|
double paid2 = b2.Close(a2, "PSC", 95, 2, out _);
|
||||||
Check(paid2 > 700 && paid2 < 760 && a2.Taint < 1000 - 500 * (1 - paid2 / 1000) + 1, $"亏损平仓 {paid2:0.0},污点按比例少回");
|
Check(paid2 > 700 && paid2 < 760 && a2.Basis < 2000 - 1000 * (1 - paid2 / 1000) + 1, $"亏损平仓 {paid2:0.0},成本按比例少回");
|
||||||
// 夜间强平:权益不到 10% 名义价值;剩余进基金
|
// 夜间强平:权益不到 10% 名义价值;剩余进基金
|
||||||
var b3 = new PerpBook { DepthMult = 1e12 }; var a3 = NewAcct(5000);
|
var b3 = new PerpBook { DepthMult = 1e12 }; var a3 = NewAcct(5000);
|
||||||
b3.Open(a3, "PSC", true, 1000, 5, 100, 1, pr);
|
b3.Open(a3, "PSC", true, 1000, 5, 100, 1, pr);
|
||||||
@@ -1181,15 +1189,15 @@ internal static class Program
|
|||||||
Check(!b8.Night(3, new Dictionary<string, double> { ["PSC"] = 87 }, a8, pr).Any(e => e.Kind == "wipe"), "小行情不上新闻");
|
Check(!b8.Night(3, new Dictionary<string, double> { ["PSC"] = 87 }, a8, pr).Any(e => e.Kind == "wipe"), "小行情不上新闻");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("CRA 质押池:计息、解锁期、污点随币、螺旋", () =>
|
Test("CRA 质押池:计息、解锁期、脏枚数随币、螺旋", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> price = a => a == Assets.PSC ? 100 : 1;
|
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 w = new Wallet { Address = "0xa" }; w.AddDirty(Assets.CRA, 1000, 400); w.Add(Assets.PSC, 10); w.Basis = 600;
|
||||||
var st = new Staking();
|
var st = new Staking();
|
||||||
Check(!st.Stake(w, 2000, price), "余额不足不能质押");
|
Check(!st.Stake(w, 2000, price), "余额不足不能质押");
|
||||||
Check(st.Stake(w, 500, price) && Math.Abs(w.Get(Assets.CRA) - 500) < 1e-9, "质押 500,钱包剩 500");
|
Check(st.Stake(w, 500, price) && Math.Abs(w.Get(Assets.CRA) - 500) < 1e-9, "质押 500,钱包剩 500");
|
||||||
double lotTaint = st.Of("0xa").Taint;
|
double lotTaint = st.Of("0xa").Dirty;
|
||||||
Check(Math.Abs(lotTaint - 400 * 500.0 / 2000) < 1e-6 && Math.Abs(w.Taint - (400 - lotTaint)) < 1e-6, $"污点按价值比例进仓位:{lotTaint}");
|
Check(Math.Abs(lotTaint - 200) < 1e-6 && Math.Abs(w.DirtyOf(Assets.CRA) - 200) < 1e-6, $"CRA 40% 脏,质押 500 带走 200 枚脏的:{lotTaint}");
|
||||||
var e1 = st.Night(1, Tuning.CraRate, _ => w);
|
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(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");
|
Check(!st.RequestUnstake("0xa", 9999, 1) && st.RequestUnstake("0xa", 200, 1), "申请取出 200");
|
||||||
@@ -1199,7 +1207,7 @@ internal static class Program
|
|||||||
Check(w.Get(Assets.CRA) < 501, "解锁期没到不能取");
|
Check(w.Get(Assets.CRA) < 501, "解锁期没到不能取");
|
||||||
for (int d = 3; d <= 1 + Tuning.CraUnlockDays; d++) st.Night(d, Tuning.CraRate, _ => w);
|
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(Math.Abs(w.Get(Assets.CRA) - 700) < 1e-6, $"到期自动回钱包 200:{w.Get(Assets.CRA):0.##}");
|
||||||
Check(w.Taint > 400 - lotTaint + 1, "污点按比例回来");
|
Check(w.DirtyOf(Assets.CRA) > 200 + 1 && w.DirtyOf(Assets.CRA) < 200 + 80 + 1e-6, $"脏枚数按比例回来(利息干净):{w.DirtyOf(Assets.CRA):0.##}");
|
||||||
// 螺旋:质押的 CRA 取回后只值当时的价格
|
// 螺旋:质押的 CRA 取回后只值当时的价格
|
||||||
var s = new Stablecoins(); s.CraCrashDay = 5;
|
var s = new Stablecoins(); s.CraCrashDay = 5;
|
||||||
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
|
for (int d = 5; d <= 7; d++) s.Night(d, new Rng(1), 0);
|
||||||
@@ -1261,19 +1269,9 @@ internal static class Program
|
|||||||
for (int i = 0; i < n; i++) { int d = 1; while (!rng.Chance(Wallet.DrainChance(mid))) d++; sum += d; }
|
for (int i = 0; i < n; i++) { int d = 1; while (!rng.Chance(Wallet.DrainChance(mid))) d++; sum += d; }
|
||||||
Check(Math.Abs(sum / n - 4) < 0.25, $"模拟平均 {sum / n:0.00} 天被转走(期望 4)");
|
Check(Math.Abs(sum / n - 4) < 0.25, $"模拟平均 {sum / n:0.00} 天被转走(期望 4)");
|
||||||
var w = new Wallet { Address = "a" };
|
var w = new Wallet { Address = "a" };
|
||||||
w.Add(Assets.PSC, 50); w.Add(Assets.CRT, 1000); w.Taint = 300; w.Basis = 900; w.Freeze(Assets.CRT, 0.5, 9);
|
w.Add(Assets.PSC, 50); w.AddDirty(Assets.CRT, 1000, 300); w.Basis = 900; w.Freeze(Assets.CRT, 0.5, 9);
|
||||||
double v = w.Drain(a => a == Assets.PSC ? 100 : 1);
|
double v = w.Drain(a => a == Assets.PSC ? 100 : 1);
|
||||||
Check(Math.Abs(v - 6000) < 1e-6 && w.Balances.Count == 0 && w.Frozen.Count == 0 && w.Taint == 0 && w.Basis == 0, $"全部转走(含冻结),污点和成本清零:{v}");
|
Check(Math.Abs(v - 6000) < 1e-6 && w.Balances.Count == 0 && w.Frozen.Count == 0 && w.Dirty.Count == 0 && w.Basis == 0, $"全部转走(含冻结),脏枚数和成本清零:{v}");
|
||||||
});
|
|
||||||
|
|
||||||
Test("被标记的钱包转出可追踪的币,收款方也被标记;Ponero 不会", () =>
|
|
||||||
{
|
|
||||||
Func<string, double> price = x => 1;
|
|
||||||
var f = new Wallet { Address = "f", Flagged = true }; f.Add(Assets.CRC, 100); f.Add(Assets.Ponero, 100);
|
|
||||||
var p1 = new Wallet { Address = "p1" }; var p2 = new Wallet { Address = "p2" };
|
|
||||||
Wallet.Transfer(f, p1, Assets.CRC, 10, price);
|
|
||||||
Wallet.Transfer(f, p2, Assets.Ponero, 10, price);
|
|
||||||
Check(p1.Flagged && !p2.Flagged, "CRC 带标记,Ponero 不带");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("多钱包:退款、出售回款、混币提回都回到原来的钱包", () =>
|
Test("多钱包:退款、出售回款、混币提回都回到原来的钱包", () =>
|
||||||
@@ -1380,12 +1378,11 @@ internal static class Program
|
|||||||
Check(o.Value >= 500 * Tuning.OtcValueMinRents && o.Value <= 500 * Tuning.OtcValueMaxRents && Math.Abs(o.Cash - o.Value * Otc.CutFor(o.TaintRatio)) <= 1, $"市值与现金价:{o.Value:0} / {o.Cash}");
|
Check(o.Value >= 500 * Tuning.OtcValueMinRents && o.Value <= 500 * Tuning.OtcValueMaxRents && Math.Abs(o.Cash - o.Value * Otc.CutFor(o.TaintRatio)) <= 1, $"市值与现金价:{o.Value:0} / {o.Cash}");
|
||||||
}
|
}
|
||||||
Check(Otc.CutFor(0) == Tuning.OtcCutClean && Otc.CutFor(1) == Tuning.OtcCutDirty && Otc.CutFor(0.3) > Otc.CutFor(0.7), "折扣按污点比例线性降低");
|
Check(Otc.CutFor(0) == Tuning.OtcCutClean && Otc.CutFor(1) == Tuning.OtcCutDirty && Otc.CutFor(0.3) > Otc.CutFor(0.7), "折扣按污点比例线性降低");
|
||||||
// 收下:币进钱包,成本是付的现金,污点 = 市值 × 比例(带上限)
|
// 收下:币进钱包,其中 数量 × 污点比例 枚是脏的,成本是付的现金
|
||||||
var oc = new OtcOffer { Side = OtcSide.Sell, Asset = Assets.CRT, Qty = 1000, Value = 1000, TaintRatio = 0.4, Cash = 700 };
|
var oc = new OtcOffer { Side = OtcSide.Sell, Asset = Assets.CRT, Qty = 1000, Value = 1000, TaintRatio = 0.4, Cash = 700 };
|
||||||
var w = new Wallet();
|
var w = new Wallet();
|
||||||
Check(Otc.Receive(w, oc, pr) == 0 && Near(w.Get(Assets.CRT), 1000, 1e-9) && Near(w.Taint, 400, 1e-9) && Near(w.Basis, 700, 1e-9), "污点按比例,成本是付的现金");
|
Otc.Receive(w, oc);
|
||||||
var wf = new Wallet(); wf.Add(Assets.CRC, 100); wf.Taint = 1000;
|
Check(Near(w.Get(Assets.CRT), 1000, 1e-9) && Near(w.DirtyOf(Assets.CRT), 400, 1e-9) && Near(w.Basis, 700, 1e-9), "1000 CRT 里 400 枚脏,成本是付的现金");
|
||||||
Check(Near(Otc.Receive(wf, oc, pr), 300, 1e-9) && Near(wf.Taint, 1100, 1e-9), "原有污点多时超出的部分返回");
|
|
||||||
// Ponero:兑换处开放后偶尔有,不带污点
|
// Ponero:兑换处开放后偶尔有,不带污点
|
||||||
int pon = 0;
|
int pon = 0;
|
||||||
for (int i = 0; i < 4000; i++) { var o = Otc.MakeSell(none, true, pr, 500, rng); if (o.Asset == Assets.Ponero) { pon++; Check(o.TaintRatio == 0 && o.Cash >= o.Value * Tuning.OtcPoneroCutMin - 1, "Ponero 不带污点"); } }
|
for (int i = 0; i < 4000; i++) { var o = Otc.MakeSell(none, true, pr, 500, rng); if (o.Asset == Assets.Ponero) { pon++; Check(o.TaintRatio == 0 && o.Cash >= o.Value * Tuning.OtcPoneroCutMin - 1, "Ponero 不带污点"); } }
|
||||||
@@ -1424,7 +1421,7 @@ internal static class Program
|
|||||||
Func<string, double> pr = a => 1;
|
Func<string, double> pr = a => 1;
|
||||||
var w = new Wallet { Address = "w" }; w.Add(Assets.CRT, 30000);
|
var w = new Wallet { Address = "w" }; w.Add(Assets.CRT, 30000);
|
||||||
var m = new OwnMixer();
|
var m = new OwnMixer();
|
||||||
Check(m.Inject(w, Assets.CRT, 20000, pr) && m.Pool(Assets.CRT).Capital == 20000 && m.Pool(Assets.CRT).CapTaint == 0, "干净的币注资,本金不带污点");
|
Check(m.Inject(w, Assets.CRT, 20000, pr) && m.Pool(Assets.CRT).Capital == 20000 && m.Pool(Assets.CRT).CapDirty == 0, "干净的币注资,本金不带污点");
|
||||||
Check(!m.Inject(w, Assets.CRT, 1e6, pr) && !m.Inject(w, Assets.SPARK, 1, pr), "余额不够、币种不支持被拒");
|
Check(!m.Inject(w, Assets.CRT, 1e6, pr) && !m.Inject(w, Assets.SPARK, 1, pr), "余额不够、币种不支持被拒");
|
||||||
Check(OwnMixer.RoundRate(40000) > OwnMixer.RoundRate(10000) && OwnMixer.RoundRate(1e9) <= Tuning.MixerCleanRate + 1e-9 && OwnMixer.RoundRate(0) == 0, "匿名集越大清洗率越高,封顶基准清洗率");
|
Check(OwnMixer.RoundRate(40000) > OwnMixer.RoundRate(10000) && OwnMixer.RoundRate(1e9) <= Tuning.MixerCleanRate + 1e-9 && OwnMixer.RoundRate(0) == 0, "匿名集越大清洗率越高,封顶基准清洗率");
|
||||||
m.Start(pr);
|
m.Start(pr);
|
||||||
@@ -1446,21 +1443,21 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
Check(deposits > 0 && payouts > 0 && m.FeesTotal > fees0, $"营业中有存入和出款:{deposits} / {payouts},手续费 {m.FeesTotal - fees0:0}");
|
Check(deposits > 0 && payouts > 0 && m.FeesTotal > fees0, $"营业中有存入和出款:{deposits} / {payouts},手续费 {m.FeesTotal - fees0:0}");
|
||||||
Check(m.Pending.All(x => x.ReadyDay >= 50), "到期的都出款了");
|
Check(m.Pending.All(x => x.ReadyDay >= 50), "到期的都出款了");
|
||||||
// 取回:收入全额带污点,本金按本金的污点
|
// 取回:收入整笔是脏的,本金按本金的脏比例
|
||||||
var m2 = new OwnMixer(); var w2 = new Wallet { Address = "w2" }; w2.Add(Assets.PSC, 1000); w2.Taint = 500;
|
var m2 = new OwnMixer(); var w2 = new Wallet { Address = "w2" }; w2.AddDirty(Assets.PSC, 1000, 500);
|
||||||
m2.Inject(w2, Assets.PSC, 1000, pr);
|
m2.Inject(w2, Assets.PSC, 1000, pr);
|
||||||
Check(Near(m2.Pool(Assets.PSC).CapTaint, 500, 1e-9) && w2.Taint < 1e-9, "脏币注资,污点跟着进本金");
|
Check(Near(m2.Pool(Assets.PSC).CapDirty, 500, 1e-9) && w2.DirtyOf(Assets.PSC) < 1e-9, "一半脏的币注资,脏枚数跟着进本金");
|
||||||
m2.Pool(Assets.PSC).Earned = 100;
|
m2.Pool(Assets.PSC).Earned = 100;
|
||||||
var w3 = new Wallet { Address = "w3" }; w3.Add(Assets.CRC, 10000);
|
var w3 = new Wallet { Address = "w3" }; w3.Add(Assets.CRC, 10000);
|
||||||
Check(m2.Withdraw(w3, Assets.PSC, 100, pr, out double o1) && Near(w3.Taint, 100, 1e-9) && o1 == 0, "先取收入:全额带污点");
|
Check(m2.Withdraw(w3, Assets.PSC, 100) && Near(w3.DirtyOf(Assets.PSC), 100, 1e-9) && w3.DirtyOf(Assets.CRC) == 0, "先取收入:整笔脏,别的币不受影响");
|
||||||
Check(m2.Withdraw(w3, Assets.PSC, 500, pr, out _) && Near(w3.Taint, 100 + 250, 1e-9), "再取本金:按本金的污点比例");
|
Check(m2.Withdraw(w3, Assets.PSC, 500) && Near(w3.DirtyOf(Assets.PSC), 100 + 250, 1e-9), "再取本金:按本金的脏比例");
|
||||||
Check(!m2.Withdraw(w3, Assets.PSC, 1000, pr, out _), "不能超过可取回的数量");
|
Check(!m2.Withdraw(w3, Assets.PSC, 1000), "不能超过可取回的数量");
|
||||||
m2.Pending.Add(new OwnMixDeposit { Asset = Assets.PSC, Amount = 300, Taint = 200, Rounds = 2, ReadyDay = 99 });
|
m2.Pending.Add(new OwnMixDeposit { Asset = Assets.PSC, Amount = 300, Taint = 200, Rounds = 2, ReadyDay = 99 });
|
||||||
Check(Near(m2.Free(Assets.PSC), 500, 1e-9) && Near(m2.Total(Assets.PSC), 800, 1e-9), "客户在途的币不能取");
|
Check(Near(m2.Free(Assets.PSC), 500, 1e-9) && Near(m2.Total(Assets.PSC), 800, 1e-9), "客户在途的币不能取");
|
||||||
// 卷款跑路:连同客户的币全部卷走、全额带污点,永久关闭
|
// 卷款跑路:连同客户的币全部卷走、整笔脏,永久关闭
|
||||||
var w4 = new Wallet { Address = "w4" };
|
var w4 = new Wallet { Address = "w4" };
|
||||||
var got = m2.Rug(w4, pr, out double o4);
|
var got = m2.Rug(w4);
|
||||||
Check(Near(w4.Get(Assets.PSC), 800, 1e-9) && Near(w4.Taint, 800, 1e-9) && m2.Closed && !m2.Open && got.Count == 1, "卷走全部、全额污点、关闭");
|
Check(Near(w4.Get(Assets.PSC), 800, 1e-9) && Near(w4.DirtyOf(Assets.PSC), 800, 1e-9) && m2.Closed && !m2.Open && got.Count == 1, "卷走全部、整笔脏、关闭");
|
||||||
Check(m2.Night(100, pr, 60, Tuning.MixerFee, rr, true, 1, false, new Rng(1)).Count == 0, "关闭后不再有夜间事件");
|
Check(m2.Night(100, pr, 60, Tuning.MixerFee, rr, true, 1, false, new Rng(1)).Count == 0, "关闭后不再有夜间事件");
|
||||||
// 查封:风声足够大时被查封,停业若干天
|
// 查封:风声足够大时被查封,停业若干天
|
||||||
var m3 = new OwnMixer { Heat = 1e6 }; m3.Inject(new Wallet { Address = "x", Balances = { [Assets.CRT] = 5000 } }, Assets.CRT, 5000, pr); m3.Start(pr);
|
var m3 = new OwnMixer { Heat = 1e6 }; m3.Inject(new Wallet { Address = "x", Balances = { [Assets.CRT] = 5000 } }, Assets.CRT, 5000, pr); m3.Start(pr);
|
||||||
@@ -1495,11 +1492,11 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("预测市场:买入、卖出、手续费、污点、持仓限制", () =>
|
Test("预测市场:买入、卖出、手续费、脏枚数、持仓限制", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> pr = a => 1;
|
Func<string, double> pr = a => 1;
|
||||||
var acct = new Wallet { Address = "poinbase" };
|
var acct = new Wallet { Address = "w" };
|
||||||
acct.Add(Assets.CRC, 1000); acct.Taint = 400; acct.Basis = 1000;
|
acct.AddDirty(Assets.CRC, 1000, 400); acct.Basis = 1000;
|
||||||
var bk = new PredictBook();
|
var bk = new PredictBook();
|
||||||
var m = PredictMarket.Create(++bk.Seq, PredictKind.Purity, "gutter", "t", 8500, 5, 6, 6, 0.5);
|
var m = PredictMarket.Create(++bk.Seq, PredictKind.Purity, "gutter", "t", 8500, 5, 6, 6, 0.5);
|
||||||
bk.Markets.Add(m);
|
bk.Markets.Add(m);
|
||||||
@@ -1511,13 +1508,13 @@ internal static class Program
|
|||||||
Check(res == PredictResult.Ok && sh > 0, "买入成功");
|
Check(res == PredictResult.Ok && sh > 0, "买入成功");
|
||||||
var pos = bk.PosOf(m.Id, acct.Address);
|
var pos = bk.PosOf(m.Id, acct.Address);
|
||||||
Check(Math.Abs(pos.Cost - 100) < 1e-6 && Math.Abs(acct.Get(Assets.CRC) - (1000 - spend)) < 1e-6, $"成本 100(另付手续费):{pos.Cost:0.00}");
|
Check(Math.Abs(pos.Cost - 100) < 1e-6 && Math.Abs(acct.Get(Assets.CRC) - (1000 - spend)) < 1e-6, $"成本 100(另付手续费):{pos.Cost:0.00}");
|
||||||
Check(Math.Abs(pos.Taint - 400 * spend / 1000) < 1e-6 && Math.Abs(acct.Taint - (400 - 400 * spend / 1000)) < 1e-6, $"污点按花掉的价值比例带进持仓:{pos.Taint:0.00}");
|
Check(Math.Abs(pos.Dirty - 0.4 * spend) < 1e-6 && Math.Abs(acct.DirtyOf(Assets.CRC) - (400 - 0.4 * spend)) < 1e-6, $"CRC 40% 脏,花掉的按比例带进持仓:{pos.Dirty:0.00}");
|
||||||
Check(bk.Buy(acct, m, false, 10, 5, pr, false, out _) == PredictResult.Opposite, "不能同盘反方向");
|
Check(bk.Buy(acct, m, false, 10, 5, pr, false, out _) == PredictResult.Opposite, "不能同盘反方向");
|
||||||
// 卖出:价差为 0,只付手续费
|
// 卖出:价差为 0,只付手续费
|
||||||
double before = acct.Get(Assets.CRC);
|
double before = acct.Get(Assets.CRC);
|
||||||
Check(bk.SellAll(acct, m, 5, pr, out double got) == PredictResult.Ok && Math.Abs(got - 100 * (1 - Tuning.PredictFee)) < 1e-6, $"原价卖回只扣手续费:{got:0.00}");
|
Check(bk.SellAll(acct, m, 5, pr, out double got) == PredictResult.Ok && Math.Abs(got - 100 * (1 - Tuning.PredictFee)) < 1e-6, $"原价卖回只扣手续费:{got:0.00}");
|
||||||
Check(Math.Abs(acct.Get(Assets.CRC) - before - got) < 1e-6 && bk.PosOf(m.Id, acct.Address) == null, "回到账户");
|
Check(Math.Abs(acct.Get(Assets.CRC) - before - got) < 1e-6 && bk.PosOf(m.Id, acct.Address) == null, "回到账户");
|
||||||
Check(acct.Taint < 400 && acct.Taint > 359.2, "卖回时污点按退回的比例回来");
|
Check(acct.DirtyOf(Assets.CRC) < 400 && acct.DirtyOf(Assets.CRC) > 359.2, "卖回时脏枚数按退回的比例回来");
|
||||||
// 持仓上限
|
// 持仓上限
|
||||||
var big = new Wallet { Address = "x" }; big.Add(Assets.CRC, 1e7);
|
var big = new Wallet { Address = "x" }; big.Add(Assets.CRC, 1e7);
|
||||||
Check(bk.Buy(big, m, true, 1e6, 5, pr, false, out _) == PredictResult.Cap, "超过份额上限被拒");
|
Check(bk.Buy(big, m, true, 1e6, 5, pr, false, out _) == PredictResult.Cap, "超过份额上限被拒");
|
||||||
@@ -1555,29 +1552,28 @@ internal static class Program
|
|||||||
double c2 = acct.Get(Assets.CRC);
|
double c2 = acct.Get(Assets.CRC);
|
||||||
var ev2 = bk.Night(9, new string[0], bk.Happened, _ => acct, pr, rng);
|
var ev2 = bk.Night(9, new string[0], bk.Happened, _ => acct, pr, rng);
|
||||||
Check(ev2.Any(e => e.Kind == "void") && Math.Abs(acct.Get(Assets.CRC) - c2 - 50) < 1e-6, $"缺数据作废并退本金:{acct.Get(Assets.CRC) - c2:0.00}");
|
Check(ev2.Any(e => e.Kind == "void") && Math.Abs(acct.Get(Assets.CRC) - c2 - 50) < 1e-6, $"缺数据作废并退本金:{acct.Get(Assets.CRC) - c2:0.00}");
|
||||||
// 内幕单:照常兑付全部份数,只有内幕份额对应的兑付记污点
|
// 内幕单:照常兑付全部份数,只有内幕份额对应的兑付记成脏的 CRC
|
||||||
var b2 = new PredictBook(); var a2 = new Wallet { Address = "p" }; a2.Add(Assets.CRC, 1e6);
|
var b2 = new PredictBook(); var a2 = new Wallet { Address = "p" }; a2.Add(Assets.CRC, 1e6);
|
||||||
var mk = PredictMarket.Create(++b2.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b2.Markets.Add(mk);
|
var mk = PredictMarket.Create(++b2.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b2.Markets.Add(mk);
|
||||||
b2.Buy(a2, mk, true, mk.BuyCost(true, 0.2 * mk.ShareCap) * 1.02, 4, pr, true, out double si);
|
b2.Buy(a2, mk, true, mk.BuyCost(true, 0.2 * mk.ShareCap) * 1.02, 4, pr, true, out double si);
|
||||||
b2.Buy(a2, mk, true, 50, 4, pr, false, out double sn);
|
b2.Buy(a2, mk, true, 50, 4, pr, false, out double sn);
|
||||||
double c2b = a2.Get(Assets.CRC), t2b = a2.Taint;
|
double c2b = a2.Get(Assets.CRC), t2b = a2.DirtyOf(Assets.CRC);
|
||||||
var e2 = b2.Night(5, new string[0], mm => true, _ => a2, pr, new Rng(1));
|
var e2 = b2.Night(5, new string[0], mm => true, _ => a2, pr, new Rng(1));
|
||||||
Check(e2[0].Kind == "insider" && Near(e2[0].Amount, si + sn, 1e-6), $"内幕单照常结算:{e2[0].Kind}");
|
Check(e2[0].Kind == "insider" && Near(e2[0].Amount, si + sn, 1e-6), $"内幕单照常结算:{e2[0].Kind}");
|
||||||
Check(Near(a2.Get(Assets.CRC) - c2b, si + sn, 1e-6), "全部份数照常兑付");
|
Check(Near(a2.Get(Assets.CRC) - c2b, si + sn, 1e-6), "全部份数照常兑付");
|
||||||
Check(Near(a2.Taint - t2b, si, 1e-6) && Near(e2[0].Taint, si, 1e-6) && e2[0].Over == 0 && e2[0].Fraud == 0, $"只有内幕份额的兑付记污点:+{a2.Taint - t2b:0.00} / {si:0.00}");
|
Check(Near(a2.DirtyOf(Assets.CRC) - t2b, si, 1e-6) && Near(e2[0].Taint, si, 1e-6), $"只有内幕份额的兑付记成脏的:+{a2.DirtyOf(Assets.CRC) - t2b:0.00} / {si:0.00}");
|
||||||
// 不是内幕单:普通结算,不加污点
|
// 不是内幕单:普通结算,不加污点
|
||||||
var b3 = new PredictBook(); var a3 = new Wallet { Address = "p" }; a3.Add(Assets.CRC, 1e6);
|
var b3 = new PredictBook(); var a3 = new Wallet { Address = "p" }; a3.Add(Assets.CRC, 1e6);
|
||||||
var m3 = PredictMarket.Create(++b3.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b3.Markets.Add(m3);
|
var m3 = PredictMarket.Create(++b3.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b3.Markets.Add(m3);
|
||||||
b3.Buy(a3, m3, true, 200, 4, pr, false, out _);
|
b3.Buy(a3, m3, true, 200, 4, pr, false, out _);
|
||||||
Check(b3.Night(5, new string[0], mm => true, _ => a3, pr, new Rng(1))[0].Kind == "win" && a3.Taint == 0, "非内幕单不记污点");
|
Check(b3.Night(5, new string[0], mm => true, _ => a3, pr, new Rng(1))[0].Kind == "win" && a3.Taint(pr) == 0, "非内幕单不记污点");
|
||||||
// 污点上限:钱包原有污点已超过价值(币价跌过),新加的全部超出,折成罪证
|
// 拿脏 CRC 下的内幕单:带回的脏枚数加上内幕记的,整笔兑付都是脏的,不会多记到钱包里别的 CRC 上
|
||||||
var b4 = new PredictBook(); var a4 = new Wallet { Address = "p" }; a4.Add(Assets.CRC, 1e5);
|
var b4 = new PredictBook(); var a4 = new Wallet { Address = "p" }; a4.AddDirty(Assets.CRC, 1e4, 1e4); a4.Add(Assets.CRC, 1e5);
|
||||||
var m4 = PredictMarket.Create(++b4.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b4.Markets.Add(m4);
|
var m4 = PredictMarket.Create(++b4.Seq, PredictKind.Event, "e", "t", 0, 4, 5, 5, 0.1); b4.Markets.Add(m4);
|
||||||
b4.Buy(a4, m4, true, m4.BuyCost(true, 0.1 * m4.ShareCap) * 1.02, 4, pr, true, out double s4);
|
b4.Buy(a4, m4, true, m4.BuyCost(true, 0.1 * m4.ShareCap) * 1.02, 4, pr, true, out double s4);
|
||||||
a4.Taint = a4.Value(pr) + 1000;
|
double d4 = a4.DirtyOf(Assets.CRC), pd4 = b4.Positions[0].Dirty;
|
||||||
var e4 = b4.Night(5, new string[0], mm => true, _ => a4, pr, new Rng(1));
|
var e4 = b4.Night(5, new string[0], mm => true, _ => a4, pr, new Rng(1));
|
||||||
Check(e4[0].Kind == "insider" && e4[0].Taint == 0 && Near(e4[0].Over, s4, 1e-6), $"污点已满时全部超出:{e4[0].Over:0.00}");
|
Check(e4[0].Kind == "insider" && Near(a4.DirtyOf(Assets.CRC) - d4, s4, 1e-6) && Near(e4[0].Taint + pd4, s4, 1e-6), $"兑付 {s4:0.00} 全部记脏:带回 {pd4:0.00} + 内幕 {e4[0].Taint:0.00}");
|
||||||
Check(Near(e4[0].Fraud, Wallet.OverflowFraud(s4), 1e-9) && e4[0].Fraud <= Tuning.PredictFraudCap, "超出的部分按比例记罪证,有上限");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("预测市场:多钱包持仓各回各的钱包,内幕污点各记各的", () =>
|
Test("预测市场:多钱包持仓各回各的钱包,内幕污点各记各的", () =>
|
||||||
@@ -1596,12 +1592,13 @@ internal static class Program
|
|||||||
Check(bk.SellAll(w2, m, 4, pr, out double got) == PredictResult.Ok && got > 0 && bk.PosOf(m.Id, "0xb") == null && bk.PosOf(m.Id, "0xa") != null, "卖出只动自己钱包的持仓");
|
Check(bk.SellAll(w2, m, 4, pr, out double got) == PredictResult.Ok && got > 0 && bk.PosOf(m.Id, "0xb") == null && bk.PosOf(m.Id, "0xa") != null, "卖出只动自己钱包的持仓");
|
||||||
Check(bk.Buy(w2, m, true, m.BuyCost(true, half) * 1.02, 4, pr, true, out _) == PredictResult.Ok, "再买");
|
Check(bk.Buy(w2, m, true, m.BuyCost(true, half) * 1.02, 4, pr, true, out _) == PredictResult.Ok, "再买");
|
||||||
// 两个钱包的内幕份额各自记在自己的钱包上
|
// 两个钱包的内幕份额各自记在自己的钱包上
|
||||||
double a0 = w1.Get(Assets.CRC), b0 = w2.Get(Assets.CRC), ta = w1.Taint, tb = w2.Taint;
|
double a0 = w1.Get(Assets.CRC), b0 = w2.Get(Assets.CRC), ta = w1.DirtyOf(Assets.CRC), tb = w2.DirtyOf(Assets.CRC);
|
||||||
double sa = bk.PosOf(m.Id, "0xa").Shares, sb = bk.PosOf(m.Id, "0xb").Shares;
|
double sa = bk.PosOf(m.Id, "0xa").Shares, sb = bk.PosOf(m.Id, "0xb").Shares;
|
||||||
double ca = bk.PosOf(m.Id, "0xa").Taint, cb = bk.PosOf(m.Id, "0xb").Taint; // 买入时随资金带进持仓的污点,兑付时原样回来
|
double ca = bk.PosOf(m.Id, "0xa").Dirty, cb = bk.PosOf(m.Id, "0xb").Dirty; // 买入时随资金带进持仓的脏枚数,兑付时原样回来
|
||||||
var ev = bk.Night(5, new string[0], x => true, pick, pr, new Rng(1));
|
var ev = bk.Night(5, new string[0], x => true, pick, pr, new Rng(1));
|
||||||
Check(ev[0].Kind == "insider" && Near(w1.Get(Assets.CRC) - a0, sa, 1e-6) && Near(w2.Get(Assets.CRC) - b0, sb, 1e-6), "各自的钱包收到兑付");
|
Check(ev[0].Kind == "insider" && Near(w1.Get(Assets.CRC) - a0, sa, 1e-6) && Near(w2.Get(Assets.CRC) - b0, sb, 1e-6), "各自的钱包收到兑付");
|
||||||
Check(Near(w1.Taint - ta - ca, sa, 1e-6) && Near(w2.Taint - tb - cb, sb, 1e-6) && Near(ev[0].Taint, sa + sb, 1e-6), "内幕污点各记各的钱包");
|
Check(Near(w1.DirtyOf(Assets.CRC) - ta, sa, 1e-6) && Near(w2.DirtyOf(Assets.CRC) - tb, sb, 1e-6) && Near(ev[0].Taint, sa - ca + sb - cb, 1e-6) && cb > 0,
|
||||||
|
$"各记各的钱包,整笔兑付都是脏的(B 下注的 CRC 里本来有 {cb:0.00} 枚脏的,内幕只补记其余部分)");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("预测市场:夜间消息反应、情报、新盘口先验", () =>
|
Test("预测市场:夜间消息反应、情报、新盘口先验", () =>
|
||||||
@@ -1676,7 +1673,7 @@ internal static class Program
|
|||||||
var m = PredictMarket.Create(++bk.Seq, PredictKind.Price, "PSC", "PSC", 100, 4, 5, 5, 0.3); bk.Markets.Add(m);
|
var m = PredictMarket.Create(++bk.Seq, PredictKind.Price, "PSC", "PSC", 100, 4, 5, 5, 0.3); bk.Markets.Add(m);
|
||||||
bk.Buy(w, m, yes, 510, 4, a => 1, false, out _);
|
bk.Buy(w, m, yes, 510, 4, a => 1, false, out _);
|
||||||
var ev = bk.Night(5, new string[0], x => outcome, _ => w, a => 1, new Rng(sd), push);
|
var ev = bk.Night(5, new string[0], x => outcome, _ => w, a => 1, new Rng(sd), push);
|
||||||
if (ev[0].Kind == "manip") { if (yes && push > 0) manip++; else Check(false, "不该被判操纵"); Check(ev[0].Fraud == 0 && Near(ev[0].Taint, ev[0].Amount, 1e-6) && Near(w.Taint, ev[0].Amount, 1e-6), "照常兑付,整笔兑付记污点"); Check(w.Get(Assets.CRC) > 1e5 - 510, "本金不没收"); }
|
if (ev[0].Kind == "manip") { if (yes && push > 0) manip++; else Check(false, "不该被判操纵"); Check(Near(ev[0].Taint, ev[0].Amount, 1e-6) && Near(w.DirtyOf(Assets.CRC), ev[0].Amount, 1e-6), "照常兑付,整笔兑付记成脏的"); Check(w.Get(Assets.CRC) > 1e5 - 510, "本金不没收"); }
|
||||||
else if (yes && push > 0) win++; else if (push == 0) noPush++;
|
else if (yes && push > 0) win++; else if (push == 0) noPush++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1708,11 +1705,11 @@ internal static class Program
|
|||||||
var q = new Ponzi(); q.Start(poor, 0.10, 20);
|
var q = new Ponzi(); q.Start(poor, 0.10, 20);
|
||||||
q.Pool = 100000; var ev2 = q.Night(20, 50, poor, new Rng(1));
|
q.Pool = 100000; var ev2 = q.Night(20, 50, poor, new Rng(1));
|
||||||
Check(ev2 != null && ev2.Kind == "collapse", "账户里没钱补利息:崩盘");
|
Check(ev2 != null && ev2.Kind == "collapse", "账户里没钱补利息:崩盘");
|
||||||
// 卷走:池子进账户、污点全额
|
// 卷走:池子进钱包、整笔脏
|
||||||
var w = new Wallet { Address = "y" }; w.Add(Assets.CRC, 2000);
|
var w = new Wallet { Address = "y" }; w.Add(Assets.CRC, 2000);
|
||||||
var r = new Ponzi(); r.Start(w, 0.04, 20); r.Pool = 5000;
|
var r = new Ponzi(); r.Start(w, 0.04, 20); r.Pool = 5000;
|
||||||
double cash = w.Get(Assets.CRC);
|
double cash = w.Get(Assets.CRC);
|
||||||
Check(Math.Abs(r.Rug(w) - 5000) < 1e-9 && Math.Abs(w.Get(Assets.CRC) - cash - 5000) < 1e-9 && Math.Abs(w.Taint - 5000) < 1e-9 && r.Done, "卷走:池子进账户,污点全额");
|
Check(Math.Abs(r.Rug(w) - 5000) < 1e-9 && Math.Abs(w.Get(Assets.CRC) - cash - 5000) < 1e-9 && Math.Abs(w.DirtyOf(Assets.CRC) - 5000) < 1e-9 && r.Done, "卷走:池子进钱包,这 5000 CRC 整笔脏");
|
||||||
// 被举报概率随日息和池子升高
|
// 被举报概率随日息和池子升高
|
||||||
Check(Ponzi.ReportChance(0.10, 5000, 20) > Ponzi.ReportChance(0.02, 5000, 20) && Ponzi.ReportChance(0.04, 9000, 20) > Ponzi.ReportChance(0.04, 100, 20), "日息越高、池子越大越容易被举报");
|
Check(Ponzi.ReportChance(0.10, 5000, 20) > Ponzi.ReportChance(0.02, 5000, 20) && Ponzi.ReportChance(0.04, 9000, 20) > Ponzi.ReportChance(0.04, 100, 20), "日息越高、池子越大越容易被举报");
|
||||||
Check(Ponzi.InflowMean(20, 0.08, 50) > Ponzi.InflowMean(20, 0.04, 50) * 2, "日息高于 4% 时存入按指数放大");
|
Check(Ponzi.InflowMean(20, 0.08, 50) > Ponzi.InflowMean(20, 0.04, 50) * 2, "日息高于 4% 时存入按指数放大");
|
||||||
@@ -1798,7 +1795,7 @@ internal static class Program
|
|||||||
Check(Math.Abs(rugs / 400.0 - Tuning.YieldRugNightly) < 0.05, $"骗局池每晚跑路概率:{rugs / 400.0:0.00}");
|
Check(Math.Abs(rugs / 400.0 - Tuning.YieldRugNightly) < 0.05, $"骗局池每晚跑路概率:{rugs / 400.0:0.00}");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("预测市场:内幕先买后卖,卖出所得的内幕部分记污点", () =>
|
Test("预测市场:内幕先买后卖,卖出所得的内幕部分记成脏的", () =>
|
||||||
{
|
{
|
||||||
var bk = new PredictBook(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRC, 1e6);
|
var bk = new PredictBook(); var w = new Wallet { Address = "w" }; w.Add(Assets.CRC, 1e6);
|
||||||
var m = PredictMarket.Create(++bk.Seq, PredictKind.Event, "e", "t", 0, 4, 7, 7, 0.05); bk.Markets.Add(m);
|
var m = PredictMarket.Create(++bk.Seq, PredictKind.Event, "e", "t", 0, 4, 7, 7, 0.05); bk.Markets.Add(m);
|
||||||
@@ -1807,29 +1804,21 @@ internal static class Program
|
|||||||
double cost = bk.PosOf(m.Id, "w").Cost;
|
double cost = bk.PosOf(m.Id, "w").Cost;
|
||||||
double p1 = m.PYes, p2 = p1 + (1 - p1) / 2;
|
double p1 = m.PYes, p2 = p1 + (1 - p1) / 2;
|
||||||
m.QYes = m.QNo + m.B * Math.Log(p2 / (1 - p2)); // 夜里价格又涨了一截
|
m.QYes = m.QNo + m.B * Math.Log(p2 / (1 - p2)); // 夜里价格又涨了一截
|
||||||
double t0 = w.Taint;
|
double t0 = w.DirtyOf(Assets.CRC);
|
||||||
Check(bk.SellAll(w, m, 5, a => 1, out double got, out double taint, out double over) == PredictResult.Ok && got > cost, "照常卖出,赚到价差");
|
Check(bk.SellAll(w, m, 5, a => 1, out double got, out double taint) == PredictResult.Ok && got > cost, "照常卖出,赚到价差");
|
||||||
Check(Near(taint, got * si / (si + sn), 1e-6) && Near(w.Taint - t0, taint, 1e-9) && over == 0, $"内幕份额对应的卖出所得记污点:{taint:0.00} / {got:0.00}");
|
Check(Near(taint, got * si / (si + sn), 1e-6) && Near(w.DirtyOf(Assets.CRC) - t0, taint, 1e-9), $"内幕份额对应的卖出所得记成脏的:{taint:0.00} / {got:0.00}");
|
||||||
// 非内幕卖出不加污点
|
// 非内幕卖出不加污点
|
||||||
var bk2 = new PredictBook(); var w2 = new Wallet { Address = "w" }; w2.Add(Assets.CRC, 1e6);
|
var bk2 = new PredictBook(); var w2 = new Wallet { Address = "w" }; w2.Add(Assets.CRC, 1e6);
|
||||||
var m2 = PredictMarket.Create(++bk2.Seq, PredictKind.Event, "e", "t", 0, 4, 7, 7, 0.05); bk2.Markets.Add(m2);
|
var m2 = PredictMarket.Create(++bk2.Seq, PredictKind.Event, "e", "t", 0, 4, 7, 7, 0.05); bk2.Markets.Add(m2);
|
||||||
bk2.Buy(w2, m2, true, 200, 4, a => 1, false, out _);
|
bk2.Buy(w2, m2, true, 200, 4, a => 1, false, out _);
|
||||||
m2.QYes = m2.QNo + m2.B * Math.Log(0.6 / 0.4);
|
m2.QYes = m2.QNo + m2.B * Math.Log(0.6 / 0.4);
|
||||||
bk2.SellAll(w2, m2, 5, a => 1, out _, out double t2, out double o2);
|
bk2.SellAll(w2, m2, 5, a => 1, out _, out double t2);
|
||||||
Check(t2 == 0 && o2 == 0 && w2.Taint == 0, "非内幕卖出不记污点");
|
Check(t2 == 0 && w2.Dirty.Count == 0, "非内幕卖出不记污点");
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("钱包:带上限的加污点", () =>
|
Test("罪证折算:按额 × 比例,单次封顶", () =>
|
||||||
{
|
{
|
||||||
Func<string, double> pr = a => 1;
|
Check(Near(Wallet.FraudFor(100), 100 * Tuning.PredictFraudShare, 1e-9) && Wallet.FraudFor(1e9) == Tuning.PredictFraudCap && Wallet.FraudFor(0) == 0, "按比例折罪证,单次封顶");
|
||||||
var w = new Wallet { Address = "w" }; w.Add(Assets.CRC, 100);
|
|
||||||
Check(w.AddTaintCapped(60, pr) == 0 && w.Taint == 60, "价值以内全部加上");
|
|
||||||
Check(Near(w.AddTaintCapped(60, pr), 20, 1e-9) && w.Taint == 100, "加到价值为止,返回超出的 20");
|
|
||||||
Check(Near(w.AddTaintCapped(30, pr), 30, 1e-9) && w.Taint == 100, "已满时全部超出");
|
|
||||||
var empty = new Wallet { Address = "e" };
|
|
||||||
Check(Near(empty.AddTaintCapped(5, pr), 5, 1e-9) && empty.Taint == 0, "空钱包加不进污点");
|
|
||||||
Check(w.AddTaintCapped(0, pr) == 0 && w.AddTaintCapped(-3, pr) == 0, "0 和负数不处理");
|
|
||||||
Check(Near(Wallet.OverflowFraud(100), 100 * Tuning.PredictFraudShare, 1e-9) && Wallet.OverflowFraud(1e9) == Tuning.PredictFraudCap && Wallet.OverflowFraud(0) == 0, "超出额按比例折罪证,单次封顶");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Test("日 K:开盘、日内高低、成交量、收盘、均线、保留天数", () =>
|
Test("日 K:开盘、日内高低、成交量、收盘、均线、保留天数", () =>
|
||||||
@@ -1865,18 +1854,19 @@ internal static class Program
|
|||||||
{
|
{
|
||||||
var sm = new StoryMods(); StoryMods.Current = sm;
|
var sm = new StoryMods(); StoryMods.Current = sm;
|
||||||
Check(sm.Apply("serpico_sec", 50) && !sm.Apply("serpico_sec", 51), "只生效一次");
|
Check(sm.Apply("serpico_sec", 50) && !sm.Apply("serpico_sec", 51), "只生效一次");
|
||||||
Check(sm.Aml(60) == Tuning.StorySecAmlMult && sm.Aml(50 + Tuning.StorySecDays) == 1, "治安部整顿期内出金审查加重,到期恢复");
|
Check(sm.MixClean(60) == Tuning.StorySecMixClean && sm.MixClean(50 + Tuning.StorySecDays) == 1, "治安部整顿期内混币器洗得更差,到期恢复");
|
||||||
|
Check(Mixer.RoundRate(1000, 60) < Mixer.RoundRate(1000) * 0.75, "整顿期内每轮清洗率 ×0.7");
|
||||||
Check(sm.Sanction(60) == Tuning.StorySecSanctionMult && sm.Enforce(60) == Tuning.StorySecEnforceMult, "制裁与查处倍率");
|
Check(sm.Sanction(60) == Tuning.StorySecSanctionMult && sm.Enforce(60) == Tuning.StorySecEnforceMult, "制裁与查处倍率");
|
||||||
sm.Apply("lun_arrested", 55);
|
sm.Apply("lun_arrested", 55);
|
||||||
Check(Math.Abs(sm.Enforce(60) - Tuning.StorySecEnforceMult * Tuning.StoryLunMult) < 1e-12 && sm.Enforce(55 + Tuning.StoryLunDays) == Tuning.StorySecEnforceMult, "伦警官立威期叠加,先到期");
|
Check(Math.Abs(sm.Enforce(60) - Tuning.StorySecEnforceMult * Tuning.StoryLunMult) < 1e-12 && sm.Enforce(55 + Tuning.StoryLunDays) == Tuning.StorySecEnforceMult, "伦警官立威期叠加,先到期");
|
||||||
// 出金审查真的变严
|
Check(sm.OtcSting(60) == Tuning.StoryLunMult && sm.OtcSting(55 + Tuning.StoryLunDays) == 1, "伦警官立威期内换币客户便衣更多");
|
||||||
var ex = new Exchange(); var ex2 = new Exchange();
|
int st0 = 0, st1 = 0;
|
||||||
var w = new Wallet { Address = "p" }; w.Add(Assets.CRC, 10000); w.Taint = 3000;
|
for (ulong sd = 1; sd <= 3000; sd++)
|
||||||
var w2 = new Wallet { Address = "p" }; w2.Add(Assets.CRC, 10000); w2.Taint = 3000;
|
{
|
||||||
double hit = ex.Cashout(w, 2000, a => 1, 60, 300, false, new Rng(1)).HitChance;
|
if (Otc.MakeSell(new List<MarketEvent>(), false, a => 1, 200, new Rng(sd)).Sting) st0++;
|
||||||
StoryMods.Current = new StoryMods();
|
if (Otc.MakeSell(new List<MarketEvent>(), false, a => 1, 200, new Rng(sd), Tuning.StoryLunMult).Sting) st1++;
|
||||||
double hit0 = ex2.Cashout(w2, 2000, a => 1, 60, 300, false, new Rng(1)).HitChance;
|
}
|
||||||
Check(hit > hit0 && hit <= 1, $"命中率 {hit0:0.000} → {hit:0.000}");
|
Check(st1 > st0, $"便衣 {st0} → {st1}(3000 位卖币客户)");
|
||||||
// CRT 脱锚减半:镇压开始时脱锚的频率
|
// CRT 脱锚减半:镇压开始时脱锚的频率
|
||||||
int dep0 = 0, dep1 = 0;
|
int dep0 = 0, dep1 = 0;
|
||||||
for (ulong sd = 1; sd <= 2000; sd++)
|
for (ulong sd = 1; sd <= 2000; sd++)
|
||||||
@@ -1928,6 +1918,96 @@ internal static class Program
|
|||||||
finally { StoryMods.Current = saved; }
|
finally { StoryMods.Current = saved; }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Test("Tumbler 之后:探员与搜查卡住上门日程、泄露还原出款污点、审判、黑市跑路、换皮重开", () =>
|
||||||
|
{
|
||||||
|
var saved = StoryMods.Current;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StoryMods.Current = new StoryMods();
|
||||||
|
// 探员:第 2 次之后的第二天起来,来过的第二天起才排第 3 次
|
||||||
|
var t = new Tumbler(); var a = new TumblerAfter();
|
||||||
|
t.TryStart(40, true); t.Visited(41); t.Visited(44);
|
||||||
|
Check(!a.AgentDue(t, 44) && a.AgentDue(t, 45), "探员在第 2 次上门的第二天起来");
|
||||||
|
Check(t.Due(46, a) == 0 && t.Due(46) == 3, "探员没来过,第 3 次不排(不传进度时照旧)");
|
||||||
|
a.Agent = TumblerAfter.Deny; a.AgentDay = 46;
|
||||||
|
Check(t.Due(46, a) == 0 && t.Due(47, a) == 3 && !a.AgentDue(t, 47), "探员来过的第二天起排第 3 次,只来一次");
|
||||||
|
t.Choice = Tumbler.Hide; t.Visited(47);
|
||||||
|
Check(!a.NeedSearch(t) && t.Due(51, a) == 4, "否认过:不搜查,第 4 次照常");
|
||||||
|
// 配合过又藏了:第 4 次前一天搜查
|
||||||
|
var t2 = new Tumbler(); var a2 = new TumblerAfter { Agent = TumblerAfter.Cooperate, AgentDay = 45 };
|
||||||
|
t2.TryStart(40, true); t2.Visited(41); t2.Visited(44); t2.Choice = Tumbler.Hide; t2.Visited(46);
|
||||||
|
Check(!a2.SearchDue(t2, 48) && a2.SearchDue(t2, 49) && t2.Due(50, a2) == 0, "配合 + 藏:第 4 次前一天搜查,搜查前不排第 4 次");
|
||||||
|
a2.Searched = true; a2.SearchDay = 50;
|
||||||
|
Check(t2.Due(50, a2) == 0 && t2.Due(51, a2) == 4 && !a2.SearchDue(t2, 51), "搜查的第二天起排第 4 次");
|
||||||
|
var t3 = new Tumbler { Choice = Tumbler.Report }; t3.TryStart(40, true); t3.Visited(41); t3.Visited(44); t3.Visited(46);
|
||||||
|
Check(!a2.NeedSearch(t3), "举报的不搜查");
|
||||||
|
|
||||||
|
// 出款记录与泄露
|
||||||
|
Func<string, double> px = x => 1;
|
||||||
|
var w = new Wallet { Address = "w" }; w.AddDirty(Assets.CRC, 5000, 4000);
|
||||||
|
var m = new Mixer();
|
||||||
|
m.Deposit(w, Assets.CRC, 1000, 3, 1, px);
|
||||||
|
m.Night(w, 4, px, new Rng(1));
|
||||||
|
var r0 = m.Returns.Single();
|
||||||
|
Check(r0.Day == 4 && r0.Wallet == "w" && r0.Cleaned > 100 && Near(r0.Cleaned, 800 - (w.DirtyOf(Assets.CRC) - 3200), 1e-6), $"出款记下洗掉的污点:{r0.Cleaned:0}");
|
||||||
|
double before = w.DirtyOf(Assets.CRC);
|
||||||
|
var lk = m.Leak(4 + Tuning.TumblerLeakDays);
|
||||||
|
Check(lk.Count == 1 && Near(lk.Cleaned, r0.Cleaned, 1e-6) && Near(lk.Fraud, Wallet.FraudFor(r0.Cleaned), 1e-9) && w.DirtyOf(Assets.CRC) == before && m.Returns.Count == 0, "泄露:按洗掉的污点记罪证,不动钱包,记录清空");
|
||||||
|
var m2 = new Mixer();
|
||||||
|
m2.Returns.Add(new MixReturn { Day = 1, Wallet = "v", Amount = 10, Cleaned = 500 });
|
||||||
|
m2.Returns.Add(new MixReturn { Day = 40, Wallet = "v", Amount = 10, Cleaned = 300 });
|
||||||
|
m2.Returns.Add(new MixReturn { Day = 40, Wallet = "gone", Amount = 10, Cleaned = 300 });
|
||||||
|
var lk2 = m2.Leak(45);
|
||||||
|
Check(lk2.Count == 2 && Near(lk2.Cleaned, 600, 1e-9) && Near(lk2.Fraud, Wallet.FraudFor(600), 1e-9), "只算 30 天内的,罪证 = 洗掉的污点 × 50%");
|
||||||
|
a.LeakTonight(50); a.LeakTonight(60);
|
||||||
|
Check(a.LeakDay == 50, "泄露只安排一次");
|
||||||
|
|
||||||
|
// 审判
|
||||||
|
int conv = 0;
|
||||||
|
for (int i = 0; i < 2000; i++) { var x = new TumblerAfter(); x.StartTrial(10, new Rng((ulong)i + 1)); if (x.Verdict == 1) conv++; }
|
||||||
|
Check(Near(conv / 2000.0, Tuning.TumblerTrialConvict, 0.03), $"定罪约 {Tuning.TumblerTrialConvict:P0}:{conv / 2000.0:P1}");
|
||||||
|
var tr = new TumblerAfter(); tr.StartTrial(10, new Rng(7));
|
||||||
|
Check(tr.TrialOpenDay == 10 + Tuning.TumblerTrialOpen && tr.TrialDay == 10 + Tuning.TumblerTrialDays && tr.ClosedDay == 10, "开盘、宣判、关停的日子");
|
||||||
|
var rng = new Rng(9);
|
||||||
|
Check(tr.Hint(tr.TrialOpenDay - 2, rng) == null && tr.Hint(tr.TrialOpenDay - 1, rng) != null && tr.Hint(tr.TrialOpenDay - 1, rng) == null, "开盘前一晚起每晚一条");
|
||||||
|
for (int dd = tr.TrialOpenDay; dd < tr.TrialDay + 3; dd++) tr.Hint(dd, rng);
|
||||||
|
Check(tr.Hints.Count == tr.TrialDay - tr.TrialOpenDay + 1, $"宣判前一晚为止:{tr.Hints.Count} 条");
|
||||||
|
Check(Near(new TumblerAfter().TrialPublic(), Tuning.TumblerTrialConvict, 1e-9), "没有新闻时公开概率 = 先验");
|
||||||
|
double sumC = 0, sumA = 0; int nC = 0, nA = 0;
|
||||||
|
for (int i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
var x = new TumblerAfter(); var rr = new Rng((ulong)i + 11); x.StartTrial(0, rr);
|
||||||
|
for (int dd = 0; dd < 10; dd++) x.Hint(dd, rr);
|
||||||
|
if (x.Verdict == 1) { sumC += x.TrialPublic(); nC++; } else { sumA += x.TrialPublic(); nA++; }
|
||||||
|
}
|
||||||
|
Check(sumC / nC > 0.85 && sumA / nA < 0.5, $"新闻把公开概率推向真实判决:定罪 {sumC / nC:0.00},无罪 {sumA / nA:0.00}");
|
||||||
|
|
||||||
|
// 黑市跑路、换皮重开
|
||||||
|
var sold = new TumblerAfter(); sold.StartSold(20, new Rng(3));
|
||||||
|
Check(sold.BmRugDay >= 20 + Tuning.TumblerBmRugMin && sold.BmRugDay <= 20 + Tuning.TumblerBmRugMax, $"黑市跑路在 {sold.BmRugDay}");
|
||||||
|
var mr = new Mixer(); var w3 = new Wallet { Address = "z" }; w3.Add(Assets.CRC, 1000);
|
||||||
|
mr.Deposit(w3, Assets.CRC, 400, 2, 1, px); mr.Deposit(w3, Assets.CRC, 300, 3, 1, px);
|
||||||
|
var rug = mr.RugAll();
|
||||||
|
Check(rug.Count == 2 && rug.All(x => x.Rugged) && mr.Pending.Count == 0, "黑市跑路:在途的全部丢失");
|
||||||
|
var rb = new TumblerAfter { ClosedDay = 30 };
|
||||||
|
Check(!rb.RebrandDue(30 + Tuning.TumblerRebrandDays - 1) && rb.RebrandDue(30 + Tuning.TumblerRebrandDays) && !new TumblerAfter().RebrandDue(100), "关停满 15 天换皮,没关停不换");
|
||||||
|
var sm = new StoryMods(); StoryMods.Current = sm;
|
||||||
|
sm.Apply("tumbler_sold", 1); sm.Apply("tumbler_bm_rug", 2);
|
||||||
|
Check(sm.MixerClosed, "黑市跑路后混币器关停");
|
||||||
|
sm.Rebrand(false);
|
||||||
|
Check(!sm.MixerClosed && sm.MixerRebranded && Near(Mixer.Fee, Tuning.MixerFee, 1e-12) && sm.MixerRug == 1, "换皮重开:重新开放,费率和跑路倍率回到 1");
|
||||||
|
var w4 = new Wallet { Address = "h" }; w4.Add(Assets.CRC, 500);
|
||||||
|
var mh = new Mixer(); mh.Deposit(w4, Assets.CRC, 500, 1, 1, px); mh.Night(w4, 2, px, new Rng(5));
|
||||||
|
Check(w4.Dirty.Count == 0, "正常的新混币器:干净的币出来还是干净的");
|
||||||
|
sm.Rebrand(true);
|
||||||
|
Check(Near(Mixer.Fee, Tuning.MixerFee * Tuning.TumblerHoneypotFee, 1e-12), "钓鱼混币器费率打折");
|
||||||
|
var w5 = new Wallet { Address = "k" }; w5.Add(Assets.CRC, 500);
|
||||||
|
var mk = new Mixer(); mk.Deposit(w5, Assets.CRC, 500, 1, 1, px); mk.Night(w5, 2, px, new Rng(5));
|
||||||
|
Check(Near(w5.DirtyOf(Assets.CRC), w5.Get(Assets.CRC), 1e-6), "从钓鱼混币器提回的币整笔都是脏的");
|
||||||
|
}
|
||||||
|
finally { StoryMods.Current = saved; }
|
||||||
|
});
|
||||||
|
|
||||||
Test("黑市商家收币:每类商家都收 CRT 或隐私币,平台收 PSC、CRT、CRA", () =>
|
Test("黑市商家收币:每类商家都收 CRT 或隐私币,平台收 PSC、CRT、CRA", () =>
|
||||||
{
|
{
|
||||||
foreach (MerchantType ty in Enum.GetValues(typeof(MerchantType)))
|
foreach (MerchantType ty in Enum.GetValues(typeof(MerchantType)))
|
||||||
|
|||||||
Reference in new issue
Block a user