Bond capital is the protocol’s slashing reserve. Its primary job is to pay users when an agent harms them. Yield on top is a bonus, not the goal. Here’s the routing strategy, the split, and the explicit trade-offs.
Idle USDC in the bond vault PDA gets split across two production USDC LPs via CPI. Both are audited, depeg-resistant, non-leveraged: the same primitives MakerDAO PSM and Nexus Mutual treasury pick. Yield is harvested on a cadence and credited via accrue_yield(amount), half to builder and half to treasury.
| Strategy | Gross APY | Net to builder | Slashing risk | Status |
|---|---|---|---|---|
| Single (Kamino) Considered, dropped | 5.0% | 2.5% | single point of failure | deprecated |
| Dual failover (60/40) Kamino + MarginFi | ~5.4% | 2.7% | tolerates 1 protocol pause | Live now |
| Vault router Meteora / Kamino Multiply | 8-12% | 4-6% | leverage + cross-asset | considered, rejected |
| Builder-elected Per-agent choice | variable | variable | moral hazard | v3 · far future |
Numbers from on-chain rates (Kamino USDC main 4.8%, MarginFi USDC 5.5%, values as of writing). Dual route: weighted average minus rebalance cost.
Bond vault deposits split via CPI. Yield is harvested on a regular cadence and credited via accrue_yield. If either protocol pauses, the other absorbs the full route. Realized APY runs around 5-6% gross.
The 50% treasury share starts routing into Kamino Multiply and Meteora dynamic vaults for higher yield (8-10% target). The slashing reserve floor (30% of treasury) stays in the conservative dual route.
Builders can opt in to riskier strategies for higher net APY, with explicit on-chain disclosure to handlers. The default stays dual failover. Deferred until the protocol has a track record and an insurance pool live.
The treasury isn’t profit. It funds:
The split logic lives in programs/bonded_agents/src/instructions/accrue_yield.rs. It’s 60 lines, fully deterministic, no governance hooks.
// state.rs - constants the on-chain code uses
pub const BUILDER_YIELD_SHARE_BPS: u64 = 5_000; // 50.00%
pub const TOTAL_BPS: u64 = 10_000;
// accrue_yield.rs handler - credited atomically per harvest
let builder_share = amount
.checked_mul(BUILDER_YIELD_SHARE_BPS).ok_or(MathOverflow)?
.checked_div(TOTAL_BPS).ok_or(MathOverflow)?;
let treasury_share = amount.checked_sub(builder_share).ok_or(MathOverflow)?;
agent.builder_yield_unclaimed = agent.builder_yield_unclaimed.checked_add(builder_share)?;
agent.treasury_yield_unclaimed = agent.treasury_yield_unclaimed.checked_add(treasury_share)?;
agent.total_yield_accrued = agent.total_yield_accrued.checked_add(amount)?;