Development of a Stablecoin with CDP (Collateralized Debt Position)
MakerDAO launched DAI in 2017 with mechanics that remain viable today: user locks ETH, receives DAI against collateral, pays stability fee. This is CDP — Collateralized Debt Position. Since then mechanics evolved, but basic invariants unchanged: stablecoin backed by real assets, system must remain solvent at any market movement.
Developing a custom CDP stablecoin — task for several months even for experienced teams. Not because individual components are complex, but because of systemic dependencies: oracle, liquidation engine, stability fee accumulation, governance — each component is critical, and one failure destroys entire system.
Three Invariants: Breaking Them Kills the System
Over-collateralization and Liquidation Ratio
CDP stablecoin works only if collateral value always exceeds debt value with sufficient buffer. Minimum collateralization ratio (CR) determined by asset volatility:
| Asset | Minimum CR | Reasoning |
|---|---|---|
| ETH | 150% | Volatility ~80% annualized |
| WBTC | 150% | Similar to ETH |
| stETH | 160% | Additional depegging risk |
| USDC | 102% | Stable asset, minimum buffer |
| LP tokens | 200%+ | Oracle complexity, impermanent loss |
If CR drops below liquidation ratio — position must be liquidated immediately. One block delay during flash crash means bad debt: collateral became cheaper than debt. System incurs loss.
Oracle Manipulation — Main Attack Vector
Black Thursday 2020: ETH dropped from $200 to $80 in hours. Chainlink feeds couldn't update fast enough, some positions liquidated at stale prices. MakerDAO incurred $4M bad debt.
Modern CDP systems use two-level oracle:
Primary oracle: Chainlink — median from 31+ nodes, updates every 60 seconds or on 0.5% deviation. High reliability, but latency during sharp moves.
Circuit Breaker oracle: on-chain TWAP from Uniswap v3 (30-minute window). If Chainlink price deviates from TWAP >20% — system enters Emergency Shutdown or freezes new CDPs.
Oracle Security Module (OSM) from MakerDAO — pattern worth adopting: price update applies with 1-hour delay. During that time governance can respond to oracle attack.
Stability Fee Accumulation and DSR
Stability fee — percentage accrued on debt every second. Correct implementation via rate accumulator (chi in Maker terms): each access to position, chi updates:
chi_new = chi_old * (1 + stabilityFee)^(block.timestamp - lastUpdate)
User debt stored as normalizedDebt (units before chi multiplication). Real debt = normalizedDebt * chi. Lets accrue interest to all CDPs simultaneously without iterating — critical with thousands active CDPs.
Error in accumulator logic — most expensive: either fees not accrued (protocol insolvent) or accrued incorrectly (users overpay/underpay).
CDP Protocol Architecture
Modular Contract Structure
Monolithic CDP contract doesn't fit — too complex, too high risk. Reference architecture:
Vat (Core CDP engine) — holds all positions, calculates collateral and debt, knows collateralization ratio. Only pure accounting — no business logic.
Spot (Oracle module) — accepts prices from oracles, recalculates into liquidation price per collateral type. Vat reads from Spot.
Jug (Fee accumulator) — updates drip() per collateral type, accumulates stability fee in Vat.
Dog/Cat (Liquidation trigger) — checks positions, starts auctions. Dog — auction liquidator (Maker v2); simpler pattern — fixed-spread liquidation like in Aave.
Clip (Auction) — Dutch auction: price starts at premium, linearly decreases. Liquidator first accepting price — gets collateral. Better mechanism than fixed-bonus in deep markets.
PSM (Peg Stability Module) — exchange DAI 1:1 for USDC without fee (or micro-fee). Key peg mechanism: arbitrage immediately restores peg on deviation.
Liquidation in Detail: Dutch Auction
When CR drops below liquidation ratio, Dog creates auction in Clip. Parameters:
-
buf— initial premium (e.g., 120% of oracle price) -
tail— maximum auction duration -
cusp— minimum allowed price drop (0.4 = 40% from start) -
chip— flash loan incentive for liquidators
Liquidator calls take(id, amt, max): buys amt collateral at price ≤ max. Remaining debt repaid, collateral surplus returned to position owner.
Edge case: auction expires (tail/cusp reached), collateral not bought? Redo restarts auction at new oracle price. Critical if price continues dropping.
Emergency Shutdown
Any CDP system must have orderly exit mechanism. ESM (Emergency Shutdown Module) lets governance token holders burn tokens to activate shutdown. After activation:
- New CDPs blocked
- Prices fixed by oracle at shutdown moment
- Users can redeem collateral at fixed rate
- All auctions complete
Without ESM no mechanism to exit on systemic failure.
Common Development Errors
Flash loan attack via oracle. Using on-chain TWAP with short window (1–5 minutes) — flash loan can briefly shift price, open CDP at inflated collateral price, withdraw funds, return flash loan. Solution: TWAP minimum 30-minute window or Chainlink with OSM.
Reentrancy in liquidation callback. Liquidator gets callback after collateral receipt. If system not locked — reentrancy via repeated take calls. All liquidation functions protected by mutex at Vat level.
Uncapped accumulated debt. Without per-collateral type debt ceiling, one asset dominates protocol backing. If that asset drops — entire system threatened. Parameters line (debt ceiling per collateral) and Line (global ceiling) — mandatory elements.
Development Process
Tokenomics and Parameters Design (1–2 weeks): liquidation ratios, stability fee model, PSM parameters, debt ceilings. These decisions fundamental — hard to change after launch.
Core Contract Development (4–6 weeks): Vat, Spot, Jug, Dog, Clip, PSM, ESM. Each contract — separate unit test suite.
Oracle Integration (1 week): Chainlink + TWAP circuit breaker, OSM with delay.
Governance (1–2 weeks): TimelockController, voting parameters, emergency roles.
Testing and Audit (3–4 weeks): Fuzz tests of invariants via Foundry, black swan scenario simulation, external audit mandatory before mainnet.
Deployment and Monitoring (1 week): staged rollout with low debt ceilings at start, Grafana monitoring of health metrics.
Total: 2–3 months for production-ready CDP system. Cost calculated individually after tokenomics design.







