Files
mev-beta/pkg/common/selectors/selectors.go
Krypto Kajun 850223a953 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>
2025-10-17 00:12:55 -05:00

189 lines
12 KiB
Go

package selectors
import (
"encoding/hex"
"fmt"
"sync"
"github.com/ethereum/go-ethereum/crypto"
)
type selectorCache struct {
mu sync.Mutex
cache map[string]string
}
var cachedSelectors = selectorCache{
cache: make(map[string]string),
}
// MustSelector returns the canonical 4-byte selector (prefixed with 0x) for a function signature.
// Panics if the signature cannot be hashed (should never happen for valid signatures).
func MustSelector(signature string) string {
cachedSelectors.mu.Lock()
defer cachedSelectors.mu.Unlock()
if sel, ok := cachedSelectors.cache[signature]; ok {
return sel
}
hash := crypto.Keccak256([]byte(signature))
if len(hash) < 4 {
panic(fmt.Sprintf("unable to derive selector for %s", signature))
}
selector := "0x" + hex.EncodeToString(hash[:4])
cachedSelectors.cache[signature] = selector
return selector
}
// Uniswap / Pancake / TraderJoe (Uniswap V2-style) selectors
var (
UniswapV2SwapExactTokensForTokens = MustSelector("swapExactTokensForTokens(uint256,uint256,address[],address,uint256)")
UniswapV2SwapTokensForExactTokens = MustSelector("swapTokensForExactTokens(uint256,uint256,address[],address,uint256)")
UniswapV2SwapExactETHForTokens = MustSelector("swapExactETHForTokens(uint256,address[],address,uint256)")
UniswapV2SwapTokensForExactETH = MustSelector("swapTokensForExactETH(uint256,uint256,address[],address,uint256)")
UniswapV2SwapExactTokensForETH = MustSelector("swapExactTokensForETH(uint256,uint256,address[],address,uint256)")
UniswapV2SwapETHForExactTokens = MustSelector("swapETHForExactTokens(uint256,address[],address,uint256)")
UniswapV2SwapExactTokensForTokensSupportingFee = MustSelector("swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256,uint256,address[],address,uint256)")
UniswapV2SwapExactETHForTokensSupportingFee = MustSelector("swapExactETHForTokensSupportingFeeOnTransferTokens(uint256,address[],address,uint256)")
UniswapV2SwapExactTokensForETHSupportingFee = MustSelector("swapExactTokensForETHSupportingFeeOnTransferTokens(uint256,uint256,address[],address,uint256)")
UniswapV2AddLiquidity = MustSelector("addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256)")
UniswapV2AddLiquidityETH = MustSelector("addLiquidityETH(address,uint256,uint256,uint256,address,uint256)")
)
// Uniswap V3 / Algebra (Camelot V3, Kyber Elastic) selectors
var (
UniswapV3ExactInputSingle = MustSelector("exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))")
UniswapV3ExactInputSingleLegacy = MustSelector("exactInputSingle((address,address,uint24,address,uint256,uint256,uint160))")
UniswapV3ExactInput = MustSelector("exactInput((bytes,address,uint256,uint256,uint256))")
UniswapV3ExactInputLegacy = MustSelector("exactInput((bytes,address,uint256,uint256))")
UniswapV3ExactOutputSingle = MustSelector("exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))")
UniswapV3ExactOutput = MustSelector("exactOutput((bytes,address,uint256,uint256,uint256))")
UniswapV3ExactOutputBytes = MustSelector("exactOutput(bytes)")
UniswapV3Multicall = MustSelector("multicall(bytes[])")
UniswapV3MulticallWithDeadline = MustSelector("multicall(uint256,bytes[])")
UniswapV3MulticallWithBlockhash = MustSelector("multicall(bytes32,bytes[])")
UniversalRouterExecute = MustSelector("execute(bytes,bytes[],uint256)")
UniversalRouterExecutePayable = MustSelector("execute(bytes,bytes[])")
UniversalRouterExecuteSimple = MustSelector("execute(bytes)")
)
// Balancer V2 selectors
var (
BalancerSwap = MustSelector("swap((bytes32,uint8,address,address,uint256,bytes),(address,bool,address,bool),uint256,uint256)")
BalancerBatchSwap = MustSelector("batchSwap(uint8,(bytes32,uint256,uint256,uint256,bytes)[],address[],(address,bool,address,bool),int256[],uint256)")
BalancerFlashLoan = MustSelector("flashLoan(address,address[],uint256[],bytes)")
)
// Curve Finance selectors
var (
CurveExchange = MustSelector("exchange(int128,int128,uint256,uint256)")
CurveExchangeUnderlying = MustSelector("exchange_underlying(int128,int128,uint256,uint256)")
CurveExchangeUint = MustSelector("exchange(uint256,uint256,uint256,uint256)")
CurveExchangeUnderlyingUint = MustSelector("exchange_underlying(uint256,uint256,uint256,uint256)")
)
// Kyber Elastic (reuses Uniswap V3 style)
var (
KyberExactInputSingleLegacy = UniswapV3ExactInputSingleLegacy
KyberExactInputSingle = UniswapV3ExactInputSingle
KyberExactInput = UniswapV3ExactInput
KyberExactOutputSingle = UniswapV3ExactOutputSingle
KyberExactOutput = UniswapV3ExactOutput
KyberMulticall = UniswapV3Multicall
KyberMulticallWithDeadline = UniswapV3MulticallWithDeadline
KyberMulticallWithBlockhash = UniswapV3MulticallWithBlockhash
KyberUniversalRouterExecute = UniversalRouterExecute
KyberUniversalRouterExecutePayable = UniversalRouterExecutePayable
KyberUniversalRouterExecuteSimple = UniversalRouterExecuteSimple
)
// Kyber Classic shares the Uniswap V2 style router interface.
var (
KyberClassicSwapExactTokensForTokens = UniswapV2SwapExactTokensForTokens
KyberClassicSwapTokensForExactTokens = UniswapV2SwapTokensForExactTokens
KyberClassicSwapExactETHForTokens = UniswapV2SwapExactETHForTokens
KyberClassicSwapTokensForExactETH = UniswapV2SwapTokensForExactETH
KyberClassicSwapExactTokensForETH = UniswapV2SwapExactTokensForETH
KyberClassicSwapETHForExactTokens = UniswapV2SwapETHForExactTokens
KyberClassicSwapExactTokensForTokensSupportingFee = UniswapV2SwapExactTokensForTokensSupportingFee
KyberClassicSwapExactETHForTokensSupportingFee = UniswapV2SwapExactETHForTokensSupportingFee
KyberClassicSwapExactTokensForETHSupportingFee = UniswapV2SwapExactTokensForETHSupportingFee
)
// PancakeSwap (BSC) uses the Uniswap V2 router interface.
var (
PancakeSwapSwapExactTokensForTokens = UniswapV2SwapExactTokensForTokens
PancakeSwapSwapTokensForExactTokens = UniswapV2SwapTokensForExactTokens
PancakeSwapSwapExactETHForTokens = UniswapV2SwapExactETHForTokens
PancakeSwapSwapTokensForExactETH = UniswapV2SwapTokensForExactETH
PancakeSwapSwapExactTokensForETH = UniswapV2SwapExactTokensForETH
PancakeSwapSwapETHForExactTokens = UniswapV2SwapETHForExactTokens
PancakeSwapSwapExactTokensForTokensSupportingFee = UniswapV2SwapExactTokensForTokensSupportingFee
PancakeSwapSwapExactETHForTokensSupportingFee = UniswapV2SwapExactETHForTokensSupportingFee
PancakeSwapSwapExactTokensForETHSupportingFee = UniswapV2SwapExactTokensForETHSupportingFee
PancakeSwapAddLiquidity = UniswapV2AddLiquidity
PancakeSwapAddLiquidityETH = UniswapV2AddLiquidityETH
)
// Trader Joe V2 (AMM) mirrors the Uniswap V2 router interface.
var (
TraderJoeSwapExactTokensForTokens = UniswapV2SwapExactTokensForTokens
TraderJoeSwapTokensForExactTokens = UniswapV2SwapTokensForExactTokens
TraderJoeSwapExactETHForTokens = UniswapV2SwapExactETHForTokens
TraderJoeSwapTokensForExactETH = UniswapV2SwapTokensForExactETH
TraderJoeSwapExactTokensForETH = UniswapV2SwapExactTokensForETH
TraderJoeSwapETHForExactTokens = UniswapV2SwapETHForExactTokens
TraderJoeSwapExactTokensForTokensSupportingFee = UniswapV2SwapExactTokensForTokensSupportingFee
TraderJoeSwapExactETHForTokensSupportingFee = UniswapV2SwapExactETHForTokensSupportingFee
TraderJoeSwapExactTokensForETHSupportingFee = UniswapV2SwapExactTokensForETHSupportingFee
TraderJoeAddLiquidity = UniswapV2AddLiquidity
TraderJoeAddLiquidityETH = UniswapV2AddLiquidityETH
)
// Trader Joe Liquidity Book router specific selectors.
var (
TraderJoeLBSwapExactTokensForTokens = MustSelector("swapExactTokensForTokens(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapTokensForExactTokens = MustSelector("swapTokensForExactTokens(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapExactTokensForNative = MustSelector("swapExactTokensForNATIVE(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapExactNativeForTokens = MustSelector("swapExactNATIVEForTokens(uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapTokensForExactNative = MustSelector("swapTokensForExactNATIVE(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapExactTokensForTokensSupportingFee = MustSelector("swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapExactTokensForNativeSupportingFee = MustSelector("swapExactTokensForNATIVESupportingFeeOnTransferTokens(uint256,uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBSwapExactNativeForTokensSupportingFee = MustSelector("swapExactNATIVEForTokensSupportingFeeOnTransferTokens(uint256,(uint256[],uint8[],address[]),address,uint256)")
TraderJoeLBLiquidityAdd = MustSelector("addLiquidity((address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int256[],uint256[],uint256[],address,address,uint256))")
TraderJoeLBLiquidityAddNative = MustSelector("addLiquidityNATIVE((address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int256[],uint256[],uint256[],address,address,uint256))")
TraderJoeLBLiquidityRemove = MustSelector("removeLiquidity(address,address,uint16,uint256,uint256,uint256[],uint256[],address,uint256)")
TraderJoeLBLiquidityRemoveNative = MustSelector("removeLiquidityNATIVE(address,uint16,uint256,uint256,uint256[],uint256[],address,uint256)")
)
// Camelot V2 uses Uniswap V2 style selectors; Camelot V3 builds on Algebra (Uniswap V3 equivalent).
var (
CamelotV2SwapExactTokensForTokens = UniswapV2SwapExactTokensForTokens
CamelotV2SwapTokensForExactTokens = UniswapV2SwapTokensForExactTokens
CamelotV2SwapExactETHForTokens = UniswapV2SwapExactETHForTokens
CamelotV2SwapTokensForExactETH = UniswapV2SwapTokensForExactETH
CamelotV2SwapExactTokensForETH = UniswapV2SwapExactTokensForETH
CamelotV2SwapETHForExactTokens = UniswapV2SwapETHForExactTokens
CamelotV2SwapExactTokensForTokensSupportingFee = UniswapV2SwapExactTokensForTokensSupportingFee
CamelotV2SwapExactETHForTokensSupportingFee = UniswapV2SwapExactETHForTokensSupportingFee
CamelotV2SwapExactTokensForETHSupportingFee = UniswapV2SwapExactTokensForETHSupportingFee
CamelotV2AddLiquidity = UniswapV2AddLiquidity
CamelotV2AddLiquidityETH = UniswapV2AddLiquidityETH
CamelotV3ExactInputSingle = UniswapV3ExactInputSingle
CamelotV3ExactInput = UniswapV3ExactInput
CamelotV3ExactOutputSingle = UniswapV3ExactOutputSingle
CamelotV3ExactOutput = UniswapV3ExactOutput
CamelotV3Multicall = UniswapV3Multicall
CamelotV3MulticallWithDeadline = UniswapV3MulticallWithDeadline
CamelotV3MulticallWithBlockhash = UniswapV3MulticallWithBlockhash
)
// Additional selectors
var (
UniswapV2SwapExactTokensForTokensSupportingFeeLegacy = MustSelector("swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256,uint256,address[],address)")
NonfungiblePositionManagerMint = MustSelector("mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256))")
)