Tokenized corporate bond lifecycle on Ethereum — subscription, coupon payments, and redemption with Dfns wallets
Issue tokenized corporate bonds on Ethereum where investors subscribe with stablecoins, receive ERC-20 bond tokens, collect periodic coupon payments, and redeem principal at maturity — all transactions signed through Dfns managed wallets.
The contract also includes default protection: if the Issuer fails to fund a coupon within a 5-day grace period, anyone can trigger a default flag that halts further operations.
Component
Technology
Contracts
Solidity 0.8.28 (OpenZeppelin, Hardhat v3)
Signing
Dfns KMS via @dfns/sdk
Scripts
TypeScript (tsx, viem)
Web UI
Single-page Express app with split Issuer/Investor dashboards
contracts/ Bond.sol ERC-20 bond token with full lifecycle management BondMath.sol Library for accrued interest calculation StableCoin.sol ERC-20 stablecoin with mint, burn, pause, and rolesscripts/ dfns.ts Shared Dfns API client and viem public client server.ts Express server with REST API for the web UI ui.html Single-page web UI (Issuer + Investor dashboards) e2e.ts Non-interactive end-to-end lifecycle script deploy-stablecoin.ts Deploy a stablecoin contract deploy-bond.ts Deploy a bond contract with configurable terms mint-stablecoin.ts Mint stablecoin to any address issuer-ops.ts Interactive CLI for issuer operations holder-ops.ts Interactive CLI for investor operations stablecoin-ops.ts Interactive CLI for stablecoin managementtest/ Bond.test.ts Core lifecycle tests BondExtended.test.ts Over/under-subscription, grace period, interest math BondFull.test.ts Full lifecycle with 4 investors BondSpecific.test.ts Short-duration bond scenario
The browser UI covers the full bond lifecycle. It shows two dashboards side by side — Issuer (blue) and Investor (green) — with numbered steps to follow in order.
Copy
Ask AI
npm run ui
Open http://localhost:3000. The UI calls a lightweight Express server that signs and broadcasts transactions via the Dfns API. Bond status auto-refreshes every 5 seconds.Each step in the UI maps to a contract function call:
Deploy StableCoin — deploy the EURC contract
Mint EURC — fund both wallets
Deploy Bond — configure face value, APR, coupon frequency, and duration
Subscribe — investor deposits EURC into escrow
Close Issuance — lock subscriptions, start interest clock
Withdraw Proceeds — issuer collects raised EURC
Claim Bond Tokens — investor mints ERC-20 bond tokens
Deposit Coupon — issuer funds the next coupon period
This deploys both contracts, mints stablecoins, subscribes, closes issuance, claims bonds, deposits and claims a coupon — all in a single run. Useful for verifying the setup end to end.
The scripts use viem to encode deployment data and function calldata, then broadcast via Dfns. A viem PublicClient reads on-chain state (balances, bond status, coupon dates) without requiring signing.
Different networks — Replace the RPC URL in .env with one for your target network (Ethereum mainnet, Polygon, Arbitrum). Update the chain import in scripts/dfns.ts.Real stablecoins — Replace the demo StableCoin contract with USDC or EURC addresses. The Bond contract accepts any ERC-20 with 6 decimals as the settlement currency.Multiple investors — The system supports any number of investors. Each uses a separate Dfns wallet. Add more wallet IDs to .env or build a backend that maps users to Dfns wallets (see the bank-custody blueprint for this pattern).Secondary trading — Bond tokens are standard ERC-20 and can be traded on any DEX. For institutional use, consider an RFQ model (UniswapX or CowSwap) where professional market makers provide quotes based on yield-to-maturity.Approval policies — Dfns policies can enforce approval quorums or velocity limits on sensitive operations (closing issuance, large coupon deposits). This adds governance without changing the smart contracts.