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 and vault supply changes only through standard ERC-4626 operations. Entry and transfer are permissionless; the vault never pays distribution stablecoin to a non-KYC-verified wallet, but all holders can always exit in Bond Token form. See Compliance at Reinvestment Vault Exit. vbtXXX 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 via redeem or withdraw, they receive their pro-rata share of everything the vault holds — Bond Token backing plus any pending coupon or call stablecoin — per Compliance at Reinvestment Vault Exit:


Pending coupon reinvestment: stablecoins sitting in the vault because the DEX swap has not completed yet (oracle staleness, pool deviation, or slippage). In practice this almost never happens as Bondi arranges the onchain liquidity with its liquidity partners so coupon swaps clear promptly.


Call proceeds: stablecoins from a bond call, held as pendingCallStable. Bondi expects this to clear quickly through unwinding, reinvestment, or exit — and preannounces the plan on the frontend before holders act. KYC holders can unwind a chosen slice via claimCallProceeds at the contractual call price without exiting the rest of their position; Bondi may reinvest some or all via reinvestCallStable when the pool allows; on full exit via redeem, any remainder settles pro-rata per Compliance at Reinvestment Vault Exit. See Called Bonds in the Reinvestment Vault.


Principal at maturity: once principalSet is true, KYC-verified holders receive all stables in one transaction; non-KYC-verified holders receive raw Bond Tokens and redeem principal at Distribution after completing KYC. See Vault Settlement at Maturity.


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 shares. See Holder Exits. withdraw follows the same exit rules.


Share price and anti-gaming: Vault Bond Token oracles price 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), or while an issuer bond call freeze is active on the underlying Bond Token (see Issuer Bond Calls).


Holder Exits

Everything a holder does with the Reinvestment Vault goes through the vault contract — deposit Bond Tokens, hold vbtXXX, exit whenever. The diagram below shows those holder-facing paths only. Bondi-operated backend steps (coupon reinvestment, bond-call registration) are covered in the lifecycle diagrams linked underneath.

vbtXXX HolderHolder
Reinvestment VaultReinv. Vault
Distribution ContractDistribution
deposit(btXXX, receiver)
Mint vbtXXX shares at the current oracle share price
3. Standard exit
redeem(shares) or withdraw(assets)
KYC-verified → Bond Token backing + pending coupon/call stable swapped to and settled as BT or as stable if the swap cannot clear
Non-KYC-verified → Bond Token backing + pending buckets swapped to BT or recorded as entitledStable for claim after KYC if the swap cannot clear
3. Alternative exit
redeemToBTAndStable — KYC-verified holders only
Bond Token backing + pending coupon/call stable paid as stablecoin (no swap)
3. Claim stables (no-KYC-verified holders only)
claimEntitledStable() or claimEntitledStableAsBT() - After KYC completion or anytime when user's entitledStable can be swapped to Bond Tokens
Stablecoin or Bond Tokens
4. After a bond call: unwind a position
claimCallProceeds(vbtToBurn) — KYC-verified holders only
Call stable + pro-rata pending coupon if a prior reinvestment failed
5. At maturity
redeem(shares) at maturity
redeemPrincipal — internal, KYC-verified holders only
Principal stablecoins → vault
KYC-verified → all stable; Non-KYC-verified → Bond Tokens + bucket handling as above

Enter: deposit(btXXX) → receive vbtXXX at the current oracle share price.


Exit fully: redeem or withdraw — always available for non-blacklisted receivers. KYC-verified holders receive Bond Token backing plus any pending coupon or call stablecoin, settled as Bond Tokens when the exit swap clears or as stablecoin when it cannot (or via redeemToBTAndStable by choice, with no swap). Non-KYC-verified holders receive Bond Tokens; pending buckets swap to Bond Tokens or are recorded as entitledStable to claim after completing KYC or whenever they can be swapped to Bond Tokens.


After a bond call, unwind the amount you choose: unwind on the Bondi frontend — receive the bond call proceeds exiting the desired portion of your position. See Why Unwinding Exists and Vault Settlement on Bond Call.


At maturity: redeem on the vault — KYC-verified holders receive all stable; non-KYC-verified holders receive Bond Tokens and handle principal at Distribution after KYC. See Vault Settlement at Maturity.


Coupon reinvestment (Bondi-operated, not a holder action): see Coupon Auto-Reinvestment below.


Compliance at Reinvestment Vault Exit

The vault never pays bond proceeds — coupon, call, or principal — directly to a non-KYC-verified wallet. All holders can still exit in Bond Token form; only Bondi's direct stablecoin payouts are gated. See Holder Exits right above for the full path map.


Blacklisted addresses are refused at vault entry and exit. vbtXXX remains freely transferable — Bondi's contracts will not serve a sanctioned address, but this is not a hard fund freeze.


entitledStable: Recorded stablecoin owed to a non-KYC-verified holder who exited when the swap of their pending coupon/call proceeds into Bond Tokens could not execute — so the proceeds could be neither delivered as Bond Tokens nor paid as distribution stable to a non-KYC-verified wallet, and are held on record instead. Claim via claimEntitledStable() once KYC-verified, or claimEntitledStableAsBT() for Bond Tokens when the liquditiy conditions improve. Bondi can never touch this bucket and it stays indefinitely in the vault until claimed.


You stay in control of the exit swap: When you exit and the vault needs to swap your pending coupon or call stablecoin into Bond Tokens, the Bondi app lets you set how much price movement you're willing to accept and shows you upfront whether the swap will go through at current market conditions — so you can go ahead, widen your tolerance, or wait. Nothing is ever forced through at a bad price. If a swap can't clear within your tolerance, your Bond Token backing is still delivered as Bond Tokens; the pending coupon/call proceeds that couldn't be converted are then paid to you as stablecoin if you're KYC-verified, or recorded as entitledStable to claim later if you're not.


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, Merkle tree building, 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 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, normally for the full pending amount in a single call. If a swap call fails — oracle staleness, pool deviation exceeding the oracle threshold, or execution output falling below the quoter-derived floor — the call reverts and proceeds remain in pendingReinvestment. Exit treatment for pending proceeds follows Compliance at Reinvestment Vault Exit.

Coupon Reinvestment Flow

Steps 1–5 (gross transfer through Merkle finalization) are identical to Coupon Distribution. Furthermore, this diagram 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; vbt oracle share price reflects pending stablecoin value
7. Reinvestment
reinvestCoupon(amount) — typically the full pending coupon balance
Swap stablecoin → btXXX
btXXX returned; pending reinvestment cleared

How Coupon Reinvestment Works

1. Gross coupon transfer through Merkle finalization
This step covers steps 1 to 5 above and 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.


4. Swap: Coupon Proceeds → Bond Tokens
The admin or relayer calls reinvestCoupon(amount) on the vault. In normal operation this is always called for the entire pending coupon balance — the amount parameter gives the contract flexibility, but partial coupon swaps are not standard practice. The vault executes a Uniswap v3 swap: stablecoins in, Bond Tokens out. Three checks run before and during the swap:


Freshness check: the oracle price (cbonds real-world price) must be less than 24 hours old. If stale, the call reverts.
Oracle deviation check: the vault obtains a Uniswap quoter output for the exact trade size; the implied price is compared against the oracle price. If the deviation exceeds oracleDeviationThreshold (default 2.5%), the call reverts. This check detects a pool that has moved far from the real-world reference price.
Quote-to-execution slippage check: the vault passes amountOutMinimum = quoterOutput × (1 − slippageThreshold) to the Uniswap router. If actual execution delivers fewer Bond Tokens than that floor, the router call reverts. This check is anchored to the quoter output — not the oracle price — and catches sandwich attacks and thin-liquidity fills that occur between the quote and the actual execution.


If any check fails, the call reverts and the coupon remains in pendingReinvestment. There is no onchain cooldown — the admin or relayer can retry at any time — but operationally Bondi tries again as soon as conditions allow, and roughly once a day thereafter, until the swap clears.


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

Two independent guards protect shareholders from receiving fewer Bond Tokens than fair market value. The oracle deviation check detects when the pool price has moved far from the real-world cbonds price — a signal of pool manipulation or unusually thin liquidity. The quote-to-execution slippage check anchors the minimum acceptable swap output to the Uniswap quoter's result at the time of the call, catching sandwich attacks that occur between the quoter query and the actual fill. Both guards revert the call if triggered. There is no onchain cooldown, so the admin or relayer can retry at any time; in practice Bondi retries as soon as conditions allow and roughly once a day thereafter, until market conditions normalize and the swap clears.


Called Bonds in the Reinvestment Vault

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, full Bond Token freeze, 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.

Why Unwinding Exists

A bond call shrinks the vault's Bond Token holdings and replaces that slice with stablecoin that sits idle — earning nothing — until it is either reinvested or paid out. Some holders are happy to stay fully invested and let that stablecoin eventually compound back into Bond Tokens or let other unwind and keep their full exposure. Others, for example some holders using vbtXXX as collateral on a lending market like Morpho, may want that cash now: to repay debt, to delever, or simply to take the proceeds without giving up the rest of their position.


claimCallProceeds gives holders that choice without asking anyone else to pay for it. A holder burns a chosen amount of their own vBT and receives the matching call stablecoin at the contractual call price. That vBT is removed from supply and call proceeds are paid out, so the Bond Tokens still backing every remaining share stay exactly as they were. Unwinding only clears idle stablecoin the holder chose to take as cash; it does not shift Bond Token exposure or coupon entitlement onto anyone else.


Bondi announces a call and the resulting unwind opportunity through all its communication channels — holders who want to unwind their call slice can do so on the Bondi frontend. Bondi expects unwinding to happen promptly after a call; no special monitoring of the vault is required.

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. Exit paths for call proceeds
After registerCall, three paths exist for accessing pendingCallStable:


Pro-rata exit via redeem(shares): Burn vault shares and receive pro-rata Bond Token backing plus pro-rata pendingCallStable and any pending coupon stablecoin. Settlement follows Compliance at Reinvestment Vault Exit. After a full bond call (callRatioBps == 10000), totalAssets() == 0 so Bond Token output is zero; use redeem, not withdraw(assets)withdraw reverts with InsufficientBondTokenForWithdraw when there are no Bond Tokens to back the asset amount.


Direct claim via claimCallProceeds(vbtToBurn) (KYC-gated): Burn a chosen number of vBT — up to what the Bondi frontend shows as available — and receive call stable at the contractual call price for those shares, plus pro-rata pending coupon on them, without exiting the full vault position. Remaining vBT keeps its Bond Token backing and continues earning future coupons. Useful for holders using vBT as collateral (e.g. Morpho) who need call cash without burning their whole position.


Admin/relayer reinvestment via reinvestCallStable(amount): Swap a portion of pendingCallStable back into Bond Tokens via the same oracle deviation and slippage guards as coupon reinvestment. Remaining holders benefit through a higher Bond Token NAV per share. This is coordinated by Bondi ops, not triggered automatically — Bondi decides per call how much to reinvest versus leave for holders to access via claimCallProceeds or redeem, based on pool liquidity.

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. 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; exit follows Compliance at Reinvestment Vault Exit. See also 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 Bond Token (shares in the ERC-4626 context) — the ERC-4626 receipt issued on deposit (e.g., vbtLIFE). Fully transferable ERC-20; no KYC required to enter or transfer; distribution stablecoin paid directly only to KYC-verified receivers on exit; no force-transfer capability; appreciates as coupons are reinvested.
exchangeRate(): totalAssets() × 1e18 / totalSupply() — Bond Token backing per Vault Bond Token.
pendingReinvestment: Stablecoin queued for the stablecoin→BT swap after a coupon claim.
pendingCallStable: Stablecoin from bond call settlements, held in the vault until it is unwound, reinvested, or paid out on exit. Bondi expects it to move quickly after a call. KYC holders unwind a slice via claimCallProceeds at the contractual call price; Bondi may reinvest some or all via reinvestCallStable when the pool allows; any remainder settles pro-rata on redeem.
pendingStableBalance(): Accounting view of in-vault stable owed pro-rata to active shareholders — pendingCallStable plus active pending coupon. Excludes totalEntitledStable (already allocated to specific wallets, not pool NAV). Used by VbtVaultOracle for the stable component of share price.
entitledStable: Stablecoin recorded for a non-KYC-verified holder who exited when the swap of their pending coupon/call proceeds into Bond Tokens could not execute (it can be neither delivered as Bond Tokens nor paid as distribution stable to a non-KYC-verified wallet). Claimable via claimEntitledStable() once KYC-verified, or claimEntitledStableAsBT() (Bond Tokens). Never admin-sweepable.
VbtVaultOracle: Morpho-compatible oracle for vbtXXX. Prices shares as (btComponent + stableComponent) × 1e18. If the bond price feed goes briefly stale, it holds the last valid bond price instead of falling back to a stable-only valuation — because dropping the Bond Token portion to zero would make the share appear almost worthless for the duration of the outage and trigger needless liquidations of otherwise-healthy positions in lending markets that use vbtXXX as collateral. Holding the last good price keeps collateral valuation continuous through temporary feed downtime.
redeemToBTAndStable: KYC-verified-only exit that pays Bond Token backing plus pending coupon/call stablecoin directly as stablecoin, with no swap. The standard redeem/withdraw exit decides the form (Bond Tokens vs. stablecoin) by whether the swap can clear and the KYC status; redeemToBTAndStable lets a KYC-verified holder pick the stablecoin form on purpose.
claimCallProceeds(vbtToBurn): KYC-gated. Burn a chosen amount of vBT and receive call stable at the contractual call price for those shares, plus pro-rata pending coupon on the amount burned. Does not require a full vault exit. The Bondi frontend shows how much you can unwind before you confirm.
currentCallRewindEligible(): View function returning how much vBT can still be burned for call proceeds at the contractual call price. The Bondi frontend uses this to show your unwind limit.
reinvestCallStable(amount): Admin/relayer function that swaps part of pendingCallStable back into Bond Tokens, using the same swap guards as reinvestCoupon. Remaining holders benefit from more Bond Token backing per share. Bondi may reinvest all, some, or none depending on pool liquidity and what it communicates ahead of the call.
Oracle deviation threshold (oracleDeviationThreshold): First of two independent reinvestment swap guards. Compares the Uniswap quoter's implied price for the exact trade size against the oracle price; if deviation exceeds the threshold (default 2.5%), the swap call reverts. Detects a pool that has moved far from the real-world reference price. Both thresholds are constructor parameters, defaulting to 250 bps each in the Bondi ignition deployment.
Slippage threshold (slippageThreshold): Second of two independent reinvestment swap guards. The vault passes amountOutMinimum = quoterOutput × (1 − slippageThreshold) to the Uniswap router; if actual execution delivers fewer tokens than that floor, the swap reverts. Anchored to the quoter output — not the oracle price — so it independently catches sandwich attacks and execution shortfalls between quote time and fill time. Default 2.5%.