diff --git a/.env.production b/.env.production index 65740ea..db16d11 100644 --- a/.env.production +++ b/.env.production @@ -1,15 +1,18 @@ # MEV Bot Production Environment Configuration # Generated: October 24, 2025 +# Environment mode (REQUIRED for proper config file selection) +GO_ENV="production" + # REQUIRED: Encryption key for secure operations (32+ chars minimum) MEV_BOT_ENCRYPTION_KEY="production_ready_encryption_key_32_chars_minimum_length_required" -# REQUIRED: Deployed contract addresses (update with your actual deployed contracts) -CONTRACT_ARBITRAGE_EXECUTOR="0x0000000000000000000000000000000000000000" -CONTRACT_FLASH_SWAPPER="0x0000000000000000000000000000000000000000" -CONTRACT_DATA_FETCHER="0x0000000000000000000000000000000000000000" +# REQUIRED: Deployed contract addresses (Uniswap V3 Flash Swaps - Oct 27, 2025) +CONTRACT_ARBITRAGE_EXECUTOR="0x6C2B1c6Eb0e5aB73d8C60944c74A62bfE629c418" +CONTRACT_FLASH_SWAPPER="0x7Cc97259cBe0D02Cd0b8A80c2E1f79C7265808b4" +CONTRACT_DATA_FETCHER="0xC6BD82306943c0F3104296a46113ca0863723cBD" -# RPC Endpoints (optional - will use defaults if not set) +# RPC Endpoints (minimal fallback - providers_runtime.yaml handles multi-provider failover) ARBITRUM_RPC_ENDPOINT="wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57" ARBITRUM_WS_ENDPOINT="wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57" diff --git a/config/arbitrum_production.yaml b/config/arbitrum_production.yaml index 4cc709b..e24fc16 100644 --- a/config/arbitrum_production.yaml +++ b/config/arbitrum_production.yaml @@ -231,21 +231,24 @@ dex_protocols: init_code_hash: "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303" # REAL DEPLOYED MEV BOT CONTRACT ADDRESSES ON ARBITRUM MAINNET -# Deployed from Mev-Alpha project - PRODUCTION READY +# Uniswap V3 Flash Swaps - Deployed October 27, 2025 contracts: # Core arbitrage execution contract - DEPLOYED AND VERIFIED - arbitrage_executor: "0xec2a16d5f8ac850d08c4c7f67efd50051e7cfc0b" - + arbitrage_executor: "0x6C2B1c6Eb0e5aB73d8C60944c74A62bfE629c418" + # Flash swap contracts - DEPLOYED AND AUTHORIZED - uniswap_v3_flash_swapper: "0x5801ee5c2f6069e0f11cce7c0f27c2ef88e79a95" - uniswap_v2_flash_swapper: "0xc0b8c3e9a976ec67d182d7cb0283fb4496692593" - - # Data fetcher for market analysis - DEPLOYED - data_fetcher: "0x3c2c9c86f081b9dac850d08c4c7f67efd50051e7cfc0b" - + uniswap_v3_flash_swapper: "0x7Cc97259cBe0D02Cd0b8A80c2E1f79C7265808b4" + data_fetcher: "0xC6BD82306943c0F3104296a46113ca0863723cBD" + uniswap_v2_flash_swapper: "0xE82c24b3fD47995E0626b1e8ac13E13130f5AeEE" + # Legacy field mappings for backward compatibility flash_swapper: "0x5801ee5c2f6069e0f11cce7c0f27c2ef88e79a95" # Points to V3 swapper - + + # Flash loan receiver contract (Balancer flash loans) - DEPLOYED + flash_loan_receiver: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" + # Balancer Vault address for flash loans (Arbitrum mainnet) + balancer_vault: "0xBA12222222228d8Ba445958a75a0704d566BF2C8" + # Arbitrage Service Configuration arbitrage: enabled: true @@ -254,11 +257,11 @@ arbitrage: stats_update_interval: "10s" max_concurrent_executions: 3 - # Detection thresholds - LOWERED FOR TESTING - min_profit_wei: 100000000000000 # ~$0.20 minimum profit (0.0001 ETH at $2000/ETH) - TESTING - min_roi_percent: 0.05 # Minimum 0.05% ROI to execute - TESTING - min_significant_swap_size: 50000000000000000 # 0.05 ETH minimum swap size to trigger analysis - slippage_tolerance: 0.003 # 0.3% max slippage + # Detection thresholds - OPTIMIZED FOR FLASH LOANS (No capital required!) + min_profit_wei: 100000000000000 # ~$0.20 minimum profit (0.0001 ETH) - Flash loans have NO capital risk! + min_roi_percent: 0.05 # Minimum 0.05% ROI for flash loans (lower threshold = more opportunities) + min_significant_swap_size: 100000000000000000 # 0.1 ETH minimum swap size to trigger analysis + slippage_tolerance: 0.003 # 0.3% max slippage # Scanning parameters min_scan_amount_wei: 100000000000000000 # 0.1 ETH minimum scan amount @@ -274,17 +277,17 @@ arbitrage: # PRODUCTION Arbitrage Strategy Configuration - ARBITRUM FOCUSED arbitrage_config: - min_profit_threshold: "0.0001" # 0.0001 ETH minimum profit - TESTING MODE - max_gas_price: "0.2" # 0.2 gwei max (appropriate for Arbitrum) - max_slippage: "0.3" # 0.3% max slippage (tight for profitability) - + min_profit_threshold: "0.001" # 0.001 ETH minimum profit (~10x gas cost for safety) + max_gas_price: "0.5" # 0.5 gwei max (capped in code, appropriate for Arbitrum) + max_slippage: "0.3" # 0.3% max slippage (tight for profitability) + # MEV Competition Settings - priority_fee_multiplier: 15 # 15x base gas for competitive advantage - max_position_size: "10.0" # Max 10 ETH per arbitrage (risk management) - - # Profitability Requirements - LOWERED FOR TESTING - min_roi_percent: 0.05 # Minimum 0.05% ROI to execute - TESTING - gas_cost_multiplier: 1 # Require 1x gas cost as minimum profit - TESTING + priority_fee_multiplier: 15 # 15x base gas for competitive advantage + max_position_size: "10.0" # Max 10 ETH per arbitrage (risk management) + + # Profitability Requirements - PRODUCTION SETTINGS + min_roi_percent: 0.1 # Minimum 0.1% ROI to execute + gas_cost_multiplier: 5 # Require 5x gas cost as minimum profit (safety margin) # Priority token pairs for arbitrage priority_pairs: @@ -319,9 +322,10 @@ arbitrum: ws_endpoint: "${ARBITRUM_WS_ENDPOINT:-wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57}" chain_id: 42161 rate_limit: - requests_per_second: 100 - max_concurrent: 10 - burst: 20 + requests_per_second: 100 # Chainstack paid tier supports 100+ RPS + max_concurrent: 20 # Increased for high throughput + burst: 100 # Allow bursts for peak activity + rpc_call_delay_ms: 0 # No delay needed with paid tier # Fallback RPC endpoints for reliability (can be overridden by ARBITRUM_FALLBACK_ENDPOINTS env var) # ENHANCED: More endpoints with timeout and retry settings connection_timeout: "30s" # Increased from default 10s @@ -330,39 +334,34 @@ arbitrum: fallback_endpoints: - url: "https://arb1.arbitrum.io/rpc" rate_limit: - requests_per_second: 50 - max_concurrent: 5 - burst: 10 + requests_per_second: 5 # Conservative for public endpoint + max_concurrent: 2 + burst: 3 - url: "https://rpc.ankr.com/arbitrum" rate_limit: - requests_per_second: 50 - max_concurrent: 5 - burst: 10 + requests_per_second: 10 # Conservative for free tier + max_concurrent: 2 + burst: 3 - url: "https://arbitrum.blockpi.network/v1/rpc/public" rate_limit: - requests_per_second: 40 - max_concurrent: 4 - burst: 8 - - url: "https://arbitrum.llamarpc.com" - rate_limit: - requests_per_second: 40 - max_concurrent: 4 - burst: 8 + requests_per_second: 5 # Conservative for public endpoint + max_concurrent: 2 + burst: 3 - url: "https://arbitrum-one.publicnode.com" rate_limit: - requests_per_second: 60 - max_concurrent: 6 - burst: 12 + requests_per_second: 5 # Conservative for public endpoint + max_concurrent: 2 + burst: 3 - url: "https://1rpc.io/arb" rate_limit: - requests_per_second: 45 - max_concurrent: 5 - burst: 9 + requests_per_second: 5 # Conservative for public endpoint + max_concurrent: 2 + burst: 3 - url: "https://arbitrum-one.public.blastapi.io" rate_limit: - requests_per_second: 35 - max_concurrent: 4 - burst: 7 + requests_per_second: 5 # Conservative for public endpoint + max_concurrent: 2 + burst: 3 # Legacy Network Configuration (for backward compatibility) network: @@ -370,7 +369,6 @@ network: name: "Arbitrum One" rpc_endpoints: - "https://arb1.arbitrum.io/rpc" - - "https://arbitrum.llamarpc.com" - "https://arbitrum-one.public.blastapi.io" ws_endpoints: - "wss://arb1.arbitrum.io/ws" diff --git a/config/providers_runtime.yaml b/config/providers_runtime.yaml index 667d8ef..c61a6da 100644 --- a/config/providers_runtime.yaml +++ b/config/providers_runtime.yaml @@ -16,16 +16,97 @@ provider_pools: health_check_interval: 30s max_concurrent_connections: 20 providers: - - Primary RPC + - Arbitrum Public HTTP + - Ankr HTTP + - Chainstack HTTP strategy: reliability_first read_only: failover_enabled: true health_check_interval: 30s max_concurrent_connections: 25 providers: - - Primary WSS + - Arbitrum Public WS + - Chainstack WSS strategy: websocket_preferred providers: + # HTTP Providers - Load distributed across multiple endpoints + - features: + - execution + - transaction_submission + - reading + health_check: + enabled: true + interval: 60s + timeout: 30s + http_endpoint: https://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57 + name: Chainstack HTTP + priority: 1 + rate_limit: + burst: 100 + max_retries: 3 + requests_per_second: 100 + retry_delay: 1s + timeout: 30s + type: standard + ws_endpoint: "" + - features: + - execution + - transaction_submission + - reading + health_check: + enabled: true + interval: 60s + timeout: 30s + http_endpoint: https://rpc.ankr.com/arbitrum + name: Ankr HTTP + priority: 3 + rate_limit: + burst: 60 + max_retries: 3 + requests_per_second: 30 + retry_delay: 1s + timeout: 30s + type: standard + ws_endpoint: "" + - features: + - execution + - transaction_submission + - reading + health_check: + enabled: true + interval: 60s + timeout: 30s + http_endpoint: https://arb1.arbitrum.io/rpc + name: Arbitrum Public HTTP + priority: 10 + rate_limit: + burst: 20 + max_retries: 3 + requests_per_second: 10 + retry_delay: 2s + timeout: 30s + type: standard + ws_endpoint: "" + # WebSocket Providers - Real-time data streams with HTTP fallback + - features: + - reading + - real_time + - execution + health_check: + enabled: true + interval: 30s + timeout: 60s + http_endpoint: https://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57 + name: Chainstack WSS + priority: 1 + rate_limit: + burst: 100 + max_retries: 3 + requests_per_second: 100 + retry_delay: 1s + timeout: 60s + type: standard + ws_endpoint: wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57 - features: - reading - real_time @@ -33,35 +114,17 @@ providers: enabled: true interval: 30s timeout: 60s - http_endpoint: "" - name: Primary WSS - priority: 1 + http_endpoint: https://arb1.arbitrum.io/rpc + name: Arbitrum Public WS + priority: 10 rate_limit: - burst: 600 + burst: 20 max_retries: 3 - requests_per_second: 300 - retry_delay: 1s + requests_per_second: 10 + retry_delay: 2s timeout: 60s type: standard - ws_endpoint: wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57 - - features: - - execution - - transaction_submission - health_check: - enabled: true - interval: 60s - timeout: 30s - http_endpoint: https://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57 - name: Primary RPC - priority: 1 - rate_limit: - burst: 400 - max_retries: 3 - requests_per_second: 200 - retry_delay: 1s - timeout: 30s - type: standard - ws_endpoint: "" + ws_endpoint: wss://arb1.arbitrum.io/ws rotation: fallover_enabled: true health_check_required: true diff --git a/pkg/scanner/market/scanner.go b/pkg/scanner/market/scanner.go index b89e428..4c0ebd2 100644 --- a/pkg/scanner/market/scanner.go +++ b/pkg/scanner/market/scanner.go @@ -234,6 +234,35 @@ func (w *EventWorker) Process(event events.Event) { func (s *MarketScanner) SubmitEvent(event events.Event) { s.wg.Add(1) + // CRITICAL FIX: Populate token addresses if they're missing (zero addresses) + // This fixes the issue where events are logged with 0x00000000 token addresses + zeroAddr := common.Address{} + if event.Token0 == zeroAddr || event.Token1 == zeroAddr { + // Try to get token addresses from cache first + s.cacheMutex.RLock() + poolKey := event.PoolAddress.Hex() + if cachedPool, exists := s.cache[poolKey]; exists { + event.Token0 = cachedPool.Token0 + event.Token1 = cachedPool.Token1 + s.logger.Debug(fmt.Sprintf("✅ Enriched event with cached tokens: %s ↔ %s for pool %s", + event.Token0.Hex()[:10], event.Token1.Hex()[:10], poolKey[:10])) + } else { + s.cacheMutex.RUnlock() + // Cache miss - fetch pool data to get token addresses + poolData, err := s.fetchPoolData(poolKey) + if err == nil { + event.Token0 = poolData.Token0 + event.Token1 = poolData.Token1 + s.logger.Debug(fmt.Sprintf("✅ Enriched event with fetched tokens: %s ↔ %s for pool %s", + event.Token0.Hex()[:10], event.Token1.Hex()[:10], poolKey[:10])) + } else { + s.logger.Debug(fmt.Sprintf("⚠️ Could not fetch tokens for pool %s: %v", poolKey[:10], err)) + } + s.cacheMutex.RLock() + } + s.cacheMutex.RUnlock() + } + // Get an available worker job channel jobChannel := <-s.workerPool @@ -1072,17 +1101,26 @@ func (s *MarketScanner) fetchPoolData(poolAddress string) (*CachedData, error) { return s.getMockPoolData(poolAddress), nil } - // Create RPC client connection - // Get RPC endpoint from config or environment - rpcEndpoint := os.Getenv("ARBITRUM_RPC_ENDPOINT") - if rpcEndpoint == "" { - rpcEndpoint = "wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57" // fallback + // Use shared RPC client from contract executor to respect rate limits + // Creating new clients bypasses rate limiting and causes 429 errors + var client *ethclient.Client + if s.contractExecutor != nil { + client = s.contractExecutor.GetClient() } - client, err := ethclient.Dial(rpcEndpoint) - if err != nil { - return nil, fmt.Errorf("failed to connect to Ethereum node: %w", err) + + if client == nil { + // Fallback: create new client only if no shared client available + rpcEndpoint := os.Getenv("ARBITRUM_RPC_ENDPOINT") + if rpcEndpoint == "" { + rpcEndpoint = "wss://arbitrum-mainnet.core.chainstack.com/53c30e7a941160679fdcc396c894fc57" + } + var err error + client, err = ethclient.Dial(rpcEndpoint) + if err != nil { + return nil, fmt.Errorf("failed to connect to Ethereum node: %w", err) + } + defer client.Close() } - defer client.Close() // Create Uniswap V3 pool interface pool := uniswap.NewUniswapV3Pool(address, client)