From da78073104aeaf227ced57fc85c79815ec1eda71 Mon Sep 17 00:00:00 2001 From: defiQUG Date: Wed, 15 Apr 2026 16:31:45 -0700 Subject: [PATCH] Deploy Chain 138 canonical non-gas PMM mesh --- config/chain138-pmm-pools.json | 29 +++- .../seed-chain138-canonical-pmm-pools.sh | 153 ++++++++++++++++++ .../sync-chain138-pmm-pools-from-json.sh | 21 ++- 3 files changed, 192 insertions(+), 11 deletions(-) create mode 100755 scripts/deployment/seed-chain138-canonical-pmm-pools.sh diff --git a/config/chain138-pmm-pools.json b/config/chain138-pmm-pools.json index 0266160..3ae0d50 100644 --- a/config/chain138-pmm-pools.json +++ b/config/chain138-pmm-pools.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "description": "Desired-state pool spec for Chain 138 DODO PMM. Scripts should create and register only missing pools from this file, not redeploy contracts.", "version": "1.0.0", - "updated": "2026-03-26", + "updated": "2026-04-15", "chainId": 138, "defaults": { "lpFeeRate": 3, @@ -48,11 +48,28 @@ ], "wethSymbol": "WETH", "deploy": { - "cStarVsCStar": true, - "cStarVsOfficial": true, - "cStarVsWeth": true, - "officialVsWeth": true + "cStarVsCStar": false, + "cStarVsOfficial": false, + "cStarVsWeth": false, + "officialVsWeth": false } }, - "explicitPairs": [] + "explicitPairs": [ + { "baseSymbol": "cUSDT", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cUSDT", "quoteSymbol": "USDT" }, + { "baseSymbol": "cUSDC", "quoteSymbol": "USDC" }, + { "baseSymbol": "cEURC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cEURT", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cGBPC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cGBPT", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cAUDC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cJPYC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cCHFC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cCADC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cXAUC", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cXAUT", "quoteSymbol": "cUSDC" }, + { "baseSymbol": "cEURC", "quoteSymbol": "cEURT" }, + { "baseSymbol": "cGBPC", "quoteSymbol": "cGBPT" }, + { "baseSymbol": "cXAUC", "quoteSymbol": "cXAUT" } + ] } diff --git a/scripts/deployment/seed-chain138-canonical-pmm-pools.sh b/scripts/deployment/seed-chain138-canonical-pmm-pools.sh new file mode 100755 index 0000000..552e1d9 --- /dev/null +++ b/scripts/deployment/seed-chain138-canonical-pmm-pools.sh @@ -0,0 +1,153 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +ENV_FILE="$SMOM_ROOT/.env" +ORIGINAL_RPC_URL_138="${RPC_URL_138:-}" + +if [[ -f "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" ]]; then + # shellcheck disable=SC1091 + source "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" + load_deployment_env --repo-root "$SMOM_ROOT" +elif [[ -f "$ENV_FILE" ]]; then + set -a + # shellcheck disable=SC1090 + source "$ENV_FILE" + set +a +fi + +if [[ -n "$ORIGINAL_RPC_URL_138" ]]; then + export RPC_URL_138="$ORIGINAL_RPC_URL_138" +fi + +command -v cast >/dev/null 2>&1 || { echo "cast is required" >&2; exit 1; } + +RPC_URL_138="${RPC_URL_138:-${RPC_URL:-http://192.168.11.221:8545}}" +DODO_PMM_INTEGRATION_ADDRESS="${DODO_PMM_INTEGRATION_ADDRESS:-${DODO_PMM_INTEGRATION:-}}" +PRIVATE_KEY="${PRIVATE_KEY:-${DEPLOYER_PRIVATE_KEY:-}}" +CHAIN_GAS_PRICE="${CHAIN_GAS_PRICE:-1000000000}" +APPROVE_GAS_LIMIT="${APPROVE_GAS_LIMIT:-200000}" +ADD_LIQUIDITY_GAS_LIMIT="${ADD_LIQUIDITY_GAS_LIMIT:-900000}" +FIAT_SEED_HUMAN="${FIAT_SEED_HUMAN:-25000}" +XAU_SEED_OZ="${XAU_SEED_OZ:-100}" +XAU_SPOT_USD="${XAU_SPOT_USD:-4506.30}" + +[[ -n "$DODO_PMM_INTEGRATION_ADDRESS" ]] || { echo "DODO_PMM_INTEGRATION_ADDRESS not set" >&2; exit 1; } +[[ -n "$PRIVATE_KEY" ]] || { echo "PRIVATE_KEY not set" >&2; exit 1; } + +DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +MAX_UINT='115792089237316195423570985008687907853269984665640564039457584007913129639935' +ZERO_ADDR='0x0000000000000000000000000000000000000000' + +declare -A TOKENS=( + [cUSDT]='0x93E66202A11B1772E55407B32B44e5Cd8eda7f22' + [cUSDC]='0xf22258f57794CC8E06237084b353Ab30fFfa640b' + [cEURC]='0x8085961F9cF02b4d800A3c6d386D31da4B34266a' + [cEURT]='0xdf4b71c61E5912712C1Bdd451416B9aC26949d72' + [cGBPC]='0x003960f16D9d34F2e98d62723B6721Fb92074aD2' + [cGBPT]='0x350f54e4D23795f86A9c03988c7135357CCaD97c' + [cAUDC]='0xD51482e567c03899eecE3CAe8a058161FD56069D' + [cJPYC]='0xEe269e1226a334182aace90056EE4ee5Cc8A6770' + [cCHFC]='0x873990849DDa5117d7C644f0aF24370797C03885' + [cCADC]='0x54dBd40cF05e15906A2C21f600937e96787f5679' + [cXAUC]='0x290E52a8819A4fbD0714E517225429aA2B70EC6b' + [cXAUT]='0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E' +) + +read -r FIAT_RAW XAU_RAW XAU_USDC_RAW <<<"$(FIAT_SEED_HUMAN="$FIAT_SEED_HUMAN" XAU_SEED_OZ="$XAU_SEED_OZ" XAU_SPOT_USD="$XAU_SPOT_USD" python3 <<'PY' +from decimal import Decimal, ROUND_DOWN +import os +fiat = Decimal(os.environ["FIAT_SEED_HUMAN"]) +xau_oz = Decimal(os.environ["XAU_SEED_OZ"]) +spot = Decimal(os.environ["XAU_SPOT_USD"]) +fiat_raw = int((fiat * Decimal(10**6)).to_integral_value(rounding=ROUND_DOWN)) +xau_raw = int((xau_oz * Decimal(10**6)).to_integral_value(rounding=ROUND_DOWN)) +xau_usdc_raw = int((xau_oz * spot * Decimal(10**6)).to_integral_value(rounding=ROUND_DOWN)) +print(fiat_raw, xau_raw, xau_usdc_raw) +PY +)" + +PAIRS=( + "cEURC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cEURT|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cGBPC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cGBPT|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cAUDC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cJPYC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cCHFC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cCADC|cUSDC|${FIAT_RAW}|${FIAT_RAW}" + "cXAUC|cUSDC|${XAU_RAW}|${XAU_USDC_RAW}" + "cXAUT|cUSDC|${XAU_RAW}|${XAU_USDC_RAW}" + "cEURC|cEURT|${FIAT_RAW}|${FIAT_RAW}" + "cGBPC|cGBPT|${FIAT_RAW}|${FIAT_RAW}" + "cXAUC|cXAUT|${XAU_RAW}|${XAU_RAW}" +) + +declare -A APPROVED=() + +approve_if_needed() { + local token="$1" + if [[ -n "${APPROVED[$token]:-}" ]]; then + return 0 + fi + cast send "$token" "approve(address,uint256)" "$DODO_PMM_INTEGRATION_ADDRESS" "$MAX_UINT" \ + --rpc-url "$RPC_URL_138" \ + --private-key "$PRIVATE_KEY" \ + --legacy \ + --gas-price "$CHAIN_GAS_PRICE" \ + --gas-limit "$APPROVE_GAS_LIMIT" >/dev/null + APPROVED["$token"]=1 +} + +pool_for() { + cast call "$DODO_PMM_INTEGRATION_ADDRESS" "pools(address,address)(address)" "$1" "$2" --rpc-url "$RPC_URL_138" | awk '{print $1}' +} + +balance_for() { + cast call "$1" "balanceOf(address)(uint256)" "$2" --rpc-url "$RPC_URL_138" | awk '{print $1}' +} + +echo "=== Seed Chain 138 canonical PMM pools ===" +echo "RPC: $RPC_URL_138" +echo "Deployer: $DEPLOYER" +echo "Fiat seed: ${FIAT_SEED_HUMAN} -> ${FIAT_RAW} raw" +echo "XAU seed: ${XAU_SEED_OZ} oz -> ${XAU_RAW} raw; quote USDC raw=${XAU_USDC_RAW}" +echo + +for row in "${PAIRS[@]}"; do + IFS='|' read -r base_sym quote_sym base_amount quote_amount <<<"$row" + base_token="${TOKENS[$base_sym]}" + quote_token="${TOKENS[$quote_sym]}" + pool="$(pool_for "$base_token" "$quote_token")" + label="${base_sym}/${quote_sym}" + if [[ -z "$pool" || "${pool,,}" == "${ZERO_ADDR,,}" ]]; then + echo "FAIL seed $label -> pool missing" + exit 1 + fi + + base_balance="$(balance_for "$base_token" "$DEPLOYER")" + quote_balance="$(balance_for "$quote_token" "$DEPLOYER")" + if (( base_balance < base_amount )); then + echo "FAIL seed $label -> insufficient $base_sym balance ($base_balance < $base_amount)" + exit 1 + fi + if (( quote_balance < quote_amount )); then + echo "FAIL seed $label -> insufficient $quote_sym balance ($quote_balance < $quote_amount)" + exit 1 + fi + + approve_if_needed "$base_token" + approve_if_needed "$quote_token" + + cast send "$DODO_PMM_INTEGRATION_ADDRESS" "addLiquidity(address,uint256,uint256)" "$pool" "$base_amount" "$quote_amount" \ + --rpc-url "$RPC_URL_138" \ + --private-key "$PRIVATE_KEY" \ + --legacy \ + --gas-price "$CHAIN_GAS_PRICE" \ + --gas-limit "$ADD_LIQUIDITY_GAS_LIMIT" >/dev/null + echo "OK seed $label -> $pool" +done + +echo +echo "Done." diff --git a/scripts/deployment/sync-chain138-pmm-pools-from-json.sh b/scripts/deployment/sync-chain138-pmm-pools-from-json.sh index b8e7842..dc74ac2 100755 --- a/scripts/deployment/sync-chain138-pmm-pools-from-json.sh +++ b/scripts/deployment/sync-chain138-pmm-pools-from-json.sh @@ -17,6 +17,8 @@ ORIG_CHAIN_GAS_PRICE="${CHAIN_GAS_PRICE-}" ORIG_TX_TIMEOUT_SECONDS="${TX_TIMEOUT_SECONDS-}" ORIG_POST_CREATE_POLL_SECONDS="${POST_CREATE_POLL_SECONDS-}" ORIG_POST_CREATE_POLL_INTERVAL="${POST_CREATE_POLL_INTERVAL-}" +ORIG_CREATE_POOL_GAS_LIMIT="${CREATE_POOL_GAS_LIMIT-}" +ORIG_REGISTER_POOL_GAS_LIMIT="${REGISTER_POOL_GAS_LIMIT-}" if [[ -f "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1091 @@ -47,6 +49,8 @@ fi [[ -n "$ORIG_TX_TIMEOUT_SECONDS" ]] && TX_TIMEOUT_SECONDS="$ORIG_TX_TIMEOUT_SECONDS" [[ -n "$ORIG_POST_CREATE_POLL_SECONDS" ]] && POST_CREATE_POLL_SECONDS="$ORIG_POST_CREATE_POLL_SECONDS" [[ -n "$ORIG_POST_CREATE_POLL_INTERVAL" ]] && POST_CREATE_POLL_INTERVAL="$ORIG_POST_CREATE_POLL_INTERVAL" +[[ -n "$ORIG_CREATE_POOL_GAS_LIMIT" ]] && CREATE_POOL_GAS_LIMIT="$ORIG_CREATE_POOL_GAS_LIMIT" +[[ -n "$ORIG_REGISTER_POOL_GAS_LIMIT" ]] && REGISTER_POOL_GAS_LIMIT="$ORIG_REGISTER_POOL_GAS_LIMIT" RPC_URL_138="${RPC_URL_138:-${RPC_URL:-http://192.168.11.211:8545}}" DODO_PMM_INTEGRATION_ADDRESS="${DODO_PMM_INTEGRATION_ADDRESS:-${DODO_PMM_INTEGRATION:-}}" @@ -63,6 +67,8 @@ CHAIN_GAS_PRICE="${CHAIN_GAS_PRICE:-1000000000}" TX_TIMEOUT_SECONDS="${TX_TIMEOUT_SECONDS:-120}" POST_CREATE_POLL_SECONDS="${POST_CREATE_POLL_SECONDS:-20}" POST_CREATE_POLL_INTERVAL="${POST_CREATE_POLL_INTERVAL:-1}" +CREATE_POOL_GAS_LIMIT="${CREATE_POOL_GAS_LIMIT:-900000}" +REGISTER_POOL_GAS_LIMIT="${REGISTER_POOL_GAS_LIMIT:-300000}" LP_FEE="${LP_FEE_RATE:-$(jq -r '.defaults.lpFeeRate' "$CONFIG_JSON")}" INITIAL_PRICE="${INITIAL_PRICE:-$(jq -r '.defaults.initialPrice' "$CONFIG_JSON")}" @@ -247,8 +253,8 @@ register_pair() { ((registered++)) || true return 0 fi - if send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$base" "$quote" "$pool" --gas-limit 200000 \ - && send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$quote" "$base" "$pool" --gas-limit 200000; then + if send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$base" "$quote" "$pool" --gas-limit "$REGISTER_POOL_GAS_LIMIT" \ + && send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$quote" "$base" "$pool" --gas-limit "$REGISTER_POOL_GAS_LIMIT"; then echo " OK register $label -> $pool" ((registered++)) || true return 0 @@ -275,7 +281,12 @@ for pair in "${DESIRED_PAIRS[@]}"; do if [[ -n "$existing_pool" && "$existing_pool" != "$zero_addr" ]]; then echo "SKIP create $label (exists: $existing_pool)" ((skipped_existing++)) || true - register_pair "$base" "$quote" "$existing_pool" "$label" + if [[ -n "$provider_pool" && "${provider_pool,,}" == "${existing_pool,,}" ]]; then + echo " OK provider already registered for $label -> $existing_pool" + ((registered++)) || true + else + register_pair "$base" "$quote" "$existing_pool" "$label" || true + fi continue fi @@ -293,7 +304,7 @@ for pair in "${DESIRED_PAIRS[@]}"; do fi if send_tx "$DODO_PMM_INTEGRATION_ADDRESS" "createPool(address,address,uint256,uint256,uint256,bool)" \ - "$base" "$quote" "$LP_FEE" "$INITIAL_PRICE" "$K_FACTOR" "$ENABLE_TWAP" --gas-limit 500000; then + "$base" "$quote" "$LP_FEE" "$INITIAL_PRICE" "$K_FACTOR" "$ENABLE_TWAP" --gas-limit "$CREATE_POOL_GAS_LIMIT"; then new_pool="$(wait_for_pool "$base" "$quote")" if [[ -z "$new_pool" || "$new_pool" == "$zero_addr" ]]; then echo "FAIL create $label (tx confirmed but integration still reports zero pool address)" @@ -302,7 +313,7 @@ for pair in "${DESIRED_PAIRS[@]}"; do fi echo "OK create $label -> $new_pool" ((created++)) || true - register_pair "$base" "$quote" "$new_pool" "$label" + register_pair "$base" "$quote" "$new_pool" "$label" || true else echo "FAIL create $label" ((failed++)) || true