feat(prod): complete production deployment with Podman containerization

- Migrate from Docker to Podman for enhanced security (rootless containers)
- Add production-ready Dockerfile with multi-stage builds
- Configure production environment with Arbitrum mainnet RPC endpoints
- Add comprehensive test coverage for core modules (exchanges, execution, profitability)
- Implement production audit and deployment documentation
- Update deployment scripts for production environment
- Add container runtime and health monitoring scripts
- Document RPC limitations and remediation strategies
- Implement token metadata caching and pool validation

This commit prepares the MEV bot for production deployment on Arbitrum
with full containerization, security hardening, and operational tooling.

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Krypto Kajun
2025-11-08 10:15:22 -06:00
parent 52d555ccdf
commit 8cba462024
55 changed files with 15523 additions and 4908 deletions

View File

@@ -216,6 +216,231 @@ func (mc *MetadataCache) loadFromDisk() {
mc.logger.Info(fmt.Sprintf("Loaded %d tokens from cache", len(tokens)))
}
// PopulateWithKnownTokens loads all known Arbitrum tokens into the cache
func (mc *MetadataCache) PopulateWithKnownTokens() {
mc.mutex.Lock()
defer mc.mutex.Unlock()
// Define all known Arbitrum tokens with their metadata
knownTokens := map[string]*TokenMetadata{
// Tier 1 - Major Assets
"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1": {
Address: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
Symbol: "WETH",
Name: "Wrapped Ether",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xaf88d065e77c8cC2239327C5EDb3A432268e5831": {
Address: common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),
Symbol: "USDC",
Name: "USD Coin",
Decimals: 6,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9": {
Address: common.HexToAddress("0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"),
Symbol: "USDT",
Name: "Tether USD",
Decimals: 6,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x912CE59144191C1204E64559FE8253a0e49E6548": {
Address: common.HexToAddress("0x912CE59144191C1204E64559FE8253a0e49E6548"),
Symbol: "ARB",
Name: "Arbitrum",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f": {
Address: common.HexToAddress("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f"),
Symbol: "WBTC",
Name: "Wrapped Bitcoin",
Decimals: 8,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1": {
Address: common.HexToAddress("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"),
Symbol: "DAI",
Name: "Dai Stablecoin",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xf97f4df75117a78c1A5a0DBb814Af92458539FB4": {
Address: common.HexToAddress("0xf97f4df75117a78c1A5a0DBb814Af92458539FB4"),
Symbol: "LINK",
Name: "ChainLink Token",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0": {
Address: common.HexToAddress("0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0"),
Symbol: "UNI",
Name: "Uniswap",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a": {
Address: common.HexToAddress("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"),
Symbol: "GMX",
Name: "GMX",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x9623063377AD1B27544C965cCd7342f7EA7e88C7": {
Address: common.HexToAddress("0x9623063377AD1B27544C965cCd7342f7EA7e88C7"),
Symbol: "GRT",
Name: "The Graph",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
// Tier 2 - DeFi Blue Chips
"0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8": {
Address: common.HexToAddress("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8"),
Symbol: "USDC.e",
Name: "USD Coin (Bridged)",
Decimals: 6,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8": {
Address: common.HexToAddress("0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8"),
Symbol: "PENDLE",
Name: "Pendle",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x3082CC23568eA640225c2467653dB90e9250AaA0": {
Address: common.HexToAddress("0x3082CC23568eA640225c2467653dB90e9250AaA0"),
Symbol: "RDNT",
Name: "Radiant Capital",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x539bdE0d7Dbd336b79148AA742883198BBF60342": {
Address: common.HexToAddress("0x539bdE0d7Dbd336b79148AA742883198BBF60342"),
Symbol: "MAGIC",
Name: "Magic",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x3d9907F9a368ad0a51Be60f7Da3b97cf940982D8": {
Address: common.HexToAddress("0x3d9907F9a368ad0a51Be60f7Da3b97cf940982D8"),
Symbol: "GRAIL",
Name: "Camelot (GRAIL)",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
// Tier 3 - Additional High Volume
"0xba5DdD1f9d7F570dc94a51479a000E3BCE967196": {
Address: common.HexToAddress("0xba5DdD1f9d7F570dc94a51479a000E3BCE967196"),
Symbol: "AAVE",
Name: "Aave",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978": {
Address: common.HexToAddress("0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978"),
Symbol: "CRV",
Name: "Curve",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8": {
Address: common.HexToAddress("0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8"),
Symbol: "BAL",
Name: "Balancer",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x354A6dA3fcde098F8389cad84b0182725c6C91dE": {
Address: common.HexToAddress("0x354A6dA3fcde098F8389cad84b0182725c6C91dE"),
Symbol: "COMP",
Name: "Compound",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
"0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879": {
Address: common.HexToAddress("0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879"),
Symbol: "MKR",
Name: "Maker",
Decimals: 18,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
},
}
// Load all known tokens into cache
for _, metadata := range knownTokens {
// Only add if not already in cache
if _, exists := mc.cache[metadata.Address]; !exists {
mc.cache[metadata.Address] = metadata
}
}
mc.logger.Info(fmt.Sprintf("✅ Populated token metadata cache with %d known tokens", len(knownTokens)))
}
// SaveAndClose persists cache and cleans up
func (mc *MetadataCache) SaveAndClose() {
mc.saveToDisk()

View File

@@ -0,0 +1,383 @@
package tokens
import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/fraktal/mev-beta/internal/logger"
)
func TestNewMetadataCache(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
assert.NotNil(t, cache)
assert.NotNil(t, cache.cache)
assert.Equal(t, log, cache.logger)
assert.Equal(t, "data/tokens.json", cache.cacheFile)
}
func TestTokenMetadataCreation(t *testing.T) {
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: "USDC",
Name: "USD Coin",
Decimals: 6,
Verified: true,
FirstSeen: time.Now(),
LastSeen: time.Now(),
SeenCount: 1,
}
assert.Equal(t, "USDC", metadata.Symbol)
assert.Equal(t, "USD Coin", metadata.Name)
assert.Equal(t, uint8(6), metadata.Decimals)
assert.True(t, metadata.Verified)
assert.Equal(t, uint64(1), metadata.SeenCount)
}
func TestCacheGetMissing(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata, exists := cache.Get(address)
assert.False(t, exists)
assert.Nil(t, metadata)
}
func TestCacheSetAndGet(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: "USDC",
Name: "USD Coin",
Decimals: 6,
Verified: true,
SeenCount: 1,
}
cache.Set(metadata)
retrieved, exists := cache.Get(metadata.Address)
assert.True(t, exists)
assert.NotNil(t, retrieved)
assert.Equal(t, "USDC", retrieved.Symbol)
assert.Equal(t, uint8(6), retrieved.Decimals)
}
func TestCacheSetFirstSeen(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: "USDC",
Name: "USD Coin",
Decimals: 6,
}
before := time.Now()
cache.Set(metadata)
after := time.Now()
retrieved, exists := cache.Get(metadata.Address)
assert.True(t, exists)
assert.NotNil(t, retrieved.FirstSeen)
assert.True(t, retrieved.FirstSeen.After(before.Add(-1*time.Second)) || retrieved.FirstSeen.Equal(before))
assert.True(t, retrieved.FirstSeen.Before(after.Add(1*time.Second)) || retrieved.FirstSeen.Equal(after))
}
func TestCacheMultipleTokens(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
tokens := []struct {
address string
symbol string
decimals uint8
}{
{"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "USDC", 6},
{"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "WETH", 18},
{"0xdAC17F958D2ee523a2206206994597C13D831ec7", "USDT", 6},
}
for _, token := range tokens {
metadata := &TokenMetadata{
Address: common.HexToAddress(token.address),
Symbol: token.symbol,
Decimals: token.decimals,
Verified: true,
SeenCount: 1,
}
cache.Set(metadata)
}
assert.Equal(t, 3, len(cache.cache))
for _, token := range tokens {
retrieved, exists := cache.Get(common.HexToAddress(token.address))
assert.True(t, exists)
assert.Equal(t, token.symbol, retrieved.Symbol)
assert.Equal(t, token.decimals, retrieved.Decimals)
}
}
func TestGetOrCreateMissing(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := cache.GetOrCreate(address)
assert.NotNil(t, metadata)
assert.Equal(t, "UNKNOWN", metadata.Symbol)
assert.Equal(t, "Unknown Token", metadata.Name)
assert.Equal(t, uint8(18), metadata.Decimals) // Default assumption
assert.False(t, metadata.Verified)
assert.Equal(t, address, metadata.Address)
}
func TestGetOrCreateExisting(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
Verified: true,
SeenCount: 1,
}
cache.Set(metadata)
retrieved := cache.GetOrCreate(address)
assert.Equal(t, "USDC", retrieved.Symbol)
assert.Equal(t, uint8(6), retrieved.Decimals)
assert.True(t, retrieved.Verified)
}
func TestSeenCountIncrement(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
SeenCount: 1,
}
// First set
cache.Set(metadata)
retrieved, _ := cache.Get(address)
assert.Equal(t, uint64(1), retrieved.SeenCount)
// Second set - should increment
metadata2 := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
SeenCount: 1,
}
cache.Set(metadata2)
retrieved2, _ := cache.Get(address)
assert.Equal(t, uint64(2), retrieved2.SeenCount)
}
func TestLastSeenUpdate(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
}
cache.Set(metadata)
firstLastSeen := cache.cache[address].LastSeen
time.Sleep(10 * time.Millisecond)
metadata2 := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
}
cache.Set(metadata2)
secondLastSeen := cache.cache[address].LastSeen
assert.True(t, secondLastSeen.After(firstLastSeen))
}
func TestFirstSeenPreserved(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
address := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
}
cache.Set(metadata)
firstFirstSeen := cache.cache[address].FirstSeen
time.Sleep(10 * time.Millisecond)
metadata2 := &TokenMetadata{
Address: address,
Symbol: "USDC",
Decimals: 6,
}
cache.Set(metadata2)
secondFirstSeen := cache.cache[address].FirstSeen
assert.Equal(t, firstFirstSeen, secondFirstSeen)
}
func TestTokenMetadataVerified(t *testing.T) {
tests := []struct {
name string
verified bool
symbol string
}{
{"Verified USDC", true, "USDC"},
{"Verified WETH", true, "WETH"},
{"Unverified token", false, "UNKNOWN"},
{"Unverified custom", false, "CUSTOM"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: tt.symbol,
Verified: tt.verified,
SeenCount: 1,
}
assert.Equal(t, tt.verified, metadata.Verified)
})
}
}
func TestTotalSupplyMetadata(t *testing.T) {
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: "USDC",
TotalSupply: "30000000000000000", // 30M USDC
Decimals: 6,
Verified: true,
SeenCount: 1,
}
assert.NotEmpty(t, metadata.TotalSupply)
assert.Equal(t, "30000000000000000", metadata.TotalSupply)
}
func TestCacheConcurrency(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
done := make(chan bool, 10)
errors := make(chan error, 10)
// Test concurrent writes
for i := 0; i < 5; i++ {
go func(index int) {
addr := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
metadata := &TokenMetadata{
Address: addr,
Symbol: "USDC",
Decimals: 6,
SeenCount: uint64(index),
}
cache.Set(metadata)
done <- true
}(i)
}
// Test concurrent reads
for i := 0; i < 5; i++ {
go func() {
addr := common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
_, _ = cache.Get(addr)
done <- true
}()
}
// Wait for all goroutines
for i := 0; i < 10; i++ {
select {
case <-done:
// Success
case <-errors:
t.Fatal("Concurrent operation failed")
}
}
}
func TestCacheSize(t *testing.T) {
log := logger.New("info", "text", "")
cache := NewMetadataCache(log)
addresses := []string{
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
"0x2260FAC5E5542a773Aa44fBCfeDd66150d0310be",
}
for _, addr := range addresses {
metadata := &TokenMetadata{
Address: common.HexToAddress(addr),
Symbol: "TEST",
Decimals: 18,
SeenCount: 1,
}
cache.Set(metadata)
}
assert.Equal(t, len(addresses), len(cache.cache))
}
func TestMetadataDecimalVariations(t *testing.T) {
tests := []struct {
symbol string
decimals uint8
expected uint8
}{
{"USDC", 6, 6},
{"USDT", 6, 6},
{"WETH", 18, 18},
{"DAI", 18, 18},
{"WBTC", 8, 8},
{"LINK", 18, 18},
{"AAVE", 18, 18},
}
for _, tt := range tests {
t.Run(tt.symbol, func(t *testing.T) {
metadata := &TokenMetadata{
Address: common.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"),
Symbol: tt.symbol,
Decimals: tt.decimals,
SeenCount: 1,
}
assert.Equal(t, tt.expected, metadata.Decimals)
})
}
}