Bonds
Summary
Section titled “Summary”fact BondDepository runs OHM-v2-style bond markets. Each market accepts one asset kind, has a payout capacity, a maxDebt, a vestingSeconds, a controlVariable and a minPriceWad. Purchases mint NOTE into a linearly vesting per-user position; the asset paid goes to the Treasury.
| Accepted asset | Valuation |
|---|---|
| USDG | Par, normalised to 18-decimal WAD |
| Whitelisted Stock Tokens | Treasury feed value |
| COUPON legs (ERC-1155) | Par (1 USDG per unit), only while the series is Live and the barrier is holding |
Buying adds payout to the market’s debt, which raises the price for the next buyer; debt decays over the vesting period, lowering the price again. This is the usual bond-market feedback: heavy demand pushes price up towards market, quiet periods let it fall towards the discount governance intended.
Utilisation discount
Section titled “Utilisation discount”The discount links NOTE emission to the Desk’s need for capital. When the Desk has committed a large share of its COUPON caps (high utilisationBps), bonds get cheaper, raising reserves that fund the Desk. When the Desk is idle the discount is zero, so NOTE is not sold cheaply for no reason. utilisationK is the slope (bps of bps) and maxDiscountBps the cap (hard maximum MAX_DISCOUNT_CAP_BPS = 5,000). DeployToken.s.sol sets k = 2,000 and maxDiscountBps = 1,500. Setting desk to the zero address disables the discount. The discount never takes marketPrice below minPriceWad.
Worked example
Section titled “Worked example”illustrative Market 0 accepts USDG. controlVariable = 8.0e18, minPriceWad = 0.40e18, vestingSeconds = 5 days. NOTE total supply 10,000,000; current debt 300,000 NOTE. Desk utilisation 60% (6,000 bps), k = 500, maxDiscountBps = 2,000.
| Step | Calculation | Result |
|---|---|---|
| debtRatio | 300,000 / 10,000,000 | 0.03 |
| basePrice | max(8.0 × 0.03, 0.40) | 0.40 (floored) |
| discount | min(6,000 × 500 / 10,000, 2,000) | 300 bps |
| marketPrice | max(0.40 × (1 − 0.03), 0.40) | 0.40 USDG per NOTE (the discount cannot take the price below minPriceWad) |
| payout for 10,000 USDG | 10,000 / 0.40 | 25,000 NOTE, vesting linearly over 5 days |
| new debt | 300,000 + 25,000 | 325,000 → debtRatio 0.0325, basePrice 0.40 (still floored) |
With controlVariable = 16.0e18 instead, basePrice would be 0.52, and the 300 bps discount would price the bond at 0.5044. If the reference market price of NOTE is 0.55, that is an 8.3% discount to market. If the market price is 0.35, the bond is more expensive than the market and nobody buys; minPriceWad is set near the Treasury floor so bonds never sell NOTE below reserve value.
Vesting and redemption
Section titled “Vesting and redemption”deposit(id, amount, maxPriceWad, recipient) transfers the quote asset to the Treasury, mints payout NOTE to the depository and opens a Bond{marketId, payout, claimed, vestStart, vestEnd} for recipient (Bonded(id, depositor, recipient, amount, payout, priceWad, bondIndex)). It reverts with PriceTooHigh(price, maxPrice) if the price moved above the caller’s limit, ExceedsCapacity, ExceedsMaxDebt, MarketInactive or MarketConcluded. redeem(uint256[] indexes) pays the vested-but-unclaimed NOTE on each listed position (pendingPayout(user, index)) and emits Redeemed(recipient, bondIndex, amount); the rest remains. Multiple positions per user are supported. The NOTE minted is bounded by the market capacity, the maxDebt, and the NOTE epoch cap, whichever binds first. closeMarket(id) sets active = false and capacity = 0.
COUPON-leg bonds
Section titled “COUPON-leg bonds”A COUPON holder may bond units of a Live series with the barrier holding. The Treasury registers the series (LegSeriesRegistered) and thereafter values the units at par until a breach, then at min(1, lastPrice / s0), and harvests the coupons (SeriesHarvested). This converts a live note position into vesting NOTE and lets the Treasury accumulate yield-bearing reserves.
Governance surface
Section titled “Governance surface”| Function | Effect |
|---|---|
createMarket(MarketParams) | New market (MarketCreated) |
closeMarket(id) | Sets capacity to zero (MarketClosed) |
setControlVariable(id, cv) | Tunes price slope (ControlVariableUpdated) |
setDiscountParams(k, maxDiscountBps) | Utilisation discount (DiscountParamsUpdated) |
setDesk(addr) | Utilisation source (DeskUpdated) |
Risk notes
Section titled “Risk notes”- Bonds dilute existing holders by design. The epoch cap bounds the pace.
- A mispriced
controlVariablecan sell NOTE too cheaply for one vesting period; the Treasury still receives full value at feed prices, so the floor rises even then. - Stock Token bonds add Stock Token issuer and oracle risk to the Treasury. See Issuer risk.
Floors and lags
Section titled “Floors and lags”fact createMarket rejects a minPriceWad below redemptionFloorWad(), the Treasury’s current redemption value of one NOTE (MinPriceBelowFloor), so bonds cannot mint NOTE for less than the Treasury would pay to buy it back. The utilisation discount uses the Desk’s utilisation as of the previous block, so a deposit or withdrawal in the same block cannot move the bond price. COUPON-leg markets refuse deposits when the live price print is stale, the live barrier is breached, or an observation closes within one hour.