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" "mev-bot/bindings/arbitrage" "mev-bot/pkg/arbitrage" "mev-bot/pkg/security" ) func TestContractDeploymentOnForkedArbitrum(t *testing.T) { // Setup forked Arbitrum environment client, cleanup := setupForkedArbitrum(t) defer cleanup() // Create a test private key for deployment privateKey, err := crypto.GenerateKey() require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(42161)) require.NoError(t, err) // Set gas price for Arbitrum gasPrice, err := client.SuggestGasPrice(context.Background()) require.NoError(t, err) auth.GasPrice = gasPrice auth.GasLimit = uint64(5000000) t.Run("Deploy ArbitrageExecutor Contract", func(t *testing.T) { // Deploy the ArbitrageExecutor contract address, tx, contract, err := arbitrage.DeployArbitrageExecutor( auth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), // Uniswap V3 Factory common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), // WETH ) require.NoError(t, err) require.NotEqual(t, common.Address{}, address) // Wait for deployment confirmation ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() receipt, err := bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) // Verify contract is deployed correctly code, err := client.CodeAt(context.Background(), address, nil) require.NoError(t, err) assert.Greater(t, len(code), 0, "Contract should have bytecode") // Test contract initialization owner, err := contract.Owner(nil) require.NoError(t, err) assert.Equal(t, auth.From, owner) // Test setting minimum profit threshold newThreshold := big.NewInt(1000000000000000000) // 1 ETH tx, err = contract.SetMinProfitThreshold(auth, newThreshold) require.NoError(t, err) receipt, err = bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) threshold, err := contract.MinProfitThreshold(nil) require.NoError(t, err) assert.Equal(t, newThreshold, threshold) }) t.Run("Test Contract Security Features", func(t *testing.T) { // Deploy with security features enabled address, tx, contract, err := arbitrage.DeployArbitrageExecutor( auth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), ) 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) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) // Test emergency pause functionality tx, err = contract.Pause(auth) require.NoError(t, err) receipt, err = bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) paused, err := contract.Paused(nil) require.NoError(t, err) assert.True(t, paused) // Test unpause tx, err = contract.Unpause(auth) require.NoError(t, err) receipt, err = bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) }) t.Run("Test Gas Limit Validation", func(t *testing.T) { // Test deployment with insufficient gas lowGasAuth := *auth lowGasAuth.GasLimit = uint64(100000) // Too low for contract deployment _, _, _, err := arbitrage.DeployArbitrageExecutor( &lowGasAuth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), ) assert.Error(t, err, "Should fail with insufficient gas") }) } func TestContractInteractionWithRealPools(t *testing.T) { client, cleanup := setupForkedArbitrum(t) defer cleanup() // Use real Arbitrum pool addresses for testing wethUsdcPool := common.HexToAddress("0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443") // WETH/USDC 0.05% privateKey, err := crypto.GenerateKey() require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(42161)) require.NoError(t, err) // Deploy contract _, tx, contract, err := arbitrage.DeployArbitrageExecutor( auth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), ) 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("Test Pool State Reading", func(t *testing.T) { // Test reading pool state through contract poolState, err := contract.GetPoolState(nil, wethUsdcPool) require.NoError(t, err) assert.Greater(t, poolState.SqrtPriceX96.Uint64(), uint64(0)) assert.Greater(t, poolState.Liquidity.Uint64(), uint64(0)) assert.NotEqual(t, int32(0), poolState.Tick) }) t.Run("Test Price Impact Calculation", func(t *testing.T) { swapAmount := big.NewInt(1000000) // 1 USDC priceImpact, err := contract.CalculatePriceImpact(nil, wethUsdcPool, swapAmount, true) require.NoError(t, err) // Price impact should be reasonable for small swaps assert.LessOrEqual(t, priceImpact.Uint64(), uint64(10000)) // Less than 1% (10000 basis points) }) t.Run("Test Arbitrage Opportunity Detection", func(t *testing.T) { // Simulate a price difference scenario pool1 := wethUsdcPool pool2 := common.HexToAddress("0x17c14D2c404D167802b16C450d3c99F88F2c4F4d") // Alternative WETH/USDC pool opportunity, err := contract.DetectArbitrageOpportunity(nil, pool1, pool2, big.NewInt(1000000)) require.NoError(t, err) // Log the detected opportunity for analysis t.Logf("Detected opportunity: profitable=%v, estimated_profit=%v", opportunity.Profitable, opportunity.EstimatedProfit) }) } func TestContractUpgradeability(t *testing.T) { client, cleanup := setupForkedArbitrum(t) defer cleanup() privateKey, err := crypto.GenerateKey() require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(42161)) require.NoError(t, err) t.Run("Test Contract Version Management", func(t *testing.T) { // Deploy initial version address, tx, contract, err := arbitrage.DeployArbitrageExecutor( auth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), ) 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) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) // Check initial version version, err := contract.Version(nil) require.NoError(t, err) assert.Equal(t, "1.0.0", version) // Test configuration updates newMaxGasPrice := big.NewInt(50000000000) // 50 gwei tx, err = contract.SetMaxGasPrice(auth, newMaxGasPrice) require.NoError(t, err) receipt, err = bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) maxGasPrice, err := contract.MaxGasPrice(nil) require.NoError(t, err) assert.Equal(t, newMaxGasPrice, maxGasPrice) }) } func TestContractWithSecurityManager(t *testing.T) { client, cleanup := setupForkedArbitrum(t) defer cleanup() // Initialize security manager keyManager := security.NewKeyManager() err := keyManager.Initialize([]byte("test-encryption-key-32-bytes-long")) require.NoError(t, err) // Generate and store a test key privateKey, err := crypto.GenerateKey() require.NoError(t, err) err = keyManager.StoreKey("test-key", privateKey) require.NoError(t, err) err = keyManager.SetActiveKey("test-key") require.NoError(t, err) // Get the active key for contract deployment activeKey, err := keyManager.GetActivePrivateKey() require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(activeKey, big.NewInt(42161)) require.NoError(t, err) t.Run("Deploy With Secure Key Management", func(t *testing.T) { address, tx, contract, err := arbitrage.DeployArbitrageExecutor( auth, client, common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"), common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), ) 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) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) // Verify the contract owner matches our secure key owner, err := contract.Owner(nil) require.NoError(t, err) assert.Equal(t, auth.From, owner) // Test secure transaction signing tx, err = contract.SetMinProfitThreshold(auth, big.NewInt(500000000000000000)) require.NoError(t, err) receipt, err = bind.WaitMined(ctx, client, tx) require.NoError(t, err) assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) }) t.Run("Test Key Rotation", func(t *testing.T) { // Generate a new key newPrivateKey, err := crypto.GenerateKey() require.NoError(t, err) err = keyManager.StoreKey("new-key", newPrivateKey) require.NoError(t, err) // Rotate to the new key err = keyManager.SetActiveKey("new-key") require.NoError(t, err) // Verify the new key is active currentKey, err := keyManager.GetActivePrivateKey() require.NoError(t, err) assert.Equal(t, newPrivateKey, currentKey) }) }