Completed clean root directory structure: - Root now contains only: .git, .env, docs/, orig/ - Moved all remaining files and directories to orig/: - Config files (.claude, .dockerignore, .drone.yml, etc.) - All .env variants (except active .env) - Git config (.gitconfig, .github, .gitignore, etc.) - Tool configs (.golangci.yml, .revive.toml, etc.) - Documentation (*.md files, @prompts) - Build files (Dockerfiles, Makefile, go.mod, go.sum) - Docker compose files - All source directories (scripts, tests, tools, etc.) - Runtime directories (logs, monitoring, reports) - Dependency files (node_modules, lib, cache) - Special files (--delete) - Removed empty runtime directories (bin/, data/) V2 structure is now clean: - docs/planning/ - V2 planning documents - orig/ - Complete V1 codebase preserved - .env - Active environment config (not in git) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
208 lines
6.8 KiB
Go
208 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
)
|
|
|
|
func main() {
|
|
// Pool to identify
|
|
poolAddr := common.HexToAddress("0xC6962004f452bE9203591991D15f6b388e09E8D0")
|
|
|
|
fmt.Println("========================================")
|
|
fmt.Printf("Identifying Pool: %s\n", poolAddr.Hex())
|
|
fmt.Println("========================================")
|
|
fmt.Println()
|
|
|
|
// Connect to Arbitrum
|
|
client, err := ethclient.Dial("https://arb1.arbitrum.io/rpc")
|
|
if err != nil {
|
|
log.Fatal("Failed to connect:", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
// First check if contract exists
|
|
code, err := client.CodeAt(ctx, poolAddr, nil)
|
|
if err != nil {
|
|
log.Fatal("Failed to get contract code:", err)
|
|
}
|
|
|
|
if len(code) == 0 {
|
|
fmt.Println("❌ NO CONTRACT AT THIS ADDRESS")
|
|
return
|
|
}
|
|
|
|
fmt.Printf("✅ Contract exists (%d bytes)\n", len(code))
|
|
fmt.Println()
|
|
|
|
// Method selectors for detection
|
|
selectors := map[string][]byte{
|
|
"token0": {0x0d, 0xfe, 0x16, 0x81}, // Common to many DEXs
|
|
"token1": {0xd2, 0x12, 0x20, 0xa7}, // Correct selector for token1()
|
|
"fee": {0xdd, 0xca, 0x3f, 0x43}, // UniswapV3
|
|
"slot0": {0x38, 0x50, 0xc7, 0xbd}, // UniswapV3
|
|
"globalState": {0x13, 0xaf, 0x40, 0x35}, // Algebra
|
|
"getReserves": {0x09, 0x02, 0xf1, 0xac}, // UniswapV2
|
|
"liquidity": {0x1a, 0x68, 0x6d, 0x0f}, // UniswapV3
|
|
"factory": {0xc4, 0x5a, 0x01, 0x55}, // Common
|
|
"tickSpacing": {0xd0, 0xc9, 0x38, 0x91}, // UniswapV3
|
|
"maxLiquidityPerTick": {0x70, 0xcf, 0x75, 0x4a}, // UniswapV3
|
|
"sqrtPriceX96": {0x88, 0x5a, 0xdb, 0x02}, // Some V3 variants
|
|
"observations": {0x25, 0x2c, 0x09, 0xd7}, // UniswapV3
|
|
"feeGrowthGlobal0X128": {0xf3, 0x05, 0x83, 0x99}, // UniswapV3
|
|
"feeGrowthGlobal1X128": {0x46, 0x14, 0x16, 0x27}, // UniswapV3
|
|
}
|
|
|
|
fmt.Println("Testing Method Signatures:")
|
|
fmt.Println("--------------------------")
|
|
|
|
results := make(map[string]bool)
|
|
tokenAddresses := make(map[string]common.Address)
|
|
|
|
for name, selector := range selectors {
|
|
result, err := client.CallContract(ctx, ethereum.CallMsg{
|
|
To: &poolAddr,
|
|
Data: selector,
|
|
}, nil)
|
|
|
|
if err == nil && len(result) > 0 {
|
|
results[name] = true
|
|
fmt.Printf("✅ %s(): SUCCESS", name)
|
|
|
|
// Extract token addresses if applicable
|
|
if name == "token0" || name == "token1" {
|
|
if len(result) >= 32 {
|
|
addr := common.BytesToAddress(result[12:32])
|
|
tokenAddresses[name] = addr
|
|
fmt.Printf(" -> %s", addr.Hex())
|
|
}
|
|
}
|
|
|
|
// Show fee value
|
|
if name == "fee" && len(result) >= 32 {
|
|
// Fee is uint24, stored in the last 3 bytes of the 32-byte word
|
|
fee := uint32(result[29])<<16 | uint32(result[30])<<8 | uint32(result[31])
|
|
fmt.Printf(" -> %d (%.2f%%)", fee, float64(fee)/10000)
|
|
}
|
|
|
|
fmt.Println()
|
|
} else {
|
|
results[name] = false
|
|
if err != nil {
|
|
fmt.Printf("❌ %s(): FAILED - %v\n", name, err)
|
|
} else {
|
|
fmt.Printf("❌ %s(): FAILED - empty result\n", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println()
|
|
fmt.Println("Analysis:")
|
|
fmt.Println("---------")
|
|
|
|
// Analyze results
|
|
hasToken0 := results["token0"]
|
|
hasToken1 := results["token1"]
|
|
hasFee := results["fee"]
|
|
hasSlot0 := results["slot0"]
|
|
hasGlobalState := results["globalState"]
|
|
hasGetReserves := results["getReserves"]
|
|
hasLiquidity := results["liquidity"]
|
|
hasTickSpacing := results["tickSpacing"]
|
|
hasMaxLiquidityPerTick := results["maxLiquidityPerTick"]
|
|
hasFeeGrowthGlobal0 := results["feeGrowthGlobal0X128"]
|
|
hasFeeGrowthGlobal1 := results["feeGrowthGlobal1X128"]
|
|
|
|
fmt.Printf("Has token0/token1: %v/%v\n", hasToken0, hasToken1)
|
|
fmt.Printf("Has fee: %v\n", hasFee)
|
|
fmt.Printf("Has slot0: %v\n", hasSlot0)
|
|
fmt.Printf("Has globalState: %v\n", hasGlobalState)
|
|
fmt.Printf("Has getReserves: %v\n", hasGetReserves)
|
|
fmt.Printf("Has liquidity: %v\n", hasLiquidity)
|
|
fmt.Printf("Has tickSpacing: %v\n", hasTickSpacing)
|
|
fmt.Printf("Has maxLiquidityPerTick: %v\n", hasMaxLiquidityPerTick)
|
|
fmt.Printf("Has feeGrowthGlobal0/1: %v/%v\n", hasFeeGrowthGlobal0, hasFeeGrowthGlobal1)
|
|
|
|
fmt.Println()
|
|
fmt.Println("========================================")
|
|
fmt.Println("IDENTIFICATION RESULT:")
|
|
fmt.Println("========================================")
|
|
|
|
// Identification logic
|
|
if hasToken0 && hasToken1 && hasSlot0 && hasFee && hasTickSpacing && hasMaxLiquidityPerTick {
|
|
fmt.Println("✅ Pool Type: UNISWAP V3")
|
|
fmt.Println(" Confidence: 95%")
|
|
fmt.Println(" Reason: Has all UniswapV3 signature methods")
|
|
if token0, ok := tokenAddresses["token0"]; ok {
|
|
fmt.Printf(" Token0: %s\n", token0.Hex())
|
|
}
|
|
if token1, ok := tokenAddresses["token1"]; ok {
|
|
fmt.Printf(" Token1: %s\n", token1.Hex())
|
|
}
|
|
} else if hasToken0 && hasToken1 && hasGlobalState && !hasSlot0 {
|
|
fmt.Println("✅ Pool Type: ALGEBRA-BASED (Camelot/QuickSwap V3)")
|
|
fmt.Println(" Confidence: 90%")
|
|
fmt.Println(" Reason: Has globalState instead of slot0")
|
|
} else if hasToken0 && hasToken1 && hasGetReserves && !hasSlot0 && !hasGlobalState {
|
|
fmt.Println("✅ Pool Type: UNISWAP V2 / SUSHISWAP")
|
|
fmt.Println(" Confidence: 85%")
|
|
fmt.Println(" Reason: Has getReserves, no slot0/globalState")
|
|
} else if hasToken0 && hasToken1 {
|
|
fmt.Println("⚠️ Pool Type: UNKNOWN DEX")
|
|
fmt.Println(" Confidence: 30%")
|
|
fmt.Println(" Reason: Has basic token methods but doesn't match known patterns")
|
|
} else {
|
|
fmt.Println("❌ Pool Type: NOT A STANDARD AMM POOL")
|
|
fmt.Println(" Reason: Missing basic token methods")
|
|
}
|
|
|
|
// Additional checks
|
|
fmt.Println()
|
|
fmt.Println("Additional Information:")
|
|
fmt.Println("----------------------")
|
|
|
|
// Check factory
|
|
factorySelector := []byte{0xc4, 0x5a, 0x01, 0x55}
|
|
factoryResult, err := client.CallContract(ctx, ethereum.CallMsg{
|
|
To: &poolAddr,
|
|
Data: factorySelector,
|
|
}, nil)
|
|
|
|
if err == nil && len(factoryResult) >= 32 {
|
|
factory := common.BytesToAddress(factoryResult[12:32])
|
|
fmt.Printf("Factory: %s\n", factory.Hex())
|
|
|
|
// Check known factories
|
|
knownFactories := map[common.Address]string{
|
|
common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"): "UniswapV3 Factory",
|
|
common.HexToAddress("0xc35DADB65012eC5796536bD9864eD8773aBc74C4"): "Sushiswap Factory",
|
|
common.HexToAddress("0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865"): "PancakeSwap V3 Factory",
|
|
}
|
|
|
|
if name, known := knownFactories[factory]; known {
|
|
fmt.Printf(" ✅ Known Factory: %s\n", name)
|
|
}
|
|
}
|
|
|
|
// Try to get current price/state
|
|
if hasSlot0 {
|
|
slot0Selector := []byte{0x38, 0x50, 0xc7, 0xbd}
|
|
slot0Result, err := client.CallContract(ctx, ethereum.CallMsg{
|
|
To: &poolAddr,
|
|
Data: slot0Selector,
|
|
}, nil)
|
|
|
|
if err == nil && len(slot0Result) >= 32 {
|
|
fmt.Println("Slot0 data available (price and tick info)")
|
|
}
|
|
}
|
|
}
|