Files
proxmox/scripts/lib/pmm-soak-chain138-tick.sh
defiQUG 6fb6bd3993 fix(pmm-soak): shellcheck-clean bots/tick/bootstrap; expand CI ShellCheck
- bootstrap: split mnemonic export (SC2155), PMM_SOAK_RPC_URL_OVERRIDE, noprofile fund-grid, ASCII echoes, help header only
- chain138-tick: document POOLS global for SC2153
- random/grid bots: log line references INTEGRATION, USD bounds, gold, gas, log_tag (SC2034)
- validate-config: ShellCheck all 11 PMM soak + chain138-pmm shell scripts incl. smoke + bootstrap

Made-with: Cursor
2026-04-12 03:43:35 -07:00

209 lines
8.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Chain 138 PMM soak — one tick (quote + optional approve/swap). Source after setting:
# POOLS (array), RPC, INTEGRATION, SLIP_BPS, GAS_WEI, GOLD_USD, USD_MIN, USD_MAX
# Optional: PMM_SOAK_LOG_TAG (default pmm-soak)
#
# Optional: CHAIN138_PMM_SOAK_GAS_LIMIT — when set, passed as --gas-limit to approve/swap cast send (helps Besu estimation).
# Optional: CHAIN138_PMM_SOAK_SWAP_VIA — pool (default) | integration
# On Chain 138, DODOPMMIntegration.swapExactIn reverts inside the pool when msg.sender is the integration contract;
# EOA transfer(token, pool, amt) + pool.sellBase/sellQuote(trader) succeeds. Default pool path matches that.
# Requires: cast, bc, python3 (pick_random_amount)
# shellcheck shell=bash
PMM_SOAK_CXAUC_LC="${PMM_SOAK_CXAUC_LC:-0x290e52a8819a4fbd0714e517225429aa2b70ec6b}"
PMM_SOAK_CXAUT_LC="${PMM_SOAK_CXAUT_LC:-0x94e408e26c6fd8f4ee00b54df19082fda07dc96e}"
pmm_soak_to_lower() {
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
}
pmm_soak_log() {
echo "[${PMM_SOAK_LOG_TAG:-pmm-soak} $(date -Iseconds)] $*"
}
pmm_soak_pick_random_amount() {
local token_lc="$1"
local decimals="$2"
PMM_SOAK_XAU_ADDRS="${PMM_SOAK_CXAUC_LC},${PMM_SOAK_CXAUT_LC}" \
GOLD_USD="$GOLD_USD" USD_MIN="$USD_MIN" USD_MAX="$USD_MAX" \
python3 - "$token_lc" "$decimals" <<'PY'
import os, random, sys
tok = sys.argv[1].lower()
d = int(sys.argv[2])
usd_min = int(os.environ["USD_MIN"])
usd_max = int(os.environ["USD_MAX"])
gold = float(os.environ["GOLD_USD"])
scale = 10 ** d
xau = {a.strip().lower() for a in os.environ["PMM_SOAK_XAU_ADDRS"].split(",") if a.strip()}
if tok in xau:
usd = random.randint(usd_min, usd_max)
oz = usd / gold
raw = int(oz * scale)
print(max(raw, 1))
else:
u = random.randint(usd_min, usd_max)
print(u * scale)
PY
}
# One loop iteration: random pool, quote as trader, swap with signer_pk when apply=1.
# Globals: POOLS RPC INTEGRATION SLIP_BPS GAS_WEI
pmm_soak_chain138_run_tick_iteration() {
local tick="$1"
local trader="$2"
local signer_pk="$3"
local apply="$4"
# POOLS[] is set by the caller (pmm-soak-pools.sh); not the local POOL below.
# shellcheck disable=SC2153
local idx=$((RANDOM % ${#POOLS[@]}))
local POOL base_out quote_out base quote base_lc quote_lc token_in token_in_lc token_out
local dec_out dec bal_out bal amt qraw quoted min_out
local swap_via="${CHAIN138_PMM_SOAK_SWAP_VIA:-pool}"
POOL="${POOLS[$idx]}"
if ! base_out="$(cast call "$POOL" '_BASE_TOKEN_()(address)' --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL (base token read failed)"
return 0
fi
if ! quote_out="$(cast call "$POOL" '_QUOTE_TOKEN_()(address)' --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL (quote token read failed)"
return 0
fi
base="$(printf '%s\n' "$base_out" | awk '{print $1}')"
quote="$(printf '%s\n' "$quote_out" | awk '{print $1}')"
base_lc="$(pmm_soak_to_lower "$base")"
quote_lc="$(pmm_soak_to_lower "$quote")"
if (( RANDOM % 2 == 0 )); then
token_in="$base"
token_in_lc="$base_lc"
token_out="$quote"
else
token_in="$quote"
token_in_lc="$quote_lc"
token_out="$base"
fi
if ! dec_out="$(cast call "$token_in" 'decimals()(uint8)' --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL (decimals failed)"
return 0
fi
dec="$(printf '%s\n' "$dec_out" | awk '{print $1}')"
if ! bal_out="$(cast call "$token_in" 'balanceOf(address)(uint256)' "$trader" --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL (balance read failed)"
return 0
fi
bal="$(printf '%s\n' "$bal_out" | awk '{print $1}')"
amt="$(pmm_soak_pick_random_amount "$token_in_lc" "$dec")"
if [[ -z "$amt" || "$amt" == "0" ]]; then
pmm_soak_log "tick $tick skip pool=$POOL (zero amount)"
return 0
fi
if (( $(echo "$bal < $amt" | bc -l) )); then
if (( $(echo "$bal == 0" | bc -l) )); then
pmm_soak_log "tick $tick skip pool=$POOL token_in=$token_in zero balance"
return 0
fi
amt=$((bal * 9 / 10))
pmm_soak_log "tick $tick clamp amount to 90% balance -> $amt"
fi
if [[ "$token_in_lc" == "$base_lc" ]]; then
if ! qraw="$(cast call "$POOL" 'querySellBase(address,uint256)(uint256,uint256)' "$trader" "$amt" --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL querySellBase reverted amt=$amt"
return 0
fi
else
if ! qraw="$(cast call "$POOL" 'querySellQuote(address,uint256)(uint256,uint256)' "$trader" "$amt" --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "tick $tick skip pool=$POOL querySellQuote reverted amt=$amt"
return 0
fi
fi
quoted="$(printf '%s\n' "$qraw" | head -1 | awk '{print $1}')"
if [[ -z "$quoted" || "$quoted" == "0" ]]; then
pmm_soak_log "tick $tick skip pool=$POOL token_in=$token_in amt=$amt (no quote)"
return 0
fi
min_out="$(echo "scale=0; (${quoted} * (10000 - ${SLIP_BPS})) / 10000" | bc)"
pmm_soak_log "tick $tick trader=$trader pool=$POOL token_in=$token_in amt=$amt quoted_out=$quoted min_out=$min_out"
if [[ "$apply" -eq 1 ]]; then
if [[ -z "$signer_pk" ]]; then
pmm_soak_log "WARN: apply=1 but empty signer_pk; skip swap"
return 0
fi
local _gas_t _gas_s _out_bal_before _out_bal_after _received
_gas_t=()
_gas_s=()
[[ -n "${CHAIN138_PMM_SOAK_GAS_LIMIT:-}" ]] && _gas_t=(--gas-limit "${CHAIN138_PMM_SOAK_GAS_LIMIT}")
[[ -n "${CHAIN138_PMM_SOAK_GAS_LIMIT:-}" ]] && _gas_s=(--gas-limit "${CHAIN138_PMM_SOAK_GAS_LIMIT}")
if [[ "$swap_via" == "integration" ]]; then
local allowance al_out can_swap
if ! al_out="$(cast call "$token_in" 'allowance(address,address)(uint256)' "$trader" "$INTEGRATION" --rpc-url "$RPC" 2>/dev/null)"; then
pmm_soak_log "WARN: allowance read failed; skip swap"
else
allowance="$(printf '%s\n' "$al_out" | awk '{print $1}')"
can_swap=1
if (( $(echo "$allowance < $amt" | bc -l) )); then
pmm_soak_log "approve $token_in -> integration amount=$amt"
if ! cast send "$token_in" 'approve(address,uint256)(bool)' "$INTEGRATION" "$amt" \
--rpc-url "$RPC" --private-key "$signer_pk" --legacy --gas-price "$GAS_WEI" "${_gas_t[@]}" >/dev/null; then
pmm_soak_log "WARN: approve failed; skip swap"
can_swap=0
fi
fi
if [[ "$can_swap" -eq 1 ]]; then
if ! cast send "$INTEGRATION" \
'swapExactIn(address,address,uint256,uint256)(uint256)' \
"$POOL" "$token_in" "$amt" "$min_out" \
--rpc-url "$RPC" --private-key "$signer_pk" --legacy --gas-price "$GAS_WEI" "${_gas_s[@]}"; then
pmm_soak_log "WARN: swap failed pool=$POOL (continuing)"
fi
fi
fi
else
# Direct pool: transfer in then sellBase / sellQuote (EOA msg.sender; avoids integration+pool revert on this chain).
if ! _out_bal_before="$(cast call "$token_out" 'balanceOf(address)(uint256)' "$trader" --rpc-url "$RPC" 2>/dev/null | awk '{print $1}')"; then
pmm_soak_log "WARN: token_out balance read failed; skip swap"
else
pmm_soak_log "swap_via=pool transfer token_in -> pool amt=$amt"
if ! cast send "$token_in" 'transfer(address,uint256)(bool)' "$POOL" "$amt" \
--rpc-url "$RPC" --private-key "$signer_pk" --legacy --gas-price "$GAS_WEI" "${_gas_t[@]}" >/dev/null; then
pmm_soak_log "WARN: transfer to pool failed pool=$POOL (continuing)"
else
if [[ "$token_in_lc" == "$base_lc" ]]; then
if ! cast send "$POOL" 'sellBase(address)(uint256)' "$trader" \
--rpc-url "$RPC" --private-key "$signer_pk" --legacy --gas-price "$GAS_WEI" "${_gas_s[@]}" >/dev/null; then
pmm_soak_log "WARN: sellBase failed pool=$POOL (continuing)"
fi
else
if ! cast send "$POOL" 'sellQuote(address)(uint256)' "$trader" \
--rpc-url "$RPC" --private-key "$signer_pk" --legacy --gas-price "$GAS_WEI" "${_gas_s[@]}" >/dev/null; then
pmm_soak_log "WARN: sellQuote failed pool=$POOL (continuing)"
fi
fi
if ! _out_bal_after="$(cast call "$token_out" 'balanceOf(address)(uint256)' "$trader" --rpc-url "$RPC" 2>/dev/null | awk '{print $1}')"; then
pmm_soak_log "WARN: token_out balance re-read failed after swap"
else
_received="$(echo "${_out_bal_after} - ${_out_bal_before}" | bc)"
if (( $(echo "${_received} < ${min_out}" | bc -l) )); then
pmm_soak_log "WARN: output ${_received} < min_out ${min_out} (slippage / partial fill)"
else
pmm_soak_log "swap_via=pool ok received_out=${_received}"
fi
fi
fi
fi
fi
fi
return 0
}