refactor: move all remaining files to orig/ directory
Completed clean root directory structure: - Root now contains only: .git, .env, docs/, orig/ - Moved all remaining files and directories to orig/: - Config files (.claude, .dockerignore, .drone.yml, etc.) - All .env variants (except active .env) - Git config (.gitconfig, .github, .gitignore, etc.) - Tool configs (.golangci.yml, .revive.toml, etc.) - Documentation (*.md files, @prompts) - Build files (Dockerfiles, Makefile, go.mod, go.sum) - Docker compose files - All source directories (scripts, tests, tools, etc.) - Runtime directories (logs, monitoring, reports) - Dependency files (node_modules, lib, cache) - Special files (--delete) - Removed empty runtime directories (bin/, data/) V2 structure is now clean: - docs/planning/ - V2 planning documents - orig/ - Complete V1 codebase preserved - .env - Active environment config (not in git) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
513
orig/test/integration/end_to_end_profit_test.go
Normal file
513
orig/test/integration/end_to_end_profit_test.go
Normal file
@@ -0,0 +1,513 @@
|
||||
//go:build integration && legacy && forked
|
||||
// +build integration,legacy,forked
|
||||
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/fraktal/mev-beta/bindings/arbitrage"
|
||||
arbService "github.com/fraktal/mev-beta/pkg/arbitrage"
|
||||
"github.com/fraktal/mev-beta/pkg/mev"
|
||||
"github.com/fraktal/mev-beta/pkg/oracle"
|
||||
"github.com/fraktal/mev-beta/pkg/uniswap"
|
||||
)
|
||||
|
||||
func TestEndToEndProfitValidation(t *testing.T) {
|
||||
client, cleanup := setupForkedArbitrum(t)
|
||||
defer cleanup()
|
||||
|
||||
// Deploy arbitrage contract
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(42161))
|
||||
require.NoError(t, err)
|
||||
|
||||
contractAddr, tx, contract, err := arbitrage.DeployArbitrageExecutor(
|
||||
auth,
|
||||
client,
|
||||
common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), // Uniswap V3 Factory
|
||||
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), // WETH
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
receipt, err := bind.WaitMined(ctx, client, tx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status)
|
||||
|
||||
t.Run("Real Market Arbitrage Opportunity", func(t *testing.T) {
|
||||
// Real Arbitrum pool addresses with different fee tiers
|
||||
wethUsdcPool05 := common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443") // 0.05%
|
||||
wethUsdcPool30 := common.HexToAddress("0x17c14D2c404D167802b16C450d3c99F88F2c4F4d") // 0.3%
|
||||
|
||||
// Get current prices from both pools
|
||||
price1, err := uniswap.GetPoolPrice(client, wethUsdcPool05)
|
||||
require.NoError(t, err)
|
||||
|
||||
price2, err := uniswap.GetPoolPrice(client, wethUsdcPool30)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Pool 1 (0.05%%) price: %s", price1.String())
|
||||
t.Logf("Pool 2 (0.30%%) price: %s", price2.String())
|
||||
|
||||
// Calculate price difference
|
||||
priceDiff := new(big.Int).Sub(price1, price2)
|
||||
if priceDiff.Sign() < 0 {
|
||||
priceDiff.Neg(priceDiff)
|
||||
}
|
||||
|
||||
// Calculate percentage difference
|
||||
priceDiffPercent := new(big.Int).Div(
|
||||
new(big.Int).Mul(priceDiff, big.NewInt(10000)),
|
||||
price1,
|
||||
)
|
||||
|
||||
t.Logf("Price difference: %s (%s basis points)", priceDiff.String(), priceDiffPercent.String())
|
||||
|
||||
// Test arbitrage opportunity detection
|
||||
swapAmount := big.NewInt(1000000000000000000) // 1 ETH
|
||||
|
||||
opportunity, err := contract.DetectArbitrageOpportunity(nil, wethUsdcPool05, wethUsdcPool30, swapAmount)
|
||||
require.NoError(t, err)
|
||||
|
||||
if opportunity.Profitable {
|
||||
t.Logf("Arbitrage opportunity detected!")
|
||||
t.Logf("Estimated profit: %s ETH", new(big.Float).Quo(
|
||||
new(big.Float).SetInt(opportunity.EstimatedProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
|
||||
// Validate minimum profit threshold
|
||||
minProfit := big.NewInt(10000000000000000) // 0.01 ETH minimum
|
||||
assert.GreaterOrEqual(t, opportunity.EstimatedProfit.Cmp(minProfit), 0,
|
||||
"Profit should meet minimum threshold")
|
||||
|
||||
// Test gas cost calculation
|
||||
gasPrice, err := client.SuggestGasPrice(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
estimatedGas := big.NewInt(300000) // Estimated gas for arbitrage
|
||||
gasCost := new(big.Int).Mul(gasPrice, estimatedGas)
|
||||
|
||||
netProfit := new(big.Int).Sub(opportunity.EstimatedProfit, gasCost)
|
||||
t.Logf("Gas cost: %s ETH", new(big.Float).Quo(
|
||||
new(big.Float).SetInt(gasCost),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
t.Logf("Net profit: %s ETH", new(big.Float).Quo(
|
||||
new(big.Float).SetInt(netProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
|
||||
assert.Greater(t, netProfit.Sign(), 0, "Net profit should be positive after gas costs")
|
||||
} else {
|
||||
t.Log("No profitable arbitrage opportunity detected in current market conditions")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Simulate Large Trade Impact", func(t *testing.T) {
|
||||
// Simulate a large trade that creates arbitrage opportunity
|
||||
wethUsdcPool := common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443")
|
||||
|
||||
// Large swap amount that should create price impact
|
||||
largeSwapAmount := new(big.Int)
|
||||
largeSwapAmount.SetString("100000000000000000000", 10) // 100 ETH
|
||||
|
||||
// Calculate price impact
|
||||
priceImpact, err := contract.CalculatePriceImpact(nil, wethUsdcPool, largeSwapAmount, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Price impact for 100 ETH swap: %s basis points", priceImpact.String())
|
||||
|
||||
// Price impact should be significant for large trades
|
||||
assert.Greater(t, priceImpact.Uint64(), uint64(100), "Large trades should have measurable price impact")
|
||||
|
||||
// Test if this creates arbitrage opportunities
|
||||
if priceImpact.Uint64() > 500 { // More than 5% price impact
|
||||
// This should create profitable arbitrage opportunities
|
||||
t.Log("Large trade creates significant arbitrage opportunity")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Multi-Pool Arbitrage Chain", func(t *testing.T) {
|
||||
// Test arbitrage opportunities across multiple pools
|
||||
pools := []common.Address{
|
||||
common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"), // WETH/USDC 0.05%
|
||||
common.HexToAddress("0x17c14D2c404D167802b16C450d3c99F88F2c4F4d"), // WETH/USDC 0.3%
|
||||
common.HexToAddress("0x641C00A822e8b671738d32a431a4Fb6074E5c79d"), // WETH/USDT 0.05%
|
||||
}
|
||||
|
||||
swapAmount := big.NewInt(5000000000000000000) // 5 ETH
|
||||
|
||||
totalOpportunities := 0
|
||||
totalPotentialProfit := big.NewInt(0)
|
||||
|
||||
for i := 0; i < len(pools); i++ {
|
||||
for j := i + 1; j < len(pools); j++ {
|
||||
opportunity, err := contract.DetectArbitrageOpportunity(nil, pools[i], pools[j], swapAmount)
|
||||
require.NoError(t, err)
|
||||
|
||||
if opportunity.Profitable {
|
||||
totalOpportunities++
|
||||
totalPotentialProfit.Add(totalPotentialProfit, opportunity.EstimatedProfit)
|
||||
|
||||
t.Logf("Opportunity between pool %d and %d: %s ETH profit",
|
||||
i, j, new(big.Float).Quo(
|
||||
new(big.Float).SetInt(opportunity.EstimatedProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Total opportunities found: %d", totalOpportunities)
|
||||
t.Logf("Total potential profit: %s ETH", new(big.Float).Quo(
|
||||
new(big.Float).SetInt(totalPotentialProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestRealWorldGasOptimization(t *testing.T) {
|
||||
client, cleanup := setupForkedArbitrum(t)
|
||||
defer cleanup()
|
||||
|
||||
t.Run("Gas Price Strategy Optimization", func(t *testing.T) {
|
||||
// Get current network conditions
|
||||
gasPrice, err := client.SuggestGasPrice(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get latest block for base fee (EIP-1559)
|
||||
header, err := client.HeaderByNumber(context.Background(), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
baseFee := header.BaseFee
|
||||
t.Logf("Current gas price: %s gwei", new(big.Int).Div(gasPrice, big.NewInt(1000000000)))
|
||||
t.Logf("Current base fee: %s gwei", new(big.Int).Div(baseFee, big.NewInt(1000000000)))
|
||||
|
||||
// Test MEV competition analysis
|
||||
analyzer := mev.NewCompetitionAnalyzer(client)
|
||||
|
||||
opportunity := &mev.MEVOpportunity{
|
||||
Type: mev.TypeArbitrage,
|
||||
EstimatedProfit: big.NewInt(50000000000000000), // 0.05 ETH
|
||||
RequiredGasLimit: big.NewInt(300000),
|
||||
PoolAddress: common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"),
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
competition, err := analyzer.AnalyzeCompetition(ctx, opportunity)
|
||||
require.NoError(t, err)
|
||||
|
||||
strategy, err := analyzer.CalculateOptimalBid(ctx, opportunity, competition)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Recommended priority fee: %s gwei",
|
||||
new(big.Int).Div(strategy.PriorityFeePerGas, big.NewInt(1000000000)))
|
||||
t.Logf("Max fee per gas: %s gwei",
|
||||
new(big.Int).Div(strategy.MaxFeePerGas, big.NewInt(1000000000)))
|
||||
t.Logf("Expected profit after gas: %s ETH",
|
||||
new(big.Float).Quo(
|
||||
new(big.Float).SetInt(strategy.ExpectedProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
|
||||
// Validate strategy is profitable
|
||||
assert.Greater(t, strategy.ExpectedProfit.Sign(), 0, "Strategy should be profitable after gas costs")
|
||||
assert.LessOrEqual(t, strategy.MaxFeePerGas.Cmp(new(big.Int).Mul(baseFee, big.NewInt(3))), 0,
|
||||
"Max fee should not exceed 3x base fee for reasonable execution")
|
||||
})
|
||||
|
||||
t.Run("Gas Limit Optimization", func(t *testing.T) {
|
||||
// Test different gas limits for arbitrage execution
|
||||
gasLimits := []*big.Int{
|
||||
big.NewInt(250000),
|
||||
big.NewInt(300000),
|
||||
big.NewInt(400000),
|
||||
big.NewInt(500000),
|
||||
}
|
||||
|
||||
profit := big.NewInt(80000000000000000) // 0.08 ETH base profit
|
||||
gasPrice := big.NewInt(10000000000) // 10 gwei
|
||||
|
||||
bestGasLimit := big.NewInt(0)
|
||||
bestNetProfit := big.NewInt(0)
|
||||
|
||||
for _, gasLimit := range gasLimits {
|
||||
gasCost := new(big.Int).Mul(gasPrice, gasLimit)
|
||||
netProfit := new(big.Int).Sub(profit, gasCost)
|
||||
|
||||
t.Logf("Gas limit %s: Net profit %s ETH",
|
||||
gasLimit.String(),
|
||||
new(big.Float).Quo(
|
||||
new(big.Float).SetInt(netProfit),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
|
||||
if netProfit.Cmp(bestNetProfit) > 0 {
|
||||
bestNetProfit.Set(netProfit)
|
||||
bestGasLimit.Set(gasLimit)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Optimal gas limit: %s", bestGasLimit.String())
|
||||
assert.Greater(t, bestGasLimit.Uint64(), uint64(0), "Should find optimal gas limit")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRealMarketConditions(t *testing.T) {
|
||||
client, cleanup := setupForkedArbitrum(t)
|
||||
defer cleanup()
|
||||
|
||||
t.Run("Market Volatility Impact", func(t *testing.T) {
|
||||
// Test arbitrage detection under different market conditions
|
||||
service, err := arbService.NewArbitrageService(client)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create events representing different market conditions
|
||||
volatileEvents := []*arbService.SimpleSwapEvent{
|
||||
// Small trade - normal market
|
||||
{
|
||||
TxHash: common.HexToHash("0x1"),
|
||||
Pool: common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"),
|
||||
Token0: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
||||
Token1: common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),
|
||||
Amount0: big.NewInt(1000000000000000000), // 1 ETH
|
||||
Amount1: big.NewInt(-2000000000), // -2000 USDC
|
||||
SqrtPriceX96: func() *big.Int { x, _ := new(big.Int).SetString("79228162514264337593543950336", 10); return x }(),
|
||||
},
|
||||
// Large trade - volatile market
|
||||
{
|
||||
TxHash: common.HexToHash("0x2"),
|
||||
Pool: common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"),
|
||||
Token0: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
||||
Token1: common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),
|
||||
Amount0: func() *big.Int { x, _ := new(big.Int).SetString("50000000000000000000", 10); return x }(), // 50 ETH
|
||||
Amount1: big.NewInt(-100000000000), // -100,000 USDC
|
||||
SqrtPriceX96: func() *big.Int { x, _ := new(big.Int).SetString("80000000000000000000000000000", 10); return x }(),
|
||||
},
|
||||
}
|
||||
|
||||
detectedOpportunities := 0
|
||||
for i, event := range volatileEvents {
|
||||
err := service.ProcessSwapEvent(event)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check if this event would trigger arbitrage detection
|
||||
if service.IsSignificantSwap(event) {
|
||||
detectedOpportunities++
|
||||
t.Logf("Event %d triggered arbitrage detection (amount: %s ETH)",
|
||||
i+1, new(big.Float).Quo(
|
||||
new(big.Float).SetInt(event.Amount0),
|
||||
new(big.Float).SetInt(big.NewInt(1000000000000000000)),
|
||||
).String())
|
||||
}
|
||||
}
|
||||
|
||||
assert.Greater(t, detectedOpportunities, 0, "Should detect opportunities in volatile market")
|
||||
})
|
||||
|
||||
t.Run("Oracle Price Validation", func(t *testing.T) {
|
||||
// Test oracle-based price validation for arbitrage
|
||||
priceOracle := oracle.NewPriceOracle(client)
|
||||
|
||||
// WETH/USDC price from different sources
|
||||
wethAddress := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
||||
usdcAddress := common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Get price from Uniswap V3
|
||||
uniPrice, err := priceOracle.GetUniswapV3Price(ctx, wethAddress, usdcAddress, 500)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get price from alternative DEX (SushiSwap)
|
||||
sushiPrice, err := priceOracle.GetSushiSwapPrice(ctx, wethAddress, usdcAddress)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Uniswap V3 WETH/USDC price: %s", uniPrice.String())
|
||||
t.Logf("SushiSwap WETH/USDC price: %s", sushiPrice.String())
|
||||
|
||||
// Calculate price deviation
|
||||
priceDiff := new(big.Int).Sub(uniPrice, sushiPrice)
|
||||
if priceDiff.Sign() < 0 {
|
||||
priceDiff.Neg(priceDiff)
|
||||
}
|
||||
|
||||
deviationPercent := new(big.Int).Div(
|
||||
new(big.Int).Mul(priceDiff, big.NewInt(10000)),
|
||||
uniPrice,
|
||||
)
|
||||
|
||||
t.Logf("Price deviation: %s basis points", deviationPercent.String())
|
||||
|
||||
// Significant price deviation indicates arbitrage opportunity
|
||||
if deviationPercent.Uint64() > 50 { // More than 0.5%
|
||||
t.Log("Significant price deviation detected - potential arbitrage opportunity")
|
||||
assert.Greater(t, deviationPercent.Uint64(), uint64(50), "Price deviation indicates opportunity")
|
||||
} else {
|
||||
t.Log("Prices are aligned - no immediate arbitrage opportunity")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Liquidity Depth Analysis", func(t *testing.T) {
|
||||
// Test liquidity depth for arbitrage execution
|
||||
pools := []common.Address{
|
||||
common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"), // WETH/USDC 0.05%
|
||||
common.HexToAddress("0x17c14D2c404D167802b16C450d3c99F88F2c4F4d"), // WETH/USDC 0.3%
|
||||
}
|
||||
|
||||
for i, pool := range pools {
|
||||
liquidity, err := uniswap.GetPoolLiquidity(client, pool)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Pool %d liquidity: %s", i+1, liquidity.String())
|
||||
|
||||
// Minimum liquidity threshold for profitable arbitrage
|
||||
minLiquidity := new(big.Int)
|
||||
minLiquidity.SetString("1000000000000000000000", 10) // 1000 ETH equivalent
|
||||
if liquidity.Cmp(minLiquidity) >= 0 {
|
||||
t.Logf("Pool %d has sufficient liquidity for large arbitrage", i+1)
|
||||
} else {
|
||||
t.Logf("Pool %d has limited liquidity - small arbitrage only", i+1)
|
||||
}
|
||||
|
||||
assert.Greater(t, liquidity.Uint64(), uint64(0), "Pool should have measurable liquidity")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestProfitabilityUnderStress(t *testing.T) {
|
||||
client, cleanup := setupForkedArbitrum(t)
|
||||
defer cleanup()
|
||||
|
||||
t.Run("High Gas Price Environment", func(t *testing.T) {
|
||||
// Simulate high gas price conditions (network congestion)
|
||||
highGasPrice := big.NewInt(50000000000) // 50 gwei
|
||||
|
||||
opportunity := &mev.MEVOpportunity{
|
||||
Type: mev.TypeArbitrage,
|
||||
EstimatedProfit: big.NewInt(30000000000000000), // 0.03 ETH
|
||||
RequiredGasLimit: big.NewInt(300000),
|
||||
PoolAddress: common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"),
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
gasCost := new(big.Int).Mul(highGasPrice, opportunity.RequiredGasLimit)
|
||||
netProfit := new(big.Int).Sub(opportunity.EstimatedProfit, gasCost)
|
||||
|
||||
t.Logf("High gas environment - Gas cost: %s ETH, Net profit: %s ETH",
|
||||
new(big.Float).Quo(new(big.Float).SetInt(gasCost), new(big.Float).SetInt(big.NewInt(1e18))),
|
||||
new(big.Float).Quo(new(big.Float).SetInt(netProfit), new(big.Float).SetInt(big.NewInt(1e18))))
|
||||
|
||||
if netProfit.Sign() > 0 {
|
||||
t.Log("Arbitrage remains profitable even with high gas prices")
|
||||
} else {
|
||||
t.Log("High gas prices make arbitrage unprofitable")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("MEV Competition Pressure", func(t *testing.T) {
|
||||
// Simulate competitive MEV environment
|
||||
analyzer := mev.NewCompetitionAnalyzer(client)
|
||||
|
||||
opportunity := &mev.MEVOpportunity{
|
||||
Type: mev.TypeArbitrage,
|
||||
EstimatedProfit: big.NewInt(100000000000000000), // 0.1 ETH
|
||||
RequiredGasLimit: big.NewInt(300000),
|
||||
PoolAddress: common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443"),
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Simulate different competition levels
|
||||
competitionLevels := []string{"low", "medium", "high", "extreme"}
|
||||
|
||||
for _, level := range competitionLevels {
|
||||
// Mock competition metrics based on level
|
||||
competition := &mev.CompetitionMetrics{
|
||||
CompetitorCount: getCompetitorCount(level),
|
||||
AveragePriorityFee: getAveragePriorityFee(level),
|
||||
SuccessRate: getSuccessRate(level),
|
||||
RecentOpportunities: 10,
|
||||
}
|
||||
|
||||
strategy, err := analyzer.CalculateOptimalBid(ctx, opportunity, competition)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Competition level %s: Priority fee %s gwei, Expected profit %s ETH",
|
||||
level,
|
||||
new(big.Int).Div(strategy.PriorityFeePerGas, big.NewInt(1e9)),
|
||||
new(big.Float).Quo(new(big.Float).SetInt(strategy.ExpectedProfit), new(big.Float).SetInt(big.NewInt(1e18))))
|
||||
|
||||
// Even under extreme competition, some profit should remain
|
||||
if level != "extreme" {
|
||||
assert.Greater(t, strategy.ExpectedProfit.Sign(), 0,
|
||||
"Should maintain profitability under %s competition", level)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Helper functions for stress testing
|
||||
|
||||
func getCompetitorCount(level string) int {
|
||||
switch level {
|
||||
case "low":
|
||||
return 2
|
||||
case "medium":
|
||||
return 5
|
||||
case "high":
|
||||
return 10
|
||||
case "extreme":
|
||||
return 20
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
func getAveragePriorityFee(level string) *big.Int {
|
||||
switch level {
|
||||
case "low":
|
||||
return big.NewInt(2000000000) // 2 gwei
|
||||
case "medium":
|
||||
return big.NewInt(5000000000) // 5 gwei
|
||||
case "high":
|
||||
return big.NewInt(10000000000) // 10 gwei
|
||||
case "extreme":
|
||||
return big.NewInt(25000000000) // 25 gwei
|
||||
default:
|
||||
return big.NewInt(3000000000) // 3 gwei
|
||||
}
|
||||
}
|
||||
|
||||
func getSuccessRate(level string) float64 {
|
||||
switch level {
|
||||
case "low":
|
||||
return 0.9
|
||||
case "medium":
|
||||
return 0.7
|
||||
case "high":
|
||||
return 0.4
|
||||
case "extreme":
|
||||
return 0.1
|
||||
default:
|
||||
return 0.8
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user