- 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>
138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
package integration_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os/exec"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
)
|
|
|
|
// setupForkedArbitrum sets up a forked Arbitrum test environment using anvil
|
|
func setupForkedArbitrum(t testing.TB) (*ethclient.Client, func()) {
|
|
// Check if anvil is available
|
|
if _, err := exec.LookPath("anvil"); err != nil {
|
|
t.Skip("anvil not found in PATH - install Foundry to run fork tests")
|
|
}
|
|
|
|
// Start anvil with Arbitrum fork
|
|
arbitrumRPC := "https://arb1.arbitrum.io/rpc"
|
|
port := "8545"
|
|
|
|
cmd := exec.Command("anvil",
|
|
"--fork-url", arbitrumRPC,
|
|
"--port", port,
|
|
"--gas-limit", "30000000",
|
|
"--gas-price", "10000000000", // 10 gwei
|
|
"--block-time", "1", // 1 second blocks
|
|
"--accounts", "10", // 10 test accounts
|
|
"--balance", "1000", // 1000 ETH per account
|
|
)
|
|
|
|
// Start anvil in background
|
|
if err := cmd.Start(); err != nil {
|
|
t.Fatalf("Failed to start anvil: %v", err)
|
|
}
|
|
|
|
// Wait for anvil to be ready
|
|
time.Sleep(3 * time.Second)
|
|
|
|
// Connect to the forked network
|
|
client, err := ethclient.Dial(fmt.Sprintf("http://localhost:%s", port))
|
|
if err != nil {
|
|
cmd.Process.Kill()
|
|
t.Fatalf("Failed to connect to forked Arbitrum: %v", err)
|
|
}
|
|
|
|
// Verify connection by getting chain ID
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
chainID, err := client.ChainID(ctx)
|
|
if err != nil {
|
|
cmd.Process.Kill()
|
|
t.Fatalf("Failed to get chain ID: %v", err)
|
|
}
|
|
|
|
if chainID.Uint64() != 42161 {
|
|
t.Logf("Warning: Expected Arbitrum chain ID 42161, got %d", chainID.Uint64())
|
|
}
|
|
|
|
// Return cleanup function
|
|
cleanup := func() {
|
|
client.Close()
|
|
if cmd.Process != nil {
|
|
cmd.Process.Kill()
|
|
cmd.Wait()
|
|
}
|
|
}
|
|
|
|
return client, cleanup
|
|
}
|
|
|
|
// getMemStats returns current memory statistics
|
|
func getMemStats() runtime.MemStats {
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
return m
|
|
}
|
|
|
|
// logMemoryUsage logs current memory usage for debugging
|
|
func logMemoryUsage(t testing.TB, label string) {
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
|
|
t.Logf("%s - Memory: Alloc=%d KB, TotalAlloc=%d KB, Sys=%d KB, NumGC=%d",
|
|
label,
|
|
m.Alloc/1024,
|
|
m.TotalAlloc/1024,
|
|
m.Sys/1024,
|
|
m.NumGC,
|
|
)
|
|
}
|
|
|
|
// waitForAnvil waits for anvil to be ready and responsive
|
|
func waitForAnvil(port string, timeout time.Duration) error {
|
|
deadline := time.Now().Add(timeout)
|
|
|
|
for time.Now().Before(deadline) {
|
|
client, err := ethclient.Dial(fmt.Sprintf("http://localhost:%s", port))
|
|
if err == nil {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
_, err := client.ChainID(ctx)
|
|
cancel()
|
|
client.Close()
|
|
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
}
|
|
|
|
return fmt.Errorf("anvil not ready after %v", timeout)
|
|
}
|
|
|
|
// createTestLogger creates a test logger for debugging
|
|
func createTestLogger(t testing.TB) *log.Logger {
|
|
return log.New(&testWriter{t: t}, "[TEST] ", log.LstdFlags|log.Lshortfile)
|
|
}
|
|
|
|
// testWriter implements io.Writer for test logging
|
|
type testWriter struct {
|
|
t testing.TB
|
|
}
|
|
|
|
func (tw *testWriter) Write(p []byte) (n int, err error) {
|
|
tw.t.Log(string(p))
|
|
return len(p), nil
|
|
}
|