/ contracts / deploy.sh
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