Add Chain138 native DODO verification tooling
This commit is contained in:
76
scripts/deployment/sync-mev-chain138-token-symbols.sh
Executable file
76
scripts/deployment/sync-mev-chain138-token-symbols.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
REGISTRY_JSON="${PROJECT_ROOT}/config/smart-contracts-master.json"
|
||||
DB_URL="${DB_URL:-postgresql://postgres:postgres@127.0.0.1:5434/mev}"
|
||||
CHAIN_ID="${CHAIN_ID:-138}"
|
||||
APPLY="${APPLY:-0}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: sync-mev-chain138-token-symbols.sh [--db-url URL] [--chain-id ID] [--apply]
|
||||
|
||||
Builds a symbol map for the live Chain 138 MEV token set from canonical repo sources
|
||||
and prints or applies UPDATE statements against the MEV Postgres database.
|
||||
EOF
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--db-url)
|
||||
DB_URL="$2"
|
||||
shift 2
|
||||
;;
|
||||
--chain-id)
|
||||
CHAIN_ID="$2"
|
||||
shift 2
|
||||
;;
|
||||
--apply)
|
||||
APPLY=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown arg: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
sql="$(
|
||||
python3 - "$REGISTRY_JSON" "$CHAIN_ID" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
|
||||
registry = json.loads(Path(sys.argv[1]).read_text())
|
||||
chain_id = str(sys.argv[2])
|
||||
contracts = registry["chains"][chain_id]["contracts"]
|
||||
|
||||
mapping = {
|
||||
contracts["cUSDT"].lower(): "cUSDT",
|
||||
contracts["cUSDC"].lower(): "cUSDC",
|
||||
contracts["WETH10"].lower(): "WETH10",
|
||||
"0x004b63a7b5b0e06f6bb6adb4a5f9f590bf3182d1": "USDT",
|
||||
"0x798f6762bb40d6801a593459d08f890603d3979c": "USDC",
|
||||
}
|
||||
|
||||
for address, symbol in mapping.items():
|
||||
safe_symbol = symbol.replace("'", "''")
|
||||
print(
|
||||
f"UPDATE tokens SET symbol = '{safe_symbol}' "
|
||||
f"WHERE chain_id = {chain_id} AND LOWER(token_id) = LOWER('{address}');"
|
||||
)
|
||||
PY
|
||||
)"
|
||||
|
||||
if [[ "${APPLY}" != "1" ]]; then
|
||||
printf '%s\n' "$sql"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
psql "$DB_URL" -v ON_ERROR_STOP=1 -c "$sql"
|
||||
243
scripts/verify/check-chain138-native-dodo-read-surfaces.sh
Executable file
243
scripts/verify/check-chain138-native-dodo-read-surfaces.sh
Executable file
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Verify the native DODO read surfaces on Chain 138.
|
||||
#
|
||||
# Scope:
|
||||
# - DODO PMM pools:
|
||||
# * getVaultReserve()
|
||||
# * getPMMStateForCall()
|
||||
# - D3MM pilot pool:
|
||||
# * getTokenReserve(address)
|
||||
# * querySellTokens(address,address,uint256)
|
||||
#
|
||||
# The script prints explicit PASS / FAIL lines per surface and exits non-zero
|
||||
# if any required surface is missing or returns an empty / invalid result.
|
||||
#
|
||||
# Default RPC comes from the project env when available, then falls back to the
|
||||
# standard Chain 138 core RPC used elsewhere in the repo.
|
||||
|
||||
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"
|
||||
fi
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
printf '[fail] missing required command: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_command cast
|
||||
require_command timeout
|
||||
|
||||
RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-${CHAIN138_RPC:-http://192.168.11.211:8545}}}"
|
||||
PROBE_AMOUNT_PMM="${CHAIN138_DODO_PMM_PROBE_AMOUNT:-1000000}"
|
||||
PROBE_AMOUNT_D3="${CHAIN138_D3_PROBE_SELL_AMOUNT:-100000000000000000}"
|
||||
TRADER_ADDRESS="${CHAIN138_DODO_READ_TRADER:-${DEPLOYER_ADDRESS:-0x4A666F96fC8764181194447A7dFdb7d471b301C8}}"
|
||||
|
||||
PMM_POOLS=(
|
||||
"cUSDT/cUSDC|0x9e89bAe009adf128782E19e8341996c596ac40dC|0x93E66202A11B1772E55407B32B44e5Cd8eda7f22|0xf22258f57794CC8E06237084b353Ab30fFfa640b|6|6"
|
||||
"cUSDT/USDT|0x866Cb44b59303d8dc5f4F9E3E7A8e8b0bf238d66|0x93E66202A11B1772E55407B32B44e5Cd8eda7f22|0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1|6|6"
|
||||
"cUSDC/USDC|0xc39B7D0F40838cbFb54649d327f49a6DAC964062|0xf22258f57794CC8E06237084b353Ab30fFfa640b|0x71D6687F38b93CCad569Fa6352c876eea967201b|6|6"
|
||||
)
|
||||
|
||||
D3_POOL="0x6550a3a59070061a262a893a1d6f3f490afFDBDA"
|
||||
D3_WETH10="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f"
|
||||
D3_USDT="0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1"
|
||||
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
LAST_CALL_OUTPUT=""
|
||||
|
||||
pass() {
|
||||
printf '[PASS] %s\n' "$*"
|
||||
pass_count=$((pass_count + 1))
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf '[FAIL] %s\n' "$*" >&2
|
||||
fail_count=$((fail_count + 1))
|
||||
}
|
||||
|
||||
run_cast_call() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
LAST_CALL_OUTPUT=""
|
||||
|
||||
local output
|
||||
if ! output="$(timeout 20s cast call --rpc-url "${RPC_URL}" "$@" 2>&1)"; then
|
||||
fail "${label}: call failed"
|
||||
printf ' %s\n' "${output}" >&2
|
||||
LAST_CALL_OUTPUT="${output}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "${output}" ]]; then
|
||||
fail "${label}: empty response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "${output}"
|
||||
LAST_CALL_OUTPUT="${output}"
|
||||
}
|
||||
|
||||
parse_first_uint() {
|
||||
awk 'NR==1 { print $1 }'
|
||||
}
|
||||
|
||||
check_gt_zero() {
|
||||
local label="$1"
|
||||
local value="$2"
|
||||
if [[ ! "${value}" =~ ^[0-9]+$ ]] || (( value <= 0 )); then
|
||||
fail "${label}: expected > 0, got ${value:-<empty>}"
|
||||
return 1
|
||||
fi
|
||||
pass "${label}: ${value}"
|
||||
}
|
||||
|
||||
check_pmm_pool() {
|
||||
local label="$1"
|
||||
local pool="$2"
|
||||
local base="$3"
|
||||
local quote="$4"
|
||||
|
||||
printf '\n=== PMM: %s ===\n' "${label}"
|
||||
printf 'pool=%s\n' "${pool}"
|
||||
|
||||
local reserves
|
||||
if ! run_cast_call "${label} getVaultReserve" "${pool}" 'getVaultReserve()(uint256,uint256)'; then
|
||||
return 1
|
||||
fi
|
||||
reserves="${LAST_CALL_OUTPUT}"
|
||||
|
||||
local reserve_base reserve_quote
|
||||
reserve_base="$(printf '%s\n' "${reserves}" | sed -n '1p' | parse_first_uint)"
|
||||
reserve_quote="$(printf '%s\n' "${reserves}" | sed -n '2p' | parse_first_uint)"
|
||||
|
||||
check_gt_zero "${label} getVaultReserve base" "${reserve_base}" || true
|
||||
check_gt_zero "${label} getVaultReserve quote" "${reserve_quote}" || true
|
||||
|
||||
local state
|
||||
if ! run_cast_call "${label} getPMMStateForCall" "${pool}" 'getPMMStateForCall()(uint256,uint256,uint256,uint256,uint256,uint256,uint256)'; then
|
||||
return 1
|
||||
fi
|
||||
state="${LAST_CALL_OUTPUT}"
|
||||
|
||||
local state_i state_k state_b state_q state_b0 state_q0 state_r
|
||||
state_i="$(printf '%s\n' "${state}" | sed -n '1p' | parse_first_uint)"
|
||||
state_k="$(printf '%s\n' "${state}" | sed -n '2p' | parse_first_uint)"
|
||||
state_b="$(printf '%s\n' "${state}" | sed -n '3p' | parse_first_uint)"
|
||||
state_q="$(printf '%s\n' "${state}" | sed -n '4p' | parse_first_uint)"
|
||||
state_b0="$(printf '%s\n' "${state}" | sed -n '5p' | parse_first_uint)"
|
||||
state_q0="$(printf '%s\n' "${state}" | sed -n '6p' | parse_first_uint)"
|
||||
state_r="$(printf '%s\n' "${state}" | sed -n '7p' | parse_first_uint)"
|
||||
|
||||
check_gt_zero "${label} getPMMStateForCall i" "${state_i}" || true
|
||||
check_gt_zero "${label} getPMMStateForCall B" "${state_b}" || true
|
||||
check_gt_zero "${label} getPMMStateForCall Q" "${state_q}" || true
|
||||
if [[ "${state_k}" =~ ^[0-9]+$ ]]; then
|
||||
pass "${label} getPMMStateForCall K: ${state_k}"
|
||||
else
|
||||
fail "${label} getPMMStateForCall K: invalid value ${state_k:-<empty>}"
|
||||
fi
|
||||
if [[ "${state_r}" =~ ^[0-9]+$ ]]; then
|
||||
pass "${label} getPMMStateForCall R: ${state_r}"
|
||||
else
|
||||
fail "${label} getPMMStateForCall R: invalid value ${state_r:-<empty>}"
|
||||
fi
|
||||
printf ' stateB0=%s stateQ0=%s\n' "${state_b0:-<empty>}" "${state_q0:-<empty>}"
|
||||
|
||||
local query_base query_quote
|
||||
if ! run_cast_call "${label} querySellBase" "${pool}" "querySellBase(address,uint256)(uint256,uint256)" "${TRADER_ADDRESS}" "${PROBE_AMOUNT_PMM}"; then
|
||||
return 1
|
||||
fi
|
||||
query_base="${LAST_CALL_OUTPUT}"
|
||||
if ! run_cast_call "${label} querySellQuote" "${pool}" "querySellQuote(address,uint256)(uint256,uint256)" "${TRADER_ADDRESS}" "${PROBE_AMOUNT_PMM}"; then
|
||||
return 1
|
||||
fi
|
||||
query_quote="${LAST_CALL_OUTPUT}"
|
||||
|
||||
local base_out quote_out
|
||||
base_out="$(printf '%s\n' "${query_base}" | sed -n '1p' | parse_first_uint)"
|
||||
quote_out="$(printf '%s\n' "${query_quote}" | sed -n '1p' | parse_first_uint)"
|
||||
|
||||
check_gt_zero "${label} querySellBase out" "${base_out}" || true
|
||||
check_gt_zero "${label} querySellQuote out" "${quote_out}" || true
|
||||
|
||||
printf ' tokens=%s/%s\n' "${base}" "${quote}"
|
||||
}
|
||||
|
||||
check_d3_pool() {
|
||||
printf '\n=== D3MM: canonical WETH10/USDT pilot ===\n'
|
||||
printf 'pool=%s\n' "${D3_POOL}"
|
||||
|
||||
local weth_reserve usdt_reserve
|
||||
if ! run_cast_call "D3MM getTokenReserve(WETH10)" "${D3_POOL}" 'getTokenReserve(address)(uint256)' "${D3_WETH10}"; then
|
||||
return 1
|
||||
fi
|
||||
weth_reserve="${LAST_CALL_OUTPUT}"
|
||||
if ! run_cast_call "D3MM getTokenReserve(USDT)" "${D3_POOL}" 'getTokenReserve(address)(uint256)' "${D3_USDT}"; then
|
||||
return 1
|
||||
fi
|
||||
usdt_reserve="${LAST_CALL_OUTPUT}"
|
||||
|
||||
local weth_raw usdt_raw
|
||||
weth_raw="$(printf '%s\n' "${weth_reserve}" | parse_first_uint)"
|
||||
usdt_raw="$(printf '%s\n' "${usdt_reserve}" | parse_first_uint)"
|
||||
check_gt_zero "D3MM getTokenReserve WETH10" "${weth_raw}" || true
|
||||
check_gt_zero "D3MM getTokenReserve USDT" "${usdt_raw}" || true
|
||||
|
||||
local quote
|
||||
if ! run_cast_call "D3MM querySellTokens(WETH10->USDT)" "${D3_POOL}" 'querySellTokens(address,address,uint256)(uint256,uint256,uint256,uint256,uint256)' "${D3_WETH10}" "${D3_USDT}" "${PROBE_AMOUNT_D3}"; then
|
||||
return 1
|
||||
fi
|
||||
quote="${LAST_CALL_OUTPUT}"
|
||||
|
||||
local pay_from receive_to vusd_amount swap_fee mt_fee
|
||||
pay_from="$(printf '%s\n' "${quote}" | sed -n '1p' | parse_first_uint)"
|
||||
receive_to="$(printf '%s\n' "${quote}" | sed -n '2p' | parse_first_uint)"
|
||||
vusd_amount="$(printf '%s\n' "${quote}" | sed -n '3p' | parse_first_uint)"
|
||||
swap_fee="$(printf '%s\n' "${quote}" | sed -n '4p' | parse_first_uint)"
|
||||
mt_fee="$(printf '%s\n' "${quote}" | sed -n '5p' | parse_first_uint)"
|
||||
|
||||
if [[ "${pay_from}" != "${PROBE_AMOUNT_D3}" ]]; then
|
||||
fail "D3MM querySellTokens payFrom mismatch: expected ${PROBE_AMOUNT_D3}, got ${pay_from:-<empty>}"
|
||||
else
|
||||
pass "D3MM querySellTokens payFrom: ${pay_from}"
|
||||
fi
|
||||
check_gt_zero "D3MM querySellTokens receiveTo" "${receive_to}" || true
|
||||
printf ' vusd=%s swapFee=%s mtFee=%s\n' "${vusd_amount:-<empty>}" "${swap_fee:-<empty>}" "${mt_fee:-<empty>}"
|
||||
}
|
||||
|
||||
main() {
|
||||
printf 'Chain 138 native DODO read-surface verifier\n'
|
||||
printf 'rpc=%s\n' "${RPC_URL}"
|
||||
printf 'probeAmountPmm=%s\n' "${PROBE_AMOUNT_PMM}"
|
||||
printf 'probeAmountD3=%s\n' "${PROBE_AMOUNT_D3}"
|
||||
printf 'trader=%s\n' "${TRADER_ADDRESS}"
|
||||
|
||||
local row
|
||||
for row in "${PMM_POOLS[@]}"; do
|
||||
IFS='|' read -r label pool base quote _ _ <<<"${row}"
|
||||
if ! check_pmm_pool "${label}" "${pool}" "${base}" "${quote}"; then
|
||||
:
|
||||
fi
|
||||
done
|
||||
|
||||
if ! check_d3_pool; then
|
||||
:
|
||||
fi
|
||||
|
||||
printf '\nSummary: %s passed, %s failed.\n' "${pass_count}" "${fail_count}"
|
||||
if (( fail_count > 0 )); then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user