A tokenized stock pays you two different things: the share itself, and the cash it throws
off. They trade as a single number. Prism separates them. Deposit one stock token and
receive pNVDA, the share, and dNVDA, every distribution it
will ever make. Sell either leg. Keep the other.
A tokenized stock bundles two different assets into one price. That is fine until you want
only one of them, and there is no way to ask for it. Prism exists because these four trades
are impossible today and obvious tomorrow.
Income buyer
Wants the cash, not the volatility
Buy dNVDA alone and collect every distribution the share pays, without holding a position that can halve on an earnings miss. A bond-like claim on an equity's cash flow, priced by a market rather than by a bank.
Buys the dividend leg
Growth buyer
Wants the upside, unpaid for
Buy pNVDA alone and stop paying for a yield you do not want. Strip the coupon off and the share should get cheaper by exactly the value of what you gave up.
Buys the principal leg
Liquidity provider
Stops being the exit liquidity
Every time the multiplier steps, an LP in a plain stock pool pays the gap to whoever crosses first, because balances never moved and the pool never noticed. A Prism pool charges that gap as a fee, so the event that used to cost you pays you.
Earns the surge fee
Existing holder
Sells one half, keeps the other
Hold the share, want cash now, do not want to sell the position? Split it and sell the dividend strip. You keep full share exposure and forfeit only future distributions. No loan, no liquidation price, no counterparty.
Monetises future yield
None of this needs a new asset class. It needs the existing one to stop being sold as a
single indivisible number.
How it works
One deposit, one settlement, one redemption.
A full lifecycle with real arithmetic: a share at $100 paying a $1.00 quarterly
distribution, one share deposited.
1
Deposit the share
You send 1 NVDAt to the vault and it stays there. The vault does not lend it, rehypothecate it, or route it to a strategy. You receive 1 pNVDA and 1 dNVDA in the same transaction.
deposit(1e18) → 1 pNVDA + 1 dNVDA
2
Trade the legs apart
Both tokens are ordinary ERC-20s with their own pools. The market prices them independently: the principal leg tracks the share minus its future income, the dividend leg tracks that income. Their sum should track the share, and where it does not, that gap is the arbitrage.
pNVDA ≈ $96.20 · dNVDA ≈ $3.80 · Σ ≈ NVDAt
3
The distribution arrives
No cash moves and your balance does not change. The token's uiMultiplier() rises by 1%, the real share price falls by 1%, and the total-return feed does not move at all. That multiplier step is the distribution, so the vault reads it from the token instead of waiting for money that never arrives.
uiMultiplier 1.000000 → 1.010000 · feed continuous → INCOME
4
The step routes to one leg only
The 1% accrues to dNVDA holders. pNVDA receives nothing, which is correct: the real share it tracks is worth 1% less than it was. Entitlement follows the token, so it survives a transfer — sell your dNVDA and the buyer inherits the unclaimed accrual.
incomeIndex ×1.01 · price leg unchanged
5
Swaps during the gap pay the LPs
Between the multiplier moving and settlement landing, the pool's books and the token disagree. A hook replaces the 0.30% static fee with a surge fee scaled to the unexplained gap, so the arbitrageur who came to extract that gap funds it instead. Adding liquidity is blocked outright until anyone calls poke().
Burn 1 pNVDA and 1 dNVDA together and the original share comes back. No maturity, no rollover, no expiry. The two halves are always worth exactly one share, which is what makes the arbitrage between them enforceable rather than hopeful.
redeem(1e18) → 1 NVDAt
What the vault cannot do. There is no admin key over principal. A steward role can only release quarantined value — accrual the contract has explicitly refused to credit to either leg. It cannot touch deposits, mint, or reverse an accrual already made. A paused oracle freezes settlement rather than guessing at it.
What the bytecode shows
Both legs already exist inside the token.
Every stock token on this chain is a beacon proxy over one implementation exposing
uiMultiplier(), effectiveAt() and
oraclePaused(), and emitting exactly one corporate-action event.
Three properties fall out of reading it.
// UIMultiplierUpdated(old, new, effectiveAt)
old 1.000000000000000000
new 1.002208724969205741
effectiveAt 1788534626
01 · Total return
A distribution is never cash
It is multiplier growth. No stablecoin arrives, no balance moves, and any vault waiting for a transfer waits forever.
02 · Fixed balances
Splits do not move balances either
balanceOf is fixed for life. Every corporate action is one global number moving.
03 · The identity
feed = real price × multiplier
The feed is total return too. On a distribution the multiplier rises by exactly what the real price drops, and the feed does not move.
That last line is the whole opportunity. The price leg and the income leg are already
separated inside every one of these tokens. They are multiplied together into a single
quote, and nobody trades them apart. Prism does not have to invent the decomposition, only
expose one that already exists. effectiveAt() is the bonus:
corporate actions are announced before they land, so a vault knows what is coming and when.
The problem
A pool prices from a number the action never touches.
An AMM quotes from balanceOf(). A corporate action here does not
move balances, it moves a global multiplier. So the pool quotes yesterday for the block
after the action lands, and whoever crosses first takes the difference out of LP inventory.
Every distribution. Forever.
Prism settles the multiplier before the pool has to answer for it.
01 · Escrow
The vault holds the real share
Deposit the canonical stock token, mint pTOKEN + dTOKEN one-for-one. Burn both together, take the share back. No maturity, no rollover, no synthetic anything.
02 · Classify
One number, read straight from the token
Settlement compares the token's multiplier against the last settled one and checks the feed stayed continuous across the step. A step it cannot explain is never credited.
03 · Route
Value goes where it belongs
Ordinary multiplier growth → income holders, pro rata, surviving every transfer. A step too large to be income → quarantine, pending steward review. Anything else → quarantine, credited to nobody.
ObservedMultiplierFeedVerdict
Distribution+smallcontinuous→ dTOKEN
Market moveflatmoves→ nobody
Large step (split?)+largecontinuous→ steward
Feed desync+anyjumps→ quarantine
Multiplier falls−anyany→ quarantine
The hook
LPs get paid for the gap instead of paying it.
The hook reads the vault's reconciliation state on every swap. While the pool and the token
disagree, the static fee is replaced with a surge fee scaled to the unexplained gap, so the
value an arbitrageur came to extract is charged to them and paid to the LPs. Liquidity
cannot be added to an unreconciled pool at all, and anyone can clear the state with one
permissionless poke().
The multiplier model, running live in your browser with integer WAD arithmetic — the same
code path the test suite asserts against. Move the inputs and watch the verdict change.
Note what a 4-for-1 does: it looks exactly like a distribution, so it stops at a human.
classifier · live
verdict
Dividend
pTOKEN·
dTOKEN·
quarantine·
hook fee 0.30% · pool settled
Network
Connect and read the chain.
The panel reads live chain state over JSON-RPC without a wallet. Point the vault field at
any deployed vault and it will read that vault's real settlement state, including whether
escrow matches accounting.
This is the full operator flow. Prism ships with no vault address configured, so the write
actions below are inert until someone deploys the contracts and fills in
config.js. Each step says exactly what it needs.
1
Get the chain and the share works now
Add the network with the button in Network, then hold any amount of the underlying stock token. The vault takes the token as it is — no wrapping, no minimum, no allowlist.
chainId 4663 · rpc.mainnet.chain.robinhood.com
2
Approve the vault needs a vault
A one-time ERC-20 approval on the stock token, spender set to the vault. Approve only what you plan to deposit if you would rather not leave a standing allowance.
NVDAt.approve(vault, amount)
3
Deposit and receive both legs needs a vault
One call mints both halves to you in the same transaction, one for one, with no fee and no slippage. The share stays escrowed and is never lent out.
This is the entire point, and it is the step that depends on somebody seeding liquidity. Both legs are ordinary ERC-20s, but minting them does not conjure a counterparty. Until a pool exists, splitting is a round trip you can make and a trade you cannot.
pNVDA + dNVDA = NVDAt · the gap is the trade
5
Claim, once a distribution lands needs a vault
Anyone can call poke() to make the vault read the multiplier and route the step. Income holders then withdraw their accrual as the real underlying. Entitlement rides the token, so a buyer inherits whatever is unclaimed.
vault.poke() · then vault.claim()
6
Redeem when you hold both needs a vault
Burn equal amounts of each leg and the share comes back. No maturity, no expiry, no rollover. Redemption is exact at the wei: the amount burned is the amount returned, with no dust.
vault.redeem(amount) → amount NVDAt
vault panel
walletnot connected
NVDAt·
pNVDAt·
dNVDAt·
claimable·
connect to read your balances
No vault is configured, so the write actions are disabled. Set one in config.js to enable them.
What this does not do
The uncomfortable half.
A distribution and a split look identical on-chain. Both are the multiplier rising while the feed stays continuous. Separating them needs a magnitude threshold plus human review, not arithmetic alone, and freezing on an ambiguous 4-for-1 beats handing 4× to the wrong leg.
The oracle is a dependency. Classification is only as honest as the feed and oraclePaused(). A paused or stale feed freezes the vault rather than guessing. That is a deliberate denial of service in exchange for never mispaying.
Quarantine needs a human. Anything the contract refuses to credit sits untouched until a steward releases it. The steward can release quarantined value and nothing else: never principal, never an accrual already made.
A graduated pool cannot host the hook. A V4 pool has exactly one hook slot, and a pool that has already spent it cannot take another. A strip pool has to be its own.
Reg S applies to the underlying. Robinhood Stock Tokens may not be offered to US persons, and anything built on top inherits that restriction.
The contracts exist, but nothing is deployed. The vault, the two legs and the fee hook are written and covered by a suite that compiles them with solc and executes them on an EVM. None of it is deployed to any chain, so this site escrows nothing, custodies nothing and lists no vault address. Anyone deploying it is responsible for what they deploy.
Unaudited. The classifier, the contracts and the site all have suites, and none of that is a security audit. A clean run says the code does what was intended; it says nothing about whether what was intended is safe. The contracts have never held real value.
This is a derivative work. Prism is an independent rebuild of Cleave, used under its MIT licence. It is not affiliated with, endorsed by, or operated by that project, and it does not share its deployment.
Reproduce it yourself
Proof it works
The classifier test suite in this repository, run against the exact module the page loads.
Every verdict class, both boundary conditions and a randomised sweep are asserted here.
Clone the repo and run npm test to regenerate this output.
·passing
·failing
·suites
·random cases
loading…
Runs in Node with no dependencies. The page and the tests import the same classifier.
Licensed permissively
MIT License
Prism derives from Cleave under this licence; both copyright notices are retained.