Learning Objectives
By the end of this module, you will:- Design a confidential lending protocol with encrypted collateral and borrowing
- Implement encrypted order books for private trading
- Apply FHE to real-world DeFi use cases
- Handle complex multi-party encrypted interactions
- Understand the privacy vs. functionality trade-offs in DeFi
Why Confidential DeFi?
Decentralized finance has transformed how we think about financial services. Lending, trading, and asset management can now happen without intermediaries. But there’s a fundamental problem: everything is public. On a standard EVM blockchain, every transaction is visible to everyone: In traditional finance, trade privacy is the default. When you place a limit order at a brokerage, other participants don’t see your order until it’s executed. When you take out a loan at a bank, other customers don’t know your loan balance. FHE (Fully Homomorphic Encryption) brings this privacy to on-chain DeFi. With FHEVM, we can build lending protocols where collateral and borrow amounts are encrypted, and order books where prices and quantities are hidden until execution.Confidential Lending Protocol
Architecture Overview
A lending protocol has a straightforward lifecycle:
In our simplified model:
- Collateral is tracked per user as
euint64 - Borrow balance is tracked per user as
euint64 - LTV (Loan-to-Value) is 50%: you can borrow up to half your collateral
- Interest is 10% per accrual period (simplified)
Encrypted Collateral Management
Each user has two encrypted balances stored in mappings:Depositing Collateral
Depositing adds encrypted collateral to the user’s balance:- The user encrypts the amount client-side using
fhevm.createEncryptedInput() - The encrypted value and proof are sent to the contract
FHE.fromExternal()converts the external input to an internaleuint64FHE.add()adds it to the existing collateral (both encrypted)- ACL is updated for the new handle (every FHE operation produces a new handle)
The Collateralization Check with FHE
The core innovation is the on-chain collateralization check using encrypted values:borrowAmountis the encrypted amount the user wants to borrownewBorrowBalanceadds this to any existing borrow (also encrypted)maxBorrow = collateral / 2computes the maximum allowed borrow (encrypted division)withinLimit = FHE.le(newBorrowBalance, maxBorrow)checks the LTV constraint — this returns anebool(encrypted boolean)FHE.select(withinLimit, newBorrowBalance, _borrowBalance[msg.sender])conditionally updates the borrow balance
The critical insight: we cannot use
if/else on encrypted booleans. The result of FHE.le() is encrypted — we don’t know if it’s true or false. Instead, we use FHE.select() to pick between two encrypted values based on the encrypted condition.The LastError Pattern
In traditional Solidity, a failed borrow wouldrevert. But reverting leaks information:
Problem with revert
Problem with revert
Solution: silent failure
Solution: silent failure
Borrowed event is always emitted regardless of success. An observer only sees that a borrow attempt was made, but not whether it succeeded or how much was borrowed.
Interest Accrual on Encrypted Balances
Interest is calculated using FHE arithmetic:interest = borrowBalance / 10, then borrowBalance += interest.
Key observations:
- The interest amount is never revealed — it’s computed entirely on encrypted data
FHE.div()performs integer division on encrypted values- The owner (or a keeper) triggers interest accrual per user
- In production, you would batch this across all users or use a per-block accrual model
Withdrawal with Collateral Sufficiency Check
Withdrawing collateral requires checking that the remaining collateral still covers the borrow:FHE.and():
- Safety check:
remaining >= 2 * borrowBalanceensures 50% LTV is maintained - Underflow check:
withdrawAmount <= collateralprevents FHE subtraction underflow
Repayment
Repayment reduces the borrow balance:FHE.min() caps the repayment to the borrow balance. If the user tries to repay more than they owe, only the owed amount is subtracted. This prevents underflow without revealing the borrow balance.
Encrypted Order Book
Why Encrypted Order Books Matter
Traditional on-chain order books (like on Serum or dYdX v3) expose every order to everyone:Traditional Order Book (public)
Traditional Order Book (public)
Encrypted Order Book
Encrypted Order Book
Order Structure
Each order stores encrypted price and amount alongside public metadata:traderis public: Addresses are always visible on-chain (transaction sender)isBuyis public: The direction (buy vs sell) must be known to match ordersisActiveis public: Needed for validation without FHE overheadpriceandamountare encrypted: These are the sensitive valuesMAX_ACTIVE_ORDERS = 50: Prevents DoS from unbounded order storage
Order Submission
Buy and sell order submission follow the same pattern:Order Matching Logic
The matching function is the heart of the order book. It compares a buy order against a sell order:Price comparison
FHE.ge(buyPrice, sellPrice) checks if the buy price is at least as high as the sell price. This returns an ebool — we don’t know the result.Fill calculation
FHE.min(buyAmount, sellAmount) determines how much can be filled. If one order is for 100 units and the other for 60, the fill is 60.Conditional fill
FHE.select(canMatch, fillAmount, 0) makes the fill 0 if prices are incompatible. This is the key privacy mechanism — the fill either happens or it doesn’t, and nobody can tell which.Amount update
FHE.sub(amount, actualFill) reduces both orders by the fill amount. If actualFill is 0 (incompatible prices), the subtraction has no effect.What Is Public vs. Private
This is a critical distinction for any confidential DeFi protocol:| Information | Visibility | Why |
|---|---|---|
| Order exists | Public | Transaction is on-chain |
| Trader address | Public | msg.sender is always visible |
| Buy/sell direction | Public | Stored as plaintext bool for matching efficiency |
| Order price | Private | Encrypted euint64 |
| Order amount | Private | Encrypted euint64 |
| Fill amount | Private | Computed with FHE.min and FHE.select |
| Whether match succeeded | Private | actualFill could be 0 or non-zero; only traders know |
| Order cancellation | Public | Changes isActive flag |
OrderMatched event is emitted regardless of whether the match actually filled. An observer sees that a match was attempted between two order IDs, but not whether it succeeded or how much was filled.
Order Cancellation
Traders can cancel their own orders:Privacy Trade-offs in DeFi
What You CAN Keep Private
With FHE, the following can remain encrypted:- Amounts: Collateral deposits, borrow amounts, order quantities, fill sizes
- Prices: Limit order prices, liquidation thresholds, interest amounts
- Balances: User balances, collateral ratios, debt levels
- Comparisons: Whether a borrow is within LTV, whether orders matched
What You CANNOT Hide
Even with FHE, some information is inherently public on any blockchain:- Addresses:
msg.senderis always visible. Everyone knows who is interacting with the protocol. - Function calls: Which function was called and when. An observer knows you called
borrow()even if they don’t know the amount. - Timing: When you placed an order, when you repaid, how frequently you interact.
- Gas usage: Different FHE operations use different gas amounts, which can sometimes leak information about the code path taken.
- Transaction count: How many orders a trader has placed.
Hybrid Approaches
In practice, confidential DeFi protocols use a hybrid approach:- Your bank knows your balance (encrypted on-chain)
- The public knows you have a bank account (address interaction)
- Aggregate statistics are published (total deposits)
Gas Costs and Optimization
FHE operations are significantly more expensive than plaintext operations:- Batching operations (e.g., accrue interest for multiple users in one transaction)
- Reducing FHE operations per function call
- Using smaller encrypted types (
euint8,euint16) where the value range allows - Caching intermediate FHE results across function calls
Production Considerations
Compliance
A common concern with privacy protocols is regulatory compliance. FHE-based DeFi can support compliance through:- KYC gates: Require address whitelisting before interaction (plaintext check before encrypted operations)
- Auditor access: Grant specific addresses ACL access to encrypted balances via
FHE.allow(handle, auditor) - Threshold reporting: Use FHE comparison to flag large transactions without revealing exact amounts
- Selective disclosure: Users can choose to make their own balances publicly decryptable
Liquidation Challenges
Liquidation in confidential lending is fundamentally harder:Traditional Lending
Traditional Lending
Confidential Lending
Confidential Lending
Summary
Confidential lending
Encrypts collateral and borrow balances, enforcing LTV with
FHE.le() and FHE.select()Encrypted order books
Hide prices and amounts while allowing on-chain matching with
FHE.ge() and FHE.min()LastError pattern
Avoids information leakage by using
FHE.select() instead of revertPrivacy trade-offs
Amounts and prices can be private; addresses, timing, and function calls cannot
Gas costs
10-15x higher than plaintext DeFi — optimization matters
Real-world DeFi
Eliminating front-running, MEV extraction, and information asymmetry
Production Example: Zaiffer Protocol (a Zama + PyratzLabs joint venture) is building ZaifferSwaps (MEV-protected trading with encrypted order amounts) and ZaifferYields (confidential yield vaults) using the exact patterns covered in this module. Zama’s 2026 roadmap includes cUSDT/cUSDC/cETH yield integration with AAVE and Morpho — demonstrating real market demand for confidential DeFi. The ERC-7984 standard (co-developed by Zama and OpenZeppelin) formalizes the confidential token interface that underpins these products.
Reference Contracts
- ConfidentialLending.sol (
contracts/18-confidential-defi/ConfidentialLending.sol:1) — Privacy-preserving lending protocol - EncryptedOrderBook.sol (
contracts/18-confidential-defi/EncryptedOrderBook.sol:1) — Order book with encrypted prices and amounts