Skip to content

Example Deployment Guide

Complete guide for deploying example IFIF and IFIFv2 projects for development, testing, and demonstration purposes using our automated deployment scripts.

Overview

The example deployment system creates a comprehensive testing environment with both IFIF v1 and IFIFv2 projects, investors, and various project lifecycle scenarios. The system consists of two complementary deployment scripts:

  • deployExamples.ts: Creates 5 IFIF v1 projects with varied configurations and investment scenarios
  • deployV2Examples.ts: Creates 1 unified IFIFv2 project demonstrating ALL v2 enhancements in a single comprehensive demonstration

This setup is essential for:

  • Development Testing: Full workflow v// The frontend will automatically detect both versions: // v1 Projects (IDs 1-5): // - Traditional IFIF functionality // - Standard investment flows // - Basic NFT operations // - Simple fee structures

// v2 Project (ID 100): // - Enhanced purchase controls // - Multi-distributor systems // - Advanced vesting interfaces // - NFT conversion pathways // - Asset recovery monitoring v1 and v2 features

  • Frontend Development: Real data for UI components across different contract versions
  • Integration Testing: Cross-contract functionality and version compatibility
  • Demo Environments: Showcasing complete platform capabilities from v1 basics to v2 advanced features
  • Feature Validation: V2 enhancements including purchase controls, multi-distributor systems, dual vesting, NFT operations, and asset recovery

Deployment Flow

The example deployment follows a specific sequence that mirrors production workflows:

1. Core Contracts (DeployAll)

Deploy the fundamental protocol infrastructure:

  • Roles contract (access control system)
  • Whitelist implementation and proxy contracts (Merkle tree whitelist management)
  • IFIF Factory (project deployment system)
  • IFIF implementation contract (v1 template)
  • IFIFv2 implementation contract (v2 template)
  • IFIFToken implementation contract (token template)

2. DEX Infrastructure (deployDex)

Deploy decentralized exchange components for token trading:

  • WETH contract (wrapped ETH for trading)
  • PairFactory contract (liquidity pool creation)
  • Router contract (trading interface)
  • Factory-DEX integration (updates factory with router address)

3. Example Projects (deployExamples)

Create comprehensive test scenarios with 5 distinct v1 projects:

  • Project 1: VIP Whitelist Project (complete lifecycle with whitelist integration)
  • Project 2: Standard Project (create-only, demonstrates basic setup)
  • Project 3: High Bonus Project (30% private sale bonus, success scenario)
  • Project 4: Failure Test Project (intentionally underfunded for refund testing)
  • Project 5: Config Update Test Project (35% bonus, demonstrates configuration updates)
  • Multiple investor accounts with realistic investment patterns
  • Complete project lifecycles from creation through success/failure outcomes
  • Real EIP-712 signatures for all governance operations

4. IFIFv2 Demonstration (deployV2Examples)

Single unified project demonstrating ALL v2 enhancements:

  • Factory implementation upgrade to v2
  • Advanced purchase controls (soft cap per purchase, hard cap percentage per user)
  • Multi-distributor fee structures with 3-signature validation system
  • Dual vesting systems (separate fund and token vesting schedules)
  • NFT splitting functionality with minimum weight controls
  • NFT operations and conversion pathways
  • Asset recovery mechanisms

Prerequisites

Before starting the example deployment:

# 1. Install dependencies
pnpm install
 
# 2. Build contracts (optional - script will compile if needed)
pnpm contracts:build
 
# 3. Start local blockchain with proper configuration
pnpm anvil-arm --port 8544   # For ARM-based systems (M1/M2 Macs)
# or
pnpm anvil-amd --port 8544   # For AMD/Intel systems

Important: You must specify --port 8544 to match the deployment scripts' RPC configuration. The deployment scripts are configured to use http://localhost:8544, but anvil defaults to port 8545 without the port flag.

Step-by-Step Deployment

Step 1: Deploy Core Contracts

# Deploy the complete protocol infrastructure
pnpm contracts:script script/DeployAll.s.sol
What this does:
  • Deploys Roles contract with admin setup
  • Deploys upgradeable Whitelist contract
  • Deploys IFIFFactory with implementation contracts
  • Configures all contracts for integration
  • Sets up basic permissions and roles
Expected Output:
=== Complete Protocol Deployment Finished ===
 
=== Important Addresses to Save ===
ROLES_ADDRESS= 0x5FbDB2315678afecb367f032d93F642f64180aa3
WHITELIST_ADDRESS= 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
IFIF_FACTORY_ADDRESS= 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9

Step 2: Deploy DEX Infrastructure

# Deploy DEX components and integrate with factory
pnpm contracts:deploy-dex
What this does:
  • Deploys WETH contract for wrapped ETH trading
  • Deploys Uniswap V2-compatible Pair Factory
  • Deploys Router contract for token swaps
  • Updates IFIF Factory with DEX router address
  • Prepares infrastructure for token trading
Expected Output:
🎉 DEX deployment completed successfully!
 
✅ All deployments successful!
Contract addresses: {
  wethAddress: '0x...',
  pairFactoryAddress: '0x...',
  routerAddress: '0x...',
  factoryAddress: '0x...'
}

Step 3: Deploy IFIF v1 Example Projects

# Create comprehensive test projects and scenarios
pnpm contracts:deploy-examples
What this does:
  • Creates 5 different IFIF v1 projects with varied configurations
  • Sets up investor accounts with USDC tokens
  • Executes investment transactions across project stages
  • Demonstrates complete project lifecycles
  • Creates whitelist sections with real Merkle proofs
  • Performs role management operations
  • Simulates time progression for project stages
Example Projects Created:

Project 1: "VIP Whitelist Project"

  • Target: 100,000 USDC
  • Private Sale: 20% bonus, 30 minutes
  • Public Sale: 1 hour
  • Features: Complete lifecycle with whitelist integration and VIP investor management

Project 2: "Standard Project" (Create-Only)

  • Target: 50,000 USDC
  • Private Sale: 15% bonus, 30 minutes
  • Public Sale: 1 hour
  • Features: Demonstrates basic project setup, remains in created state for testing

Project 3: "High Bonus Project"

  • Target: 80,000 USDC
  • Private Sale: 30% bonus, 30 minutes
  • Public Sale: 1 hour
  • Features: Success scenario with high private sale incentives

Project 4: "Failure Test Project"

  • Target: 120,000 USDC (intentionally high)
  • Private Sale: 15% bonus, 30 minutes
  • Public Sale: 1 hour
  • Features: Deliberately underfunded for refund testing scenarios

Project 5: "Config Update Test Project"

  • Target: 150,000 USDC
  • Private Sale: 35% bonus (highest), 30 minutes
  • Public Sale: 1 hour
  • Features: Demonstrates configuration updates and maximum bonus scenarios

Step 4: Deploy IFIFv2 Comprehensive Demonstration

# Create comprehensive IFIFv2 feature demonstration
pnpm contracts:deploy-examples-v2
What this does:
  • Creates single unified project demonstrating ALL v2 features
  • Connects to existing infrastructure from previous deployments
  • Updates factory implementation to IFIFv2 automatically
  • Executes comprehensive 8-phase demonstration covering every v2 capability
  • Demonstrates advanced purchase controls, vesting, and asset recovery
  • Validates multi-distributor systems with 3-signature validation
  • Shows complete project lifecycle with v2 enhancements
IFIFv2 Demonstration Overview:

Unified Project: "IFIFv2 Demo Project" (ID: 100)

  • Target: 50,000 USDC
  • Private Sale: 20% bonus, 30 minutes
  • Public Sale: 1 hour
  • Purchase Controls: 1,000 USDC soft cap, 20% hard cap (10,000 USDC max per user)
  • Features: Complete demonstration of all v2 enhancements including advanced purchase controls, multi-distributor fees, dual vesting systems, and NFT splitting
  • Status: Complete success with full feature demonstration
Phase-by-Phase Breakdown:

Phase 1: Infrastructure Connection

  • Connects to existing deployed contracts (factory, roles, whitelist, USDC)
  • Automatically updates factory to IFIFv2 implementation
  • Validates proper infrastructure integration

Phase 2: Unified Project Configuration

  • Single project showcasing ALL v2 enhancements
  • Enhanced purchase controls (soft/hard caps)
  • Multi-distributor support configuration
  • Advanced vesting system setup

Phase 3: Contract Deployment & v2 Initialization

  • EIP-712 signature validation for all v2 configurations
  • Project deployment with v2 capabilities
  • initialize_v2() function execution with configV2 parameters

Phase 4: Purchase Control Demonstrations

  • Soft Cap: 1,000 USDC minimum per purchase enforced
  • Hard Cap: 10,000 USDC maximum per user (20% of total) enforced
  • Private Sale: 23,000 USDC total (ACCOUNT_4: 5k, ACCOUNT_5: 8k, ACCOUNT_6: 10k)
  • Public Sale: 27,000 USDC total (ACCOUNT_7: 10k, ACCOUNT_8: 10k, ACCOUNT_9: 7k)
  • Automatic Transitions: INIT → PRIVATE_SALE → PUBLIC_SALE → SALE_SUCCESSED
  • Whitelist Verification: Merkle proof validation for private/public sales

Phase 5: Multi-Distributor Demonstrations

  • 3 Distributors with unique fee structures:
    • Distributor 1 (ACCOUNT_2): 2%/5%/2% fees
    • Distributor 2 (ACCOUNT_8): 3%/4%/2% fees
    • Distributor 3 (ACCOUNT_9): 1%/6%/1% fees
  • 3-Signature Validation: Manager + Distributor + Owner signatures required
  • Fund Vesting Setup: 90-day progressive fund claiming for project owner
  • NFT Claiming: Investment tokenization in SALE_SUCCESSED stage
  • Token Deposits: 37,000 USDC total liquidity from all distributors

Phase 6: Token Vesting Configuration

  • 12-Week Vesting: Progressive token unlock for investors
  • Weekly Periods: 7-day unlock cycles
  • Stage Compliance: Must be configured in CLAIM stage (after deposits)
  • Proper Sequencing: Fund vesting → NFT claiming → deposits → token vesting

Phase 7: Vesting Demonstrations

  • Token Claims: Progressive claiming with vesting enforcement
  • NFT Conversion: convertNFT() for NFT holders to access vested tokens
  • Dual Pathways: claim() for normal purchases vs convertNFT() for NFT holders
  • Complete Cycles: 0% → 50% → 100% vesting progression for both fund and token vesting

Phase 8: Asset Recovery

  • Sweep Timing: After all vesting periods + 180-day grace period
  • Asset Recovery: Unclaimed tokens and funds swept to factory
  • Final Cleanup: Complete project lifecycle closure

Investment Scenarios

The deployment creates realistic investment patterns:

Investor Profiles (v1 Projects):
  • Account 4: Aggressive early investor (900k USDC initial balance)
  • Account 5: Balanced portfolio investor (700k USDC initial balance)
  • Account 6: Conservative late investor (900k USDC initial balance)
  • Account 7: Small retail investor (550k USDC initial balance)
  • Account 8: Strategic investor (550k USDC initial balance)
IFIFv2 Investment Pattern:
  • Private Sale: 23k USDC total (Account 4: 5k, Account 5: 8k, Account 6: 10k)
  • Public Sale: 27k USDC total (Account 7: 10k, Account 8: 10k, Account 9: 7k)
  • Multi-Distributor: 37k USDC total (Account 2: 10k, Account 8: 15k, Account 9: 12k)
Investment Patterns:
  • Private sale bonus calculations
  • Public sale standard rates
  • Partial investments across multiple projects
  • Failed project refund scenarios
  • NFT claiming and operations

Complete Deployment Sequence

For comprehensive development environment, deploy everything in sequence:

# Complete example environment setup with both v1 and v2
# Note: Keep anvil running throughout the entire deployment process
 
# 1. Deploy core contracts
pnpm contracts:script script/DeployAll.s.sol
 
# 2. Deploy DEX infrastructure  
pnpm contracts:deploy-dex
 
# 3. Deploy IFIF v1 example projects
pnpm contracts:deploy-examples
 
# 4. Deploy IFIFv2 comprehensive demonstration
pnpm contracts:deploy-examples-v2
 
echo "🎉 Complete IFIF v1 + v2 environment ready!"
Important Notes:
  • Keep anvil running: Do not restart anvil between deployment steps as this will reset all deployed contracts
  • Sequential execution: Each step depends on the previous step's deployed contracts
  • Total time: Complete deployment takes ~5-10 minutes depending on system performance
  • State preservation: Anvil will preserve all state between scripts when using the provided anvil-arm or anvil-amd commands

Quick v2-Only Deployment

Important: There is no true "v2-only" deployment because the v2 script depends on contracts deployed by the v1 examples script.

Prerequisites (ALL REQUIRED):
  • Core contracts must be deployed (Step 1: DeployAll.s.sol)
  • DEX infrastructure must be deployed (Step 2: deploy-dex)
  • USDC token and SignatureHelper must be deployed (Step 3: deploy-examples required)
  • Contract addresses in deployV2Examples.ts must match your deployed addresses
Why Step 3 is Required:
  • USDC_TOKEN contract is deployed by deployExamples.ts, not DeployAll.s.sol
  • SIGNATURE_HELPER contract is deployed by deployExamples.ts, not DeployAll.s.sol
  • The v2 script requires these contracts to function properly
# You must run Steps 1-3 first:
pnpm contracts:script script/DeployAll.s.sol
pnpm contracts:deploy-dex
pnpm contracts:deploy-examples  # Required for USDC and SignatureHelper
 
# Then update CONTRACT_ADDRESSES in contracts/deployV2Examples.ts
# Set all addresses to match your deployed contracts from Steps 1-3
 
# Finally deploy v2 demonstration
pnpm contracts:deploy-examples-v2
 
echo "🚀 IFIFv2 demonstration complete!"

Note: The v2 script has hard-coded contract addresses including USDC_TOKEN and SIGNATURE_HELPER that are only deployed by the v1 examples script. You cannot skip Step 3 and run only v2 deployment.

Generated Test Data

After successful deployment, you'll have comprehensive test environments for both v1 and v2:

Contracts

  • Core Protocol: Roles, Whitelist (implementation + proxy), IFIF Factory
  • Implementation Templates: IFIF v1, IFIFv2, IFIFToken contracts
  • DEX Infrastructure: WETH, PairFactory, Router contracts with factory integration
  • Test Utilities: USDC mock token, SignatureHelper contract for address prediction
  • Project Instances: 5 IFIF v1 example projects in various states
  • v2 Demonstration: 1 comprehensive IFIFv2 project demonstrating all v2 features
  • Factory Configuration: Automatically updated to support both v1 and v2 implementations

Test Accounts

  • Admin (Account 0): Protocol administrator, contract deployer, 5M USDC balance
  • Project Owner (Account 1): Manages all projects (both v1 and v2), creates and configures projects
  • Distributor (Account 2): DISTRIBUTOR_ROLE granted, primary distributor for v1, also distributor #1 in v2 demo
  • Manager (Account 3): MANAGER_ROLE granted, EIP-712 signing permissions for both versions
  • Investors (Accounts 4-9): Various investment patterns across v1 and v2 projects:
    • Account 4: 900k USDC (aggressive early investor)
    • Account 5: 700k USDC (balanced portfolio investor)
    • Account 6: 900k USDC (conservative late investor)
    • Account 7: 550k USDC (small retail investor)
    • Account 8: 550k USDC (strategic investor, also distributor #2 in v2)
    • Account 9: 10k USDC (test account, also distributor #3 in v2)

Blockchain State

  • v1 Projects: Realistic investment transactions, project stage progressions, NFT operations
  • v2 Project: Advanced purchase controls, multi-distributor operations, dual vesting systems
  • Cross-Version: Whitelist management, role assignments, complete lifecycle demonstrations

Financial Data

  • v1 Data: USDC distributions, investment bonuses, fee calculations, refund scenarios
  • v2 Data: Enhanced purchase caps, distributor-specific fees, progressive vesting claims
  • Vesting Systems:
    • Fund vesting (90 days for project owner)
    • Token vesting (12 weeks for investors)
    • Asset recovery (sweep after grace periods)

Advanced v2 Features

  • Purchase Controls: Soft caps (1k USDC minimum), hard caps (20% maximum per user)
  • Multi-Distributor: 3 distributors with unique fee structures and 3-signature validation
  • Vesting Systems: Dual vesting for funds and tokens with time-based unlocks
  • NFT Operations: Investment tokenization, conversion pathways, and burn mechanics
  • Asset Recovery: Sweep functionality for unclaimed assets after vesting periods

Development Usage

Frontend Development

Use the deployed contracts for UI development across both v1 and v2:

// Contract addresses from deployment (addresses will vary per deployment)
// These are example addresses - use actual addresses from your deployment output
const CONTRACT_ADDRESSES = {
  ROLES: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  WHITELIST: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0', 
  FACTORY: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',
  USDC_TOKEN: '0x0b306bf915c4d645ff596e518faf3f9669b97016', // Mock USDC from deployExamples
  SIGNATURE_HELPER: '0x9a676e781a523b5d0c0e43731313a708cb607508', // From deployExamples
  // v1 projects: IDs 1-5 (use factory.deployments(projectId) to get addresses)
  // v2 project: ID 100 (comprehensive demonstration)
}
 
// Use with wagmi or viem for contract interactions
const factory = getContract({
  address: CONTRACT_ADDRESSES.FACTORY,
  abi: ififFactoryAbi,
  client: publicClient
})
 
// Get project details (works for both v1 and v2)
const projectDetails = await factory.read.getProject([projectId])
 
// Get actual project contract address
const projectAddress = await factory.read.deployments([projectId])
 
// v2-specific features (only for project ID 100)
const v2Project = getContract({
  address: projectAddress, // Use actual deployed address
  abi: ififv2Abi, // Use v2 ABI for enhanced features
  client: publicClient
})
 
// Check if project has v2 features
const hasV2Features = projectId === 100n // Project 100 is the v2 demonstration project

Indexer Development

Start the indexer to process events from both v1 and v2 projects:

# Start indexer after complete deployment
pnpm indexer:dev
 
# The indexer will process events from both versions:
# v1 Events (Projects 1-5):
# - Project creations and stage transitions
# - Investment transactions and refunds
# - NFT operations and transfers
# - Role management activities
# - Whitelist updates
 
# v2 Events (Project 100):
# - Enhanced purchase events with cap validation
# - Multi-distributor configuration updates
# - Fund vesting configuration and claims
# - Token vesting setup and progressive claims
# - NFT conversion and burn operations
# - Asset recovery sweep events

Testing Integration

Use the deployed state for comprehensive integration testing across both versions:

// Test with real deployed contracts (both v1 and v2)
describe('IFIF Integration Tests', () => {
  // v1 Tests
  it('should handle v1 project lifecycle', async () => {
    // Test against deployed v1 project 1 (successful project)
    const project = await factory.read.getProject([1])
    expect(project.stage).toBe(4n) // 4 = SALE_SUCCESSED stage
  })
  
  it('should process v1 investor NFT operations', async () => {
    // Get project contract address and test NFT functionality
    const projectAddress = await factory.read.deployments([1])
    const projectContract = getContract({ 
      address: projectAddress, 
      abi: ififAbi,
      client: publicClient 
    })
    const nftBalance = await projectContract.read.balanceOf([ACCOUNTS.ACCOUNT_4])
    expect(nftBalance).toBeGreaterThan(0n)
  })
 
  // v2 Tests  
  it('should handle v2 project with enhanced features', async () => {
    // Test against deployed v2 project 100
    const v2Project = await factory.read.getProject([100])
    expect(v2Project.stage).toBe(6n) // 6 = CLAIM stage after deposits
  })
 
  it('should validate v2 purchase controls', async () => {
    // Test v2 purchase cap enforcement
    const v2ProjectAddress = await factory.read.deployments([100])
    const v2Contract = getContract({ 
      address: v2ProjectAddress, 
      abi: ififv2Abi,
      client: publicClient 
    })
    const config = await v2Contract.read.config_v2()
    expect(config.purchaseHardCapPercent).toBe(20n) // 20% hard cap
    expect(config.purchaseSoftCap).toBe(parseEther('1000')) // 1k USDC soft cap
  })
 
  it('should process v2 multi-distributor system', async () => {
    // Test multiple distributors with different fee structures
    const v2ProjectAddress = await factory.read.deployments([100])
    const v2Contract = getContract({ 
      address: v2ProjectAddress, 
      abi: ififv2Abi,
      client: publicClient 
    })
    const distributors = [ACCOUNTS.ACCOUNT_2, ACCOUNTS.ACCOUNT_8, ACCOUNTS.ACCOUNT_9]
    for (const distributor of distributors) {
      const config = await v2Contract.read.distributorConfigs([distributor])
      expect(config.distributorFeePercent).toBeGreaterThan(0n)
    }
  })
 
  it('should validate v2 vesting systems', async () => {
    // Test dual vesting system (fund + token)
    const v2ProjectAddress = await factory.read.deployments([100])
    const v2Contract = getContract({ 
      address: v2ProjectAddress, 
      abi: ififv2Abi,
      client: publicClient 
    })
    const fundConfig = await v2Contract.read.fundClaimConfig()
    expect(fundConfig.periodLength).toBe(7n * 24n * 60n * 60n) // 7 days = 604800 seconds
    
    // Token vesting configured through updateClaimConfig
    // Test vesting progression and claim availability
    const claimConfig = await v2Contract.read.claimConfig()
    expect(claimConfig.periodLength).toBe(7n * 24n * 60n * 60n) // Weekly unlocks
  })
})

Verification & Validation

Contract Verification

Verify deployed contracts are properly configured for both v1 and v2:

# Set contract addresses from deployment output (update with your actual addresses)
export ROLES_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3
export FACTORY_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
export USDC_ADDRESS=0x0b306bf915c4d645ff596e518faf3f9669b97016
 
# Check core contract deployment
cast call $ROLES_ADDRESS "owner()" --rpc-url http://localhost:8544
 
# Verify factory configuration (should be v2 after deployV2Examples)
cast call $FACTORY_ADDRESS "implementation()" --rpc-url http://localhost:8544
 
# Check specific project deployments (factory.deployments(projectId) returns project address)
# Project 1 (v1)
cast call $FACTORY_ADDRESS "deployments(uint256)" 1 --rpc-url http://localhost:8544
 
# Project 100 (v2)
cast call $FACTORY_ADDRESS "deployments(uint256)" 100 --rpc-url http://localhost:8544
 
# Get v2 project contract address and check v2-specific features
V2_PROJECT=$(cast call $FACTORY_ADDRESS "deployments(uint256)" 100 --rpc-url http://localhost:8544)
cast call $V2_PROJECT "stage()" --rpc-url http://localhost:8544 # Should be 6 (CLAIM)
cast call $V2_PROJECT "totalPurchase()" --rpc-url http://localhost:8544 # Should be 50k USDC (50000000000000000000000)

Data Validation

Verify example data creation across both v1 and v2:

# Check investor USDC balances (should reflect both v1 and v2 participation)
cast call $USDC_ADDRESS "balanceOf(address)" 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url http://localhost:8544 # ACCOUNT_4
cast call $USDC_ADDRESS "balanceOf(address)" 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 --rpc-url http://localhost:8544 # ACCOUNT_5
 
# Get project contract addresses first
V1_PROJECT_1=$(cast call $FACTORY_ADDRESS "deployments(uint256)" 1 --rpc-url http://localhost:8544)
V2_PROJECT=$(cast call $FACTORY_ADDRESS "deployments(uint256)" 100 --rpc-url http://localhost:8544)
 
# Verify v1 project investments (project 1 should have investments from deployment)
cast call $V1_PROJECT_1 "totalPurchase()" --rpc-url http://localhost:8544
 
# Check v1 project stage (should be 4 = SALE_SUCCESSED for most projects)
cast call $V1_PROJECT_1 "stage()" --rpc-url http://localhost:8544
 
# Verify v2 project investment (project 100 - should be 50k USDC)
cast call $V2_PROJECT "totalPurchase()" --rpc-url http://localhost:8544
 
# Check v2 project stage (should be 6 = CLAIM after all deposits)
cast call $V2_PROJECT "stage()" --rpc-url http://localhost:8544
 
# Check v1 NFT allocations (investors who claimed NFTs)
cast call $V1_PROJECT_1 "balanceOf(address)" 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url http://localhost:8544 # ACCOUNT_4
 
# Check v2 NFT operations (may be 0 if converted back to tokens)
cast call $V2_PROJECT "balanceOf(address)" 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url http://localhost:8544 # ACCOUNT_4
 
# Verify v2 purchase controls (specific to v2 projects)
cast call $V2_PROJECT "config_v2()" --rpc-url http://localhost:8544
 
# Check multi-distributor configurations in v2
cast call $V2_PROJECT "distributorConfigs(address)" 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC --rpc-url http://localhost:8544 # ACCOUNT_2 (Distributor 1)
cast call $V2_PROJECT "distributorConfigs(address)" 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 --rpc-url http://localhost:8544 # ACCOUNT_8 (Distributor 2) 
cast call $V2_PROJECT "distributorConfigs(address)" 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 --rpc-url http://localhost:8544 # ACCOUNT_9 (Distributor 3)
 
# Verify v2 vesting configurations
cast call $V2_PROJECT "fundClaimConfig()" --rpc-url http://localhost:8544    # Fund vesting for project owner
cast call $V2_PROJECT "claimConfig()" --rpc-url http://localhost:8544        # Token vesting for investors

Expected Results

When verification commands are run successfully, you should see:

Contract Verification:
  • owner() should return 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (ACCOUNT_0)
  • implementation() should return the IFIFv2 implementation address after v2 deployment
  • Project deployments should return non-zero contract addresses
Data Validation:
  • USDC balances should reflect post-deployment amounts (reduced from initial 5M, 900k, 700k etc.)
  • V1 project totalPurchase() should show funding amounts (100k for project 1)
  • V2 project totalPurchase() should show 50,000 USDC (50000000000000000000000 wei)
  • Project stages: V1 successful projects = 4 (SALE_SUCCESSED), V2 project = 6 (CLAIM)
  • NFT balances may be 0 if NFTs were converted back to tokens during deployment
  • V2 config_v2() should show purchase controls (soft cap: 1000 USDC, hard cap: 20%)
  • Distributor configs should show different fee percentages for each distributor
  • Vesting configs should show 7-day periods (604800 seconds) for both fund and token vesting

Troubleshooting

Common Issues

Contract Address Mismatch

Problem: Deployment scripts fail with "Contract not found" or "Invalid address" errors.

Solution:

# Update CONTRACT_ADDRESSES in deployDex.ts, deployExamples.ts, and deployV2Examples.ts
# with actual deployed addresses from DeployAll output
 
# For deployExamples.ts, update these addresses:
const CONTRACT_ADDRESSES = {
  ROLES: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  WHITELIST: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0',
  FACTORY: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',
  IFIF_IMPLEMENTATION: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9'
}
 
# For deployV2Examples.ts, ensure all addresses match deployed contracts:
# - USDC_TOKEN and SIGNATURE_HELPER come from deployExamples.ts
# - All other addresses must match DeployAll.s.sol output

Anvil State Issues

Problem: Contracts appear to be missing or in wrong state between deployments.

Solution:

# Reset anvil state completely
rm -rf anvil-state/ anvil-state-amd/
 
# Restart anvil with correct port and state preservation
pnpm anvil-arm --port 8544  # For ARM-based systems (M1/M2 Macs)
# or
pnpm anvil-amd --port 8544  # For AMD/Intel systems
 
# Important: Always specify --port 8544 to match deployment scripts

EIP-712 Signature Verification Errors

Problem: signature verification failed! Expected X, got Y errors during deployment.

Solution:

# Common causes:
# 1. Wrong domain separator (chain ID mismatch)
# 2. Incorrect struct encoding
# 3. Wrong signer account
 
# Verify chain ID matches anvil (should be 31337)
cast chain-id --rpc-url http://localhost:8544
 
# Ensure MANAGER_ROLE is properly assigned to ACCOUNT_3
# Check role assignments in deployment logs

V2 Implementation Update Failures

Problem: Could not check implementation or Implementation update failed errors.

Solution:

# Verify factory contract has correct admin permissions
cast call $FACTORY_ADDRESS "owner()" --rpc-url http://localhost:8544
 
# Check current implementation
cast call $FACTORY_ADDRESS "implementation()" --rpc-url http://localhost:8544
 
# Manually update implementation if needed (as admin/owner)
cast send $FACTORY_ADDRESS "updateImplementation(address)" $V2_IMPLEMENTATION_ADDRESS \
  --rpc-url http://localhost:8544 --private-key $ADMIN_PRIVATE_KEY

Purchase Control Validation Errors

Problem: V2 purchases fail with soft cap or hard cap violations.

Solution:

# Check project's purchase controls
cast call $V2_PROJECT "config_v2()" --rpc-url http://localhost:8544
 
# Common issues:
# - Purchase amount below soft cap (1000 USDC minimum)
# - User exceeding hard cap percentage (20% of total)
# - Insufficient USDC balance or allowance
 
# Verify USDC allowance
cast call $USDC_ADDRESS "allowance(address,address)" $USER_ADDRESS $V2_PROJECT --rpc-url http://localhost:8544

Stage Transition Issues

Problem: Projects stuck in wrong stages or failing to progress.

Solution:

# Check current project stage
cast call $PROJECT_ADDRESS "stage()" --rpc-url http://localhost:8544
 
# Verify time progression (anvil might need manual time advancement)
cast call $PROJECT_ADDRESS "activeSaleEndTime()" --rpc-url http://localhost:8544
 
# Common stage issues:
# - Stage 0 (NONE): Project not properly initialized
# - Stage 1 (INIT): Waiting for sale start time
# - Stage 2/3: Sale periods active
# - Stage 4 (SALE_SUCCESSED): Ready for deposits/claims
# - Stage 6 (CLAIM): After first deposit (V2 projects)

Transaction Failures

Problem: Transactions revert with gas or execution errors.

Solution:

# Check anvil logs for detailed error messages
# Common issues:
 
# 1. Insufficient ETH for gas
cast balance $ACCOUNT_ADDRESS --rpc-url http://localhost:8544
 
# 2. Insufficient USDC balance
cast call $USDC_ADDRESS "balanceOf(address)" $ACCOUNT_ADDRESS --rpc-url http://localhost:8544
 
# 3. Missing role permissions
cast call $ROLES_ADDRESS "hasRole(bytes32,address)" $ROLE_HASH $ACCOUNT_ADDRESS --rpc-url http://localhost:8544
 
# 4. Contract addresses incorrect
# Verify all addresses exist and are contracts (not EOAs)

Vesting Configuration Errors

Problem: V2 vesting setup fails or produces unexpected results.

Solution:

# Vesting must be configured in correct order:
# 1. Fund vesting (in SALE_SUCCESSED stage)  
# 2. Token deposits (transitions to CLAIM stage)
# 3. Token vesting (in CLAIM stage)
 
# Check current vesting configurations
cast call $V2_PROJECT "fundClaimConfig()" --rpc-url http://localhost:8544
cast call $V2_PROJECT "claimConfig()" --rpc-url http://localhost:8544
 
# Verify vesting periods are reasonable (604800 = 7 days)

Network Issues

RPC Connection

Problem: Cannot connect to local anvil instance.

Solution:

# Verify anvil is running on correct port
curl -X POST -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
  http://localhost:8544
 
# Check if port 8544 is in use
lsof -i :8544
 
# Restart anvil with explicit port
pnpm anvil-arm --port 8544  # Must specify port, defaults to 8545

Port Configuration Issues

Problem: Scripts connect to wrong port or can't find blockchain.

Solution:

# Deployment scripts are configured for http://localhost:8544
# Anvil defaults to port 8545 without --port flag
 
# Always start anvil with explicit port:
pnpm anvil-arm --port 8544  # ARM systems
pnpm anvil-amd --port 8544  # AMD/Intel systems
 
# Or update RPC_URL in deployment scripts:
const RPC_URL = 'http://localhost:8544'  # Must match anvil port

Account Configuration

Problem: Wrong accounts or missing private keys.

Solution:

# Verify account addresses match anvil defaults:
# Account 0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
# Account 1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
# ... (standard anvil test accounts)
 
# Check account balances (should have 10,000 ETH each)
cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url http://localhost:8544
 
# Verify private keys match anvil test accounts
# Account 0 private key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Dependency Issues

Node.js/PNPM Version Issues

Problem: Script execution fails with version compatibility errors.

Solution:

# Ensure compatible versions:
node --version  # Should be v18+ 
pnpm --version  # Should be v8+
 
# Install/update dependencies
pnpm install
 
# Clear cache if needed
pnpm store prune
rm -rf node_modules pnpm-lock.yaml
pnpm install

Foundry/Forge Issues

Problem: Contract compilation or script execution fails.

Solution:

# Update foundry
foundryup
 
# Clean and rebuild
pnpm contracts:build
# or manually:
cd contracts && forge clean && forge build
 
# Verify forge can access remappings
cd contracts && forge remappings

Advanced Configuration

Custom Project Parameters

Modify project configurations for both v1 and v2:

v1 Projects (deployExamples.ts):

// Customize v1 project settings
const customProjectConfig = {
  fundToken: usdcAddress,
  projectId: 6n, // Next available ID after existing 5 (must be bigint)
  fundAmount: parseEther('25000'), // 25k USDC target
  privateSaleTime: BigInt(5 * 24 * 60 * 60), // 5 days duration (not epoch time)
  privateBonusPercent: 15n, // 15% bonus (must be bigint)
  publicSaleTime: BigInt(10 * 24 * 60 * 60), // 10 days duration (not epoch time)
  desiredEndEpoch: BigInt(Date.now() / 1000 + (30 * 24 * 60 * 60)) // 30 days from now (epoch time)
}
 
const customProjectNextConfig = {
  projectOwner: ACCOUNTS.ACCOUNT_1,
  distributor: ACCOUNTS.ACCOUNT_2,
  distributorFeePercent: 3n, // 3% distributor fee
  projectOwnerFeePercent: 5n, // 5% project owner fee
  platformFeePercent: 2n, // 2% platform fee
  pairPrice: parseEther('0.1') // 0.1 USDC per token
}

v2 Projects (deployV2Examples.ts):

// Customize v2 project settings (unified demonstration)
const customV2ProjectConfig = {
  fundToken: usdcAddress as `0x${string}`,
  projectId: 101n, // Next available ID after demo project 100
  fundAmount: parseEther('75000'), // 75k USDC target
  privateSaleTime: 3600n, // 1 hour duration (not epoch time)
  privateBonusPercent: 25n, // 25% bonus
  publicSaleTime: 7200n, // 2 hours duration (not epoch time)
  desiredEndEpoch: BigInt(Date.now() / 1000 + 14400) // 4 hours from now (epoch time)
}
 
const customV2ProjectNextConfig = {
  projectOwner: ACCOUNTS.ACCOUNT_1 as `0x${string}`,
  distributor: ACCOUNTS.ACCOUNT_2 as `0x${string}`, // Primary distributor
  distributorFeePercent: 2n,
  projectOwnerFeePercent: 5n,
  platformFeePercent: 2n,
  pairPrice: parseEther('0.1')
}
 
// v2-specific enhancements
const customV2ProjectConfigV2 = {
  privateSaleStartEpoch: BigInt(Date.now() / 1000 + 300), // 5 minutes from now
  purchaseHardCapPercent: 15n, // 15% max per user (11,250 USDC for 75k target)
  purchaseSoftCap: parseEther('2000'), // 2k USDC minimum purchase
  minNFTWeight: 200n // NFT splitting minimum weight (200 units)
}

Investment Patterns

Create custom investment scenarios for both versions:

v1 Investment Patterns:

// Add custom v1 investor behavior
const customV1Investments = [
  {
    account: ACCOUNTS.ACCOUNT_4,
    projectId: 6n,
    amount: parseEther('5000'),
    stage: 'private', // During private sale period
    description: 'Early investor with bonus'
  },
  {
    account: ACCOUNTS.ACCOUNT_5,
    projectId: 6n,
    amount: parseEther('3000'),
    stage: 'public', // During public sale period
    description: 'Standard public sale investment'
  },
  {
    account: ACCOUNTS.ACCOUNT_6,
    projectId: 6n,
    amount: parseEther('7500'),
    stage: 'private',
    description: 'Large private investment'
  }
]
 
// Execute investments with proper timing
for (const investment of customV1Investments) {
  // Set appropriate stage timing before purchase
  if (investment.stage === 'private') {
    await setBlockTimestamp(testClient, privateStartTime)
  } else {
    await setBlockTimestamp(testClient, publicStartTime)
  }
  
  // Execute purchase with proper transaction structure
  await executePurchase(
    testClient,
    investment.projectId,
    investment.account,
    usdcAddress,
    investment.amount,
    investment.description
  )
}

v2 Investment Patterns (with Purchase Controls):

// v2 investment scenarios with cap validation
const v2PurchaseScenarios = [
  { 
    account: ACCOUNTS.ACCOUNT_4,
    projectId: 101n,
    amount: parseEther('5000'),
    description: 'Valid: Above 2k soft cap, within 15% hard cap',
    stage: 'private',
    shouldSucceed: true
  },
  { 
    account: ACCOUNTS.ACCOUNT_5,
    projectId: 101n,
    amount: parseEther('11250'), // Exactly at 15% hard cap (75k * 0.15)
    description: 'Valid: Maximum allowed per user',
    stage: 'private',
    shouldSucceed: true
  },
  { 
    account: ACCOUNTS.ACCOUNT_6,
    projectId: 101n,
    amount: parseEther('1500'), // Below 2k soft cap
    description: 'Invalid: Below 2k soft cap - will fail',
    stage: 'public',
    shouldSucceed: false
  },
  {
    account: ACCOUNTS.ACCOUNT_7,
    projectId: 101n,
    amount: parseEther('12000'), // Above 15% hard cap
    description: 'Invalid: Exceeds 15% hard cap - will fail',
    stage: 'public',
    shouldSucceed: false
  }
]
 
// Execute v2 purchases with enhanced validation
for (const scenario of v2PurchaseScenarios) {
  try {
    // Set appropriate stage timing
    if (scenario.stage === 'private') {
      await setBlockTimestamp(testClient, privateStartTime)
    } else {
      await setBlockTimestamp(testClient, publicStartTime)
    }
    
    // Execute v2 purchase with enhanced controls
    await executeV2Purchase(
      testClient,
      scenario.projectId,
      scenario.account,
      usdcAddress,
      scenario.amount,
      scenario.description
    )
    
    if (!scenario.shouldSucceed) {
      console.log(`   ⚠️ Expected failure but transaction succeeded: ${scenario.description}`)
    }
  } catch (error: any) {
    if (scenario.shouldSucceed) {
      console.log(`   ❌ Unexpected failure: ${scenario.description} - ${error.message}`)
    } else {
      console.log(`   ✅ Expected failure: ${scenario.description} - ${error.message}`)
    }
  }
}

Time Simulation

Control project timeline progression for testing different scenarios:

// Import time utilities from deployment scripts
import { advanceTimeAndTrack, setBlockTimestampAndTrack } from './deployExamples'
 
// Advance time for specific testing scenarios
const sevenDays = 7 * 24 * 60 * 60 // 7 days in seconds
await advanceTimeAndTrack(testClient, sevenDays)
 
// Set specific timestamp for testing stage transitions
const futureTimestamp = Math.floor(Date.now() / 1000) + (30 * 60) // 30 minutes from now
await setBlockTimestampAndTrack(testClient, futureTimestamp)
 
// Example: Fast-forward through project stages
const projectStartTime = Math.floor(Date.now() / 1000)
const privateStartTime = projectStartTime + 300 // 5 minutes delay
const publicStartTime = privateStartTime + 1800 // 30 minutes private sale
const saleEndTime = publicStartTime + 3600 // 1 hour public sale
 
// Test private sale phase
await setBlockTimestampAndTrack(testClient, privateStartTime)
console.log('⏰ Time advanced to private sale start')
 
// Test public sale phase  
await setBlockTimestampAndTrack(testClient, publicStartTime)
console.log('⏰ Time advanced to public sale start')
 
// Test sale completion
await setBlockTimestampAndTrack(testClient, saleEndTime)
console.log('⏰ Time advanced to sale end')
 
// Advanced time manipulation for vesting tests
const vestingPeriod = 7 * 24 * 60 * 60 // 7 days
await advanceTimeAndTrack(testClient, vestingPeriod)
console.log('⏰ Advanced by one vesting period')

Multi-Distributor Configuration (V2 Only)

Configure multiple distributors with different fee structures for V2 projects:

// Define multiple distributors with unique fee structures
const distributorConfigs = [
  {
    distributorAddress: ACCOUNTS.ACCOUNT_2,
    distributorFeePercent: 2n, // 2% fee
    projectOwnerFeePercent: 5n, // 5% to project owner
    platformFeePercent: 2n, // 2% to platform
    description: 'Conservative fee distributor'
  },
  {
    distributorAddress: ACCOUNTS.ACCOUNT_8,
    distributorFeePercent: 3n, // 3% fee
    projectOwnerFeePercent: 4n, // 4% to project owner
    platformFeePercent: 2n, // 2% to platform
    description: 'Balanced fee distributor'
  },
  {
    distributorAddress: ACCOUNTS.ACCOUNT_9,
    distributorFeePercent: 1n, // 1% fee
    projectOwnerFeePercent: 6n, // 6% to project owner
    platformFeePercent: 1n, // 1% to platform
    description: 'Low fee high owner reward distributor'
  }
]
 
// Example: Setting up deposits with multiple distributors
const multiDistributorDeposits = [
  {
    distributor: ACCOUNTS.ACCOUNT_2,
    amount: parseEther('10000'), // 10k USDC
    signers: [ACCOUNTS.ACCOUNT_3, ACCOUNTS.ACCOUNT_2, ACCOUNTS.ACCOUNT_1] // Manager, Distributor, Owner
  },
  {
    distributor: ACCOUNTS.ACCOUNT_8,
    amount: parseEther('15000'), // 15k USDC
    signers: [ACCOUNTS.ACCOUNT_3, ACCOUNTS.ACCOUNT_8, ACCOUNTS.ACCOUNT_1]
  },
  {
    distributor: ACCOUNTS.ACCOUNT_9,
    amount: parseEther('12000'), // 12k USDC
    signers: [ACCOUNTS.ACCOUNT_3, ACCOUNTS.ACCOUNT_9, ACCOUNTS.ACCOUNT_1]
  }
]
 
// Execute multi-distributor deposits (requires 3-signature validation)
for (const deposit of multiDistributorDeposits) {
  // Create deposit configuration with proper signatures
  const depositConfig = {
    distributor: deposit.distributor,
    amount: deposit.amount,
    // Additional V2 deposit parameters...
  }
  
  // Generate required signatures from all three parties
  const signatures = await generateMultiDistributorSignatures(
    depositConfig,
    deposit.signers
  )
  
  // Execute deposit with proper validation
  await executeMultiDistributorDeposit(
    testClient,
    projectId,
    depositConfig,
    signatures
  )
}

Vesting Configuration

Configure dual vesting systems for V2 projects:

// Fund vesting configuration (for project owner)
const fundVestingConfig = {
  startEpoch: BigInt(Math.floor(Date.now() / 1000)), // Start now
  endEpoch: BigInt(Math.floor(Date.now() / 1000) + (90 * 24 * 60 * 60)), // 90 days
  periodLength: BigInt(7 * 24 * 60 * 60), // 7 days per period
  description: 'Progressive fund claiming over 90 days'
}
 
// Token vesting configuration (for investors)  
const tokenVestingConfig = {
  startEpoch: BigInt(Math.floor(Date.now() / 1000) + (7 * 24 * 60 * 60)), // Start in 7 days
  endEpoch: BigInt(Math.floor(Date.now() / 1000) + (12 * 7 * 24 * 60 * 60)), // 12 weeks total
  periodLength: BigInt(7 * 24 * 60 * 60), // Weekly unlocks
  description: '12-week progressive token vesting'
}
 
// Apply vesting configurations to V2 project
await configureV2Vesting(
  testClient,
  v2ProjectAddress,
  fundVestingConfig,
  tokenVestingConfig
)

Integration with Frontend

The Next.js frontend provides a comprehensive interface for viewing both v1 and v2 project data:

# Start the frontend with deployed contracts
cd examples
pnpm dev
 
# Frontend runs on http://localhost:4000 (not default 3000)
# This connects to the indexer on http://localhost:42069
Important Connection Requirements:
  • Indexer Required: The frontend relies entirely on the Ponder indexer for data
  • No Direct Contract Calls: The frontend does NOT make direct blockchain calls
  • Data Flow: Blockchain → Indexer → Frontend (via API)
  • Start Order: Deploy contracts → Start indexer → Start frontend

Indexer Integration

The frontend connects to indexed data, not live contracts:

# Start indexer first (processes deployed contract events)
pnpm indexer:dev
 
# The indexer processes events from both v1 and v2 projects:
# - v1 Projects (IDs 1-5): Traditional IFIF events
# - v2 Project (ID 100): Enhanced v2 events + all v1 events
# - Indexer creates unified data views for frontend consumption

Available Frontend Features

The frontend displays indexed data from deployed examples:

Project Management Pages

  • Project List (/ifif-projects): Overview of all deployed projects (v1 + v2)
  • Project Details (/project/[id]): Individual project views with investment data
  • User Profiles (/user/[address]): Individual investor portfolios across projects
  • Project Analytics (/analytics): Aggregated metrics and performance data

Core Functionality Available

  • Investment Tracking: Purchase history, amounts, bonuses from indexed events
  • NFT Operations: Basic NFT display, transfer history (convertNFT function exists)
  • Role Management (/roles): Role assignments and administrative activities
  • Whitelist Management (/whitelist): Whitelist sections and Merkle root updates
  • Activity Feeds: Transaction history and event logs across all contracts

v2-Specific Features Status

  • Purchase Controls: Not implemented - Frontend lacks v2 cap validation UI
  • Multi-Distributor Dashboard: Not implemented - No distributor comparison interface
  • Vesting Management: Not implemented - No vesting visualization or interaction
  • Advanced Asset Recovery: Not implemented - No sweep operation interface

Current Limitations

The frontend is not a complete v2 demonstration as described in the documentation:

  1. Missing V2-Specific UI: No specialized interfaces for v2 purchase controls, vesting systems, or multi-distributor management
  2. Basic NFT Operations Only: convertNFT function exists but no advanced v2 NFT splitting/merging interfaces
  3. No Vesting Visualization: Fund and token vesting progress not displayed
  4. No Asset Recovery Interface: Sweep operations not accessible through UI
  5. Limited V2 Analytics: V2-specific metrics and comparisons not implemented

What the Frontend Actually Provides

A functional interface for viewing and interacting with basic IFIF functionality:

// Frontend focuses on core IFIF features across both versions:
// - Project lifecycle tracking (all stages)
// - Investment history and portfolio views  
// - NFT ownership and basic operations
// - Role-based access control management
// - Whitelist administration
// - General analytics and reporting

The frontend serves as a data viewer and basic interface rather than a comprehensive v2 feature demonstration. For complete v2 functionality testing, use the deployment scripts and direct contract interactions as described in the development usage section.

Production Considerations

While these deployment scripts are designed for development and testing environments, they provide valuable patterns for production indexer deployments:

Indexer Production Patterns

Event Processing Architecture

  • Comprehensive Event Coverage: Indexes all v1 and v2 events from factory and project contracts
  • Real-time Processing: Ponder indexer processes events as they occur on-chain
  • Data Normalization: Transforms raw blockchain events into structured database records
  • Cross-Contract Relationships: Links events across factory, projects, roles, and whitelist contracts

Database Schema Design

  • Relational Structure: Proper foreign key relationships between contracts and events
  • Aggregated Views: Pre-computed summaries for efficient frontend queries
  • Historical Tracking: Complete audit trail of all contract state changes
  • Analytics Tables: Daily metrics and user activity summaries

Production Indexer Deployment

Infrastructure Requirements

  • Database: PostgreSQL for production (Ponder default) with proper indexing
  • RPC Provider: Reliable blockchain RPC endpoint (Alchemy/Infura for mainnet)
  • Monitoring: Indexer health monitoring and alert systems
  • Backup Strategy: Regular database backups and disaster recovery procedures

Configuration Adjustments Needed

// Production ponder.config.ts adjustments:
export default createConfig({
  chains: {
    mainnet: { // Replace anvil with actual network
      id: 1,
      rpc: process.env.RPC_URL, // Use environment variables
      maxRpcRequestConcurrency: 10,
      pollingInterval: 2000
    }
  },
  contracts: {
    // Update with actual deployed contract addresses
    Factory: {
      address: process.env.FACTORY_ADDRESS, // Not hard-coded
      startBlock: DEPLOYMENT_BLOCK, // Start from deployment block
    },
    // Configure for multiple chains if needed
  },
  database: {
    // Production database configuration
    kind: "postgres",
    connectionString: process.env.DATABASE_URL,
    pool: { max: 20 }
  }
})

Scalability Considerations

Event Volume Handling:
  • Batch Processing: Handle high-volume events efficiently during network congestion
  • Block Range Optimization: Configure optimal block range sizes for initial sync
  • Concurrent Processing: Balance RPC requests to avoid rate limiting
Database Performance:
  • Index Optimization: Proper database indexes for frequently queried fields
  • Connection Pooling: Efficient database connection management
  • Query Optimization: Analyze and optimize slow queries
Real-time Updates:
  • WebSocket Connections: Real-time event streaming for frontend updates
  • Caching Strategy: Redis or similar for frequently accessed data
  • API Rate Limiting: Protect indexer API from excessive requests

Development vs Production Differences

Current Development Setup

# Local development (current setup)
pnpm anvil-arm --port 8544          # Local blockchain
pnpm indexer:dev                    # Ponder dev mode
pnpm contracts:deploy-examples      # Deploy test contracts

Production Deployment Flow

# Production deployment flow
export RPC_URL="https://mainnet.infura.io/v3/YOUR_KEY"
export DATABASE_URL="postgresql://user:pass@host:5432/db"
export FACTORY_ADDRESS="0x..." # Actual deployed factory
 
pnpm indexer:build                  # Build optimized indexer
pnpm indexer:start                  # Start production indexer
# + Docker containerization
# + Load balancer configuration
# + Monitoring setup

Production Monitoring

Essential Metrics

  • Indexer Sync Status: Current block height vs chain tip
  • Event Processing Rate: Events processed per second
  • Database Performance: Query response times and connection usage
  • RPC Health: Request success rates and response times

Alert Configuration

  • Sync Lag Alerts: When indexer falls behind chain by threshold
  • Error Rate Monitoring: Failed event processing or RPC errors
  • Database Health: Connection failures or slow query alerts
  • Resource Usage: Memory and CPU utilization monitoring

Migration from Development

Pre-Production Checklist

  1. Contract Address Verification: Update all hard-coded addresses to production deployments
  2. RPC Configuration: Switch from local anvil to production RPC providers
  3. Database Setup: Migrate from local SQLite to production PostgreSQL
  4. Environment Variables: Secure configuration management for sensitive data
  5. Monitoring Setup: Deploy monitoring and alerting infrastructure

Deployment Strategy

  • Staged Rollout: Deploy to staging environment first
  • Historical Sync: Allow time for complete blockchain history indexing
  • Performance Testing: Load test with expected event volumes
  • Backup Procedures: Verify backup and recovery processes

The deployment scripts demonstrate proper event indexing patterns and database schema design that can be adapted for production use with appropriate infrastructure scaling and security considerations.