package market import ( "context" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/fraktal/mev-beta/internal/logger" ) // PoolValidator provides pool address validation before RPC queries type PoolValidator struct { logger *logger.Logger client *ethclient.Client } // NewPoolValidator creates a new pool validator func NewPoolValidator(logger *logger.Logger, client *ethclient.Client) *PoolValidator { return &PoolValidator{ logger: logger, client: client, } } // IsValidPoolAddress performs comprehensive validation on a pool address // Returns true only if the address is worth querying from RPC func (pv *PoolValidator) IsValidPoolAddress(ctx context.Context, addr common.Address) (bool, string) { // Check 1: Address must not be zero if addr == (common.Address{}) { return false, "zero address" } // Check 2: Address must be a valid Ethereum address format if !isValidEthereumAddress(addr) { return false, "invalid address format" } // Check 3: If we have a client, verify contract exists at this address // This is the primary defense against invalid pool addresses if pv.client != nil { codeSize, err := getContractCodeSize(ctx, pv.client, addr) if err != nil { // Network errors are transient - allow retry pv.logger.Debug(fmt.Sprintf("Transient error checking contract for %s: %v (will retry)", addr.Hex(), err)) return true, "" // Allow retry for transient failures } // Zero bytecode means definitely no contract if codeSize == 0 { return false, "no contract deployed" } // Contract exists - but may still be non-standard, let RPC call handle that return true, "" } return true, "" } // getContractCodeSize returns the size of bytecode at an address // Size 0 means no contract is deployed func getContractCodeSize(ctx context.Context, client *ethclient.Client, addr common.Address) (int, error) { code, err := client.CodeAt(ctx, addr, nil) if err != nil { return -1, err } return len(code), nil } // isValidEthereumAddress validates basic Ethereum address format func isValidEthereumAddress(addr common.Address) bool { // Address must not be all zeros or all ones (obviously fake) zeroAddr := common.Address{} if addr == zeroAddr { return false } // Check if it's a valid hex address length (already checked by common.Address type) return true }