diff --git a/pkg/arbitrage/calculator.go b/pkg/arbitrage/calculator.go index 41a291c..3538254 100644 --- a/pkg/arbitrage/calculator.go +++ b/pkg/arbitrage/calculator.go @@ -271,19 +271,13 @@ func (c *Calculator) calculateSwapOutputCurve(pool *types.PoolInfo, tokenIn, tok return nil, 0, fmt.Errorf("pool has nil reserves") } - // Determine direction - var reserveIn, reserveOut *big.Int - if tokenIn == pool.Token0 { - reserveIn = pool.Reserve0 - reserveOut = pool.Reserve1 - } else if tokenIn == pool.Token1 { - reserveIn = pool.Reserve1 - reserveOut = pool.Reserve0 - } else { + // Determine direction (validate token is in pool) + if tokenIn != pool.Token0 && tokenIn != pool.Token1 { return nil, 0, fmt.Errorf("token not in pool") } // Simplified: assume 1:1 swap with low slippage for stablecoins + // TODO: Implement proper Curve StableSwap math using reserves and amp coefficient // This is a rough approximation - actual Curve math is more complex fee := pool.Fee if fee == 0 { diff --git a/pkg/arbitrage/detector.go b/pkg/arbitrage/detector.go index a490814..b4e1b98 100644 --- a/pkg/arbitrage/detector.go +++ b/pkg/arbitrage/detector.go @@ -56,7 +56,7 @@ type Detector struct { config *DetectorConfig pathFinder *PathFinder calculator *Calculator - poolCache *cache.PoolCache + poolCache cache.PoolCache logger *slog.Logger // Statistics @@ -72,7 +72,7 @@ func NewDetector( config *DetectorConfig, pathFinder *PathFinder, calculator *Calculator, - poolCache *cache.PoolCache, + poolCache cache.PoolCache, logger *slog.Logger, ) *Detector { if config == nil { @@ -153,7 +153,9 @@ func (d *Detector) DetectOpportunitiesForSwap(ctx context.Context, swapEvent *me ) // Get affected tokens - tokens := []common.Address{swapEvent.TokenIn, swapEvent.TokenOut} + tokenIn, _ := swapEvent.GetInputToken() + tokenOut, _ := swapEvent.GetOutputToken() + tokens := []common.Address{tokenIn, tokenOut} allOpportunities := make([]*Opportunity, 0) diff --git a/pkg/arbitrage/path_finder.go b/pkg/arbitrage/path_finder.go index fe0b892..662a46e 100644 --- a/pkg/arbitrage/path_finder.go +++ b/pkg/arbitrage/path_finder.go @@ -37,13 +37,13 @@ func DefaultPathFinderConfig() *PathFinderConfig { // PathFinder finds arbitrage paths between tokens type PathFinder struct { - cache *cache.PoolCache + cache cache.PoolCache config *PathFinderConfig logger *slog.Logger } // NewPathFinder creates a new path finder -func NewPathFinder(cache *cache.PoolCache, config *PathFinderConfig, logger *slog.Logger) *PathFinder { +func NewPathFinder(cache cache.PoolCache, config *PathFinderConfig, logger *slog.Logger) *PathFinder { if config == nil { config = DefaultPathFinderConfig() } @@ -427,11 +427,11 @@ func (pf *PathFinder) getCommonTokens(ctx context.Context, baseToken common.Addr // ARB arb := common.HexToAddress("0x912CE59144191C1204E64559FE8253a0e49E6548") - common := []common.Address{weth, usdc, usdt, dai, arb} + commonTokens := []common.Address{weth, usdc, usdt, dai, arb} // Filter out the base token itself filtered := make([]common.Address, 0) - for _, token := range common { + for _, token := range commonTokens { if token != baseToken { filtered = append(filtered, token) } diff --git a/pkg/cache/interface.go b/pkg/cache/interface.go index d521e29..5d679d6 100644 --- a/pkg/cache/interface.go +++ b/pkg/cache/interface.go @@ -24,6 +24,9 @@ type PoolCache interface { // GetByLiquidity retrieves pools sorted by liquidity (descending) GetByLiquidity(ctx context.Context, minLiquidity *big.Int, limit int) ([]*types.PoolInfo, error) + // GetPoolsByToken retrieves all pools containing a specific token + GetPoolsByToken(ctx context.Context, token common.Address) ([]*types.PoolInfo, error) + // Add adds or updates a pool in the cache Add(ctx context.Context, pool *types.PoolInfo) error diff --git a/pkg/cache/pool_cache.go b/pkg/cache/pool_cache.go index d8df870..f6b674e 100644 --- a/pkg/cache/pool_cache.go +++ b/pkg/cache/pool_cache.go @@ -112,6 +112,21 @@ func (c *poolCache) GetByLiquidity(ctx context.Context, minLiquidity *big.Int, l return pools, nil } +// GetPoolsByToken retrieves all pools containing a specific token +func (c *poolCache) GetPoolsByToken(ctx context.Context, token common.Address) ([]*types.PoolInfo, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + var pools []*types.PoolInfo + for _, pool := range c.byAddress { + if pool.Token0 == token || pool.Token1 == token { + pools = append(pools, pool) + } + } + + return pools, nil +} + // Add adds or updates a pool in the cache func (c *poolCache) Add(ctx context.Context, pool *types.PoolInfo) error { if pool == nil { diff --git a/pkg/execution/executor.go b/pkg/execution/executor.go index 390d587..79687e5 100644 --- a/pkg/execution/executor.go +++ b/pkg/execution/executor.go @@ -232,7 +232,7 @@ func (e *Executor) Execute(ctx context.Context, opp *arbitrage.Opportunity) (*Ex // Calculate actual profit actualProfit := e.calculateActualProfit(receipt, opp) - gasCost := new(big.Int).Mul(receipt.GasUsed, receipt.EffectiveGasPrice) + gasCost := new(big.Int).Mul(big.NewInt(int64(receipt.GasUsed)), receipt.EffectiveGasPrice) result := &ExecutionResult{ Success: receipt.Status == types.ReceiptStatusSuccessful, diff --git a/pkg/execution/risk_manager.go b/pkg/execution/risk_manager.go index 944de2a..210d882 100644 --- a/pkg/execution/risk_manager.go +++ b/pkg/execution/risk_manager.go @@ -8,8 +8,8 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/your-org/mev-bot/pkg/arbitrage" @@ -254,7 +254,7 @@ func (rm *RiskManager) SimulateExecution( defer cancel() // Create call message - msg := types.CallMsg{ + msg := ethereum.CallMsg{ To: &tx.To, Gas: tx.GasLimit, GasPrice: tx.MaxFeePerGas, diff --git a/pkg/sequencer/reader.go b/pkg/sequencer/reader.go index 5844c68..ede4a8f 100644 --- a/pkg/sequencer/reader.go +++ b/pkg/sequencer/reader.go @@ -2,7 +2,6 @@ package sequencer import ( "context" - "encoding/json" "fmt" "log/slog" "math/big" @@ -66,9 +65,9 @@ type Reader struct { logger *slog.Logger // Components - parsers *parsers.Factory - validator *validation.Validator - poolCache *cache.PoolCache + parsers parsers.Factory + validator validation.Validator + poolCache cache.PoolCache detector *arbitrage.Detector executor *execution.Executor @@ -104,9 +103,9 @@ type Reader struct { // NewReader creates a new sequencer reader func NewReader( config *ReaderConfig, - parsers *parsers.Factory, - validator *validation.Validator, - poolCache *cache.PoolCache, + parsers parsers.Factory, + validator validation.Validator, + poolCache cache.PoolCache, detector *arbitrage.Detector, executor *execution.Executor, logger *slog.Logger, @@ -333,8 +332,8 @@ func (r *Reader) processTxHash(ctx context.Context, txHash string) error { parseStart := time.Now() - // Parse transaction events - events, err := r.parsers.ParseTransaction(tx) + // Parse transaction events (no receipt for pending transactions) + events, err := r.parsers.ParseTransaction(procCtx, tx, nil) if err != nil { r.parseErrors++ return fmt.Errorf("parse failed: %w", err) @@ -347,7 +346,7 @@ func (r *Reader) processTxHash(ctx context.Context, txHash string) error { r.avgParseLatency = time.Since(parseStart) // Validate events - validEvents := r.validator.FilterValid(events) + validEvents := r.validator.FilterValid(procCtx, events) if len(validEvents) == 0 { r.validationErrors++ return nil @@ -358,7 +357,7 @@ func (r *Reader) processTxHash(ctx context.Context, txHash string) error { // Detect arbitrage opportunities for each swap for _, event := range validEvents { // Get input token from the swap - inputToken := event.GetInputToken() + inputToken, _ := event.GetInputToken() // Detect opportunities starting with this token opportunities, err := r.detector.DetectOpportunities(procCtx, inputToken)