Section 1 of 15
Introduction to Liquity V1
Key takeaway: This module is the full Liquity V1 reconstruction at Zealynx Academy. Across 15 sections you write every function in the core protocol (TroveManager, BorrowerOperations, StabilityPool, ActivePool, DefaultPool, SortedTroves, LUSDToken, LQTYStaking) modernized to Solidity 0.8.x. The result is a deployable CDP stablecoin: users open a Trove by depositing ETH, borrow LUSD against it at a one-time 0.5% fee, and the system stays solvent through three independent mechanisms — Stability Pool offset, debt redistribution, and redemptions at face value. No governance. No interest rate. No oracle wrapper. The cleanest CDP design in DeFi.
What You Are Building
You are going to build the actual Liquity V1 protocol. Not a simplified CDP. Not a toy. The real thing.
Liquity V1 was deployed on Ethereum mainnet in April 2021 and has been running continuously since — through the 2022 bear, the 2023 banking crisis, and every ETH crash in between — without governance intervention, without parameter changes, without admin keys. The LUSD stablecoin has held its peg through it all. Dozens of stablecoin protocols have forked this architecture: Lybra, Prisma, Raft, Gravita, Felix. When people say "Liquity-style stablecoin," they mean the architecture you are about to build.
By the end of this module, you will have written every function in the protocol. You will understand why the 110% Minimum Collateral Ratio is so low (other CDP systems use 150%+), why the Stability Pool's P/S decay is the most elegant per-share reward accounting in DeFi, and why redemptions hurt individual Troves but help the whole system. You will have a complete, deployable codebase you can fork for your own stablecoin.
The Architecture
Liquity V1 splits into ten contracts. You will build all of them.
TroveManager is the heart of the protocol. It stores every Trove (collateral, debt, owner), runs liquidations, executes redemptions, and tracks the running terms (L_ETH, L_LUSDDebt, baseRate) that let the system distribute losses and fees to remaining Troves without iterating over them. Most of the math in the protocol lives here.
BorrowerOperations is the user-facing entry point for everything except liquidation and redemption. Users call openTrove, addColl, withdrawColl, withdrawLUSD, repayLUSD, adjustTrove, and closeTrove through this contract. It enforces the safety rules — Minimum Collateral Ratio, Total Collateral Ratio, Recovery Mode restrictions — and orchestrates calls into TroveManager, the pools, and the LUSDToken.
StabilityPool holds the LUSD that absorbs liquidated debt. Depositors lock LUSD and receive a share of the collateral from every liquidation that the pool offsets. The accounting uses a multiplicative running product P (tracking compounded balance) and an additive running sum S (tracking ETH gains per LUSD originally deposited). Both update in O(1) per liquidation, and any depositor's current balance and accumulated gain are derivable from a single snapshot taken at deposit time. This is the most pedagogically dense piece of code in any Build module.
ActivePool holds the ETH backing active Troves and tracks the total LUSD debt outstanding. DefaultPool holds redistributed ETH and debt waiting to be claimed by remaining Troves after a redistribution-style liquidation. The split exists for clean accounting — active vs. pending — not for any access-control reason.
SortedTroves is a doubly-linked list of every active Trove, sorted by Nominal Individual Collateral Ratio (NICR) ascending. Liquidations and redemptions both iterate from the tail (lowest NICR first), so this data structure is what makes both O(k) in the number of Troves touched rather than O(n) in the system.
LUSDToken is the stablecoin itself — a standard ERC-20 with EIP-2612 permit and a tight allowlist controlling which protocol contracts can mint and burn. Only TroveManager, BorrowerOperations, and StabilityPool ever touch supply.
LQTYStaking distributes the protocol's revenue — borrowing fees in LUSD and redemption fees in ETH — to LQTY stakers. It uses an additive running sum (F_LUSD, F_ETH) that is structurally the opposite of the Stability Pool's multiplicative P. Side-by-side these two contracts are a textbook contrast between the two shapes of per-share reward accounting.
CollSurplusPool holds leftover collateral from Recovery Mode liquidations and full-debt redemptions, claimable by the original Trove owner. GasPool holds the 200 LUSD per-Trove gas-compensation deposits that get paid to liquidators.
How This Module Works
This is not a tutorial. You are replicating a production protocol.
Each section gives you the contract scaffolding — declarations, state variables, events, imports, stubs for functions implemented elsewhere. Your job is to write the function bodies. The math. The validation. The state transitions. The parts that make the protocol work.
The starter code has TODO blocks where you need to write. Each TODO explains what the function should do, but not how. That's for you to figure out. When you are done, run the tests to verify your implementation matches the actual Liquity V1 behavior.
If you get stuck, you can reveal the reference implementation. This is the actual Liquity V1 code, modernized to Solidity 0.8.x. Compare your solution to theirs. Understand the differences.
About the Code
The original Liquity V1 protocol was written in Solidity 0.6.11 and deployed in April 2021. We have modernized it to Solidity 0.8.20 with these changes:
- SafeMath removed. Every
.add(),.sub(),.mul(),.div()call disappears — Solidity 0.8.x checks arithmetic by default. TheLiquityMathlibrary shrinks from 80 lines to 60. nowreplaced withblock.timestamp. Thenowkeyword was removed in 0.7.0; the LUSDToken's permit deadline and the TroveManager's fee timestamps use the explicit form.uint(-1)replaced withtype(uint256).max. Used to represent the "infinite collateral ratio" for a Trove with zero debt.- Constructor visibility removed. 0.8.x no longer accepts explicit visibility on constructors.
block.chainidbuiltin replaces assembly. The LUSDToken permit's EIP-712 chain-ID cache uses the language-level builtin instead of inlinechainid()assembly.- Reentrancy guards added. Liquity V1 omitted a generic
ReentrancyGuardand relied on careful CEI ordering and trusted-caller restrictions. The academy module adds an inlinenonReentrantmutex (matching the Uniswap V2 module's style) to every external user-facing function. The pools' internal ETH sends still use CEI — the mutex is defense-in-depth. - PriceFeed simplified to a mock. The production 5-state Chainlink + Tellor FSM is replaced with a 12-line
MockPriceFeedexposingsetPriceandfetchPrice. The original is recommended reading; rebuilding it is the subject of an optional advanced module. - HintHelpers dropped. Production Liquity ships an off-chain hint contract that gives
SortedTroves.insertan O(1) starting point. The academy walks from head; with the small Trove counts in tests, the gas difference is invisible. - LQTY governance/issuance layer dropped. The LQTYToken simplifies to a non-transferable stake-tracking ERC-20 used only as the input to LQTYStaking. CommunityIssuance (the LQTY emission curve to Stability Pool depositors) and the
Gaccumulator are removed because theGmath is structurally identical toS— teaching it twice is duplicate. Borrowing and redemption fees still flow to the staking contract. - Frontend operator tags dropped from
provideToSP. Without LQTY emissions there is nothing for the frontend kickback to apportion. setAddressesceremony replaced with constructor immutables. Liquity's production contracts used a deploy-then-wire-then-renounce-ownership pattern because circular dependencies prevented setting addresses in constructors. The academy resolves the order at deploy time and every protocol address becomesimmutable. This eliminates an entire ownership-management subsystem.
Everything else stays the same. The CDP mechanics — MCR = 110%, CCR = 150%, MIN_NET_DEBT = 1800 LUSD, LUSD_GAS_COMPENSATION = 200 LUSD, the redemption fee formula, the base-rate decay (half-life ≈ 12 hours), the Stability Pool offset math, the doubly-linked SortedTroves data structure, the Active/Default/CollSurplus pool split — are byte-identical to the deployed protocol. The function signatures, the require strings, the storage layout, the event signatures are all preserved. When you finish this module, your code matches the deployed Liquity V1 logic wherever the protocol logic lives; what changes is the language-level scaffolding, not the protocol itself.
The source code is licensed under MIT, which means you can fork it, modify it, and deploy your own version. Several active stablecoin protocols have done exactly that — Liquity's design is one of the most successful CDP architectures in DeFi history, and forks remain the standard reference for any team building a stablecoin against a single collateral type.
What You Will Learn
By building this protocol yourself, you will understand:
- Why the 110% MCR is a competitive feature, not a risk — and what makes it possible
- How the Stability Pool's
P(product) andS(sum) terms distribute liquidation losses and gains in O(1) per event - Why the
SCALE_FACTORexists and when it fires (typically after 99.99%+ pool depletion in a single liquidation) - How
L_ETHandL_LUSDDebtrunning terms redistribute losses to remaining Troves without touching their storage - Why
totalStakesSnapshotandtotalCollateralSnapshotare necessary — and what breaks without them - How redemptions arbitrage LUSD back to $1 by burning LUSD for ETH at face value, hitting the riskiest Troves first
- Why the base rate decays over a 12-hour half-life using exponentiation-by-squaring in fixed-point math
- How Recovery Mode (TCR < 150%) changes the liquidation rules to restore the system
- Why the additive
F_LUSD/F_ETHdistribution in LQTYStaking is the opposite shape of the Stability Pool's multiplicativeP - How the protocol stays solvent and pegged with zero governance, zero interest rates, and zero admin keys after deployment
These are not theoretical concepts. They are implementation details that matter when you audit, fork, or build on top of this code.
Knowledge Check
Answer correctly to earn lynx
What is the protocol-owned mechanism that absorbs liquidated Trove debt instantly, without auctions, keepers, or external liquidator bids?
Two words. Depositors lock LUSD here and receive a share of liquidated ETH in return.