SECTION 1: LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Define Decentralised Finance (DeFi) and its core principles.
-
Explain the key components of the DeFi ecosystem.
-
Understand how DeFi protocols work (lending, DEXs, derivatives).
-
Differentiate between DeFi and traditional finance (CeFi).
-
Describe yield farming, staking, and liquidity provision.
-
Identify risks and challenges in DeFi.
-
Implement a simplified DeFi protocol simulation in Python.
-
Develop a framework for evaluating DeFi protocols.
SECTION 2: WHAT IS DEFI?
2.1 Definition
Decentralised Finance (DeFi) is a financial ecosystem built on blockchain technology that offers open, permissionless, and transparent financial services without intermediaries. DeFi uses smart contracts to automate financial functions traditionally performed by banks, brokers, and exchanges.
2.2 Core Principles
┌─────────────────────────────────────────────────────────────────────────────┐ │ CORE PRINCIPLES OF DEFI │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ PERMISSIONLESS │ │ │ │ Anyone can access DeFi services without approval or KYC. │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ TRANSPARENT │ │ │ │ All transactions and code are visible on the blockchain. │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ NON-CUSTODIAL │ │ │ │ Users retain control of their assets and private keys. │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ COMPOSABLE │ │ │ │ Protocols can be combined like Lego bricks. │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ TRUSTLESS │ │ │ │ Relies on code and consensus, not trusted intermediaries. │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
SECTION 3: THE DEFI ECOSYSTEM
3.1 DeFi Ecosystem Map
┌─────────────────────────────────────────────────────────────────────────────┐ │ DEFI ECOSYSTEM │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ LENDING & BORROWING │ │ │ │ Protocols that enable lending and borrowing of assets. │ │ │ │ Examples: Aave, Compound, MakerDAO │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ DECENTRALISED EXCHANGES (DEXs) │ │ │ │ Peer-to-peer trading without order books. │ │ │ │ Examples: Uniswap, SushiSwap, Curve │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ DERIVATIVES │ │ │ │ Options, futures, and synthetic assets. │ │ │ │ Examples: Synthetix, dYdX, GMX │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ STABLECOINS │ │ │ │ Price-stable cryptocurrencies. │ │ │ │ Examples: DAI, USDC, USDT │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ YIELD AGGREGATORS │ │ │ │ Automate yield farming strategies. │ │ │ │ Examples: Yearn Finance, Convex │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ INSURANCE │ │ │ │ Smart contract coverage and risk protection. │ │ │ │ Examples: Nexus Mutual, Cover │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
3.2 DeFi vs Traditional Finance (CeFi)
| Aspect | DeFi | Traditional Finance (CeFi) |
|---|---|---|
| Access | Anyone, anytime | Requires approval/account |
| Custody | User-controlled | Institution-controlled |
| Transparency | Fully on-chain | Proprietary |
| Speed | Near-instant | 1-3 days |
| Cost | Gas fees (variable) | Service fees, spreads |
| Privacy | Pseudonymous | Full KYC/AML |
| Innovation | Rapid, experimental | Slow, regulated |
| Trust | Code/consensus | Institutions |
SECTION 4: KEY DEFI PROTOCOLS
4.1 Lending Protocols (Aave/Compound)
┌─────────────────────────────────────────────────────────────────────────────┐ │ LENDING PROTOCOL FLOW │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ SUPPLIER (Lender) │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ 1. Deposit assets into lending pool │ │ │ │ 2. Receive aTokens / cTokens (interest-bearing) │ │ │ │ 3. Earn interest from borrowers │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ LENDING POOL │ │ │ │ • Pooled liquidity │ │ │ │ • Algorithmic interest rates │ │ │ │ • Collateral management │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ BORROWER │ │ │ │ │ v │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ 1. Deposit collateral (over-collateralised) │ │ │ │ 2. Borrow assets (up to borrowing power) │ │ │ │ 3. Pay interest (variable/stable) │ │ │ │ 4. Liquidation if collateral value drops │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
4.2 Automated Market Makers (Uniswap)
AMM Formula (Constant Product):
x × y = k Where: x = amount of Token A y = amount of Token B k = constant Price = x / y (actually, y/x for price of x in terms of y)
4.3 Yield Farming
Yield farming involves providing liquidity to DeFi protocols in exchange for rewards (usually governance tokens and fees).
Strategies:
-
Liquidity Provision: Supply assets to a DEX pool.
-
Staking: Lock tokens in a protocol for rewards.
-
Compound Farming: Use rewards to earn more rewards.
-
Arbitrage: Exploit price differences across protocols.
SECTION 5: DEFI RISKS
| Risk | Description | Mitigation |
|---|---|---|
| Smart Contract Risk | Bugs or exploits in contract code | Audits, bug bounties, insurance |
| Impermanent Loss | Loss compared to holding assets | Understand AMM mechanics |
| Liquidity Risk | Inability to exit positions | Check liquidity depth |
| Oracle Manipulation | False price data leading to liquidations | Decentralised oracles, TWAP |
| Protocol Governance Risk | Governance attacks | Decentralised governance, time-locks |
| Regulatory Risk | Uncertainty in legal treatment | Monitor regulatory developments |
| Scams/Fraud | Rug pulls, honeypots | Due diligence, audits |
SECTION 6: IMPLEMENTATION IN PYTHON
# =================================================================== # MODULE 2, LESSON 3: DEFI ECOSYSTEM AND PROTOCOLS # =================================================================== import hashlib import time import random import math from typing import Dict, List, Optional, Tuple import pandas as pd import matplotlib.pyplot as plt import numpy as np import warnings warnings.filterwarnings('ignore') print("="*70) print("DEFI ECOSYSTEM AND PROTOCOLS") print("="*70) # ---------------------------------------------------------------- # PART A: LENDING PROTOCOL SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART A: Lending Protocol Simulation") print("-"*60) class LendingPool: def __init__(self, name: str, reserve_asset: str): self.name = name self.reserve_asset = reserve_asset self.total_liquidity = 0 self.total_borrowed = 0 self.utilization_rate = 0 self.interest_rate = 0.02 # 2% base rate self.suppliers: Dict[str, float] = {} self.borrowers: Dict[str, Dict] = {} self.history = [] def deposit(self, user: str, amount: float) -> bool: self.total_liquidity += amount self.suppliers[user] = self.suppliers.get(user, 0) + amount self.update_utilization() self.history.append({ 'type': 'deposit', 'user': user, 'amount': amount, 'timestamp': time.time() }) print(f"Deposited {amount} {self.reserve_asset} into {self.name}") return True def borrow(self, user: str, amount: float, collateral: float) -> bool: # Over-collateralised borrowing if collateral * 0.75 < amount: # 75% LTV print(f"Collateral insufficient. Need {amount/0.75:.2f}, provided {collateral}") return False if self.total_liquidity - self.total_borrowed < amount: print("Insufficient liquidity in pool") return False self.total_borrowed += amount self.borrowers[user] = { 'amount': amount, 'collateral': collateral, 'timestamp': time.time() } self.update_utilization() self.history.append({ 'type': 'borrow', 'user': user, 'amount': amount, 'collateral': collateral, 'timestamp': time.time() }) print(f"Borrowed {amount} {self.reserve_asset} with {collateral} collateral") return True def repay(self, user: str, amount: float) -> bool: if user not in self.borrowers: print("No loan found") return False if amount > self.borrowers[user]['amount']: amount = self.borrowers[user]['amount'] self.borrowers[user]['amount'] -= amount self.total_borrowed -= amount if self.borrowers[user]['amount'] <= 0: del self.borrowers[user] self.update_utilization() self.history.append({ 'type': 'repay', 'user': user, 'amount': amount, 'timestamp': time.time() }) print(f"Repaid {amount} {self.reserve_asset}") return True def update_utilization(self): if self.total_liquidity == 0: self.utilization_rate = 0 else: self.utilization_rate = self.total_borrowed / self.total_liquidity # Interest rate increases with utilization self.interest_rate = 0.02 + self.utilization_rate * 0.10 def get_metrics(self) -> Dict: return { 'name': self.name, 'total_liquidity': self.total_liquidity, 'total_borrowed': self.total_borrowed, 'utilization_rate': self.utilization_rate, 'interest_rate': self.interest_rate, 'num_suppliers': len(self.suppliers), 'num_borrowers': len(self.borrowers) } # Create lending pool pool = LendingPool("Digital Lending Vault", "ETH") # Simulate activity print("Lending Pool Simulation:") pool.deposit("Alice", 100) pool.deposit("Bob", 150) pool.borrow("Charlie", 50, 75) pool.borrow("David", 30, 50) pool.repay("Charlie", 50) print("\nPool Metrics:") metrics = pool.get_metrics() for k, v in metrics.items(): print(f" {k}: {v}") # Visualise utilization and interest utilization_rates = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] interest_rates = [0.02 + u * 0.10 for u in utilization_rates] fig, ax = plt.subplots(figsize=(8, 4)) ax.plot(utilization_rates, interest_rates, marker='o', color='blue') ax.set_xlabel('Utilization Rate') ax.set_ylabel('Interest Rate') ax.set_title('Lending Protocol: Interest Rate Model') ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('lending_interest_model.png', dpi=300, bbox_inches='tight') plt.show() print("Interest rate model chart saved as 'lending_interest_model.png'") # ---------------------------------------------------------------- # PART B: AMM / DEX SIMULATION (Uniswap-style) # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART B: Automated Market Maker (AMM) Simulation") print("-"*60) class AMMPool: def __init__(self, token_a: str, token_b: str, reserve_a: float, reserve_b: float): self.token_a = token_a self.token_b = token_b self.reserve_a = reserve_a self.reserve_b = reserve_b self.k = reserve_a * reserve_b self.fee = 0.003 # 0.3% self.liquidity_providers: Dict[str, Dict] = {} self.total_liquidity = reserve_a + reserve_b # Simplified self.swap_history = [] def get_price(self, base_token: str) -> float: if base_token == self.token_a: return self.reserve_b / self.reserve_a else: return self.reserve_a / self.reserve_b def swap_a_for_b(self, user: str, amount_a: float) -> Optional[float]: # Swap token A for token B if amount_a > self.reserve_a: print("Insufficient reserve A") return None # Calculate amount out with fee amount_a_with_fee = amount_a * (1 - self.fee) amount_b_out = self.reserve_b * (amount_a_with_fee / (self.reserve_a + amount_a_with_fee)) # Update reserves self.reserve_a += amount_a self.reserve_b -= amount_b_out self.k = self.reserve_a * self.reserve_b self.swap_history.append({ 'user': user, 'direction': f'{self.token_a}→{self.token_b}', 'amount_in': amount_a, 'amount_out': amount_b_out, 'timestamp': time.time() }) print(f"Swapped {amount_a:.2f} {self.token_a} for {amount_b_out:.2f} {self.token_b}") return amount_b_out def swap_b_for_a(self, user: str, amount_b: float) -> Optional[float]: if amount_b > self.reserve_b: print("Insufficient reserve B") return None amount_b_with_fee = amount_b * (1 - self.fee) amount_a_out = self.reserve_a * (amount_b_with_fee / (self.reserve_b + amount_b_with_fee)) self.reserve_b += amount_b self.reserve_a -= amount_a_out self.k = self.reserve_a * self.reserve_b self.swap_history.append({ 'user': user, 'direction': f'{self.token_b}→{self.token_a}', 'amount_in': amount_b, 'amount_out': amount_a_out, 'timestamp': time.time() }) print(f"Swapped {amount_b:.2f} {self.token_b} for {amount_a_out:.2f} {self.token_a}") return amount_a_out def add_liquidity(self, user: str, amount_a: float, amount_b: float) -> bool: # Simplified: add proportional liquidity current_ratio = self.reserve_a / self.reserve_b if amount_a / amount_b != current_ratio: print("Warning: Not proportional, adjust amount") # Adjust to maintain ratio if amount_a / amount_b > current_ratio: amount_a = amount_b * current_ratio else: amount_b = amount_a / current_ratio self.reserve_a += amount_a self.reserve_b += amount_b self.k = self.reserve_a * self.reserve_b self.liquidity_providers[user] = { 'amount_a': self.liquidity_providers.get(user, {}).get('amount_a', 0) + amount_a, 'amount_b': self.liquidity_providers.get(user, {}).get('amount_b', 0) + amount_b, 'share': (amount_a + amount_b) / (self.reserve_a + self.reserve_b) } print(f"Added liquidity: {amount_a:.2f} {self.token_a}, {amount_b:.2f} {self.token_b}") return True def get_metrics(self) -> Dict: return { 'reserve_a': self.reserve_a, 'reserve_b': self.reserve_b, 'k': self.k, 'price_a_in_b': self.get_price(self.token_a), 'price_b_in_a': self.get_price(self.token_b), 'num_lps': len(self.liquidity_providers), 'num_swaps': len(self.swap_history) } # Create AMM amm = AMMPool("ETH", "USDC", 100, 200000) # ETH price = 2000 USDC print("AMM Pool Created: 100 ETH, 200,000 USDC") print(f"ETH Price: {amm.get_price('ETH'):.2f} USDC") # Simulate trades print("\n--- Swaps ---") amm.swap_a_for_b("Alice", 5) # Swap 5 ETH for USDC amm.swap_b_for_a("Bob", 2000) # Swap 2000 USDC for ETH print("\n--- Add Liquidity ---") amm.add_liquidity("Charlie", 10, 20000) print("\n--- Pool Metrics ---") metrics = amm.get_metrics() for k, v in metrics.items(): print(f" {k}: {v}") # ---------------------------------------------------------------- # PART C: YIELD FARMING SIMULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART C: Yield Farming Simulation") print("-"*60) class YieldFarm: def __init__(self, name: str, reward_token: str, reward_rate: float): self.name = name self.reward_token = reward_token self.reward_rate = reward_rate # per day self.stakers: Dict[str, Dict] = {} self.total_staked = 0 self.rewards_distributed = 0 def stake(self, user: str, amount: float, asset: str) -> bool: if user in self.stakers: self.stakers[user]['amount'] += amount else: self.stakers[user] = { 'amount': amount, 'asset': asset, 'stake_time': time.time(), 'rewards_claimed': 0 } self.total_staked += amount print(f"Staked {amount} {asset} in {self.name}") return True def calculate_rewards(self, user: str, days: int) -> float: if user not in self.stakers: return 0 amount = self.stakers[user]['amount'] base_reward = amount * self.reward_rate * days # Add compounding effect (simplified) return base_reward def claim_rewards(self, user: str, days: int) -> float: if user not in self.stakers: return 0 rewards = self.calculate_rewards(user, days) self.rewards_distributed += rewards self.stakers[user]['rewards_claimed'] += rewards print(f"Claimed {rewards:.2f} {self.reward_token} from {self.name}") return rewards def get_metrics(self) -> Dict: return { 'name': self.name, 'total_staked': self.total_staked, 'num_stakers': len(self.stakers), 'rewards_distributed': self.rewards_distributed, 'daily_apy': self.reward_rate * 365 * 100 } # Create yield farm farm = YieldFarm("Green Yield Vault", "YIELD", 0.001) # 0.1% per day = ~36.5% APY print("Yield Farm Simulation:") farm.stake("Alice", 1000, "ETH") farm.stake("Bob", 500, "ETH") farm.stake("Charlie", 2000, "ETH") # Simulate earning rewards print(f"\nDaily reward rate: {farm.reward_rate * 100:.2f}%") alice_rewards = farm.calculate_rewards("Alice", 30) bob_rewards = farm.calculate_rewards("Bob", 30) charlie_rewards = farm.calculate_rewards("Charlie", 30) print(f"Alice 30-day rewards: {alice_rewards:.2f} YIELD") print(f"Bob 30-day rewards: {bob_rewards:.2f} YIELD") print(f"Charlie 30-day rewards: {charlie_rewards:.2f} YIELD") # Claim rewards farm.claim_rewards("Alice", 30) print("\nFarm Metrics:") metrics = farm.get_metrics() for k, v in metrics.items(): print(f" {k}: {v}") # ---------------------------------------------------------------- # PART D: DEFI PROTOCOL COMPARISON # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART D: DeFi Protocol Comparison") print("-"*60) defi_protocols = pd.DataFrame({ 'Protocol': [ 'Aave', 'Compound', 'Uniswap', 'MakerDAO', 'Yearn', 'Synthetix', 'Curve' ], 'Category': [ 'Lending', 'Lending', 'DEX', 'Stablecoin', 'Yield Aggregator', 'Derivatives', 'DEX (Stable)' ], 'TVL (B USD)': [4.5, 2.8, 6.2, 5.1, 1.2, 0.8, 3.5], 'Governance Token': ['AAVE', 'COMP', 'UNI', 'MKR', 'YFI', 'SNX', 'CRV'], 'Blockchain': ['Ethereum', 'Ethereum', 'Ethereum', 'Ethereum', 'Ethereum', 'Ethereum', 'Ethereum'] }) print(defi_protocols.to_string(index=False)) # Visualise TVL fig, ax = plt.subplots(figsize=(10, 5)) ax.barh(defi_protocols['Protocol'], defi_protocols['TVL (B USD)'], color='teal', alpha=0.7) ax.set_xlabel('TVL (Billion USD)') ax.set_title('DeFi Protocol TVL Comparison') ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('defi_tvl.png', dpi=300, bbox_inches='tight') plt.show() print("DeFi TVL chart saved as 'defi_tvl.png'") # ---------------------------------------------------------------- # PART E: DEFI RISK ASSESSMENT FRAMEWORK # ----------------------------------------------------------------