Skip to content

Bondi v2: Composable, fungible, verifiable

12 min readAli Sarp Mestçioğlu

Our first offering (v1) fully matured in June 2025 on Base. We paid the final coupon along the principal onchain, delivering a 9.98% APR. v1 remains backward-compatible: if you haven’t claimed yet, use https://app.bondifinance.io/bondiv1 (you can also inspect the distribution contract from the landing page’s Track Record section).

With that foundation proven—and no additional financial risk introduced—we rebuilt the distribution layer to make Bond Tokens truly crypto-native: composable, fungible, scalable, and regulation-friendly.

Bondi v2: Composable, fungible, verifiable — three equal mint and pine paper loops interlinked into one composition.

Why we upgraded (what v1 couldn’t scale)

v1 worked, but two things didn’t scale:

  1. Proceeds distribution: coupons relied on per-investor accounting, which doesn’t scale and isn’t set-verifiable onchain.
  2. Bond Token distribution: also used per-user state and loops.

In v2 we fixed both and unified everything under a single Distribution.sol. We also prepared for multichain: partner programs will fund user incentives for funding participation and seed secondary liquidity (we match with Bond Tokens), so we added incentive flows to Distribution.sol and designed a no-bridge accounting model to keep everything onchain and compliant.

The goal: a plain ERC-20 Bond Token that trades cleanly on DEXs and fits DeFi collateral —without sacrificing compliance. Product overview: https://docs.bondifinance.io/docs/product/bond-tokens



Post-funding: verifiability through Merkle, fungibility through snapshot, UX through relayer

  • Snapshot at deposit. For each distribution (coupons and incentive), entitlements are fixed at the deposit-time snapshot preserving Bond Token fungibility preserved; later transfers don’t change who’s owed.
  • Merkle commitment. We commit one Merkle root per distribution; anyone can independently rebuild the full set and verify onchain. Claims verify in O(log N); rounding always floors and dust is left. Spec:https://docs.bondifinance.io/docs/product/implementation-spec
  • Relayer = push-style payouts. For KYC'ed wallets, our relayer calls claimCouponForUser(user, couponId, amount, proof) (we pay gas); non-KYC holders who later complete KYC will manually back-claim on our UI via claimCoupon(...) for all pending coupons once. All coupons after KYC completion are automated.
  • Maturity order: UI claims the final coupon first, then calls redeemPrincipal() (burn BT, receive principal back at bond's face value)

Bondi Distribution Design vs. Alternatives

Method How it works (tl;dr) Snapshot / Entitlement basis (preserves fungibility) Population cost (admin-side, onchain/offchain) Claim gas (user, onchain) Set-level verifiability (can anyone recompute & check completeness onchain?) Pros Cons When it fits
Our v2: snapshot-at-deposit + Merkle root (with relayer auto-claim) Detect deposit → reconstruct balances at deposit block offchain → build Merkle → store root; relayer submits claimCouponForUser Deposit-time offchain snapshot Offchain: O(N) compute only. Onchain: O(1) (store root) O(log N) proof verify + one SSTORE (paid by Bondi via relayer in our UX) Yes. One root commits the full set; anyone can rebuild per our spec Gas-scalable, auditable, keeps ERC-20 lean**; strong composability, fungibility, and a DEX-friendly token We own tree/proof tooling Large N; you want auditability + great UX (relayer “push”)
Direct onchain mapping (full storage) Admin writes entitlement[user] = amount per coupon Same: deposit-time offchain snapshot Onchain: O(N) writes per coupon (tx storm) O(1) read + SSTORE No. There is no set commitment; you cannot verify completeness against a committed root Trivial claims; no proofs Onchain storage bloat; does not remove the need for an offchain snapshot Very small N; ultra-simple drops (this was Bondi v1; fixed in v2 with FPUSD + Merkle snapshots)
Admin push (batched transfers) Admin/relayer sends payouts to each recipient (batch where gas allows) Same: deposit-time offchain snapshot Onchain: O(N) runtime per coupon (multiple tx; batching limits) 0 for user No. Only per-tx traces; no set commitment to audit Zero user friction; instant payout Ops/gas heavy; retries/partial failures; All its UX benefits are provided by our relayer anyway, plus we add onchain verifiability with Merkle Controlled drops where pure “push” is fine
EIP-712 signed claims Offchain computes amounts at deposit block → per-user signature (user, amount, couponId, block, nonce); user/relayer submits Same: deposit-time offchain snapshot Offchain: O(N) signatures; Onchain: tiny setup Sig verify + SSTORE (often ≥ Merkle per claim at scale) No. Claims are individually authorized; there’s no set-level commitment. You must include a nonce/couponId in the signed payload to prevent signature replays No tree; flexible ops Needs trusted signer key; weak set-level audit story; ops to issue/distribute sigs Medium N; okay with signer trust; don’t need set-level auditability
Snapshot-token inheritance (ERC20Snapshot v4 or Votes-based in v5) Token exposes historical balance at deposit; contract stores snapshotId/block + rate = depositAmount / totalSupplyAt; each claim = balanceAt * rate (pure onchain math) Onchain snapshot at deposit (entitlement computed onchain) Onchain: O(1) (store id+rate); no per-address writes O(1) math N/A. Set completeness root not needed: entitlement is computed onchain from snapshotId+rate Cleanest claim path; no proofs; O(1) claims Snapshot is OZ v4-only (vendoring/maintenance). In v5 you’d approximate via ERC20Votes, which adds checkpoint writes on every transfer → persistent gas overhead → degrades composability, fungibility, and a DEX-friendly token Low-trade/governance-style tokens; not ideal for a widely traded bond token

**“keeps ERC-20 lean” vs inheriting ERC20Snapshot/Votes : our Merkle design does not add checkpoint/snapshot machinery inside the token, avoiding transfer-time overhead. ERC20Snapshot (v4): negligible one-time overhead per account after each snapshot ~7k–10k gas once, then normal transfers until the next snapshot (≈ $0.006–$0.02 on Base at 0.2–0.5 gwei, assuming ETH ≈ $4,000). ERC20Votes (v5) with forced auto self-delegation (votes ≈ balances for everyone): ~65.6k gas added to every transfer, always ≈ $0.05–$0.13 on Base at 0.2–0.5 gwei (ETH ≈ $4,000). Not ideal for a composable and highly-tradable Bond Token.

After proceeds are funded into Distribution, we close the round: the Orchestrator captures the deposit-time snapshot, rebuilds balances per our public spec, constructs the Merkle tree, and finalizes a single root onchain. That root is the commitment everything hangs on. No one is paid until it exists.

After the Orchestrator finalizes a single Merkle root onchain, the relayer continuously sweeps finalised rounds. For KYC-verified wallets, it calls claimCouponForUser(user, couponId, amount, proof) ; we pay the gas. Holders who weren’t KYC’d can complete KYC and use the UI’s back-claim to call claimCoupon(...) across all pending couponIds once; from then on, every new coupon is paid automatically by the relayer.

Post-Funding Bond Token Lifecycle Until Maturity

Funding: FpUSD receipts and multichain without bridges

  • Unified Distribution. One contract handles bond allocation, incentives, coupons, principal, with KYC gates where required.
  • FpUSD receipts. Users deposit a local USD stablecoin and receive FpUSD on the same chain. When bonds are emitted, they burn FpUSD for Bond Tokens in O(1) via claimBonds()—no per-user allocation loops.
  • Multichain accounting, zero bridging. Our Watcher mirrors accounting only across chains (assets never move). Emission and claims always happen on the chain you funded. This removes bridge risk and aligns with compliance.
  • Operational redundancy. We run multiple providers (websocket + webhooks) with dedupe so event detection is resilient.
Funding Process

Security and no added financial risk

  • Least-privilege roles. Across Watcher / Orchestrator / Relayer; services can delay UX but cannot move user funds.
  • Assets never leave their chain; only accounting is mirrored.
  • Deterministic public spec for snapshots/proofs; anyone can rebuild and verify distributions end-to-end onchain.
  • Built on v1’s battle-tested foundations —we changed the scaling model, not the risk model.

Conclusion

Bondi v2 delivers a market-friendly multichain Bond Token that stays fungible and composable, with auditable distributions and push-style UX—transparent, onchain, and without bridge risk. Funding remains chain-local via FpUSD receipts; proceeds are Merkle-verified; KYC’d users get auto-payouts; everyone gets verifiability. If you’re a builder, auditor, or partner chain, our spec and diagrams make it straightforward to validate every step.

All posts