feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault. - Token-aggregation service routes, planner, chain config, relay env templates. - Config snapshots and multi-chain deployment markdown updates. - gitignore services/btc-intake/dist/ (tsc output); do not track dist. Run forge build && forge test before deploy (large solc graph). Made-with: Cursor
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
# RPC_URL_138 / RPC_URL
|
||||
# PRIVATE_KEY or DEPLOYER_PRIVATE_KEY — ETH/USD oracle push (update-oracle-price.sh)
|
||||
# KEEPER_PRIVATE_KEY + PRICE_FEED_KEEPER_ADDRESS — on-chain keeper performUpkeep when needed
|
||||
# DODO_PMM_INTEGRATION_ADDRESS — default 0x5BDc… (current canonical integration)
|
||||
# DODO_PMM_INTEGRATION_ADDRESS — default 0x86AD… (current canonical integration)
|
||||
# PMM_MESH_POLL_POOLS — space-separated pool addresses (default: cUSDT/cUSDC PMM pool)
|
||||
# ENABLE_MESH_ORACLE_TICK=1 Run scripts/update-oracle-price.sh each tick (skips on-chain if <1% move)
|
||||
# ENABLE_MESH_KEEPER_TICK=1 Run keeper when checkUpkeep is true
|
||||
@@ -16,6 +16,9 @@
|
||||
# ENABLE_MESH_WETH_READS=1 eth_call WETH9/WETH10 totalSupply (ETH mesh signal)
|
||||
# MESH_WETH_WRAP_WEI=0 If >0 and KEEPER_PRIVATE_KEY set: WETH9.deposit{value} (costs gas; rare)
|
||||
# MESH_WETH_WRAP_EVERY_N=60 Only wrap every N ticks when MESH_WETH_WRAP_WEI>0
|
||||
# MESH_TX_BACKOFF_SEC=30 Cooldown after "known tx" / "replacement underpriced" send errors
|
||||
# KEEPER_SECRET_FILE Dedicated keeper env file (default: /root/.secure-secrets/chain138-keeper.env)
|
||||
# ALLOW_ORACLE_KEY_FOR_KEEPER=0 Set to 1 to let keeper reuse PRIVATE_KEY when no dedicated keeper key exists
|
||||
# MAX_TICKS= Exit after N ticks (empty = run forever)
|
||||
# DRY_RUN=1 Log only, no txs
|
||||
#
|
||||
@@ -25,6 +28,22 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$SMOM_ROOT"
|
||||
|
||||
ORACLE_PUBLISHER_ENV="${ORACLE_PUBLISHER_ENV:-/opt/oracle-publisher/.env}"
|
||||
KEEPER_SECRET_FILE="${KEEPER_SECRET_FILE:-/root/.secure-secrets/chain138-keeper.env}"
|
||||
if [ -f "$ORACLE_PUBLISHER_ENV" ]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$ORACLE_PUBLISHER_ENV"
|
||||
set +a
|
||||
fi
|
||||
|
||||
if [ -f "$KEEPER_SECRET_FILE" ]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$KEEPER_SECRET_FILE"
|
||||
set +a
|
||||
fi
|
||||
|
||||
if [ -f "$SMOM_ROOT/.env" ]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
@@ -43,9 +62,9 @@ fi
|
||||
|
||||
RPC="${RPC_URL_138:-${RPC_URL:-http://192.168.11.211:8545}}"
|
||||
INTERVAL="${PMM_MESH_INTERVAL_SEC:-6}"
|
||||
DODO="${DODO_PMM_INTEGRATION_ADDRESS:-${DODO_PMM_INTEGRATION:-0x5BDc62f1ae7D630c37A8B363a1d49845356Ee72d}}"
|
||||
DODO="${DODO_PMM_INTEGRATION_ADDRESS:-${DODO_PMM_INTEGRATION:-0x86ADA6Ef91A3B450F89f2b751e93B1b7A3218895}}"
|
||||
# Canonical cUSDT/cUSDC PMM pool on Chain 138 (current integration)
|
||||
DEFAULT_POOLS="0xff8d3b8fDF7B112759F076B69f4271D4209C0849"
|
||||
DEFAULT_POOLS="0x9e89bAe009adf128782E19e8341996c596ac40dC"
|
||||
POOLS="${PMM_MESH_POLL_POOLS:-$DEFAULT_POOLS}"
|
||||
WETH9="${WETH9_ADDRESS:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}"
|
||||
WETH10="${WETH10_ADDRESS:-0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f}"
|
||||
@@ -56,14 +75,45 @@ ENABLE_PMM_READS="${ENABLE_MESH_PMM_READS:-1}"
|
||||
ENABLE_WETH_READS="${ENABLE_MESH_WETH_READS:-1}"
|
||||
WRAP_WEI="${MESH_WETH_WRAP_WEI:-0}"
|
||||
WRAP_EVERY_N="${MESH_WETH_WRAP_EVERY_N:-60}"
|
||||
MESH_TX_BACKOFF_SEC="${MESH_TX_BACKOFF_SEC:-30}"
|
||||
ALLOW_ORACLE_KEY_FOR_KEEPER="${ALLOW_ORACLE_KEY_FOR_KEEPER:-0}"
|
||||
# Besu often needs an explicit gas price for replacement / mempool policy.
|
||||
MESH_CAST_GAS_PRICE="${MESH_CAST_GAS_PRICE:-2gwei}"
|
||||
|
||||
ORACLE_PK="${PRIVATE_KEY:-${DEPLOYER_PRIVATE_KEY:-}}"
|
||||
KEEPER_PK="${KEEPER_PRIVATE_KEY:-${PRIVATE_KEY:-}}"
|
||||
KEEPER_PK="${KEEPER_PRIVATE_KEY:-}"
|
||||
if [ -z "$KEEPER_PK" ] && [ "$ALLOW_ORACLE_KEY_FOR_KEEPER" = "1" ]; then
|
||||
KEEPER_PK="${PRIVATE_KEY:-}"
|
||||
fi
|
||||
ORACLE_ADDR=""
|
||||
KEEPER_ADDR=""
|
||||
if [ -n "$ORACLE_PK" ]; then
|
||||
ORACLE_ADDR="$(cast wallet address --private-key "$ORACLE_PK" 2>/dev/null || true)"
|
||||
fi
|
||||
if [ -n "$KEEPER_PK" ]; then
|
||||
KEEPER_ADDR="$(cast wallet address --private-key "$KEEPER_PK" 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
NEXT_KEEPER_TX_AT=0
|
||||
NEXT_ORACLE_TX_AT=0
|
||||
|
||||
log() { echo "[$(date -Iseconds)] $*"; }
|
||||
|
||||
is_retryable_tx_error() {
|
||||
local text="${1:-}"
|
||||
grep -qiE 'Known transaction|Replacement transaction underpriced' <<<"$text"
|
||||
}
|
||||
|
||||
account_has_pending_nonce_gap() {
|
||||
local addr="${1:-}"
|
||||
[ -n "$addr" ] || return 1
|
||||
local latest pending
|
||||
latest="$(cast nonce "$addr" --rpc-url "$RPC" --block latest 2>/dev/null || true)"
|
||||
pending="$(cast nonce "$addr" --rpc-url "$RPC" --block pending 2>/dev/null || true)"
|
||||
[[ "$latest" =~ ^[0-9]+$ && "$pending" =~ ^[0-9]+$ ]] || return 1
|
||||
(( pending > latest ))
|
||||
}
|
||||
|
||||
eth_call_price() {
|
||||
local to="$1" data="$2"
|
||||
cast rpc eth_call "{\"to\":\"$to\",\"data\":\"$data\"}" latest --rpc-url "$RPC" 2>/dev/null | tr -d '\n\"' || true
|
||||
@@ -95,8 +145,19 @@ tick_weth_reads() {
|
||||
|
||||
tick_keeper() {
|
||||
[ "$ENABLE_KEEPER" = "1" ] || return 0
|
||||
local now
|
||||
now="$(date +%s)"
|
||||
if (( now < NEXT_KEEPER_TX_AT )); then
|
||||
log "keeper tick cooling down until $(date -d "@$NEXT_KEEPER_TX_AT" -Iseconds)"
|
||||
return 0
|
||||
fi
|
||||
local k="${PRICE_FEED_KEEPER_ADDRESS:-}"
|
||||
[ -n "$k" ] && [ -n "$KEEPER_PK" ] || { log "keeper tick skipped (set PRICE_FEED_KEEPER_ADDRESS + KEEPER_PRIVATE_KEY)"; return 0; }
|
||||
if account_has_pending_nonce_gap "$KEEPER_ADDR"; then
|
||||
NEXT_KEEPER_TX_AT=$(( now + MESH_TX_BACKOFF_SEC ))
|
||||
log "keeper tx already pending for $KEEPER_ADDR; backoff ${MESH_TX_BACKOFF_SEC}s"
|
||||
return 0
|
||||
fi
|
||||
local raw dec first
|
||||
raw="$(cast rpc eth_call "{\"to\":\"$k\",\"data\":\"$(cast calldata "checkUpkeep()")\"}" latest --rpc-url "$RPC" 2>/dev/null | tr -d '\n\"')" || return 0
|
||||
dec="$(cast abi-decode "checkUpkeep()(bool,address[])" "$raw" 2>/dev/null)" || return 0
|
||||
@@ -107,9 +168,20 @@ tick_keeper() {
|
||||
log "[dry-run] cast send performUpkeep"
|
||||
return 0
|
||||
fi
|
||||
if ! cast send "$k" "performUpkeep()" --rpc-url "$RPC" --private-key "$KEEPER_PK" \
|
||||
--legacy --gas-limit 500000 --gas-price "$MESH_CAST_GAS_PRICE"; then
|
||||
log "WARN: performUpkeep failed (RPC / gas / nonce); next tick in ${INTERVAL}s"
|
||||
local out rc
|
||||
set +e
|
||||
out="$(cast send "$k" "performUpkeep()" --rpc-url "$RPC" --private-key "$KEEPER_PK" \
|
||||
--legacy --gas-limit 500000 --gas-price "$MESH_CAST_GAS_PRICE" 2>&1)"
|
||||
rc=$?
|
||||
set -e
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
echo "$out"
|
||||
if is_retryable_tx_error "$out"; then
|
||||
NEXT_KEEPER_TX_AT=$(( now + MESH_TX_BACKOFF_SEC ))
|
||||
log "WARN: performUpkeep pending/underpriced; keeper backoff ${MESH_TX_BACKOFF_SEC}s"
|
||||
else
|
||||
log "WARN: performUpkeep failed (RPC / gas / nonce); next tick in ${INTERVAL}s"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log "keeper checkUpkeep=false (no tx)"
|
||||
@@ -118,14 +190,31 @@ tick_keeper() {
|
||||
|
||||
tick_oracle() {
|
||||
[ "$ENABLE_ORACLE" = "1" ] || return 0
|
||||
local now
|
||||
now="$(date +%s)"
|
||||
if (( now < NEXT_ORACLE_TX_AT )); then
|
||||
log "oracle tick cooling down until $(date -d "@$NEXT_ORACLE_TX_AT" -Iseconds)"
|
||||
return 0
|
||||
fi
|
||||
[ -n "$ORACLE_PK" ] || { log "oracle tick skipped (set PRIVATE_KEY)"; return 0; }
|
||||
if [ -n "${DRY_RUN:-}" ]; then
|
||||
log "[dry-run] update-oracle-price.sh"
|
||||
return 0
|
||||
fi
|
||||
# Exits 0 when price unchanged (<1%) or on success; failures must not stop the loop
|
||||
if ! bash "$SMOM_ROOT/scripts/update-oracle-price.sh" "$RPC"; then
|
||||
log "WARN: update-oracle-price.sh failed (rate limit / RPC / gas); next tick in ${INTERVAL}s"
|
||||
local out rc
|
||||
set +e
|
||||
out="$(bash "$SMOM_ROOT/scripts/update-oracle-price.sh" "$RPC" 2>&1)"
|
||||
rc=$?
|
||||
set -e
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
echo "$out"
|
||||
if is_retryable_tx_error "$out"; then
|
||||
NEXT_ORACLE_TX_AT=$(( now + MESH_TX_BACKOFF_SEC ))
|
||||
log "WARN: oracle tx pending/underpriced; oracle backoff ${MESH_TX_BACKOFF_SEC}s"
|
||||
else
|
||||
log "WARN: update-oracle-price.sh failed (rate limit / RPC / gas); next tick in ${INTERVAL}s"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user