RNBW.wiki
🇨🇳
🇷🇺Русский 🇬🇧English 🇪🇸Español 🇨🇳中文 🇩🇪Deutsch

文章 · 质押

为什么分配窗口永远不会超过七天

从退出者身上扣下的费用,并不会一次性交给留下的人,而是均匀发放——这个发放有一个窗口。看上去,连续几次退出应该把窗口一个接一个地串起来。合约里的做法并非如此,而这个差别正好解释了池子收益率为什么呈锯齿状。

2026 年 10 月 5 日 · 发布时已核验

简短的回答

窗口是从每一次退出单独计算的,永远不超过七天。连续三次大额退出并不会得到二十一天:每一次都把窗口清零,并从自己这一刻重新数七天。窗口不会串成一条链,而是互相重叠。

看上去是这样 7 + 7 + 7 = 21 实际是这样 7 7 7 0 3 6 9 12 15 18 21 距第一次退出的天数

橙色刻度是退出发生的时刻,蓝色矩形是分配窗口,每个矩形里的数字就是它的天数。头两天里的三次退出会让分配在第九天结束,而不是第二十一天。结束时间原则上也不可能更晚:每个窗口都从它自己那次退出算起,正好七天。

发放的钱从哪来

质押池只有一个收入来源——向退出者扣下的费用。当一位质押者取回仓位时,合约会把整个仓位的 10% 留在池子里,连同已累积的收益一起。这一点可以直接在源码里核验:计数器 undistributedFees 只有一处会增长,就在退出函数内部。

但扣下的钱不会立刻发放。它会落进未分配费用这个「锅」里,并以恒定速度 rewardRate(单位是每秒多少 RNBW)均匀流出。在流出的过程中,份额价格上涨——也就是说,这笔增量会按仓位大小的比例,同时到达池子里的每一个人。没有人会因此拿到新的份额:是每一份既有份额变得更值钱。

所以质押收益率取决于有多少人退出,而不是有多少人进场。流入会把它压低:同样的币流要分给更大的池子。流出会把它抬高,而且是双重的——池子缩小了,同时还加进了离场者的十分之一。

每次退出时合约做的判断

新扣下的费用并不是简单地加到旧的上面。合约会重新计算现在全部流完需要多快,并在三个分支中选一个。选择只取决于一次比较:新速度是不是高于当前速度。

没有正在进行的分配——上一个窗口已经到期

新的周期

速度等于锅里的量除以七天。一切从零开始。

窗口——正好 7 天

锅 ÷ 7 天不小于当前速度——大额退出

速度上升

速度提高,窗口清零,并从这一秒重新开始计算。

窗口——正好 7 天

锅 ÷ 7 天小于当前速度——小额退出

期限延长

速度不变,滴答还是原来那个。只是要滴得更久:窗口的剩余时间,加上新增量除以速度。

窗口——少于 7 天

这就是上限毫无例外地成立的原因。其中两个分支里,窗口按定义就等于七天。第三个分支里它短于七天——否则速度就会上升,走的会是第二个分支。代码里没有第四种可能。

禁止下调速度是有意为之,合约里用这句话作了注释:rewardRate can only stay flat or increase。没有它,任何人都可以按几分钱的份额反复退出,每退一次就把其他所有人的收益率往下拉一截。

在时间上是什么样子

三种情形放在同一个刻度上。橙色表示锅里有多少 RNBW:退出时跳升补充,然后均匀地向下流走。线的斜率就是分配速度——越陡,费用到达质押者的速度越快。

A 0 5 10 C 0 5 10 D 0 5 10

A——没有分配在进行时的一次退出。锅是空的,扣下 100,000 RNBW,于是每天发放 14,286。到第七天什么都不剩。

C——分配进行到一半时的大额退出。第三天又扣下 100,000。斜率变陡,速度升到每天 22,449,窗口清零——结束时间滑到了第十天。

D——连续三次大额退出。结束落在第九天,而不是第二十一天。真正增长的是速度:从每天 14,286 涨到 37,026 RNBW,分配快了 2.6 倍。

情形 C 里藏着视觉上的错觉。分配确实会比最初的七天更晚结束——在第十天。但这并不是「一个十天长的窗口」:从第三天那次退出到结束,正好是七天。窗口没有被拉长,而是被挪了位置。

小额退出:「期限延长」是什么意思

第三个分支看着不起眼,却几乎每次都是它在起作用:纵观全部历史,大到足以抬高速度的退出屈指可数。我们把它放大来看——在总图上,所有关键的事情都发生在那里看不见的尺度上。

+1,000 1 2 该分支的上限——7 还剩 4.07 01 23 45 67 89 1011 1 补充的瞬间,纵向放大 28 倍 +1,000 2 分配的结尾,时间放大 15 倍 1 小时 41 分

插图 ① 纵向放大了 28 倍,插图 ② 在时间上放大了 15 倍。两幅图里的虚线都表示:如果没有这次补充,事情会怎么走。

最关键的一点在插图 ① 里:台阶之前的线和之后的线是平行的。速度没有变化,滴答还是原来那个——上升的只是锅里的液位。所以期限延长的时间,正好等于滴答把新增量搬出去所需的时间:1,000 ÷ 每天 14,286 = 1 小时 41 分钟。这在插图 ② 里看得到。

分配结束从 7.00 挪到了 7.07 天,而从这次退出本身到结束还剩 4.07——比上限少了将近三天。但这三天的余量是这个例子的性质,不是这个分支的性质:它来自退出发生在窗口中间,而且金额极小。

如果退出发生在窗口的末尾

那么同一个第三分支会把分配拉长将近七天。它的余量不仅取决于新增量的大小,还取决于窗口还剩多少:延长的时长等于窗口的剩余时间,加上新增量除以速度。

7 天上限——「速度上升」分支 +1,000 +25,000 +50,000 +95,000 B 01 23 45 67 01 23 45 67 退出发生在进行中窗口内的时刻,天

纵轴是从退出算起的窗口长度,单位是天。每条橙线对应一种扣费规模。点 B 是上一节的那个例子:第三天退出,新增 1,000。右上角那个点是第 6.9 天退出,新增 95,000。

这些线互相平行,并且全都顶在蓝色上限上。退出得越晚,剩下要流完的就越少——但新增量相对这点余量的分量就越重。窗口末尾的一次大额新增,能逼近七天:第 6.9 天退出、扣下 95,000 时,0.10 加 6.65 得到 6.75 天,而这仍然属于「期限延长」分支。

扣下锅内窗口,天结束,天分支
1,0002,4290.177.07期限延长
25,00026,4291.858.75期限延长
50,00051,4293.6010.50期限延长
95,00096,4296.7513.65期限延长
98,571100,0007.0013.90期限延长
100,000101,4297.0013.90速度上升

请看最后两行——那就是两个分支的边界。扣下 98,571 RNBW 仍然落在「期限延长」里,而 100,000 已经会抬高速度。两者给出的结果却一样:正好七天。它们之间没有跳变,边界是平滑的——「期限延长」分支从下方逼近七天,「速度上升」分支正好站在七天上。所以上限才会毫无例外地成立。

而分配在日历上的总长度,却不受任何限制。在「结束」这一列里,扣下 95,000 时是 13.90 天——将近两周。七天的上限约束的是每一次单独退出的窗口,而不是整体时长。落在窗口末尾的退出可以把它无限往后推,只要退出流持续不断,分配就根本不会停——实际发生的正是这样:锅从来没有见底。

如何自己核验

这里描述的一切,都直接来自 _addFees 这个函数,它位于质押合约 0x288ea8Bcb51d53aD361D786EFa904C401904aF70 之中。源码已公开并通过验证,可以在区块浏览器里阅读。

01

「速度上升」分支

合约会赋值 dripEndTime = block.timestamp + dripDuration,其中 dripDuration 等于 604800 秒,也就是从当前这一秒算起正好七天。上一个窗口就此不复存在。

02

「期限延长」分支

这里是 dripEndTime = block.timestamp + undistributedFees / rewardRate。进入这个分支的条件本身就保证了这个商小于 dripDuration——否则走的会是上一个分支。

03

当前状态

锅内余额和速度可以用 undistributedFees() 和 rewardRate() 这两个调用从合约里读出。它们连同全部退出的历史、以及每次退出触发了哪个分支的标注,都在质押页面上。

本文示例中的数字,是把 _syncPool 和 _addFees 从零状态开始逐步重放算出来的,而不是从网站上取的——这样它们就无法被凑成想要的结论。