- 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
263 lines
7.2 KiB
Bash
Executable File
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."
|