CRITICAL BUG FIX: - MultiHopScanner.updateTokenGraph() was EMPTY - adding no pools! - Result: Token graph had 0 pools, found 0 arbitrage paths - All opportunities showed estimatedProfitETH: 0.000000 FIX APPLIED: - Populated token graph with 8 high-liquidity Arbitrum pools: * WETH/USDC (0.05% and 0.3% fees) * USDC/USDC.e (0.01% - common arbitrage) * ARB/USDC, WETH/ARB, WETH/USDT * WBTC/WETH, LINK/WETH - These are REAL verified pool addresses with high volume AGGRESSIVE THRESHOLD CHANGES: - Min profit: 0.0001 ETH → 0.00001 ETH (10x lower, ~$0.02) - Min ROI: 0.05% → 0.01% (5x lower) - Gas multiplier: 5x → 1.5x (3.3x lower safety margin) - Max slippage: 3% → 5% (67% higher tolerance) - Max paths: 100 → 200 (more thorough scanning) - Cache expiry: 2min → 30sec (fresher opportunities) EXPECTED RESULTS (24h): - 20-50 opportunities with profit > $0.02 (was 0) - 5-15 execution attempts (was 0) - 1-2 successful executions (was 0) - $0.02-$0.20 net profit (was $0) WARNING: Aggressive settings may result in some losses Monitor closely for first 6 hours and adjust if needed Target: First profitable execution within 24 hours 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
59 lines
4.8 KiB
Markdown
59 lines
4.8 KiB
Markdown
# MEV Bot Code Review — October 27, 2025
|
||
|
||
## Overview
|
||
- **Scope:** Core arbitrage execution path, security/key management, operational configuration.
|
||
- **Reviewer:** Codex (GPT-5)
|
||
- **Tests Run:** `go test ./...` *(fails — see Findings #6)*
|
||
- **Status:** Blocking issues identified; remediation required before further rollout.
|
||
|
||
## Critical Findings
|
||
|
||
### 1. Live framework constructed with nil dependencies
|
||
- **Location:** `pkg/arbitrage/service.go:247-276`, `pkg/arbitrage/service.go:1668-1767`
|
||
- **What’s wrong:** `FlashSwapExecutor` and `LiveExecutionFramework` are instantiated with a nil `KeyManager` and zeroed contract addresses, yet `StartLiveMode` / `ExecuteOpportunityLive` invoke them during runtime.
|
||
- **Impact:** First execution attempts call `getTransactionOptions` → `executor.keyManager.GetActivePrivateKey()` and crash with “key manager not configured,” disabling live/monitor modes in production.
|
||
- **Fix:** Pass the real `security.KeyManager` and configured contract addresses into `NewFlashSwapExecutor` / `NewLiveExecutionFramework`, or guard live mode until those dependencies exist.
|
||
|
||
### 2. Shared `TransactOpts` causes race conditions & nonce reuse
|
||
- **Location:** `pkg/arbitrage/executor.go:384-407`, `pkg/arbitrage/service.go:636-674`, `config/arbitrum_production.yaml:255`
|
||
- **What’s wrong:** A single `*bind.TransactOpts` is stored on `ArbitrageExecutor` and mutated inside `ExecuteArbitrage`. Multiple opportunities are launched concurrently (config allows 3), so goroutines share and overwrite nonce, gas limit, and fee fields.
|
||
- **Impact:** High probability of duplicate nonces, incorrect gas bids, and data races leading to reverted or invalid transactions under load.
|
||
- **Fix:** Create a fresh `TransactOpts` per execution (clone signer) and guard shared state; ensure concurrency-safe nonce management.
|
||
|
||
### 3. Key derivation invalidates keystore on restart
|
||
- **Location:** `pkg/security/keymanager.go:1295-1314`, `pkg/security/keymanager.go:303-336`, `pkg/security/security_manager.go:129-138`
|
||
- **What’s wrong:** `deriveEncryptionKey` generates a new random salt each time the process starts, producing a different AES key for the same master secret. Stored encrypted keys/backups become unreadable, and the security manager’s separately constructed key manager derives yet another key.
|
||
- **Impact:** Keys created in one run cannot be decrypted after restart; signing fails, and backups are useless. Production restart equals outage.
|
||
- **Fix:** Persist the salt (e.g., alongside keystore) so the derived key is stable, or accept a user-provided salt. Ensure a single key-manager instance per keystore.
|
||
|
||
### 4. Production config silently overrides local runs
|
||
- **Location:** `cmd/mev-bot/main.go:83-89`
|
||
- **What’s wrong:** If `config/arbitrum_production.yaml` exists, it is always loaded—even in development—overriding `config/local.yaml`.
|
||
- **Impact:** Local tests default to live Arbitrum RPC endpoints and contracts, risking quota drain or unwanted on-chain activity.
|
||
- **Fix:** Respect `GO_ENV` (development vs production) before loading the production config; make the override explicit via CLI flag or env var.
|
||
|
||
### 5. Public repo leaks Chainstack endpoint token
|
||
- **Location:** `config/providers.yaml:36-55`, `docker-compose.production.yaml:17-19`
|
||
- **What’s wrong:** Hard-coded Chainstack URL includes an active access token.
|
||
- **Impact:** Anyone cloning the repo can consume RPC quota or launch attacks through that endpoint; provider may revoke access.
|
||
- **Fix:** Rotate the credential immediately and remove it from version control. Replace with placeholder variables documented for operators.
|
||
|
||
## Additional Findings
|
||
|
||
### 6. Test suite failing due to duplicate main packages
|
||
- **Location:** `scripts/load-pools.go:1-89`, `scripts/generate-key.go:1-70`
|
||
- **What’s wrong:** Multiple standalone utilities share the `github.com/fraktal/mev-beta/scripts` package, so `go test ./...` fails with “main redeclared.”
|
||
- **Impact:** CI cannot stay green; future regressions won’t surface automatically.
|
||
- **Fix:** Move each tool into its own module/folder (e.g., `scripts/cmd/...`) or add build tags to exclude them from the main module tests.
|
||
|
||
## Recommended Next Steps
|
||
1. Wire live execution components to real contract/key dependencies or gate the feature.
|
||
2. Refactor transaction signing to use isolated `TransactOpts` and robust nonce management.
|
||
3. Stabilize key derivation and consolidate key-manager ownership.
|
||
4. Adjust config loading logic; require explicit opt-in for production settings.
|
||
5. Rotate the leaked Chainstack token and scrub it from history/configs.
|
||
6. Reorganize Go scripts so `go test ./...` passes again; rerun full regression afterward.
|
||
|
||
## Test Status
|
||
- `go test ./...` — **FAILED**: build error (`github.com/fraktal/mev-beta/scripts` contains multiple `main` definitions).
|