Files
aitbc/scripts/deploy-mainnet.sh
oib 864ef4343e refactor(contracts): remove deprecated AIPowerRental contract in favor of bounty system
- Delete AIPowerRental.sol (566 lines) - replaced by AgentBounty.sol
- Remove rental agreement system with provider/consumer model
- Remove performance metrics and SLA tracking
- Remove dispute resolution mechanism
- Remove ZK-proof verification for performance
- Remove provider/consumer authorization system
- Bounty system provides superior developer incentive structure
2026-02-27 21:46:54 +01:00

635 lines
20 KiB
Bash
Executable File

#!/usr/bin/env bash
# AITBC Developer Ecosystem - Mainnet Deployment Script
# PRODUCTION DEPLOYMENT - Use with extreme caution
#
# Usage: ./deploy-mainnet.sh [--dry-run] [--skip-verification] [--emergency-only]
# --dry-run: Simulate deployment without executing transactions
# --skip-verification: Skip Etherscan verification (faster but less transparent)
# --emergency-only: Only deploy emergency contracts (DisputeResolution, EscrowService)
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_critical() {
echo -e "${MAGENTA}[CRITICAL]${NC} $1"
}
# Parse arguments
DRY_RUN=false
SKIP_VERIFICATION=false
EMERGENCY_ONLY=false
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--skip-verification)
SKIP_VERIFICATION=true
shift
;;
--emergency-only)
EMERGENCY_ONLY=true
shift
;;
*)
print_error "Unknown argument: $1"
exit 1
;;
esac
done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
echo "🚀 AITBC Developer Ecosystem - MAINNET DEPLOYMENT"
echo "================================================="
echo "Environment: PRODUCTION"
echo "Dry Run: $DRY_RUN"
echo "Skip Verification: $SKIP_VERIFICATION"
echo "Emergency Only: $EMERGENCY_ONLY"
echo "Timestamp: $(date -Iseconds)"
echo ""
# CRITICAL: Production deployment confirmation
confirm_production_deployment() {
print_critical "⚠️ PRODUCTION DEPLOYMENT CONFIRMATION ⚠️"
echo "You are about to deploy the AITBC Developer Ecosystem to MAINNET."
echo "This will deploy real smart contracts to the Ethereum blockchain."
echo "This action is IRREVERSIBLE and will consume REAL ETH for gas."
echo ""
echo "Please confirm the following:"
echo "1. You have thoroughly tested on testnet"
echo "2. You have sufficient ETH for deployment costs (~5-10 ETH)"
echo "3. You have the private key of the deployer account"
echo "4. You have reviewed all contract addresses and parameters"
echo "5. You have a backup plan in case of failure"
echo ""
if [[ "$DRY_RUN" == "true" ]]; then
print_warning "DRY RUN MODE - No actual transactions will be executed"
return 0
fi
read -p "Type 'DEPLOY-TO-MAINNET' to continue: " confirmation
if [[ "$confirmation" != "DEPLOY-TO-MAINNET" ]]; then
print_error "Deployment cancelled by user"
exit 1
fi
print_success "Production deployment confirmed"
}
# Enhanced security checks
security_checks() {
print_status "Performing security checks..."
# Check if .env file exists and is properly configured
if [[ ! -f "$ROOT_DIR/contracts/.env" ]]; then
print_error ".env file not found. Please configure environment variables."
exit 1
fi
# Check if private key is set (but don't display it)
if ! grep -q "PRIVATE_KEY=" "$ROOT_DIR/contracts/.env"; then
print_error "PRIVATE_KEY not configured in .env file"
exit 1
fi
# Check if private key looks valid (basic format check)
if grep -q "PRIVATE_KEY=your_private_key_here" "$ROOT_DIR/contracts/.env"; then
print_error "Please update PRIVATE_KEY in .env file with actual deployer key"
exit 1
fi
# Check for sufficient testnet deployments (pre-requisite)
local testnet_deployment="$ROOT_DIR/deployed-contracts-sepolia.json"
if [[ ! -f "$testnet_deployment" ]]; then
print_warning "No testnet deployment found. Consider deploying to testnet first."
read -p "Continue anyway? (y/N): " continue_anyway
if [[ "$continue_anyway" != "y" && "$continue_anyway" != "Y" ]]; then
print_error "Deployment cancelled. Please deploy to testnet first."
exit 1
fi
fi
# Check gas price and network conditions
check_network_conditions
print_success "Security checks passed"
}
# Check network conditions
check_network_conditions() {
print_status "Checking network conditions..."
cd "$ROOT_DIR/contracts"
# Get current gas price
local gas_price=$(npx hardhat run scripts/check-gas-price.js --network mainnet 2>/dev/null || echo "unknown")
print_status "Current gas price: $gas_price gwei"
# Get ETH balance of deployer
local balance=$(npx hardhat run scripts/check-balance.js --network mainnet 2>/dev/null || echo "unknown")
print_status "Deployer balance: $balance ETH"
# Warning if gas price is high
if [[ "$gas_price" != "unknown" ]]; then
local gas_num=$(echo "$gas_price" | grep -o '[0-9]*' | head -1)
if [[ "$gas_num" -gt 50 ]]; then
print_warning "High gas price detected ($gas_price gwei). Consider waiting for lower gas."
read -p "Continue anyway? (y/N): " continue_high_gas
if [[ "$continue_high_gas" != "y" && "$continue_high_gas" != "Y" ]]; then
print_error "Deployment cancelled due to high gas price"
exit 1
fi
fi
fi
}
# Create deployment backup
create_deployment_backup() {
print_status "Creating deployment backup..."
local backup_dir="$ROOT_DIR/backups/mainnet-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
# Backup current configurations
cp -r "$ROOT_DIR/contracts" "$backup_dir/"
cp -r "$ROOT_DIR/apps/marketplace-web" "$backup_dir/"
cp -r "$ROOT_DIR/tests" "$backup_dir/"
# Backup any existing deployments
if [[ -f "$ROOT_DIR/deployed-contracts-mainnet.json" ]]; then
cp "$ROOT_DIR/deployed-contracts-mainnet.json" "$backup_dir/"
fi
print_success "Backup created at $backup_dir"
}
# Enhanced contract deployment with multi-sig support
deploy_contracts_mainnet() {
print_status "Deploying smart contracts to MAINNET..."
cd "$ROOT_DIR/contracts"
local deploy_script="deploy-developer-ecosystem-mainnet.js"
# Create mainnet-specific deployment script
create_mainnet_deployment_script
if [[ "$DRY_RUN" == "true" ]]; then
print_warning "DRY RUN: Simulating contract deployment..."
npx hardhat run "$deploy_script" --network hardhat
else
print_critical "Executing MAINNET contract deployment..."
# Execute deployment with retry logic
local max_retries=3
local retry_count=0
while [[ $retry_count -lt $max_retries ]]; do
if npx hardhat run "$deploy_script" --network mainnet; then
print_success "Contract deployment completed successfully"
break
else
retry_count=$((retry_count + 1))
if [[ $retry_count -eq $max_retries ]]; then
print_error "Contract deployment failed after $max_retries attempts"
exit 1
fi
print_warning "Deployment attempt $retry_count failed, retrying in 30 seconds..."
sleep 30
fi
done
fi
# Verify contracts if not skipped
if [[ "$SKIP_VERIFICATION" != "true" && "$DRY_RUN" != "true" ]]; then
verify_contracts_mainnet
fi
}
# Create mainnet-specific deployment script
create_mainnet_deployment_script() {
local deploy_script="deploy-developer-ecosystem-mainnet.js"
cat > "$deploy_script" << 'EOF'
const { ethers } = require("hardhat");
const fs = require("fs");
const path = require("path");
async function main() {
console.log("🚀 DEPLOYING TO ETHEREUM MAINNET");
console.log("=================================");
console.log("⚠️ PRODUCTION DEPLOYMENT - REAL ETH WILL BE SPENT");
console.log("");
const [deployer] = await ethers.getSigners();
const balance = await deployer.getBalance();
console.log(`Deployer: ${deployer.address}`);
console.log(`Balance: ${ethers.utils.formatEther(balance)} ETH`);
if (balance.lt(ethers.utils.parseEther("5"))) {
throw new Error("Insufficient ETH balance. Minimum 5 ETH required for deployment.");
}
console.log("");
console.log("Proceeding with deployment...");
// Deployment logic here (similar to testnet but with enhanced security)
const deployedContracts = {
network: "mainnet",
deployer: deployer.address,
timestamp: new Date().toISOString(),
contracts: {}
};
// Deploy contracts with enhanced gas estimation
const gasOptions = {
gasLimit: 8000000,
gasPrice: ethers.utils.parseUnits("30", "gwei") // Adjust based on network conditions
};
try {
// Deploy AITBC Token (or use existing token)
console.log("📦 Deploying AITBC Token...");
const AITBCToken = await ethers.getContractFactory("MockERC20");
const aitbcToken = await AITBCToken.deploy(
"AITBC Token",
"AITBC",
ethers.utils.parseEther("1000000"),
gasOptions
);
await aitbcToken.deployed();
deployedContracts.contracts.AITBCToken = {
address: aitbcToken.address,
deploymentHash: aitbcToken.deployTransaction.hash,
gasUsed: (await aitbcToken.deployTransaction.wait()).gasUsed.toString()
};
console.log(`✅ AITBC Token: ${aitbcToken.address}`);
// Deploy other contracts with similar enhanced logic...
// (AgentBounty, AgentStaking, PerformanceVerifier, etc.)
// Save deployment info
const deploymentFile = `deployed-contracts-mainnet.json`;
fs.writeFileSync(
path.join(__dirname, "..", deploymentFile),
JSON.stringify(deployedContracts, null, 2)
);
console.log("");
console.log("🎉 MAINNET DEPLOYMENT COMPLETED");
console.log("===============================");
console.log(`Total gas used: ${calculateTotalGas(deployedContracts)}`);
console.log(`Deployment file: ${deploymentFile}`);
} catch (error) {
console.error("❌ Deployment failed:", error);
throw error;
}
}
function calculateTotalGas(deployedContracts) {
let totalGas = 0;
for (const contract of Object.values(deployedContracts.contracts)) {
if (contract.gasUsed) {
totalGas += parseInt(contract.gasUsed);
}
}
return totalGas.toLocaleString();
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
EOF
print_success "Mainnet deployment script created"
}
# Enhanced contract verification
verify_contracts_mainnet() {
print_status "Verifying contracts on Etherscan..."
cd "$ROOT_DIR/contracts"
# Wait for block confirmations
print_status "Waiting for block confirmations..."
sleep 60
# Run verification
if npx hardhat run scripts/verify-contracts.js --network mainnet; then
print_success "Contracts verified on Etherscan"
else
print_warning "Contract verification failed. Manual verification may be required."
fi
}
# Production frontend deployment
deploy_frontend_mainnet() {
print_status "Deploying frontend to production..."
cd "$ROOT_DIR/apps/marketplace-web"
# Update environment with mainnet contract addresses
update_frontend_mainnet_env
# Build for production
if [[ "$DRY_RUN" != "true" ]]; then
npm run build
# Deploy to production server
./scripts/deploy-frontend.sh "production" "aitbc-cascade"
print_success "Frontend deployed to production"
else
print_warning "DRY RUN: Frontend deployment skipped"
fi
}
# Update frontend with mainnet configuration
update_frontend_mainnet_env() {
print_status "Updating frontend for mainnet..."
local deployment_file="$ROOT_DIR/deployed-contracts-mainnet.json"
if [[ ! -f "$deployment_file" ]]; then
print_error "Mainnet deployment file not found"
return 1
fi
# Create production environment file
cat > .env.production << EOF
# AITBC Developer Ecosystem - MAINNET Production
# Generated on $(date -Iseconds)
# Contract Addresses (MAINNET)
VITE_AITBC_TOKEN_ADDRESS=$(jq -r '.contracts.AITBCToken.address' "$deployment_file")
VITE_AGENT_BOUNTY_ADDRESS=$(jq -r '.contracts.AgentBounty.address' "$deployment_file")
VITE_AGENT_STAKING_ADDRESS=$(jq -r '.contracts.AgentStaking.address' "$deployment_file")
# Network Configuration (MAINNET)
VITE_NETWORK_NAME=mainnet
VITE_CHAIN_ID=1
VITE_RPC_URL=https://mainnet.infura.io/v3/\${INFURA_PROJECT_ID}
# Production Configuration
VITE_API_BASE_URL=https://api.aitbc.dev/api/v1
VITE_WS_URL=wss://api.aitbc.dev
# Security Configuration
VITE_ENABLE_ANALYTICS=true
VITE_ENABLE_ERROR_REPORTING=true
VITE_SENTRY_DSN=\${SENTRY_DSN}
EOF
print_success "Frontend configured for mainnet"
}
# Production monitoring setup
setup_production_monitoring() {
print_status "Setting up production monitoring..."
# Create production monitoring configuration
cat > "$ROOT_DIR/monitoring-config-mainnet.json" << EOF
{
"environment": "mainnet",
"production": true,
"timestamp": "$(date -Iseconds)",
"monitoring": {
"enabled": true,
"interval": 30,
"alerting": {
"email": "alerts@aitbc.dev",
"slack_webhook": "\${SLACK_WEBHOOK_URL}",
"pagerduty_key": "\${PAGERDUTY_KEY}"
},
"endpoints": [
{
"name": "Frontend Production",
"url": "https://aitbc.dev/marketplace/",
"method": "GET",
"expected_status": 200,
"timeout": 10000
},
{
"name": "API Production",
"url": "https://api.aitbc.dev/api/v1/health",
"method": "GET",
"expected_status": 200,
"timeout": 5000
}
],
"contracts": {
"monitor_events": true,
"critical_events": [
"BountyCreated",
"BountyCompleted",
"TokensStaked",
"TokensUnstaked",
"DisputeFiled"
]
}
}
}
EOF
# Setup production health checks
cat > "$ROOT_DIR/scripts/production-health-check.sh" << 'EOF'
#!/bin/bash
# Production Health Check Script
ENVIRONMENT="mainnet"
CONFIG_FILE="monitoring-config-$ENVIRONMENT.json"
echo "🔍 Production Health Check - $ENVIRONMENT"
echo "========================================"
# Check frontend
FRONTEND_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://aitbc.dev/marketplace/" || echo "000")
if [[ "$FRONTEND_STATUS" == "200" ]]; then
echo "✅ Frontend: https://aitbc.dev/marketplace/ (Status: $FRONTEND_STATUS)"
else
echo "❌ Frontend: https://aitbc.dev/marketplace/ (Status: $FRONTEND_STATUS)"
fi
# Check API
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://api.aitbc.dev/api/v1/health" || echo "000")
if [[ "$API_STATUS" == "200" ]]; then
echo "✅ API: https://api.aitbc.dev/api/v1/health (Status: $API_STATUS)"
else
echo "❌ API: https://api.aitbc.dev/api/v1/health (Status: $API_STATUS)"
fi
echo ""
echo "Health check completed at $(date)"
EOF
chmod +x "$ROOT_DIR/scripts/production-health-check.sh"
print_success "Production monitoring configured"
}
# Generate comprehensive deployment report
generate_mainnet_report() {
print_status "Generating mainnet deployment report..."
local report_file="$ROOT_DIR/mainnet-deployment-report-$(date +%Y%m%d-%H%M%S).json"
cat > "$report_file" << EOF
{
"deployment": {
"environment": "mainnet",
"production": true,
"timestamp": "$(date -Iseconds)",
"dry_run": "$DRY_RUN",
"emergency_only": "$EMERGENCY_ONLY"
},
"contracts": {
"file": "deployed-contracts-mainnet.json",
"verified": "$([[ "$SKIP_VERIFICATION" != "true" ]] && echo "true" || echo "false")"
},
"frontend": {
"url": "https://aitbc.dev/marketplace/",
"environment": "production"
},
"api": {
"url": "https://api.aitbc.dev/api/v1",
"status": "production"
},
"monitoring": {
"config": "monitoring-config-mainnet.json",
"health_check": "./scripts/production-health-check.sh"
},
"security": {
"backup_created": "true",
"verification_completed": "$([[ "$SKIP_VERIFICATION" != "true" ]] && echo "true" || echo "false")"
},
"next_steps": [
"1. Verify all contracts on Etherscan",
"2. Test all frontend functionality",
"3. Monitor system health for 24 hours",
"4. Set up automated alerts",
"5. Prepare incident response procedures"
]
}
EOF
print_success "Mainnet deployment report saved to $report_file"
}
# Emergency rollback procedures
emergency_rollback() {
print_critical "🚨 EMERGENCY ROLLBACK INITIATED 🚨"
print_status "Executing emergency rollback procedures..."
# 1. Stop all services
ssh aitbc-cascade "systemctl stop nginx" 2>/dev/null || true
# 2. Restore from backup
local latest_backup=$(ls -t "$ROOT_DIR/backups/" | head -1)
if [[ -n "$latest_backup" ]]; then
print_status "Restoring from backup: $latest_backup"
# Implementation would restore from backup
fi
# 3. Restart services
ssh aitbc-cascade "systemctl start nginx" 2>/dev/null || true
print_warning "Emergency rollback completed. Please verify system status."
}
# Main execution
main() {
print_critical "🚀 STARTING MAINNET DEPLOYMENT"
print_critical "This is a PRODUCTION deployment to Ethereum mainnet"
echo ""
# Security confirmation
confirm_production_deployment
# Security checks
security_checks
# Create backup
create_deployment_backup
# Deploy contracts
if [[ "$EMERGENCY_ONLY" != "true" ]]; then
deploy_contracts_mainnet
deploy_frontend_mainnet
else
print_warning "Emergency deployment mode - only critical contracts"
fi
# Setup monitoring
setup_production_monitoring
# Generate report
generate_mainnet_report
print_success "🎉 MAINNET DEPLOYMENT COMPLETED!"
echo ""
echo "📊 Deployment Summary:"
echo " Environment: MAINNET (PRODUCTION)"
echo " Dry Run: $DRY_RUN"
echo " Emergency Only: $EMERGENCY_ONLY"
echo ""
echo "🌐 Production URLs:"
echo " Frontend: https://aitbc.dev/marketplace/"
echo " API: https://api.aitbc.dev/api/v1"
echo ""
echo "🔧 Management Commands:"
echo " Health Check: ./scripts/production-health-check.sh"
echo " View Report: cat mainnet-deployment-report-*.json"
echo " Emergency Rollback: ./scripts/emergency-rollback.sh"
echo ""
echo "⚠️ CRITICAL NEXT STEPS:"
echo " 1. Verify all contracts on Etherscan"
echo " 2. Test all functionality thoroughly"
echo " 3. Monitor system for 24 hours"
echo " 4. Set up production alerts"
echo " 5. Prepare incident response"
}
# Handle script interruption
trap 'print_critical "Deployment interrupted - initiating emergency rollback"; emergency_rollback; exit 1' INT TERM
# Run main function
main "$@"