- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
267 lines
8.9 KiB
Bash
Executable File
267 lines
8.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deploy contracts in parallel where dependencies allow
|
|
# Uses .env file for configuration
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Load environment variables
|
|
if [ ! -f .env ]; then
|
|
log_error "Error: .env file not found"
|
|
echo "Please create .env file with required variables"
|
|
exit 1
|
|
fi
|
|
|
|
source .env
|
|
|
|
# Check required variables
|
|
if [ -z "$PRIVATE_KEY" ]; then
|
|
log_error "Error: PRIVATE_KEY not set in .env"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$RPC_URL" ]; then
|
|
log_error "Error: RPC_URL not set in .env"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify RPC endpoint is accessible
|
|
log_warn "Verifying RPC endpoint..."
|
|
if ! curl -s -X POST "$RPC_URL" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' > /dev/null 2>&1; then
|
|
log_error "Error: RPC endpoint is not accessible"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "✅ RPC endpoint is accessible"
|
|
|
|
# Export variables for parallel execution
|
|
export PRIVATE_KEY
|
|
export RPC_URL
|
|
export CCIP_ROUTER="${CCIP_ROUTER:-}"
|
|
export CCIP_FEE_TOKEN="${CCIP_FEE_TOKEN:-0x0000000000000000000000000000000000000000}"
|
|
export ORACLE_DESCRIPTION="${ORACLE_DESCRIPTION:-ETH/USD Price Feed}"
|
|
export ORACLE_HEARTBEAT="${ORACLE_HEARTBEAT:-60}"
|
|
export ORACLE_DEVIATION_THRESHOLD="${ORACLE_DEVIATION_THRESHOLD:-50}"
|
|
|
|
# Function to update .env file
|
|
update_env() {
|
|
local key=$1
|
|
local value=$2
|
|
if grep -q "^${key}=" .env; then
|
|
sed -i "s|^${key}=.*|${key}=${value}|" .env
|
|
else
|
|
echo "${key}=${value}" >> .env
|
|
fi
|
|
log_success "✅ Updated .env: ${key}=${value}"
|
|
}
|
|
|
|
# Function to extract deployed address from forge output
|
|
extract_address() {
|
|
local output=$1
|
|
echo "$output" | grep -oE "0x[a-fA-F0-9]{40}" | tail -1 || echo ""
|
|
}
|
|
|
|
log_success "=== Starting Parallel Contract Deployment ==="
|
|
|
|
# Phase 1: Independent contracts (can be deployed in parallel)
|
|
log_warn "Phase 1: Deploying independent contracts in parallel..."
|
|
|
|
# Deploy Multicall, WETH9, and WETH10 in parallel
|
|
{
|
|
log_warn "Deploying Multicall..."
|
|
MULTICALL_OUTPUT=$(forge script script/DeployMulticall.s.sol:DeployMulticall \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
MULTICALL_ADDRESS=$(extract_address "$MULTICALL_OUTPUT")
|
|
if [ -n "$MULTICALL_ADDRESS" ]; then
|
|
update_env "MULTICALL_ADDRESS" "$MULTICALL_ADDRESS"
|
|
log_success "✅ Multicall deployed at: $MULTICALL_ADDRESS"
|
|
fi
|
|
} &
|
|
MULTICALL_PID=$!
|
|
|
|
{
|
|
log_warn "Deploying WETH9..."
|
|
WETH9_OUTPUT=$(forge script script/DeployWETH.s.sol:DeployWETH \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
WETH9_ADDRESS=$(extract_address "$WETH9_OUTPUT")
|
|
if [ -n "$WETH9_ADDRESS" ]; then
|
|
update_env "WETH9_ADDRESS" "$WETH9_ADDRESS"
|
|
log_success "✅ WETH9 deployed at: $WETH9_ADDRESS"
|
|
fi
|
|
} &
|
|
WETH9_PID=$!
|
|
|
|
{
|
|
log_warn "Deploying WETH10..."
|
|
WETH10_OUTPUT=$(forge script script/DeployWETH10.s.sol:DeployWETH10 \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
WETH10_ADDRESS=$(extract_address "$WETH10_OUTPUT")
|
|
if [ -n "$WETH10_ADDRESS" ]; then
|
|
update_env "WETH10_ADDRESS" "$WETH10_ADDRESS"
|
|
log_success "✅ WETH10 deployed at: $WETH10_ADDRESS"
|
|
fi
|
|
} &
|
|
WETH10_PID=$!
|
|
|
|
# Wait for Phase 1 to complete
|
|
wait $MULTICALL_PID
|
|
wait $WETH9_PID
|
|
wait $WETH10_PID
|
|
|
|
# Reload .env to get deployed addresses
|
|
source .env
|
|
|
|
# Phase 2: CCIP Router (if needed)
|
|
if [ -z "$CCIP_ROUTER" ] || [ "$CCIP_ROUTER" = "0x0000000000000000000000000000000000000000" ]; then
|
|
log_warn "Phase 2: Deploying CCIP Router..."
|
|
CCIP_ROUTER_OUTPUT=$(forge script script/DeployCCIPRouter.s.sol:DeployCCIPRouter \
|
|
--sig "run(address,uint256,uint256)" \
|
|
"$CCIP_FEE_TOKEN" \
|
|
"1000000000000000" \
|
|
"1000000000" \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
CCIP_ROUTER=$(extract_address "$CCIP_ROUTER_OUTPUT")
|
|
if [ -n "$CCIP_ROUTER" ]; then
|
|
update_env "CCIP_ROUTER" "$CCIP_ROUTER"
|
|
log_success "✅ CCIP Router deployed at: $CCIP_ROUTER"
|
|
fi
|
|
else
|
|
log_success "✅ CCIP Router already configured: $CCIP_ROUTER"
|
|
fi
|
|
|
|
# Reload .env
|
|
source .env
|
|
|
|
# Phase 3: Bridge contracts (can be deployed in parallel if dependencies are met)
|
|
if [ "${DEPLOY_BRIDGES:-true}" = "true" ] && [ -n "$CCIP_ROUTER" ] && [ -n "$WETH9_ADDRESS" ] && [ -n "$WETH10_ADDRESS" ]; then
|
|
log_warn "Phase 3: Deploying CCIP bridges in parallel..."
|
|
|
|
{
|
|
log_warn "Deploying CCIPWETH9Bridge..."
|
|
export CCIP_ROUTER WETH9_ADDRESS CCIP_FEE_TOKEN
|
|
BRIDGE9_OUTPUT=$(forge script script/DeployCCIPWETH9Bridge.s.sol:DeployCCIPWETH9Bridge \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
CCIPWETH9BRIDGE_ADDRESS=$(extract_address "$BRIDGE9_OUTPUT")
|
|
if [ -n "$CCIPWETH9BRIDGE_ADDRESS" ]; then
|
|
update_env "CCIPWETH9BRIDGE_ADDRESS" "$CCIPWETH9BRIDGE_ADDRESS"
|
|
log_success "✅ CCIPWETH9Bridge deployed at: $CCIPWETH9BRIDGE_ADDRESS"
|
|
fi
|
|
} &
|
|
BRIDGE9_PID=$!
|
|
|
|
{
|
|
log_warn "Deploying CCIPWETH10Bridge..."
|
|
export CCIP_ROUTER WETH10_ADDRESS CCIP_FEE_TOKEN
|
|
BRIDGE10_OUTPUT=$(forge script script/DeployCCIPWETH10Bridge.s.sol:DeployCCIPWETH10Bridge \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
CCIPWETH10BRIDGE_ADDRESS=$(extract_address "$BRIDGE10_OUTPUT")
|
|
if [ -n "$CCIPWETH10BRIDGE_ADDRESS" ]; then
|
|
update_env "CCIPWETH10BRIDGE_ADDRESS" "$CCIPWETH10BRIDGE_ADDRESS"
|
|
log_success "✅ CCIPWETH10Bridge deployed at: $CCIPWETH10BRIDGE_ADDRESS"
|
|
fi
|
|
} &
|
|
BRIDGE10_PID=$!
|
|
|
|
wait $BRIDGE9_PID
|
|
wait $BRIDGE10_PID
|
|
else
|
|
log_warn "⚠️ Bridge deployment skipped (DEPLOY_BRIDGES=false or missing dependencies)"
|
|
fi
|
|
|
|
# Phase 4: Oracle and MultiSig (can be deployed in parallel if MultiSig owners are set)
|
|
log_warn "Phase 4: Deploying Oracle and MultiSig in parallel..."
|
|
|
|
# Deploy Oracle (independent)
|
|
{
|
|
export ORACLE_DESCRIPTION ORACLE_HEARTBEAT ORACLE_DEVIATION_THRESHOLD
|
|
ORACLE_OUTPUT=$(forge script script/DeployOracle.s.sol:DeployOracle \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
|
|
# Extract addresses (Oracle deploys both aggregator and proxy)
|
|
ORACLE_AGGREGATOR_ADDRESS=$(echo "$ORACLE_OUTPUT" | grep -i "Aggregator" | grep -oE "0x[a-fA-F0-9]{40}" | head -1)
|
|
ORACLE_PROXY_ADDRESS=$(echo "$ORACLE_OUTPUT" | grep -i "Proxy" | grep -oE "0x[a-fA-F0-9]{40}" | tail -1)
|
|
|
|
if [ -n "$ORACLE_AGGREGATOR_ADDRESS" ]; then
|
|
update_env "ORACLE_AGGREGATOR_ADDRESS" "$ORACLE_AGGREGATOR_ADDRESS"
|
|
log_success "✅ Oracle Aggregator deployed at: $ORACLE_AGGREGATOR_ADDRESS"
|
|
fi
|
|
if [ -n "$ORACLE_PROXY_ADDRESS" ]; then
|
|
update_env "ORACLE_PROXY_ADDRESS" "$ORACLE_PROXY_ADDRESS"
|
|
log_success "✅ Oracle Proxy deployed at: $ORACLE_PROXY_ADDRESS"
|
|
fi
|
|
} &
|
|
ORACLE_PID=$!
|
|
|
|
# Deploy MultiSig (independent if owners are set)
|
|
if [ -z "$MULTISIG_OWNERS" ]; then
|
|
log_warn "⚠️ MULTISIG_OWNERS not set. Skipping MultiSig deployment."
|
|
log_warn "Set MULTISIG_OWNERS in .env (comma-separated addresses) to deploy."
|
|
MULTISIG_PID=""
|
|
else
|
|
{
|
|
export OWNERS="$MULTISIG_OWNERS"
|
|
MULTISIG_OUTPUT=$(forge script script/DeployMultiSig.s.sol:DeployMultiSig \
|
|
--rpc-url "$RPC_URL" \
|
|
--broadcast \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--verify 2>&1)
|
|
MULTISIG_ADDRESS=$(extract_address "$MULTISIG_OUTPUT")
|
|
if [ -n "$MULTISIG_ADDRESS" ]; then
|
|
update_env "MULTISIG_ADDRESS" "$MULTISIG_ADDRESS"
|
|
log_success "✅ MultiSig deployed at: $MULTISIG_ADDRESS"
|
|
fi
|
|
} &
|
|
MULTISIG_PID=$!
|
|
fi
|
|
|
|
# Wait for parallel deployments to complete
|
|
wait $ORACLE_PID
|
|
if [ -n "$MULTISIG_PID" ]; then
|
|
wait $MULTISIG_PID
|
|
fi
|
|
|
|
# Reload .env to get all new addresses
|
|
source .env
|
|
|
|
# Final summary
|
|
log_success "=== Deployment Summary ==="
|
|
source .env
|
|
log_success "Multicall: ${MULTICALL_ADDRESS:-N/A}"
|
|
log_success "WETH9: ${WETH9_ADDRESS:-N/A}"
|
|
log_success "WETH10: ${WETH10_ADDRESS:-N/A}"
|
|
log_success "CCIP Router: ${CCIP_ROUTER:-N/A}"
|
|
log_success "CCIPWETH9Bridge: ${CCIPWETH9BRIDGE_ADDRESS:-N/A}"
|
|
log_success "CCIPWETH10Bridge: ${CCIPWETH10BRIDGE_ADDRESS:-N/A}"
|
|
log_success "Oracle Aggregator: ${ORACLE_AGGREGATOR_ADDRESS:-N/A}"
|
|
log_success "Oracle Proxy: ${ORACLE_PROXY_ADDRESS:-N/A}"
|
|
log_success "MultiSig: ${MULTISIG_ADDRESS:-N/A}"
|
|
log_success ""
|
|
log_success "=== Parallel Deployment Complete ==="
|
|
log_success "All addresses have been updated in .env file"
|
|
|