8.3 KiB
8.3 KiB
MEV Bot Blocker - Debug & Fix Guide
Quick Navigation
- Blocker #1 Root Cause:
/home/administrator/projects/mev-beta/pkg/events/parser.go - Blocker #2 Root Cause:
/home/administrator/projects/mev-beta/pkg/arbitrage/multihop.go(lines 522-644) - Blocker #6 Root Cause:
/home/administrator/projects/mev-beta/pkg/arbitrage/service.go - Blocker #10 Root Cause:
/home/administrator/projects/mev-beta/pkg/arbitrum/parser/core.go
Blocker #1: Zero Amount Extraction (HIGHEST PRIORITY)
Symptom
Amount In: 0.000000 tokens
Amount Out: 0.000000 tokens
rejectReason: negative profit after gas and slippage costs
Files to Examine
-
/home/administrator/projects/mev-beta/pkg/events/parser.go- Look for Swap event parsing
- Search for:
amount0,amount1,Amount0,Amount1
-
/home/administrator/projects/mev-beta/pkg/arbitrum/parser/core.go- Look for Uniswap V3 Swap event signature
0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67
-
/home/administrator/projects/mev-beta/pkg/arbitrum/l2_parser.go- Check how events are extracted from logs
- Validate event signature matching
Debug Steps
# 1. Add logging to see what amounts are extracted
# File: pkg/events/parser.go
# Add before returning from ParseSwapEvent:
logger.Debug(fmt.Sprintf("PARSED AMOUNTS: amount0=%s amount1=%s", event.Amount0, event.Amount1))
# 2. Compare to raw event data
# Check: Are amounts in wei? Need to divide by token decimals?
# Example: 1000000000000000000 wei = 1.0 with 18 decimals
# 3. Verify event signature
# Uniswap V3 Swap: 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67
# Should decode: (sender, recipient, amount0, amount1, sqrtPriceX96, liquidity, tick)
What to Look For
- Event signature mismatch (V2 vs V3 signatures are different)
- Token decimal handling (need to convert from wei)
- Signed integer handling (Swap amounts can be negative in V3)
- Wrong field extraction (getting liquidity instead of amount)
Expected Fix
Once amounts are correctly extracted:
// Should see real amounts like:
amount0: 1000000000000000000 (1.0 WETH)
amount1: 2000000000 (2000 USDC @ 6 decimals)
// NOT: 0
Blocker #2: Empty Token Graph
Symptom
⚠️ Start token 0x82aF49... has no adjacent tokens in graph!
Files to Examine
-
/home/administrator/projects/mev-beta/pkg/arbitrage/multihop.go- Lines 502-644:
updateTokenGraph()function - Lines 522-594: Hardcoded pool initialization
- Lines 646-659:
addPoolToGraph()andaddEdge()
- Lines 502-644:
-
/home/administrator/projects/mev-beta/pkg/pools/discovery.go- Where 314 cached pools are loaded
- Pool structure definition (lines 45-61)
Debug Steps
# 1. Check what pools are being loaded
# File: pkg/pools/discovery.go
grep -n "loadPersistedData\|LoadPools" pkg/pools/discovery.go
# 2. Verify pool cache exists and has data
ls -la data/pools.json
head -20 data/pools.json | jq '.[0]'
# 3. Add logging to see token graph building
# File: pkg/arbitrage/multihop.go line 628
# Add after line 628:
logger.Info(fmt.Sprintf("DEBUG: Graph has %d vertices", len(adjacencyList)))
for token, edges := range adjacencyList {
logger.Info(fmt.Sprintf(" Token %s has %d connections", token.Hex()[:8], len(edges)))
}
# 4. Check if pools are being added to graph
# Should see something like:
# ✅ Token graph updated with 314/314 high-liquidity pools
# But currently shows: 8/8 hardcoded pools only
What to Look For
- Hardcoded pool list (lines 522-594) has only 8 pools
- Cached 314 pools are never read into the graph
- No connection between pool discovery and token graph
- Graph is populated at service startup only, never updated
Expected Fix
// Current code (WRONG):
pools := []*PoolInfo{
// 8 hardcoded pools only
{ Address: 0xC31E..., Token0: WETH, Token1: USDC, ... },
// ...
}
// Should be (CORRECT):
// Load 314 pools from cache and add them all to graph
cachedPools := pd.GetAllPools() // Get from PoolDiscovery
for _, pool := range cachedPools {
mhs.addPoolToGraph(pool)
}
// Result: 314 pools, 1000+ graph connections
Blocker #6: Execution Pipeline Disconnected
Symptom
2025/11/02 15:22:38 [INFO] Arbitrage Service Stats
Executed: 0
Successful: 0
Files to Examine
-
/home/administrator/projects/mev-beta/pkg/arbitrage/service.go- Lines 80-130: ArbitrageService struct definition
- Look for:
ExecuteArbitrage(),executor,flashExecutor
-
/home/administrator/projects/mev-beta/pkg/scanner/market/scanner.go- Lines 86-89:
SetOpportunityForwarder() - Look for:
opportunityForwarder.ExecuteArbitrage()
- Lines 86-89:
-
/home/administrator/projects/mev-beta/pkg/arbitrage/executor.go- Look for:
Execute()method that actually submits transactions
- Look for:
Debug Steps
# 1. Search for Execute calls on the executor
grep -n "\.Execute\|ExecuteArbitrage" pkg/arbitrage/service.go
# Expected: Should find multiple calls
# Actual: Likely finds NONE
# 2. Check if opportunityForwarder is actually used
grep -n "opportunityForwarder\." pkg/scanner/market/scanner.go
# Expected: Should call ExecuteArbitrage for valid opportunities
# Actual: Likely only sets it, never calls it
# 3. Check ArbitrageService.Start() to see what goroutines are started
grep -n "go.*(" pkg/arbitrage/service.go | head -20
# Should see: execution loop, monitoring loop, etc.
# Likely missing: execution loop that actually calls executor
What to Look For
- Opportunity forwarder is set but never used
- No goroutine in ArbitrageService.Start() that processes opportunities
- Executor and FlashExecutor exist but are never invoked
- Missing event loop that listens for valid opportunities
Expected Fix
// Current code (WRONG):
func (as *ArbitrageService) Start() error {
as.isRunning = true
go as.monitorLoop() // Only monitoring, no execution
return nil
}
// Should be (CORRECT):
func (as *ArbitrageService) Start() error {
as.isRunning = true
go as.opportunityLoop() // Listen for valid opportunities
go as.executionLoop() // Execute profitable trades
go as.monitoringLoop() // Monitor results
return nil
}
// New method:
func (as *ArbitrageService) opportunityLoop() {
for {
select {
case opp := <-as.opportunityChannel:
if opp.IsExecutable {
as.executeOpportunity(opp)
}
}
}
}
Blocker #10: Event Parser Extracts Zero Amounts
Same as Blocker #1
See section "Blocker #1: Zero Amount Extraction" above.
Verification Checklist
After each fix, verify:
- Event parser extracts non-zero amounts
- Amounts are in correct decimal format (wei vs human readable)
- Token graph has 100+ connections
- Profit calculator receives valid amounts
- At least 50 opportunities marked as isExecutable:true per minute
- Executor methods are called for valid opportunities
- First transaction submits successfully
- Transaction is confirmed on-chain
- Profit is positive
Files to Modify (Summary)
| Blocker | File | Lines | Issue |
|---|---|---|---|
| #1 | pkg/events/parser.go |
? | Amount extraction |
| #1 | pkg/arbitrum/parser/core.go |
? | Event signature/parsing |
| #2 | pkg/arbitrage/multihop.go |
502-644 | Connect pool cache to graph |
| #6 | pkg/arbitrage/service.go |
80-150 | Add execution loop |
| #6 | pkg/scanner/market/scanner.go |
86-89 | Actually use forwarder |
| #10 | pkg/arbitrum/l2_parser.go |
? | Log parsing |
Expected Timeline
- Hour 1-2: Debug event parser, identify why amounts are zero
- Hour 2-3: Fix event parser amount extraction
- Hour 3-4: Connect token graph to pool cache
- Hour 4-5: Verify 50%+ opportunities are executable
- Hour 5-7: Connect execution pipeline
- Hour 7-8: Test first arbitrage execution
- Hour 8-10: Debug and fix any execution issues
- Hour 10+: Monitor first profitable trades
Emergency Debug Command
If system is running and still showing zero amounts:
# Check current amount extraction in real-time
tail -f logs/mev_bot.log | grep -i "Amount In\|Amount Out\|amount.*0x"
# Should show real amounts like:
# Amount In: 1000000000000000000 tokens
# Amount Out: 2000000000 tokens
# If shows zeros, event parser is broken (Blocker #1)