A tokenized stock pays you two different things: the share, and the cash it throws off.
They trade as one number. Cleave separates them. Deposit one Stock Token and receive
pNVDA (the share) and dNVDA (every dividend it will ever pay).
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. Cleave exists because these four
trades are impossible today and obvious tomorrow.
Income buyer
Wants the cash, not the volatility
Buy dNVDA alone. You collect every dividend the share ever pays without holding a position that can halve on an earnings miss. A bond-like claim on an equity's cash flow, priced by the 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 don't want. Dividend-paying names cost more than their growth is worth to you; strip the coupon off and the share gets cheaper by exactly that amount.
Buys the principal leg
Liquidity provider
Stops being the exit liquidity
Every ex-dividend date, an LP in a plain stock pool pays the gap to whoever arbitrages it first. In a Cleave pool the hook charges that gap as a fee instead, so the event that used to cost you now pays you.
Earns the surge fee
Existing holder
Sells one half, keeps the other
Hold the share, want cash now, don't 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. NVDA at $100 with a $1.00 quarterly dividend, one
share deposited.
1
Deposit the share
You send 1 NVDAt to the vault. It stays there. The vault never lends it, never rehypothecates it, never routes 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
The two tokens are ordinary ERC-20s with their own V4 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 when it doesn't, that gap is the arbitrage.
pNVDA ≈ $96.20 · dNVDA ≈ $3.80 · Σ ≈ NVDAt
3
The ex-dividend date arrives
The vault's cash balance rises by $1.00 and the feed price drops from $100 to $99. Two independent observations agree, so the event is classified as a dividend. Agreement is the only thing that qualifies it. A price drop with no cash is a market move and pays nobody. Cash with no price drop is quarantined and credited to nobody.
The $1.00 is credited pro rata to dNVDA holders and is claimable immediately. pNVDA receives nothing, which is correct: the share it represents is now worth $1 less. Entitlement follows the token, so it survives a transfer: sell your dNVDA and the buyer inherits the unclaimed cash.
dividendPerToken += 1e18 · splitIndex unchanged
5
Swaps during the gap pay the LPs
Between the corporate action and the settlement, the pool's books and the feed disagree. The 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 entirely until anyone calls poke().
Burn 1 pNVDA and 1 dNVDA together and the original share comes back. No maturity date, 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. The steward role can only route quarantined cash, meaning money the contract has explicitly refused to credit to either leg. It cannot touch deposits, the split index, or accrued dividends. A stale price feed freezes settlement instead of guessing at it.
The problem
An AMM cannot tell a dividend from a crash.
On the ex-dividend date a stock gaps down by roughly the dividend. Nothing is lost. The
value moved from the share into cash. A pool holding that share does not know this. It
quotes the old price for one block and arbitrageurs take the difference out of LP inventory.
Every quarter. Forever. The same pool cannot tell that gap apart from a 2-for-1 split, where
the price halves and nothing is owed to anyone.
Cleave settles the question before the pool has to answer it.
01 · Escrow
The vault holds the real share
Deposit a canonical Robinhood Stock Token, mint pTOKEN + dTOKEN one-for-one. Burn both together, take the share back. No maturity, no rollover, no synthetic anything.
02 · Classify
Every change is corroborated twice
A settlement reads three things at once: the vault's share balance, its cash balance, and the price feed. A distribution is credited only if the price gap actually matches the cash per share.
03 · Route
Value goes where it belongs
Cash → dividend holders, pro rata, surviving every transfer. Split shares → principal holders via a rising splitIndex. Anything unexplained → quarantine, credited to nobody.
ObservedSharesCashPriceVerdict
Cash dividendflat+gap ≈ cash/share→ dTOKEN
Stock split×n0÷n (value held)→ pTOKEN
Market moveflat0any→ nobody
Cash, no gapflat+unchanged→ quarantine
Free shares×n0unchanged→ quarantine
The hook
LPs get paid for the gap instead of paying it.
The Uniswap V4 hook reads the vault's reconciliation state on every swap. While the books and
the feed 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 into an unreconciled pool at all. Anyone can clear the state with one
permissionless poke().
This is the exact arithmetic of CorporateActionLib.classify(), ported line for line to the browser. Move the inputs and watch the verdict change.
classifier · live
verdict
Dividend
pTOKEN·
dTOKEN·
quarantine·
hook fee 0.30% · pool settled
Network
Connect and read the chain.
MetaMask, Robinhood Chain 4663. The panel reads live chain state over JSON-RPC; when a vault address is configured it reads the vault's real settlement state too.
The oracle is a dependency. Classification is only as honest as the price feed. A stale feed freezes the vault rather than guessing. That is a deliberate denial-of-service in exchange for never mispaying.
Quarantine needs a human. Cash that arrives without a corroborating gap sits untouched until a steward routes it. The steward can move quarantined cash and nothing else: never principal, never the split index.
Pons V2 cannot host the hook. A V4 pool has exactly one hook slot and a Pons-graduated pool has already spent it. Cleave runs its own pool; Pons stays useful for distributing the dividend leg, not for the strip itself.
Reg S applies. Robinhood Stock Tokens may not be offered to US persons. Anything built on top inherits that, including this.
Not deployed to mainnet yet. Contracts compile and pass 27 tests locally against mocks. Nothing here has been audited, and no vault address is live.
Reproduce it yourself
Proof it works
The full test suite, run against the contracts in this repository. Every corporate-action
class, the routing rules, the quarantine path and the hook's fee behaviour are asserted
here, including a fuzzed solvency invariant over 256 random deposit/dividend pairs.
·passing
·failing
·suites
512fuzz runs
loading…
Clone the repo, run forge test, get this output. Mocked feeds and tokens, not a mainnet deployment.
Licensed permissively
MIT License
The contracts, the classifier and this page are all covered.