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,8 +2,13 @@ package monitor
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"os"
"path/filepath"
"strings"
"sync"
"time"
@@ -26,6 +31,14 @@ import (
"golang.org/x/time/rate"
)
// safeConvertInt64ToUint64 safely converts an int64 to uint64, ensuring no negative values
func safeConvertInt64ToUint64(v int64) uint64 {
if v < 0 {
return 0
}
return uint64(v)
}
// ArbitrumMonitor monitors the Arbitrum sequencer for transactions with concurrency support
type ArbitrumMonitor struct {
config *config.ArbitrumConfig
@@ -48,6 +61,11 @@ type ArbitrumMonitor struct {
lastHealthCheck time.Time
}
var (
payloadCaptureDir string
payloadCaptureOnce sync.Once
)
// NewArbitrumMonitor creates a new Arbitrum monitor with rate limiting
func NewArbitrumMonitor(
arbCfg *config.ArbitrumConfig,
@@ -451,10 +469,19 @@ func getUint64(m map[string]interface{}, key string) uint64 {
case uint64:
return v
case int64:
if v < 0 {
return 0
}
return uint64(v)
case int:
if v < 0 {
return 0
}
return uint64(v)
case float64:
if v < 0 {
return 0
}
return uint64(v)
}
}
@@ -652,7 +679,7 @@ func (m *ArbitrumMonitor) processTransactionReceipt(ctx context.Context, receipt
// Also process through the legacy pipeline for compatibility
transactions := []*types.Transaction{tx}
if err := m.pipeline.ProcessTransactions(ctx, transactions, blockNumber, uint64(time.Now().Unix())); err != nil {
if err := m.pipeline.ProcessTransactions(ctx, transactions, blockNumber, safeConvertInt64ToUint64(time.Now().Unix())); err != nil {
m.logger.Debug(fmt.Sprintf("Legacy pipeline processing error for receipt %s: %v", receipt.TxHash.Hex(), err))
}
}
@@ -748,8 +775,53 @@ func (m *ArbitrumMonitor) getTransactionReceiptWithRetry(ctx context.Context, tx
return nil, fmt.Errorf("failed to fetch receipt for transaction %s after %d attempts", txHash.Hex(), maxRetries)
}
func capturePayloadIfEnabled(dexTx *arbitrum.DEXTransaction) {
if dexTx == nil || len(dexTx.InputData) == 0 {
return
}
payloadCaptureOnce.Do(func() {
dir := strings.TrimSpace(os.Getenv("PAYLOAD_CAPTURE_DIR"))
if dir == "" {
return
}
if err := os.MkdirAll(dir, 0o755); err != nil {
return
}
payloadCaptureDir = dir
})
if payloadCaptureDir == "" {
return
}
entry := map[string]interface{}{
"hash": dexTx.Hash,
"from": dexTx.From,
"to": dexTx.To,
"value": dexTx.Value.String(),
"protocol": dexTx.Protocol,
"function": dexTx.FunctionName,
"function_sig": dexTx.FunctionSig,
"input_data": fmt.Sprintf("0x%s", hex.EncodeToString(dexTx.InputData)),
"contract_name": dexTx.ContractName,
"block_number": dexTx.BlockNumber,
}
data, err := json.MarshalIndent(entry, "", " ")
if err != nil {
return
}
fileName := fmt.Sprintf("%s_%s.json", time.Now().UTC().Format("20060102T150405.000Z"), strings.TrimPrefix(dexTx.Hash, "0x"))
filePath := filepath.Join(payloadCaptureDir, fileName)
_ = os.WriteFile(filePath, data, 0o600)
}
// convertToStandardFormat converts a DEX transaction to standard format for pipeline processing
func (m *ArbitrumMonitor) convertToStandardFormat(dexTx *arbitrum.DEXTransaction) interface{} {
capturePayloadIfEnabled(dexTx)
// Convert DEX transaction to a standardized transaction format
// that can be processed by the arbitrage pipeline
return map[string]interface{}{
@@ -762,7 +834,7 @@ func (m *ArbitrumMonitor) convertToStandardFormat(dexTx *arbitrum.DEXTransaction
"function_sig": dexTx.FunctionSig,
"contract": dexTx.ContractName,
"block_number": dexTx.BlockNumber,
"input_data": dexTx.InputData,
"input_data": fmt.Sprintf("0x%s", hex.EncodeToString(dexTx.InputData)),
"timestamp": time.Now().Unix(),
// Token and amount information would be extracted from InputData
// during deeper analysis in the pipeline