docs: update master documentation and push to Gitea (2026-03-06)
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled

- MASTER_INDEX: Last Updated 2026-03-06; status 59/59 contracts; add NEXT_STEPS_LIST, CONTRACT_NEXT_STEPS_LIST
- docs/README, NEXT_STEPS_INDEX, 06-besu/MASTER_INDEX: Last Updated 2026-03-06
- Contract check script: 59 addresses (PMM, vault/reserve, CompliantFiatTokens); canonical CCIP/router
- New docs: EXECUTION_CHECKLIST, NEXT_STEPS_LIST, DOTENV_AUDIT, ADDITIONAL_PATHS, deployer gas runbook, WEMIX_ACQUISITION_TABLED, etc.
- Config: deployer-gas-routes, cro-wemix-swap-routes, routing-registry, token-mapping
- Scripts: check-contracts-on-chain-138, check-pmm-pool-balances-chain138, deployer-gas-auto-route, acquire-cro-and-wemix-gas
- Operator rule: operator-lan-access-check.mdc

Made-with: Cursor
This commit is contained in:
defiQUG
2026-03-06 19:11:25 -08:00
parent d38174dc25
commit 3f76bc9507
63 changed files with 3439 additions and 107 deletions

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Print all swap routes and instructions to acquire CRO (Cronos) and WEMIX (Wemix) native gas for the deployer.
# Reads multiple routes from config/cro-wemix-swap-routes.json. No in-repo execution: use aggregator UIs.
#
# Usage:
# ./scripts/deployment/acquire-cro-and-wemix-gas.sh # full output from config
# ./scripts/deployment/acquire-cro-and-wemix-gas.sh --json # emit config paths + deployer only
# ./scripts/deployment/acquire-cro-and-wemix-gas.sh --list # one line per route (name, url)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CONFIG="${PROJECT_ROOT}/config/cro-wemix-swap-routes.json"
OUTPUT_JSON=false
OUTPUT_LIST=false
for a in "$@"; do
[[ "$a" == "--json" ]] && OUTPUT_JSON=true
[[ "$a" == "--list" ]] && OUTPUT_LIST=true
done
if [[ ! -f "$CONFIG" ]]; then
echo "Error: Config not found: $CONFIG" >&2
exit 1
fi
DEPLOYER="$(jq -r '.deployerAddress // "0x4A666F96fC8764181194447A7dFdb7d471b301C8"' "$CONFIG")"
if $OUTPUT_JSON; then
jq -c '{ deployerAddress, configPath: $config, chains: .chains | keys }' --arg config "$CONFIG" "$CONFIG"
exit 0
fi
echo ""
echo "=============================================="
echo " Swap routes: CRO and WEMIX deployer gas"
echo " Deployer: $DEPLOYER"
echo " Config: $CONFIG"
echo "=============================================="
echo ""
for chain_key in 25 1111; do
name=$(jq -r --arg k "$chain_key" '.chains[$k].name // empty' "$CONFIG")
[[ -z "$name" ]] && continue
native=$(jq -r --arg k "$chain_key" '.chains[$k].nativeSymbol // empty' "$CONFIG")
required=$(jq -r --arg k "$chain_key" '.chains[$k].requiredNative // empty' "$CONFIG")
unit=$(jq -r --arg k "$chain_key" '.chains[$k].requiredUnit // empty' "$CONFIG")
recipient=$(jq -r --arg k "$chain_key" '.chains[$k].recipientNote // empty' "$CONFIG")
echo "--- $name (chain $chain_key) ---"
echo " Required: ~$required $unit"
echo " $recipient"
echo " Deployer address: $DEPLOYER"
echo ""
if $OUTPUT_LIST; then
jq -r --arg k "$chain_key" '.chains[$k].swapRoutes[]? | " \(.name): \(.url)"' "$CONFIG" 2>/dev/null
else
echo " Swap routes (use any aggregator; send $unit to deployer when done):"
jq -r --arg k "$chain_key" '.chains[$k].swapRoutes[]? | " [\(.name)] \(.description)\n \(.url)"' "$CONFIG" 2>/dev/null
fi
echo ""
done
echo "After funding:"
echo " Cronos: set CRONOS_RPC (or CRONOS_RPC_URL) in smom-dbis-138/.env, then run deploy-bridges-config-ready-chains.sh cronos and complete-config-ready-chains.sh."
echo " Wemix: set WEMIX_RPC in smom-dbis-138/.env, then run deploy-bridges-config-ready-chains.sh wemix and complete-config-ready-chains.sh. See WEMIX_ACQUISITION_TABLED.md."
echo ""

View File

@@ -0,0 +1,89 @@
#!/usr/bin/env bash
# Chain 138 path for deployer gas auto-route: try token-aggregation quote for cUSDT/cUSDC → WETH.
# If no c*→WETH pool exists (current state), output "use genesis/validator only".
# Uses config/deployer-gas-routes.json for 138 entry (tokenAggregationBaseUrl, token addresses).
#
# Usage:
# ./scripts/deployment/chain138-tokens-to-gas.sh [--dry-run] [--amount-raw WEI]
# TOKEN_AGGREGATION_URL=https://dbis-api.d-bis.org/api/v1 ./scripts/deployment/chain138-tokens-to-gas.sh
#
# Requires: curl, jq. Optional: RPC_URL_138, PRIVATE_KEY for execute path (not implemented in v1).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CONFIG="${PROJECT_ROOT}/config/deployer-gas-routes.json"
DRY_RUN=false
AMOUNT_RAW="${AMOUNT_RAW:-1000000000}"
# Default: 1000 USDT (6 decimals) in raw units
if [[ -f "$CONFIG" ]]; then
BASE_URL="${TOKEN_AGGREGATION_URL:-$(jq -r '.chains[] | select(.chainId==138) | .tokenAggregationBaseUrl // empty' "$CONFIG")}"
FALLBACK_URL="$(jq -r '.chains[] | select(.chainId==138) | .tokenAggregationFallbackUrl // empty' "$CONFIG")"
CUSDT="$(jq -r '.chains[] | select(.chainId==138) | .cusdt // empty' "$CONFIG")"
CUSDC="$(jq -r '.chains[] | select(.chainId==138) | .cusdc // empty' "$CONFIG")"
WETH9="$(jq -r '.chains[] | select(.chainId==138) | .weth9 // empty' "$CONFIG")"
fi
BASE_URL="${BASE_URL:-https://dbis-api.d-bis.org/api/v1}"
CUSDT="${CUSDT:-0x93E66202A11B1772E55407B32B44e5Cd8eda7f22}"
CUSDC="${CUSDC:-0xf22258f57794CC8E06237084b353Ab30fFfa640b}"
WETH9="${WETH9:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}"
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
--amount-raw=*) AMOUNT_RAW="${arg#*=}" ;;
esac
done
# Try quote cUSDT -> WETH
quote_cusdt_weth() {
local url="${1:-$BASE_URL}"
curl -sS --connect-timeout 5 "${url}/quote?chainId=138&tokenIn=${CUSDT}&tokenOut=${WETH9}&amountIn=${AMOUNT_RAW}" 2>/dev/null || echo '{"amountOut":null,"error":"request failed"}'
}
# Try quote cUSDC -> WETH
quote_cusdc_weth() {
local url="${1:-$BASE_URL}"
curl -sS --connect-timeout 5 "${url}/quote?chainId=138&tokenIn=${CUSDC}&tokenOut=${WETH9}&amountIn=${AMOUNT_RAW}" 2>/dev/null || echo '{"amountOut":null,"error":"request failed"}'
}
echo "Chain 138 path: tokens → gas (WETH)"
echo " Token-aggregation: $BASE_URL"
echo " Amount (raw): $AMOUNT_RAW"
echo ""
res_cusdt="$(quote_cusdt_weth)"
res_cusdc="$(quote_cusdc_weth)"
amount_out_cusdt="$(echo "$res_cusdt" | jq -r '.amountOut // empty' 2>/dev/null)"
amount_out_cusdc="$(echo "$res_cusdc" | jq -r '.amountOut // empty' 2>/dev/null)"
err_cusdt="$(echo "$res_cusdt" | jq -r '.error // empty' 2>/dev/null)"
err_cusdc="$(echo "$res_cusdc" | jq -r '.error // empty' 2>/dev/null)"
if [[ -n "$amount_out_cusdt" && "$amount_out_cusdt" != "null" && "$amount_out_cusdt" -gt 0 ]] 2>/dev/null; then
echo " cUSDT → WETH: quote available (amountOut=$amount_out_cusdt). Pool exists; use DODO PMM swap then optional unwrap."
echo " Action: build DODO swap tx (swapCUSDTFor* to WETH pool) and optional WETH9.withdraw; see DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md."
exit 0
fi
if [[ -n "$amount_out_cusdc" && "$amount_out_cusdc" != "null" && "$amount_out_cusdc" -gt 0 ]] 2>/dev/null; then
echo " cUSDC → WETH: quote available (amountOut=$amount_out_cusdc). Pool exists; use DODO PMM swap then optional unwrap."
echo " Action: build DODO swap tx (swapCUSDCFor* to WETH pool) and optional WETH9.withdraw; see DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md."
exit 0
fi
# Fallback URL if primary failed with network error
if [[ -z "$amount_out_cusdt" && -z "$amount_out_cusdc" && -n "$FALLBACK_URL" ]]; then
res_cusdt="$(quote_cusdt_weth "$FALLBACK_URL")"
amount_out_cusdt="$(echo "$res_cusdt" | jq -r '.amountOut // empty' 2>/dev/null)"
if [[ -n "$amount_out_cusdt" && "$amount_out_cusdt" != "null" && "$amount_out_cusdt" -gt 0 ]] 2>/dev/null; then
echo " cUSDT → WETH: quote available (fallback URL). Pool exists."
exit 0
fi
fi
echo " No cUSDT/cUSDC → WETH pool found on Chain 138 (token-aggregation returned no quote)."
echo " Chain 138 gas: use genesis alloc or validator transfer. See FUNDING_AND_DEPLOYMENT_CHECKLIST.md."
echo " Output: method=genesis_or_validator"
exit 0

View File

@@ -0,0 +1,158 @@
#!/usr/bin/env bash
# Deployer gas auto-route orchestrator: for each chain where deployer native balance is below
# threshold, dispatch to internal (138), Protocolink (public), or manual (Wemix) path.
# Uses config/deployer-gas-routes.json and smom-dbis-138/.env for RPC and deployer.
#
# Usage:
# ./scripts/deployment/deployer-gas-auto-route.sh [--dry-run] [--chain CHAIN_ID] [--no-execute]
# # From repo root; load-project-env sources smom-dbis-138/.env
#
# Requires: jq, curl, cast (Foundry). Optional: Node for protocolink-swap-to-gas.js.
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
source "$PROJECT_ROOT/scripts/lib/load-project-env.sh"
fi
CONFIG="${PROJECT_ROOT}/config/deployer-gas-routes.json"
DRY_RUN=false
NO_EXECUTE=false
CHAIN_FILTER=""
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
--no-execute) NO_EXECUTE=true ;;
--chain=*) CHAIN_FILTER="${arg#*=}" ;;
--chain) CHAIN_FILTER="${2:-}"; shift ;;
esac
done
if [[ ! -f "$CONFIG" ]]; then
echo "ERROR: Config not found: $CONFIG" >&2
exit 1
fi
DEPLOYER="${DEPLOYER_ADDRESS:-$(jq -r '.deployerAddress // empty' "$CONFIG")}"
if [[ -z "$DEPLOYER" && -n "${PRIVATE_KEY:-}" ]] && command -v cast &>/dev/null; then
DEPLOYER="$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)"
fi
DEPLOYER="${DEPLOYER:-0x4A666F96fC8764181194447A7dFdb7d471b301C8}"
# Map chainId to RPC env var name (from check-balances-gas-and-deploy.sh)
get_rpc_for_chain() {
local c="$1"
case "$c" in
1) echo "${ETHEREUM_MAINNET_RPC:-}" ;;
56) echo "${BSC_RPC_URL:-${BSC_MAINNET_RPC:-}}" ;;
137) echo "${POLYGON_MAINNET_RPC:-}" ;;
138) echo "${RPC_URL_138:-}" ;;
10) echo "${OPTIMISM_MAINNET_RPC:-}" ;;
42161) echo "${ARBITRUM_MAINNET_RPC:-}" ;;
8453) echo "${BASE_MAINNET_RPC:-}" ;;
43114) echo "${AVALANCHE_RPC_URL:-${AVALANCHE_MAINNET_RPC:-}}" ;;
100) echo "${GNOSIS_MAINNET_RPC:-${GNOSIS_RPC:-}}" ;;
25) echo "${CRONOS_RPC_URL:-}" ;;
42220) echo "${CELO_RPC_URL:-}" ;;
1111) echo "${WEMIX_RPC_URL:-}" ;;
651940) echo "${ALLTRA_MAINNET_RPC:-}" ;;
*) echo "" ;;
esac
}
# thresholdEther is human number; convert to wei for ETH-like 18 decimals. For MATIC/BNB/etc same scale.
threshold_to_wei() {
local th="$1"
echo "${th}" | awk 'BEGIN { OFMT="%.0f" } { gsub(/,/,""); printf "%.0f", $0 * 1e18 }'
}
echo "=============================================="
echo "Deployer gas auto-route"
echo "Deployer: ${DEPLOYER:0:6}...${DEPLOYER: -6}"
echo "Config: $CONFIG"
echo "=============================================="
echo ""
needs_gas=()
while read -r line; do
chain_id="$(echo "$line" | jq -r '.chainId')"
name="$(echo "$line" | jq -r '.name')"
method="$(echo "$line" | jq -r '.method')"
th_ether="$(echo "$line" | jq -r '.thresholdEther')"
native_sym="$(echo "$line" | jq -r '.nativeSymbol // "native"')"
[[ "$chain_id" == "null" || -z "$chain_id" ]] && continue
[[ -n "$CHAIN_FILTER" && "$CHAIN_FILTER" != "$chain_id" ]] && continue
rpc="$(get_rpc_for_chain "$chain_id")"
if [[ -z "$rpc" ]]; then
echo "[$chain_id] $name — no RPC configured; skip"
continue
fi
balance_wei="$(cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0")"
[[ -z "$balance_wei" || ! "$balance_wei" =~ ^[0-9]+$ ]] && balance_wei="0"
th_wei="$(threshold_to_wei "$th_ether")"
if [[ "$(echo "$balance_wei >= $th_wei" | bc 2>/dev/null)" -eq 1 ]]; then
echo "[$chain_id] $name — balance OK (>= $th_ether $native_sym); skip"
continue
fi
echo "[$chain_id] $name — below threshold ($th_ether); method=$method"
needs_gas+=("$chain_id|$name|$method|$line")
done < <(jq -c '.chains[]' "$CONFIG" 2>/dev/null)
echo ""
if [[ ${#needs_gas[@]} -eq 0 ]]; then
echo "No chains need gas. Done."
exit 0
fi
echo "Chains needing gas: ${#needs_gas[@]}"
echo ""
for entry in "${needs_gas[@]}"; do
IFS='|' read -r chain_id name method line <<< "$entry"
echo "--- $name (chain $chain_id) ---"
case "$method" in
internal)
if [[ "$chain_id" == "138" ]]; then
"$SCRIPT_DIR/chain138-tokens-to-gas.sh" ${DRY_RUN:+--dry-run} 2>&1 || true
else
echo " Internal path only for chain 138; skip."
fi
;;
protocolink)
if command -v node &>/dev/null; then
node "$SCRIPT_DIR/protocolink-swap-to-gas.cjs" --chain-id "$chain_id" --no-execute 2>&1 || true
else
echo " Install Node to run protocolink-swap-to-gas.cjs for this chain."
fi
;;
manual)
manual_links="$(echo "$line" | jq -r '.manualLinks[]? // empty' 2>/dev/null)"
manual_instr="$(echo "$line" | jq -r '.manualInstructions // empty' 2>/dev/null)"
echo " $manual_instr"
if [[ -n "$manual_links" ]]; then
echo "$manual_links" | while read -r url; do [[ -n "$url" ]] && echo " $url"; done
fi
if [[ "$chain_id" == "25" || "$chain_id" == "1111" ]]; then
echo " For all swap routes (multiple aggregators): ./scripts/deployment/acquire-cro-and-wemix-gas.sh"
fi
if [[ "$chain_id" == "1111" ]] && command -v node &>/dev/null; then
node "$SCRIPT_DIR/wemix-acquire-via-lifi.js" --dry-run 2>&1 | head -20
fi
;;
lifi|jumper)
echo " LiFi/Jumper path not yet implemented; use manual links or wemix-acquire-via-lifi.js for Wemix."
;;
*)
echo " Unknown method: $method"
;;
esac
echo ""
done
echo "Done. See docs/03-deployment/DEPLOYER_GAS_AUTO_ROUTE_RUNBOOK.md for full steps."

View File

@@ -0,0 +1,175 @@
#!/usr/bin/env node
/**
* Protocolink path for deployer gas auto-route: get quote and build tx data for
* swapping ERC-20 (USDT, USDC, LINK) to native gas (or WETH) on Protocolink-supported chains.
*
* Usage:
* node scripts/deployment/protocolink-swap-to-gas.cjs --chain-id 1 [--token USDC] [--amount-raw 1000000] [--no-execute]
* PROTOCOLINK_API_URL=https://api.protocolink.com node scripts/deployment/protocolink-swap-to-gas.cjs --chain-id 137
*
* Requires: Node 18+ (fetch), config/deployer-gas-routes.json for chain list.
* Output: JSON with quote and tx building instructions; no private key or signing in script.
*/
const fs = require('fs');
const path = require('path');
const PROJECT_ROOT = path.resolve(__dirname, '../..');
const CONFIG_PATH = path.join(PROJECT_ROOT, 'config/deployer-gas-routes.json');
const API_BASE = process.env.PROTOCOLINK_API_URL || 'https://api.protocolink.com';
const PROTOCOL_ID = process.env.PROTOCOLINK_PROTOCOL || 'paraswap-v5';
const LOGIC_ID = 'swap-token';
const SLIPPAGE_BPS = parseInt(process.env.SLIPPAGE_BPS || '150', 10);
// Common token addresses per chain (mainnet; extend as needed)
const NATIVE_OR_WETH = {
1: { address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', decimals: 18, symbol: 'WETH' },
56: { address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', decimals: 18, symbol: 'WBNB' },
137: { address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', decimals: 18, symbol: 'WMATIC' },
100: { address: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', decimals: 18, symbol: 'WXDAI' },
10: { address: '0x4200000000000000000000000000000000000006', decimals: 18, symbol: 'WETH' },
42161: { address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBb1', decimals: 18, symbol: 'WETH' },
8453: { address: '0x4200000000000000000000000000000000000006', decimals: 18, symbol: 'WETH' },
43114: { address: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', decimals: 18, symbol: 'WAVAX' },
25: { address: '0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23', decimals: 18, symbol: 'WCRO' },
};
const USDT = {
1: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
56: '0x55d398326f99059fF775485246999027B3197955',
137: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
100: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6',
10: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58',
42161: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
8453: '0x0000000000000000000000000000000000000000', // TBD
43114: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7',
25: '0x66e428c3f67a68878562e79A0234c1F83c208770',
};
const USDC = {
1: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
56: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
137: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
100: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83',
10: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
42161: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
8453: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
43114: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
25: '0xc21223249CA28397B4B6541dfFaEcC539BfF0c59',
};
const LINK = {
1: '0x514910771AF9Ca656af840dff83E8264EcF986CA',
56: '0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD',
137: '0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39',
100: '0xE2e73A1c69ecF83F464CECE147577d37BCf26298',
10: '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6',
42161: '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4',
8453: '0x0000000000000000000000000000000000000000', // TBD
43114: '0x5947BB275c521040051D82396192181b413227A3',
25: '0xE7d7D8374CF6a8e3F656c433F6B0f0C81F6d06F5',
};
function getTokenIn(chainId, symbol) {
const s = (symbol || 'USDC').toUpperCase();
let addr;
if (s === 'USDT') addr = USDT[chainId];
else if (s === 'USDC') addr = USDC[chainId];
else if (s === 'LINK') addr = LINK[chainId];
else return null;
if (!addr || addr === '0x0000000000000000000000000000000000000000') return null;
const decimals = s === 'LINK' ? 18 : 6;
return { chainId, address: addr, decimals, symbol: s, name: s };
}
function getTokenOut(chainId) {
const t = NATIVE_OR_WETH[chainId];
if (!t) return null;
return { chainId, address: t.address, decimals: t.decimals, symbol: t.symbol, name: t.symbol };
}
function parseArgs() {
const args = process.argv.slice(2);
let chainId, tokenIn = 'USDC', amountRaw, noExecute = false;
for (let i = 0; i < args.length; i++) {
if (args[i] === '--chain-id' && args[i + 1]) chainId = parseInt(args[i + 1], 10);
if (args[i] === '--token' && args[i + 1]) tokenIn = args[i + 1];
if (args[i] === '--amount-raw' && args[i + 1]) amountRaw = args[i + 1];
if (args[i] === '--no-execute') noExecute = true;
}
return { chainId, tokenIn, amountRaw: amountRaw || '1000000', noExecute };
}
async function requestQuote(chainId, tokenInObj, tokenOutObj, amountRaw) {
const url = `${API_BASE}/v1/protocols/${chainId}/${PROTOCOL_ID}/${LOGIC_ID}/quote`;
const body = {
input: {
token: tokenInObj,
amount: amountRaw,
},
tokenOut: tokenOutObj,
slippage: SLIPPAGE_BPS,
};
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Protocolink quote failed ${res.status}: ${text}`);
}
return res.json();
}
function loadConfig() {
if (!fs.existsSync(CONFIG_PATH)) return null;
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
}
async function main() {
const { chainId, tokenIn: tokenSymbol, amountRaw, noExecute } = parseArgs();
if (!chainId) {
console.error('Usage: node protocolink-swap-to-gas.cjs --chain-id <chainId> [--token USDC|USDT|LINK] [--amount-raw <raw>] [--no-execute]');
process.exit(1);
}
const tokenInObj = getTokenIn(chainId, tokenSymbol);
const tokenOutObj = getTokenOut(chainId);
if (!tokenInObj || !tokenOutObj) {
console.error(JSON.stringify({
error: 'Unsupported chain or token',
chainId,
tokenIn: tokenSymbol,
message: 'Add token addresses for this chain in protocolink-swap-to-gas.cjs or use a supported chain (1, 56, 137, 100, 10, 42161, 8453, 43114, 25).',
}, null, 2));
process.exit(1);
}
try {
const quote = await requestQuote(chainId, tokenInObj, tokenOutObj, amountRaw);
const output = {
chainId,
protocolId: PROTOCOL_ID,
logicId: LOGIC_ID,
quote,
tokenIn: tokenInObj,
tokenOut: tokenOutObj,
amountInRaw: amountRaw,
slippageBps: SLIPPAGE_BPS,
nextStep: 'Use Protocolink API "build transaction" or SDK to build tx; sign with deployer key and submit. See https://docs.protocolink.com/protocolink-api/overview.',
noExecute: true,
};
console.log(JSON.stringify(output, null, 2));
} catch (err) {
console.error(JSON.stringify({
error: err.message,
chainId,
tokenIn: tokenSymbol,
}, null, 2));
process.exit(1);
}
}
main();

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# Check that Chain 138 deployed contracts have bytecode on-chain.
# Address list: 59 (core, CCIP, PMM, vault/reserve, CompliantFiatTokens). Source: CONTRACT_ADDRESSES_REFERENCE, ADDRESS_MATRIX.
# Usage: ./scripts/verify/check-contracts-on-chain-138.sh [RPC_URL] [--dry-run]
# Default RPC: from env RPC_URL_138 (Chain 138 Core standard) or config/ip-addresses.conf, else https://rpc-core.d-bis.org
# Optional: SKIP_EXIT=1 to exit 0 even when some addresses MISS (e.g. when RPC unreachable from this host).
@@ -81,7 +82,28 @@ else
"0x6427F9739e6B6c3dDb4E94fEfeBcdF35549549d8" # MirrorRegistry
"0x66FEBA2fC9a0B47F26DD4284DAd24F970436B8Dc" # AlltraAdapter
"0x7131F887DBEEb2e44c1Ed267D2A68b5b83285afc" # TransactionMirror Chain 138 (deployed 2026-02-27; set TRANSACTION_MIRROR_ADDRESS in .env)
"0x9fcB06Aa1FD5215DC0E91Fd098aeff4B62fEa5C8" # DODO cUSDT-cUSDC pool (pending until CreateCUSDTCUSDCPool succeeds)
"0x9fcB06Aa1FD5215DC0E91Fd098aeff4B62fEa5C8" # DODO cUSDT-cUSDC pool
"0x79cdbaFBaA0FdF9F55D26F360F54cddE5c743F7D" # DODOPMMIntegration
"0x8EF6657D2a86c569F6ffc337EE6b4260Bd2e59d0" # DODOPMMProvider
"0xa3Ee6091696B28e5497b6F491fA1e99047250c59" # DODO pool cUSDT/USDT
"0x90bd9Bf18Daa26Af3e814ea224032d015db58Ea5" # DODO pool cUSDC/USDC
"0x607e97cD626f209facfE48c1464815DDE15B5093" # ReserveSystem
"0x34B73e6EDFd9f85a7c25EeD31dcB13aB6E969b96" # ReserveTokenIntegration
"0xEA4C892D6c1253797c5D95a05BF3863363080b4B" # RegulatedEntityRegistry (vault)
"0xB2Ac70f35A81481B005067ed6567a5043BA32336" # VaultFactory
"0x67b3831dc64C14FB9352B2a45C6Dd69b3C86B7af" # Ledger (vault)
"0x3aCdbCB749d6037a02F0ef6ea2E5Fb89D31fAB72" # Liquidation (vault)
"0xf23E1eDa304082ab7a81531dFE6020E6105e77A8" # XAU Oracle (vault)
"0x8085961F9cF02b4d800A3c6d386D31da4B34266a" # cEURC
"0xdf4b71c61E5912712C1Bdd451416B9aC26949d72" # cEURT
"0x003960f16D9d34F2e98d62723B6721Fb92074aD2" # cGBPC
"0x350f54e4D23795f86A9c03988c7135357CCaD97c" # cGBPT
"0xD51482e567c03899eecE3CAe8a058161FD56069D" # cAUDC
"0xEe269e1226a334182aace90056EE4ee5Cc8A6770" # cJPYC
"0x873990849DDa5117d7C644f0aF24370797C03885" # cCHFC
"0x54dBd40cF05e15906A2C21f600937e96787f5679" # cCADC
"0x290E52a8819A4fbD0714E517225429aA2B70EC6b" # cXAUC
"0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E" # cXAUT
)
fi

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Check all Chain 138 DODO PMM pool token balances (base + quote).
# Uses eth_call (curl) for compatibility with RPCs that reject some cast call formats.
#
# Usage: ./scripts/verify/check-pmm-pool-balances-chain138.sh [RPC_URL]
# Default RPC: http://192.168.11.211:8545
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
RPC="${1:-${RPC_URL_138:-http://192.168.11.211:8545}}"
# Token addresses (Chain 138 canonical)
cUSDT="0x93E66202A11B1772E55407B32B44e5Cd8eda7f22"
cUSDC="0xf22258f57794CC8E06237084b353Ab30fFfa640b"
OFFICIAL_USDT="0x15DF1D5BFDD8Aa4b380445D4e3E9B38d34283619"
# Official USDC from integration or placeholder (no contract on 138)
OFFICIAL_USDC="0x0000000000000000000000000000000000000000"
# Pool addresses
POOL_CUSDTCUSDC="0x9fcB06Aa1FD5215DC0E91Fd098aeff4B62fEa5C8"
POOL_CUSDTUSDT="0xa3Ee6091696B28e5497b6F491fA1e99047250c59"
POOL_CUSDCUSDC="0x90bd9Bf18Daa26Af3e814ea224032d015db58Ea5"
pads() { local a; a=$(echo "$1" | sed 's/0x//'); printf '%064s' "$a" | tr ' ' '0'; }
balance() {
local tok="$1" acc="$2"
local d="0x70a08231$(pads "$acc")"
local res
res=$(curl -s -X POST "$RPC" -H "Content-Type: application/json" \
--data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"$tok\",\"data\":\"$d\"},\"latest\"],\"id\":1}" \
| jq -r '.result // empty')
echo "${res:-0x0000000000000000000000000000000000000000000000000000000000000000}"
}
hex2dec() { local h="$1"; [[ -z "$h" || "$h" == "0x" ]] && echo "0" && return; printf '%d' "$h"; }
human6() { local r; r=$(hex2dec "$1"); echo "scale=6; $r / 1000000" | bc 2>/dev/null || echo "$r"; }
echo "=============================================="
echo " Chain 138 — PMM pool balances"
echo " RPC: $RPC"
echo "=============================================="
echo ""
# Pool 1: cUSDT / cUSDC (base / quote)
echo "Pool 1: cUSDT / cUSDC"
echo " Address: $POOL_CUSDTCUSDC"
r1=$(balance "$cUSDT" "$POOL_CUSDTCUSDC")
r2=$(balance "$cUSDC" "$POOL_CUSDTCUSDC")
echo " cUSDT (base): raw=$r1$(human6 "$r1")"
echo " cUSDC (quote): raw=$r2$(human6 "$r2")"
echo ""
# Pool 2: cUSDT / USDT (official USDT has no code on 138)
echo "Pool 2: cUSDT / USDT (official)"
echo " Address: $POOL_CUSDTUSDT"
r1=$(balance "$cUSDT" "$POOL_CUSDTUSDT")
r2=$(balance "$OFFICIAL_USDT" "$POOL_CUSDTUSDT")
echo " cUSDT (base): raw=${r1:-0x0}$(human6 "$r1")"
echo " USDT (quote): raw=${r2:-0x0}$(human6 "$r2")"
echo ""
# Pool 3: cUSDC / USDC (official USDC not deployed on 138)
echo "Pool 3: cUSDC / USDC (official)"
echo " Address: $POOL_CUSDCUSDC"
r1=$(balance "$cUSDC" "$POOL_CUSDCUSDC")
echo " cUSDC (base): raw=$r1$(human6 "$r1")"
if [[ "$OFFICIAL_USDC" != "0x0000000000000000000000000000000000000000" ]]; then
r2=$(balance "$OFFICIAL_USDC" "$POOL_CUSDCUSDC")
echo " USDC (quote): raw=$r2$(human6 "$r2")"
else
echo " USDC (quote): N/A (no official USDC contract on 138)"
fi
echo ""
echo "Note: Pool 1 (cUSDT/cUSDC) is the only pool with liquidity on 138. Pools 2 and 3 use official USDT/USDC which have no contract on Chain 138."
echo "Done."

View File

@@ -32,11 +32,11 @@ FEE_COLLECTOR=0xF78246eB94c6CB14018E507E60661314E5f4C53f
DEBT_REGISTRY=0x95BC4A997c0670d5DAC64d55cDf3769B53B63C28
POLICY_MANAGER=0x0C4FD27018130A00762a802f91a72D6a64a60F14
TOKEN_IMPLEMENTATION=0x0059e237973179146237aB49f1322E8197c22b21
CCIPWETH9_BRIDGE_CHAIN138=0x971cD9D156f193df8051E48043C476e53ECd4693
CCIPWETH9_BRIDGE_CHAIN138=0x9cba0D04Ae5f6f16e3C599025aB97a05c4A593d5
CCIPWETH10_BRIDGE_CHAIN138=0xe0E93247376aa097dB308B92e6Ba36bA015535D0
LINK_TOKEN=0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03
CCIP_FEE_TOKEN=0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03
CCIP_ROUTER=0x8078A09637e47Fa5Ed34F626046Ea2094a5CDE5e
CCIP_ROUTER=0x89EC6574eeAC72Ed1b93DfCa4DB43547C8367FF0
CCIP_SENDER=0x105F8A15b819948a89153505762444Ee9f324684
UNIVERSAL_ASSET_REGISTRY=0xAEE4b7fBe82E1F8295951584CBc772b8BBD68575
GOVERNANCE_CONTROLLER=0xA6891D5229f2181a34D4FF1B515c3Aa37dd90E0e