Files
mev-beta/docs/MATH_FIX_EXAMPLES_20251101.md

11 KiB

Mathematical Fixes - Code Examples

Issue #1: Profit Margin Cap at 100%

BEFORE (WRONG):

// profit_calc.go: Lines 199-210
if profitMarginFloat > 1.0 { // 100% profit margin is unrealistic
    opportunity.ProfitMargin = 0.0
    opportunity.IsExecutable = false
    opportunity.RejectReason = "unrealistic profit margin"
    opportunity.Confidence = 0.0
} else {
    opportunity.ProfitMargin = profitMarginFloat
}

Problem: This rejects ALL opportunities with >100% profit margin, which is mathematically possible in arbitrage.

AFTER (CORRECT):

// Remove the arbitrary 100% cap
// Only reject if profit is negative or margin is NaN
if math.IsNaN(profitMarginFloat) {
    opportunity.ProfitMargin = 0.0
    opportunity.IsExecutable = false
    opportunity.RejectReason = "invalid profit margin calculation"
    opportunity.Confidence = 0.0
} else if profitMarginFloat < 0 {
    opportunity.ProfitMargin = 0.0
    opportunity.IsExecutable = false
    opportunity.RejectReason = "negative profit margin"
    opportunity.Confidence = 0.0
} else {
    opportunity.ProfitMargin = profitMarginFloat
    // Confidence increases with margin
    if profitMarginFloat > 0.5 { // 50% margin
        opportunity.Confidence += 0.2
    }
}

Issue #2: Slippage Calculation Formula

BEFORE (WRONG):

// slippage_protection.go: Lines 59-67
estimatedSlippage := tradeSizeFloat / 2.0

// Apply curve adjustment for larger trades (non-linear slippage)
if tradeSizeFloat > 0.1 { // > 10% of pool
    // Quadratic increase for large trades
    estimatedSlippage = estimatedSlippage * (1 + tradeSizeFloat)
}

Problems:

  1. Formula is not based on actual AMM mechanics
  2. The "curve adjustment" is arbitrary
  3. Doesn't account for fees

AFTER (CORRECT):

// Implement proper Uniswap V2 constant product formula
// For swap: amountOut = (amountIn * 997 * reserveOut) / (reserveIn * 1000 + amountIn * 997)
// Price impact = 1 - (amountOut / (amountIn * spotPrice))

func (sp *SlippageProtector) CalculateAccurateSlippage(
    amountIn *big.Float,
    reserveIn *big.Float,
    reserveOut *big.Float,
    fee uint32, // In basis points, e.g., 3000 for 0.3%
) float64 {
    if amountIn.Sign() <= 0 || reserveIn.Sign() <= 0 || reserveOut.Sign() <= 0 {
        return 0
    }

    // Apply fee: amountInWithFee = amountIn * (10000 - fee) / 10000
    feeMultiplier := new(big.Float).SetInt64(int64(10000 - fee))
    tenThousand := new(big.Float).SetInt64(10000)
    feeFactor := new(big.Float).Quo(feeMultiplier, tenThousand)
    
    amountInWithFee := new(big.Float).Mul(amountIn, feeFactor)

    // Numerator = amountInWithFee * reserveOut
    numerator := new(big.Float).Mul(amountInWithFee, reserveOut)

    // Denominator = reserveIn * 10000 + amountInWithFee
    reserveInTenK := new(big.Float).Mul(reserveIn, tenThousand)
    denominator := new(big.Float).Add(reserveInTenK, amountInWithFee)

    // amountOut = numerator / denominator
    amountOut := new(big.Float).Quo(numerator, denominator)

    // Spot price = reserveOut / reserveIn
    spotPrice := new(big.Float).Quo(reserveOut, reserveIn)

    // Expected output = amountIn * spotPrice
    expectedOut := new(big.Float).Mul(amountIn, spotPrice)

    // Slippage = (expectedOut - amountOut) / expectedOut
    if expectedOut.Sign() <= 0 {
        return 0
    }
    
    diff := new(big.Float).Sub(expectedOut, amountOut)
    slippageRatio := new(big.Float).Quo(diff, expectedOut)
    
    slippage, _ := slippageRatio.Float64()
    if slippage < 0 {
        return 0
    }
    if slippage > 1.0 {
        return 1.0
    }
    return slippage
}

Issue #3: Float to Int Conversion for Profit Comparison

BEFORE (WRONG):

// profit_calc.go: Lines 214-216
if netProfit.Sign() > 0 {
    netProfitWei, _ := netProfit.Int(nil)  // Truncates decimal places!
    if netProfitWei.Cmp(spc.minProfitThreshold) >= 0 {
        // Execute opportunity
    }
}

Problem:

  • Converts big.Float to big.Int, truncating all decimal places
  • 0.00005 ETH becomes 0 when converted to Int
  • Valid opportunities are incorrectly rejected

AFTER (CORRECT):

// profit_calc.go: Keep netProfit as big.Float
if netProfit.Sign() > 0 {
    minThresholdFloat := new(big.Float).SetInt(spc.minProfitThreshold)
    minThresholdFloat.Quo(minThresholdFloat, new(big.Float).SetInt64(1e18)) // Convert wei to ETH
    
    if netProfit.Cmp(minThresholdFloat) >= 0 {
        // Execute opportunity
    }
}

// Or better yet, use UniversalDecimal throughout:
netProfitDecimal := &math.UniversalDecimal{
    Value:    netProfit.Int(nil), // Only convert when absolutely necessary
    Decimals: 18,
    Symbol:   "ETH",
}

if netProfitDecimal.Cmp(spc.minProfitThresholdDecimal) >= 0 {
    // Execute opportunity
}

Issue #4: Price Impact Missing Fee Adjustment

BEFORE (WRONG):

// exchange_math.go: Lines 128-146
amountOut, err := u.CalculateAmountOut(amountIn, reserveIn, reserveOut, 3000)
if err != nil {
    return 0, err
}

// WRONG: Using raw amountIn instead of amountInWithFee
newReserveIn := new(big.Int).Add(reserveIn, amountIn)  // ← BUG HERE
newReserveOut := new(big.Int).Sub(reserveOut, amountOut)

priceAfter := new(big.Float).Quo(new(big.Float).SetInt(newReserveOut), new(big.Float).SetInt(newReserveIn))

Problem: Uses raw amountIn instead of the fee-adjusted amount, underestimating price impact

AFTER (CORRECT):

// exchange_math.go: Lines 128-146
amountOut, err := u.CalculateAmountOut(amountIn, reserveIn, reserveOut, 3000)
if err != nil {
    return 0, err
}

// Apply fee BEFORE calculating new reserves
if fee == 0 {
    fee = 3000
}
feeFactor := big.NewInt(int64(10000 - fee))
amountInWithFee := new(big.Int).Mul(amountIn, feeFactor)
amountInWithFee.Div(amountInWithFee, big.NewInt(10000))

// Use fee-adjusted amount in reserve calculation
newReserveIn := new(big.Int).Add(reserveIn, amountInWithFee)  // ← FIXED
newReserveOut := new(big.Int).Sub(reserveOut, amountOut)

priceAfter := new(big.Float).Quo(new(big.Float).SetInt(newReserveOut), new(big.Float).SetInt(newReserveIn))

Issue #5: Division by Zero Protection

BEFORE (WRONG):

// slippage_protection.go: Line 56
tradeSizeRatio := new(big.Float).Quo(tradeAmount, poolLiquidity)

Problem: No check if poolLiquidity is zero

AFTER (CORRECT):

// Add proper validation
if poolLiquidity == nil || poolLiquidity.Sign() <= 0 {
    return &SlippageAnalysis{
        IsAcceptable:   false,
        RiskLevel:      "Extreme",
        Recommendation: "Invalid pool liquidity for slippage calculation",
    }
}

tradeSizeRatio := new(big.Float).Quo(tradeAmount, poolLiquidity)

Issue #6: Arbitrary Gas Cost Buffer

BEFORE (WRONG):

// profit_calc.go: Lines 271-273
// Add 20% buffer for MEV competition
buffer := new(big.Int).Div(gasCostWei, big.NewInt(5)) // 20%
gasCostWei.Add(gasCostWei, buffer)

Problem: 20% is arbitrary, not based on actual network conditions

AFTER (CORRECT):

// Dynamic gas adjustment based on network state
func (spc *ProfitCalculator) calculateGasCostWithNetworkAdjustment() *big.Float {
    gasLimitInt64, _ := security.SafeUint64ToInt64(spc.gasLimit)
    gasLimit := big.NewInt(gasLimitInt64)
    currentGasPrice := spc.GetCurrentGasPrice()
    gasCostWei := new(big.Int).Mul(currentGasPrice, gasLimit)

    // Dynamic buffer based on gas price volatility
    gasPrice := spc.GetCurrentGasPrice()
    
    // Get recent gas price trend (this would need implementation)
    recentAvgGasPrice := spc.GetRecentAverageGasPrice() // Needs implementation
    
    if gasPrice == nil || recentAvgGasPrice == nil || recentAvgGasPrice.Sign() == 0 {
        // Default conservative estimate
        buffer := new(big.Int).Div(gasCostWei, big.NewInt(5)) // 20%
        gasCostWei.Add(gasCostWei, buffer)
    } else {
        // Calculate buffer as percentage of price change
        priceDiff := new(big.Int).Sub(gasPrice, recentAvgGasPrice)
        if priceDiff.Sign() > 0 {
            // Gas price is above average - add 10-30% buffer
            bufferPercent := calculateBufferPercent(priceDiff, recentAvgGasPrice)
            buffer := new(big.Int).Mul(gasCostWei, big.NewInt(int64(bufferPercent)))
            buffer.Div(buffer, big.NewInt(100))
            gasCostWei.Add(gasCostWei, buffer)
        } else {
            // Gas price is below average - use minimal buffer
            buffer := new(big.Int).Div(gasCostWei, big.NewInt(20)) // 5%
            gasCostWei.Add(gasCostWei, buffer)
        }
    }

    // Convert to big.Float for easier calculation
    gasCostFloat := new(big.Float).SetInt(gasCostWei)
    etherDenominator := new(big.Float).SetInt(big.NewInt(1e18))
    return new(big.Float).Quo(gasCostFloat, etherDenominator)
}

Issue #7: Proper Rounding for Amount Calculations

BEFORE (WRONG):

// exchange_math.go: Lines 107-109
// amountIn = numerator / denominator + 1 (round up)
amountIn := new(big.Int).Div(numerator, denominator)
amountIn.Add(amountIn, big.NewInt(1))  // Always adds 1

Problem: Always adds 1, even when exact division occurs

AFTER (CORRECT):

// Implement proper banker's rounding (round-half-to-even)
amountIn := new(big.Int).Div(numerator, denominator)

// Check if there's a remainder
remainder := new(big.Int).Mod(numerator, denominator)
if remainder.Sign() > 0 {
    // There's a remainder, round up
    amountIn.Add(amountIn, big.NewInt(1))
}

// Alternative: Always round up for safety
amountIn := new(big.Int).Add(numerator, new(big.Int).Sub(denominator, big.NewInt(1)))
amountIn.Div(amountIn, denominator)

Testing the Fixes

Add these test cases:

func TestProfitMarginWithHighReturns(t *testing.T) {
    // Should allow 200% profit margin
    profitMargin := 2.0 // 200%
    
    // Should NOT be rejected
    if profitMargin > 1.0 {
        t.Fatal("Valid 200% profit margin incorrectly rejected")
    }
}

func TestSlippageCalculation(t *testing.T) {
    // Test against known Uniswap V2 swap
    amountIn, _ := new(big.Float).SetString("1000000000000000000")     // 1 ETH
    reserveIn, _ := new(big.Float).SetString("10000000000000000000")   // 10 ETH
    reserveOut, _ := new(big.Float).SetString("100000000000000000000") // 100 tokens
    
    slippage := CalculateAccurateSlippage(amountIn, reserveIn, reserveOut, 3000)
    
    // Expected: ~8.26% slippage for this swap
    if slippage < 0.08 || slippage > 0.09 {
        t.Errorf("Slippage calculation incorrect: got %f, expected ~0.0826", slippage)
    }
}

func TestProfitThresholdComparison(t *testing.T) {
    // Should accept profits > 0 wei, even very small ones
    netProfit := big.NewFloat(0.00000001) // 0.00000001 ETH (10 wei)
    minThreshold := big.NewFloat(0.00000000) // 0 wei
    
    if netProfit.Cmp(minThreshold) <= 0 {
        t.Fatal("Valid small profit incorrectly rejected")
    }
}