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 systemsImportant: 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- 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
=== Complete Protocol Deployment Finished ===
=== Important Addresses to Save ===
ROLES_ADDRESS= 0x5FbDB2315678afecb367f032d93F642f64180aa3
WHITELIST_ADDRESS= 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
IFIF_FACTORY_ADDRESS= 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9Step 2: Deploy DEX Infrastructure
# Deploy DEX components and integrate with factory
pnpm contracts:deploy-dex- 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
🎉 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- 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
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- 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
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 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)
- 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)
- 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!"- 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-armoranvil-amdcommands
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.tsmust match your deployed addresses
USDC_TOKENcontract is deployed bydeployExamples.ts, not DeployAll.s.solSIGNATURE_HELPERcontract is deployed bydeployExamples.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 projectIndexer 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 eventsTesting 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 investorsExpected Results
When verification commands are run successfully, you should see:
Contract Verification:owner()should return0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266(ACCOUNT_0)implementation()should return the IFIFv2 implementation address after v2 deployment- Project deployments should return non-zero contract addresses
- 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 outputAnvil 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 scriptsEIP-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 logsV2 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_KEYPurchase 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:8544Stage 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 8545Port 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 portAccount 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: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80Dependency 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 installFoundry/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 remappingsAdvanced 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- 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 consumptionAvailable 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:
- Missing V2-Specific UI: No specialized interfaces for v2 purchase controls, vesting systems, or multi-distributor management
- Basic NFT Operations Only:
convertNFTfunction exists but no advanced v2 NFT splitting/merging interfaces - No Vesting Visualization: Fund and token vesting progress not displayed
- No Asset Recovery Interface: Sweep operations not accessible through UI
- 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 reportingThe 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
- Index Optimization: Proper database indexes for frequently queried fields
- Connection Pooling: Efficient database connection management
- Query Optimization: Analyze and optimize slow queries
- 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 contractsProduction 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 setupProduction 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
- Contract Address Verification: Update all hard-coded addresses to production deployments
- RPC Configuration: Switch from local anvil to production RPC providers
- Database Setup: Migrate from local SQLite to production PostgreSQL
- Environment Variables: Secure configuration management for sensitive data
- 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.