327 lines
10 KiB
Bash
327 lines
10 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Deploy and seed a first-tier Mainnet DODO PMM Wave 1 cW*/USDC pool.
|
|
#
|
|
# Amount arguments are base units (6 decimals for the current cW* / USDC suite).
|
|
#
|
|
# Example:
|
|
# bash scripts/deployment/deploy-mainnet-public-dodo-wave1-pool.sh \
|
|
# --pair=cweurc-usdc \
|
|
# --initial-price=1151700000000000000 \
|
|
# --base-amount=1250000 \
|
|
# --quote-amount=1439625 \
|
|
# --mint-base-amount=1300000
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
|
|
source "${PROJECT_ROOT}/smom-dbis-138/scripts/load-env.sh" >/dev/null 2>&1
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || {
|
|
echo "[fail] missing required command: $1" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
uint_lt() {
|
|
python3 - "$1" "$2" <<'PY'
|
|
import sys
|
|
print("1" if int(sys.argv[1]) < int(sys.argv[2]) else "0")
|
|
PY
|
|
}
|
|
|
|
require_cmd cast
|
|
|
|
PAIR=""
|
|
INITIAL_PRICE=""
|
|
BASE_AMOUNT=""
|
|
QUOTE_AMOUNT=""
|
|
MINT_BASE_AMOUNT="0"
|
|
FEE_BPS="10"
|
|
K_VALUE="0"
|
|
OPEN_TWAP="false"
|
|
DRY_RUN=0
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--pair=*) PAIR="${arg#*=}" ;;
|
|
--initial-price=*) INITIAL_PRICE="${arg#*=}" ;;
|
|
--base-amount=*) BASE_AMOUNT="${arg#*=}" ;;
|
|
--quote-amount=*) QUOTE_AMOUNT="${arg#*=}" ;;
|
|
--mint-base-amount=*) MINT_BASE_AMOUNT="${arg#*=}" ;;
|
|
--fee-bps=*) FEE_BPS="${arg#*=}" ;;
|
|
--k=*) K_VALUE="${arg#*=}" ;;
|
|
--open-twap=*) OPEN_TWAP="${arg#*=}" ;;
|
|
--dry-run) DRY_RUN=1 ;;
|
|
*)
|
|
echo "[fail] unknown arg: $arg" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$PAIR" || -z "$INITIAL_PRICE" || -z "$BASE_AMOUNT" || -z "$QUOTE_AMOUNT" ]]; then
|
|
echo "[fail] required args: --pair, --initial-price, --base-amount, --quote-amount" >&2
|
|
exit 1
|
|
fi
|
|
|
|
RPC_URL="${ETHEREUM_MAINNET_RPC:-}"
|
|
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
|
INTEGRATION="${DODO_PMM_INTEGRATION_MAINNET:-}"
|
|
USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
|
|
|
if [[ -z "$RPC_URL" || -z "$PRIVATE_KEY" || -z "$INTEGRATION" ]]; then
|
|
echo "[fail] ETHEREUM_MAINNET_RPC, PRIVATE_KEY, and DODO_PMM_INTEGRATION_MAINNET are required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
|
|
|
BASE_SYMBOL=""
|
|
BASE_TOKEN=""
|
|
POOL_ENV_KEY=""
|
|
PAIR_LABEL=""
|
|
|
|
case "$PAIR" in
|
|
cweurc-usdc)
|
|
BASE_SYMBOL="cWEURC"
|
|
BASE_TOKEN="${CWEURC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWEURC_USDC_MAINNET"
|
|
PAIR_LABEL="cWEURC/USDC"
|
|
;;
|
|
cweurt-usdc)
|
|
BASE_SYMBOL="cWEURT"
|
|
BASE_TOKEN="${CWEURT_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWEURT_USDC_MAINNET"
|
|
PAIR_LABEL="cWEURT/USDC"
|
|
;;
|
|
cwgbpc-usdc)
|
|
BASE_SYMBOL="cWGBPC"
|
|
BASE_TOKEN="${CWGBPC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWGBPC_USDC_MAINNET"
|
|
PAIR_LABEL="cWGBPC/USDC"
|
|
;;
|
|
cwgbpt-usdc)
|
|
BASE_SYMBOL="cWGBPT"
|
|
BASE_TOKEN="${CWGBPT_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWGBPT_USDC_MAINNET"
|
|
PAIR_LABEL="cWGBPT/USDC"
|
|
;;
|
|
cwaudc-usdc)
|
|
BASE_SYMBOL="cWAUDC"
|
|
BASE_TOKEN="${CWAUDC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWAUDC_USDC_MAINNET"
|
|
PAIR_LABEL="cWAUDC/USDC"
|
|
;;
|
|
cwjpyc-usdc)
|
|
BASE_SYMBOL="cWJPYC"
|
|
BASE_TOKEN="${CWJPYC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWJPYC_USDC_MAINNET"
|
|
PAIR_LABEL="cWJPYC/USDC"
|
|
;;
|
|
cwchfc-usdc)
|
|
BASE_SYMBOL="cWCHFC"
|
|
BASE_TOKEN="${CWCHFC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWCHFC_USDC_MAINNET"
|
|
PAIR_LABEL="cWCHFC/USDC"
|
|
;;
|
|
cwcadc-usdc)
|
|
BASE_SYMBOL="cWCADC"
|
|
BASE_TOKEN="${CWCADC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWCADC_USDC_MAINNET"
|
|
PAIR_LABEL="cWCADC/USDC"
|
|
;;
|
|
cwxauc-usdc)
|
|
BASE_SYMBOL="cWXAUC"
|
|
BASE_TOKEN="${CWXAUC_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWXAUC_USDC_MAINNET"
|
|
PAIR_LABEL="cWXAUC/USDC"
|
|
;;
|
|
cwxaut-usdc)
|
|
BASE_SYMBOL="cWXAUT"
|
|
BASE_TOKEN="${CWXAUT_MAINNET:-}"
|
|
POOL_ENV_KEY="POOL_CWXAUT_USDC_MAINNET"
|
|
PAIR_LABEL="cWXAUT/USDC"
|
|
;;
|
|
*)
|
|
echo "[fail] unsupported pair: $PAIR" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
if [[ -z "$BASE_TOKEN" ]]; then
|
|
echo "[fail] base token address missing in .env for pair: $PAIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
parse_tx_hash() {
|
|
local output="$1"
|
|
local tx_hash
|
|
tx_hash="$(printf '%s\n' "$output" | grep -E '^0x[0-9a-fA-F]{64}$' | tail -n1 || true)"
|
|
if [[ -z "$tx_hash" ]]; then
|
|
tx_hash="$(printf '%s\n' "$output" | grep -E '^transactionHash[[:space:]]+0x[0-9a-fA-F]{64}$' | awk '{print $2}' | tail -n1 || true)"
|
|
fi
|
|
if [[ -z "$tx_hash" ]]; then
|
|
return 1
|
|
fi
|
|
printf '%s\n' "$tx_hash"
|
|
}
|
|
|
|
bool_to_cli() {
|
|
if [[ "$1" == "true" ]]; then
|
|
printf 'true'
|
|
else
|
|
printf 'false'
|
|
fi
|
|
}
|
|
|
|
existing_pool="$(cast call "$INTEGRATION" 'pools(address,address)(address)' "$BASE_TOKEN" "$USDC_MAINNET" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
|
|
base_balance_before="$(cast call "$BASE_TOKEN" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
quote_balance_before="$(cast call "$USDC_MAINNET" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
base_allowance_before="$(cast call "$BASE_TOKEN" 'allowance(address,address)(uint256)' "$DEPLOYER" "$INTEGRATION" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
quote_allowance_before="$(cast call "$USDC_MAINNET" 'allowance(address,address)(uint256)' "$DEPLOYER" "$INTEGRATION" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
base_approval_required="$(uint_lt "$base_allowance_before" "$BASE_AMOUNT")"
|
|
quote_approval_required="$(uint_lt "$quote_allowance_before" "$QUOTE_AMOUNT")"
|
|
|
|
create_gas="0"
|
|
if [[ "$existing_pool" == "0x0000000000000000000000000000000000000000" ]]; then
|
|
create_gas="$(cast estimate "$INTEGRATION" \
|
|
'createPool(address,address,uint256,uint256,uint256,bool)(address)' \
|
|
"$BASE_TOKEN" "$USDC_MAINNET" "$FEE_BPS" "$INITIAL_PRICE" "$K_VALUE" "$(bool_to_cli "$OPEN_TWAP")" \
|
|
--from "$DEPLOYER" \
|
|
--rpc-url "$RPC_URL")"
|
|
fi
|
|
|
|
if (( base_balance_before < BASE_AMOUNT )); then
|
|
base_balance_after_mint=$(( base_balance_before + MINT_BASE_AMOUNT ))
|
|
if (( MINT_BASE_AMOUNT == 0 || base_balance_after_mint < BASE_AMOUNT )); then
|
|
echo "[fail] insufficient ${BASE_SYMBOL} balance: have=$base_balance_before need=$BASE_AMOUNT mint_base_amount=$MINT_BASE_AMOUNT" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if (( quote_balance_before < QUOTE_AMOUNT )); then
|
|
echo "[fail] insufficient USDC balance: have=$quote_balance_before need=$QUOTE_AMOUNT" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if (( DRY_RUN == 1 )); then
|
|
echo "pair=$PAIR_LABEL"
|
|
echo "baseToken=$BASE_TOKEN"
|
|
echo "quoteToken=$USDC_MAINNET"
|
|
echo "integration=$INTEGRATION"
|
|
echo "existingPool=$existing_pool"
|
|
echo "poolEnvKey=$POOL_ENV_KEY"
|
|
echo "initialPrice=$INITIAL_PRICE"
|
|
echo "feeBps=$FEE_BPS"
|
|
echo "k=$K_VALUE"
|
|
echo "openTwap=$OPEN_TWAP"
|
|
echo "createGas=$create_gas"
|
|
echo "baseAmount=$BASE_AMOUNT"
|
|
echo "quoteAmount=$QUOTE_AMOUNT"
|
|
echo "mintBaseAmount=$MINT_BASE_AMOUNT"
|
|
echo "baseBalanceBefore=$base_balance_before"
|
|
echo "quoteBalanceBefore=$quote_balance_before"
|
|
echo "baseAllowanceBefore=$base_allowance_before"
|
|
echo "quoteAllowanceBefore=$quote_allowance_before"
|
|
exit 0
|
|
fi
|
|
|
|
mint_tx=""
|
|
create_tx=""
|
|
approve_base_tx=""
|
|
approve_quote_tx=""
|
|
add_liquidity_tx=""
|
|
|
|
if (( MINT_BASE_AMOUNT > 0 )); then
|
|
mint_output="$(
|
|
cast send "$BASE_TOKEN" \
|
|
'mint(address,uint256)' \
|
|
"$DEPLOYER" "$MINT_BASE_AMOUNT" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY"
|
|
)"
|
|
mint_tx="$(parse_tx_hash "$mint_output")"
|
|
fi
|
|
|
|
if [[ "$existing_pool" == "0x0000000000000000000000000000000000000000" ]]; then
|
|
create_output="$(
|
|
cast send "$INTEGRATION" \
|
|
'createPool(address,address,uint256,uint256,uint256,bool)(address)' \
|
|
"$BASE_TOKEN" "$USDC_MAINNET" "$FEE_BPS" "$INITIAL_PRICE" "$K_VALUE" "$(bool_to_cli "$OPEN_TWAP")" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY"
|
|
)"
|
|
create_tx="$(parse_tx_hash "$create_output")"
|
|
existing_pool="$(cast call "$INTEGRATION" 'pools(address,address)(address)' "$BASE_TOKEN" "$USDC_MAINNET" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
fi
|
|
|
|
if [[ "$existing_pool" == "0x0000000000000000000000000000000000000000" ]]; then
|
|
echo "[fail] pool creation did not yield a pool address" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$base_approval_required" == "1" ]]; then
|
|
approve_base_output="$(
|
|
cast send "$BASE_TOKEN" \
|
|
'approve(address,uint256)(bool)' \
|
|
"$INTEGRATION" "$BASE_AMOUNT" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY"
|
|
)"
|
|
approve_base_tx="$(parse_tx_hash "$approve_base_output")"
|
|
fi
|
|
|
|
if [[ "$quote_approval_required" == "1" ]]; then
|
|
approve_quote_output="$(
|
|
cast send "$USDC_MAINNET" \
|
|
'approve(address,uint256)(bool)' \
|
|
"$INTEGRATION" "$QUOTE_AMOUNT" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY"
|
|
)"
|
|
approve_quote_tx="$(parse_tx_hash "$approve_quote_output")"
|
|
fi
|
|
|
|
add_liquidity_output="$(
|
|
cast send "$INTEGRATION" \
|
|
'addLiquidity(address,uint256,uint256)(uint256,uint256,uint256)' \
|
|
"$existing_pool" "$BASE_AMOUNT" "$QUOTE_AMOUNT" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY"
|
|
)"
|
|
add_liquidity_tx="$(parse_tx_hash "$add_liquidity_output")"
|
|
|
|
reserves="$(cast call "$existing_pool" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_URL")"
|
|
base_reserve="$(printf '%s\n' "$reserves" | sed -n '1p' | awk '{print $1}')"
|
|
quote_reserve="$(printf '%s\n' "$reserves" | sed -n '2p' | awk '{print $1}')"
|
|
base_balance_after="$(cast call "$BASE_TOKEN" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
quote_balance_after="$(cast call "$USDC_MAINNET" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
|
|
echo "pair=$PAIR_LABEL"
|
|
echo "poolEnvKey=$POOL_ENV_KEY"
|
|
echo "pool=$existing_pool"
|
|
echo "baseToken=$BASE_TOKEN"
|
|
echo "quoteToken=$USDC_MAINNET"
|
|
echo "initialPrice=$INITIAL_PRICE"
|
|
echo "feeBps=$FEE_BPS"
|
|
echo "k=$K_VALUE"
|
|
echo "openTwap=$OPEN_TWAP"
|
|
echo "baseAmount=$BASE_AMOUNT"
|
|
echo "quoteAmount=$QUOTE_AMOUNT"
|
|
echo "mintBaseAmount=$MINT_BASE_AMOUNT"
|
|
echo "mintTx=${mint_tx:-none}"
|
|
echo "createTx=${create_tx:-none}"
|
|
echo "approveBaseTx=${approve_base_tx:-none}"
|
|
echo "approveQuoteTx=${approve_quote_tx:-none}"
|
|
echo "addLiquidityTx=$add_liquidity_tx"
|
|
echo "baseReserve=$base_reserve"
|
|
echo "quoteReserve=$quote_reserve"
|
|
echo "baseBalanceBefore=$base_balance_before"
|
|
echo "baseBalanceAfter=$base_balance_after"
|
|
echo "quoteBalanceBefore=$quote_balance_before"
|
|
echo "quoteBalanceAfter=$quote_balance_after"
|