The TreasuryVault
One vault per market. It receives 2 % of every trade and turns it into tokenized stocks, airdropped to the token's holders. It is the protocol's heaviest contract, and the one with the fewest powers.
What it does not have
No withdraw. No transfer. No sweep. No owner. Those functions do not exist in the
current implementation, which anyone can verify: a call fails because there is nothing to
call. Since 2026-10-02 the vault itself is upgradeable: see below.
The conversion cycle
- Accumulation. ETH arrives with the trades. Once every 24 hours, the cycle starts if the vault holds at least 0.1 ETH when the keeper checks it, at its first pass after the airdrop window closes; below that, nothing fires that day, even if the ETH crosses the threshold later — gas and slippage would eat the operation. The keeper holds to this since 2026-10-06; until then it converted as soon as the vault held the threshold.
- ETH → USDC on Uniswap v4 Ethereum, bounded at 50 basis points against the ETH/USD feed. Deep pair, so the bound can be tight. The keeper names the amount, at least the threshold and at most the balance, and the bound is computed on that amount.
- USDC → USDG via Curve, then across Paxos's OFT on LayerZero.
- Buying the stocks on Robinhood Chain's secondary pools, by the mirror vault, bounded at 200 basis points against an independent Chainlink feed, each stock out of the cash reserved for it.
- Airdrop. In the same daily cycle, the keeper sends the stocks bought to the airdrop contract on Ethereum, where the token's holders claim them, pro rata. Since the seventh audit loop, on 2026-10-06, it sends them once they are worth what sending them costs; otherwise they wait in the vault for a later window.
The vault measures what it actually receives and refuses if the result falls short of the keeper's minimum, which is never looser than the bound (since 2026-10-05; until then the result was checked against the bound alone). It trusts neither the keeper, nor the rail, nor the quoted price.
Since 2026-10-05 each purchase leg runs on its own, on both vaults that buy stocks. A leg
that fails — a route that reverts, a frozen stock, a stale feed, an output below the
minimum, a refused quote, and since 2026-10-06 on Robinhood Chain a stock whose token
pauses its oracle for a corporate action — keeps its cash reserved for its stock and emits
LegFailed, and the other legs run. Only when no leg runs does the call fail, with the
first leg's reason, as a single leg would. Until then one failing leg made the whole
purchase fail. On Robinhood Chain, with the oracle's sequencer check set, a sequencer down
or just back up holds every leg back (see The Robinhood rail); that
check is off until Chainlink publishes an uptime feed for the chain.
The threshold and both bounds are the defaults of settings of StockFun's owner, since 2026-10-05, read live by every vault: the factory's for the Ethereum vaults, the remote hub's for the mirror vaults' purchases. A change applies to the next conversion of every vault.
Amounts and reservations
Since 2026-10-01, after the security audit of 2026-09-29:
- Each step spends an amount the keeper names. A vault larger than its venue can absorb within the bound converts in slices, over several cycles. Before, every step spent the whole balance, and a vault that outgrew its venue could never convert again.
- The ETH step's bound is computed on that amount, not on the live balance. The ETH that trades add while the transaction waits no longer invalidates the keeper's minimum.
- The cash is reserved stock by stock. As it arrives, it is set aside for each basket stock at the basket's weights. Each stock spends only its own reservation, and a stock the keeper skips keeps it for later. Before, a skipped stock's share was split again across the whole basket: by skipping, a keeper could move almost all of a treasury into one stock.
Both vaults that buy stocks work this way: the mirror vault on Robinhood Chain, in USDG, and the Ethereum vault on the local rail, in USDC.
In both, since the security pipeline of 2026-10-01, an emergency transfer that takes the cash below the reservations zeroes them all: what is left, and every later inflow, is split afresh at the basket's weights. An emergency that takes only unreserved cash, or another asset, keeps them. Before, the reset existed only in the vault's reading of its reservations: the old reservations came back with the next inflow, and the order of the keeper's calls decided the basket's mix.
The keeper's role
Triggering, nothing else. It picks the moment, names each step's amount, proposes swap routes, and supplies minimum amounts — which the vault rejects if they are looser than its own oracle bound, or if an amount exceeds what is reserved for that stock. The keeper can ask for more than the bound, never for less. Since 2026-10-05 the vault holds the keeper's minimum on what actually arrives.
The keeper spends each stock's reservation in full, except on the basket's last stock, where it holds back n−1 units, n being the number of stocks: see The keeper.
On the optional Ondo rail, the keeper hands the vault a signed quote from the issuer for
each leg. Such a quote is valid for whoever presents it, so since 2026-10-05 the Ondo router
serves only the factory's vaults, the protocol vault and each registered market's, and
refuses anyone else (NotAVault): nobody else can spend the keeper's quote and make that
conversion fail. And every router of the protocol refuses itself as the recipient of a
swap, so it holds nothing between transactions.
Whatever it names, the keeper cannot divert an asset, pick another basket, move one stock's cash to another, or loosen a bound.
The airdrop
The vault's stocks have one destination: the token's holders, at each airdrop, pro rata to their holdings. The split follows from balances under a rule nobody chooses — neither the creator nor the keeper. The mechanism is coded since 2026-10-04, not deployed: see The airdrop.
On the local rail, the vault hands its stocks over itself. sendToAirdrop(stocks), keeper
only, sends the whole balance of each listed basket stock to the airdrop contract the
factory names, read live. The vault approves the exact amounts, the contract pulls them and
credits them to the market's current cycle, and the approvals are closed again before the
call returns. A stock listed twice or outside the basket makes the call fail; a stock
without a balance is skipped. Since 2026-10-05 each stock goes on its own: one whose
balance cannot be read or whose transfer is refused, an issuer freeze for instance, stays in
the vault with an event (AirdropSendFailed), and the others go; when no stock goes, the
call fails and says why. A vault wired to the bridge hub refuses this call: its stocks are
bought and held on Robinhood Chain, where the mirror vault sends them the same way, through
each stock's LayerZero adapter.
The creator buyback, buybackAndBurn(...), which let a creator sell treasury stocks to buy
back and burn their token, was dropped on 2026-09-27 and removed from the code on
2026-09-28.
What a vault can hold
ETH, USDC, USDG, and its basket's stocks, plus, on the optional Ondo rail, the USDon an issuer mint can refund. A vault buys nothing else. That follows from the code; no test checks it as an invariant, and nothing stops a third party from sending an unrelated token to a vault's address. Emergency mode moves such a token out like any other asset.
A vault full of USDC is not broken: it is in transit. All three states are shown as the treasury awaiting the next airdrop; only stocks are distributed, once bought.
One proxy per market
Since 2026-10-02 each market's vault is its own proxy. It is created with the market, in front of the vault implementation the factory names at that moment, and initialized in the same transaction with its basket, its market, and the router, oracle and bridge hub the factory names then. StockFun's owner upgrades the vaults one by one, market by market, with immediate effect. A new implementation named in the factory reaches only the markets created afterwards.
The mirror vaults on Robinhood Chain follow the same rule: see The Robinhood rail.
Emergency mode
Since 2026-08-29, StockFun's owner can move any asset out of a vault, to any address; since 2026-10-05 the transfer is immediate, with no notice. Together with the airdrop, it is the only way the current implementation lets assets leave a vault, and it is covered in Emergency mode.