DeFi Protocol Testing

Test DeFi protocols including DEX trading, lending platforms, yield farming, and liquidity pools with comprehensive transaction monitoring

LoadForge can record your browser, graphically build tests, scan your site with a wizard and more. Sign up now to run your first test.

Sign up now


This guide demonstrates how to test DeFi (Decentralized Finance) protocols including DEX trading, lending platforms, yield farming, and liquidity management. Perfect for Web3 developers building DeFi applications, testing protocol integrations, and monitoring DeFi infrastructure performance.

Use Cases

  • Testing DEX trading functionality (Uniswap, SushiSwap, PancakeSwap)
  • Validating lending and borrowing protocols (Aave, Compound, MakerDAO)
  • Monitoring yield farming and liquidity mining rewards
  • Testing flash loan functionality and arbitrage opportunities
  • Validating protocol governance and voting mechanisms
  • Load testing DeFi protocol APIs under high transaction volume

Key Features

  • Multi-Protocol Support: Test various DeFi protocols with unified framework
  • Transaction Monitoring: Track transaction status, gas usage, and slippage
  • Price Impact Analysis: Monitor price impact and MEV opportunities
  • Liquidity Pool Testing: Test LP token operations and impermanent loss
  • Gas Optimization: Monitor and optimize gas usage across protocols
  • Error Handling: Robust handling of failed transactions and reverts

Example Implementation

from locust import task, HttpUser
import json
import time
import random
from web3 import Web3
from eth_account import Account

class DeFiProtocolUser(HttpUser):
    abstract = True
    
    def on_start(self):
        # Web3 provider setup (using Infura/Alchemy)
        self.infura_url = "https://mainnet.infura.io/v3/your-project-id"
        self.w3 = Web3(Web3.HTTPProvider(self.infura_url))
        
        # Test wallet setup (use test accounts only)
        self.test_private_key = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
        self.test_account = Account.from_key(self.test_private_key)
        self.wallet_address = self.test_account.address
        
        # Common DeFi contract addresses (Ethereum mainnet)
        self.contracts = {
            # Uniswap V3
            "uniswap_v3_router": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
            "uniswap_v3_factory": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
            "uniswap_v3_quoter": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
            
            # Aave V3
            "aave_pool": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
            "aave_pool_data_provider": "0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3",
            
            # Compound V3
            "compound_comet_usdc": "0xc3d688B66703497DAA19211EEdff47f25384cdc3",
            
            # Common ERC20 tokens
            "usdc": "0xA0b86a33E6441b8435b662303c0f479c7e1b5b8e",
            "usdt": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
            "weth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
            "dai": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
        }
        
        # Common test amounts (in wei for ETH, smallest unit for tokens)
        self.test_amounts = {
            "small": int(0.01 * 10**18),   # 0.01 ETH
            "medium": int(0.1 * 10**18),   # 0.1 ETH  
            "large": int(1 * 10**18)       # 1 ETH
        }

class UniswapV3User(DeFiProtocolUser):
    """Test Uniswap V3 DEX functionality"""
    
    @task(3)
    def test_uniswap_quote(self):
        """Test Uniswap V3 price quotes"""
        # Test WETH -> USDC quote
        token_in = self.contracts["weth"]
        token_out = self.contracts["usdc"]
        amount_in = self.test_amounts["small"]
        fee = 3000  # 0.3% fee tier
        
        # Quoter contract ABI (simplified)
        quoter_abi = [
            {
                "inputs": [
                    {"name": "tokenIn", "type": "address"},
                    {"name": "tokenOut", "type": "address"},
                    {"name": "fee", "type": "uint24"},
                    {"name": "amountIn", "type": "uint256"},
                    {"name": "sqrtPriceLimitX96", "type": "uint160"}
                ],
                "name": "quoteExactInputSingle",
                "outputs": [{"name": "amountOut", "type": "uint256"}],
                "type": "function"
            }
        ]
        
        start_time = time.time()
        
        try:
            quoter_contract = self.w3.eth.contract(
                address=self.contracts["uniswap_v3_quoter"],
                abi=quoter_abi
            )
            
            # Get quote
            amount_out = quoter_contract.functions.quoteExactInputSingle(
                token_in,
                token_out, 
                fee,
                amount_in,
                0
            ).call()
            
            response_time = (time.time() - start_time) * 1000
            
            if amount_out > 0:
                # Calculate price impact and slippage
                eth_price_estimate = amount_out / (amount_in / 10**18) / 10**6  # Rough USDC price
                
                # Log successful quote
                self.environment.events.request.fire(
                    request_type="Uniswap_Quote",
                    name=f"WETH->USDC Quote: ${eth_price_estimate:.2f}",
                    start_time=start_time,
                    response_time=response_time,
                    response_length=len(str(amount_out)),
                    context={
                        "token_pair": "WETH/USDC",
                        "amount_in": amount_in,
                        "amount_out": amount_out,
                        "estimated_price": eth_price_estimate,
                        "fee_tier": fee
                    },
                    url="/uniswap/quote",
                    exception=None,
                )
            else:
                raise Exception("Invalid quote: amount_out is 0")
                
        except Exception as e:
            response_time = (time.time() - start_time) * 1000
            self.environment.events.request.fire(
                request_type="Uniswap_Quote",
                name="WETH->USDC Quote Failed",
                start_time=start_time,
                response_time=response_time,
                response_length=0,
                context={"error": str(e)},
                url="/uniswap/quote",
                exception=e,
            )

    @task(2)
    def test_uniswap_pool_info(self):
        """Test Uniswap V3 pool information"""
        # WETH/USDC 0.3% pool
        pool_address = "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"
        
        # Pool contract ABI (simplified)
        pool_abi = [
            {
                "inputs": [],
                "name": "slot0",
                "outputs": [
                    {"name": "sqrtPriceX96", "type": "uint160"},
                    {"name": "tick", "type": "int24"},
                    {"name": "observationIndex", "type": "uint16"},
                    {"name": "observationCardinality", "type": "uint16"},
                    {"name": "observationCardinalityNext", "type": "uint16"},
                    {"name": "feeProtocol", "type": "uint8"},
                    {"name": "unlocked", "type": "bool"}
                ],
                "type": "function"
            },
            {
                "inputs": [],
                "name": "liquidity",
                "outputs": [{"name": "", "type": "uint128"}],
                "type": "function"
            }
        ]
        
        start_time = time.time()
        
        try:
            pool_contract = self.w3.eth.contract(address=pool_address, abi=pool_abi)
            
            # Get pool state
            slot0 = pool_contract.functions.slot0().call()
            liquidity = pool_contract.functions.liquidity().call()
            
            response_time = (time.time() - start_time) * 1000
            
            sqrt_price = slot0[0]
            current_tick = slot0[1]
            
            # Calculate current price from sqrtPriceX96
            price = (sqrt_price / (2**96))**2
            
            self.environment.events.request.fire(
                request_type="Uniswap_Pool",
                name=f"WETH/USDC Pool Info - Tick: {current_tick}",
                start_time=start_time,
                response_time=response_time,
                response_length=len(str(liquidity)),
                context={
                    "pool_address": pool_address,
                    "sqrt_price": sqrt_price,
                    "current_tick": current_tick,
                    "liquidity": liquidity,
                    "calculated_price": price
                },
                url="/uniswap/pool-info",
                exception=None,
            )
            
        except Exception as e:
            response_time = (time.time() - start_time) * 1000
            self.environment.events.request.fire(
                request_type="Uniswap_Pool",
                name="Pool Info Failed",
                start_time=start_time,
                response_time=response_time,
                response_length=0,
                context={"error": str(e)},
                url="/uniswap/pool-info",
                exception=e,
            )

    @task(1)
    def test_uniswap_transaction_simulation(self):
 

Ready to run your test?
Launch your locust test at scale.