Files
smom-dbis-138/scripts/deployment/fund-chain138-eth-pmm-pools.sh
defiQUG f3d2961b97
Some checks failed
CI/CD Pipeline / Lint and Format (push) Failing after 46s
CI/CD Pipeline / Terraform Validation (push) Failing after 35s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 37s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 1m50s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 2m19s
Validation / validate-genesis (push) Successful in 51s
Validation / validate-terraform (push) Failing after 39s
Validation / validate-kubernetes (push) Failing after 10s
CI/CD Pipeline / Solidity Contracts (push) Failing after 12m56s
Validation / validate-smart-contracts (push) Failing after 12s
CI/CD Pipeline / Security Scanning (push) Failing after 15m52s
Validation / validate-security (push) Failing after 10m59s
Validation / validate-documentation (push) Failing after 17s
Validate Token List / validate (push) Failing after 30s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 26s
Verify Deployment / Verify Deployment (push) Failing after 56s
feat: add hybx omnl stack and gas pmm tooling
2026-04-24 12:56:40 -07:00

298 lines
12 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$SMOM_ROOT"
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"
else
source "$SMOM_ROOT/scripts/load-env.sh" >/dev/null 2>&1 || true
fi
PLAN_JSON="${PLAN_JSON:-$SMOM_ROOT/config/chain138-eth-pmm-liquidity-plan.json}"
PROFILE="${PROFILE:-}"
EXECUTE="${EXECUTE:-0}"
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:-}}"
PRIVATE_KEY="${PRIVATE_KEY:-}"
command -v jq >/dev/null 2>&1 || { echo "jq is required" >&2; exit 1; }
command -v cast >/dev/null 2>&1 || { echo "cast is required" >&2; exit 1; }
[[ -f "$PLAN_JSON" ]] || { echo "PLAN_JSON not found: $PLAN_JSON" >&2; exit 1; }
[[ -n "$DODO_PMM_INTEGRATION_ADDRESS" ]] || { echo "DODO_PMM_INTEGRATION_ADDRESS not set" >&2; exit 1; }
require_private_key_env || exit 1
EXECUTION_CONFIG="$(jq -r '.executionConfig' "$PLAN_JSON")"
if [[ "$EXECUTION_CONFIG" != /* ]]; then
EXECUTION_CONFIG="$SMOM_ROOT/${EXECUTION_CONFIG#smom-dbis-138/}"
fi
[[ -f "$EXECUTION_CONFIG" ]] || { echo "Execution config not found: $EXECUTION_CONFIG" >&2; exit 1; }
if [[ -z "$PROFILE" ]]; then
PROFILE="$(jq -r '.defaultProfile' "$PLAN_JSON")"
fi
FIAT_BASE_UNITS="$(jq -r --arg p "$PROFILE" '.profiles[$p].fiatBaseUnits' "$PLAN_JSON")"
XAU_BASE_UNITS="$(jq -r --arg p "$PROFILE" '.profiles[$p].xauBaseUnits' "$PLAN_JSON")"
[[ "$FIAT_BASE_UNITS" != "null" ]] || { echo "Unknown PROFILE: $PROFILE" >&2; exit 1; }
[[ "$XAU_BASE_UNITS" != "null" ]] || { echo "Unknown PROFILE: $PROFILE" >&2; exit 1; }
APPROVE_GAS_LIMIT="$(jq -r '.execution.approveGasLimit' "$PLAN_JSON")"
MINT_GAS_LIMIT="$(jq -r '.execution.mintGasLimit' "$PLAN_JSON")"
WRAP_GAS_LIMIT="$(jq -r '.execution.wrapGasLimit' "$PLAN_JSON")"
ADD_LIQUIDITY_GAS_LIMIT="$(jq -r '.execution.addLiquidityGasLimit' "$PLAN_JSON")"
GAS_PRICE_WEI="${CHAIN_GAS_PRICE:-$(jq -r '.execution.legacyGasPriceWei' "$PLAN_JSON")}"
WRAP_WHEN_NEEDED="$(jq -r '.execution.wrapNativeEthWhenNeeded' "$PLAN_JSON")"
MINT_WHEN_OWNER="$(jq -r '.execution.mintMissingBaseWhenOwner' "$PLAN_JSON")"
APPROVE_MAX="$(jq -r '.execution.approveMax' "$PLAN_JSON")"
DEPLOYER="$(derive_deployer_address || true)"
[[ -n "$DEPLOYER" ]] || { echo "ERROR: Could not derive DEPLOYER_ADDRESS from PRIVATE_KEY." >&2; exit 1; }
WETH_ADDRESS="$(jq -r '.tokens.WETH' "$EXECUTION_CONFIG")"
MAX_UINT="0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
ZERO_ADDR="0x0000000000000000000000000000000000000000"
log() {
printf '%s\n' "$*"
}
get_pool_reserves() {
local pool="$1"
local lines
mapfile -t lines < <(cast call "$pool" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_URL_138")
printf '%s\t%s\n' "$(uint_clean "${lines[0]:-0}")" "$(uint_clean "${lines[1]:-0}")"
}
uint_clean() {
printf '%s\n' "$1" | awk '{print $1}'
}
hex_to_addr() {
local raw="${1#0x}"
if [[ ${#raw} -lt 40 ]]; then
printf '%s\n' "$ZERO_ADDR"
return 0
fi
printf '0x%s\n' "${raw: -40}"
}
send_tx() {
local to="$1"
shift
cast send "$to" "$@" \
--rpc-url "$RPC_URL_138" \
--private-key "$PRIVATE_KEY" \
--legacy \
--gas-price "$GAS_PRICE_WEI" \
-q
}
big_add() {
python3 - "$1" "$2" <<'PY'
import sys
print(int(sys.argv[1]) + int(sys.argv[2]))
PY
}
big_sub_if_positive() {
python3 - "$1" "$2" <<'PY'
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a - b if a > b else 0)
PY
}
big_lt() {
python3 - "$1" "$2" <<'PY'
import sys
print("1" if int(sys.argv[1]) < int(sys.argv[2]) else "0")
PY
}
raw_to_human_6() {
awk -v v="$1" 'BEGIN { printf "%.6f", v / 1000000 }'
}
raw_to_human_18() {
awk -v v="$1" 'BEGIN { printf "%.18f", v / 1000000000000000000 }'
}
mul_div_round() {
awk -v a="$1" -v b="$2" -v c="$3" 'BEGIN { printf "%.0f", (a * b) / c }'
}
derive_usd_per_eth() {
local pool base_reserve quote_reserve
local cusdt quote
cusdt="$(jq -r '.tokens.cUSDT' "$EXECUTION_CONFIG")"
quote="$WETH_ADDRESS"
pool="$(hex_to_addr "$(cast call "$DODO_PMM_INTEGRATION_ADDRESS" 'pools(address,address)(address)' "$cusdt" "$quote" --rpc-url "$RPC_URL_138")")"
[[ "$pool" != "$ZERO_ADDR" ]] || { echo "0"; return 1; }
read -r base_reserve quote_reserve < <(get_pool_reserves "$pool")
awk -v base="$base_reserve" -v quote="$quote_reserve" 'BEGIN { printf "%.12f", (base / 1000000) / (quote / 1000000000000000000) }'
}
derive_xau_usd_per_unit() {
local pool base_symbol quote_symbol base_addr quote_addr base_reserve quote_reserve fallback
base_symbol="$(jq -r '.xauPricing.poolBaseSymbol' "$PLAN_JSON")"
quote_symbol="$(jq -r '.xauPricing.poolQuoteSymbol' "$PLAN_JSON")"
fallback="$(jq -r '.xauPricing.fallbackUsdPerUnit' "$PLAN_JSON")"
base_addr="$(jq -r --arg sym "$base_symbol" '.tokens[$sym]' "$EXECUTION_CONFIG")"
quote_addr="$(jq -r --arg sym "$quote_symbol" '.tokens[$sym]' "$EXECUTION_CONFIG")"
pool="$(hex_to_addr "$(cast call "$DODO_PMM_INTEGRATION_ADDRESS" 'pools(address,address)(address)' "$base_addr" "$quote_addr" --rpc-url "$RPC_URL_138")")"
if [[ "$pool" == "$ZERO_ADDR" ]]; then
echo "$fallback"
return 0
fi
read -r base_reserve quote_reserve < <(get_pool_reserves "$pool")
if [[ "$base_reserve" == "0" || "$quote_reserve" == "0" ]]; then
echo "$fallback"
return 0
fi
awk -v base="$base_reserve" -v quote="$quote_reserve" 'BEGIN { printf "%.12f", (quote / 1000000) / (base / 1000000) }'
}
usd_per_eth="$(derive_usd_per_eth)"
[[ "$usd_per_eth" != "0" ]] || { echo "Could not derive USD per ETH from live cUSDT/WETH pool" >&2; exit 1; }
xau_usd_per_unit="$(derive_xau_usd_per_unit)"
log "=== Chain 138 ETH PMM Liquidity Funding ==="
log "Mode: $( [[ "$EXECUTE" == "1" ]] && echo EXECUTE || echo DRY_RUN )"
log "Profile: $PROFILE"
log "Plan: $PLAN_JSON"
log "Config: $EXECUTION_CONFIG"
log "Integration: $DODO_PMM_INTEGRATION_ADDRESS"
log "RPC: $RPC_URL_138"
log "Deployer: $DEPLOYER"
log "USD per ETH: $usd_per_eth"
log "XAU USD: $xau_usd_per_unit"
log ""
total_quote_units=0
wrap_needed=0
declare -a ROWS=()
while IFS=$'\t' read -r base_symbol base_address; do
pool="$(hex_to_addr "$(cast call "$DODO_PMM_INTEGRATION_ADDRESS" 'pools(address,address)(address)' "$base_address" "$WETH_ADDRESS" --rpc-url "$RPC_URL_138")")"
[[ "$pool" != "$ZERO_ADDR" ]] || continue
case "$base_symbol" in
cXAUC|cXAUT)
base_units="$XAU_BASE_UNITS"
usd_per_unit="$xau_usd_per_unit"
;;
*)
base_units="$FIAT_BASE_UNITS"
usd_per_unit="$(jq -r --arg sym "$base_symbol" '.usdPerUnit[$sym]' "$PLAN_JSON")"
[[ "$usd_per_unit" != "null" ]] || { echo "Missing usdPerUnit for $base_symbol" >&2; exit 1; }
;;
esac
quote_units="$(awk -v base="$base_units" -v usd="$usd_per_unit" -v usd_eth="$usd_per_eth" 'BEGIN { printf "%.0f", ((base / 1000000) * usd / usd_eth) * 1000000000000000000 }')"
read -r current_base_reserve current_quote_reserve < <(get_pool_reserves "$pool")
base_delta="$(big_sub_if_positive "$base_units" "$current_base_reserve")"
quote_delta="$(big_sub_if_positive "$quote_units" "$current_quote_reserve")"
base_balance="$(cast call "$base_address" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL_138" 2>/dev/null || echo 0)"
base_balance="$(uint_clean "$base_balance")"
owner_addr="$(cast call "$base_address" 'owner()(address)' --rpc-url "$RPC_URL_138" 2>/dev/null || echo "$ZERO_ADDR")"
ROWS+=("$base_symbol|$base_address|$pool|$base_units|$quote_units|$current_base_reserve|$current_quote_reserve|$base_delta|$quote_delta|$base_balance|$owner_addr")
total_quote_units="$(big_add "$total_quote_units" "$quote_delta")"
done < <(jq -r '.explicitPairs[] | [.baseSymbol, (.baseSymbol as $s | .baseSymbol)] | @tsv' "$EXECUTION_CONFIG" | while IFS=$'\t' read -r base_symbol _; do
base_address="$(jq -r --arg sym "$base_symbol" '.tokens[$sym]' "$EXECUTION_CONFIG")"
printf '%s\t%s\n' "$base_symbol" "$base_address"
done)
weth_balance="$(cast call "$WETH_ADDRESS" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$RPC_URL_138" 2>/dev/null || echo 0)"
weth_balance="$(uint_clean "$weth_balance")"
eth_balance="$(cast balance "$DEPLOYER" --rpc-url "$RPC_URL_138" 2>/dev/null || echo 0)"
if [[ "$(big_lt "$weth_balance" "$total_quote_units")" == "1" ]]; then
wrap_needed="$(big_sub_if_positive "$total_quote_units" "$weth_balance")"
fi
log "Current ETH: $(raw_to_human_18 "$eth_balance")"
log "Current WETH: $(raw_to_human_18 "$weth_balance")"
log "Total WETH needed for profile: $(raw_to_human_18 "$total_quote_units")"
log "Additional WETH to wrap: $(raw_to_human_18 "$wrap_needed")"
log ""
for row in "${ROWS[@]}"; do
IFS='|' read -r base_symbol base_address pool base_units quote_units current_base_reserve current_quote_reserve base_delta quote_delta base_balance owner_addr <<< "$row"
need_mint=0
if [[ "$(big_lt "$base_balance" "$base_delta")" == "1" ]]; then
need_mint="$(big_sub_if_positive "$base_delta" "$base_balance")"
fi
log "$base_symbol pool=$pool"
log " target base: $(raw_to_human_6 "$base_units")"
log " target quote: $(raw_to_human_18 "$quote_units") WETH"
log " current base: $(raw_to_human_6 "$current_base_reserve")"
log " current quote: $(raw_to_human_18 "$current_quote_reserve") WETH"
log " top-up base: $(raw_to_human_6 "$base_delta")"
log " top-up quote: $(raw_to_human_18 "$quote_delta") WETH"
log " base balance: $(raw_to_human_6 "$base_balance")"
if [[ "$need_mint" != "0" ]]; then
log " mint needed: $(raw_to_human_6 "$need_mint")"
else
log " mint needed: no"
fi
done
if [[ "$EXECUTE" != "1" ]]; then
log ""
log "Dry run only. Re-run with EXECUTE=1 to mint/wrap/approve/add liquidity."
exit 0
fi
if [[ "$wrap_needed" != "0" ]]; then
if [[ "$WRAP_WHEN_NEEDED" != "true" ]]; then
echo "Need additional WETH but wrapNativeEthWhenNeeded=false" >&2
exit 1
fi
if [[ "$(big_lt "$eth_balance" "$wrap_needed")" == "1" ]]; then
echo "Insufficient ETH to wrap required WETH" >&2
exit 1
fi
log "Wrapping $(raw_to_human_18 "$wrap_needed") ETH into WETH"
send_tx "$WETH_ADDRESS" 'deposit()' --value "$wrap_needed" --gas-limit "$WRAP_GAS_LIMIT" >/dev/null
fi
for row in "${ROWS[@]}"; do
IFS='|' read -r base_symbol base_address pool base_units quote_units current_base_reserve current_quote_reserve base_delta quote_delta base_balance owner_addr <<< "$row"
if [[ "$base_delta" == "0" && "$quote_delta" == "0" ]]; then
log "Skipping $base_symbol/WETH; already at or above target."
continue
fi
if [[ "$(big_lt "$base_balance" "$base_delta")" == "1" ]]; then
mint_amount="$(big_sub_if_positive "$base_delta" "$base_balance")"
if [[ "$MINT_WHEN_OWNER" != "true" ]]; then
echo "Need to mint $base_symbol but mintMissingBaseWhenOwner=false" >&2
exit 1
fi
if [[ "${owner_addr,,}" != "${DEPLOYER,,}" ]]; then
echo "Cannot mint $base_symbol; deployer is not owner ($owner_addr)" >&2
exit 1
fi
log "Minting $(raw_to_human_6 "$mint_amount") $base_symbol"
send_tx "$base_address" 'mint(address,uint256)' "$DEPLOYER" "$mint_amount" --gas-limit "$MINT_GAS_LIMIT" >/dev/null
fi
if [[ "$APPROVE_MAX" == "true" ]]; then
log "Approving $base_symbol to integration"
send_tx "$base_address" 'approve(address,uint256)' "$DODO_PMM_INTEGRATION_ADDRESS" "$MAX_UINT" --gas-limit "$APPROVE_GAS_LIMIT" >/dev/null
log "Approving WETH for $base_symbol pair"
send_tx "$WETH_ADDRESS" 'approve(address,uint256)' "$DODO_PMM_INTEGRATION_ADDRESS" "$MAX_UINT" --gas-limit "$APPROVE_GAS_LIMIT" >/dev/null
fi
log "Adding liquidity to $base_symbol/WETH at $pool"
send_tx "$DODO_PMM_INTEGRATION_ADDRESS" 'addLiquidity(address,uint256,uint256)' "$pool" "$base_delta" "$quote_delta" --gas-limit "$ADD_LIQUIDITY_GAS_LIMIT" >/dev/null
done
log ""
log "Liquidity funding complete."