How the thing is built

Contract layout, the maths behind redemption, the fee model and what is still missing. Written for someone who intends to read the code.

Status

The factory is live on Robinhood Chain at 0xd495a9574534A48852CBF7358F420AD018EA3c67, deployed in block 57869957. It has no owner, no fee and no upgrade path, so what is described below is what is running.

Stock, basket and yield launches work today. Pool launches do not: a Uniswap v4 position is an NFT and this vault holds ERC-20 balances only, so that launch type needs a second vault and a second deployment.

Contracts

OnaFactory

0xd495a9574534A48852CBF7358F420AD018EA3c67. One call creates everything: launch(type, name, symbol, supply, assets, amounts) deploys the vault, deploys the token, mints the whole supply to the caller and pulls each asset from the caller into the vault. Approve the factory for every asset first. It holds no funds between transactions and has no upgrade path.

Vault

Holds the backing for exactly one token. Exposes holdings() for what it contains and redeem(uint256 amount) for burning tokens against it. It has no owner, no withdraw function, no pause and no setter for the token address it is bound to.

Token

A plain ERC-20. Fixed supply, no transfer hooks, no blocklist, no mint function after construction. The only unusual thing about it is that the vault can burn from a redeemer during redeem.

Redemption

Redemption is pro rata across everything the vault holds. For a vault holding assets A1..An and a token with supply S, burning x tokens pays out Ai * x / S of each asset, rounded down, in one transaction. Rounding dust stays in the vault, which makes every subsequent redemption very slightly better rather than worse.

Because payout is proportional to the current supply, a redemption never changes the backing per token for anybody who stayed. This is what allows redemption to be open permanently without a first mover advantage.

Yield

Yield is never distributed. It arrives in the vault and therefore raises backing per token for every holder at once. The four sources:

  • Pool launch: fees accrued by the v4 position, collected into the vault.
  • Stock launch: dividends and splits, which Robinhood Chain's stock tokens deliver as a rise in uiMultiplier() rather than as new units.
  • Basket launch: the same, per constituent.
  • Yield launch: the approved venue's share price.

Fees

There is a flat launch fee, paid once, in the creation transaction. Ona takes no cut of the backing and no cut of the yield, because a cut of the yield would have to be swept out of the vault, and a vault that can be swept is a vault with a withdraw function in it.

Chain

  • Robinhood Chain, chain ID 4663, gas paid in ETH.
  • RPC https://rpc.mainnet.chain.robinhood.com.
  • Explorer https://explorer.mainnet.chain.robinhood.com.
  • Quote asset for stock and yield launches: USDG.

What is missing

  • Pool launches. The vault holds ERC-20 balances, not v4 position NFTs.
  • An audit. The contracts pass eleven tests on a fork of live mainnet, which is not the same thing as having been reviewed.
  • The approved strategy list for yield launches is not enforced on chain yet; the factory currently accepts any ERC-20 as backing.
  • An indexer, so there is no page listing launches. The factory keeps them in allVaults and emits Launched, so one can read them.

Put something behind your coin