package main import ( "context" "encoding/json" "fmt" "io/ioutil" "log" "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) type BlacklistEntry struct { Address string `json:"address"` FailureCount int `json:"failure_count"` LastReason string `json:"last_reason"` FirstSeen time.Time `json:"first_seen"` IsBlacklisted bool `json:"is_blacklisted"` } func main() { // Read blacklist data, err := ioutil.ReadFile("logs/pool_blacklist.json") if err != nil { log.Fatal("Failed to read blacklist:", err) } var entries []BlacklistEntry if err := json.Unmarshal(data, &entries); err != nil { log.Fatal("Failed to parse blacklist:", err) } // Connect to Arbitrum client, err := ethclient.Dial("https://arb1.arbitrum.io/rpc") if err != nil { log.Fatal("Failed to connect:", err) } fmt.Println("Analyzing Valid Failing Pools") fmt.Println("=============================") fmt.Println() // Function selectors token0Selector := []byte{0x0d, 0xfe, 0x16, 0x81} // token0() token1Selector := []byte{0xd2, 0x12, 0x20, 0xa7} // token1() feeSelector := []byte{0xdd, 0xca, 0x3f, 0x43} // fee() slot0Selector := []byte{0x38, 0x50, 0xc7, 0xbd} // slot0() reservesSelector := []byte{0x09, 0x02, 0xf1, 0xac} // getReserves() uniV3Count := 0 uniV2Count := 0 otherCount := 0 noContractCount := 0 // Test first 20 valid entries tested := 0 for _, entry := range entries { if !entry.IsBlacklisted || tested >= 20 { continue } poolAddress := common.HexToAddress(entry.Address) fmt.Printf("Testing %s (reason: %s):\n", entry.Address[:10]+"...", entry.LastReason) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // Check if contract exists code, err := client.CodeAt(ctx, poolAddress, nil) if err != nil || len(code) == 0 { fmt.Println(" ❌ No contract") noContractCount++ cancel() tested++ continue } // Test token0 result, err := client.CallContract(ctx, ethereum.CallMsg{ To: &poolAddress, Data: token0Selector, }, nil) hasToken0 := err == nil && len(result) >= 32 // Test token1 result, err = client.CallContract(ctx, ethereum.CallMsg{ To: &poolAddress, Data: token1Selector, }, nil) hasToken1 := err == nil && len(result) >= 32 // Test fee (V3) result, err = client.CallContract(ctx, ethereum.CallMsg{ To: &poolAddress, Data: feeSelector, }, nil) hasFee := err == nil && len(result) >= 32 // Test slot0 (V3) result, err = client.CallContract(ctx, ethereum.CallMsg{ To: &poolAddress, Data: slot0Selector, }, nil) hasSlot0 := err == nil && len(result) >= 32 // Test getReserves (V2) result, err = client.CallContract(ctx, ethereum.CallMsg{ To: &poolAddress, Data: reservesSelector, }, nil) hasReserves := err == nil && len(result) >= 96 // Determine pool type if hasToken0 && hasToken1 { if hasFee && hasSlot0 { fmt.Println(" ✅ UniswapV3 Pool") uniV3Count++ } else if hasReserves { fmt.Println(" ✅ UniswapV2/Sushiswap Pool") uniV2Count++ } else { fmt.Println(" ⚠️ Has tokens but unknown type") otherCount++ } } else { fmt.Printf(" ❌ Not standard AMM (token0:%v, token1:%v)\n", hasToken0, hasToken1) otherCount++ } cancel() tested++ } fmt.Println() fmt.Println("Summary") fmt.Println("=======") fmt.Printf("UniswapV3: %d\n", uniV3Count) fmt.Printf("UniswapV2: %d\n", uniV2Count) fmt.Printf("Other/Unknown: %d\n", otherCount) fmt.Printf("No Contract: %d\n", noContractCount) fmt.Println() // Analyze failure reasons reasonCounts := make(map[string]int) for _, entry := range entries { if entry.IsBlacklisted { reasonCounts[entry.LastReason]++ } } fmt.Println("Failure Reasons") fmt.Println("===============") for reason, count := range reasonCounts { fmt.Printf("%s: %d\n", reason, count) } }