Introduction: The Parallel Financial Universe

Throughout this module, we have explored how open banking, RESTful APIs, Account Information Services (AIS), Payment Initiation Services (PIS), and Banking-as-a-Service (BaaS) modernize traditional financial systems. However, all of these architectures share a common structural foundation: they rely on Centralized Financial Intermediaries—licensed banks, regulated payment processors, and institutional data gateways acting as trusted middlemen.

Simultaneously, a parallel financial ecosystem has emerged that operates completely independently of traditional banks and government-backed currencies. Decentralized Finance (DeFi) utilizes blockchain technology, cryptographic ledgers, and self-executing code known as Smart Contracts to automate lending, borrowing, trading, and asset management without a single intermediary. This lesson deconstructs blockchain fundamentals, smart contract architecture, decentralized lending pools, automated market makers, and the futuristic convergence of open banking with decentralized finance.

Part 1: Foundations of Blockchain and Smart Contracts

To understand Decentralized Finance, we must first examine the foundational technology stack that powers it.

1. What is a Blockchain?

A blockchain is a distributed, decentralized, immutable digital ledger shared across a peer-to-peer computer network.

Decentralization: Instead of a single bank maintaining a private database on its own servers, thousands of independent validator nodes maintain identical copies of the ledger.

Immutability: Once a block of transactions is cryptographically validated and added to the chain, it cannot be altered or deleted retroactively without rewriting the entire history of the network, making fraud mathematically impossible.

2. Smart Contracts: Code as Law

Definition: A smart contract is a self-executing computer program stored directly on a blockchain network.

Execution Mechanics: Smart contracts execute automatically when predefined conditions are met (e.g., “If Party A deposits $100 in cryptocurrency, automatically transfer ownership of Digital Asset B to Party A”). Because code execution is managed by the blockchain network, no human intermediaries, lawyers, or banks are required to enforce agreements.

Part 2: Core Components of Decentralized Finance (DeFi)

DeFi recreates traditional financial primitives (banking, lending, and trading) using open-source, composable smart contracts.

1. Decentralized Lending and Borrowing Protocols (e.g., Aave, Compound)

In traditional banking, a bank acts as a middleman matching depositors with borrowers, taking a heavy interest rate spread.

DeFi Lending Pools: Users deposit digital assets into shared smart contract liquidity pools, earning passive interest. Borrowers can draw loans instantly from these pools by locking up overcollateralized digital assets as security, eliminating credit checks, loan officers, and approval delays.

2. Automated Market Makers (AMMs) and Decentralized Exchanges (DEXs)

Traditional stock and currency exchanges use central order books and market makers to match buyers and sellers.

AMMs (e.g., Uniswap): Decentralized exchanges replace order books with mathematical formulas. Liquidity providers deposit token pairs into smart contract pools, and traders swap tokens directly against the pool. Asset prices adjust automatically based on the ratio of tokens remaining in the pool via constant-product formulas (x × y = k).

Part 3: The Convergence of Open Banking and Decentralized Finance

Initially, open banking and decentralized finance developed as entirely separate economic tracks: open banking modernized traditional legacy banking, while DeFi created a parallel crypto-native economy. Today, these two worlds are beginning to converge.

1. Bridging Fiat Accounts with Web3 Wallets

Fiat-to-Crypto On/Off Ramps: Users use open banking Payment Initiation Services (PIS) to securely push funds instantly from their traditional checking accounts to decentralized exchanges, buying digital assets without enduring multi-day wire delays.

Tokenized Real-World Assets (RWA): Traditional financial institutions are tokenizing real-world assets—such as U.S. Treasury bonds, real estate, and corporate debt—bringing traditional financial instruments onto public and private blockchains.

2. Decentralized Identity (DID) and Credit Scoring

On-Chain Credit History: As more financial transactions move onto blockchains, users build transparent, immutable on-chain credit histories.

Open Banking Integration: Future hybrid underwriting engines will combine traditional open banking AIS data (checking account cash flow) with decentralized wallet verification, creating holistic, global credit scores that transcend borders.

Part 4: Risks, Vulnerabilities, and Regulatory Challenges

While DeFi offers incredible efficiency and transparency, it introduces unique technical and regulatory risks that differ fundamentally from traditional banking.

1. Smart Contract Bugs and Exploits

Because smart contracts are immutable, once deployed to a blockchain, faulty code cannot be easily patched. If a developer leaves a security vulnerability in a smart contract, hackers can exploit it within seconds to drain millions of dollars from liquidity pools with zero recourse or bank deposit insurance.

2. Regulatory Compliance and Anti-Money Laundering (AML)

DeFi protocols are pseudonymous and borderless, making traditional Know Your Customer (KYC) compliance extremely difficult. Regulatory bodies globally are cracking down on decentralized finance, demanding that user interfaces and bridge protocols enforce strict identity verification to prevent illicit money laundering.

1. Blockchain Architecture Deep-Dive

Blockchain Structure:

text
Blockchain Data Structure:

┌─────────────────────────────────────────────────────────────────────┐
│                           Blockchain                               │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                       Block N-1                             │   │
│  │  ┌─────────────────────────────────────────────────────┐   │   │
│  │  │  Hash: 0x7f3a...                                    │   │   │
│  │  │  Previous: 0x9d2e...                               │   │   │
│  │  │  Transactions: [...]                               │   │   │
│  │  │  Timestamp: 2024-01-01T00:00:00Z                  │   │   │
│  │  └─────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                    │
│                              ▼                                    │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                       Block N                               │   │
│  │  ┌─────────────────────────────────────────────────────┐   │   │
│  │  │  Hash: 0x8a4b...                                    │   │   │
│  │  │  Previous: 0x7f3a...                               │   │   │
│  │  │  Transactions: [...]                               │   │   │
│  │  │  Timestamp: 2024-01-01T00:01:00Z                  │   │   │
│  │  └─────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                    │
│                              ▼                                    │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                       Block N+1                             │   │
│  │  ┌─────────────────────────────────────────────────────┐   │   │
│  │  │  Hash: 0x9c5d...                                    │   │   │
│  │  │  Previous: 0x8a4b...                               │   │   │
│  │  │  Transactions: [...]                               │   │   │
│  │  │  Timestamp: 2024-01-01T00:02:00Z                  │   │   │
│  │  └─────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘

Each block contains:
1. Block Header:
   - Previous block hash (links blocks together)
   - Merkle root (hash of all transactions)
   - Timestamp
   - Nonce (proof-of-work)
   - Difficulty target

2. Block Body:
   - All transactions in the block
   - Transaction count
   - Size in bytes

Block Header Components:

 
 
Component Size (Bytes) Description
Version 4 Block version number
Previous Block Hash 32 Hash of previous block header
Merkle Root 32 Root hash of transaction Merkle tree
Timestamp 4 Block creation timestamp
Difficulty Target 4 Current difficulty target
Nonce 4 Proof-of-work nonce

Block Hash Calculation:

text
Block Hash = SHA256(SHA256(
    Version + Previous_Hash + Merkle_Root + Timestamp + Difficulty + Nonce
))

Where:
- SHA256 is the cryptographic hash function
- + represents concatenation
- The double SHA256 provides additional security

2. Smart Contract Architecture

Ethereum Smart Contract Structure:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Open Banking ↔ DeFi Bridge Smart Contract
contract OpenBankingDeFiBridge {
    // State Variables
    address public owner;
    mapping(address => uint256) public balances;
    mapping(address => bool) public authorizedBanks;
    mapping(bytes32 => bool) public processedTransactions;
    
    // Events
    event Deposit(address indexed user, uint256 amount, string bankReference);
    event Withdrawal(address indexed user, uint256 amount, string bankReference);
    event BankAuthorized(address indexed bank, bool status);
    
    // Modifiers
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }
    
    modifier onlyAuthorizedBank() {
        require(authorizedBanks[msg.sender], "Only authorized banks can call this function");
        _;
    }
    
    // Constructor
    constructor() {
        owner = msg.sender;
    }
    
    // Bank Authorization
    function authorizeBank(address bank, bool status) external onlyOwner {
        authorizedBanks[bank] = status;
        emit BankAuthorized(bank, status);
    }
    
    // Deposit from Open Banking
    function depositFromBank(
        address user,
        uint256 amount,
        string memory bankReference,
        bytes32 transactionHash
    ) external onlyAuthorizedBank {
        require(amount > 0, "Amount must be greater than 0");
        require(!processedTransactions[transactionHash], "Transaction already processed");
        
        processedTransactions[transactionHash] = true;
        balances[user] += amount;
        
        emit Deposit(user, amount, bankReference);
    }
    
    // Withdraw to Open Banking
    function withdrawToBank(
        address user,
        uint256 amount,
        string memory bankReference
    ) external {
        require(balances[user] >= amount, "Insufficient balance");
        require(amount > 0, "Amount must be greater than 0");
        
        balances[user] -= amount;
        
        // Emit withdrawal event for Open Banking to process
        emit Withdrawal(user, amount, bankReference);
    }
    
    // Get Balance
    function getBalance(address user) external view returns (uint256) {
        return balances[user];
    }
    
    // Emergency Withdrawal
    function emergencyWithdraw(address user) external onlyOwner {
        uint256 amount = balances[user];
        balances[user] = 0;
        // Trigger emergency withdrawal via Open Banking
    }
}

DeFi Lending Protocol:

solidity
// Simplified DeFi Lending Protocol
contract DeFiLendingPool {
    // User Positions
    struct Position {
        uint256 collateralAmount;
        uint256 debtAmount;
        uint256 collateralAsset;
        uint256 debtAsset;
        uint256 openTime;
        uint256 lastInterestUpdate;
    }
    
    mapping(address => Position) public positions;
    
    // Pool State
    mapping(uint256 => uint256) public poolLiquidity;
    mapping(uint256 => uint256) public poolUtilization;
    mapping(uint256 => uint256) public interestRates;
    
    // Events
    event Deposit(address indexed user, uint256 assetId, uint256 amount);
    event Borrow(address indexed user, uint256 assetId, uint256 amount);
    event Repay(address indexed user, uint256 assetId, uint256 amount);
    event WithdrawCollateral(address indexed user, uint256 assetId, uint256 amount);
    event Liquidation(address indexed user, address liquidator, uint256 collateralAmount);
    
    // Constants
    uint256 public constant LIQUIDATION_THRESHOLD = 80; // 80%
    uint256 public constant LIQUIDATION_BONUS = 105; // 5% bonus
    uint256 public constant SECONDS_PER_YEAR = 31557600;
    
    // Deposit Collateral
    function depositCollateral(uint256 assetId, uint256 amount) external {
        require(amount > 0, "Amount must be greater than 0");
        
        // Transfer tokens from user to contract
        // (Simplified, actual implementation would use ERC20 transfer)
        
        poolLiquidity[assetId] += amount;
        
        emit Deposit(msg.sender, assetId, amount);
    }
    
    // Borrow Asset
    function borrowAsset(uint256 assetId, uint256 amount) external {
        require(amount > 0, "Amount must be greater than 0");
        
        Position storage pos = positions[msg.sender];
        
        // Calculate health factor
        uint256 healthFactor = calculateHealthFactor(msg.sender);
        require(healthFactor >= 100, "Health factor too low");
        
        // Check pool liquidity
        require(poolLiquidity[assetId] >= amount, "Insufficient pool liquidity");
        
        // Update position
        pos.debtAmount += amount;
        pos.debtAsset = assetId;
        pos.lastInterestUpdate = block.timestamp;
        
        // Update pool
        poolLiquidity[assetId] -= amount;
        poolUtilization[assetId] = calculateUtilization(assetId);
        
        // Update interest rate
        updateInterestRate(assetId);
        
        // Transfer tokens to user
        // (Simplified, actual implementation would use ERC20 transfer)
        
        emit Borrow(msg.sender, assetId, amount);
    }
    
    // Repay Debt
    function repayDebt(uint256 assetId, uint256 amount) external {
        require(amount > 0, "Amount must be greater than 0");
        
        Position storage pos = positions[msg.sender];
        require(pos.debtAmount > 0, "No debt to repay");
        
        // Calculate accrued interest
        uint256 accruedInterest = calculateAccruedInterest(msg.sender);
        uint256 totalDebt = pos.debtAmount + accruedInterest;
        
        uint256 repayAmount = amount;
        if (repayAmount > totalDebt) {
            repayAmount = totalDebt;
        }
        
        // Update position
        pos.debtAmount = totalDebt - repayAmount;
        pos.lastInterestUpdate = block.timestamp;
        
        // Update pool
        poolLiquidity[assetId] += repayAmount;
        poolUtilization[assetId] = calculateUtilization(assetId);
        
        // Update interest rate
        updateInterestRate(assetId);
        
        emit Repay(msg.sender, assetId, repayAmount);
    }
    
    // Calculate Health Factor
    function calculateHealthFactor(address user) public view returns (uint256) {
        Position storage pos = positions[user];
        
        if (pos.debtAmount == 0) {
            return type(uint256).max;
        }
        
        // Get collateral value in debt asset terms
        uint256 collateralValue = getCollateralValue(pos.collateralAsset, pos.collateralAmount);
        uint256 debtValue = pos.debtAmount;
        
        // Health Factor = (Collateral Value * Liquidation Threshold) / Debt Value * 100
        uint256 healthFactor = (collateralValue * LIQUIDATION_THRESHOLD * 100) / (debtValue * 100);
        
        return healthFactor;
    }
    
    // Calculate Accrued Interest
    function calculateAccruedInterest(address user) public view returns (uint256) {
        Position storage pos = positions[user];
        
        if (pos.debtAmount == 0) {
            return 0;
        }
        
        uint256 timeElapsed = block.timestamp - pos.lastInterestUpdate;
        uint256 interestRate = getInterestRate(pos.debtAsset);
        
        // Simple interest calculation
        uint256 interest = pos.debtAmount * interestRate * timeElapsed / (SECONDS_PER_YEAR * 10000);
        
        return interest;
    }
    
    // Calculate Utilization Rate
    function calculateUtilization(uint256 assetId) internal view returns (uint256) {
        uint256 totalLiquidity = getTotalLiquidity(assetId);
        if (totalLiquidity == 0) {
            return 0;
        }
        
        uint256 borrowed = getTotalBorrowed(assetId);
        return (borrowed * 10000) / totalLiquidity;
    }
    
    // Update Interest Rate (Dynamic)
    function updateInterestRate(uint256 assetId) internal {
        uint256 utilization = calculateUtilization(assetId);
        
        // Interest rate model (simplified)
        // Utilization < 80%: Base rate + (Utilization * Slope)
        // Utilization >= 80%: Base rate + (80% * Slope) + ((Utilization - 80%) * Slope2)
        
        uint256 baseRate = 100; // 1%
        uint256 slope1 = 50; // 0.5%
        uint256 slope2 = 100; // 1%
        
        uint256 interestRate;
        if (utilization <= 8000) { // 80%
            interestRate = baseRate + (utilization * slope1 / 10000);
        } else {
            interestRate = baseRate + (8000 * slope1 / 10000) + ((utilization - 8000) * slope2 / 10000);
        }
        
        interestRates[assetId] = interestRate;
    }
    
    // Get Interest Rate
    function getInterestRate(uint256 assetId) public view returns (uint256) {
        return interestRates[assetId];
    }
}

3. Automated Market Maker (AMM) Deep-Dive

Constant Product Formula:

text
x * y = k

Where:
- x = Reserve of token A
- y = Reserve of token B
- k = Constant product (invariant)

Price Calculation:
price_A_in_B = y / x
price_B_in_A = x / y

Swap Calculation:
Given: Swap dx amount of token A for token B
Δy = (y * dx) / (x + dx)

After Swap:
x' = x + dx
y' = y - Δy
k' = x' * y' = k (remains constant)

AMM Implementation:

solidity
// Simplified AMM (Uniswap-style) with Open Banking Integration
contract OpenBankingAMM {
    // Pool Information
    struct Pool {
        address tokenA;
        address tokenB;
        uint256 reserveA;
        uint256 reserveB;
        uint256 totalLiquidity;
        uint256 fee; // LP fee in basis points (e.g., 30 = 0.3%)
    }
    
    mapping(address => mapping(address => Pool)) public pools;
    mapping(address => uint256) public liquidityProviderShares;
    
    // Open Banking Integration
    mapping(bytes32 => bool) public processedDeposits;
    mapping(address => bool) public authorizedOracles;
    
    // Events
    event Swap(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut);
    event LiquidityAdded(address indexed user, address pool, uint256 amountA, uint256 amountB);
    event LiquidityRemoved(address indexed user, address pool, uint256 amountA, uint256 amountB);
    event FiatDeposit(address indexed user, uint256 amount, string bankReference);
    
    // Create Pool
    function createPool(address tokenA, address tokenB, uint256 fee) external {
        require(tokenA != tokenB, "Tokens must be different");
        require(pools[tokenA][tokenB].totalLiquidity == 0, "Pool already exists");
        
        Pool storage pool = pools[tokenA][tokenB];
        pool.tokenA = tokenA;
        pool.tokenB = tokenB;
        pool.fee = fee;
        pool.reserveA = 0;
        pool.reserveB = 0;
        pool.totalLiquidity = 0;
    }
    
    // Add Liquidity (with Open Banking deposit)
    function addLiquidityWithFiat(
        address tokenA,
        address tokenB,
        uint256 amountA,
        uint256 amountB,
        string memory bankReference,
        bytes32 transactionHash
    ) external {
        require(!processedDeposits[transactionHash], "Transaction already processed");
        processedDeposits[transactionHash] = true;
        
        // Get pool
        Pool storage pool = pools[tokenA][tokenB];
        require(pool.totalLiquidity > 0, "Pool does not exist");
        
        // Calculate optimal amounts
        uint256 optimalAmountA;
        uint256 optimalAmountB;
        
        if (pool.reserveA == 0 && pool.reserveB == 0) {
            // First deposit
            optimalAmountA = amountA;
            optimalAmountB = amountB;
        } else {
            // Calculate optimal amounts based on current reserves
            optimalAmountA = (amountB * pool.reserveA) / pool.reserveB;
            if (optimalAmountA > amountA) {
                optimalAmountA = amountA;
                optimalAmountB = (optimalAmountA * pool.reserveB) / pool.reserveA;
            } else {
                optimalAmountB = amountB;
            }
        }
        
        // Update pool reserves
        pool.reserveA += optimalAmountA;
        pool.reserveB += optimalAmountB;
        
        // Calculate shares (LP tokens)
        uint256 shares;
        if (pool.totalLiquidity == 0) {
            shares = sqrt(optimalAmountA * optimalAmountB);
        } else {
            shares = min(
                (optimalAmountA * pool.totalLiquidity) / pool.reserveA,
                (optimalAmountB * pool.totalLiquidity) / pool.reserveB
            );
        }
        
        // Update LP shares
        liquidityProviderShares[msg.sender] += shares;
        pool.totalLiquidity += shares;
        
        emit LiquidityAdded(msg.sender, address(this), optimalAmountA, optimalAmountB);
        emit FiatDeposit(msg.sender, optimalAmountA + optimalAmountB, bankReference);
    }
    
    // Swap Tokens
    function swap(
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 minAmountOut
    ) external returns (uint256 amountOut) {
        // Get pool
        Pool storage pool = getPool(tokenIn, tokenOut);
        require(pool.totalLiquidity > 0, "Pool not found");
        
        // Determine reserves
        uint256 reserveIn = tokenIn == pool.tokenA ? pool.reserveA : pool.reserveB;
        uint256 reserveOut = tokenOut == pool.tokenA ? pool.reserveA : pool.reserveB;
        
        // Calculate output amount (constant product formula)
        uint256 amountInWithFee = amountIn * (10000 - pool.fee);
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = (reserveIn * 10000) + amountInWithFee;
        amountOut = numerator / denominator;
        
        require(amountOut >= minAmountOut, "Insufficient output amount");
        
        // Update reserves
        if (tokenIn == pool.tokenA) {
            pool.reserveA += amountIn;
            pool.reserveB -= amountOut;
        } else {
            pool.reserveB += amountIn;
            pool.reserveA -= amountOut;
        }
        
        emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut);
        
        return amountOut;
    }
    
    // Get Pool
    function getPool(address tokenA, address tokenB) internal view returns (Pool storage) {
        // Check both orders
        if (pools[tokenA][tokenB].totalLiquidity > 0) {
            return pools[tokenA][tokenB];
        } else if (pools[tokenB][tokenA].totalLiquidity > 0) {
            return pools[tokenB][tokenA];
        }
        revert("Pool not found");
    }
    
    // Price Oracle (for Open Banking integration)
    function getPrice(address tokenA, address tokenB) external view returns (uint256) {
        Pool storage pool = getPool(tokenA, tokenB);
        
        uint256 reserveIn = tokenA == pool.tokenA ? pool.reserveA : pool.reserveB;
        uint256 reserveOut = tokenB == pool.tokenA ? pool.reserveA : pool.reserveB;
        
        return (reserveOut * 1e18) / reserveIn;
    }
    
    // Helper Functions
    function sqrt(uint256 x) internal pure returns (uint256) {
        uint256 z = (x + 1) / 2;
        uint256 y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
        return y;
    }
    
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
}

4. Open Banking ↔ DeFi Convergence Architecture

text
Open Banking ↔ DeFi Convergence Architecture:

┌─────────────────────────────────────────────────────────────────────┐
│                         User Experience Layer                      │
│                                                                   │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  Mobile App │  │  Web Portal │  │  Wallet App │              │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘              │
└─────────┼────────────────┼────────────────┼──────────────────────┘
          │                │                │
          ▼                ▼                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         API Gateway Layer                          │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  Authentication │ Rate Limiting │ Logging │ Orchestration  │   │
│  └─────────────────────────────────────────────────────────────┘   │
└────────────────────────────┬────────────────────────────────────────┘
          │                    │                    │
          ▼                    ▼                    ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│  Open Banking    │  │   Hybrid Layer   │  │  DeFi Layer      │
│  Services        │  │                  │  │                  │
│                  │  │  ┌────────────┐  │  │  ┌────────────┐  │
│  ┌────────────┐  │  │  │ Oracles    │  │  │  │ Smart      │  │
│  │ AIS (Read) │  │  │  └────────────┘  │  │  │ Contracts  │  │
│  └────────────┘  │  │  ┌────────────┐  │  │  └────────────┘  │
│  ┌────────────┐  │  │  │ On/Off     │  │  │  ┌────────────┐  │
│  │ PIS (Write)│  │  │  │ Ramps      │  │  │  │ AMM/DEX    │  │
│  └────────────┘  │  │  └────────────┘  │  │  └────────────┘  │
│  ┌────────────┐  │  │  ┌────────────┐  │  │  ┌────────────┐  │
│  │ BaaS       │  │  │  │ DID/KYC   │  │  │  │ Lending    │  │
│  └────────────┘  │  │  └────────────┘  │  │  └────────────┘  │
└──────────────────┘  └──────────────────┘  └──────────────────┘
          │                    │                    │
          ▼                    ▼                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         Settlement Layer                          │
│                                                                   │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │  RTGS/ACH  │  │  Blockchain │  │  CBDC       │              │
│  │  (TradFi)  │  │  (DeFi)     │  │  Rails      │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────────────────────────┘