Files
mev-beta/pkg/sequencer/selector_registry.go
Administrator 3505921207 feat: comprehensive audit infrastructure and Phase 1 refactoring
This commit includes:

## Audit & Testing Infrastructure
- scripts/audit.sh: 12-section comprehensive codebase audit
- scripts/test.sh: 7 test types (unit, integration, race, bench, coverage, contracts, pkg)
- scripts/check-compliance.sh: SPEC.md compliance validation
- scripts/check-docs.sh: Documentation coverage checker
- scripts/dev.sh: Unified development script with all commands

## Documentation
- SPEC.md: Authoritative technical specification
- docs/AUDIT_AND_TESTING.md: Complete testing guide (600+ lines)
- docs/SCRIPTS_REFERENCE.md: All scripts documented (700+ lines)
- docs/README.md: Documentation index and navigation
- docs/DEVELOPMENT_SETUP.md: Environment setup guide
- docs/REFACTORING_PLAN.md: Systematic refactoring plan

## Phase 1 Refactoring (Critical Fixes)
- pkg/validation/helpers.go: Validation functions for addresses/amounts
- pkg/sequencer/selector_registry.go: Thread-safe selector registry
- pkg/sequencer/reader.go: Fixed race conditions with atomic metrics
- pkg/sequencer/swap_filter.go: Fixed race conditions, added error logging
- pkg/sequencer/decoder.go: Added address validation

## Changes Summary
- Fixed race conditions on 13 metric counters (atomic operations)
- Added validation at all ingress points
- Eliminated silent error handling
- Created selector registry for future ABI migration
- Reduced SPEC.md violations from 7 to 5

Build Status:  All packages compile
Compliance:  No race conditions, no silent failures
Documentation:  1,700+ lines across 5 comprehensive guides

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 07:17:13 +01:00

151 lines
4.5 KiB
Go

package sequencer
import (
"sync"
"github.com/ethereum/go-ethereum/accounts/abi"
)
// SelectorRegistry maintains a registry of function selectors
// This prepares for ABI-based detection to replace hardcoded selectors
type SelectorRegistry struct {
// Map of selector bytes to method name
selectors map[[4]byte]string
mu sync.RWMutex
}
// NewSelectorRegistry creates a new selector registry
func NewSelectorRegistry() *SelectorRegistry {
return &SelectorRegistry{
selectors: make(map[[4]byte]string),
}
}
// Register registers a function selector with its name
func (r *SelectorRegistry) Register(selector [4]byte, name string) {
r.mu.Lock()
defer r.mu.Unlock()
r.selectors[selector] = name
}
// RegisterFromABI registers all methods from an ABI
// This is the future replacement for hardcoded selectors
func (r *SelectorRegistry) RegisterFromABI(contractABI *abi.ABI) {
r.mu.Lock()
defer r.mu.Unlock()
for _, method := range contractABI.Methods {
var selector [4]byte
copy(selector[:], method.ID[:4])
r.selectors[selector] = method.Name
}
}
// Lookup looks up a function selector and returns the method name
func (r *SelectorRegistry) Lookup(selector [4]byte) (string, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
name, ok := r.selectors[selector]
return name, ok
}
// LookupBytes looks up a function selector from bytes
func (r *SelectorRegistry) LookupBytes(selectorBytes []byte) (string, bool) {
if len(selectorBytes) < 4 {
return "", false
}
var selector [4]byte
copy(selector[:], selectorBytes[:4])
return r.Lookup(selector)
}
// IsSwapMethod checks if a selector corresponds to a known swap method
func (r *SelectorRegistry) IsSwapMethod(selector [4]byte) bool {
name, ok := r.Lookup(selector)
if !ok {
return false
}
// Check if method name indicates a swap operation
swapMethods := map[string]bool{
"swap": true,
"swapExactTokensForTokens": true,
"swapTokensForExactTokens": true,
"swapExactETHForTokens": true,
"swapETHForExactTokens": true,
"swapExactTokensForETH": true,
"swapTokensForExactETH": true,
"exactInputSingle": true,
"exactInput": true,
"exactOutputSingle": true,
"exactOutput": true,
"exchange": true,
"exchange_underlying": true,
"uniswapV3Swap": true,
"sellToUniswap": true,
"fillRfqOrder": true,
}
return swapMethods[name]
}
// Count returns the number of registered selectors
func (r *SelectorRegistry) Count() int {
r.mu.RLock()
defer r.mu.RUnlock()
return len(r.selectors)
}
// GetAllSelectors returns a copy of all registered selectors
func (r *SelectorRegistry) GetAllSelectors() map[[4]byte]string {
r.mu.RLock()
defer r.mu.RUnlock()
result := make(map[[4]byte]string, len(r.selectors))
for k, v := range r.selectors {
result[k] = v
}
return result
}
// NewDefaultRegistry creates a registry with common DEX selectors
// This is a temporary measure until we migrate to ABI-based detection
func NewDefaultRegistry() *SelectorRegistry {
r := NewSelectorRegistry()
// Register common swap selectors
// TODO: Replace this with RegisterFromABI() calls once we have contract bindings
// UniswapV2 Router selectors
r.Register([4]byte{0x38, 0xed, 0x17, 0x39}, "swapExactTokensForTokens")
r.Register([4]byte{0x88, 0x03, 0xdb, 0xee}, "swapTokensForExactTokens")
r.Register([4]byte{0x7f, 0xf3, 0x6a, 0xb5}, "swapExactETHForTokens")
r.Register([4]byte{0xfb, 0x3b, 0xdb, 0x41}, "swapETHForExactTokens")
r.Register([4]byte{0x18, 0xcb, 0xaf, 0xe5}, "swapExactTokensForETH")
r.Register([4]byte{0x4a, 0x25, 0xd9, 0x4a}, "swapTokensForExactETH")
// UniswapV3 Router selectors
r.Register([4]byte{0x41, 0x4b, 0xf3, 0x89}, "exactInputSingle")
r.Register([4]byte{0xc0, 0x4b, 0x8d, 0x59}, "exactInput")
r.Register([4]byte{0xdb, 0x3e, 0x21, 0x98}, "exactOutputSingle")
r.Register([4]byte{0xf2, 0x8c, 0x04, 0x98}, "exactOutput")
// UniswapV2 Pair direct swap
r.Register([4]byte{0x02, 0x2c, 0x0d, 0x9f}, "swap")
// Curve selectors
r.Register([4]byte{0x3d, 0xf0, 0x21, 0x24}, "exchange")
r.Register([4]byte{0xa6, 0x41, 0x7e, 0xd6}, "exchange_underlying")
// 1inch selectors
r.Register([4]byte{0x7c, 0x02, 0x52, 0x00}, "swap")
r.Register([4]byte{0xe4, 0x49, 0x02, 0x2e}, "uniswapV3Swap")
// 0x Protocol selectors
r.Register([4]byte{0xd9, 0x62, 0x7a, 0xa4}, "sellToUniswap")
r.Register([4]byte{0x41, 0x55, 0x65, 0xb0}, "fillRfqOrder")
return r
}