Files
proxmox/scripts/deployment/cancel-chain138-eoa-nonce-range.sh
defiQUG dbd517b279 Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains
- Omit embedded publish git dirs and empty placeholders from index

Made-with: Cursor
2026-04-12 06:12:20 -07:00

263 lines
7.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Cancel a queued nonce range for a Chain 138 EOA by sending 0-value self-transfers
# at each nonce with a bumped gas price. Default mode is dry-run.
#
# Example:
# PRIVATE_KEY=0xabc... bash scripts/deployment/cancel-chain138-eoa-nonce-range.sh \
# --rpc http://192.168.11.217:8545 \
# --from-nonce 1
#
# PRIVATE_KEY=0xabc... bash scripts/deployment/cancel-chain138-eoa-nonce-range.sh \
# --rpc http://192.168.11.217:8545 \
# --from-nonce 1 \
# --to-nonce 8 \
# --apply
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
if [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]]; then
# shellcheck source=/dev/null
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
fi
RPC_URL="${RPC_URL_138:-http://192.168.11.211:8545}"
PRIVATE_KEY_INPUT="${PRIVATE_KEY:-${DEPLOYER_PRIVATE_KEY:-}}"
FROM_NONCE=""
TO_NONCE=""
APPLY=0
GAS_LIMIT=21000
GAS_BUMP_MULTIPLIER=2
MIN_GAS_WEI=2000
usage() {
cat <<'EOF'
Usage: cancel-chain138-eoa-nonce-range.sh [options]
Options:
--private-key <hex> Private key for the EOA owner.
--rpc <url> Chain 138 RPC URL. Default: RPC_URL_138 or http://192.168.11.211:8545
--from-nonce <n> First nonce to cancel. Required.
--to-nonce <n> Last nonce to cancel. Optional; defaults to highest pending owner nonce seen on the RPC.
--apply Actually send cancel/self-transfer txs.
--min-gas-wei <n> Floor gas price in wei. Default: 2000
--gas-multiplier <n> Multiply current eth_gasPrice by this factor. Default: 2
--help Show this help.
Behavior:
1. Derives the owner address from the provided private key.
2. Reads latest nonce and owner pending txs from txpool_besuPendingTransactions.
3. Plans a cancel range from --from-nonce to --to-nonce.
4. In --apply mode, sends 0-value self-transfers at each nonce in that range.
Notes:
- Dry-run is the default and is recommended first.
- Use this when the owner wants to invalidate old deployment attempts instead of completing them.
- Requires: cast, curl, jq
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--private-key)
PRIVATE_KEY_INPUT="${2:-}"
shift 2
;;
--rpc)
RPC_URL="${2:-}"
shift 2
;;
--from-nonce)
FROM_NONCE="${2:-}"
shift 2
;;
--to-nonce)
TO_NONCE="${2:-}"
shift 2
;;
--apply)
APPLY=1
shift
;;
--min-gas-wei)
MIN_GAS_WEI="${2:-}"
shift 2
;;
--gas-multiplier)
GAS_BUMP_MULTIPLIER="${2:-}"
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage
exit 1
;;
esac
done
for cmd in cast curl jq; do
command -v "$cmd" >/dev/null 2>&1 || {
echo "Missing required command: $cmd" >&2
exit 1
}
done
if [[ -z "$PRIVATE_KEY_INPUT" ]]; then
echo "Missing private key. Pass --private-key or set PRIVATE_KEY." >&2
exit 1
fi
if [[ -z "$FROM_NONCE" ]]; then
echo "Missing required --from-nonce." >&2
exit 1
fi
case "$FROM_NONCE" in
''|*[!0-9]*)
echo "--from-nonce must be a non-negative integer." >&2
exit 1
;;
esac
if [[ -n "$TO_NONCE" ]]; then
case "$TO_NONCE" in
''|*[!0-9]*)
echo "--to-nonce must be a non-negative integer." >&2
exit 1
;;
esac
fi
OWNER_ADDRESS="$(cast wallet address --private-key "$PRIVATE_KEY_INPUT" 2>/dev/null || true)"
if [[ -z "$OWNER_ADDRESS" ]]; then
echo "Could not derive owner address from private key." >&2
exit 1
fi
OWNER_ADDRESS_LC="$(printf '%s' "$OWNER_ADDRESS" | tr '[:upper:]' '[:lower:]')"
rpc_call() {
local method="$1"
local params_json="$2"
curl -fsS "$RPC_URL" \
-H 'content-type: application/json' \
--data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"${method}\",\"params\":${params_json}}"
}
hex_to_dec() {
cast --to-dec "$1"
}
latest_hex="$(rpc_call eth_getTransactionCount "[\"${OWNER_ADDRESS}\",\"latest\"]" | jq -r '.result // "0x0"')"
pending_hex="$(rpc_call eth_getTransactionCount "[\"${OWNER_ADDRESS}\",\"pending\"]" | jq -r '.result // "0x0"')"
gas_hex="$(rpc_call eth_gasPrice "[]" | jq -r '.result // "0x0"')"
latest_nonce="$(hex_to_dec "$latest_hex")"
pending_nonce="$(hex_to_dec "$pending_hex")"
network_gas_wei="$(hex_to_dec "$gas_hex")"
pending_json="$(rpc_call txpool_besuPendingTransactions "[]")"
owner_pending_json="$(
printf '%s' "$pending_json" | jq --arg owner "$OWNER_ADDRESS_LC" '
[
.result[]?
| select(((.from // .sender // "") | ascii_downcase) == $owner)
| {
hash,
nonce_hex: .nonce,
to,
gas,
gasPrice,
maxFeePerGas,
maxPriorityFeePerGas,
type
}
]
'
)"
owner_pending_count="$(printf '%s' "$owner_pending_json" | jq 'length')"
highest_pending_nonce="$latest_nonce"
if [[ "$owner_pending_count" -gt 0 ]]; then
highest_pending_nonce="$(
printf '%s' "$owner_pending_json" \
| jq -r '.[].nonce_hex' \
| while read -r nonce_hex; do cast --to-dec "$nonce_hex"; done \
| sort -n \
| tail -n1
)"
fi
if [[ -z "$TO_NONCE" ]]; then
TO_NONCE="$highest_pending_nonce"
fi
if (( TO_NONCE < FROM_NONCE )); then
echo "--to-nonce must be greater than or equal to --from-nonce." >&2
exit 1
fi
effective_gas_wei="$(( network_gas_wei * GAS_BUMP_MULTIPLIER ))"
if (( effective_gas_wei < MIN_GAS_WEI )); then
effective_gas_wei="$MIN_GAS_WEI"
fi
echo "=== Chain 138 EOA nonce-range cancel ==="
echo "Owner address: $OWNER_ADDRESS"
echo "RPC URL: $RPC_URL"
echo "Latest nonce: $latest_nonce"
echo "Pending nonce view: $pending_nonce"
echo "Pending tx count: $owner_pending_count"
echo "Highest pending nonce:${highest_pending_nonce}"
echo "Cancel from nonce: $FROM_NONCE"
echo "Cancel to nonce: $TO_NONCE"
echo "Network gas price: $network_gas_wei wei"
echo "Planned gas price: $effective_gas_wei wei"
echo ""
if [[ "$owner_pending_count" -gt 0 ]]; then
echo "--- Pending txs for owner in txpool_besuPendingTransactions ---"
printf '%s\n' "$owner_pending_json" | jq '.'
echo ""
else
echo "No owner txs found in txpool_besuPendingTransactions."
echo ""
fi
echo "--- Planned cancel range ---"
for ((nonce = FROM_NONCE; nonce <= TO_NONCE; nonce++)); do
echo "nonce $nonce -> self-transfer cancel"
done
echo ""
if [[ "$APPLY" -ne 1 ]]; then
echo "Dry-run only. Re-run with --apply to submit cancels for the full nonce range above."
exit 0
fi
echo "--- Applying cancels ---"
for ((nonce = FROM_NONCE; nonce <= TO_NONCE; nonce++)); do
echo "Sending cancel tx for nonce $nonce ..."
cast send "$OWNER_ADDRESS" \
--private-key "$PRIVATE_KEY_INPUT" \
--rpc-url "$RPC_URL" \
--nonce "$nonce" \
--value 0 \
--gas-limit "$GAS_LIMIT" \
--gas-price "$effective_gas_wei" \
>/tmp/cancel-chain138-eoa-nonce-range.out 2>/tmp/cancel-chain138-eoa-nonce-range.err || {
echo "Failed to send cancel for nonce $nonce" >&2
cat /tmp/cancel-chain138-eoa-nonce-range.err >&2 || true
exit 1
}
cat /tmp/cancel-chain138-eoa-nonce-range.out
done
echo ""
echo "Submitted cancel transactions. Wait for inclusion, then rerun in dry-run mode to verify the queue is gone."