Skip to main content

Reinvestment Vault (Vault Bond Tokens)

The Reinvestment Vault is a Bondi product built as an ERC-4626 wrapper around a Bond Token that compounds coupon payments back into the underlying Bond Token. Depositing btXXX into the vault mints vbtXXX — a standard ERC-20 whose value rises as each coupon is swapped for more Bond Tokens.

vbtXXX is the true DeFi composability layer for Bond Tokens. Holding btXXX directly means dealing with Distribution separately for each coupon, principal redemption, and bond call. vbtXXX consolidates that into one ERC-4626 interface: deposit Bond Tokens, hold a share, exit through redeem or withdraw. There is no admin force-transfer capability, vault supply changes only through standard ERC-4626 operations, and there is no KYC check on redeem/withdraw. vbtXXX moves freely as a standard ERC-20 and integrates with any protocol — including lending markets and yield aggregators — enabling collateralization and leveraged looping strategies that are not possible with raw Bond Tokens.


Overview

Standard path: A holder deposits Bond Tokens (btXXX) and receives vault shares (vbtXXX). Each coupon payment is routed through the vault, swapped for more Bond Tokens, and the resulting Bond Tokens are added to the vault's total assets — increasing the redemption value of every outstanding share without requiring any action from the holder.


The full abstraction: A vbtXXX holder interacts only with the vault contract. On exit, they receive their share of the vault's Bond Token backing plus any stablecoin the vault is currently holding:


Pending coupon reinvestment — stablecoin sitting in the vault because the DEX swap has not completed yet (oracle staleness, pool deviation, or retry interval). This is not the steady state; it is the window while a swap is blocked or queued.


Call proceeds — stablecoin from a bond call, held as pendingCallStable until the share holder exits. A single redeem or withdraw pays this call stablecoin pro-rata to the exiting holder together with any other pending stablecoin in the vault. Call proceeds are never reinvested back into Bond Tokens, and settlement is accounted atomically so there is no artificial NAV gap from the call event. See Vault Settlement on Bond Call.


Principal at maturity — a single redeem or withdraw routes to principal redemption through Distribution and pays principal stablecoin plus any remaining pending stable in one transaction. Bond call settlements are absorbed atomically in-vault — the oracle sees no NAV gap because BT burn and stablecoin receipt happen in the same block. See Vault Settlement at Maturity for maturity settlement.



Vault Shares (vbtXXX)

vbtXXX shares follow the standard ERC-4626 accounting model and entry/exit interfaces:

Deposit: deposit(btXXX, receiver) — transfer Bond Tokens into the vault, receive vault shares proportional to the current share price.


Redeem: redeem(shares, receiver, owner) — burn Vault Bond Tokens. Before maturity, receive the proportional Bond Token balance plus any pro-rata pending stablecoin (coupon awaiting swap, or call proceeds). At maturity, redeem routes to principal redemption — see Vault Settlement at Maturity. withdraw follows the same routing.


Share price and anti-gaming: VbtVaultOracle prices vbtXXX shares as btComponent + stableComponent:


btComponent — Bond Token holdings per share × bond oracle price
stableComponent — pending stablecoin (coupon + call proceeds) per share


The share price reflects the full economic value of the vault at all times, regardless of what form that value takes. When a coupon arrives, the stablecoin component rises immediately; when it is reinvested into Bond Tokens, the BT component rises equivalently. A new depositor entering while a coupon or call is pending pays an oracle-adjusted price that already includes the pending value — there is no window to enter, capture proceeds, and exit at a windfall. Anti-gaming comes from full-value accounting at entry and exit, not from timing assumptions.


Deposit window: New deposits are accepted at all times unless the vault has been permanently closed (post-maturity, or after a full bond call that burns all Bond Tokens in the vault).


Coupon Auto-Reinvestment

Coupons reach the vault through the same onchain distribution path as wallet holders — the vault address is included in the entitlement snapshot and the relayer claims on its behalf. See Coupon Distribution for the full registration, snapshot, and claim sequence. Once stablecoin arrives in the vault, a relayer-triggered swap converts it to Bond Tokens and completes the reinvestment.

Compounding Efficiency vs. Traditional Markets

In traditional bond markets, the minimum tradable lot is typically $200,000 face value. For a semi-annual 10% bond, a holder would need at least $4,000,000 in Bond Token face value to reinvest a single coupon payment back into that same bond at the minimum $200,000 lot. Bond Tokens lower the holding threshold to any fraction — but reinvesting coupon stablecoin for Bond Tokens still requires accessing a liquid market. The Reinvestment Vault handles this by pooling all vault holders' coupon proceeds into a single DEX swap. In practice this delivers institutional-grade compounding access to holders at any position size — a theoretical efficiency improvement of up to four million times compared to the traditional minimum lot constraint.


Bondi works with liquidity providers to ensure the Bond Token pool can absorb coupon reinvestments at minimal slippage. A pending reinvestment state is transient — coupon proceeds are expected to be swapped into Bond Tokens promptly. In the unlikely event that a swap fails (oracle staleness or excessive pool deviation), coupon proceeds remain safely pending: any holder who exits during the pending window receives their pro-rata stablecoin share immediately, with no loss and no action required.

Coupon Reinvestment Flow

Steps 1–5 (gross transfer through Merkle finalization) are identical to Coupon Distribution. This diagram also shows the Reinvestment Vault-specific steps after the standard coupon distribution path.

Segregated AccountSeg. Account
AdminAdmin
OrchestratorOrchestrator
Distribution ContractDistribution
RelayerRelayer
Reinvestment VaultReinv. Vault
DEX PoolDEX Pool
Transfer gross stablecoin for coupon
registerCoupon(amount)
finalizeCoupon(couponId, root, blockNumber)
claimCouponForUser(vault, couponId, amount, proof)
Stablecoin transfer + registerCoupon callback
Pending reinvestment queued; vbt oracle share price reflects pending stablecoin value
7. Reinvestment
reinvestCoupon()
Swap stablecoin → btXXX
btXXX returned; pending reinvestment cleared
Exiting while pending
redeem(shares) while pending → btXXX + pro-rata stablecoin payout

How Coupon Reinvestment Works

1. Gross coupon transfer through Merkle finalization
This step follows the standard coupon distribution path — see Coupon Distribution. The snapshot and Merkle tree include the vault address as an ordinary holder.


2. Relayer coupon claim
The relayer calls Distribution.claimCouponForUser(vault, couponId, amount, proof) on behalf of the vault address. Because the Reinvestment Vault is a whitelisted Bondi vault, Distribution transfers stablecoins to the vault and immediately calls the vault's registerCoupon callback in the same transaction.


3. Pending state
Once registerCoupon is called on the vault, the pending reinvestment balance is active. The oracle share price immediately reflects the pending stablecoin value. New depositors pay a fair oracle-adjusted entry price that already prices in the pending coupon. Existing holders who exit while the coupon is pending receive their pro-rata share of the pending stablecoin immediately, without having to wait for the swap.


4. Swap: Coupon Proceeds → Bond Tokens
The relayer calls reinvestCoupon() on the vault. The vault executes a Uniswap v3 swap: stablecoins in, Bond Tokens out. Two validation checks run before the swap:


Freshness check: the oracle price (cbonds real-world price) must be less than 24 hours old. If stale, the swap reverts.
Deviation check: the pool price is compared against the oracle price. If the deviation exceeds oracleDeviationThreshold (default 5%), the swap is blocked and queued for retry after retryInterval (default 24 hours).


On success, Bond Tokens are added to the vault and totalAssets() increases. The pending stablecoin clears; the oracle's stable component returns to zero and the BT component rises to reflect the new Bond Token balance. The net oracle price is approximately unchanged as the coupon value was already tracked in stablecoin form throughout the pending window.


If a second coupon arrives while a reinvestment is still pending, the two amounts are merged into the same pending bucket and reinvested together in the next successful swap.

Price Protection

The oracle deviation check is the primary defense against pool manipulation. If a malicious actor moves the Bond Token pool price just before a reinvestment, the vault detects the deviation from the real-world cbonds price and blocks the swap — protecting shareholders from receiving fewer Bond Tokens than fair market value. Bondi triggers a retry after the cooldown period once the pool price normalizes.


Called Bonds in Vault Context

When the bond issuer exercises a call provision, all Bond Token holders are affected pro-rata — including the Reinvestment Vault. Without careful handling, a bond call would create a window where the vault's Bond Tokens are burned but their equivalent stablecoin proceeds have not yet been reflected in the vault's accounting.

For lending protocols using vbtXXX as collateral, any unaccounted gap in NAV during that window could trigger unnecessary liquidations of otherwise-healthy positions. The Reinvestment Vault eliminates this gap entirely.

The general issuer bond call flow — registration, snapshot, and relayer execution — applies to all holders. See the Issuer Bond Call Flow in Redemption. For how whitelisted vaults are settled differently from individual Bond Token holders, see Vault Settlement on Bond Call.

How Called Bond Settlement Works for the Reinvestment Vault

1. Relayer execution
The relayer calls Distribution.executeCallForUser(callId, vault, expectedBalance). Distribution identifies the vault as a whitelisted Bondi vault.


2. Atomic settlement
The vault's callable Bond Tokens are burned, call stablecoin proceeds are transferred to the vault, and the vault's registerCall callback is triggered in a single transaction. The vault records the stablecoin in pendingCallStable. Because the BT burn and stablecoin receipt happen atomically, the oracle's BT component and stable component update in the same block — the share price is never artificially depressed.


3. Pro-rata payout on exit
Call proceeds in pendingCallStable are not reinvested back into Bond Tokens. When any vault holder redeems or withdraws, they receive their proportional share of pendingCallStable alongside their Bond Tokens in the same transaction with no separate claim step. At maturity, redeem on the vault pays any pending coupon stable (if reinvestment failed), call stable, and principal stablecoin the same way. See Vault Settlement at Maturity.

Share Price Continuity Through All Lifecycle Events

VbtVaultOracle always prices vbtXXX shares as btComponent + stableComponent. This design means the share price accounts for every form of value in the vault — whether that value is held as Bond Tokens, pending coupon stablecoin, or call proceeds. No lifecycle event creates a gap:


Pending coupon reinvestment: stableComponent rises immediately when the coupon is registered. New depositors pay an oracle-adjusted entry price that includes the pending value; exiters receive it on redemption. No gaming window exists.
Bond call settlement: btComponent drops (fewer Bond Tokens) and stableComponent rises (pendingCallStable added) in the same block. No artificial NAV drop triggers liquidations. Yet a slight net price shift can happen, reflecting the call price vs. the prevailing oracle price rather than an accounting gap.
Maturity: deposits close; redeem routes to principal redemption. The oracle continues pricing correctly until the last holder exits — pending coupon stable and call stable are paid pro-rata, and the corresponding Bond Token backing is burned through Distribution for principal settlement within the same exit flow. See Vault Settlement at Maturity.
Oracle staleness: if the live bond price feed is temporarily unavailable, VbtVaultOracle uses the last valid recorded bond price rather than dropping to stable-only valuation. This avoids artificial liquidation pressure from oracle downtime while preserving continuous collateral pricing.


Key Terms

btXXX: Bond Token — the underlying asset deposited into the vault (e.g., btLIFE).
vbtXXX: Vault share token — the ERC-4626 receipt issued on deposit (e.g., vbtLIFE). Fully transferable ERC-20; no KYC check on redeem/withdraw; no force-transfer capability; full composability; appreciates as coupons are reinvested.
VbtVaultOracle: Morpho-compatible oracle for vbtXXX. Its price() output equals (btComponent + stableComponent) × 1e18, where btComponent is computed from the vault's exchangeRate() and the bond oracle price, and stableComponent is pendingStableBalance() / totalSupply. Gives lending protocols accurate real-time pricing through every lifecycle phase — including pending coupon reinvestment and call settlement windows. On temporary oracle staleness/unavailability, it uses the last valid recorded bond price to keep collateral pricing continuous.
pendingCallStable: Running total of stablecoin received from bond call settlements, held in the vault and paid pro-rata to holders on every exit. Never reinvested back into Bond Tokens due to onchain liquidty concerns.
pendingReinvestment: Stablecoin queued for the USD→BT swap after a coupon claim. Paid pro-rata in stablecoin to any holder who exits before the swap completes.
pendingStableBalance(): View function returning stablecoin value currently held in-vault for holders — including pendingCallStable, any active pending coupon amount, and (in maturity context) principal already received into the vault and awaiting holder exits. Used by VbtVaultOracle to compute the stable component of the vault's NAV.
exchangeRate(): Vault function returning totalAssets() × 1e18 / totalSupply() — the Bond Token backing per vault share, used by VbtVaultOracle as its BT component input.
Oracle deviation threshold: The maximum allowed difference between the Uniswap pool price and the cbonds oracle price before a coupon reinvestment swap is blocked. Default 5%.
retryInterval: The cooldown between failed coupon reinvestment swap attempts. Default 24 hours.