决策日志
权威登记册是 doc/DECISIONS.md。本页概述其中的转折点。
2026-08-25——内部安全审查
一项高危发现:部分成交会让 ETH 和 USDC 滞留在路由器中,并被全额征税。修复方式是拒绝部分成交,而不是处理它们。
2026-08-27——费用从 4 % 提高到 5 %
创建者份额翻倍,从 1 % 提高到 2 %。$STOCKFUN 的费率结构从 2 / 1.5 / 0.5 变为 2 / 2.5 / 0.5。国库份额保持在 2 %,这正是那个永不改变的数字。
接受的后果:往返成本从 7.84 % 升至 9.75 %。自 2026-10-05 起,费率及其分配比例是所有者的设置,这些数值是默认值。
2026-08-27——创建者回购
在单独一条路径上解除了“无退出”的排除规则,而这条路径总是以销毁告终。Treasury Ratio 从此可能因创建者的自行决定而下降。已于 2026-09-27 移除,由空投取代。
2026-08-29——紧急模式
所有者可以在公开的 48 小时之后转移国库的资产。取代了“没有人能触碰国库”这一承诺。协议不再被描述为无需信任。自 2026-10-05 起立即生效:延迟已被取消。
2026-09-11——通道迁移到 Robinhood Chain
阻碍在于金库合约在一级铸造发行方那里的资格问题,而这一点从未被公开记录。Robinhood Chain 的二级市场池不需要这一资格。付出的代价:一项被接受的跨链依赖。
2026-09-12——联合曲线被取消
由两个单边 Uniswap v4 头寸取代,自创建起即被锁定。没有毕业,没有迁移,没有毕业费。
发射 FDV 不变:它仍然是曲线开盘时的 3.409 ETH。第一笔 2 ETH 的买入拿走 36.06 % 的供应量,而之前是 36.99 %——发射的表现与之前相同,误差在一个点以内。
在此过程中被排除的方案:以 $5,000 发射、上限为 $50,000 的方案,它只提供 3.25 ETH 的深度,并让第一个 2 ETH 的买家拿走 57 % 的供应量。还有“更低的上限会让市场平静下来”这一想法——它会更早地把接力交给无上限的区间,而该区间很薄,并且会让花费 50 ETH 之后达到的 FDV 翻倍。
2026-09-12——三区块防狙击
区块 1 仅限创建者;区块 2 中除创建者和所有者白名单外,99 % 进入回购;此后恢复正常。已于 2026-09-28 被取代,取而代之的是递减式防狙击。
这一决定是在充分了解反对意见的情况下做出的:99 % 的税只有在有人损失资金时才会产生任何东西,而直接关闭区块 2 本可以在没有受害者的情况下达到同样的威慑效果。白名单设在协议层面而不是创建者层面,正是为了让它不会在一个又一个市场中变成内部人的优势。
2026-09-12——卖出时不销毁
每次卖出时将流入代币的 10 % 发送去销毁的想法被放弃了。如果由卖家承担,它会把往返成本推高到 18.78 %。如果由 LP 承担,它会让“流动性永久锁定”变成假话,并让任何人都获得一个约 1:1 的杠杆,用来销毁流通筹码、拉升自己的持仓。
2026-09-27——空投取代创建者回购
一个市场的国库如今只有一个用途:它买入的股票 100 % 在 Robinhood Chain 上按比例、以实物形式空投给其代币的持有者。创建者回购被移除,跨链桥的回程路径也随之移除。$STOCKFUN 的回购并销毁保留。
在此过程中被排除的方案:保留创建者回购,以及一种将 60 % 留在国库、分发 40 % 的拆分方案,即此前的 V2 计划。接受的后果:不再有任何国库会积累资产,Treasury Ratio 失去意义,口号和标语需要重新审视。该机制已于 2026-10-04 写进代码:参见空投。
2026-09-27——每 24 小时一次的循环
空投的频率于同一天确定。每 24 小时一次,对于每个国库已累积至少 0.1 ETH 的市场,Keeper 会进行转换、跨链、买入股票,然后将这些股票空投出去。低于门槛时,当天什么也不会发生;ETH 会继续等待。
股票只能在美股市场开盘期间买入,因此周末和 NYSE 休市日没有循环。在 Keeper 的代码中,直到 2026-10-06,转换都在交易时段内、在金库达到门槛的第一轮进行;从那时起,它遵循这一决定:每个时间窗口一次,在时间窗口关闭后 Keeper 的第一轮进行,并且只有在金库当时达到门槛时才进行(参见下文 2026-10-06);自第六个审计循环(同一天)起,金库持有的 USDC 也遵循这一节奏。自 2026-10-05 起,向空投的发送每个时间窗口运行一次,在当天的交易时段之后:参见Keeper。
2026-09-27——卡住的资金与持仓计量
被中断循环的剩余资产会在下一次循环中处理完毕,无论是否再次达到门槛。在镜像金库中卡住 24 小时的空投资金,可以由所有者在无需事先公告的情况下转移:这是公开 48 小时延迟的唯一例外,是在知情的情况下做出的选择。持仓按循环前 24 小时内的平均余额计量,周一也是如此。卡住资金的时间窗口已于 2026-09-28 改为 48 小时,该规则已于 2026-10-05 关闭,从未写进代码。
2026-09-28——递减式防狙击
开盘区块 80 %,此后每个区块减少 8 个点,从第 11 个区块起为 5 %,买入和卖出均适用。超出部分进入该市场的国库;在 $STOCKFUN 上,则进入团队可领取的费用。豁免:创建者在发射时的买入,以及由创建者设定的白名单,该名单在创建交易中确定,公开、不可更改,上限为 20 个地址;在 $STOCKFUN 上,则由所有者在发射时设定。自 2026-10-05 起,这些数值是所有者的设置,以上数值为默认值。
在此过程中被排除的方案:标记在最初几个区块中买入的钱包,并对其之后的卖出征税,即使在转账之后也不例外。v4 池看不到钱包,由代币收取的税会让卖出失败,而在 StockFun 路由器之外封锁被标记的钱包,会让代币被扫描工具标记为可疑。接受的后果:白名单从协议转移到创建者手中,而 2026-09-12 的决定曾为防止内部人优势而排除了这一做法。
2026-09-28——卡住的空投资金:48 小时
在镜像金库中停留 48 小时(而不是 24 小时)的空投资金,可以由所有者在无需事先公告的情况下转移。在 24 小时时,这一时间窗口与循环周期相等,因此仅顺延一个循环的普通结转资金,也会变得可以在无需事先公告的情况下转移;在 48 小时时,情况就不再如此。周五失败的循环,其资金仍会在周日变得可以转移,即早于周一的循环。同日决定:计时从不停止,无论是在暂停期间还是在周末。已于 2026-10-05 关闭,从未写进代码:紧急转移在任何地方都立即生效。
2026-09-28——持仓在链上记录
每个市场的代币都会记录每个钱包随时间变化的持仓,因此由一个合约计算循环前 24 小时内的平均值以及每一份额;Keeper 从不提供这些数据。被排除的方案:由 Keeper 在链下计算、并附带质疑期发布的分配。接受的代价:代币的每一次转账都要支付额外的 gas。
2026-09-28——以封装股票在以太坊上空投
在 Robinhood Chain 上买入的股票被锁定在由 StockFun 部署的 LayerZero 适配器中(每只股票一个),并以封装股票的形式发送到以太坊。分发在以太坊上进行,即代币及其持仓所在之处,每位持有者自费领取自己的份额。接受的后果:封装股票的价值仅取决于被锁定的股票和 LayerZero 配置,它们在以太坊上没有市场,而且一旦发行方冻结 Stock Tokens,被锁定的股票也将无法动用。同日决定:适配器的 LayerZero 配置由所有者掌握,没有延迟,也没有提取上限,就像 Paxos 对 USDG 所做的那样。被排除的方案:部署后冻结的配置,以及须经 48 小时事先公告的更改。
2026-09-28——官方路由器仍可更改
所有者可以随时更改官方兑换路由器,而 Hook 通过该路由器识别防狙击白名单。接受的后果:通过指定另一个路由器,所有者可以让任何人豁免防狙击。
2026-09-28——0.001 ETH 的创建费
创建费改为 0.001 ETH,写死在代码中,取代原先的约 $3:没有价格喂价,也没有所有者设置。它的美元价值如今随 ETH 价格变动。自 2026-10-05 起成为所有者的设置,默认为 0.001 ETH。
2026-09-28——PoolManager 不计入持仓记录
代币不记录 Uniswap 的 PoolManager:它是每一笔兑换的一方,持有所有池子的代币,也从不接收空投。它的历史读数为零,交易者的持仓照常记录。实测节省:每笔兑换约 24,000 gas,买入和卖出都一样。
2026-09-29——StockFun 池不收取 LP 手续费
池子在创建时将 Uniswap LP 手续费设为零,而不是 0.30 %:Hook 的税就是一笔交易的全部成本,单向为 5 %,一次往返交易在计入价格影响之前为 9.75 %。接受的代价:国库、团队和创建者失去各自在 LP 手续费中的份额,这些手续费中代币一侧的销毁也随之消失。自 2026-10-05 起,LP 手续费是一项发射设置,默认为零;每个池子保留它创建时的手续费。
2026-10-01——2026-09-29 安全审计的修复
于 2026-09-30 和 2026-10-01 实施,此前每一项发现都经过审阅,并选定了修复方案。每一项已修复的发现都有回归测试,这些测试在被审计的代码上会失败。
只有流动性锁定合约可以向 StockFun 池子添加流动性:第三方头寸曾与被征税的兑换进行交易,却既不支付税,也不支付防狙击税。新的 Hook 权限改变了 Hook 的地址,该地址已重新挖掘。
交易期间只发送国库份额。团队份额和回购份额记在 Hook 上,通过任何人都可以调用的领取,支付给工厂合约当前指定的钱包;托管已被移除。路由器和锁定合约在兑换之前支付输入金额。在此之前,一个回调 Uniswap 的费用钱包可以让每一个池子的交易都停止。
每一个转换步骤花费 Keeper 指定的数额,因此规模大于其交易场所的金库会分批转换。现金一到达就按每只篮子股票预留,被 Keeper 跳过的股票保留其预留额;镜像金库也以同样的方式运作。
每个代币都会记录其在 Uniswap PoolManager 之外的供应量随时间的变化,即空投按比例份额的分母。在审计提出的三个方案中,这一方案让每笔兑换多一次写入;重新记录 PoolManager 则会让每笔兑换多消耗约 24,000 gas。接受的后果:空投的时间窗口在整点开始和结束。
在 Robinhood 通道上,被拒绝的篮子不再阻断同一批次中的其他市场,一个远端代币只对应一个标识符,v3 上的部分成交会让其路径失败,暂停中的远端枢纽仍会应用角色变更,官方跨链桥的记录按其到达的顺序支付。
实测:通过路由器买入耗费 113,529 gas,卖出耗费 137,250,此前分别为 125,862 和 150,416。仍未解决、等待所有者决定的事项:跨链桥适配器的轮换(M-2,以及随之而来的 L-8)、Ondo 证明(M-7),以及接受自身作为接收方的路由器(L-4)。自 2026-10-05 起,M-7 和 L-4 已经修复,M-2 则按所有者的决定维持现状,L-8 也随之维持现状。
2026-10-01——安全流水线补全修复
同一天,由两位独立审计员进行的第二轮审计补全了若干修复。每一项都有回归测试;没有一项改变任何设计决策或不可变参数。
在 Robinhood Chain 上,v3 路径逐个池执行,每个池都必须用掉它的全部输入:此前的检查只看到第一个池,而在后面的池中发生的部分成交,会把中间代币留在任何人都可以拿走的地方。官方跨链桥的账目票据支付的记录最多与它加入队列的记录一样多,从最早的开始,因此积压不再会让它超出其自动执行的 gas;其余的由 sweep 支付。
一次已执行的紧急转移如果使金库现金低于其预留额,就会把这些预留额全部清零,两种金库都是如此:剩余的现金,以及之后每一笔流入的现金,都按权重重新分配。在此之前,这种清零只存在于读取之中,旧的预留额会随着下一笔流入的现金回来。
每次买入时,Keeper 都会在篮子的最后一只股票上留出 n−1 个单位:舍入余数归于这只股票,而一笔粉尘转账就可能让买入回滚。它还会把 $STOCKFUN 池无法完整成交的一批销毁数额减半。每个代币都在部署时记录其第一个整点标记,这只在从第 0 个小时开始的时钟上才有影响,例如测试链的时钟。以太坊上的股票路由器在用 ETH 付款之前先执行 sync,而 Lens 会拒绝空页。
实测:一个代币在每个小时中的第一笔兑换,作为一笔单独的交易,要多消耗约 28,000 至 30,000 gas,而不是约 23,000。
等待所有者决定、尚未作出决定的事项:针对远端枢纽上已记录现金的紧急转移,其记录随后会用其他市场的现金支付(R2H-1);拒绝某一个镜像金库的现金代币,它会让官方跨链桥的队列停滞,并让与该市场捆绑在一起的批次回滚(R2H-2);最后一只股票的余量在合约一侧的实现,它会改变文档所记录的分配规则(R2T-1);以 PoolManager claims 的形式收取买入税,使任何路由器都能买入(R2F-1,option b);让工厂合约自行部署 $STOCKFUN 的金库(R2F-2);以及三个信息性要点(R2H-4、R2H-6、R2H-7)。一只再也无法被买入的股票,仍会从每一笔流入的现金中获得其权重对应的份额:这是有意为之,因为停用其中一段会改变篮子固定的权重。自 2026-10-05 起,R2H-1 已由当天各个审计循环的结算工具加上一套流程涵盖,即所有者在转移之前暂停远端枢纽;R2H-2 已由第四个循环的非阻断式送达关闭;R2F-1 的 option b 被否决,税保持目前的收取方式;拒收 ETH 的金库也不再让其市场停止,而这正是 R2F-2 所描述的停止:参见下文 2026-10-05 的各条目。
2026-10-02——每个模块都可升级
在此之前,协议中没有任何合约可以升级。除代币和流动性锁定合约之外,每个模块都变为可由 StockFun 的所有者升级,并立即生效:没有时间锁。每个模块都是一个通过 UUPS 升级的代理合约,并向其升级授权方询问谁可以升级它:以太坊上是工厂合约,Robinhood Chain 上是远端枢纽。两条链上的金库都是每个市场一个代理合约,逐个市场升级。Hook 的代理合约在挖掘时带有全部 14 个 v4 权限,因此以后的实现合约可以使用任何回调,而无需移动地址。
代币不承载任何自己的逻辑:一个供应量固定的普通 ERC-20,只有一个 setter setRecorder,归所有者使用。持仓记录从代币中移出,进入一个新模块,即持仓记录器,每个代币在每次转账时都会调用它;如果调用失败,转账也会失败。自 2026-10-05 起,代币还具有救援函数,用于处理发到它们自身地址的东西,而这一阻断性调用是创始人隔离规则唯一的刻意例外(见下文)。
流动性锁定合约仍然不可升级,并增加了终止模式:所有者宣布它,30 天后可以把每个池子的全部流动性(包括 $STOCKFUN 的流动性)回收到任意地址。所有者可以取消;在这 30 天内交易照常进行,而在终止待生效期间,不能发射任何新市场。它用于项目关闭的情形;这 30 天是给持有者的事先公告期。Robinhood Chain 上的镜像金库部署器同样不可升级:每一个镜像金库的地址都由它推导而来。
它带来的变化:升级不必等待紧急模式的 48 小时,而紧急模式本身保留;本书称为固定的规则,从金库的界限到销毁和 5 % 的费率,只要所有者不升级承载它们的模块,就依然成立;工厂合约最先部署,并由所有者完成接入,这改变了部署顺序。一次兑换多消耗约 27,000 gas,这是单独测得的:买入为 237,190 gas,而不是 210,105;卖出为 285,031,而不是 258,278——这是其路径上的代理合约以及对记录器的调用所付出的代价。自 2026-10-05 起,紧急模式也不再有延迟,而金库的界限和 5 % 的费率都是所有者的设置。
2026-10-04——空投合约
已写进代码并经过测试,尚未部署。AirdropDistributor 是以太坊上一个绑定到工厂合约的可升级模块,按每日循环分发每个市场的股票。一个循环的时间窗口在 13:00 UTC 关闭,全年都在美股开盘之前;它的买入和发送在紧接着的交易时段内进行。一个循环由它的第一次发送开启,或提前开启,并冻结其各项数值:持仓记录器、时间窗口关闭时有效的排除名单,以及合格持仓。两条路径为它供给股票,即 sendToAirdrop:一条在镜像金库上,经由每只股票的 LayerZero 适配器;另一条在以太坊金库上,用于本地通道;除此之外没有任何东西能计入一个循环。
同日确定:Keeper 不推送,只有持有者自行领取,费用自理(TBD 5);没有单个钱包的上限,没有最低额,没有期限(TBD 7);每个代币一份排除名单,由所有者设定,最多 16 个地址,始终包括销毁地址,对于 $STOCKFUN 还包括归属合约(TBD 8)。为一个没有合格持仓的时间窗口所做的发送,会被搁置,留给第一个拥有合格持仓的时间窗口,无论由谁调用、何时调用,前提是在此期间循环时刻没有改变,代币的持仓记录器也没有被替换。
接受并记录在案的是:Keeper 选择时机,因此在下一个 13:00 UTC 之后到达的发送,按次日的时间窗口计量;调整循环时刻会重新划分尚未开启的时间窗口,包括搁置的股票仍需检查的那些;代币的持仓记录器只能就地升级,绝不能在一个正在使用的代币上被替换。不在这次变更之内的有:针对卡住资金的 48 小时规则、股票适配器、Keeper 的空投步骤,以及 dapp 的领取页面。自 2026-10-05 起,已不再有需要排除的归属合约,48 小时规则已经关闭,循环时刻则归入所有者设定的时间表,即时间窗口的长度和关闭时刻(setCycleSchedule);在一个正在使用的代币上指定的记录器,从该代币在 PoolManager 之外的供应量起步(参见下文审计循环的条目)。
2026-10-05——没有团队分配、立即生效的紧急模式、每个数值都是一项设置
三项决定,同日写进代码并经过测试,尚未部署。
团队分配被取消。团队归属合约 TeamVesting 被删除,不再为团队预留任何 $STOCKFUN:全部供应量(默认为 1,000,000,000 枚代币)都进入锁定的单边头寸,正如一个市场的全部供应量进入它的两个头寸。在此之前,10 % 进入归属合约,在 12 个月内归属,而空投把该合约排除在 $STOCKFUN 的循环之外;如今只有销毁地址被排除,自当天的第三个审计循环起,还有发射操作者(见下文)。
紧急模式变为立即生效。emergencyTransfer 把一项资产从金库、跨链桥枢纽或空投合约中立即转移到任意地址;每一次转移都有一个顺序编号和一个公开事件。2026-08-29 的 48 小时安排机制连同其取消窗口一并取消,而延迟也不是一个参数:紧急模式一经所有者使用就立即生效,从不需要等待。替换跨链桥适配器(changeAdapter)同样立即生效,所固定的地址保持不变。针对卡住的空投资金的规则,于 2026-09-27 和 2026-09-28 决定、从未写进代码,现已关闭:立即生效的转移涵盖了这种情况,可用于任何合约,随时可用。
每个数值都变为一项设置。协议的各项数值如今都是所有者的链上设置,在两条链上都是如此,以今天的数值为默认值:税、其分配比例和防狙击;创建费和新市场各字符串的长度限制;新市场的形态(包括 LP 手续费和 tick 间距),以及锁定头寸所收取部分的分配份额;转换门槛和金库的价格界限;空投的时间表和限额;预言机的心跳间隔;跨链桥的 gas 和滑点。每一项都立即生效,并拒绝不可能的数值。税的变更从下一笔兑换起适用于每个池子,包括仍处于防狙击区块内的池子;形态的变更适用于此后创建的市场,每个池子保留它创建时的 LP 手续费和 tick 间距。
保持固定的:终止模式的 30 天事先公告期 END_DELAY,位于无法升级的锁定合约中;单位和编码,从基点到持仓记录的小时;以及接线,从价格喂价到跨链桥的端点,只有升级才能让它们指向别处。
接受的后果:本书就税、发射、金库和空投给出的数字是默认值,而不是保证;所有者可以随时更改其中任何一项,无需事先公告。实测:读取税的设置让一笔兑换多消耗约 1,200 gas(热存储)。参见信任模型。
2026-10-05——审计循环的修复
同一天,一个覆盖全部代码的审查循环带来了若干合约修复,每一项都有回归测试,尚未部署。其中四项改变了行为。
紧急转移之后,账目会被结清,绝不由另一个市场支付。空投合约和远端枢纽持有多个市场应得的资产。从二者中任何一个转出之后,依赖于缺失部分的支付——空投对该股票的领取、远端枢纽在 USDG 通道上的支付——会等待,直到资产被送回,或者 StockFun 的所有者把损失从遭受它的那个循环或市场中核销;在官方跨链桥通道上,所有者在下一笔存入到达之前,删除其现金被转移拿走的那条记录。一个循环只有在还没有人从中领取过该股票时才能被部分减记,此时每位持有者损失相同的比例;一旦已有持有者获得支付,就只能减记它的全部剩余部分,这部分损失由尚未获得支付的持有者承担。转移本身仍然立即生效,不附带任何条件。参见紧急模式。
只有 Keeper 进行跨链。在此之前,任何人都可以发送跨链批次:第三方可以在自己于 Curve 池上的两笔交易之间,以适配器所允许的最宽松的最低数额塞入一个批次,或者抢先跨链 Keeper 批次中的一个金库,使 Keeper 的批次失败。
只有 Keeper 和 StockFun 的所有者能在 Robinhood Chain 上预先部署镜像金库。在此之前,任何人都可以这样做,甚至可以为一个尚不存在的市场预先部署,并与当天的接线绑定在一起。如今,预先部署的金库会在收到其第一个批次时采用远端枢纽的股票路由器和预言机。
在一个正在使用的代币上指定的持仓记录器,从该代币在 PoolManager 之外的供应量起步,而一个此前记录过该代币的记录器会拒绝该代币。在此之前,新的记录器从零起步:每一笔卖出都会失败,此后开启的循环的空投份额也被永久破坏。如今交易会继续进行,而新记录器没有见到变动过的持有者,在其下一次变动之前都会被读作什么也没有持有。就地升级记录器仍然是规则。
较小的修复:金库会确保实际到达的数量不低于 Keeper 自己的最低数额,而不只是满足它们自己的界限;官方跨链桥的账目票据按批次的规模付费;各项设置会拒绝任何池子都无法在其上开启的发射 tick、为零的名称长度限制,以及分别位于不同 PoolManager 上的 Hook 和锁定合约;改用更长的空投时间窗口不再会阻断搁置着股票的市场。参见信任模型。
2026-10-05——审计循环的第二遍
同一天,针对这些修复的第二个审查循环带来了更多合约修复,每一项都有测试,尚未部署,还带来了 Keeper 的变更。
账目计算的是支撑它们的资产,从来不是余额。空投合约的余额,以及 USDG 通道上远端枢纽的余额,还包含已经到达但尚未计入的代币:即最后一步尚未运行的送达。在一次紧急转移之后,这样的代币可能让一个已被清空的循环重新开放领取,并用另一个市场的股票支付这些领取。如今这两个合约都自行计算支撑其账目的资产。紧急转移首先从这部分资产中拿取;它超出这部分所拿走的,来自尚未计入的代币,而之后的送达会先把它偿清,然后才支撑任何东西,远端枢纽会记录这些批次,而不是交付它们。资产通过任何人都可以调用的 restore 送回;一笔普通转账不支撑任何东西,因此救出误入的代币,只能是为了把它们送回。参见紧急模式。
一个循环的全部剩余部分被核销之后(这样的核销发生在一次领取之后),再到达该循环的一切都会在其所有持有者之间按比例分配,就好像被核销的数额从未存在过一样;在此之前,它首先归于尚未获得支付的持有者,按他们领取的顺序。一次核销如果使一个市场不再有任何搁置的股票,就会结束该市场对时间窗口的查找。
代币会拒绝绑定在另一个 Uniswap PoolManager 上、而不是其池子所在的 PoolManager 上的持仓记录器,这样的记录器会把池子算作一位持有者,只付给每位持有者其份额的一部分。而在一个正在使用的代币上指定的记录器,在每位持有者都变动过之前,所保持的已记录供应量至少等于持有者余额的总和,而不是与之相等。
在官方跨链桥上,费用按 Keeper 指定的基础费用报价,即最新基础费用的两倍,多付的部分会被退还:在没有 gas 价格的情况下读取的报价看到的基础费用为零,于是一个较长的批次失败了。远端枢纽只能从批次中得知 Keeper:在第一个批次之前,由 StockFun 的所有者预先部署第一个市场的镜像金库,而一个 Keeper 无法为其预先部署金库的市场会被留在它的批次之外,并发出警报。Keeper 分别统计一个金库在以太坊上和在 Robinhood Chain 上的失败。
就 2026-10-01 的第二轮审计而言:R2H-1 已由结算工具加上一套流程涵盖,即所有者在转移之前暂停远端枢纽;R2H-2 已得到缓解,仍未解决:被冻结的镜像金库不再会让官方跨链桥的队列永久停滞,而且只有 Keeper 构建批次,但向该金库的送达仍会整体失败,因此 Keeper 必须把该市场留在批次之外。参见信任模型。同一天由第四遍关闭:见下文。
2026-10-05——一处失败绝不阻断其余部分
创始人的设计规则,于同一天确立:当某件事让一个功能失败时,其他功能不得为此付出代价;一切都必须继续运作,一切都必须有补救手段,用以找回损失的资金并接受修复。它包含两部分。隔离:一个功能、市场、股票、循环、记录或接收方的失败,绝不会阻断其他部分;该项会被跳过、作为欠款保留或被延后,并发出一个事件,其余部分照常进行。补救手段:每一个可能持有 ETH 或代币的合约,即使只是途经或出于失误,都有一个补救手段,用来转出被卡住的东西;每一个模块都能接受修复,即一次升级或一个替换该模块的 setter。从第四个审计循环起,各审计循环把任何违反都算作缺陷。
唯一的刻意例外:代币向其持仓记录器的报告仍然是阻断性的,报告失败会让转账失败。如果允许报告失败,持有者就可以在自己的转账中让它耗尽 gas,使记录漏掉这次变动,从而让自己的空投份额增大。补救手段立即生效:在代币上调用 setRecorder(0),或者就地升级记录器,各只需一笔交易。
被接受的后果:被拒收的份额会等待其接收方,而不会让其余部分停止;不记在任何市场名下的紧急转移,会让该资产的支付一直等待,直到它被结清;在一个代币没有记录器期间,空投不会为它开启任何循环,并会搁置它的股票。参见架构。
2026-10-05——审计循环的第三遍
同一天,第三个循环针对操作序列展开:单独执行时正确、但在某种顺序或时机下会出错的操作。每一项修复都有测试,尚未部署。
在空投合约上以及远端枢纽的 USDG 通道上,restore 首先偿还紧急转移超出支撑账目的资产所拿走的部分,再用其余部分支撑账目:归还一笔正在等待的送达的代币,不再会用这些代币支付已被清空的市场。一只在任何人领取之前就被从某个循环中整体核销的股票,会离开该循环的股票列表。
在正在使用的代币上指定的持仓记录器,会在切换时开始一份新的记录:空投不会计量任何在切换之前开始的时间窗口,这些时间窗口的股票会被搁置,等待新记录器完整覆盖的第一个时间窗口;代币还会在切换时报告销毁地址的余额。在此之前,这样的时间窗口只从切换时起计量,会多付给在切换之后变动过的人。流程:先开启已关闭时间窗口的循环,然后在一个时间窗口刚结束时进行切换;就地升级记录器仍是规则。
$STOCKFUN 的发射脚本把发射操作者排除在空投之外;在此之前,空投的第一个循环会为这笔持仓付款。跨链桥脚本在工厂合约已经指定另一个枢纽时会在部署之前停止,并在指定枢纽之前先映射股票;setBridgeHub 会拒绝一个无法承载已注册篮子的枢纽。链下:无法读取回执的交易会凭其哈希继续跟踪,绝不会发送两次;紧急监控分块读取其事件,并在失败时警报一次、在恢复时再警报一次;无法构建其批次条目的市场会被排除在外,并发出一次警报。在应用中,未确认的交易会保留其哈希(自第十个审计循环起,它会被一直跟踪到在其 nonce 上被打包的内容,钱包中的取消绝不会被读作已完成:见下文),被终止模式回收的池子既不显示价格,也不显示交易。
2026-10-05——审计循环的第四遍:把规则写进代码
同一天,第四个循环把创始人的规则写进了代码。每一项修复都有回归测试,尚未部署。
跨链送达绝不阻断另一个市场,这是所有者就 R2H-2 作出的决定:现金代币拒绝转给某个镜像金库的份额会留在远端枢纽上,作为欠其市场的款项,其他市场照常获得支付;在官方跨链桥通道上,它会离开队列,因此排在它后面的记录照常支付。任何人都可以之后通过 sweep 支付它。远端枢纽上的紧急转移可以记在单个市场名下,在同一次调用中结清该市场的账目。领取支付它能支付的部分:账目短缺的股票,或者转账被拒绝的股票,会被延后并仍然待付,claimMany 会跳过排除了调用者的循环。每一段买入、向空投的一次发送中的每一只股票,以及跨链批次中的每一个市场,都单独进行。拒收 ETH 的金库不再让其市场停止:Hook 把它未能支付的部分作为欠该金库的款项保留,锁定合约为接收方保留一次手续费收取中被拒收的份额,任何人都可以支付这些款项;无法接收 ETH 的创建者合约可以领取到另一个地址。Lens 一次读取一个金库。
补救手段无处不在:在每一个不为任何人保管任何东西的模块上,都有转出该模块误持之物的救援函数;在 Hook 上只针对误入资金;在锁定合约上绝不针对它所保留的份额;在销毁合约上,只有在任何销毁都无法再花费其 ETH 时才针对这些 ETH;两种代币上也都有;金库、枢纽和空投合约则保留紧急模式。
此外:Ondo 路由器只为其工厂合约的金库服务(M-7),每一个路由器都拒绝把自己作为接收方(L-4);官方跨链桥通道的存入票据按基础费用定价;$STOCKFUN 的发射脚本在铸造之前就把发射操作者列入名单;存储检查会比较每个结构体的每一层。同一天决定:M-2 和 R2F-1 维持现状。参见紧急模式和信任模型。
2026-10-05——Keeper 的空投步骤与领取页面
同一天应创始人的要求编写,没有作出新的决定;尚未部署。Keeper 每个时间窗口发送一次每个市场的股票,默认在美股交易时段之后:先归入搁置的股票,然后开启循环,再进行发送,每只股票和每个市场都单独进行;来自 Robinhood Chain 的每一次送达都会被跟踪,直到它被计入,并附有一条警报,警报中带有重新运行延迟送达的命令。dapp 的领取页面按时间窗口逐一列出一个钱包可以领取的部分,每笔交易最多领取十个时间窗口,在冷存储下测得约消耗 340 万至 350 万 gas。未纳入的部分:自动运行失败送达的最后一步;警报改为给出相应的命令。
随后,第四个循环的链下审查赋予了 Keeper 新的职责:支付 Hook 和锁定合约所保留的欠款,对失败的段、反复被跳过的市场和被拒收的送达发出警报,单独规划每只股票的那一段,一个跨越重启的状态文件,以及每日收取 LP 手续费。对于无法响应的金库,应用会显示“Figures unavailable”。参见Keeper和dapp。
2026-10-05——审计循环的第五遍
同一天,第五个循环发现了七个低严重性问题,每一个都已修复并附有测试,尚未部署。远端枢纽上记在官方跨链桥某条记录名下的转移,只用于存入已经到达的记录:如果数额超过扣除为被拒收份额保留的部分之后剩余的现金,它就会拒绝,而存入已经丢失的记录会被核销。余额无法读取的股票不再会阻止向空投的发送,也不再会阻止其报价;报价中没有代码的适配器同样不会。工厂合约和远端枢纽的实现合约把它们的管理员保存在代理合约的存储中,对于发给它们的东西,由它们的部署者充当补救手段。锁定合约和两种代币都新增了针对误发给它们的 v4 claims 和 NFT 的救援函数;锁定合约仍然没有通用调用。跨链批次会排除金库尚无代码的市场。一条错误描述了买入如何转移资金的注释已被更正。参见紧急模式。
2026-10-06——第五个审计循环的链下审查
第五个审计循环对链下代码的审查发现了三个中等严重性问题和十六个低严重性问题,每一个都已在当天修复并附有测试,尚未部署。Keeper 现在遵循 2026-09-27 的节奏:金库的 ETH 每个空投时间窗口转换一次,前提是在时间窗口关闭后 Keeper 的第一轮中金库达到门槛;低于门槛时,ETH 会等待下一个时间窗口。在此之前,只要金库达到门槛,Keeper 就会在交易时段的任何一轮转换它。Keeper 发送的每一笔交易都会连同其 nonce 一起写入它的状态文件,然后才等待回执,因此在等待期间被终止的 Keeper 不会再次发送它;一笔任何节点都不再知道的交易会在一个时限之后被放弃;一个状态文件夹同一时间只由一个 Keeper 使用。在 Ondo 通道上,Ondo 报价低于金库界限的买入不再会被发送去失败,也不再为它支付证明费用。适配器没有响应的股票会单独被排除在空投发送之外。
一个篮子最多包含五只股票,这是 StockFun 的所有者可以通过升级更改的技术上限:每一项随篮子增长的成本都已在这一规模以内测量过,三个发射篮子分别包含三只、三只和两只股票。Lens 包含每个金库的状态以及 Hook 和锁定合约欠它的款项,它的升级要先于读取它的 Worker 和应用上线。$STOCKFUN 的发射脚本会恢复一次在协议市场被指定之前停止的运行,而不是铸造第二个代币。应用把欠某个金库的 ETH 计入其国库,在领取中为一只在被打包之前计入的股票留出余量,记住被其代币拒绝的股票,并且绝不把无法读取的数据显示为没有。参见Keeper、篮子和dapp。
2026-10-06——第六个审计循环
第六个审计循环发现了一个高严重性问题和五个低严重性问题,每一个都已在当天修复并附有测试,尚未部署。在官方跨链桥上(用于测试网,也作为备用),一旦一个批次的市场被计入,Keeper 就会停止重放该批次的票据,而且一个市场可能被计入另一个批次的现金,因此一笔错过了自动执行的存款可能过期。Keeper 现在会跟踪每一张票据,直到知道它已被执行,无论其转账是否已被计入;它会重放仍然有效的票据,并在默认六小时后仍不知道某张票据已被执行,或该票据已丢失时发出警报;它只依据远端枢纽自身的事件计入官方跨链桥上的转账,从不依据余额。
随这些修复而来的还有一项决定,由审计作为其推荐的默认方案作出:2026-09-27 的节奏扩展到 USDC。金库的 USDC,无论是在以太坊上用于买入股票,还是通过跨链桥发送,都在其 ETH 每次转换之后推进一次,其他情况下每个时间窗口最多一次;在此之前,发送到金库的几个单位的 USDC 会让 Keeper 在每一轮都发送一笔交易,或一个完整的跨链批次。Robinhood Chain 上的买入仍然每一轮都会运行:镜像金库的余额无法区分送达和赠送,而每次买入的上限有意把一笔大额送达分摊到多轮中。本地和测试网运行用同一个开关关闭这两种节奏。
同样已修复:对于没有任何东西可发送的金库,一次不会归入任何东西的搁置股票查找不再每天发送;低于门槛的金库会依据时间窗口关闭之后读取的余额进行检查;在同一天更早的时候,本地部署文件改为在使用之前与链上进行核对;当 Lens 无法读取 $STOCKFUN 的国库时,应用会把它的价格标为“(last read)”,worker 在此期间也不会为它记录任何价格。同一天开始的下一个审计循环发现,Keeper 在同一个路由器上为所有金库报价,而每个金库保留的是它创建时所用的路由器:现在每个金库都在自己的路由器上报价。参见Keeper。
自第七个审计循环起(见下文),“没有任何东西可发送”指的是没有任何值得发送的东西,而 Keeper 会先从每张票据的创建回执开始读取它。
2026-10-06——第七个审计循环
第七个审计循环发现了一个中等严重性问题和十四个低严重性问题,每一个都已在当天修复并附有测试,尚未部署;合约中没有发现问题。在官方跨链桥上,Keeper 会先读取一张票据是否仍然存在,再读取其创建回执:一笔在两次读取之间创建的存款,或被相差一个区块的两个节点看到的存款,可能在仍然有效时被当作已执行,并在没有重放、也没有警报的情况下过期。现在它按照 Arbitrum SDK 的顺序读取它们:先读取回执,然后是自动执行,最后在不早于其创建的区块上读取票据。
随这些修复而来的还有一项决定,由审计作为其推荐的默认方案作出:Keeper 只向空投发送价值抵得上发送成本的东西。一只高于 LayerZero 跨链桥无法携带的粉尘的股票,按其金库自己的预言机、以其价格喂价的最新报价估值,其价值必须至少抵得上它自己的 LayerZero 费用,或它在以太坊上那次发送的 gas 中所占的份额;而通过检验的股票合计必须抵得上整次发送的成本,在时间窗口的循环尚未开启时,还要加上开启它的成本;否则它们会在金库中等待之后的时间窗口,连同之后累积的部分一起发送。Keeper 无法读取的价值会让发送照常进行,与之前一样。倍数是一项 Keeper 设置,KEEPER_AIRDROP_MIN_VALUE_BPS:默认为成本的一倍,设为 0 即关闭这一规则。它只决定一只股票何时发出,从不决定数额、对象或去向。在此之前,向一个无人交易的市场的金库赠送一笔略高于粉尘的股票,就会让 Keeper 每天开启该时间窗口的循环并支付一条 LayerZero 消息;而同样的粉尘被算作“有东西可发送”,因此第六个审计循环对搁置股票查找的限制在跨链桥上并不成立。
同样已修复:Keeper 的每一次日志查找都在链的最新区块之下几个区块处停止,因此事件绝不会因一个落后一两个区块的节点而被漏掉;Keeper 会检查每个 RPC 服务的是否是其配置所指定的链,否则拒绝启动;它的警报 webhook 有时间限制,其响应会被读取,webhook 未接收的警报会被保留并重新发送;空的设置采用其默认值。应用的数据 Worker 单独读取每一个可升级合约,因此一个在有缺陷的升级之后失效的合约不再会让 $STOCKFUN 代币的数据变成空白;当它对交易日志的读取持续失败时,它会把 24 小时交易量显示为未知,它会检查自己的每个端点是否服务于其所在的链,而价格图表会把每个数据点放在它的时间上。Lens 和 Worker 的数据模式没有变化。参见Keeper和dapp。
自第八个审计循环起(见下文),对于自身报价为零的股票,会向其适配器询问;在本地通道上,时间窗口的开启只计算一次;票据在最新区块之下几个区块处读取;在没有设置链标识符时,Keeper 不再假定一个。
2026-10-06——Robinhood Chain 上的价格喂价防护
发射计划列出了预言机当时尚不具备的两项防护,两者都是 Robinhood 的文档所推荐的。它们已经建成,尚未部署,作为 StockFun 所有者的设置,初始为关闭;每一项都只能暂缓给出价格,绝不会改变价格。
- 公司行动。当一只股票经历公司行动时,它的代币会表明其预言机已暂停,而它的价格喂价会保持其最后一个数值,在代币的乘数变化时,这个数值看上去可能仍然是新鲜的。预言机现在会暂缓给出该股票的价格:它的买入段单独失败,其现金为它保留,篮子中的其他股票照常买入。这项检查对 Robinhood 通道上的每只股票开启,按股票分别设置,因此一个其响应无法使用、或其标志一直处于设置状态的代币,可以单独关闭。不响应的代币被视为未暂停:Robinhood 称这个标志仅供参考,而喂价自身的过期检查仍是主要防护。
- 排序器。Robinhood Chain 是一条只有单一排序器的 Arbitrum 链。在设置了 Chainlink 的 L2 排序器在线状态喂价的情况下,当排序器宕机、在宽限期(默认一小时)内刚刚恢复,或该喂价无法读取时,预言机会暂缓给出所有价格。Robinhood Chain 没有这样的喂价,而 Chainlink 也不再为新网络添加这类喂价:通道在部署时关闭这项检查,这是部署脚本要求作出的明确选择,如果将来发布了这样的喂价,由 StockFun 的所有者设置它。
在以太坊上,两者都保持关闭。参见Robinhood 通道。
2026-10-06——第八个审计循环
第八个审计循环发现了一个中等严重性问题和八个低严重性问题,每一个都已在当天修复并附有测试,尚未部署;合约和价格喂价防护中没有发现问题。在应用读取链上的篮子注册表之前,它的发射表单提供的是配置中的篮子及其配置编号:在一个以其他方式为篮子编号的部署上,创建者可能会不可逆地在一个与所显示的篮子不同的篮子上发射市场。表单现在只提供从链上读取的篮子,并在发送之前从工厂合约再次读取所选的篮子,如果名称或股票不同就拒绝发送。
同样已修复:Keeper 只在包含跨链批次的区块已有几个区块深度之后才跟踪该批次,因此以太坊最新区块的一次重组不再会让它跟踪永远不会出现的标识符;它能区分跨链桥无法携带的粉尘和一只自身的 LayerZero 费用无法报价的股票,现在会把后者排除在外并发出警报,而不是悄无声息地丢弃它;它对每一条不同的警报只保留一条待发记录,并附上它被触发的次数和时间,因此每个循环都重复的警报不再会把一次性的警报挤出去;在检查自己的 RPC 服务于哪条链之前,它不再把为另一条链写入的状态文件移到一边,并且要求两个链标识符都已设置;它在最新区块之下几个区块处读取票据,而一个端点的每个节点都拥有这个区块;在本地通道上,它对时间窗口的开启只计算一次。Keeper、它的预检和它的检查器掌握了价格喂价防护:当预言机因排序器而暂缓给出价格时,Robinhood Chain 上的买入会等待,并发出一次警报,而处于公司行动中的股票会单独等待,绝不计为失败。应用的数据 Worker 绝不把它的交易窗口往回移动,因此一个落后几个区块的节点不再会让 24 小时交易量把区块统计两次;它的 RPC 代理会拒绝任何并非地址的地址;它发布股票价格缺失的原因(数据模式 8),由应用显示;交易面板在防狙击期间对白名单钱包收取正常税率,与 Hook 一致。Lens 没有变化,Worker 和应用仍然可以按任意顺序部署。参见Keeper和dapp。
2026-10-06——Glamsterdam 下空投送达的 gas
Sepolia 于 2026-10-06 在 LayerZero 测试网运行期间(见下文)启用了以太坊的 Glamsterdam 升级;Hoodi 和主网当时还没有确定日期。它重新定价了状态的增长:一个以冷方式写入的新存储槽需要 110,020 gas,而之前是 22,100。合约和脚本中的每一个固定 gas 数值都在 Sepolia 上重新测量过,除了一对数值之外全部成立,这一对就是空投送达在以太坊上获得的 gas:镜像金库的发送只携带一个 compose 数值,即 600,000,而股票 OFT 的 lzReceive 只获得该 OFT 强制设定的 gas。这次运行的第一个循环中的每一次送达都在 LayerZero 的执行器处耗尽了 gas,并被手动执行。第十个审计循环随后又发现了两个:部署脚本自身的 gas,以及跨链桥 compose 针对一个批次的 gas(见下文)。
创始人在同一天作出决定:Keeper 模拟每一次送达并为其选择 gas,这一 gas 被限制在 StockFun 的所有者于远端枢纽上设定的范围之内;仍然卡住的送达由 Keeper 重新执行,第二次失败时发出警报。已写进代码,尚未在主网上部署:
- 远端枢纽保存两项 gas 策略,每一项都包括一个默认值、一个下限和一个上限:在股票 OFT 强制设定的 gas 之上的
lzReceivegas,650,000,介于 200,000 和 1,500,000 之间(setAirdropReceiveGas),以及 compose gas,1,250,000,介于 600,000 和 4,000,000 之间(setAirdropComposeGas)。镜像金库的sendToAirdrop(stocks, receiveGas, composeGas)针对 Keeper 的请求发送枢纽所批准的数值,零表示采用默认值;只带股票的调用采用两个默认值。从没有这些策略的版本升级而来的枢纽,在两项策略都设置之前会拒绝每一次发送 - Keeper 从端点的地址出发,在以太坊上模拟每只股票的
lzReceive和 compose,并请求所需的 gas 加 25 %;当模拟无法运行时,它采用该市场最近几次送达所使用的 gas,然后是枢纽的默认值。一次在 LayerZero 的执行器使其失败之后、或十分钟之后仍存储在端点上的送达,会由 Keeper 用自己的密钥再次执行,使用其模拟所需的 gas 加 25 %,默认最多 4,000,000 gas;无法执行的送达会发出附带手动执行命令的警报,第二次失败会发出警报,并且绝不再发送 - 应用每笔交易领取五个时间窗口而不是十个,为一个时间窗口仍可能收到的每只股票留出 400,000 gas,并曾在每笔交易的估算之上增加 150,000 gas,第九个审计循环已用每笔交易自己的上限取代了这一做法(见下文)
这一修复通过升级应用到测试网运行的远端枢纽和镜像金库上,并支撑了它之后的各个循环。参见Keeper和Robinhood 通道。
2026-10-06——LayerZero 测试网运行
协议被部署在 Sepolia 和 Robinhood Chain 的测试网上,使用的是生产脚本,或保留其主体的测试网包装脚本,共 167 笔交易,全部成功,配有测试股票、测试适配器、一种测试 USDG 和模拟喂价,并从 13:50 运行到 19:07 UTC:七个每小时的时间窗口,每一个的 ETH 都被转换、通过 LayerZero 跨链并花费在测试股票上;六个空投循环通过 LayerZero 发回,前四个由五位持有者全额领取,每一笔支付都恰好等于根据持仓记录器计算出的份额;事故演练在真实消息上进行,并按文档所述恢复,只有两个半项例外。它证明了 StockFun 的代码能在 LayerZero 真实的端点、DVN 和执行器上运行。它不能证明 Paxos 的 USDG 对、Robinhood 的股票及其适配器、真实的喂价或流动性,也不能证明主网的 gas、费用和最终性:仍需进行一次主网试验。它在生产代码中发现的是 Glamsterdam 的重新定价(见上文)和第九个审计循环的一部分(见下文)。参见Robinhood 通道。
2026-10-06——第九个审计循环与验证者关卡
第九个审计循环审查了第八个审计循环的修复,并采纳了 LayerZero 测试网运行操作者的发现。它发现了两个中等严重性问题,即空投送达的 gas(见上文),以及应用的数据 Worker 在其 Cloudflare 对象每次被逐出时都重建其 RPC 故障转移,这在主 RPC 中断期间让它在不到七分钟内向主 RPC 发出了 37 个请求,而现在只有 8 个;还发现了 Keeper、Worker 和一个测试网脚本中的若干低严重性问题,每一个都已在当天修复并附有测试。在自己的一笔交易之后的一分钟内,Keeper 会在该交易所在的区块上读取它所改变的内容,并估算它接下来要发送的交易的 gas,因此一个落后一个区块的节点不再会把转换之后立即发送的跨链批次变成一次虚假的失败;它的每一笔交易都以其估算的 gas 加 25 % 发送;它未能送达的警报按最后一次被触发的顺序发送;一张被它自己的执行删除的票据不再被当作仍然有效而发出警报;一个任何日期都无法容纳的链上时间会读作“an unknown time”;它会解码预言机的错误;它的预检可以在测试网运行的部署上运行。Worker 记录 Robinhood Chain 自身的区块号。
自这个审计循环起,第二个代理会在每一项修复被推送之前审查其改动,对照的是之前各个审计循环发现的缺陷类别,其中大多数出现在上一个审计循环的修复中:这就是验证者关卡。它发现的问题会像审查发现一样被修复,而这一修复会再次经过关卡。在这个审计循环中,它在若干修复中发现了低严重性缺陷,其中包括一次重新执行相信了任何人都可以发出的警报事件,现在只相信来自 LayerZero 执行器的这类事件;以及一次重新执行在失败运行自己的区块上判定失败,而该区块的一次重组本可能把它变成一次虚假的第二次失败:现在它会等到该区块已有几个区块的深度。全部都已修复。
随后,这个审计循环对 Worker 和应用的审查又发现了一个中等严重性问题,即当一笔交易遇到比当小时供应量标记更多的新存储时,应用在交易估算之上增加的 150,000 gas 不够用,已于当天修复:现在每笔交易获得其估算值加 50,000 gas,而一笔交易还会获得其估算无法看到、但仍可能发生的每一项写入的 gas,并在估算所用的区块上读取;估算失败的交易会使用固定上限发送,此时发射会等待。它的两个低严重性发现也已修复:作为估算值的国库金额无论显示在哪里都标有“+”,而无法读取的授权绝不会被当作没有授权。这个审计循环不是干净的,干净审计循环的计数仍为零。参见Keeper和dapp。
2026-10-06——第十个审计循环
第十个审计循环审查了第九个审计循环的修复以及围绕以太坊 Glamsterdam 升级的工作,每个领域都从它自己的角度审查:新 gas 价格下的合约、每一条在目的地失败的跨链消息、跨越数月的 Keeper、使用真实钱包的应用,以及对照代码的文档。它发现了三个中等严重性问题和六个低严重性问题,每一个都已在当天修复并附有测试,每一项修复都经过验证者关卡审查,尚未在主网上部署。从 gas 的角度看,合约在两套价格表下都是干净的。
- Glamsterdam 下的部署流程。文档所述的以太坊部署不可能成功:部署工具给每笔交易的是它自己本地模拟的 gas,按旧价格计算,而现在创建一个合约需要四到七倍。现在每次广播都会在上一笔交易被打包之后,向节点询问每笔交易的 gas;已在 Sepolia 上演练
- 跨链批次的 compose gas。跨链批次在 Robinhood Chain 上的最后一步只获得一个固定的 gas 数值,即 1,200,000,无论批次包含什么:四个新的五只股票市场耗尽了它,它们的 USDG 随后停留在远端枢纽上,没有任何记录,而之后每一个包含相同市场的批次都以同样的方式失败。现在这一 gas 是一个基数加上每个市场的一份,默认分别为 200,000 和 400,000,两者都是 StockFun 所有者的设置,而一个批次最多携带 17 个市场,这使它的消息保持在 LayerZero 的大小限制之内,它的 gas 保持在 Robinhood Chain 每笔交易的限制之内;Keeper 最多发送这么多,其余的留到它的下一轮,等待最久的市场优先。额外的 gas 成本很低:LayerZero 的执行器按 Robinhood Chain 的 gas 价格收取,在测试网上为每百万 gas 0.00001 ETH。Keeper 针对停滞转账的警报现在会说明批次消息所处的状态。测试网的适配器在同一天升级,它的下一个批次以新的 gas 顺利通过
- 紧急监控。Keeper 过去在一个日志请求中列出所有被监控的金库,而端点会拒绝超出其限制的请求:一旦注册表超过这一限制,就再也不会有任何紧急转移被转发。现在它分组列出这些金库,每组的规模受一项新设置约束
- 较小的修复。Keeper 的错误文本只保留 RPC 地址的主机;它对每个市场的读取通过 Multicall3 进行,每次调用一百个市场,而不是在每一轮逐个读取;应用会跟踪钱包取消或替换的交易,绝不把取消显示为已完成,并且在它自己的交易之后的一分钟内,在不早于该交易所在区块的区块上读取,因此紧随授权之后的卖出不再会被落后一个区块的节点拒绝;另有两份文档已与代码保持一致
在其默认设置(在美股交易时段之后发送)下,Keeper 现在对交易时段结束后没有任何东西可发送的金库,只会在下一个交易时段再次读取。这是这项节省带来的后果,而不是一条新规则:在交易时段结束后、在任何买入之外转入金库的股票,会随下一个交易时段的发送进入之后的某个时间窗口;金库自己的买入带来的部分仍然进入当天结束的那个时间窗口。
审计还权衡了一项建议,而不是一个缺陷:让领取在 Hook 的每一项手续费累计中留下一个 wei,使下一笔交易永远不必为从零写入这些存储槽付费。它目前未被采纳。额外的 gas 落在每次领取之后的第一笔交易上,每个存储槽约 104,000,而应用为此留出的余量提高的是交易的上限,而不是它支付的费用;这一改动会触及领取代码,而其形式化规则在不运行证明器的情况下无法再次得到证明;Hook 和销毁合约以后可以通过升级采纳它,无需迁移。这个审计循环不是干净的,干净审计循环的计数仍为零。参见Keeper、Robinhood 通道和dapp。