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

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                    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

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                    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)

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                    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):

text
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

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
# ----------------------------------------------------------------