Version 1.0 · live on Robinhood Chain, not externally audited
Abstract
Corpus is a collateralised borrowing protocol on Robinhood Chain (chain ID 4663). A user deposits a Robinhood Stock Token, borrows USDG from a treasury the protocol itself holds, and yield generated by the deposited collateral is harvested, swapped to USDG and applied against the debt. The loan carries no interest, no origination fee, no early-repayment fee, no repayment schedule and no maturity. After the moment of borrowing, a position's debt can only decrease.
Because the protocol lends its own USDG rather than matching depositors with borrowers, there is no interest rate to discover and no lender whose withdrawal can force a borrower out. The only price in the system is the risk parameters, which are fixed per market and published in full.
At the time of writing, every market's yield source is a 1:1 custody vault. The realised yield is therefore zero and no debt is being repaid by the protocol. The mechanism below is live and tested; the input to it is currently zero. This paper says so wherever it matters rather than describing a steady state that does not exist yet.
1. Problem
Someone holding tokenised equity who wants liquidity has three ordinary options, and each has a cost.
Selling ends the exposure. The position that was held for a reason is gone, and reacquiring it later is a separate decision at a different price.
Borrowing at interest preserves the exposure but starts a clock. Interest accrues whether or not the collateral does anything, the debt grows in the background, and in a variable-rate pool the cost is set by someone else's demand. A position that was comfortable when opened can become uncomfortable without the borrower doing anything.
Borrowing with a maturity adds a second clock: a date on which the loan must be settled regardless of whether that date is convenient.
The observation behind Corpus is simple. A borrower who keeps their collateral also keeps whatever that collateral earns. If the protocol takes that earning stream and points it at the debt, the loan repays itself at whatever speed the collateral happens to produce, and the borrower is never obliged to add money. Removing interest removes the growing side of the debt; removing maturity removes the deadline. What remains is a loan that gets smaller or stays the same, never larger.
This is not a new idea, and Corpus does not claim it is. What Corpus tries to do is implement it narrowly and describe it honestly.
2. Mechanism
2.1 Components
- Core. Holds market configuration, positions, the USDG treasury, and every user-facing action.
- Oracle. A thin adapter over Chainlink aggregators, normalising each feed to 18-decimal USD prices and reporting the time of last update.
- Yield source. Routes each collateral asset into one ERC-4626 vault, tracks principal and shares per account, and performs harvests.
- Vault. One ERC-4626 vault per asset. At launch, a Corpus custody vault holding tokens 1:1.
- Router adapter. Executes the yield-to-USDG swap on a Uniswap-V3-style router with a per-pair fee tier.
The contracts are not upgradeable. Configuration is owner-controlled; positions are not.
2.2 Actions
Let q be the collateral quantity of a position, p the oracle price of the collateral in USD, D the debt in USDG, maxLTV the market's maximum loan-to-value ratio and LT its liquidation threshold.
Collateral value, expressed in USDG units, is
V = q x p
Deposit increases q and forwards the tokens to the yield source, which deposits them into the vault and records the principal. No price is needed, so a deposit is never blocked by a stale feed.
Borrow of an amount b requires a fresh price, an open market, and
D + b <= V x maxLTV
and that the treasury holds at least b USDG. Borrowing capacity is therefore max(0, V x maxLTV - D).
Repay of an amount r reduces D by min(r, D). It requires nothing else: no fresh price, no open market, not even an unpaused protocol. Anyone may repay on behalf of anyone.
Withdraw of a quantity w requires w <= q, and if the position has debt, a fresh price and D <= (q - w) x p x maxLTV afterwards. With no debt, a withdrawal needs no price at all.
Harvest is described in section 3. Anyone may call it for any position.
Claim transfers a position holder's accumulated USDG credit. It works while the protocol is paused.
2.3 Why the debt cannot grow
There is no interest accrual anywhere in the accounting. A position's debt is written at borrow time and afterwards only ever has amounts subtracted from it: by repayment, by harvested yield, or by liquidation. This is not a policy that could be relaxed by a parameter; there is no rate variable to set. The invariant tested in the contract suite is stated directly as a user's debt never increases except through borrow.
3. Defining yield
Yield has an exact definition here, and it is worth being pedantic about it, because most of the protocol's honesty rests on this one paragraph.
For each (asset, account) pair the yield source records principal, the quantity of tokens deposited, and shares, the vault shares received for them. The surplus at any moment is
surplus = max(0, vault.convertToAssets(shares) - principal)
That is: yield is the appreciation of the vault shares above the recorded principal, measured in the collateral token, floored at zero. Three consequences follow.
Yield is never negative. If the vault loses value, the surplus is zero. A loss is never converted into additional debt for the borrower. The position's principal simply becomes partially unbacked inside the vault, which is a risk borne on withdrawal, not a debt increase.
Yield is only realised when harvested. Until a harvest runs, the surplus sits in the vault as unconverted shares. The interface shows it as pending yield.
Yield is exactly zero today. A custody vault's convertToAssets(shares) always equals principal, so surplus = 0, every harvest returns zero, and nothing is applied to any debt. This is the current state of every one of the nine markets.
3.1 The harvest
When a harvest runs for an asset with surplus > 0:
Exactly
surplustokens are withdrawn from the vault.A minimum output is computed from the oracle, not from the pool:
minOut = surplus x p x (1 - s)where
sis the slippage bound, 1% at launch, with a hard ceiling of 10% that the owner cannot exceed.The tokens are swapped to USDG through the router adapter.
If the swap returns less than
minOut, the whole harvest reverts. A thin pool cannot quietly sell collateral yield at a bad price.
The oracle bound is the important part. The swap is checked against an independent price source, so the cost of a harvest is bounded by policy rather than by whatever the pool offers at that instant.
3.2 Distribution
Harvested USDG arrives at the market level and is distributed by an accumulator index. On each sync, if the market holds collateral,
yieldIndex += usdgOut / totalCollateral
and a position settles its share when it is next touched:
gross = q x (yieldIndex - snapshot)
cut = gross x 10% -> protocol fee recipient
net = gross - cut
toDebt = min(net, D) -> D decreases by toDebt
credit = net - toDebt -> claimable USDG for the position holder
snapshot = yieldIndex
Conservation holds exactly: gross = cut + toDebt + credit. Because a position settles before its collateral changes, a deposit made after yield has accrued cannot capture any of it.
Every position-changing call first attempts a sync. For deposits, repayments, withdrawals and borrows, the sync is wrapped so that a failing swap cannot block the action; a borrower can always repay even when the market for their collateral is broken. An explicit harvest call uses the strict path and reverts on failure, so nobody is told a harvest succeeded when it did not.
4. Risk parameters
| Market | Max LTV | Liquidation threshold | Liquidation bonus | Cap |
|---|---|---|---|---|
| AAPL, AMZN, GOOGL, META, MSFT, NVDA | 50% | 60% | 5% | Unlimited |
| QQQ, SPY | 60% | 70% | 5% | Unlimited |
| TSLA | 40% | 50% | 7.5% | Unlimited |
Protocol share of harvested yield: 10%. Staleness window: 80 hours (288,000 seconds). Harvest slippage bound: 1%.
Three groups, three arguments.
Broad-index ETFs get the most room. QQQ and SPY are baskets. A single earnings miss or product failure moves them a fraction of what it moves a constituent, so a 60% starting LTV with a 70% threshold is defensible.
Large single names sit in the middle. Six household-name equities at 50/60. The 10-point gap means a position borrowed to the limit is liquidatable after a 16.67% fall — small, but single stocks routinely gap by that much on a result.
TSLA gets the least room and the largest bonus. Its realised volatility has persistently exceeded that of the other listed names, and its single-day moves are larger. 40/50 leaves a 20% fall before liquidation from the maximum, and the 7.5% bonus exists to make liquidating it attractive during exactly the fast move in which nobody wants to.
Every parameter set must satisfy 0 < maxLTV < LT <= 100%, bonus <= 20% and LT x (1 + bonus) < 1. The last condition is what makes the liquidation formula in section 6 well defined: without it, the repayment that restores health would be undefined or negative.
Caps are unlimited at launch. This is a simplification, not a claim about market depth, and it is the parameter most likely to change.
5. Oracle policy
Prices come from Chainlink aggregators, one per asset, normalised to 18 decimals. The oracle adapter rejects an answer that is zero or negative, an incomplete round, and an answer outside a configured floor and ceiling (neither bound is configured at launch). It does not judge freshness; that is the core's job, so that each consumer can decide what staleness means for its own operation.
The core treats a price as fresh for 80 hours after the aggregator's last update. Equity feeds update while the underlying market trades, so they are quiet every night, every weekend and every holiday. 80 hours covers the roughly 65.5 hours between a Friday close and a Monday open with margin; it does not cover the roughly 89.5 hours of a three-day weekend, which is a deliberate choice in favour of refusing to act rather than acting on a price that is nearly four days old.
The rule when a price is stale:
| Operation | Stale price |
|---|---|
| Deposit | Allowed |
| Repay (own or on behalf of another) | Allowed |
| Harvest | Allowed |
| Claim credit | Allowed |
| Fund treasury | Allowed |
| Borrow | Blocked |
| Withdraw with outstanding debt | Blocked |
| Liquidate | Blocked |
The principle: operations that cannot worsen a position's health are never blocked; operations that need a valuation are blocked until there is one. Notably, liquidation is blocked too. A stale feed cannot demonstrate that a position is unhealthy, so the protocol does not let anyone seize collateral on the strength of it. That transfers risk to the protocol — a position that became unhealthy during the closure is liquidated late — and that is the intended trade. See the risk page for what that costs.
Withdrawal with no debt is permitted while stale because no valuation is required to conclude that an unencumbered deposit belongs to its owner.
Harvest is listed as allowed because the core never gates it on price age. The yield source does: it prices the surplus it is about to sell against the same oracle and refuses an answer older than its own maxPriceAge, 26 hours by default and capped at three days. So a market with a surplus to sell can stop harvesting well inside the core's 80-hour window. That is a bound on the price a sale is measured against, not a freshness rule for the protocol, and it blocks nothing else — except a deposit, which requires the pending harvest to land.
6. Liquidation
A position is unhealthy when
HF = V x LT / D < 1
With no debt, HF is infinite. The price fall a position can absorb is 1 - 1 / HF.
6.1 Partial by construction
Many protocols allow a liquidator to close a fixed fraction of a position, commonly half. Corpus allows exactly the amount that restores health and not one unit more. Repaying R reduces the debt by R and removes collateral worth R x (1 + bonus). Setting the post-liquidation health factor equal to 1 gives
(V - R x (1 + bonus)) x LT = D - R
and solving for R:
R = (D - V x LT) / (1 - LT x (1 + bonus))
The denominator is positive precisely because parameter validation requires LT x (1 + bonus) < 1. The result is then capped:
R = min( R, D, V / (1 + bonus) )
The second cap bounds the liquidator to the outstanding debt; the third stops a claim on more collateral than the position holds. The contract computes this in integer arithmetic, rounding R up, and when neither cap binds it adds a further ceil(LT x BPS / denominator) units — two at the AAPL parameters — to absorb the floor applied when the remaining collateral is re-valued. Repaying exactly the bound therefore lands at or above 1e18, and the bound is a fixed point: it reads zero afterwards.
A repayAmount above the bound is clamped to it rather than rejected, so a one-unit repayFor from anybody can no longer cancel a liquidation that is already due by moving the bound under a pending call. Only a bound of zero still reverts, with OverLiquidation(0). A liquidator protects their own execution with the fourth argument, minSeize: the call reverts InsufficientSeize(seized, minSeize) if the collateral they would receive falls below it.
Collateral seized is
seized = R x (1 + bonus) / p
rounded down and capped at the position's collateral, withdrawn from the yield source and sent to the liquidator.
6.2 Worked example
A position of 10 AAPL borrowed 600.00 USDG when AAPL was $200.00 (HF = 2.00). AAPL falls to $95.00.
V = 950.00
HF = 950.00 x 0.60 / 600.00 = 0.95 -> liquidatable
R = (600.00 - 570.00) / (1 - 0.63)
= 30.00 / 0.37 = 81.081081... -> 81.081082 USDG permitted
seized = 81.081082 x 1.05 / 95.00 = 0.8961... AAPL
After the liquidation the debt is 518.92 USDG against 9.1038 AAPL worth 864.86 USDG, and
HF = 864.864863 x 0.60 / 518.918918 = 0.999999999614583332
That is 1.00 to every digit a reader cares about, and a few hundred million units of 1e18 — about 4e-10 — below it in the arithmetic the contract actually runs. The position therefore stays liquidatable for one further USDG unit, 0.000001 USDG, until the price moves. The borrower paid the 5% bonus on 81.08 USDG — about 4.05 USDG — and kept 91% of their collateral. A liquidator attempting 81.081083 USDG is reverted.
6.3 Pending yield first
A liquidation call syncs the market and settles the position before computing R. Yield already earned but not yet applied therefore reduces the debt before anyone is allowed to seize anything, and if that is enough to bring HF to 1 or above, the liquidation reverts as Healthy. Today, with yield at zero, this path never changes an outcome. It matters the day an earning vault is connected.
6.4 Residual debt
If collateral reaches zero while debt remains — a gap large enough to jump past the bonus — the remaining debt stays recorded against the position and is a loss to the treasury. The protocol does not socialise it onto other borrowers, because there are no other lenders to socialise it onto. It simply reduces the USDG available to borrow.
7. Revenue and incentives
Protocol revenue is 10% of harvested yield, taken at settlement and sent to a fee recipient. It is the only revenue in the system. There is no interest spread, no deposit fee, no withdrawal fee, no liquidation share and no fee on repayment. When yield is zero, protocol revenue is zero. The owner can change the share but can never set it above 50%.
Liquidators are paid by the bonus: 5% on most markets, 7.5% on TSLA. Because liquidations are partial, the absolute payout per call is small, so the design relies on liquidations being cheap to compute — every input is a public view function — rather than on large individual rewards.
Harvesters are paid nothing. Harvest is permissionless and its gas is a cost to whoever calls it. This works because harvesting is not urgent: unharvested yield is not lost, only unapplied, and it will be picked up by the next call that touches the market. A keeper batches harvests across positions when pending yield passes a threshold. Any user may harvest their own position at any time.
The treasury is funded by whoever chooses to fund it; borrowing capacity across the whole protocol is limited by its balance minus outstanding claimable credit. It is a hard limit and the interface reports it.
8. Limits
What this design does not do:
- It does not protect against price falls. Self-repayment reduces debt over time; it does nothing about collateral that halves in a week. Liquidation risk is ordinary collateralised-lending risk, unchanged.
- It does not repay on a schedule. The rate of repayment is whatever the vault produces. If the vault produces little, the loan takes years. As an illustration: a 2,000 USDG position earning 4% a year produces 80 USDG gross, 72 USDG after the protocol's share, which retires a 600 USDG debt in roughly 8.3 years. Self-repaying is a description of direction, not speed.
- It does not work without an earning vault. Today, none exists on Robinhood Chain for these tokens, so the repayment rate is exactly zero.
- It does not remove custody and issuer risk. A Robinhood Stock Token is a claim honoured off-chain. Corpus makes no assertion about the quality of that claim.
- It does not hedge, insure or guarantee anything.
9. Status
Corpus is live on Robinhood Chain and has not been externally audited. The contract suite includes unit tests for every guard and error, property tests over the liquidation and settlement arithmetic, stateful invariant tests, and fork tests against live feeds and tokens — and none of that is a substitute for an audit.
The contracts cannot be upgraded. The owner can list and configure markets, replace the oracle or router, set the protocol share within its ceiling, pause the protocol and withdraw from the treasury. Pausing blocks deposits, borrows, withdrawals, liquidations and harvests; it never blocks repayment, repayment on behalf of another, claiming credit or funding the treasury. Those powers are real and are listed on the risk page alongside everything else that can go wrong.
Use small amounts. Robinhood Stock Tokens are not available to US persons and are restricted in other jurisdictions; establishing that you may lawfully hold and use them is your responsibility.