deploy.sh
1 #!/bin/bash 2 3 # Unified deployment script for KaraokeSchool contracts 4 # Supports multiple networks, versions, and signing methods 5 6 set -e 7 8 # Colors for output 9 RED='\033[0;31m' 10 GREEN='\033[0;32m' 11 YELLOW='\033[1;33m' 12 BLUE='\033[0;34m' 13 NC='\033[0m' # No Color 14 15 # Default values 16 NETWORK="" 17 VERSION="" 18 USE_LEDGER=false 19 DRY_RUN=false 20 VERIFY=true 21 22 # Function to display usage 23 usage() { 24 echo "Usage: $0 [OPTIONS]" 25 echo "" 26 echo "Options:" 27 echo " -n, --network <network> Network to deploy to (base-mainnet, base-sepolia, optimism-sepolia)" 28 echo " -v, --version <version> Contract version to deploy (v4, v5, or 'latest')" 29 echo " -l, --ledger Use Ledger hardware wallet" 30 echo " -d, --dry-run Perform a dry run without deploying" 31 echo " --no-verify Skip contract verification" 32 echo " -h, --help Display this help message" 33 echo "" 34 echo "Examples:" 35 echo " $0 -n base-mainnet -v v4 --ledger # Deploy V4 to mainnet with Ledger" 36 echo " $0 -n base-sepolia -v v5 # Deploy V5 to testnet" 37 echo " $0 -n base-sepolia -v latest # Deploy latest version (v5) to testnet" 38 exit 1 39 } 40 41 # Parse command line arguments 42 while [[ $# -gt 0 ]]; do 43 case $1 in 44 -n|--network) 45 NETWORK="$2" 46 shift 2 47 ;; 48 -v|--version) 49 VERSION="$2" 50 shift 2 51 ;; 52 -l|--ledger) 53 USE_LEDGER=true 54 shift 55 ;; 56 -d|--dry-run) 57 DRY_RUN=true 58 shift 59 ;; 60 --no-verify) 61 VERIFY=false 62 shift 63 ;; 64 -h|--help) 65 usage 66 ;; 67 *) 68 echo -e "${RED}Unknown option: $1${NC}" 69 usage 70 ;; 71 esac 72 done 73 74 # Source environment files early 75 if [ -f ".env" ]; then 76 source .env 77 fi 78 if [ -f "../.env" ]; then 79 source ../.env 80 fi 81 82 # Validate required arguments 83 if [ -z "$NETWORK" ]; then 84 echo -e "${RED}Error: Network is required${NC}" 85 usage 86 fi 87 88 # Network configuration - hardcoded to avoid jq dependency 89 case "$NETWORK" in 90 "base-mainnet") 91 CHAIN_ID=8453 92 RPC_URL="https://mainnet.base.org" 93 VERIFIER="etherscan" 94 VERIFIER_URL="https://api.basescan.org/api" 95 USDC_ADDRESS="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" 96 SPLITS_ADDRESS="0x90840E8cfbeEB3adC85cb665A5b9CeB942150f88" 97 DEPLOY_WITH_PROXY=true 98 VERIFY=false 99 ;; 100 "base-sepolia") 101 CHAIN_ID=84532 102 RPC_URL="https://sepolia.base.org" 103 VERIFIER="blockscout" 104 VERIFIER_URL="https://base-sepolia.blockscout.com/api" 105 USDC_ADDRESS="0x036CbD53842c5426634e7929541eC2318f3dCF7e" 106 SPLITS_ADDRESS="0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE" 107 ;; 108 "optimism-sepolia") 109 CHAIN_ID=11155420 110 RPC_URL="https://sepolia.optimism.io" 111 VERIFIER="blockscout" 112 VERIFIER_URL="https://optimism-sepolia.blockscout.com/api" 113 USDC_ADDRESS="0x5fd84259d66Cd46123540766Be93DFE6D43130D7" 114 SPLITS_ADDRESS="0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE" 115 ;; 116 *) 117 echo -e "${RED}Error: Unknown network: $NETWORK${NC}" 118 echo "Available networks: base-mainnet, base-sepolia, optimism-sepolia" 119 exit 1 120 ;; 121 esac 122 123 # Determine version to deploy 124 if [ -z "$VERSION" ] || [ "$VERSION" == "latest" ]; then 125 VERSION="v5" # Current version 126 fi 127 128 # Contract configuration 129 case "$VERSION" in 130 "v4") 131 CONTRACT_NAME="KaraokeSchoolV4" 132 ;; 133 "v5") 134 CONTRACT_NAME="KaraokeSchoolV5" 135 ;; 136 *) 137 echo -e "${RED}Error: Only v4 and v5 are supported. V3 is deprecated.${NC}" 138 exit 1 139 ;; 140 esac 141 REQUIRES_USDC=false 142 # Don't override DEPLOY_WITH_PROXY if it's already set by network config 143 if [ -z "$DEPLOY_WITH_PROXY" ]; then 144 DEPLOY_WITH_PROXY=false 145 fi 146 147 # Display configuration 148 echo -e "${BLUE}🚀 KaraokeSchool Deployment Configuration${NC}" 149 echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" 150 echo -e "Network: ${GREEN}$NETWORK${NC}" 151 echo -e "Chain ID: ${GREEN}$CHAIN_ID${NC}" 152 echo -e "RPC URL: ${GREEN}$RPC_URL${NC}" 153 echo -e "Contract: ${GREEN}$CONTRACT_NAME${NC}" 154 echo -e "Deploy Proxy: ${GREEN}$DEPLOY_WITH_PROXY${NC}" 155 echo -e "Signing Method: ${GREEN}$([ "$USE_LEDGER" = true ] && echo "Ledger" || echo "Private Key")${NC}" 156 echo -e "Dry Run: ${GREEN}$DRY_RUN${NC}" 157 echo -e "Verify: ${GREEN}$VERIFY${NC}" 158 echo "" 159 echo -e "Contracts:" 160 echo -e " USDC: ${YELLOW}$USDC_ADDRESS${NC}" 161 echo -e " Splits: ${YELLOW}$SPLITS_ADDRESS${NC}" 162 echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" 163 echo "" 164 165 # Setup environment variables 166 export USDC_ADDRESS 167 export SPLITS_ADDRESS 168 169 # Handle Ledger deployment 170 if [ "$USE_LEDGER" = true ]; then 171 echo -e "${YELLOW}⚠️ Ledger Deployment Requirements:${NC}" 172 echo " - Ledger connected and unlocked" 173 echo " - Ethereum app open" 174 echo " - Blind signing enabled (if needed)" 175 echo "" 176 177 # Get Ledger address 178 echo -e "${BLUE}🔍 Detecting Ledger address...${NC}" 179 LEDGER_ADDRESS=$(cast wallet address --ledger) 180 echo -e "${GREEN}📍 Ledger address: $LEDGER_ADDRESS${NC}" 181 182 # Check balance 183 BALANCE=$(cast balance $LEDGER_ADDRESS --rpc-url $RPC_URL | sed 's/[^0-9.]//g') 184 echo -e "${GREEN}💰 Balance: $BALANCE ETH${NC}" 185 186 # Check if balance is sufficient 187 if (( $(echo "$BALANCE < 0.01" | bc -l) )); then 188 echo -e "${RED}❌ Insufficient balance for deployment${NC}" 189 exit 1 190 fi 191 192 SENDER_ARGS="--ledger --sender $LEDGER_ADDRESS" 193 else 194 # Check for private key 195 if [ -z "$PRIVATE_KEY" ]; then 196 echo -e "${RED}Error: PRIVATE_KEY not found${NC}" 197 echo "Please set PRIVATE_KEY in .env file" 198 exit 1 199 fi 200 201 # Add 0x prefix if missing 202 if [[ ! "$PRIVATE_KEY" =~ ^0x ]]; then 203 PRIVATE_KEY="0x${PRIVATE_KEY}" 204 fi 205 206 SENDER_ARGS="" 207 fi 208 209 # Check for API key if verification is enabled 210 if [ "$VERIFY" = true ] && [ "$NETWORK" == "base-mainnet" ] && [ -z "$ETHERSCAN_API_KEY" ]; then 211 echo -e "${YELLOW}Warning: ETHERSCAN_API_KEY not set, verification may fail${NC}" 212 fi 213 214 # Prepare verification arguments 215 if [ "$VERIFY" = true ]; then 216 VERIFY_ARGS="--verify --verifier $VERIFIER --verifier-url $VERIFIER_URL" 217 if [ "$NETWORK" == "base-mainnet" ] || [ "$NETWORK" == "base-sepolia" ]; then 218 # Ensure we have the API key 219 if [ -z "$ETHERSCAN_API_KEY" ]; then 220 echo -e "${RED}Error: ETHERSCAN_API_KEY not set for verification${NC}" 221 exit 1 222 fi 223 VERIFY_ARGS="$VERIFY_ARGS --etherscan-api-key $ETHERSCAN_API_KEY" 224 fi 225 else 226 VERIFY_ARGS="" 227 fi 228 229 # Select deployment script based on version 230 if [ "$VERSION" == "v5" ]; then 231 DEPLOY_SCRIPT="script/DeployV5.s.sol" 232 else 233 DEPLOY_SCRIPT="script/DeployUnified.s.sol" 234 fi 235 236 # Set environment variables for the script 237 export CONTRACT_VERSION=$VERSION 238 export DEPLOY_PROXY=$DEPLOY_WITH_PROXY 239 export USE_LEDGER=$USE_LEDGER 240 export PRIVATE_KEY=$PRIVATE_KEY 241 242 # Build command 243 FORGE_CMD="forge script $DEPLOY_SCRIPT --rpc-url $RPC_URL $SENDER_ARGS" 244 245 # Add private key for non-ledger deployments 246 if [ "$USE_LEDGER" = false ] && [ -n "$PRIVATE_KEY" ]; then 247 FORGE_CMD="$FORGE_CMD --private-key $PRIVATE_KEY" 248 fi 249 250 if [ "$DRY_RUN" = false ]; then 251 FORGE_CMD="$FORGE_CMD --broadcast" 252 fi 253 254 FORGE_CMD="$FORGE_CMD $VERIFY_ARGS -vvv" 255 256 # Display command to be executed 257 echo -e "${BLUE}📋 Deployment Command:${NC}" 258 echo "$FORGE_CMD" 259 echo "" 260 261 if [ "$DRY_RUN" = false ]; then 262 # Only prompt for confirmation on mainnet with private key 263 if [ "$NETWORK" == "base-mainnet" ] && [ "$USE_LEDGER" = false ]; then 264 echo "Press Enter to deploy or Ctrl+C to cancel..." 265 read 266 fi 267 fi 268 269 # Execute deployment 270 echo -e "${BLUE}🚀 Starting deployment...${NC}" 271 eval $FORGE_CMD 272 273 if [ $? -eq 0 ]; then 274 echo "" 275 echo -e "${GREEN}✅ Deployment successful!${NC}" 276 277 if [ "$DRY_RUN" = false ]; then 278 # Save deployment info 279 DEPLOYMENT_DIR="deployments" 280 mkdir -p $DEPLOYMENT_DIR 281 282 DEPLOYMENT_FILE="$DEPLOYMENT_DIR/${NETWORK}-$(date +%Y%m%d-%H%M%S).json" 283 284 # Save basic deployment info 285 echo "{" > $DEPLOYMENT_FILE 286 echo " \"network\": \"$NETWORK\"," >> $DEPLOYMENT_FILE 287 echo " \"chainId\": $CHAIN_ID," >> $DEPLOYMENT_FILE 288 echo " \"version\": \"$VERSION\"," >> $DEPLOYMENT_FILE 289 echo " \"contractName\": \"$CONTRACT_NAME\"," >> $DEPLOYMENT_FILE 290 echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> $DEPLOYMENT_FILE 291 echo " \"deployedWith\": \"$([ "$USE_LEDGER" = true ] && echo "ledger" || echo "privateKey")\"" >> $DEPLOYMENT_FILE 292 echo "}" >> $DEPLOYMENT_FILE 293 294 echo -e "${GREEN}📄 Deployment info saved to: $DEPLOYMENT_FILE${NC}" 295 echo -e "${YELLOW}Note: Check broadcast/$DEPLOY_SCRIPT/$CHAIN_ID/run-latest.json for detailed deployment data${NC}" 296 297 echo "" 298 echo -e "${YELLOW}📌 Next Steps:${NC}" 299 echo "1. Update .env files with the new contract address" 300 echo "2. Run verification script: ./check-deployment.sh -n $NETWORK" 301 echo "3. Update frontend configuration" 302 303 if [ "$VERSION" == "v4" ]; then 304 echo "4. If upgrading existing proxy, call upgradeTo() with new implementation" 305 fi 306 fi 307 else 308 echo -e "${RED}❌ Deployment failed${NC}" 309 exit 1 310 fi