Files
explorer-monorepo/scripts/deploy-link-token.sh

271 lines
9.7 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# Deploy LINK Token Contract on ChainID 138
# This script deploys a standard ERC20 LINK token contract
# Usage: ./deploy-link-token.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "$PROJECT_ROOT/scripts/lib/address-inventory.sh"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
load_explorer_runtime_env
# Configuration
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
EXPECTED_LINK_ADDRESS="$(resolve_address_value LINK_TOKEN LINK_TOKEN 0x326C977E6efc84E512bB9C30f76E30c160eD06FB)"
if [ -z "${PRIVATE_KEY:-}" ]; then
log_error "PRIVATE_KEY not available in effective environment"
exit 1
fi
DEPLOYER=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || echo "")
if [ -z "$DEPLOYER" ]; then
log_error "Could not derive address from PRIVATE_KEY"
exit 1
fi
log_info "========================================="
log_info "Deploy LINK Token Contract"
log_info "========================================="
log_info ""
log_info "Network: ChainID 138"
log_info "RPC: $RPC_URL"
log_info "Deployer: $DEPLOYER"
log_info "Expected Address: $EXPECTED_LINK_ADDRESS"
log_info ""
# Check if contract already exists
log_info "Checking if LINK token already exists..."
EXISTING_CODE=$(cast code "$EXPECTED_LINK_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$EXISTING_CODE" ] && [ "$EXISTING_CODE" != "0x" ]; then
log_warn "Contract already exists at $EXPECTED_LINK_ADDRESS"
log_info "Checking if it's a valid ERC20 token..."
# Try to call standard ERC20 functions
NAME=$(cast call "$EXPECTED_LINK_ADDRESS" "name()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
SYMBOL=$(cast call "$EXPECTED_LINK_ADDRESS" "symbol()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$NAME" ] && [ -n "$SYMBOL" ]; then
log_success "✓ Valid ERC20 token found!"
log_info " Name: $NAME"
log_info " Symbol: $SYMBOL"
log_info ""
log_info "No deployment needed. Contract is already deployed."
exit 0
else
log_warn "Contract exists but doesn't appear to be a valid ERC20 token"
log_info "Proceeding with deployment to expected address..."
fi
fi
# Check if we need to use CREATE2 for deterministic address
log_info ""
log_info "Note: To deploy to the expected address ($EXPECTED_LINK_ADDRESS),"
log_info "you may need to use CREATE2 with specific salt, or deploy to a"
log_info "different address and update configurations."
log_info ""
# Create temporary contract file
TEMP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_DIR" EXIT
log_info "Creating LINK token contract..."
cat > "$TEMP_DIR/LinkToken.sol" << 'EOF'
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract LinkToken is ERC20 {
constructor() ERC20("Chainlink Token", "LINK") {
// Initial supply: 1 billion LINK (1,000,000,000 * 10^18)
_mint(msg.sender, 1_000_000_000 * 10**18);
}
}
EOF
log_info "Contract source created at: $TEMP_DIR/LinkToken.sol"
log_info ""
log_warn "⚠️ This script requires Foundry and OpenZeppelin contracts"
log_warn "⚠️ For production, use the official Chainlink LINK token contract"
log_warn "⚠️ This is a simplified ERC20 implementation"
log_info ""
# Check if forge is available
if ! command -v forge &> /dev/null; then
log_error "Foundry (forge) is not installed"
log_info "Install Foundry: https://book.getfoundry.sh/getting-started/installation"
log_info ""
log_info "Alternative: Deploy using Remix IDE or Hardhat"
log_info "Contract source saved to: $TEMP_DIR/LinkToken.sol"
exit 1
fi
# Check if source project exists
SOURCE_PROJECT="/home/intlc/projects/smom-dbis-138"
if [ ! -d "$SOURCE_PROJECT" ]; then
log_warn "Source project not found: $SOURCE_PROJECT"
log_info "Creating minimal Foundry project for deployment..."
cd "$TEMP_DIR"
forge init --no-git --force . > /dev/null 2>&1 || true
# Install OpenZeppelin
forge install OpenZeppelin/openzeppelin-contracts --no-git --no-commit > /dev/null 2>&1 || true
# Copy contract
mkdir -p src
cp LinkToken.sol src/
log_info "Minimal project created"
DEPLOY_DIR="$TEMP_DIR"
else
log_info "Using source project: $SOURCE_PROJECT"
cd "$SOURCE_PROJECT"
# Check if MockLinkToken exists
if [ -f "contracts/tokens/MockLinkToken.sol" ]; then
log_info "Found MockLinkToken contract, using it instead"
USE_MOCK=true
else
USE_MOCK=false
# Copy contract to source project if needed
if [ ! -f "contracts/LinkToken.sol" ]; then
mkdir -p contracts
cp "$TEMP_DIR/LinkToken.sol" contracts/
log_info "Contract copied to source project"
fi
fi
DEPLOY_DIR="$SOURCE_PROJECT"
fi
# Deploy contract
log_info ""
log_info "Deploying LINK token contract..."
log_info "This may take a few minutes..."
# Get optimal gas price
if [ -f "$SCRIPT_DIR/get-optimal-gas-from-api.sh" ]; then
OPTIMAL_GAS=$("$SCRIPT_DIR/get-optimal-gas-from-api.sh" "proposed" 2>/dev/null || echo "")
if [ -z "$OPTIMAL_GAS" ] || [ "$OPTIMAL_GAS" = "0" ]; then
CURRENT_GAS=$(cast gas-price --rpc-url "$RPC_URL" 2>/dev/null || echo "1000000000")
OPTIMAL_GAS=$(echo "scale=0; $CURRENT_GAS * 1.5 / 1" | bc 2>/dev/null || echo "$CURRENT_GAS")
fi
else
CURRENT_GAS=$(cast gas-price --rpc-url "$RPC_URL" 2>/dev/null || echo "1000000000")
OPTIMAL_GAS=$(echo "scale=0; $CURRENT_GAS * 1.5 / 1" | bc 2>/dev/null || echo "$CURRENT_GAS")
fi
log_info "Using gas price: $(echo "scale=2; $OPTIMAL_GAS / 1000000000" | bc) gwei"
# Deploy using forge create (direct deployment, avoids compilation issues)
cd "$DEPLOY_DIR"
if [ "${USE_MOCK:-false}" = true ]; then
CONTRACT_PATH="contracts/tokens/MockLinkToken.sol:MockLinkToken"
log_info "Deploying MockLinkToken using forge create..."
# Deploy directly - forge create should handle dependencies
DEPLOY_OUTPUT=$(forge create \
"$CONTRACT_PATH" \
--rpc-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
--gas-price "$OPTIMAL_GAS" \
2>&1 || echo "FAILED")
else
if [ "$DEPLOY_DIR" = "$TEMP_DIR" ]; then
CONTRACT_PATH="src/LinkToken.sol:LinkToken"
else
CONTRACT_PATH="contracts/LinkToken.sol:LinkToken"
fi
log_info "Deploying LinkToken using forge create..."
DEPLOY_OUTPUT=$(forge create \
"$CONTRACT_PATH" \
--rpc-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
--gas-price "$OPTIMAL_GAS" \
2>&1 || echo "FAILED")
fi
# Extract deployed address from output (handle both forge script and forge create formats)
DEPLOYED_ADDRESS=""
TX_HASH=""
if echo "$DEPLOY_OUTPUT" | grep -qE "Deployed to:"; then
DEPLOYED_ADDRESS=$(echo "$DEPLOY_OUTPUT" | grep -oE "Deployed to: 0x[0-9a-fA-F]{40}" | awk '{print $3}')
TX_HASH=$(echo "$DEPLOY_OUTPUT" | grep -oE "Transaction hash: 0x[0-9a-fA-F]{64}" | awk '{print $3}')
elif echo "$DEPLOY_OUTPUT" | grep -qE "Mock LINK Token deployed at:"; then
DEPLOYED_ADDRESS=$(echo "$DEPLOY_OUTPUT" | grep -oE "Mock LINK Token deployed at: 0x[0-9a-fA-F]{40}" | awk '{print $5}')
TX_HASH=$(echo "$DEPLOY_OUTPUT" | grep -oE "0x[0-9a-fA-F]{64}" | head -1)
fi
if [ -n "$DEPLOYED_ADDRESS" ] && [ "$DEPLOYED_ADDRESS" != "0x0000000000000000000000000000000000000000" ]; then
log_success "✓ LINK token deployed successfully!"
log_info ""
log_info "Contract Address: $DEPLOYED_ADDRESS"
log_info "Transaction Hash: $TX_HASH"
log_info ""
# Verify deployment
log_info "Verifying deployment..."
sleep 5
NAME=$(cast call "$DEPLOYED_ADDRESS" "name()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
SYMBOL=$(cast call "$DEPLOYED_ADDRESS" "symbol()" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
TOTAL_SUPPLY=$(cast call "$DEPLOYED_ADDRESS" "totalSupply()" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
DEPLOYER_BALANCE=$(cast call "$DEPLOYED_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -n "$NAME" ] && [ -n "$SYMBOL" ]; then
log_success "✓ Deployment verified!"
log_info " Name: $NAME"
log_info " Symbol: $SYMBOL"
log_info " Total Supply: $(cast --from-wei "$TOTAL_SUPPLY" ether) LINK"
log_info " Deployer Balance: $(cast --from-wei "$DEPLOYER_BALANCE" ether) LINK"
log_info ""
if [ "$DEPLOYED_ADDRESS" != "$EXPECTED_LINK_ADDRESS" ]; then
log_warn "⚠️ Deployed address differs from expected address"
log_info " Expected: $EXPECTED_LINK_ADDRESS"
log_info " Deployed: $DEPLOYED_ADDRESS"
log_info ""
log_info "Update your .env file:"
log_info " LINK_TOKEN=$DEPLOYED_ADDRESS"
log_info " CCIP_CHAIN138_LINK_TOKEN=$DEPLOYED_ADDRESS"
else
log_success "✓ Deployed to expected address!"
fi
log_info ""
log_info "Next steps:"
log_info "1. Update config/address-inventory.json with LINK token address"
log_info "2. Fund bridge contracts: ./scripts/fund-bridge-contracts.sh 10"
log_info "3. Verify contract on explorer: https://explorer.d-bis.org/address/$DEPLOYED_ADDRESS"
exit 0
else
log_error "Deployment verification failed"
log_error "Contract may not be a valid ERC20 token"
exit 1
fi
else
log_error "Deployment failed"
log_error "$DEPLOY_OUTPUT"
exit 1
fi