Docs
How the productworks.
Stock Tokens, baskets, forks, vaults, fees, live contracts, and the pricing formulas. $PRSM
Overview
$PRSM is a market and product layer for Robinhood Stock Tokens on Robinhood Chain (chain ID 4663).
You can look at live tokenized stocks, buy and sell them, and compose them into products — baskets, forks, and strategy vaults — without treating those tokens as brokerage shares.
Onchain products on top of Robinhood Stock Tokens. Exposure to stocks and ETFs as ERC-20s, plus tools to basket, split, and manage that exposure.
Stock Tokens
A Stock Token is tokenized economic exposure to an underlying stock or ETF. It is an 18-decimal ERC-20 on Robinhood Chain. It is not legal or beneficial ownership of the underlying security.
| It is | It is not |
|---|---|
| An 18-decimal ERC-20 on Robinhood Chain | A brokerage share |
| Priced from Robinhood / Chainlink stock-token feeds | A claim on voting rights or cash dividends |
| Something you can hold, transfer, basket, or split | Something this app mints or burns with Robinhood for you |
Only Robinhood authorized participants mint and burn with Robinhood Assets Jersey. $PRSM composes with tokens that already exist. Nothing here is investment, legal, tax, or financial advice.
The desk
The terminal is three panes:
- Left rail — searchable Stock Tokens and baskets.
- Center — chart, holders, and transfers for the selected name.
- Right rail — order ticket and a live Activity feed. On Portfolio, Activity fills the rail.
Create opens a drawer: Basket or Fork. Deploy confirms in a modal. Image uploads go to Pinata only when you confirm deploy.
Connect a wallet on Robinhood Chain. The API prepares unsigned transactions. Your wallet signs them. The server does not hold keys.
Trading a Stock Token
The ticket lists Stock Tokens. The app shows last sale / RHJ ask, Nasdaq session %, chart, holders, and onchain transfers.
Buy and sell are live Uniswap swaps against USDG. Preview lists every v3 and v4 USDG pool that quotes for your size. You pick one (best fill is marked). v4 goes through Permit2 and the Universal Router; v3 uses SwapRouter02. No pool means no send — the app will not invent a fill.
A desk buy is a wallet swap. It is not a vault mint, and it is not ownership of the stock.
Baskets
A basket is a vault that holds a weighted mix of Stock Tokens. Create deploys an empty vault. You deposit after.
The live cash path is USDG. Enter an amount. The vault splits it by target weights and buys each name on that token’s USDG Uniswap pool (same venues as the trade ticket). There is no INDEX/USDG pool. In-kind is if you already hold the names: approve each token and depositInKind.
- Basket names must be on AssetRegistry (AAPL, NVDA, MSFT, TSLA, GOOGL, META, AMZN, AMD today). NFLX and AVGO cannot go in a vault until Chainlink publishes those feeds.
- At least 2 and at most 25 Stock Tokens.
- Weights must sum to 10,000 bps (100%).
- Default management fee is 50 bps per year (0.50%).
- No protocol deposit fee. Uniswap pool fee and slippage apply on the USDG path.
- Live vaults accrue the fee by minting basket shares to the fee recipient.
Redeem burns basket tokens. USDG out sells the pro-rata mix on Uniswap and pays you cash. In-kind returns the Stock Tokens instead. No approve — the vault is the basket ERC-20. Basket tokens are exposure to the mix, not ownership of Apple or anything else in it.
Pricing calculations
Stock Token price
Price of one Stock Token, not one brokerage share.
| Source | Formula |
|---|---|
| Offchain / desk | RHJ ask (fallback bid) × currentMultiplier |
| Onchain / live vault | Chainlink stock-token feed |
Do not apply uiMultiplier() to Chainlink. That feed is already multiplier-adjusted. GET /rhj/prices/{symbol} is raw underlying bid/ask, so offchain quotes multiply by currentMultiplier. Use ask, not mid.
Basket price (NAV per token)
The basket token price is vault NAV divided by supply. It is not a weighted average of stock prices.
NAV = Σ (Bᵢ × Pᵢ) P_idx = $1 if S = 0 or NAV ≤ 0 P_idx = NAV / S otherwise
| Symbol | Meaning |
|---|---|
| Bᵢ | Vault balance of Stock Token i (18-decimal ERC-20) |
| Pᵢ | USD price of one token i |
| S | Basket token totalSupply |
| P_idx | USD price of one basket token (navPerTokenUsd) |
Empty vault / first mint: P_idx = $1. A first deposit of V USD mints V shares. Do not use Σ wᵢ Pᵢ. That is an index level and does not match a vault share that starts at $1.
| Source | Bᵢ | S |
|---|---|---|
| Vault | balanceOf on the IndexVault | ERC-20 totalSupply |
If the vault is empty, session change still needs a basket. Implied units for a $1 target-weight slice:
Bᵢ = wᵢ / Pᵢ wᵢ = targetWeightBps / 10,000 Σ wᵢ = 1
Session percentage change
Same meaning as a stock’s Nasdaq day change: return of P_idx versus session open. There is no stored prior-close NAV yet. Open is rebuilt from each constituent’s Nasdaq move rᵢ:
rᵢ = Δ%ᵢ / 100 P_open,i = Pᵢ / (1 + rᵢ) NAV_now = Σ Bᵢ Pᵢ NAV_open = Σ Bᵢ P_open,i Δ%_idx = (NAV_now − NAV_open) / NAV_open × 100
Supply cancels when S is unchanged, so this is also the return of P_idx. Skip a leg if Pᵢ, Bᵢ, or Nasdaq Δ%ᵢ is missing, or if rᵢ ≤ −1. If nothing remains, percentageChange is null.
Example: 1 AAPL token at $110 (+10%) and 2 MSFT tokens at $50 (−20%). Open prices are 100 and 125. NAV now 210, NAV open 225. Δ% = (210 − 225) / 225 × 100 = −6.67%.
Stocks in the app still use Nasdaq percentageChange directly. Baskets never invent a letter-seed change.
Forks
A fork locks one Stock Token and mints a price token plus a drip token. There is no USDG-in. Buy the name on Uniswap first, then fork.
- Split takes 10 bps and mints the net amount of each child.
- Merge both sides anytime to unlock the Stock Token. Merge is free.
- Maturity must be 7–1,825 days out.
- After maturity, settle freezes dT. Price redeems a × d0 / dT of the locked token. Drip redeems a × (dT − d0) / dT minus 5%.
- Drip is a claim on remaining
uiMultiplier()growth. It is not a cash dividend and does not expire.
Management fee on a series is 0–500 bps per year. Default in the create flow is 50 bps.
Vaults
A strategy vault holds Stock Tokens under a mandate (sector, yield, and similar). Depositors get vault-token exposure, not the stocks themselves. Price is the same NAV-per-share idea as a basket: holdings × token prices ÷ supply.
Fees
| Product | Fee | Who gets it |
|---|---|---|
| Basket | Management fee, default 50 bps / year. No protocol deposit fee. USDG deposits pay Uniswap pool fee and slippage. | Vaults mint fee shares to the fee recipient. |
| Fork | 10 bps on fork. Merge is free. 5% on drip redeem after settle. Optional management fee. | FeeManager: 20% protocol, 80% creator on collected protocol fees. |
| Stock Token trade | Uniswap pool fee plus slippage on the USDG pool you pick. | Not a $PRSM brokerage commission. |
50 bps means 0.50% per year. 10 bps means 0.10% of the split amount. Protocol fee bps of 2,000 means 20% of that collected fee, not 20% of AUM.
Portfolio
Portfolio shows onchain balances for the connected wallet: USDG cash, basket tokens, and Stock Tokens. Equity is cash plus marked positions. Stock Token value uses the same RHJ ask mid the desk uses. Basket value uses vault NAV × shares when the API provides it.
This book is exposure. It is not a brokerage statement of share ownership.
Activity
The right-rail Activity panel is a websocket of app events: live buys, sells, creates, splits, merges, deposits, and redeems. It is not the same as the selected token’s onchain transfer list in the center pane.
Oracles and multipliers
uiMultiplier() is a shares-per-token ratio scaled by 1e18. Use it only for share-equivalent display:
share-equivalent = raw balance × uiMultiplier / 1e18
Do not multiply Chainlink stock-token prices by the multiplier. Those feeds are already adjusted. During corporate actions, treat oraclePaused() as price temporarily unavailable. Staleness remains the primary guard.
How it is built
Terminal (Next.js)
→ API (NestJS)
→ Robinhood RHJ — assets, prices, corporate actions
→ Robinhood Chain — balances, vaults, transfers
→ Uniswap v3 / v4 — USDG ↔ Stock Token pools
→ Contracts — IndexVault, SplitVault, TradeExecutor, factories, oracles, feesThe asset list and prices come from Robinhood, not a hardcoded watchlist. The backend prepares unsigned transactions. Wallets sign. The server does not hold keys.
Contracts
Shared infra is live on Robinhood Chain (chain ID 4663). These six addresses are protocol-wide. They are not stored per index in the database.
Create Basket and Create Fork talk to the factories. After a product deploys, the new vault address is what the app saves on that product.
| Contract | Address | What it does |
|---|---|---|
AssetRegistry | 0x7BbaFa68c804Ef3FB16A72A7321A1DeeE494579E | Allowlists which Stock Tokens and USDG the protocol may hold, plus each token’s Chainlink feed. Live now: AAPL, NVDA, MSFT, TSLA, GOOGL, META, AMZN, AMD, and USDG. An index or split cannot deploy until the underlying is registered here. |
OracleAdapter | 0xDF155a334867705CdDB6Eb82a2ce9D552e3AdF99 | Reads those feeds for onchain NAV. Checks staleness, positivity, and oraclePaused(). Does not apply uiMultiplier() again. |
TradeExecutor | 0xA25d37894217Cce1D6fA0816E1442F0766b9A885 | Lets factory indexes call Uniswap. A USDG index deposit uses this to buy the basket. In-kind deposits and splits do not use it. |
FeeManager | 0x405e1481B86105B1f9ea3cb0327AA5dB8A494773 | Splits collected management-fee shares between the protocol (20%) and the creator (80%). |
IndexFactory | 0x26c911124B458feaC1E061ac8Bcc26738b05c799 | Create a basket from the app. Validates the mix and deploys one IndexVault. That vault is the basket token. |
SplitSeriesFactory | 0x629810B4781E2b25Fdd380d74261B1c80Fa15fdE | Create a fork from the app. Deploys a SplitVault plus price and drip tokens. |
Admin / deployer: 0x02BE958CFb5973118448B0c7CA2B63B583ff7AE2. USDG: 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168.
Per product
Factories create these when you deploy from the app. The API then writes the vault onto the product row.
| Contract | What it does |
|---|---|
| IndexVault | One per basket. It is the basket ERC-20. Holds the mix, mints on deposit, burns on redeem, reports NAV. |
| SplitVault | One per fork. Locks one Stock Token. Fork 10 bps, merge free. After maturity: settle, redeemPrice, redeemDrip. |
| SplitChildToken | Two per fork — price and drip. Vault-only ERC-20s the user holds. |
| MultiplierAccountant | One per underlying Stock Token, then reused. Classifies uiMultiplier() moves as dividend vs share split. |
What this is not
- Not a licensed broker-dealer or a way to buy the actual stock.
- Not legal or beneficial ownership of any underlying share.
- Not investment, legal, tax, or financial advice.
- Not a share-equivalent index level like SPX.
Official Robinhood context: Stock Tokens, building guide, oracles.