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
allVaultsand emitsLaunched, so one can read them.