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))") )