Get the code
dfns/dfns-solutions: bond-issuance
Overview
The system models a bond issuance with two actors:- Issuer: deploys the bond contract, manages the lifecycle (close issuance, fund coupons, return principal)
- Investor: subscribes with stablecoins, claims bond tokens, collects coupons, redeems at maturity
- The Issuer deploys a stablecoin (EURC) and the Bond contract
- Investors subscribe by depositing EURC into escrow
- The Issuer closes the issuance. The interest accrual clock starts
- Investors claim ERC-20 bond tokens proportional to their investment
- Each coupon period, the Issuer funds and Investors claim their pro-rata share
- At maturity, the Issuer deposits principal and Investors redeem bonds for EURC
Prerequisites
- A DFNS account with a service account for API access
- Two DFNS wallets on Ethereum Sepolia (Issuer and Investor)
- Node.js v22+
- Testnet ETH in both wallets for gas fees (use a Sepolia faucet)
Project Structure
Configuration
1
Clone and install
2
Set up environment variables
Copy the example environment file and fill in your values:
.env
3
Compile contracts
4
Run tests
The test suite runs against a local Hardhat network (no DFNS credentials needed):16 tests cover the full lifecycle: subscription, over/under-subscription, coupon claims, redemption, grace periods, default triggering, and interest math.
Deploy
Step 1: Deploy the stablecoin
Step 2: Mint stablecoin to the investor
Step 3: Deploy the bond
Save the bond contract address.
End-to-End Bond Lifecycle
Step 1: Investor subscribes
subscribe(). The stablecoin is held in escrow.
Step 2: Issuer closes issuance
Step 3: Issuer withdraws proceeds
Step 4: Investor claims bond tokens
decimals is 6 (matching the stablecoin).
Step 5: Coupon payments (each period)
Issuer deposits the coupon:(totalPrincipal * APR * frequency) / (365 days * 10000).
Investor claims:
Step 6: Redemption at maturity
Issuer returns principal:Web UI
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.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
- Claim Coupon: investor collects pro-rata interest (auto-detects coupon index)
- Return Principal: issuer deposits EURC for redemption
- Redeem: investor burns bonds, gets principal back
End-to-End Script
Run the full lifecycle non-interactively:Smart Contract Reference
Bond.sol
An ERC-20 token representing a corporate bond with full lifecycle management:
Bond lifecycle:
Open → Issuance Closed → Coupons → Maturity / Redemption
Default path: Coupon Due → Grace Period (5 days) → Default
BondMath.sol
Library for interest calculations:StableCoin.sol
ERC-20 stablecoin used as the settlement currency:How DFNS Is Used
All on-chain transactions are signed and broadcast through the DFNS API. No private keys are stored locally.
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.
Adapting for Production
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 accept cryptocurrencies 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.