Files
mev-beta/test/integration/contract_deployment_test.go
2025-09-16 11:05:47 -05:00

319 lines
9.8 KiB
Go

package integration
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)
})
}