2025-09-24 10:57:22 +02:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2025-10-01 20:26:49 +02:00
|
|
|
# Install jq if not available
|
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
|
|
|
apk add --no-cache jq >/dev/null 2>&1 || apt-get update && apt-get install -y jq >/dev/null 2>&1 || true
|
|
|
|
|
fi
|
|
|
|
|
|
2025-09-24 10:57:22 +02:00
|
|
|
ROOT_DIR=/workspace
|
2025-10-02 17:11:22 +02:00
|
|
|
GIT_BRANCH="${GIT_BRANCH:-}"
|
|
|
|
|
|
|
|
|
|
# Checkout branch if specified
|
|
|
|
|
if [[ -n "$GIT_BRANCH" ]]; then
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
git config --global --add safe.directory "$ROOT_DIR" 2>/dev/null || true
|
|
|
|
|
CURRENT=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
|
|
|
|
|
|
|
|
if [[ "$CURRENT" != "$GIT_BRANCH" ]]; then
|
|
|
|
|
echo "[bootstrap] Switching to branch: $GIT_BRANCH"
|
|
|
|
|
# Try local branch first, then remote
|
|
|
|
|
if git rev-parse --verify "$GIT_BRANCH" >/dev/null 2>&1; then
|
|
|
|
|
git checkout "$GIT_BRANCH" 2>/dev/null || echo "[bootstrap] WARNING: Could not checkout $GIT_BRANCH"
|
|
|
|
|
else
|
|
|
|
|
git fetch origin "$GIT_BRANCH" 2>/dev/null || true
|
|
|
|
|
git checkout "$GIT_BRANCH" 2>/dev/null || echo "[bootstrap] WARNING: Could not checkout $GIT_BRANCH"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2026-02-03 12:07:28 +01:00
|
|
|
|
2025-11-08 14:08:46 +01:00
|
|
|
STATE_DIR=$ROOT_DIR/tmp/containers
|
2025-09-24 10:57:22 +02:00
|
|
|
LOG_DIR=$STATE_DIR/logs
|
|
|
|
|
SETUP_LOG=$LOG_DIR/setup.log
|
|
|
|
|
MNEMONIC_FILE=$ROOT_DIR/onchain/.secret.local
|
|
|
|
|
|
|
|
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
|
: >"$SETUP_LOG"
|
|
|
|
|
|
2026-02-03 12:07:28 +01:00
|
|
|
# ── Configure shared bootstrap variables ──
|
2025-09-24 10:57:22 +02:00
|
|
|
ANVIL_RPC=${ANVIL_RPC:-"http://anvil:8545"}
|
2026-02-03 12:07:28 +01:00
|
|
|
CONTRACT_ENV=$STATE_DIR/contracts.env
|
|
|
|
|
LOG_FILE=$SETUP_LOG
|
|
|
|
|
ONCHAIN_DIR=$ROOT_DIR/onchain
|
2025-09-24 10:57:22 +02:00
|
|
|
TXNBOT_FUND_VALUE=${TXNBOT_FUND_VALUE:-1ether}
|
|
|
|
|
|
2026-02-03 12:07:28 +01:00
|
|
|
# Source shared bootstrap functions
|
|
|
|
|
# shellcheck source=../scripts/bootstrap-common.sh
|
|
|
|
|
source "$ROOT_DIR/scripts/bootstrap-common.sh"
|
2025-10-04 18:08:10 +02:00
|
|
|
|
2026-02-03 12:07:28 +01:00
|
|
|
# ── Local-only helpers ─────────────────────────────────────────────────
|
2025-09-24 10:57:22 +02:00
|
|
|
|
|
|
|
|
maybe_set_deployer_from_mnemonic() {
|
2026-02-03 12:07:28 +01:00
|
|
|
if [[ -n "$DEPLOYER_PK" && "$DEPLOYER_PK" != "$DEFAULT_DEPLOYER_PK" ]]; then
|
2025-09-24 10:57:22 +02:00
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
if [[ -f "$MNEMONIC_FILE" ]]; then
|
|
|
|
|
local mnemonic pk addr
|
|
|
|
|
mnemonic="$(tr -d '\n\r' <"$MNEMONIC_FILE")"
|
|
|
|
|
if [[ -n "$mnemonic" ]]; then
|
|
|
|
|
pk="$(cast wallet private-key --mnemonic "$mnemonic" --mnemonic-derivation-path "m/44'/60'/0'/0/0")"
|
|
|
|
|
addr="$(cast wallet address --private-key "$pk")"
|
2026-02-03 12:07:28 +01:00
|
|
|
DEPLOYER_PK=${pk}
|
|
|
|
|
DEPLOYER_ADDR=${addr}
|
2025-09-24 10:57:22 +02:00
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-02 17:11:22 +02:00
|
|
|
derive_txnbot_wallet() {
|
|
|
|
|
if [[ -f "$MNEMONIC_FILE" ]]; then
|
|
|
|
|
local mnemonic
|
|
|
|
|
mnemonic="$(tr -d '\n\r' <"$MNEMONIC_FILE")"
|
|
|
|
|
if [[ -n "$mnemonic" ]]; then
|
|
|
|
|
TXNBOT_PRIVATE_KEY="$(cast wallet private-key --mnemonic "$mnemonic" --mnemonic-index 2)"
|
|
|
|
|
TXNBOT_ADDRESS="$(cast wallet address --private-key "$TXNBOT_PRIVATE_KEY")"
|
2026-02-03 12:07:28 +01:00
|
|
|
bootstrap_log "Derived txnBot wallet: $TXNBOT_ADDRESS (account index 2)"
|
2025-10-02 17:11:22 +02:00
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
# Fallback to hardcoded Anvil account 1
|
2026-02-03 12:07:28 +01:00
|
|
|
TXNBOT_PRIVATE_KEY=$DEFAULT_TXNBOT_PK
|
|
|
|
|
TXNBOT_ADDRESS=$DEFAULT_TXNBOT_ADDR
|
|
|
|
|
bootstrap_log "Using default txnBot wallet: $TXNBOT_ADDRESS"
|
2025-10-07 21:57:32 +00:00
|
|
|
}
|
|
|
|
|
|
2025-09-24 10:57:22 +02:00
|
|
|
write_ponder_env() {
|
|
|
|
|
cat >"$ROOT_DIR/services/ponder/.env.local" <<EOPONDER
|
|
|
|
|
PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK
|
|
|
|
|
KRAIKEN_ADDRESS=$KRAIKEN
|
|
|
|
|
STAKE_ADDRESS=$STAKE
|
|
|
|
|
START_BLOCK=$DEPLOY_BLOCK
|
|
|
|
|
PONDER_RPC_URL_BASE_SEPOLIA_LOCAL_FORK=$ANVIL_RPC
|
2025-10-01 20:26:49 +02:00
|
|
|
DATABASE_URL=postgresql://ponder:ponder_local@postgres:5432/ponder_local
|
|
|
|
|
DATABASE_SCHEMA=ponder_local_${DEPLOY_BLOCK}
|
2025-09-24 10:57:22 +02:00
|
|
|
EOPONDER
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
write_txn_bot_env() {
|
2026-02-03 12:07:28 +01:00
|
|
|
local txnbot_env=$STATE_DIR/txnBot.env
|
2025-10-11 10:55:49 +00:00
|
|
|
local provider_url=${TXNBOT_PROVIDER_URL:-$ANVIL_RPC}
|
|
|
|
|
local graphql_endpoint=${TXNBOT_GRAPHQL_ENDPOINT:-http://ponder:42069/graphql}
|
2026-02-03 12:07:28 +01:00
|
|
|
cat >"$txnbot_env" <<EOTXNBOT
|
2025-09-24 10:57:22 +02:00
|
|
|
ENVIRONMENT=BASE_SEPOLIA_LOCAL_FORK
|
2025-10-11 10:55:49 +00:00
|
|
|
PROVIDER_URL=$provider_url
|
2025-09-24 10:57:22 +02:00
|
|
|
PRIVATE_KEY=$TXNBOT_PRIVATE_KEY
|
|
|
|
|
LM_CONTRACT_ADDRESS=$LIQUIDITY_MANAGER
|
|
|
|
|
STAKE_CONTRACT_ADDRESS=$STAKE
|
2025-10-11 10:55:49 +00:00
|
|
|
GRAPHQL_ENDPOINT=$graphql_endpoint
|
2025-09-24 10:57:22 +02:00
|
|
|
WALLET_ADDRESS=$TXNBOT_ADDRESS
|
|
|
|
|
PORT=43069
|
|
|
|
|
EOTXNBOT
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-03 12:07:28 +01:00
|
|
|
prime_chain() {
|
|
|
|
|
bootstrap_log "Pre-mining 5 blocks (minimal warmup for fast Ponder sync)..."
|
|
|
|
|
if cast rpc --rpc-url "$ANVIL_RPC" anvil_mine "0x5" "0x1" >/dev/null 2>&1; then
|
|
|
|
|
bootstrap_log "Mined 5 blocks"
|
|
|
|
|
else
|
|
|
|
|
bootstrap_log "Batch mining failed, using individual evm_mine calls"
|
|
|
|
|
for i in {1..5}; do
|
|
|
|
|
cast rpc --rpc-url "$ANVIL_RPC" evm_mine >/dev/null 2>&1 || true
|
|
|
|
|
done
|
2025-09-24 10:57:22 +02:00
|
|
|
fi
|
2026-02-03 12:07:28 +01:00
|
|
|
bootstrap_log "Pre-mining complete"
|
2025-09-24 10:57:22 +02:00
|
|
|
}
|
|
|
|
|
|
2026-02-03 12:07:28 +01:00
|
|
|
# ── Main ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
2025-09-24 10:57:22 +02:00
|
|
|
main() {
|
2026-02-03 12:07:28 +01:00
|
|
|
local start_time
|
|
|
|
|
start_time=$(date +%s%3N)
|
|
|
|
|
|
|
|
|
|
bootstrap_log "Waiting for Anvil"
|
2025-09-24 10:57:22 +02:00
|
|
|
wait_for_rpc
|
2026-03-13 11:55:22 +00:00
|
|
|
|
|
|
|
|
# Idempotency: if deployments-local.json exists and contracts have code,
|
|
|
|
|
# bootstrap already ran against this Anvil instance — skip.
|
|
|
|
|
local deploy_file="$ONCHAIN_DIR/deployments-local.json"
|
|
|
|
|
if [[ -f "$deploy_file" ]]; then
|
|
|
|
|
local krk_addr
|
|
|
|
|
krk_addr=$(jq -r '.contracts.Kraiken // empty' "$deploy_file" 2>/dev/null || true)
|
|
|
|
|
if [[ -n "$krk_addr" ]]; then
|
|
|
|
|
local code
|
|
|
|
|
code=$(cast call --rpc-url "$ANVIL_RPC" "$krk_addr" "decimals()(uint8)" 2>/dev/null || true)
|
|
|
|
|
if [[ -n "$code" && "$code" != "0x" ]]; then
|
|
|
|
|
bootstrap_log "Already bootstrapped (Kraiken at $krk_addr responds) — skipping"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2025-09-24 10:57:22 +02:00
|
|
|
maybe_set_deployer_from_mnemonic
|
2026-03-13 11:55:22 +00:00
|
|
|
|
|
|
|
|
# On forked networks, well-known addresses (Anvil mnemonic accounts) may
|
|
|
|
|
# have code (e.g. ERC-4337 Account Abstraction proxies on Base Sepolia).
|
|
|
|
|
# The feeDestination lock in LiquidityManager treats any address with code
|
|
|
|
|
# as a contract and locks permanently. Strip code so they behave as EOAs.
|
|
|
|
|
bootstrap_log "Clearing code from deployer + feeDest (fork safety)"
|
|
|
|
|
cast rpc --rpc-url "$ANVIL_RPC" anvil_setCode "$DEPLOYER_ADDR" "0x" 2>/dev/null || true
|
|
|
|
|
# feeDest = address(uint160(uint256(keccak256("harb.local.feeDest"))))
|
|
|
|
|
cast rpc --rpc-url "$ANVIL_RPC" anvil_setCode "0x8A9145E1Ea4C4d7FB08cF1011c8ac1F0e10F9383" "0x" 2>/dev/null || true
|
|
|
|
|
|
2025-10-02 17:11:22 +02:00
|
|
|
derive_txnbot_wallet
|
2025-09-24 10:57:22 +02:00
|
|
|
run_forge_script
|
|
|
|
|
extract_addresses
|
2026-02-03 12:07:28 +01:00
|
|
|
write_contracts_env
|
2026-03-13 23:28:52 +00:00
|
|
|
bootstrap_vwap
|
2025-09-24 10:57:22 +02:00
|
|
|
fund_liquidity_manager
|
|
|
|
|
seed_application_state
|
2025-10-07 21:57:32 +00:00
|
|
|
write_deployments_json
|
2025-09-24 10:57:22 +02:00
|
|
|
write_ponder_env
|
|
|
|
|
write_txn_bot_env
|
|
|
|
|
fund_txn_bot_wallet
|
2025-10-02 17:00:21 +02:00
|
|
|
prime_chain &
|
|
|
|
|
local prime_pid=$!
|
2025-10-04 18:08:10 +02:00
|
|
|
wait "$prime_pid"
|
2026-02-03 12:07:28 +01:00
|
|
|
|
|
|
|
|
local end_time
|
|
|
|
|
end_time=$(date +%s%3N)
|
|
|
|
|
local elapsed_ms=$((end_time - start_time))
|
|
|
|
|
local elapsed_sec
|
2025-10-04 18:08:10 +02:00
|
|
|
elapsed_sec=$(awk -v ms="$elapsed_ms" 'BEGIN { printf "%.3f", ms/1000 }')
|
2026-02-03 12:07:28 +01:00
|
|
|
bootstrap_log "Bootstrap complete in ${elapsed_sec}s"
|
|
|
|
|
bootstrap_log "Kraiken: $KRAIKEN"
|
|
|
|
|
bootstrap_log "Stake: $STAKE"
|
|
|
|
|
bootstrap_log "LiquidityManager: $LIQUIDITY_MANAGER"
|
|
|
|
|
bootstrap_log "txnBot: $TXNBOT_ADDRESS"
|
2025-09-24 10:57:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main "$@"
|