空投
自 2026-09-27 起,一个市场的国库只有一个用途:其买入的代币化股票 100 % 空投给该市场代币的持有者,按持仓比例分配,每 24 小时一次。此前的创建者回购已被移除。
已写进代码并经过测试,尚未部署。空投合约 AirdropDistributor 已于 2026-10-04 写进代码并经过测试,同时完成的还有从两种金库为它供给股票的路径;Keeper 每日的空投步骤和 dapp 的领取页面已于 2026-10-05 编写完成。测试以 mock 模拟 LayerZero,而且尚未部署任何东西。仍待完成:各只股票的 LayerZero 适配器。参见实施状态。
分发什么
国库买入的一切:每一笔交易(买入和卖出)的 2 %,加上该市场前十个区块中防狙击的超出部分,在转换为该市场篮子中的股票之后进行分发。
分发以实物形式进行:持有者收到的是代币化股票,以封装形式发放在以太坊上(见下文),绝不是现金。仍在等待转换的 ETH、USDC 或 USDG 不会以原样分发;它们在转换为股票之后才会被分发。
分发给谁,在哪里
分发给该市场代币的持有者,按持仓比例分配。协议自身的地址什么也收不到。
持仓按每个钱包在循环前 24 小时内的平均余额计算,周一也是如此:持有代币一小时,计为一整天的 1/24。在时间窗口关闭前一刻买入,几乎分不到任何份额。自 2026-09-28 起,每个钱包随时间变化的持仓都在链上记录,因此每一份额都由以太坊上的一个合约计算;Keeper 从不提供这些份额。自 2026-10-02 起,这份记录保存在代币之外,由一个模块即持仓记录器保存:每个代币都会向它报告每一次余额变动,如果报告失败,转账也会失败。这是有意为之,是协议“一处失败绝不阻断其余部分”这一规则的唯一例外:如果允许报告失败,持有者就可以在自己的转账中让它耗尽 gas,使记录漏掉这次变动,从而让自己的份额增大。参见架构和下文的运营规则。
自 2026-10-01 起,这份记录还保存每个代币的已记录供应量随时间的变化:即 Uniswap PoolManager 之外的所有余额。它为份额提供了分母:
份额 = 时间窗口内的平均余额
÷ (平均已记录供应量 − 各被排除地址的平均余额)
被排除的地址是那些什么也收不到的地址:始终包括销毁地址,以及该代币排除名单上的地址;参见下文的排除名单。记录器只在整点边界上提供已记录供应量,因此空投的时间窗口都在整点开始和结束。其代价是每一笔兑换多一次存储写入。一个代币在每个小时中的第一笔兑换,无论买入还是卖出,都要多消耗约 28,000 至 30,000 gas,这是于 2026-10-01、在这份记录移出代币之前作为一笔单独的交易测得的;本页直到 2026-10-01 的安全流水线为止给出的 23,000,是在一笔交易内部测得的。因此,如果交易落地时成为下一个小时的第一笔兑换,钱包在一个小时临近结束时做出的 gas 估算就可能不足。自以太坊的 Glamsterdam 升级起(自 2026-10-06 起已在 Sepolia 上启用,主网则在其分叉时启用),这次写入会按新价格创建它的存储槽:在 Sepolia 上,一个小时的第一笔兑换多消耗了 123,216 gas。对于可能成为一个小时第一笔兑换的交易,应用会多给 150,000 gas:这只是一个更高的上限,因为一笔交易只为它实际使用的 gas 付费。
持仓在代币进行交易的以太坊上计量,而自 2026-09-28 起,股票也在那里分发。股票在 Robinhood Chain 上买入,锁定在由 StockFun 部署的 LayerZero 适配器中(每只股票一个),再以封装股票的形式发送到以太坊,每一股锁定的股票对应一股封装股票。每位持有者在以太坊上领取自己的份额,并支付领取的 gas。若要持有真正的股票,持有者需自费将封装股票通过跨链桥送回 Robinhood Chain。StockFun 的所有者掌握适配器的 LayerZero 配置,没有延迟,也没有提取上限:参见信任模型。
这一规则适用于每一个国库,包括 $STOCKFUN 的国库,它会空投给 $STOCKFUN 的持有者。
每 24 小时一次
空投以每日循环的方式运行,逐个市场进行。它的时间(默认为 13:00 UTC)关闭用于计量持仓的时间窗口,全年都在美股开盘之前:开盘时间夏季为 13:30 UTC,冬季为 14:30 UTC。循环中的买入随后在紧接着的交易时段内进行,而它的发送默认在该交易时段结束之后进行:
- 如果该市场的国库已累积至少 0.1 ETH,Keeper 会将其转换,通过跨链桥发送,并买入篮子中的股票。
- 默认在当天的交易时段结束之后,Keeper 将所买入的股票以封装形式发送到以太坊上的空投合约,其中 100 % 可由代币的持有者领取。自第七个审计循环(2026-10-06)起,它在这些股票的价值抵得上发送它们的成本(包括开启时间窗口的成本)时才发送;否则它们会在金库中等待之后的时间窗口,连同之后累积的部分一起发送(参见Keeper)。自第十个审计循环起,对于一个在交易时段结束后没有任何东西可发送的金库,Keeper 要到下一个交易时段才会再次读取它,因此在交易时段结束后、在其买入之外转入金库的股票,会随下一个交易时段的发送进入之后的某个时间窗口;当天的买入带来的部分仍然进入当天结束的那个时间窗口。
低于 0.1 ETH 时,该市场当天什么也不会发生:ETH 会等待下一次循环。按 2 % 计算,达到这一门槛需要该市场约 5 ETH 的交易量,买入和卖出合计。在一天当中越过门槛不会触发任何操作:转换只在每日循环中进行。Keeper 在时间窗口关闭后的第一轮检查每个金库,并在该时间窗口内只转换一次其 ETH;它自 2026-10-06 起遵循这一点,在此之前,只要金库达到门槛,它就会在交易时段内的任何一轮转换金库的 ETH。已在金库中等待的现金会继续推进,无论是否达到门槛:自第六个审计循环(2026-10-06)起,金库的 USDC 在其每次 ETH 转换之后推进一次,其他情况下每个时间窗口最多一次,镜像金库的 USDG 则在每一轮推进。
股票只能在美股市场开盘期间买入。因此,周末和 NYSE 休市日没有循环:周五的费用会在周一分发。
门槛和日历是 Keeper 的规则:空投合约对二者都一无所知。它只知道时间窗口,并把每一次发送记入它到达时最近一个已关闭的时间窗口。
循环的长度和关闭时刻、门槛 0.1 ETH,以及下文所述空投合约的各项限额,自 2026-10-05 起都是 StockFun 所有者的设置;本页给出的数值是默认值。新的时间表适用于尚未开启的时间窗口:已经开启的循环保留其时间窗口。
在途中失败的循环——跨链桥延迟、喂价过期、界限拒绝执行——只会停止失败所触及的部分。自 2026-10-05 起,每只股票的买入都单独进行:某一段失败的股票会把它的现金保留到之后的循环,而篮子中的其他股票照常买入;被排除在跨链批次之外的市场会等待,而其他市场照常跨链。未能继续的部分会在该市场的金库中(在以太坊上或在 Robinhood Chain 上)等待,并在下一次循环中处理完毕,即使国库尚未再次达到 0.1 ETH。StockFun 的所有者也可以随时通过立即生效的紧急转移来转移它:参见紧急模式。
循环如何运作
在空投合约中,自 2026-10-04 起:
- 时间窗口。一个循环的时间窗口是其结束时刻之前的一段时间:默认为在 13:00 UTC 结束的 24 小时。StockFun 的所有者以整小时为单位设定其长度和关闭时刻(
setCycleSchedule)。一次发送属于在其到达之时或之前最近一个关闭时刻结束的时间窗口,绝不会属于早于该市场最近一个已开启循环的时间窗口。 - 开启即冻结各项数值。一个时间窗口的第一次发送会开启它的循环。Keeper 可以先用
openCycle开启它,任何人都可以调用这个函数:Keeper 在时间窗口关闭之后、股票到达之前这样做,因此每一次送达都只是向该循环追加。开启会永久冻结:代币的持仓记录器、时间窗口关闭时有效的排除名单(无论循环何时开启),以及分母,即时间窗口内的已记录供应量减去销毁地址和名单上各地址的持仓。一个循环的每位持有者都依据同样的数值计量,无论之后发生什么变化。 - 每个时间窗口一个循环。同一时间窗口内之后的发送,都追加到同一个循环中。
- Keeper 决定时机。它触发发送;它从不指定时间窗口、持有者或数额。因此,在下一个关闭时刻之后到达的发送,按次日的时间窗口计量。这一点已被接受并记录在案。
股票如何到达那里
两条路径,除此之外没有任何东西能计入一个循环。
- 从 Robinhood Chain。Keeper 调用该市场的镜像金库
sendToAirdrop(stocks),并支付 LayerZero 费用;多付的部分会退还给它。自 2026-10-06 起,这一调用还会指定每次送达在以太坊上获得的 gas,即sendToAirdrop(stocks, receiveGas, composeGas),远端枢纽会把它保持在 StockFun 的所有者所设定的下限和上限之间(参见Robinhood 通道和Keeper)。对于列出的每只股票,金库通过远端枢纽为该股票指定的适配器,把自己的全部余额发送到远端枢纽所指定的空投合约,并以该市场的 id 作为载荷。LayerZero 只携带六位小数:一只 18 位小数的股票不足 10^12 个单位的部分,即一枚代币的百万分之一,会留在金库中,等待之后的发送。在以太坊上,该股票的 OFT 把封装股票铸造给空投合约,随后 LayerZero 的端点调用空投合约。只有当这次送达来自合约自己的端点、来自 StockFun 所有者登记过的股票 OFT、来自 Robinhood Chain、由载荷所指市场的镜像金库发出,并且该市场存在时,合约才会将其计入。 - 从以太坊。在一个于以太坊上买入股票的金库上,即本地通道上,Keeper 在该市场的
TreasuryVault上调用sendToAirdrop(stocks)。金库授权确切的数额,空投合约将其拉取,并按它实际收到的数量计入,随后授权被重新关闭。只有该市场自己的金库可以为它发送。接入了跨链桥枢纽的金库会拒绝这条路径:它的股票在 Robinhood Chain 上。
在这两条路径中,Keeper 决定时机,从不决定数额、对象或去向:数额是金库的余额,目的地是协议所指定的合约,而一只被列出两次或不在篮子中的股票会让调用失败。
自 2026-10-05 起,列出的每只股票都单独进行。被其发行方冻结的股票、余额无法读取的股票,或者(从 Robinhood Chain 发送时)没有适配器、或其费用未被 Keeper 的付款覆盖的股票,会留在金库中,并发出一个事件(AirdropSendFailed),其他股票照常发送;它会随之后的一次发送一起发出。当没有任何股票发出时,调用会失败,并说明原因。
份额与领取
- 由持有者领取。每位持有者在以太坊上自行领取自己的份额,并支付 gas:领取一个循环用
claim,领取多个用claimMany。没有人能替别人领取,Keeper 也不发送任何东西。自 2026-10-05 起,dapp 的领取页面会列出该钱包可以领取的每一个时间窗口,并发送领取,每笔交易五个循环(2026-10-06 之前为十个):参见dapp。 数额。对于一个循环中的每只股票:
应得 = 向下取整(数额 × 时间窗口内的持仓 ÷ 合格持仓) − 已支付给该持有者的数额绝不超过该循环在这只股票上的剩余数量。领取之后到达的发送会提高数额,持有者再领取差额。舍入留下的部分留在合约中。
- 没有期限,没有上限,没有最低额。份额可以随时领取,没有截止日期。没有单个钱包的上限,也没有最低数额。
- 被排除的地址领取不到任何东西。
- 绝不由另一个循环支付。自 2026-10-05 起,空投合约逐只股票记录它所欠的数额以及支撑这一数额的资产,并且只有在支撑资产足以覆盖这一数额时才支付该股票。支撑资产由已计入各循环的股票算出,从不取自合约的余额,而余额中还包含尚未计入的送达:正在前往另一个市场途中的股票绝不会支付领取。在一次拿走了某只股票一部分的紧急转移之后,在每一个持有该股票的市场中,对该股票的领取都会等待,直到该股票通过任何人都可以调用的
restore被送回(一笔普通转账不算数),或者 StockFun 的所有者把这笔损失从蒙受它的那个循环中核销。只要还没有人从该循环中领取过这只股票,其中任意一部分都可以被核销,每位持有者损失相同的比例;一旦已有持有者获得支付,就只能核销全部剩余部分,这部分损失由尚未获得支付的持有者承担。在这样一次核销之后到达该循环的一切,都会在其所有持有者之间按比例分配,就好像被核销的数额从未存在过一样。参见紧急模式。 - 一次领取支付它能支付的部分。自 2026-10-05 起,
claim和claimMany会支付它们能支付的每一只股票。账目短缺的股票(如上所述),或者转账被拒绝的股票(例如因为其发行方冻结了它),会被延后(ClaimDeferred):它仍然待付,之后的一次领取会支付它。claimMany会跳过排除名单上列有调用者的循环;claim则会拒绝它(Excluded)。一次什么也没支付的领取会失败,并说明原因:账目短缺某只股票(Underfunded)、转账被拒绝(TransferRefused),或者没有可领取的东西(NothingToClaim)。在此之前,一只这样的股票就会让整个领取失败,一个被排除的循环就会让整个claimMany失败。 - 成本。领取一个包含两到三只股票的循环,按测试中的测量约消耗 120,000 至 210,000 gas,测试是在热存储下运行的。2026-10-05 在冷存储下测得:每个循环五只股票时,第一个循环作为一整笔交易约消耗 508,000 至 528,000 gas,同一次
claimMany中之后的每个循环约消耗 321,000 至 332,000:十个循环(即当时领取页面每一批的规模)约消耗 340 万至 350 万 gas,而当每个循环的股票也都处于冷状态时,最多约 530 万。这些是以太坊 Glamsterdam 升级之前的 gas 价格。在这次升级下(自 2026-10-06 起已在 Sepolia 上启用),一个新的存储槽的成本约为原来的五倍,而一次领取所支付的每只股票可能写入三个新的存储槽:在 Sepolia 上,领取一个包含三只股票的循环,该循环的第一位领取者花费了 1,177,679 gas,之后的领取者花费 878,713 至 888,051 gas。十个各含五只股票的循环约需 800 万至 1,400 万 gas,仍在 EIP-7825 为每笔交易设定的 16,777,216 gas 之内(在 Glamsterdam 下,这一上限针对的是其执行 gas),而领取页面每一批为五个循环。
claimable 显示一个地址可以从一个循环中领取多少,逐只股票列出。
排除名单
每个代币都有自己的名单,由 StockFun 的所有者设定:默认最多 16 个地址(setMaxExcluded),不得重复,不得为零地址。销毁地址 0x…dEaD 始终被排除,并且不列入名单。每次修改都会生成名单的一个新版本,并标注日期:一个时间窗口依据其关闭时有效的名单计量,无论它的循环何时开启;一次修改只适用于此后关闭的时间窗口。
默认情况下,一个市场的代币只有销毁地址被排除。Uniswap 的 PoolManager 从不被记录,因此无需列入。StockFun 池子唯一的流动性提供者是流动性锁定合约,它在发射之外不持有任何东西。另一家交易所上持有该代币的池子会是一个普通的已记录持有者,所有者可以将其列入名单。
在 $STOCKFUN 上,名单中还包括发射操作者,它在铸造与锁定之间的几个区块内持有全部供应量。自 2026-10-05 起,发射脚本在代币存在之前,就在代币将要使用的地址上列入这个地址,然后才铸造,因此在铸造与列入名单之间不可能有时间窗口关闭:发射操作者什么也收不到。如果所有者在发射之后的第一个时间窗口关闭之前更改这份名单,新的名单必须保留这个地址。
搁置的股票
为一个没有合格持仓的时间窗口所做的发送,会为该市场搁置:例如在某个市场发射当天发送的股票,对应的是一个在该市场存在之前就已结束的时间窗口。
搁置的股票归入最近一个被查出没有合格持仓的时间窗口之后、第一个拥有合格持仓的时间窗口,无论由谁查看、何时查看。针对紧接其后的那个时间窗口的 openCycle 或一次发送会把它们一并带上。否则,任何人都可以调用的 assignUnassigned 会按顺序检查已结束的时间窗口,每次调用默认最多 30 个(setMaxWindowsPerAssign),并开启第一个拥有合格持仓的时间窗口,即使更晚的循环已经开启。因此,循环可能不按顺序开启。
这一点成立的前提是,在此期间循环时间表没有改变,代币的持仓记录器也没有被替换。新的时间表会重新划分尚未开启的时间窗口,包括搁置的股票仍需检查的那些;在此期间换上的记录器不会计量任何在它之前开始的时间窗口,这些股票会等待它完整覆盖的第一个时间窗口(参见下文的运营规则)。
一次本身没有找到合格持仓的发送,如果更早的时间窗口仍未检查,就会失败:先运行 assignUnassigned,再重新发送。来自 Robinhood Chain 的送达会存储在以太坊上,可以再次执行:自 2026-10-06 起,一旦其模拟能够通过,Keeper 会自己再次执行已存储的送达;当它无法执行时,会发出附带手动执行命令的警报(参见Keeper)。自 2026-10-05 起,一次发送如果针对的时间窗口结束得不晚于最近一个已检查的时间窗口(改用更长的时间窗口就可能造成这种情况),就会转而加入搁置的股票:一个搁置着股票的市场会继续接收它的发送。
原则
- 是资产空投,绝不是份额回购。没有人把代币交还给金库。重要的是持有代币。
- 它奖励的是持有,而不是交易。
- 不承诺任何数额。空投取决于过去的交易量,而不是某个比率。它可能为零,也没有任何东西承诺明天还会有交易量。
- 没有赎回。持有者获得其在每次空投中的份额,除此之外什么也没有:对金库依然不存在任何提取权。
- Keeper 负责触发,从不做选择。分配由一个合约根据持仓记录器所保存的持仓计算得出。Keeper 选择何时发送,从不选择数额、对象、去向或受益人,也无法把份额分配给自己,或分配给此计算之外的任何人。
- 绝不超过一个循环的持有量。每个循环逐只股票支付的数量至多为其持有量,任何持有者获得的数量也不超过其按比例计算并向下取整的份额。
- 一处失败只停止它自身。自 2026-10-05 起,无法发送或无法支付的股票,或者无法跨链的市场,会单独等待,其他部分照常进行。参见架构。
紧急模式适用于空投合约,与适用于任何持有协议资产的合约一样:所有者的转移立即生效,它转移股票,而份额保持不变。自 2026-10-05 起,其他循环绝不为此付出代价:对被转移拿走的那只股票的领取会延后这只股票,并支付其他股票,直到该股票通过 restore 被送回,或者所有者把这笔损失从蒙受它的那个循环中核销(参见上文和紧急模式)。所有者的流程绝不让账目出现短缺:先减记该循环(writeDownCycle,对于搁置的股票则用 writeDownUnassigned),然后再转移该股票。空投合约的暂停会停止发送、循环的开启以及搁置股票的归入;它不转移任何东西,也从不阻止领取。空投合约和持仓记录器都可以由 StockFun 的所有者升级,并立即生效,与除代币和流动性锁定合约之外的每一个模块一样。
由此得出一条运营规则:代币的持仓记录器就地升级,这样会保留它的全部历史;它不会在一个正在使用的代币上被替换。自 2026-10-05 起,替换不再会破坏交易:新的记录器从该代币当时在 Uniswap PoolManager 之外的供应量起步,一个此前记录过该代币的记录器会拒绝该代币,而且自当天的第二个审计循环起,代币会拒绝一个所绑定的 PoolManager 并非其池子所在者的记录器,这样的记录器会把池子算作一位持有者。自第三个审计循环起,新的记录器在切换时开始一份新的记录:空投合约不会计量任何在切换之前开始的时间窗口,这些时间窗口的股票会被搁置,等待新记录器完整覆盖的第一个时间窗口;代币还会在切换时报告销毁地址的余额,因此已销毁的代币仍被排除在外。但新的记录器并不知道持有者的余额:一个它没有见到变动过的持有者,在其下一次变动之前都会被读作什么也没有持有,因此一个跨越这段时间的时间窗口付给他们的会更少,也不会多付给任何人。已经开启的循环保留它们所冻结的记录器。必须替换的记录器,要在一个时间窗口刚结束时、在已关闭时间窗口的循环都已开启之后进行切换。在 2026-10-05 之前,新的记录器从零供应量起步:每一笔卖出都会失败,此后开启的循环的份额也被永久破坏。
由于报告失败会让转账失败,StockFun 的所有者保留两个立即生效的补救手段,各只需一笔交易:就地升级记录器,或者在代币上调用 setRecorder(0),停止它的记录。在一个代币没有记录器期间,空投合约不会为它开启任何循环,为它发送的股票会被搁置,直到指定了记录器为止。
曾经待定的事项,以及如何确定
项目的登记册 doc/DECISIONS.md 曾将三个待定事项列为 TBD 5、7 和 8。三者均已于 2026-10-04 确定:
- Keeper 推送(TBD 5)。不推送:只有持有者自行领取,为自己领取,费用自理。
- 限额(TBD 7)。没有单个钱包的上限,没有最低数额,份额永不过期。
- 排除项(TBD 8)。每个代币一份名单,由 StockFun 的所有者设定,默认最多 16 个地址,销毁地址始终被排除;默认情况下只有销毁地址。参见上文。
尚待完成的事项
- 股票适配器。把每只股票带到以太坊的 LayerZero 适配器,每只股票一个:Robinhood Chain 上的锁仓适配器及其在以太坊上的 OFT。它们不在代码库中;测试使用 mock
- 部署。尚未部署任何东西
Keeper 的空投步骤和 dapp 的领取页面此前列在这里,已于 2026-10-05 编写完成:参见Keeper和dapp。
那么 Treasury Ratio 呢?
Treasury Ratio——国库价值除以流通市值——曾是产品的标志性指标。它已不再有任何意义:每次分发都会清空国库。自 2026-09-27 起,它已废弃。
取代它的指标仍待确定。当前的提议是:分发给一个市场持有者的股票的累计价值,以美元计。在两次分发之间,dapp 会继续显示国库所持有的资产,等待下一次空投。
那么创建者回购呢?
已移除。从 2026-08-27 到 2026-09-27,市场的创建者可以让国库卖出股票,用于回购并销毁其代币。如今创建者对国库没有任何权力:他们只能像任何持有者一样获得股票,前提是他们持有该代币。
跨链桥的回程路径也随之取消,即从 Robinhood Chain 回到以太坊的路径,它只服务于创建者回购。跨链桥如今只单向运行。为了空投,股票以封装形式经由股票适配器反向跨链:这是另一条路径,只传输股票。
$STOCKFUN 的回购并销毁不受影响:每笔交易中用于买入 $STOCKFUN 并将其发送至销毁地址的 0.5 % 不涉及任何国库,它将继续保留。参见 $STOCKFUN。
措辞
为 dapp 提议的措辞,待审定:
国库买入的股票在每次分发时按比例空投给代币持有者。这既不是收益,也不是保证。
禁用词汇完全适用于空投。项目从不写 passive income、earn stocks、returns 或 your stocks are safe in the vault,也从不把未来的空投数额表述为确定无疑。
由 Robinhood 发行的代币化股票,不向 US persons 提供。