紧急模式

自 2026-08-29 起,StockFun 的所有者可以把一个国库的资产,或任何持有协议资金的合约中的资产,转移到任意地址。自 2026-10-05 起,这种转移立即生效:没有事先公告,没有延迟,任何设置也无法加上延迟。这是项目影响最深远的一项变更,它改变了产品被允许说的话。

它允许什么

emergencyTransfer(asset, amount, to) 在持有该资产的合约上调用,把任何资产——ETH、USDC、USDG、代币化股票、市场代币——的这一数额立即转移到 to。有五个合约具备这一函数:以太坊上的 TreasuryVault、BridgeHub,以及自 2026-10-04 起的空投合约 AirdropDistributor;Robinhood Chain 上的 RemoteHub 和各个镜像金库。只有它们的紧急管理员可以调用它:在以太坊上是工厂合约的所有者;在 Robinhood Chain 上是最近一个跨链批次所携带的同一地址。所有者可以随时在这些合约中的任何一个上使用它。

每一次转移都会获得一个顺序编号,并发出一个公开事件 EmergencyExecuted,其中载有资产、数额和接收方。事先没有任何公告。

在 2026-10-05 之前,所有者需要先安排转移:一个公开事件予以宣布,所有者可以在 48 小时内取消,此后任何人都可以执行。这一安排机制已被取消,而延迟也不是一个参数:紧急模式一经所有者使用就立即生效,从不需要等待。随之取消的,还有为卡在镜像金库中的空投资金规划的例外,该例外从未写进代码:立即生效的转移已经涵盖了这些资金。

与之并行的还有:对转换和跨链的暂停——立即生效,不转移任何资金——以及替换未来发送所用的跨链桥适配器(changeAdapter),自 2026-10-05 起同样立即生效。在空投合约上,暂停会停止发送、循环的开启(openCycle)以及搁置股票的归入(assignUnassigned);它不转移任何东西,也从不阻止领取。

自 2026-10-01 起,暂停中的远端枢纽仍会应用每个批次所携带的 Keeper 和紧急管理员变更,因此所有者的更换总能抵达 Robinhood Chain;在此期间它收到的现金会留在那里,按市场记录,直到解除暂停后的一次 sweep。

2026-09-29 的安全审计发现,适配器替换无法端到端地运作:远端枢纽只接受来自原适配器的批次,因此替换之后发送的每一个批次都会滞留在远端枢纽上,直到紧急模式将其回收(M-2)。2026-10-05,所有者决定维持现状:适配器的更换通过就地升级完成,地址不变;换用一个新地址,首先需要升级远端枢纽,使其接受这个地址。

在金库上,自 2026-10-01 的安全流水线起,一次紧急转移如果使现金低于各股票的预留额,就会把这些预留额全部清零:剩余的现金,以及之后每一笔流入的现金,都按篮子的权重重新分配。只拿走未预留现金或其他资产的紧急转移,会保留这些预留额。被取出后又送回金库的现金,会像任何流入的现金一样分配,而不会回到它原先为之预留的那只股票。

2026-10-01 的第二轮审计发现,在远端枢纽上,拿走已为某个市场记录的现金的紧急转移,会让该记录保持不变,留待用其他市场的现金支付(R2H-1)。自 2026-10-05 起,转移之后会进行结算,见下文,而这种情况由结算的工具加上一套流程涵盖:在官方跨链桥通道上,StockFun 的所有者在转移之前暂停远端枢纽。自当天的第四个审计循环起,转移还可以记在单个市场名下,在同一次调用中结清该市场的账目。

转移之后:结清账目

自 2026-10-05 起,在当天的各个审计循环之后。转移本身没有改变:立即生效,没有任何条件。但有两个合约所持有的资产,支撑着多个市场应得的数额:空投合约和远端枢纽。从二者中任何一个转出之后,账目会被结清,绝不由另一个市场支付。要么资产被送回,要么 StockFun 的所有者把损失从遭受它的那个市场中核销。

这两个合约计算的都是支撑其账目的资产,从来不是它们的余额。余额中还包含已经到达但尚未计入的代币:一笔在以太坊上的最后一步尚未运行的股票送达,或者在 USDG 通道上,一个在 Robinhood Chain 上的最后一步尚未运行的批次的现金。这些代币尚未支撑任何东西,并且可能属于另一个市场。在 2026-10-05 的第二个循环之前,这两个合约读取的是余额,因此这样的代币可能让一个已被清空的循环重新开放领取,并用另一个市场的股票支付这些领取。

  • 紧急转移首先从支撑账目的资产中拿取。这些代币无法区分,而先把已计入的代币算作已被拿走,绝不会让一个市场为另一个市场付出代价。它超出这部分所拿走的,来自尚未计入的代币:合约会记录这一数额(taken、cashTaken),而该资产之后的送达会先把它偿清,然后才支撑任何东西。
  • 资产通过 restore 送回。任何人都可以调用它;它从调用者那里拉取代币。向合约进行的一笔普通转账不支撑任何东西。自 2026-10-05 的第三个审计循环起,restore 首先偿还一次转移超出支撑账目的资产所拿走的部分(taken、cashTaken),再用其余部分支撑账目:一笔仍在等待的送达的代币,绝不会用来支付一个已被清空的市场。
  • 误入的代币。到达空投合约或 USDG 通道上的远端枢纽、却从未被计入的代币,即被误发到那里的代币,如果被一次紧急转移取出,同样会从支撑账目的资产中扣除。一次紧急转移取出它们,只能是为了把它们送回;否则,它们的数额就必须从它所落到的那个循环或市场中核销,或者通过一次升级清除。

  • 空投合约逐只股票记录它所欠的数额以及支撑这一数额的资产,并且只有在支撑资产足以覆盖这一数额时才支付该股票。在一次拿走了某只股票一部分的转移之后,在每一个持有该股票的市场中,对该股票的领取都会等待,直到该股票通过 restore 被送回,或者直到所有者把这笔损失从蒙受它的那个循环中核销(writeDownCycle),或从一个市场所搁置的股票中核销(writeDownUnassigned)。只要还没有人从该循环中领取过这只股票,所有者就可以核销其中的任意一部分,该循环的每位持有者都损失相同的比例;一旦已有持有者获得支付,所有者就只能要么核销全部剩余部分,这部分损失由尚未获得支付的持有者承担,要么把该股票送回。此后到达该循环的一切,都会在其所有持有者之间按比例分配,就好像被核销的数额从未存在过一样。没有任何其他循环为此支付。自第四个审计循环起,一次领取只延后正在等待的那只股票(ClaimDeferred),并在同一次调用中支付其他股票;在此之前,它会整体失败。空投合约没有记在单个循环名下的转移:它的大小限制没有留下空间。绝不让其账目出现短缺的流程是:先减记该循环或搁置的股票,然后再转移该股票;先进行的转移则会保持上文所述的整体等待。

  • USDG 通道上的远端枢纽计算支撑其所欠数额的现金,并在这部分现金不足时拒绝支付(sweep)。一次转移如果拿走的超过了这部分现金,接下来的批次就会被记录而不是交付,直到它们补足了这一差额。所有者把现金送回(restore),或者核销一笔已经损失的数额,或一笔已由转移手动交付给该市场镜像金库的数额(writeOffPending)。自第四个审计循环起,所有者还可以把一次转移记在单个市场名下:emergencyTransferFromPending(marketId, amount, to) 转移枢纽欠该市场的款项,并在同一次调用中将其核销,因此账目绝不会出现短缺,也没有任何其他市场需要等待。
  • 官方跨链桥通道上的远端枢纽所欠的是其队列中的记录,它不做这样的计算:保护靠的是一套流程。所有者在转移之前暂停枢纽,转移现金,删除这笔现金所属的那条记录(writeOffRecord),然后解除暂停,这样队列就绝不会用另一个市场的现金第二次支付这条记录。自第四个审计循环起,针对一条记录,一次调用即可完成这些:emergencyTransferRecord(index, to) 转移该记录的全部数额并将其删除。自第五个审计循环起,这一调用只用于存入已经到达的记录:队列的现金是汇集在一起的,因此,如果数额超过扣除为被拒收份额保留的部分之后剩余的现金,它就会拒绝(RecordNotCovered);存入已经丢失的记录则通过 writeOffRecord 删除。被某个镜像金库拒收、为其市场单独保存的份额(undeliverable),通过 emergencyTransferFromPending 转移并核销。

每一次核销都会发出一个公开事件(WrittenDown、PendingWrittenOff),每一次送回(Restored)和每一次被延后的领取(ClaimDeferred)也是如此。

救援:模块误持的资产

自 2026-10-05 起,根据创始人“一切能够持有资金的东西都要有补救手段”的规则(参见架构),没有紧急模式的合约都有自己的救援函数,用于处理误发给它们的东西,或一次失败的操作所遗留的东西。只有 StockFun 的所有者可以调用它:在以太坊上是工厂合约的所有者,在 Robinhood Chain 上是远端枢纽的管理员,也就是升级各个模块的那个地址。每一次救援都会发出一个公开事件。

  • 在交易之间不为任何人保管任何东西的模块——工厂合约、Lens、预言机、持仓记录器、股票路由器、官方兑换路由器和跨链桥适配器——都有 rescue(asset, amount, to),可用于 ETH(零地址)或任何代币
  • Hook 只救援误入资金:至多是除 PoolManager 之外的任何人发给它的 ETH(strayEth),以及任何代币,因为它从不持有代币。创建者、团队和回购的余额以及欠各金库的款项,绝不会通过这种方式离开。不经调用被强行转入的 ETH 不计入其中,只能等待一次升级
  • 流动性锁定合约不可升级,它可以救援任何代币,以及超出它为金库和创建者保留的份额(totalOwed)的 ETH,这些份额绝不会通过这种方式离开;自第五个审计循环起,还可以救援在 PoolManager 中记给它的 v4 claims(rescueClaims),以及通过普通转账发给它的 NFT(rescueNft)。它没有通用调用:借助 PoolManager,这样的调用可能绕过 30 天,直接达成终止模式的回收。它的头寸仍然只能通过终止模式触及
  • BuybackBurner 随时可以救援代币,而它的 ETH 只有在任何销毁都无法再花费时才能救援:在协议市场被指定之前,或者在终止模式回收了 $STOCKFUN 池之后。只要该池仍处于锁定状态,它的 ETH 就只能通过销毁离开
  • 代币不可升级,它们可以救援发到它们自身地址的东西:它们自己的代币(像任何转账一样向持仓记录器报告)、任何其他代币、被强行转入的 ETH,以及自第五个审计循环起的 v4 claims 和 NFT(rescue、rescueClaims、rescueNft)。任何持有者的余额都无法通过这种方式转移
  • 代理合约背后的实现合约从不被直接使用。工厂合约和远端枢纽的实现合约把它们的管理员保存在代理合约的存储中,对于发到它们自身地址的东西,掌握补救手段的是部署它们的地址;其他每一个实现合约都通过其授权方读取它的管理员,即协议所有者

金库、两个枢纽和空投合约则保留紧急模式,因为它们有自己的账目。以太坊上的两个部署器和镜像金库部署器不持有任何状态,不接收 ETH,也没有所有者:它们不需要补救手段。

它不允许什么

紧急模式不会触及喂价注册表。它转移资产;它不改变执行界限,执行界限是所有者另行掌握的设置。它无法让金库以任意价格买入任何东西;它可以立即拿走金库里的东西。

它也无法触碰锁定的流动性或持有者的代币。空投同样如此:紧急模式可以转移空投合约中的股票,但它无法改变一个循环在其持有者之间如何分配。份额保持不变;自 2026-10-05 起,只有当支撑合约账目的资产足以覆盖它在该股票上所欠的全部数额时,领取才会被支付,而一笔不会回来的损失会从遭受它的那个循环中扣除,绝不会从另一个循环中扣除(见上文)。

不过,它并不是所有者通往金库的唯一路径。自 2026-10-02 起,StockFun 的所有者还可以升级金库或金库所读取的预言机,同样立即生效。锁定的流动性有自己的出口,即提前 30 天宣布的终止模式:这是协议中唯一固定的延迟。参见信任模型。

它为什么存在

跨链故障模式审查提出了一个简单的问题:当一条路径失败、一条跨链桥消息丢失,或一个合约存在漏洞时,会发生什么?

如果没有回收路径,答案就是“资金永久丢失”。协议选择了一条受控的回收路径,由所有者掌握并记录在链上,而不是一个什么都无法修复的系统所具有的优雅。自 2026-10-05 起,这条路径一经使用就立即生效。

自 2026-10-01 起,对于篮子被 Robinhood Chain 拒绝的市场,其现金也正是通过这条路径离开该市场的镜像金库,而该镜像金库保持未初始化状态:参见Robinhood 通道。

它的代价

所有者可以把一个国库的资产立即转移到任意地址,无需事先公告。这一点已写入项目的信任模型。

最重要的是,经审定的措辞取代了此前的每一个承诺。

资产由市场的金库持有,并由其规则管辖。StockFun 团队可以在紧急情况下,于公开的 48 小时延迟之后转移一个国库的资产。

自 2026-10-05 起,这句话中的延迟已不复存在:转移立即生效。这句话有待修订,其新措辞有待审定。自 2026-10-02 起,它也不涵盖金库的升级,这些升级立即生效。

产品再也不能说 non-custodial、trustless、immutable treasury 或 no one can touch the treasury。这些说法已被品牌规范禁止;自动文案审计并不检查它们,而是由人工审阅把关。

紧急模式从不被描述为一种保护,或一种针对损失的保证。它是团队所持有的一项权力,立即生效。仅此而已。

用户看到什么

在 2026-10-05 之前,原计划在每个受影响的界面上显示一条横幅,宣布已安排的回收及其执行日期。如今转移立即生效,因此没有任何可以提前宣布的东西:它只在事后才变得可见,即出现在它所离开的那个合约的 EmergencyExecuted 事件中。