- 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
164 lines
5.7 KiB
Bash
Executable File
164 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Read-only: scan deployed bytecode (Chain 138) for common flash / callback entrypoints.
|
|
# Address source: config/smart-contracts-master.json (chains.138.contracts) plus optional extras.
|
|
#
|
|
# Usage:
|
|
# RPC_URL_138=https://rpc-core.d-bis.org bash scripts/verify/sweep-flash-selectors-chain138.sh
|
|
# OUT_JSON=path/to/flash_candidates.json RPC_URL_138=... bash scripts/verify/sweep-flash-selectors-chain138.sh
|
|
#
|
|
# Requires: cast, jq. Does not use cast selectors --resolve (no OpenChain); matches 4-byte selectors only.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
JSON="${ROOT}/config/smart-contracts-master.json"
|
|
RPC="${RPC_URL_138:-https://rpc-core.d-bis.org}"
|
|
OUT_JSON="${OUT_JSON:-${ROOT}/config/flash_candidates-chain138.json}"
|
|
CHAIN_KEY="${CHAIN_KEY:-138}"
|
|
|
|
if ! command -v cast >/dev/null || ! command -v jq >/dev/null; then
|
|
echo "ERROR: need cast and jq on PATH" >&2
|
|
exit 1
|
|
fi
|
|
if [[ ! -f "$JSON" ]]; then
|
|
echo "ERROR: missing $JSON" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Workspace-canonical PMM addresses (may differ from smart-contracts-master.json); always merged for sweep.
|
|
EXTRA_ADDRS=(
|
|
"0x5BDc62f1ae7D630c37A8B363a1d49845356Ee72d"
|
|
"0xff8d3b8fDF7B112759F076B69f4271D4209C0849"
|
|
"0x6fc60DEDc92a2047062294488539992710b99D71"
|
|
"0x9f74Be42725f2Aa072a9E0CdCce0E7203C510263"
|
|
"0xBe9e0B2d4cF6A3b2994d6f2f0904D2B165eB8ffC"
|
|
"0xD084b68cB4B1ef2cBA09CF99FB1B6552fd9b4859"
|
|
"0x89F7a1fcbBe104BeE96Da4b4b6b7d3AF85f7E661"
|
|
)
|
|
|
|
declare -A SIG_OF
|
|
while IFS= read -r line; do
|
|
sel="${line%%$'\t'*}"
|
|
sig="${line#*$'\t'}"
|
|
sel_lc=$(echo "$sel" | tr '[:upper:]' '[:lower:]')
|
|
SIG_OF[$sel_lc]="$sig"
|
|
done <<'EOF'
|
|
0xd0a494e4 flashLoan(uint256,uint256,address,bytes)
|
|
0xadf51de1 flashLoan(address,uint256,address,bytes)
|
|
0xf859ddd7 flashLoan(address,uint256,uint256,address,bytes)
|
|
0x5cffe9de flashLoan(address,address,uint256,bytes)
|
|
0x5c38449e flashLoan(address,address[],uint256[],bytes)
|
|
0xf740f328 flash(address,uint256,bytes)
|
|
0x10d1e85c uniswapV2Call(address,uint256,uint256,bytes)
|
|
0x244dac6e executeOperation(address,address,address,uint256,uint256,bytes)
|
|
0xfc08f9f6 executeOperation(address[],uint256[],uint256[],address,address,bytes)
|
|
0x3e0a794c operateAction(uint8,uint256,bytes)
|
|
0x2b2d17ad flashLoanSimple(address,uint256,bytes,uint16)
|
|
0x613255ab maxFlashLoan(address)(uint256)
|
|
0x88e492ab flashFees(address,address)(uint256)
|
|
0xeb2021c3 DVMFlashLoanCall(address,uint256,uint256,bytes)
|
|
0x4d7f652f DPPFlashLoanCall(address,uint256,uint256,bytes)
|
|
0x2eaeb2e6 DSPFlashLoanCall(address,uint256,uint256,bytes)
|
|
EOF
|
|
|
|
mapfile -t PAIRS < <(
|
|
jq -r --arg c "$CHAIN_KEY" '.chains[$c].contracts // {} | to_entries[] | "\(.key)\t\(.value)"' "$JSON"
|
|
)
|
|
for a in "${EXTRA_ADDRS[@]}"; do
|
|
PAIRS+=("EXTRA_CANONICAL"$'\t'"$a")
|
|
done
|
|
|
|
declare -A SEEN_ADDR
|
|
declare -a SCAN_ROWS=()
|
|
declare -a CANDIDATE_JSON=()
|
|
declare -a NO_CODE=()
|
|
declare -a ERRORS=()
|
|
|
|
cid=$(cast chain-id --rpc-url "$RPC" 2>/dev/null || echo "")
|
|
|
|
for row in "${PAIRS[@]}"; do
|
|
name="${row%%$'\t'*}"
|
|
addr="${row#*$'\t'}"
|
|
addr_lc=$(echo "$addr" | tr '[:upper:]' '[:lower:]')
|
|
if [[ -n "${SEEN_ADDR[$addr_lc]:-}" ]]; then
|
|
continue
|
|
fi
|
|
SEEN_ADDR[$addr_lc]=1
|
|
|
|
if [[ ! "$addr" =~ ^0x[0-9a-fA-F]{40}$ ]]; then
|
|
ERRORS+=("{\"name\":\"$name\",\"address\":\"$addr\",\"error\":\"invalid address\"}")
|
|
continue
|
|
fi
|
|
|
|
code=$(cast code "$addr" --rpc-url "$RPC" 2>&1) || true
|
|
if [[ "$code" == "0x" || -z "$code" ]]; then
|
|
NO_CODE+=("{\"name\":\"$(jq -cn --arg n "$name" '$n')\",\"address\":\"$addr\"}")
|
|
continue
|
|
fi
|
|
if [[ "$code" == Error:* ]]; then
|
|
ERRORS+=("{\"name\":\"$(jq -cn --arg n "$name" '$n')\",\"address\":\"$addr\",\"error\":$(jq -cn --arg m "$code" '$m')}")
|
|
continue
|
|
fi
|
|
|
|
sel_text=$(cast selectors "$code" 2>/dev/null || true)
|
|
matched=()
|
|
matched_sigs=()
|
|
while IFS= read -r sline; do
|
|
sel=$(echo "$sline" | awk '{print $1}' | tr '[:upper:]' '[:lower:]')
|
|
[[ "$sel" =~ ^0x[0-9a-f]{8}$ ]] || continue
|
|
if [[ -n "${SIG_OF[$sel]:-}" ]]; then
|
|
matched+=("$sel")
|
|
matched_sigs+=("${SIG_OF[$sel]}")
|
|
fi
|
|
done <<< "$sel_text"
|
|
|
|
if ((${#matched[@]} > 0)); then
|
|
ms=$(printf '%s\n' "${matched_sigs[@]}" | jq -R . | jq -s .)
|
|
mc=$(printf '%s\n' "${matched[@]}" | jq -R . | jq -s .)
|
|
CANDIDATE_JSON+=("$(jq -nc \
|
|
--arg name "$name" \
|
|
--arg addr "$addr" \
|
|
--argjson ms "$ms" \
|
|
--argjson mc "$mc" \
|
|
'{name:$name,address:$addr,matchedSelectors:$mc,matchedSignatures:$ms}')")
|
|
fi
|
|
|
|
SCAN_ROWS+=("{\"name\":$(jq -cn --arg n "$name" '$n'),\"address\":\"$addr\",\"bytecodeHexChars\":$((${#code} - 2)),\"flashMatchCount\":${#matched[@]}}")
|
|
done
|
|
|
|
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
ref=$(printf '%s\n' "${!SIG_OF[@]}" | sort -u | while read -r s; do
|
|
jq -nc --arg sel "$s" --arg sig "${SIG_OF[$s]}" '{selector:$sel,signature:$sig}'
|
|
done | jq -s .)
|
|
|
|
candidates_arr=$(printf '%s\n' "${CANDIDATE_JSON[@]}" | jq -s .)
|
|
scanned_arr=$(printf '%s\n' "${SCAN_ROWS[@]}" | jq -s .)
|
|
nocode_arr=$(printf '%s\n' "${NO_CODE[@]}" | jq -s .)
|
|
errors_arr=$(printf '%s\n' "${ERRORS[@]}" | jq -s .)
|
|
|
|
jq -nc \
|
|
--arg ts "$ts" \
|
|
--arg rpc "$RPC" \
|
|
--arg chainId "$cid" \
|
|
--argjson ref "$ref" \
|
|
--argjson candidates "$candidates_arr" \
|
|
--argjson scanned "$scanned_arr" \
|
|
--argjson noCode "$nocode_arr" \
|
|
--argjson errors "$errors_arr" \
|
|
'{
|
|
schemaVersion: 1,
|
|
generatedAt: $ts,
|
|
rpcUrl: $rpc,
|
|
chainId: ($chainId | tonumber? // $chainId),
|
|
description: "Heuristic flash/callback selector scan; false positives possible (e.g. unrelated executeOperation).",
|
|
flashSelectorsReference: $ref,
|
|
candidates: $candidates,
|
|
scannedContracts: $scanned,
|
|
emptyBytecode: $noCode,
|
|
errors: $errors
|
|
}' > "$OUT_JSON"
|
|
|
|
echo "Wrote $OUT_JSON"
|
|
echo "Candidates: $(jq '.candidates | length' "$OUT_JSON")"
|
|
jq '.candidates' "$OUT_JSON"
|