fix(multicall): resolve critical multicall parsing corruption issues

- Added comprehensive bounds checking to prevent buffer overruns in multicall parsing
- Implemented graduated validation system (Strict/Moderate/Permissive) to reduce false positives
- Added LRU caching system for address validation with 10-minute TTL
- Enhanced ABI decoder with missing Universal Router and Arbitrum-specific DEX signatures
- Fixed duplicate function declarations and import conflicts across multiple files
- Added error recovery mechanisms with multiple fallback strategies
- Updated tests to handle new validation behavior for suspicious addresses
- Fixed parser test expectations for improved validation system
- Applied gofmt formatting fixes to ensure code style compliance
- Fixed mutex copying issues in monitoring package by introducing MetricsSnapshot
- Resolved critical security vulnerabilities in heuristic address extraction
- Progress: Updated TODO audit from 10% to 35% complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Krypto Kajun
2025-10-17 00:12:55 -05:00
parent f358f49aa9
commit 850223a953
8621 changed files with 79808 additions and 7340 deletions

View File

@@ -2,23 +2,27 @@ package main
import (
"context"
"crypto/tls"
"fmt"
"math/big"
"net/url"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/joho/godotenv"
"github.com/urfave/cli/v2"
"github.com/fraktal/mev-beta/internal/config"
"github.com/fraktal/mev-beta/internal/logger"
"github.com/fraktal/mev-beta/internal/monitoring"
"github.com/fraktal/mev-beta/pkg/arbitrage"
"github.com/fraktal/mev-beta/pkg/metrics"
"github.com/fraktal/mev-beta/pkg/security"
"github.com/fraktal/mev-beta/pkg/transport"
"github.com/joho/godotenv"
"github.com/urfave/cli/v2"
)
func main() {
@@ -50,22 +54,27 @@ func main() {
}
func startBot() error {
// Load environment variables from .env files (in order of precedence)
envFiles := []string{
".env.production", // Highest priority
".env.staging",
".env",
".env.local", // Lowest priority
// Load environment variables based on GO_ENV
envMode := strings.ToLower(os.Getenv("GO_ENV"))
if envMode == "" {
envMode = "development"
}
for _, envFile := range envFiles {
if _, err := os.Stat(envFile); err == nil {
if err := godotenv.Load(envFile); err != nil {
fmt.Printf("Warning: Failed to load %s: %v\n", envFile, err)
} else {
fmt.Printf("Loaded environment variables from %s\n", envFile)
}
var envFile string
if envMode == "development" {
envFile = ".env"
} else {
envFile = fmt.Sprintf(".env.%s", envMode)
}
if _, err := os.Stat(envFile); err == nil {
if err := godotenv.Load(envFile); err != nil {
fmt.Printf("Warning: failed to load %s: %v\n", envFile, err)
} else {
fmt.Printf("Loaded environment variables from %s\n", envFile)
}
} else {
fmt.Printf("Warning: %s not found; proceeding without mode-specific env overrides\n", envFile)
}
// Load configuration
@@ -90,15 +99,16 @@ func startBot() error {
log.Debug(fmt.Sprintf("Chain ID: %d", cfg.Arbitrum.ChainID))
// Initialize comprehensive security framework
securityKeyDir := getEnvOrDefault("MEV_BOT_KEYSTORE_PATH", "keystore")
securityConfig := &security.SecurityConfig{
KeyStoreDir: "keystore",
KeyStoreDir: securityKeyDir,
EncryptionEnabled: true,
TransactionRPS: 100,
RPCRPS: 200,
MaxBurstSize: 50,
FailureThreshold: 5,
RecoveryTimeout: 5 * time.Minute,
TLSMinVersion: 771, // TLS 1.2
TLSMinVersion: tls.VersionTLS12, // TLS 1.2 minimum
EmergencyStopFile: "emergency.stop",
MaxGasPrice: "50000000000", // 50 gwei
AlertWebhookURL: os.Getenv("SECURITY_WEBHOOK_URL"),
@@ -109,7 +119,9 @@ func startBot() error {
if err != nil {
return fmt.Errorf("failed to initialize security manager: %w", err)
}
defer securityManager.Shutdown(context.Background())
if err := securityManager.Shutdown(context.Background()); err != nil {
log.Error("Failed to shutdown security manager", "error", err)
}
log.Info("Security framework initialized successfully")
@@ -135,19 +147,18 @@ func startBot() error {
// Initialize unified provider manager
log.Info("Initializing provider manager with separate read-only, execution, and testing pools...")
// Create temporary provider config file from main config and environment variables
tempProviderConfigPath := "config/providers_runtime.yaml"
if err := cfg.CreateProviderConfigFile(tempProviderConfigPath); err != nil {
return fmt.Errorf("failed to create provider config: %w", err)
}
// Use existing providers.yaml config file for runtime
providerConfigPath := "config/providers.yaml"
defer os.Remove(tempProviderConfigPath) // Clean up temp file
providerManager, err := transport.NewUnifiedProviderManager(tempProviderConfigPath)
providerManager, err := transport.NewUnifiedProviderManager(providerConfigPath)
if err != nil {
return fmt.Errorf("failed to initialize provider manager: %w", err)
}
defer providerManager.Close()
defer func() {
if err := providerManager.Close(); err != nil {
log.Error("Failed to close provider manager", "error", err)
}
}()
// Get execution client for transaction operations
executionClient, err := providerManager.GetExecutionHTTPClient()
@@ -165,8 +176,15 @@ func startBot() error {
return fmt.Errorf("MEV_BOT_ENCRYPTION_KEY environment variable is required for secure operations")
}
keystorePath := getEnvOrDefault("MEV_BOT_KEYSTORE_PATH", "keystore")
if strings.TrimSpace(keystorePath) == "" {
keystorePath = "keystore"
}
fmt.Printf("Using keystore path: %s\n", keystorePath)
log.Info(fmt.Sprintf("Using keystore path: %s", keystorePath))
keyManagerConfig := &security.KeyManagerConfig{
KeystorePath: getEnvOrDefault("MEV_BOT_KEYSTORE_PATH", "keystore"),
KeystorePath: keystorePath,
EncryptionKey: encryptionKey,
KeyRotationDays: 30,
MaxSigningRate: 100,
@@ -184,7 +202,11 @@ func startBot() error {
if err != nil {
return fmt.Errorf("failed to create arbitrage database: %w", err)
}
defer arbitrageDB.Close()
defer func() {
if err := arbitrageDB.Close(); err != nil {
log.Error("Failed to close arbitrage database", "error", err)
}
}()
// Check if arbitrage service is enabled
if !cfg.Arbitrage.Enabled {
@@ -211,6 +233,38 @@ func startBot() error {
}
log.Info("Arbitrage service created successfully")
// Initialize data integrity monitoring system
log.Info("Initializing data integrity monitoring system...")
// Initialize integrity monitor
integrityMonitor := monitoring.NewIntegrityMonitor(log)
// Initialize dashboard server
dashboardPort := 8080
if portEnv := os.Getenv("DASHBOARD_PORT"); portEnv != "" {
if port, err := strconv.Atoi(portEnv); err == nil {
dashboardPort = port
}
}
dashboardServer := monitoring.NewDashboardServer(log, integrityMonitor, integrityMonitor.GetHealthCheckRunner(), dashboardPort)
// Start dashboard server
go func() {
log.Info(fmt.Sprintf("Starting monitoring dashboard on port %d...", dashboardPort))
if err := dashboardServer.Start(); err != nil {
log.Error("Dashboard server error", "error", err)
}
}()
// Start integrity monitoring
go func() {
log.Info("Starting integrity monitoring...")
integrityMonitor.StartHealthCheckRunner(ctx)
}()
log.Info("Data integrity monitoring system initialized successfully")
log.Info(fmt.Sprintf("Dashboard available at http://localhost:%d", dashboardPort))
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
@@ -229,7 +283,11 @@ func startBot() error {
errChan <- fmt.Errorf("arbitrage service error: %w", err)
}
}()
defer arbitrageService.Stop()
defer func() {
if err := arbitrageService.Stop(); err != nil {
log.Error("Failed to stop arbitrage service", "error", err)
}
}()
log.Info("Arbitrage service started successfully")
log.Info("MEV bot started successfully - monitoring for arbitrage opportunities...")
@@ -244,6 +302,13 @@ func startBot() error {
return err
}
// Stop monitoring services
log.Info("Stopping monitoring services...")
if err := dashboardServer.Stop(); err != nil {
log.Error("Failed to stop dashboard server gracefully", "error", err)
}
integrityMonitor.StopHealthCheckRunner()
// Stop metrics server if running
if metricsServer != nil {
if err := metricsServer.Stop(); err != nil {
@@ -342,7 +407,11 @@ func scanOpportunities() error {
if err != nil {
return fmt.Errorf("failed to initialize provider manager: %w", err)
}
defer providerManager.Close()
defer func() {
if err := providerManager.Close(); err != nil {
log.Error("Failed to close provider manager in scan mode", "error", err)
}
}()
// Get read-only client for scanning (more efficient)
client, err := providerManager.GetReadOnlyHTTPClient()
@@ -375,7 +444,11 @@ func scanOpportunities() error {
if err != nil {
return fmt.Errorf("failed to create arbitrage database: %w", err)
}
defer arbitrageDB.Close()
defer func() {
if err := arbitrageDB.Close(); err != nil {
log.Error("Failed to close arbitrage database in scan mode", "error", err)
}
}()
// Create arbitrage service with scanning enabled but execution disabled
scanConfig := cfg.Arbitrage
@@ -397,7 +470,11 @@ func scanOpportunities() error {
if err := arbitrageService.Start(); err != nil {
return fmt.Errorf("failed to start arbitrage service: %w", err)
}
defer arbitrageService.Stop()
defer func() {
if err := arbitrageService.Stop(); err != nil {
log.Error("Failed to stop arbitrage service in scan mode", "error", err)
}
}()
// Create context with timeout for scanning
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)