Files
mev-beta/docs/FLASH_LOAN_DEPLOYMENT_GUIDE.md
Krypto Kajun 432bcf0819 docs: add flash loan, binding, and testing documentation
Additional documentation and testing infrastructure:

## Documentation Added
- PROFIT_ROADMAP.md - 4-week profitability roadmap
- PRODUCTION_DEPLOYMENT.md - Production deployment guide
- docs/FLASH_LOAN_DEPLOYMENT_GUIDE.md - Flash loan implementation
- docs/FLASH_LOAN_IMPLEMENTATION_SUMMARY.md - Flash loan summary
- docs/BINDING_CONSISTENCY_GUIDE.md - Contract binding guidelines
- docs/BINDING_QUICK_START.md - Quick start for bindings
- docs/COMPLETE_FORK_TESTING_GUIDE.md - Fork testing guide

## Testing Scripts Added
- scripts/generate-test-report.sh - Generate test reports
- scripts/monitor-24h-test.sh - 24-hour monitoring
- scripts/start-24h-test.sh - Start long-running tests
- scripts/stop-24h-test.sh - Stop test runs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 05:51:44 -05:00

15 KiB

Flash Loan Execution - Deployment & Integration Guide

Status: Framework Complete, Contracts Ready for Deployment

Last Updated: October 26, 2025


📋 Overview

This guide covers the deployment and integration of the MEV bot's flash loan execution system, which enables real arbitrage execution using flash loans from multiple providers.

Architecture Summary

┌─────────────────────────────────────────────────────────────┐
│                      MEV Bot Go Process                      │
│                                                              │
│  ┌────────────────┐         ┌──────────────────┐           │
│  │   Arbitrage    │────────▶│  Flash Loan      │           │
│  │   Detector     │         │  Provider        │           │
│  └────────────────┘         └────────┬─────────┘           │
│                                      │                       │
└──────────────────────────────────────┼───────────────────────┘
                                       │ RPC Call
                                       ▼
                    ┌──────────────────────────────────┐
                    │   FlashLoanReceiver Contract     │
                    │   (Deployed on Arbitrum)        │
                    └────────┬─────────────────────────┘
                             │
         ┌───────────────────┼──────────────────────┐
         │                   │                      │
         ▼                   ▼                      ▼
   ┌─────────────┐   ┌──────────────┐   ┌──────────────────┐
   │  Balancer   │   │  Uniswap V2  │   │  Uniswap V3      │
   │  Vault      │   │  Router      │   │  Router          │
   │  (0% fee)   │   │  (0.3% fee)  │   │  (0.05%-1% fee)  │
   └─────────────┘   └──────────────┘   └──────────────────┘

🎯 Implementation Status

Complete

  1. Solidity Smart Contract

    • Location: contracts/balancer/FlashLoanReceiver.sol
    • Features:
      • Balancer flash loan integration
      • Uniswap V2/V3 swap execution
      • Profit calculation and validation
      • Owner-only access control
      • Emergency withdrawal
  2. Go Execution Framework

    • Location: pkg/execution/
    • Files:
      • executor.go - Core execution engine (316 lines)
      • flashloan_providers.go - Provider implementations (360+ lines)
      • alerts.go - Alert system (291 lines)
  3. ABI Bindings

    • Location: bindings/balancer/vault.go
    • Generated with abigen for Balancer Vault
  4. Calldata Encoding

    • Function: encodeArbitragePath() in flashloan_providers.go
    • Encodes ArbitragePath struct for contract

Pending

  1. Smart Contract Deployment

    • Deploy FlashLoanReceiver.sol to Arbitrum
    • Set receiver address in BalancerFlashLoanProvider
    • Fund contract with gas if needed
  2. Transaction Signing

    • Implement private key management
    • Add transaction signer
    • Gas estimation logic
  3. ABI Encoding/Decoding

    • Complete ABI encoding for ArbitragePath struct
    • Parse execution results from contract events
  4. Integration Testing

    • Test on Arbitrum testnet
    • Fork testing with Tenderly/Hardhat
    • Mainnet dry-run testing

🚀 Deployment Steps

Prerequisites

# Install dependencies
npm install --save-dev hardhat @nomiclabs/hardhat-ethers ethers
npm install @openzeppelin/contracts

# Or use Foundry (recommended for production)
curl -L https://foundry.paradigm.xyz | bash
foundryup

Step 1: Compile Contract

Using Hardhat:

npx hardhat compile contracts/balancer/FlashLoanReceiver.sol

Using Foundry:

forge build contracts/balancer/FlashLoanReceiver.sol

Step 2: Deploy to Arbitrum

Deployment Script (Hardhat):

// scripts/deploy-flash-receiver.js
const hre = require("hardhat");

async function main() {
  const BALANCER_VAULT = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";

  console.log("Deploying FlashLoanReceiver...");

  const FlashLoanReceiver = await hre.ethers.getContractFactory("FlashLoanReceiver");
  const receiver = await FlashLoanReceiver.deploy(BALANCER_VAULT);

  await receiver.deployed();

  console.log("✅ FlashLoanReceiver deployed to:", receiver.address);
  console.log("   Owner:", await receiver.owner());
  console.log("   Vault:", await receiver.vault());

  // Save deployment info
  const fs = require("fs");
  fs.writeFileSync("deployment.json", JSON.stringify({
    address: receiver.address,
    owner: await receiver.owner(),
    vault: BALANCER_VAULT,
    timestamp: new Date().toISOString()
  }, null, 2));
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Deploy:

npx hardhat run scripts/deploy-flash-receiver.js --network arbitrum

Using Foundry:

forge create contracts/balancer/FlashLoanReceiver.sol:FlashLoanReceiver \
  --rpc-url $ARBITRUM_RPC \
  --private-key $PRIVATE_KEY \
  --constructor-args 0xBA12222222228d8Ba445958a75a0704d566BF2C8 \
  --verify

Step 3: Configure MEV Bot

After deployment, update the Go code with the deployed contract address:

// pkg/execution/flashloan_providers.go

func NewBalancerFlashLoanProvider(client *ethclient.Client, logger *logger.Logger) *BalancerFlashLoanProvider {
	return &BalancerFlashLoanProvider{
		client: client,
		logger: logger,
		vaultAddress: common.HexToAddress("0xBA12222222228d8Ba445958a75a0704d566BF2C8"),
		// UPDATE THIS with deployed contract address:
		receiverAddress: common.HexToAddress("0xYOUR_DEPLOYED_CONTRACT_ADDRESS"),
	}
}

Or use environment variable:

export FLASH_LOAN_RECEIVER="0xYOUR_DEPLOYED_CONTRACT_ADDRESS"

Step 4: Generate Contract Bindings

Generate Go bindings for the deployed contract:

# Get contract ABI
cat contracts/balancer/FlashLoanReceiver.sol | \
  solc --abi - > contracts/balancer/FlashLoanReceiver.abi

# Generate Go bindings
abigen --abi contracts/balancer/FlashLoanReceiver.abi \
  --pkg execution \
  --type FlashLoanReceiver \
  --out pkg/execution/flashloan_receiver.go

🔧 Integration Implementation

Complete the TODO Items

1. Transaction Signing (pkg/execution/transaction_signer.go - NEW FILE)

package execution

import (
	"context"
	"crypto/ecdsa"
	"math/big"

	"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/ethereum/go-ethereum/ethclient"
)

type TransactionSigner struct {
	privateKey *ecdsa.PrivateKey
	chainID    *big.Int
	client     *ethclient.Client
}

func NewTransactionSigner(privateKeyHex string, client *ethclient.Client) (*TransactionSigner, error) {
	privateKey, err := crypto.HexToECDSA(privateKeyHex)
	if err != nil {
		return nil, err
	}

	chainID, err := client.ChainID(context.Background())
	if err != nil {
		return nil, err
	}

	return &TransactionSigner{
		privateKey: privateKey,
		chainID:    chainID,
		client:     client,
	}, nil
}

func (ts *TransactionSigner) SignAndSend(ctx context.Context, tx *types.Transaction) (common.Hash, error) {
	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(ts.chainID), ts.privateKey)
	if err != nil {
		return common.Hash{}, err
	}

	err = ts.client.SendTransaction(ctx, signedTx)
	if err != nil {
		return common.Hash{}, err
	}

	return signedTx.Hash(), nil
}

func (ts *TransactionSigner) GetTransactor() (*bind.TransactOpts, error) {
	auth, err := bind.NewKeyedTransactorWithChainID(ts.privateKey, ts.chainID)
	if err != nil {
		return nil, err
	}
	return auth, nil
}

2. Complete ABI Encoding

Update encodeArbitragePath() to use proper ABI encoding:

import (
	"github.com/ethereum/go-ethereum/accounts/abi"
	"strings"
)

func (b *BalancerFlashLoanProvider) encodeArbitragePath(
	opportunity *arbitrage.ArbitragePath,
	config *ExecutionConfig,
) ([]byte, error) {
	// Define ABI for ArbitragePath struct
	arbitragePathABI := `[{
		"components": [
			{"name": "tokens", "type": "address[]"},
			{"name": "exchanges", "type": "address[]"},
			{"name": "fees", "type": "uint24[]"},
			{"name": "isV3", "type": "bool[]"},
			{"name": "minProfit", "type": "uint256"}
		],
		"name": "path",
		"type": "tuple"
	}]`

	contractABI, err := abi.JSON(strings.NewReader(arbitragePathABI))
	if err != nil {
		return nil, err
	}

	// Prepare data (same as before)
	numHops := len(opportunity.TokenPath) - 1
	exchanges := make([]common.Address, numHops)
	fees := make([]*big.Int, numHops)
	isV3 := make([]bool, numHops)

	// ... (populate arrays) ...

	// Encode using ABI
	encoded, err := contractABI.Pack("path",
		opportunity.TokenPath,
		exchanges,
		fees,
		isV3,
		minProfit,
	)
	if err != nil {
		return nil, err
	}

	return encoded, nil
}

3. Complete ExecuteFlashLoan

func (b *BalancerFlashLoanProvider) ExecuteFlashLoan(
	ctx context.Context,
	opportunity *arbitrage.ArbitragePath,
	config *ExecutionConfig,
) (*ExecutionResult, error) {
	startTime := time.Now()

	// ... (validation and encoding as before) ...

	// Create contract instance
	receiver, err := NewFlashLoanReceiver(b.receiverAddress, b.client)
	if err != nil {
		return nil, err
	}

	// Get transactor
	auth, err := config.Signer.GetTransactor()
	if err != nil {
		return nil, err
	}

	// Set gas price and limit
	auth.GasPrice = config.MaxGasPrice
	auth.GasLimit = 500000 // Estimate based on path length

	// Call executeArbitrage
	tx, err := receiver.ExecuteArbitrage(auth, tokens, amounts, userData)
	if err != nil {
		return &ExecutionResult{
			OpportunityID: opportunity.ID,
			Success:       false,
			Error:         err,
			ExecutionTime: time.Since(startTime),
		}, err
	}

	// Wait for receipt
	receipt, err := bind.WaitMined(ctx, b.client, tx)
	if err != nil {
		return &ExecutionResult{
			OpportunityID: opportunity.ID,
			Success:       false,
			TxHash:        tx.Hash(),
			Error:         err,
			ExecutionTime: time.Since(startTime),
		}, err
	}

	// Parse events to get actual profit
	var actualProfit *big.Int
	for _, log := range receipt.Logs {
		event, err := receiver.ParseArbitrageExecuted(*log)
		if err == nil {
			actualProfit = event.Profit
			break
		}
	}

	return &ExecutionResult{
		OpportunityID:   opportunity.ID,
		Success:         receipt.Status == 1,
		TxHash:          tx.Hash(),
		GasUsed:         receipt.GasUsed,
		ActualProfit:    actualProfit,
		EstimatedProfit: opportunity.NetProfit,
		ExecutionTime:   time.Since(startTime),
		Timestamp:       time.Now(),
	}, nil
}

Testing Strategy

1. Local Fork Testing

# Start Hardhat node with Arbitrum fork
npx hardhat node --fork https://arb1.arbitrum.io/rpc

# Deploy contract to local fork
npx hardhat run scripts/deploy-flash-receiver.js --network localhost

# Run Go tests against local fork
export ARBITRUM_RPC_ENDPOINT="http://localhost:8545"
export FLASH_LOAN_RECEIVER="0x..."
go test ./pkg/execution/... -v

2. Arbitrum Testnet

# Deploy to Arbitrum Sepolia testnet
npx hardhat run scripts/deploy-flash-receiver.js --network arbitrum-sepolia

# Test with testnet RPC
export ARBITRUM_RPC_ENDPOINT="https://sepolia-rollup.arbitrum.io/rpc"
./mev-bot start --dry-run

3. Mainnet Dry-Run

# Test on mainnet without executing
export EXECUTION_MODE="simulation"
./mev-bot start

📊 Gas Optimization

Estimated Gas Costs

Operation Gas Estimate Cost (@ 0.1 gwei)
Contract deployment 1,500,000 0.00015 ETH
2-hop arbitrage 300,000 0.00003 ETH
3-hop arbitrage 450,000 0.000045 ETH
4-hop arbitrage 600,000 0.00006 ETH

Optimization Tips

  1. Batch token approvals - Approve max once instead of per transaction
  2. Use V3 single-hop when possible - Lower gas than multi-contract calls
  3. Optimize path length - 2-hop paths preferred
  4. Monitor gas prices - Only execute when gas < threshold

🔐 Security Considerations

Smart Contract Security

  1. Access Control

    • Only owner can call executeArbitrage()
    • Only Balancer Vault can call receiveFlashLoan()
  2. Profit Validation

    • Minimum profit threshold enforced on-chain
    • Prevents unprofitable execution
  3. Emergency Functions

    • emergencyWithdraw() for stuck funds
    • withdrawProfit() for profit extraction

Operational Security

  1. Private Key Management

    # NEVER commit private keys to git
    # Use environment variables or secret managers
    export EXECUTOR_PRIVATE_KEY="0x..."
    
    # Or use hardware wallets (Ledger/Trezor)
    # Or use AWS KMS / Google Cloud KMS
    
  2. Gas Price Limits

    config := &ExecutionConfig{
        MaxGasPrice: big.NewInt(1000000000), // 1 gwei max
        // ...
    }
    
  3. Slippage Protection

    • Set MaxSlippage appropriately
    • Default 5% is reasonable for volatile markets

📈 Monitoring & Alerts

Integration with Alert System

// In main.go or orchestrator
alertSystem := execution.NewAlertSystem(&execution.AlertConfig{
    EnableConsoleAlerts: true,
    EnableWebhook:       true,
    WebhookURL:          os.Getenv("SLACK_WEBHOOK"),
    MinProfitForAlert:   big.NewInt(1e16), // 0.01 ETH
    MinROIForAlert:      0.05,              // 5%
}, logger)

// Send execution alerts
result, err := executor.ExecuteOpportunity(ctx, opportunity)
if err == nil {
    alertSystem.SendExecutionAlert(result)
}

Dashboard Metrics

Add to monitoring/dashboard.sh:

# Execution metrics
EXECUTIONS=$(grep -c "Arbitrage executed successfully" "${LATEST_LOG}")
EXECUTION_PROFIT=$(grep "profit=" "${LATEST_LOG}" | awk '{sum+=$NF} END {print sum}')
echo "  Executions: ${EXECUTIONS}"
echo "  Total Profit: ${EXECUTION_PROFIT} ETH"

🎯 Next Steps

  1. Deploy FlashLoanReceiver contract to Arbitrum
  2. Implement transaction signing in Go
  3. Complete ABI encoding for ArbitragePath
  4. Test on Arbitrum testnet
  5. Conduct security audit of smart contract
  6. Monitor 24-hour test results before enabling execution
  7. Start with small amounts (0.01-0.1 ETH)
  8. Scale gradually as confidence builds

📚 Reference


Last Updated: October 26, 2025 Status: Ready for Deployment