chore: update .env.master.example with new deployment scripts and treasury manager parameters; enhance AGENTS.md with GRU reference primacy details
- Added new deployment script references for Aave quote-push and treasury manager in .env.master.example. - Updated AGENTS.md to include information on GRU reference primacy versus public PMM mesh execution model. - Minor updates to various documentation files to reflect changes in policy and operational guidelines. Made-with: Cursor
This commit is contained in:
107
scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh
Normal file
107
scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Deploy only the Mainnet Aave quote-push receiver.
|
||||
# Default: simulation only. Use --apply to broadcast.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required
|
||||
# AAVE_POOL_ADDRESS optional; defaults inside the Forge script
|
||||
# QUOTE_PUSH_RECEIVER_OWNER optional; defaults to deployer derived from PRIVATE_KEY
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --dry-run
|
||||
# bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_pool="${AAVE_POOL_ADDRESS-}"
|
||||
_qp_owner="${QUOTE_PUSH_RECEIVER_OWNER-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_pool" ]] && export AAVE_POOL_ADDRESS="$_qp_pool"
|
||||
[[ -n "$_qp_owner" ]] && export QUOTE_PUSH_RECEIVER_OWNER="$_qp_owner"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_pool _qp_owner
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local name="$1"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "[fail] missing required env: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_receiver() {
|
||||
local mode="$1"
|
||||
local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json"
|
||||
if [[ "$mode" == "dry-run" ]]; then
|
||||
latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/dry-run/run-latest.json"
|
||||
fi
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
require_cmd forge
|
||||
|
||||
MODE="dry-run"
|
||||
BROADCAST=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run"; BROADCAST=() ;;
|
||||
--apply) MODE="apply"; BROADCAST=(--broadcast) ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env PRIVATE_KEY
|
||||
require_env ETHEREUM_MAINNET_RPC
|
||||
|
||||
echo "=== deploy-mainnet-aave-quote-push-receiver ($MODE) ==="
|
||||
if [[ -n "${QUOTE_PUSH_RECEIVER_OWNER:-}" ]]; then
|
||||
echo "receiver_owner=$QUOTE_PUSH_RECEIVER_OWNER"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$SMOM"
|
||||
forge script script/deploy/DeployAaveQuotePushFlashReceiver.s.sol:DeployAaveQuotePushFlashReceiver \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
"${BROADCAST[@]}" \
|
||||
-vvvv
|
||||
)
|
||||
|
||||
receiver_addr="$(pick_latest_receiver "$MODE" || true)"
|
||||
echo
|
||||
if [[ "$MODE" == "dry-run" ]]; then
|
||||
echo "Projected receiver address from this dry-run:"
|
||||
else
|
||||
echo "After --apply: copy deployed address into .env:"
|
||||
fi
|
||||
echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...}"
|
||||
echo "Shortest manager handoff:"
|
||||
echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...} QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply"
|
||||
echo "Full stack alternative:"
|
||||
echo " bash scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh --apply"
|
||||
@@ -3,6 +3,7 @@ set -euo pipefail
|
||||
|
||||
# Deploy Mainnet flash quote-push stack (Aave receiver + external unwinder).
|
||||
# Default: simulation only (no --broadcast). Use --apply to broadcast.
|
||||
# For receiver-only migrations, use deploy-mainnet-aave-quote-push-receiver.sh.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC
|
||||
@@ -165,6 +166,8 @@ unwinder_addr="$(pick_latest_create_address "$unwinder_script" "$unwinder_contra
|
||||
echo "After --apply: copy deployed addresses into .env:"
|
||||
echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...}"
|
||||
echo " QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET=${unwinder_addr:-...}"
|
||||
echo "Optional retained-surplus manager:"
|
||||
echo " QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply"
|
||||
echo "Or rerun immediately with QUOTE_PUSH_UNWINDER_TYPE=${UNW} so run-mainnet-aave-cwusdc-quote-push-once.sh can auto-pick the latest broadcast unwinder."
|
||||
echo "Then set FLASH_QUOTE_AMOUNT_RAW, UNWIND_MODE, UNWIND_V3_FEE_U24 (or UNWIND_DODO_POOL / two-hop vars) and run:"
|
||||
echo " bash scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh --dry-run"
|
||||
|
||||
137
scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh
Normal file
137
scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh
Normal file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Deploy the Mainnet quote-push treasury manager and optionally transfer the
|
||||
# receiver ownership to it. Default: simulation only. Use --apply to broadcast.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required
|
||||
# AAVE_QUOTE_PUSH_RECEIVER_MAINNET optional; auto-picks latest receiver broadcast
|
||||
# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC
|
||||
# QUOTE_PUSH_TREASURY_OWNER optional; defaults to deployer
|
||||
# QUOTE_PUSH_TREASURY_OPERATOR optional; defaults to owner
|
||||
# QUOTE_PUSH_TREASURY_GAS_RECIPIENT optional; defaults to owner
|
||||
# QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT optional; defaults to owner
|
||||
# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; defaults to 0
|
||||
# QUOTE_PUSH_TREASURY_RESERVE_RAW optional; defaults to 0
|
||||
# QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP optional; 1 transfers receiver ownership to manager
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --dry-run
|
||||
# QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 \
|
||||
# bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}"
|
||||
_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}"
|
||||
_qp_owner="${QUOTE_PUSH_TREASURY_OWNER-}"
|
||||
_qp_operator="${QUOTE_PUSH_TREASURY_OPERATOR-}"
|
||||
_qp_gas_recipient="${QUOTE_PUSH_TREASURY_GAS_RECIPIENT-}"
|
||||
_qp_recycle_recipient="${QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT-}"
|
||||
_qp_receiver_reserve="${QUOTE_PUSH_RECEIVER_RESERVE_RAW-}"
|
||||
_qp_manager_reserve="${QUOTE_PUSH_TREASURY_RESERVE_RAW-}"
|
||||
_qp_take_receiver="${QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver"
|
||||
[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token"
|
||||
[[ -n "$_qp_owner" ]] && export QUOTE_PUSH_TREASURY_OWNER="$_qp_owner"
|
||||
[[ -n "$_qp_operator" ]] && export QUOTE_PUSH_TREASURY_OPERATOR="$_qp_operator"
|
||||
[[ -n "$_qp_gas_recipient" ]] && export QUOTE_PUSH_TREASURY_GAS_RECIPIENT="$_qp_gas_recipient"
|
||||
[[ -n "$_qp_recycle_recipient" ]] && export QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT="$_qp_recycle_recipient"
|
||||
[[ -n "$_qp_receiver_reserve" ]] && export QUOTE_PUSH_RECEIVER_RESERVE_RAW="$_qp_receiver_reserve"
|
||||
[[ -n "$_qp_manager_reserve" ]] && export QUOTE_PUSH_TREASURY_RESERVE_RAW="$_qp_manager_reserve"
|
||||
[[ -n "$_qp_take_receiver" ]] && export QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP="$_qp_take_receiver"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_receiver _qp_token _qp_owner _qp_operator _qp_gas_recipient
|
||||
unset _qp_recycle_recipient _qp_receiver_reserve _qp_manager_reserve _qp_take_receiver
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local name="$1"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "[fail] missing required env: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_create_address() {
|
||||
local script_name="$1"
|
||||
local contract_name="$2"
|
||||
local mode="${3:-apply}"
|
||||
local latest_json="${SMOM}/broadcast/${script_name}/1/run-latest.json"
|
||||
if [[ "$mode" == "dry-run" ]]; then
|
||||
latest_json="${SMOM}/broadcast/${script_name}/1/dry-run/run-latest.json"
|
||||
fi
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r --arg contract "$contract_name" \
|
||||
'.transactions[]? | select(.transactionType == "CREATE" and .contractName == $contract) | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
require_cmd forge
|
||||
|
||||
MODE="dry-run"
|
||||
BROADCAST=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run"; BROADCAST=() ;;
|
||||
--apply) MODE="apply"; BROADCAST=(--broadcast) ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env PRIVATE_KEY
|
||||
require_env ETHEREUM_MAINNET_RPC
|
||||
if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then
|
||||
inferred_receiver="$(pick_latest_create_address "DeployAaveQuotePushFlashReceiver.s.sol" "AaveQuotePushFlashReceiver" "apply" || true)"
|
||||
if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then
|
||||
export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver"
|
||||
fi
|
||||
fi
|
||||
require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
|
||||
echo "=== deploy-mainnet-quote-push-treasury-manager ($MODE) ==="
|
||||
echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET"
|
||||
echo "take_receiver_ownership=${QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP:-0}"
|
||||
|
||||
(
|
||||
cd "$SMOM"
|
||||
forge script script/deploy/DeployQuotePushTreasuryManager.s.sol:DeployQuotePushTreasuryManager \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
"${BROADCAST[@]}" \
|
||||
-vvvv
|
||||
)
|
||||
|
||||
manager_addr="$(pick_latest_create_address "DeployQuotePushTreasuryManager.s.sol" "QuotePushTreasuryManager" "$MODE" || true)"
|
||||
echo
|
||||
if [[ "$MODE" == "dry-run" ]]; then
|
||||
echo "Projected treasury manager address from this dry-run:"
|
||||
else
|
||||
echo "After --apply: copy deployed addresses into .env:"
|
||||
fi
|
||||
echo " QUOTE_PUSH_TREASURY_MANAGER_MAINNET=${manager_addr:-...}"
|
||||
echo "Optional keeper entrypoint:"
|
||||
echo " bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --dry-run"
|
||||
124
scripts/deployment/manage-mainnet-quote-push-treasury.sh
Normal file
124
scripts/deployment/manage-mainnet-quote-push-treasury.sh
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Harvest receiver surplus into the treasury manager and/or distribute quote to
|
||||
# the configured gas and recycle recipients. Default: simulation only.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required
|
||||
# QUOTE_PUSH_TREASURY_MANAGER_MAINNET optional; auto-picks latest manager broadcast
|
||||
# QUOTE_PUSH_TREASURY_HARVEST optional; defaults to 1
|
||||
# QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW optional; defaults to 0
|
||||
# QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW optional; defaults to 0
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/deployment/manage-mainnet-quote-push-treasury.sh --dry-run
|
||||
# QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW=1000 \
|
||||
# QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW=2000 \
|
||||
# bash scripts/deployment/manage-mainnet-quote-push-treasury.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}"
|
||||
_qp_harvest="${QUOTE_PUSH_TREASURY_HARVEST-}"
|
||||
_qp_gas_raw="${QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW-}"
|
||||
_qp_recycle_raw="${QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager"
|
||||
[[ -n "$_qp_harvest" ]] && export QUOTE_PUSH_TREASURY_HARVEST="$_qp_harvest"
|
||||
[[ -n "$_qp_gas_raw" ]] && export QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW="$_qp_gas_raw"
|
||||
[[ -n "$_qp_recycle_raw" ]] && export QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW="$_qp_recycle_raw"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_manager _qp_harvest _qp_gas_raw _qp_recycle_raw
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local name="$1"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "[fail] missing required env: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_manager() {
|
||||
local latest_json="${SMOM}/broadcast/DeployQuotePushTreasuryManager.s.sol/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "QuotePushTreasuryManager") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
require_cmd cast
|
||||
require_cmd forge
|
||||
|
||||
MODE="dry-run"
|
||||
BROADCAST=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run"; BROADCAST=() ;;
|
||||
--apply) MODE="apply"; BROADCAST=(--broadcast) ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env PRIVATE_KEY
|
||||
require_env ETHEREUM_MAINNET_RPC
|
||||
if [[ -z "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then
|
||||
inferred_manager="$(pick_latest_manager || true)"
|
||||
if [[ -n "$inferred_manager" && "$inferred_manager" != "null" ]]; then
|
||||
export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$inferred_manager"
|
||||
fi
|
||||
fi
|
||||
require_env QUOTE_PUSH_TREASURY_MANAGER_MAINNET
|
||||
|
||||
DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
||||
manager_owner="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
manager_operator="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'operator()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
if [[ "${manager_owner,,}" != "${DEPLOYER,,}" && "${manager_operator,,}" != "${DEPLOYER,,}" ]]; then
|
||||
echo "[fail] deployer $DEPLOYER is neither manager owner ($manager_owner) nor operator ($manager_operator)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
quote_balance="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'quoteBalance()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
available_quote="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'availableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
receiver_sweepable="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'receiverSweepableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
|
||||
echo "=== manage-mainnet-quote-push-treasury ($MODE) ==="
|
||||
echo "manager=$QUOTE_PUSH_TREASURY_MANAGER_MAINNET"
|
||||
echo "manager_owner=$manager_owner"
|
||||
echo "manager_operator=$manager_operator"
|
||||
echo "harvest=${QUOTE_PUSH_TREASURY_HARVEST:-1}"
|
||||
echo "gas_distribution_raw=${QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW:-0}"
|
||||
echo "recycle_distribution_raw=${QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW:-0}"
|
||||
echo "quote_balance_raw=$quote_balance"
|
||||
echo "available_quote_raw=$available_quote"
|
||||
echo "receiver_sweepable_raw=$receiver_sweepable"
|
||||
|
||||
(
|
||||
cd "$SMOM"
|
||||
forge script script/flash/ManageQuotePushTreasuryManager.s.sol:ManageQuotePushTreasuryManager \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
"${BROADCAST[@]}" \
|
||||
-vvvv
|
||||
)
|
||||
@@ -10,6 +10,8 @@ set -euo pipefail
|
||||
# (Aave flashLoan USDC → PMM swap USDC→cWUSDC → external unwind cWUSDC→USDC
|
||||
# → repay Aave + premium). Each successful round **raises PMM quote reserves** and
|
||||
# **draws base** from the pool, moving base-heavy / quote-thin books toward peg.
|
||||
# Retained quote surplus stays on the receiver until swept by the owner and can
|
||||
# then be recycled into wallet-funded pool growth.
|
||||
#
|
||||
# This script is read-only + local modeling:
|
||||
# - reads live pool reserves (cast)
|
||||
@@ -102,7 +104,12 @@ echo
|
||||
echo "4) Reserve peg monitor after any live work:"
|
||||
echo " bash scripts/verify/check-mainnet-cwusdc-usdc-reserve-peg.sh"
|
||||
echo
|
||||
echo "5) Pick a valid Uniswap V3 unwind (no guessing fee tiers):"
|
||||
echo "5) Receiver surplus accounting and recycle path:"
|
||||
echo " bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
echo " bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --dry-run"
|
||||
echo " bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run"
|
||||
echo
|
||||
echo "6) Pick a valid Uniswap V3 unwind (no guessing fee tiers):"
|
||||
echo " bash scripts/verify/probe-uniswap-v3-cwusdc-usdc-mainnet.sh"
|
||||
echo " If no pool: UNWIND_MODE=2 — build path: bash scripts/verify/build-uniswap-v3-exact-input-path-hex.sh ... (VERIFY_POOLS=1 optional)"
|
||||
echo " Calculations report (dry-run snapshots): reports/status/mainnet_cwusdc_usdc_quote_push_calculations_2026-04-12.md"
|
||||
|
||||
@@ -185,8 +185,11 @@ _pmm_fund_grid_err() {
|
||||
trap '_pmm_fund_grid_err' ERR
|
||||
|
||||
_chunk_wall_start="$SECONDS"
|
||||
_prog_every="${PMM_SOAK_FUND_PROGRESS_EVERY:-50}"
|
||||
[[ "$_prog_every" =~ ^[0-9]+$ ]] || _prog_every=50
|
||||
# Avoid names starting with "_" inside (( )) under set -u (some shells/envs treat expansion oddly).
|
||||
fund_progress_every=50
|
||||
if [[ -n "${PMM_SOAK_FUND_PROGRESS_EVERY:-}" && "${PMM_SOAK_FUND_PROGRESS_EVERY}" =~ ^[0-9]+$ ]]; then
|
||||
fund_progress_every="${PMM_SOAK_FUND_PROGRESS_EVERY}"
|
||||
fi
|
||||
n=0
|
||||
for r in "${RECIPIENTS[@]}"; do
|
||||
n=$((n + 1))
|
||||
@@ -197,10 +200,12 @@ for r in "${RECIPIENTS[@]}"; do
|
||||
cast send "$TOKEN_ADDR" 'transfer(address,uint256)(bool)' "$r" "$AMOUNT" \
|
||||
--rpc-url "$RPC" --private-key "$PK" --legacy --gas-price "$GAS_WEI"
|
||||
fi
|
||||
if [[ "$_prog_every" -gt 0 ]] && (( n % _prog_every == 0 || n == total )); then
|
||||
_el=$((SECONDS - _chunk_wall_start))
|
||||
python3 -c "n=$n;total=$total;el=$_el;avg=el/n if n else 0.0;rem=total-n;eta=int(rem*avg) if rem>0 else 0;print(f'[fund-grid] progress {n}/{total} chunk_elapsed_s={el} avg_s_per_tx={avg:.2f} est_remaining_this_chunk_s={eta}')" 2>/dev/null || true
|
||||
elif [[ "$_prog_every" -eq 0 ]] && [[ "$n" -eq "$total" ]]; then
|
||||
if [[ "${fund_progress_every}" -gt 0 ]]; then
|
||||
if (( n % fund_progress_every == 0 )) || (( n == total )); then
|
||||
_el=$((SECONDS - _chunk_wall_start))
|
||||
python3 -c "n=$n;total=$total;el=$_el;avg=el/n if n else 0.0;rem=total-n;eta=int(rem*avg) if rem>0 else 0;print(f'[fund-grid] progress {n}/{total} chunk_elapsed_s={el} avg_s_per_tx={avg:.2f} est_remaining_this_chunk_s={eta}')" 2>/dev/null || true
|
||||
fi
|
||||
elif [[ "$n" -eq "$total" ]]; then
|
||||
echo "[fund-grid] progress ${n}/${total} chunk_elapsed_s=$((SECONDS - _chunk_wall_start)) (final)"
|
||||
fi
|
||||
done
|
||||
|
||||
155
scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh
Normal file
155
scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh
Normal file
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Sweep retained quote surplus from the receiver to the deployer and, when the
|
||||
# deployer gas reserve is healthy, immediately recycle that quote into the
|
||||
# wallet-funded cWUSDC/USDC peg tranche helper.
|
||||
#
|
||||
# Default: simulation only. Use --apply to broadcast / execute.
|
||||
#
|
||||
# Env:
|
||||
# ETHEREUM_MAINNET_RPC required
|
||||
# PRIVATE_KEY required
|
||||
# AAVE_QUOTE_PUSH_RECEIVER_MAINNET required
|
||||
# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC
|
||||
# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; amount to keep on receiver after sweep
|
||||
# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH optional; default 0.003
|
||||
# QUOTE_PUSH_OPERATION_BUFFER_ETH optional; default 0.0005
|
||||
# QUOTE_PUSH_NATIVE_TOKEN_PRICE optional; default 3200
|
||||
#
|
||||
# Usage:
|
||||
# source scripts/lib/load-project-env.sh
|
||||
# bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run
|
||||
# bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local name="$1"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "[fail] missing required env: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_receiver() {
|
||||
local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
require_cmd cast
|
||||
require_cmd python3
|
||||
|
||||
MODE="dry-run"
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run" ;;
|
||||
--apply) MODE="apply" ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env ETHEREUM_MAINNET_RPC
|
||||
require_env PRIVATE_KEY
|
||||
if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then
|
||||
inferred_receiver="$(pick_latest_receiver || true)"
|
||||
if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then
|
||||
export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver"
|
||||
fi
|
||||
fi
|
||||
require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
|
||||
DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
||||
TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}"
|
||||
RECEIVER_RESERVE_RAW="${QUOTE_PUSH_RECEIVER_RESERVE_RAW:-0}"
|
||||
GAS_FLOOR_ETH="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH:-0.003}"
|
||||
OP_BUFFER_ETH="${QUOTE_PUSH_OPERATION_BUFFER_ETH:-0.0005}"
|
||||
NATIVE_TOKEN_PRICE="${QUOTE_PUSH_NATIVE_TOKEN_PRICE:-3200}"
|
||||
|
||||
deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")"
|
||||
receiver_quote_raw="$(cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
|
||||
read -r sweepable_raw gas_shortfall_eth <<EOF
|
||||
$(python3 - "$deployer_eth" "$receiver_quote_raw" "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" <<'PY'
|
||||
import sys
|
||||
|
||||
deployer_eth = float(sys.argv[1])
|
||||
receiver_quote_raw = int(sys.argv[2])
|
||||
receiver_reserve_raw = int(sys.argv[3])
|
||||
gas_floor_eth = float(sys.argv[4])
|
||||
op_buffer_eth = float(sys.argv[5])
|
||||
|
||||
sweepable_raw = max(0, receiver_quote_raw - receiver_reserve_raw)
|
||||
gas_shortfall_eth = max(0.0, gas_floor_eth + op_buffer_eth - deployer_eth)
|
||||
|
||||
print(sweepable_raw, gas_shortfall_eth)
|
||||
PY
|
||||
)
|
||||
EOF
|
||||
|
||||
gas_floor_breached="$(
|
||||
python3 - "$gas_shortfall_eth" <<'PY'
|
||||
import sys
|
||||
print("yes" if float(sys.argv[1]) > 0 else "no")
|
||||
PY
|
||||
)"
|
||||
|
||||
echo "=== recycle-mainnet-aave-quote-push-surplus ($MODE) ==="
|
||||
echo "deployer=$DEPLOYER"
|
||||
echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET"
|
||||
echo "token=$TOKEN"
|
||||
echo "receiver_quote_raw=$receiver_quote_raw"
|
||||
echo "receiver_reserve_raw=$RECEIVER_RESERVE_RAW"
|
||||
echo "sweepable_raw=$sweepable_raw"
|
||||
echo "deployer_eth=$deployer_eth"
|
||||
echo "gas_floor_eth=$GAS_FLOOR_ETH"
|
||||
echo "operation_buffer_eth=$OP_BUFFER_ETH"
|
||||
echo "native_token_price=$NATIVE_TOKEN_PRICE"
|
||||
|
||||
bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
|
||||
if (( sweepable_raw == 0 )); then
|
||||
echo "[stop] no sweepable receiver surplus is available" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if [[ "$MODE" == "dry-run" ]]; then
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh" --dry-run
|
||||
if [[ "$gas_floor_breached" == "yes" ]]; then
|
||||
echo "[stop] deployer gas reserve is below recycle floor; sweep can proceed, but pool recycle is intentionally skipped"
|
||||
exit 0
|
||||
fi
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --dry-run
|
||||
exit 0
|
||||
fi
|
||||
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh" --apply
|
||||
|
||||
if [[ "$gas_floor_breached" == "yes" ]]; then
|
||||
echo "[stop] swept surplus to deployer, but deployer ETH is still below recycle floor; skipping pool-growth tranche"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --apply
|
||||
@@ -285,3 +285,4 @@ echo "flash_quote_amount_raw=$FLASH_QUOTE_AMOUNT_RAW unwind_mode=$UM"
|
||||
)
|
||||
|
||||
echo "Done. Re-check: bash scripts/verify/check-mainnet-cwusdc-usdc-reserve-peg.sh"
|
||||
echo "Receiver surplus accounting: bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
|
||||
356
scripts/deployment/run-mainnet-aave-quote-push-keeper.sh
Normal file
356
scripts/deployment/run-mainnet-aave-quote-push-keeper.sh
Normal file
@@ -0,0 +1,356 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Single entrypoint for the quote-push maintenance loop:
|
||||
# 1. plan current accounting / gas policy
|
||||
# 2. execute one flash quote-push
|
||||
# 3. recycle retained quote via treasury manager or direct sweep fallback
|
||||
#
|
||||
# Default: simulation only. Use --apply to broadcast / execute.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required
|
||||
# DODO_PMM_INTEGRATION_MAINNET required unless QUOTE_PUSH_KEEPER_SKIP_FLASH=1
|
||||
# QUOTE_PUSH_TREASURY_MANAGER_MAINNET optional; when set, manager path is preferred
|
||||
# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC
|
||||
# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; defaults to 0
|
||||
# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH optional; defaults to 0.003
|
||||
# QUOTE_PUSH_OPERATION_BUFFER_ETH optional; defaults to 0.0005
|
||||
# QUOTE_PUSH_NATIVE_TOKEN_PRICE optional; defaults to 3200
|
||||
# QUOTE_PUSH_KEEPER_SKIP_FLASH optional; default 0
|
||||
# QUOTE_PUSH_KEEPER_SKIP_RECYCLE optional; default 0
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --dry-run
|
||||
# bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}"
|
||||
_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}"
|
||||
_qp_receiver_reserve="${QUOTE_PUSH_RECEIVER_RESERVE_RAW-}"
|
||||
_qp_gas_floor="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH-}"
|
||||
_qp_gas_buffer="${QUOTE_PUSH_OPERATION_BUFFER_ETH-}"
|
||||
_qp_native_price="${QUOTE_PUSH_NATIVE_TOKEN_PRICE-}"
|
||||
_qp_skip_flash="${QUOTE_PUSH_KEEPER_SKIP_FLASH-}"
|
||||
_qp_skip_recycle="${QUOTE_PUSH_KEEPER_SKIP_RECYCLE-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager"
|
||||
[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token"
|
||||
[[ -n "$_qp_receiver_reserve" ]] && export QUOTE_PUSH_RECEIVER_RESERVE_RAW="$_qp_receiver_reserve"
|
||||
[[ -n "$_qp_gas_floor" ]] && export QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH="$_qp_gas_floor"
|
||||
[[ -n "$_qp_gas_buffer" ]] && export QUOTE_PUSH_OPERATION_BUFFER_ETH="$_qp_gas_buffer"
|
||||
[[ -n "$_qp_native_price" ]] && export QUOTE_PUSH_NATIVE_TOKEN_PRICE="$_qp_native_price"
|
||||
[[ -n "$_qp_skip_flash" ]] && export QUOTE_PUSH_KEEPER_SKIP_FLASH="$_qp_skip_flash"
|
||||
[[ -n "$_qp_skip_recycle" ]] && export QUOTE_PUSH_KEEPER_SKIP_RECYCLE="$_qp_skip_recycle"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_manager _qp_token _qp_receiver_reserve _qp_gas_floor
|
||||
unset _qp_gas_buffer _qp_native_price _qp_skip_flash _qp_skip_recycle
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
pick_latest_manager() {
|
||||
local latest_json="${SMOM}/broadcast/DeployQuotePushTreasuryManager.s.sol/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "QuotePushTreasuryManager") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
pick_latest_receiver() {
|
||||
local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
to_human() {
|
||||
python3 - "$1" <<'PY'
|
||||
import sys
|
||||
print(f"{int(sys.argv[1]) / 1_000_000:.6f}")
|
||||
PY
|
||||
}
|
||||
|
||||
compute_keeper_plan() {
|
||||
local manager_addr="${1:-}"
|
||||
local deployer_eth="$2"
|
||||
local token_addr="$3"
|
||||
local receiver_addr="$4"
|
||||
local receiver_reserve_raw="$5"
|
||||
local gas_floor_eth="$6"
|
||||
local gas_buffer_eth="$7"
|
||||
local native_price="$8"
|
||||
|
||||
local receiver_quote_raw=0
|
||||
local manager_quote_raw=0
|
||||
local manager_available_raw=0
|
||||
local receiver_sweepable_raw=0
|
||||
local total_controlled_raw=0
|
||||
local gas_distribution_raw=0
|
||||
local recycle_distribution_raw=0
|
||||
local gas_shortfall_eth=0
|
||||
local gas_shortfall_quote_raw=0
|
||||
local gas_recipient=""
|
||||
local recycle_recipient=""
|
||||
|
||||
if [[ -n "$manager_addr" ]]; then
|
||||
manager_quote_raw="$(cast call "$manager_addr" 'quoteBalance()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
manager_available_raw="$(cast call "$manager_addr" 'availableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
receiver_sweepable_raw="$(cast call "$manager_addr" 'receiverSweepableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
gas_recipient="$(cast call "$manager_addr" 'gasRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
recycle_recipient="$(cast call "$manager_addr" 'recycleRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
else
|
||||
receiver_quote_raw="$(cast call "$token_addr" 'balanceOf(address)(uint256)' "$receiver_addr" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
receiver_sweepable_raw="$(
|
||||
python3 - "$receiver_quote_raw" "$receiver_reserve_raw" <<'PY'
|
||||
import sys
|
||||
receiver_quote_raw = int(sys.argv[1])
|
||||
receiver_reserve_raw = int(sys.argv[2])
|
||||
print(max(0, receiver_quote_raw - receiver_reserve_raw))
|
||||
PY
|
||||
)"
|
||||
fi
|
||||
|
||||
eval "$(
|
||||
python3 - "$deployer_eth" "$gas_floor_eth" "$gas_buffer_eth" "$native_price" \
|
||||
"${manager_available_raw:-0}" "${receiver_sweepable_raw:-0}" <<'PY'
|
||||
import math
|
||||
import sys
|
||||
|
||||
deployer_eth = float(sys.argv[1])
|
||||
gas_floor_eth = float(sys.argv[2])
|
||||
gas_buffer_eth = float(sys.argv[3])
|
||||
native_price = float(sys.argv[4])
|
||||
manager_available_raw = int(sys.argv[5])
|
||||
receiver_sweepable_raw = int(sys.argv[6])
|
||||
|
||||
gas_shortfall_eth = max(0.0, gas_floor_eth + gas_buffer_eth - deployer_eth)
|
||||
gas_shortfall_quote_raw = math.ceil(gas_shortfall_eth * native_price * 1_000_000)
|
||||
total_controlled_raw = manager_available_raw + receiver_sweepable_raw
|
||||
gas_distribution_raw = min(total_controlled_raw, gas_shortfall_quote_raw)
|
||||
recycle_distribution_raw = max(0, total_controlled_raw - gas_distribution_raw)
|
||||
|
||||
print(f"GAS_SHORTFALL_ETH={gas_shortfall_eth}")
|
||||
print(f"GAS_SHORTFALL_QUOTE_RAW={gas_shortfall_quote_raw}")
|
||||
print(f"TOTAL_CONTROLLED_RAW={total_controlled_raw}")
|
||||
print(f"GAS_DISTRIBUTION_RAW={gas_distribution_raw}")
|
||||
print(f"RECYCLE_DISTRIBUTION_RAW={recycle_distribution_raw}")
|
||||
PY
|
||||
)"
|
||||
|
||||
KEEPER_MANAGER_QUOTE_RAW="${manager_quote_raw:-0}"
|
||||
KEEPER_MANAGER_AVAILABLE_RAW="${manager_available_raw:-0}"
|
||||
KEEPER_RECEIVER_QUOTE_RAW="${receiver_quote_raw:-0}"
|
||||
KEEPER_RECEIVER_SWEEPABLE_RAW="${receiver_sweepable_raw:-0}"
|
||||
KEEPER_TOTAL_CONTROLLED_RAW="${TOTAL_CONTROLLED_RAW:-0}"
|
||||
KEEPER_GAS_SHORTFALL_ETH="${GAS_SHORTFALL_ETH:-0}"
|
||||
KEEPER_GAS_SHORTFALL_QUOTE_RAW="${GAS_SHORTFALL_QUOTE_RAW:-0}"
|
||||
KEEPER_GAS_DISTRIBUTION_RAW="${GAS_DISTRIBUTION_RAW:-0}"
|
||||
KEEPER_RECYCLE_DISTRIBUTION_RAW="${RECYCLE_DISTRIBUTION_RAW:-0}"
|
||||
KEEPER_GAS_RECIPIENT="${gas_recipient:-}"
|
||||
KEEPER_RECYCLE_RECIPIENT="${recycle_recipient:-}"
|
||||
}
|
||||
|
||||
require_cmd cast
|
||||
require_cmd python3
|
||||
require_cmd forge
|
||||
|
||||
MODE="dry-run"
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run" ;;
|
||||
--apply) MODE="apply" ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "${PRIVATE_KEY:-}" || -z "${ETHEREUM_MAINNET_RPC:-}" ]]; then
|
||||
echo "[fail] PRIVATE_KEY and ETHEREUM_MAINNET_RPC are required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then
|
||||
inferred_manager="$(pick_latest_manager || true)"
|
||||
if [[ -n "$inferred_manager" && "$inferred_manager" != "null" ]]; then
|
||||
export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$inferred_manager"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then
|
||||
inferred_receiver="$(pick_latest_receiver || true)"
|
||||
if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then
|
||||
export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver"
|
||||
fi
|
||||
fi
|
||||
|
||||
SKIP_FLASH="${QUOTE_PUSH_KEEPER_SKIP_FLASH:-0}"
|
||||
SKIP_RECYCLE="${QUOTE_PUSH_KEEPER_SKIP_RECYCLE:-0}"
|
||||
TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}"
|
||||
RECEIVER="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}"
|
||||
RECEIVER_RESERVE_RAW="${QUOTE_PUSH_RECEIVER_RESERVE_RAW:-0}"
|
||||
GAS_FLOOR_ETH="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH:-0.003}"
|
||||
OP_BUFFER_ETH="${QUOTE_PUSH_OPERATION_BUFFER_ETH:-0.0005}"
|
||||
NATIVE_TOKEN_PRICE="${QUOTE_PUSH_NATIVE_TOKEN_PRICE:-3200}"
|
||||
DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
||||
MANAGER="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}"
|
||||
|
||||
echo "=== run-mainnet-aave-quote-push-keeper ($MODE) ==="
|
||||
echo "deployer=$DEPLOYER"
|
||||
echo "manager=${MANAGER:-<direct-receiver-path>}"
|
||||
echo "skip_flash=$SKIP_FLASH"
|
||||
echo "skip_recycle=$SKIP_RECYCLE"
|
||||
|
||||
bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
|
||||
deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")"
|
||||
compute_keeper_plan "$MANAGER" "$deployer_eth" "$TOKEN" "$RECEIVER" "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" "$NATIVE_TOKEN_PRICE"
|
||||
|
||||
echo
|
||||
echo "=== Keeper policy plan ==="
|
||||
echo "deployer_eth=$deployer_eth"
|
||||
echo "gas_shortfall_eth=$KEEPER_GAS_SHORTFALL_ETH"
|
||||
echo "gas_shortfall_quote_raw=$KEEPER_GAS_SHORTFALL_QUOTE_RAW human=$(to_human "$KEEPER_GAS_SHORTFALL_QUOTE_RAW")"
|
||||
if [[ -n "$MANAGER" ]]; then
|
||||
echo "manager_quote_raw=$KEEPER_MANAGER_QUOTE_RAW human=$(to_human "$KEEPER_MANAGER_QUOTE_RAW")"
|
||||
echo "manager_available_raw=$KEEPER_MANAGER_AVAILABLE_RAW human=$(to_human "$KEEPER_MANAGER_AVAILABLE_RAW")"
|
||||
echo "receiver_sweepable_raw=$KEEPER_RECEIVER_SWEEPABLE_RAW human=$(to_human "$KEEPER_RECEIVER_SWEEPABLE_RAW")"
|
||||
echo "gas_recipient=${KEEPER_GAS_RECIPIENT:-<unset>}"
|
||||
echo "recycle_recipient=${KEEPER_RECYCLE_RECIPIENT:-<unset>}"
|
||||
else
|
||||
echo "receiver_quote_raw=$KEEPER_RECEIVER_QUOTE_RAW human=$(to_human "$KEEPER_RECEIVER_QUOTE_RAW")"
|
||||
echo "receiver_sweepable_raw=$KEEPER_RECEIVER_SWEEPABLE_RAW human=$(to_human "$KEEPER_RECEIVER_SWEEPABLE_RAW")"
|
||||
fi
|
||||
echo "total_controlled_raw=$KEEPER_TOTAL_CONTROLLED_RAW human=$(to_human "$KEEPER_TOTAL_CONTROLLED_RAW")"
|
||||
echo "planned_gas_distribution_raw=$KEEPER_GAS_DISTRIBUTION_RAW human=$(to_human "$KEEPER_GAS_DISTRIBUTION_RAW")"
|
||||
echo "planned_recycle_distribution_raw=$KEEPER_RECYCLE_DISTRIBUTION_RAW human=$(to_human "$KEEPER_RECYCLE_DISTRIBUTION_RAW")"
|
||||
|
||||
if [[ "$SKIP_RECYCLE" != "1" ]]; then
|
||||
if [[ -n "$MANAGER" ]]; then
|
||||
manager_receiver_owned="$(cast call "$MANAGER" 'isReceiverOwnedByManager()(bool)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')"
|
||||
if [[ "$manager_receiver_owned" != "true" ]]; then
|
||||
cat >&2 <<EOF
|
||||
[fail] treasury manager is not the receiver owner, so it cannot harvest retained quote yet
|
||||
[hint] Deploy or transfer ownership with:
|
||||
bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply
|
||||
AAVE_QUOTE_PUSH_RECEIVER_MAINNET=<new_receiver> QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
receiver_owner="$(cast call "$RECEIVER" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)"
|
||||
if [[ -z "$receiver_owner" ]]; then
|
||||
cat >&2 <<EOF
|
||||
[fail] receiver does not expose owner()/sweep support: ${RECEIVER:-<unset>}
|
||||
[hint] Redeploy the updated receiver, then hand it to the treasury manager:
|
||||
bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply
|
||||
AAVE_QUOTE_PUSH_RECEIVER_MAINNET=<new_receiver> QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$MODE" == "dry-run" && -n "$MANAGER" ]]; then
|
||||
export QUOTE_PUSH_TREASURY_HARVEST=1
|
||||
export QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW="$KEEPER_GAS_SHORTFALL_QUOTE_RAW"
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh" --dry-run
|
||||
|
||||
if [[ "${KEEPER_RECYCLE_RECIPIENT,,}" == "${DEPLOYER,,}" ]]; then
|
||||
echo "[plan] A live managed cycle would route recycle quote back to the deployer, after which the wallet LP helper can be attempted."
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_FLASH" != "1" ]]; then
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh" "--${MODE}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== Post-execution accounting ==="
|
||||
bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
|
||||
if [[ "$SKIP_RECYCLE" == "1" ]]; then
|
||||
echo "[stop] recycle phase skipped by QUOTE_PUSH_KEEPER_SKIP_RECYCLE=1"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")"
|
||||
compute_keeper_plan "$MANAGER" "$deployer_eth" "$TOKEN" "$RECEIVER" "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" "$NATIVE_TOKEN_PRICE"
|
||||
|
||||
if (( KEEPER_TOTAL_CONTROLLED_RAW == 0 )); then
|
||||
echo "[stop] no controllable quote is available for recycle"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -n "$MANAGER" ]]; then
|
||||
export QUOTE_PUSH_TREASURY_HARVEST="$(
|
||||
python3 - "$KEEPER_RECEIVER_SWEEPABLE_RAW" <<'PY'
|
||||
import sys
|
||||
print("1" if int(sys.argv[1]) > 0 else "0")
|
||||
PY
|
||||
)"
|
||||
export QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW="$KEEPER_GAS_DISTRIBUTION_RAW"
|
||||
export QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW="$KEEPER_RECYCLE_DISTRIBUTION_RAW"
|
||||
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/manage-mainnet-quote-push-treasury.sh" "--${MODE}"
|
||||
|
||||
if [[ "$MODE" == "dry-run" ]]; then
|
||||
if [[ "${KEEPER_RECYCLE_RECIPIENT,,}" == "${DEPLOYER,,}" && "$KEEPER_RECYCLE_DISTRIBUTION_RAW" != "0" ]]; then
|
||||
echo "[plan] After a live manager distribution to the deployer, the wallet tranche helper will be attempted."
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if python3 - "$KEEPER_GAS_SHORTFALL_ETH" <<'PY'
|
||||
import sys
|
||||
sys.exit(0 if float(sys.argv[1]) > 0 else 1)
|
||||
PY
|
||||
then
|
||||
echo "[stop] quote was distributed, but deployer ETH is still below the recycle floor; skipping wallet LP tranche"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if (( KEEPER_RECYCLE_DISTRIBUTION_RAW == 0 )); then
|
||||
echo "[stop] no recycle allocation remains after gas holdback"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "${KEEPER_RECYCLE_RECIPIENT:-}" || "${KEEPER_RECYCLE_RECIPIENT,,}" != "${DEPLOYER,,}" ]]; then
|
||||
echo "[stop] recycle recipient is not the deployer wallet, so the wallet LP helper is intentionally skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --apply; then
|
||||
status=$?
|
||||
if [[ "$status" == "3" ]]; then
|
||||
echo "[stop] recycle distribution completed, but no wallet-funded LP tranche is currently affordable"
|
||||
exit 0
|
||||
fi
|
||||
exit "$status"
|
||||
fi
|
||||
else
|
||||
bash "${PROXMOX_ROOT}/scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh" "--${MODE}"
|
||||
fi
|
||||
278
scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh
Normal file
278
scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh
Normal file
@@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Run one manager-backed Mainnet quote-push cycle:
|
||||
# flash quote-push -> harvest retained quote into manager -> distribute to configured recipients.
|
||||
#
|
||||
# Default: simulation only. Use --apply to broadcast.
|
||||
#
|
||||
# Required env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC
|
||||
# DODO_PMM_INTEGRATION_MAINNET
|
||||
# QUOTE_PUSH_TREASURY_MANAGER_MAINNET
|
||||
# AAVE_QUOTE_PUSH_RECEIVER_MAINNET optional; defaults to latest broadcast or canonical receiver
|
||||
# QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET optional; can be auto-picked from latest broadcast
|
||||
# FLASH_QUOTE_AMOUNT_RAW optional; defaults to 200000
|
||||
#
|
||||
# Optional treasury env:
|
||||
# QUOTE_PUSH_TREASURY_HARVEST optional; defaults to 1
|
||||
# QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW optional; defaults to 0
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh --dry-run
|
||||
# QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW=0 bash scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
DEFAULT_AAVE_QUOTE_PUSH_RECEIVER_MAINNET="0x241cb416aaFC2654078b7E2376adED2bDeFbCBa2"
|
||||
DEFAULT_POOL_CWUSDC_USDC_MAINNET="0x69776fc607e9edA8042e320e7e43f54d06c68f0E"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}"
|
||||
_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}"
|
||||
_qp_unwinder="${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET-}"
|
||||
_qp_amount="${FLASH_QUOTE_AMOUNT_RAW-}"
|
||||
_qp_unwind_type="${QUOTE_PUSH_UNWINDER_TYPE-}"
|
||||
_qp_unwind_mode="${UNWIND_MODE-}"
|
||||
_qp_pool="${POOL_CWUSDC_USDC_MAINNET-}"
|
||||
_qp_integration="${DODO_PMM_INTEGRATION_MAINNET-}"
|
||||
_qp_pool_a="${UNWIND_TWO_HOP_POOL_A-}"
|
||||
_qp_pool_b="${UNWIND_TWO_HOP_POOL_B-}"
|
||||
_qp_mid_token="${UNWIND_TWO_HOP_MID_TOKEN-}"
|
||||
_qp_min_mid_out="${UNWIND_MIN_MID_OUT_RAW-}"
|
||||
_qp_min_out_pmm="${MIN_OUT_PMM-}"
|
||||
_qp_min_out_unwind="${MIN_OUT_UNWIND-}"
|
||||
_qp_fee_u24="${UNWIND_V3_FEE_U24-}"
|
||||
_qp_dodo_pool="${UNWIND_DODO_POOL-}"
|
||||
_qp_v3_path="${UNWIND_V3_PATH_HEX-}"
|
||||
_qp_intermediate_token="${UNWIND_INTERMEDIATE_TOKEN-}"
|
||||
_qp_min_intermediate_out="${UNWIND_MIN_INTERMEDIATE_OUT_RAW-}"
|
||||
_qp_treasury_harvest="${QUOTE_PUSH_TREASURY_HARVEST-}"
|
||||
_qp_treasury_holdback="${QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver"
|
||||
[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager"
|
||||
[[ -n "$_qp_unwinder" ]] && export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$_qp_unwinder"
|
||||
[[ -n "$_qp_amount" ]] && export FLASH_QUOTE_AMOUNT_RAW="$_qp_amount"
|
||||
[[ -n "$_qp_unwind_type" ]] && export QUOTE_PUSH_UNWINDER_TYPE="$_qp_unwind_type"
|
||||
[[ -n "$_qp_unwind_mode" ]] && export UNWIND_MODE="$_qp_unwind_mode"
|
||||
[[ -n "$_qp_pool" ]] && export POOL_CWUSDC_USDC_MAINNET="$_qp_pool"
|
||||
[[ -n "$_qp_integration" ]] && export DODO_PMM_INTEGRATION_MAINNET="$_qp_integration"
|
||||
[[ -n "$_qp_pool_a" ]] && export UNWIND_TWO_HOP_POOL_A="$_qp_pool_a"
|
||||
[[ -n "$_qp_pool_b" ]] && export UNWIND_TWO_HOP_POOL_B="$_qp_pool_b"
|
||||
[[ -n "$_qp_mid_token" ]] && export UNWIND_TWO_HOP_MID_TOKEN="$_qp_mid_token"
|
||||
[[ -n "$_qp_min_mid_out" ]] && export UNWIND_MIN_MID_OUT_RAW="$_qp_min_mid_out"
|
||||
[[ -n "$_qp_min_out_pmm" ]] && export MIN_OUT_PMM="$_qp_min_out_pmm"
|
||||
[[ -n "$_qp_min_out_unwind" ]] && export MIN_OUT_UNWIND="$_qp_min_out_unwind"
|
||||
[[ -n "$_qp_fee_u24" ]] && export UNWIND_V3_FEE_U24="$_qp_fee_u24"
|
||||
[[ -n "$_qp_dodo_pool" ]] && export UNWIND_DODO_POOL="$_qp_dodo_pool"
|
||||
[[ -n "$_qp_v3_path" ]] && export UNWIND_V3_PATH_HEX="$_qp_v3_path"
|
||||
[[ -n "$_qp_intermediate_token" ]] && export UNWIND_INTERMEDIATE_TOKEN="$_qp_intermediate_token"
|
||||
[[ -n "$_qp_min_intermediate_out" ]] && export UNWIND_MIN_INTERMEDIATE_OUT_RAW="$_qp_min_intermediate_out"
|
||||
[[ -n "$_qp_treasury_harvest" ]] && export QUOTE_PUSH_TREASURY_HARVEST="$_qp_treasury_harvest"
|
||||
[[ -n "$_qp_treasury_holdback" ]] && export QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW="$_qp_treasury_holdback"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_receiver _qp_manager _qp_unwinder _qp_amount _qp_unwind_type _qp_unwind_mode
|
||||
unset _qp_pool _qp_integration _qp_pool_a _qp_pool_b _qp_mid_token _qp_min_mid_out _qp_min_out_pmm
|
||||
unset _qp_min_out_unwind _qp_fee_u24 _qp_dodo_pool _qp_v3_path _qp_intermediate_token _qp_min_intermediate_out
|
||||
unset _qp_treasury_harvest _qp_treasury_holdback
|
||||
|
||||
BROADCAST=()
|
||||
if (($# == 0)); then
|
||||
:
|
||||
else
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
--apply) BROADCAST=(--broadcast) ;;
|
||||
--dry-run) BROADCAST=() ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $a" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
require() {
|
||||
local n="$1"
|
||||
if [[ -z "${!n:-}" ]]; then
|
||||
echo "[fail] missing required env: $n" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_create_address() {
|
||||
local script_name="$1"
|
||||
local contract_name="$2"
|
||||
local latest_json="${SMOM}/broadcast/${script_name}/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r --arg contract "$contract_name" \
|
||||
'.transactions[]? | select(.transactionType == "CREATE" and .contractName == $contract) | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
pick_default_unwinder() {
|
||||
local addr=""
|
||||
PICK_DEFAULT_UNWINDER_ADDR=""
|
||||
PICK_DEFAULT_UNWINDER_MODE=""
|
||||
|
||||
addr="$(pick_latest_create_address "DeployTwoHopDodoIntegrationUnwinder.s.sol" "TwoHopDodoIntegrationUnwinder" || true)"
|
||||
if [[ -n "$addr" && "$addr" != "null" ]]; then
|
||||
PICK_DEFAULT_UNWINDER_ADDR="$addr"
|
||||
PICK_DEFAULT_UNWINDER_MODE="4"
|
||||
return 0
|
||||
fi
|
||||
|
||||
addr="$(pick_latest_create_address "DeployDODOIntegrationExternalUnwinder.s.sol" "DODOIntegrationExternalUnwinder" || true)"
|
||||
if [[ -n "$addr" && "$addr" != "null" ]]; then
|
||||
PICK_DEFAULT_UNWINDER_ADDR="$addr"
|
||||
PICK_DEFAULT_UNWINDER_MODE="1"
|
||||
return 0
|
||||
fi
|
||||
|
||||
addr="$(pick_latest_create_address "DeployUniswapV3ExternalUnwinder.s.sol" "UniswapV3ExternalUnwinder" || true)"
|
||||
if [[ -n "$addr" && "$addr" != "null" ]]; then
|
||||
PICK_DEFAULT_UNWINDER_ADDR="$addr"
|
||||
PICK_DEFAULT_UNWINDER_MODE="0"
|
||||
return 0
|
||||
fi
|
||||
|
||||
addr="$(pick_latest_create_address "DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol" "DODOToUniswapV3MultiHopExternalUnwinder" || true)"
|
||||
if [[ -n "$addr" && "$addr" != "null" ]]; then
|
||||
PICK_DEFAULT_UNWINDER_ADDR="$addr"
|
||||
PICK_DEFAULT_UNWINDER_MODE="5"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
UNW="${QUOTE_PUSH_UNWINDER_TYPE:-}"
|
||||
if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then
|
||||
inferred_receiver="$(pick_latest_create_address "DeployAaveQuotePushFlashReceiver.s.sol" "AaveQuotePushFlashReceiver" || true)"
|
||||
export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="${inferred_receiver:-$DEFAULT_AAVE_QUOTE_PUSH_RECEIVER_MAINNET}"
|
||||
fi
|
||||
|
||||
if [[ -z "${POOL_CWUSDC_USDC_MAINNET:-}" || "${_qp_pool:-}" == "" ]]; then
|
||||
export POOL_CWUSDC_USDC_MAINNET="$DEFAULT_POOL_CWUSDC_USDC_MAINNET"
|
||||
fi
|
||||
|
||||
if [[ -z "${FLASH_QUOTE_AMOUNT_RAW:-}" ]]; then
|
||||
export FLASH_QUOTE_AMOUNT_RAW=200000
|
||||
fi
|
||||
|
||||
if [[ -z "${MIN_OUT_PMM:-}" ]]; then
|
||||
export MIN_OUT_PMM=1
|
||||
fi
|
||||
|
||||
if [[ -z "${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET:-}" && -n "$UNW" ]]; then
|
||||
unwind_script=""
|
||||
unwind_contract=""
|
||||
case "$UNW" in
|
||||
univ3)
|
||||
unwind_script="DeployUniswapV3ExternalUnwinder.s.sol"
|
||||
unwind_contract="UniswapV3ExternalUnwinder"
|
||||
export UNWIND_MODE="${UNWIND_MODE:-0}"
|
||||
;;
|
||||
dodo)
|
||||
unwind_script="DeployDODOIntegrationExternalUnwinder.s.sol"
|
||||
unwind_contract="DODOIntegrationExternalUnwinder"
|
||||
export UNWIND_MODE="${UNWIND_MODE:-1}"
|
||||
;;
|
||||
two_hop_dodo)
|
||||
unwind_script="DeployTwoHopDodoIntegrationUnwinder.s.sol"
|
||||
unwind_contract="TwoHopDodoIntegrationUnwinder"
|
||||
export UNWIND_MODE="${UNWIND_MODE:-4}"
|
||||
;;
|
||||
dodo_univ3)
|
||||
unwind_script="DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol"
|
||||
unwind_contract="DODOToUniswapV3MultiHopExternalUnwinder"
|
||||
export UNWIND_MODE="${UNWIND_MODE:-5}"
|
||||
;;
|
||||
*)
|
||||
echo "[fail] QUOTE_PUSH_UNWINDER_TYPE must be univ3, dodo, two_hop_dodo, or dodo_univ3 when set" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
inferred_unwinder="$(pick_latest_create_address "$unwind_script" "$unwind_contract" || true)"
|
||||
if [[ -n "$inferred_unwinder" && "$inferred_unwinder" != "null" ]]; then
|
||||
export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$inferred_unwinder"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET:-}" ]]; then
|
||||
if pick_default_unwinder; then
|
||||
if [[ -n "$PICK_DEFAULT_UNWINDER_ADDR" && "$PICK_DEFAULT_UNWINDER_ADDR" != "null" ]]; then
|
||||
export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$PICK_DEFAULT_UNWINDER_ADDR"
|
||||
export UNWIND_MODE="$PICK_DEFAULT_UNWINDER_MODE"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${UNWIND_MODE:-}" == "4" ]]; then
|
||||
export UNWIND_TWO_HOP_POOL_A="${UNWIND_TWO_HOP_POOL_A:-0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB}"
|
||||
export UNWIND_TWO_HOP_POOL_B="${UNWIND_TWO_HOP_POOL_B:-0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2}"
|
||||
export UNWIND_TWO_HOP_MID_TOKEN="${UNWIND_TWO_HOP_MID_TOKEN:-0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE}"
|
||||
export UNWIND_MIN_MID_OUT_RAW="${UNWIND_MIN_MID_OUT_RAW:-1}"
|
||||
elif [[ "${UNWIND_MODE:-}" == "5" ]]; then
|
||||
export UNWIND_DODO_POOL="${UNWIND_DODO_POOL:-0xCC0fd27A40775c9AfcD2BBd3f7c902b0192c247A}"
|
||||
export UNWIND_INTERMEDIATE_TOKEN="${UNWIND_INTERMEDIATE_TOKEN:-0xdAC17F958D2ee523a2206206994597C13D831ec7}"
|
||||
export UNWIND_MIN_INTERMEDIATE_OUT_RAW="${UNWIND_MIN_INTERMEDIATE_OUT_RAW:-1}"
|
||||
fi
|
||||
|
||||
require ETHEREUM_MAINNET_RPC
|
||||
require PRIVATE_KEY
|
||||
require QUOTE_PUSH_TREASURY_MANAGER_MAINNET
|
||||
require AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
require QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET
|
||||
require DODO_PMM_INTEGRATION_MAINNET
|
||||
require FLASH_QUOTE_AMOUNT_RAW
|
||||
|
||||
UM="${UNWIND_MODE:-0}"
|
||||
if [[ "$UM" == "0" ]]; then
|
||||
require UNWIND_V3_FEE_U24
|
||||
elif [[ "$UM" == "1" ]]; then
|
||||
require UNWIND_DODO_POOL
|
||||
elif [[ "$UM" == "2" ]]; then
|
||||
require UNWIND_V3_PATH_HEX
|
||||
elif [[ "$UM" == "4" ]]; then
|
||||
require UNWIND_TWO_HOP_POOL_A
|
||||
require UNWIND_TWO_HOP_POOL_B
|
||||
require UNWIND_TWO_HOP_MID_TOKEN
|
||||
elif [[ "$UM" == "5" ]]; then
|
||||
require UNWIND_DODO_POOL
|
||||
require UNWIND_INTERMEDIATE_TOKEN
|
||||
require UNWIND_V3_PATH_HEX
|
||||
else
|
||||
echo "[fail] UNWIND_MODE must be 0, 1, 2, 4, or 5" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET"
|
||||
echo "manager=$QUOTE_PUSH_TREASURY_MANAGER_MAINNET"
|
||||
echo "unwinder=$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET"
|
||||
echo "flash_quote_amount_raw=$FLASH_QUOTE_AMOUNT_RAW unwind_mode=$UM"
|
||||
echo "gas_holdback_target_raw=${QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW:-0}"
|
||||
|
||||
(
|
||||
cd "$SMOM"
|
||||
forge script script/flash/RunManagedMainnetAaveCwusdcUsdcQuotePushCycle.s.sol:RunManagedMainnetAaveCwusdcUsdcQuotePushCycle \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
"${BROADCAST[@]}" \
|
||||
-vvvv
|
||||
)
|
||||
@@ -9,6 +9,7 @@ set -euo pipefail
|
||||
# FLASH_MODEL_SCAN_SIZES — comma-separated gross flash quote sizes in raw units (default 5e6,1e7,2e7)
|
||||
# PMM_FLASH_EXIT_PRICE_CMD — passed to node --external-exit-price-cmd (default: printf 1.02)
|
||||
# GAS_GWEI, NATIVE_PRICE — optional overrides for the economics model
|
||||
# If GAS_GWEI is unset, the script reads the live mainnet gas price and converts it to gwei.
|
||||
# FLASH_MODEL_GAS_TX_COUNT, FLASH_MODEL_GAS_PER_TX — gas row (defaults 3 / 250000)
|
||||
# FLASH_MODEL_MAX_POST_TRADE_DEV_BPS — deviation guard (default 500; raise only for stress math, not production)
|
||||
#
|
||||
@@ -40,7 +41,7 @@ INTEGRATION="${DODO_PMM_INTEGRATION_MAINNET:-}"
|
||||
POOL="${POOL_CWUSDC_USDC_MAINNET:-0x69776fc607e9edA8042e320e7e43f54d06c68f0E}"
|
||||
SCAN="${FLASH_MODEL_SCAN_SIZES:-5000000,10000000,25000000}"
|
||||
EXIT_CMD="${PMM_FLASH_EXIT_PRICE_CMD:-printf 1.02}"
|
||||
GAS_GWEI="${GAS_GWEI:-40}"
|
||||
GAS_GWEI="${GAS_GWEI:-}"
|
||||
NATIVE_PRICE="${NATIVE_PRICE:-3200}"
|
||||
GAS_TXN="${FLASH_MODEL_GAS_TX_COUNT:-3}"
|
||||
GAS_PER="${FLASH_MODEL_GAS_PER_TX:-250000}"
|
||||
@@ -62,6 +63,15 @@ out="$(cast call "$POOL" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_UR
|
||||
B="$(printf '%s\n' "$out" | sed -n '1p' | awk '{print $1}')"
|
||||
Q="$(printf '%s\n' "$out" | sed -n '2p' | awk '{print $1}')"
|
||||
|
||||
if [[ -z "$GAS_GWEI" ]]; then
|
||||
gas_price_wei="$(cast gas-price --rpc-url "$RPC_URL" | awk '{print $1}')"
|
||||
GAS_GWEI="$(python3 - "$gas_price_wei" <<'PY'
|
||||
import sys
|
||||
print(f"{int(sys.argv[1]) / 1_000_000_000:.9f}")
|
||||
PY
|
||||
)"
|
||||
fi
|
||||
|
||||
PMM_JS="${PROXMOX_ROOT}/scripts/analytics/pmm-flash-push-break-even.mjs"
|
||||
|
||||
echo "=== Flash quote-push model sweep (dry-run only) ==="
|
||||
@@ -92,3 +102,4 @@ for x in "${sizes[@]}"; do
|
||||
done
|
||||
|
||||
echo "Live execution: deploy-mainnet-aave-quote-push-stack.sh then run-mainnet-aave-cwusdc-quote-push-once.sh (see plan-mainnet-cwusdc-flash-quote-push-rebalance.sh)"
|
||||
echo "Receiver surplus accounting: bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh"
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Sweep retained surplus from a deployed Mainnet Aave quote-push receiver.
|
||||
# Default: simulation only. Use --apply to broadcast.
|
||||
#
|
||||
# Env:
|
||||
# PRIVATE_KEY, ETHEREUM_MAINNET_RPC, AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC
|
||||
# QUOTE_PUSH_SURPLUS_RECIPIENT optional; defaults to deployer derived from PRIVATE_KEY
|
||||
# QUOTE_PUSH_SURPLUS_RESERVE_RAW optional; keep this much on the receiver when sweeping surplus mode
|
||||
# QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW optional; if > 0, sweep this exact amount instead of balance - reserve
|
||||
#
|
||||
# Usage:
|
||||
# source scripts/lib/load-project-env.sh
|
||||
# bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --dry-run
|
||||
# QUOTE_PUSH_SURPLUS_RESERVE_RAW=50000 bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --apply
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM="${PROXMOX_ROOT}/smom-dbis-138"
|
||||
DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
||||
|
||||
_qp_private_key="${PRIVATE_KEY-}"
|
||||
_qp_rpc="${ETHEREUM_MAINNET_RPC-}"
|
||||
_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}"
|
||||
_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}"
|
||||
_qp_recipient="${QUOTE_PUSH_SURPLUS_RECIPIENT-}"
|
||||
_qp_reserve="${QUOTE_PUSH_SURPLUS_RESERVE_RAW-}"
|
||||
_qp_exact="${QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW-}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true
|
||||
# shellcheck disable=SC1091
|
||||
source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true
|
||||
|
||||
[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key"
|
||||
[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc"
|
||||
[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver"
|
||||
[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token"
|
||||
[[ -n "$_qp_recipient" ]] && export QUOTE_PUSH_SURPLUS_RECIPIENT="$_qp_recipient"
|
||||
[[ -n "$_qp_reserve" ]] && export QUOTE_PUSH_SURPLUS_RESERVE_RAW="$_qp_reserve"
|
||||
[[ -n "$_qp_exact" ]] && export QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW="$_qp_exact"
|
||||
|
||||
unset _qp_private_key _qp_rpc _qp_receiver _qp_token _qp_recipient _qp_reserve _qp_exact
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[fail] missing required command: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_cmd cast
|
||||
require_cmd forge
|
||||
|
||||
require_env() {
|
||||
local name="$1"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "[fail] missing required env: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pick_latest_receiver() {
|
||||
local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json"
|
||||
if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \
|
||||
"$latest_json" | tail -n1
|
||||
}
|
||||
|
||||
MODE="dry-run"
|
||||
BROADCAST=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) MODE="dry-run"; BROADCAST=() ;;
|
||||
--apply) MODE="apply"; BROADCAST=(--broadcast) ;;
|
||||
*)
|
||||
echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env PRIVATE_KEY
|
||||
require_env ETHEREUM_MAINNET_RPC
|
||||
if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then
|
||||
inferred_receiver="$(pick_latest_receiver || true)"
|
||||
if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then
|
||||
export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver"
|
||||
fi
|
||||
fi
|
||||
require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
|
||||
TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}"
|
||||
DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")"
|
||||
RECIPIENT="${QUOTE_PUSH_SURPLUS_RECIPIENT:-$DEPLOYER}"
|
||||
RESERVE_RAW="${QUOTE_PUSH_SURPLUS_RESERVE_RAW:-0}"
|
||||
EXACT_RAW="${QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW:-0}"
|
||||
receiver_owner="$(cast call "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)"
|
||||
|
||||
if [[ -z "$receiver_owner" ]]; then
|
||||
cat >&2 <<EOF
|
||||
[fail] receiver does not expose owner()/sweep support: $AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
[hint] Redeploy the updated receiver, then point AAVE_QUOTE_PUSH_RECEIVER_MAINNET at the new address:
|
||||
bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${receiver_owner,,}" != "${DEPLOYER,,}" ]]; then
|
||||
echo "[fail] deployer $DEPLOYER is not the receiver owner ($receiver_owner)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
receiver_balance_raw="$(
|
||||
cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
| awk '{print $1}'
|
||||
)"
|
||||
|
||||
if (( EXACT_RAW > 0 )); then
|
||||
if (( receiver_balance_raw < EXACT_RAW )); then
|
||||
echo "[fail] receiver balance too small for exact sweep: have=$receiver_balance_raw need=$EXACT_RAW" >&2
|
||||
exit 1
|
||||
fi
|
||||
sweep_raw="$EXACT_RAW"
|
||||
else
|
||||
if (( receiver_balance_raw <= RESERVE_RAW )); then
|
||||
echo "[stop] nothing to sweep: receiver_balance_raw=$receiver_balance_raw reserve_raw=$RESERVE_RAW" >&2
|
||||
exit 3
|
||||
fi
|
||||
sweep_raw=$((receiver_balance_raw - RESERVE_RAW))
|
||||
fi
|
||||
|
||||
echo "=== sweep-mainnet-aave-quote-push-receiver-surplus ($MODE) ==="
|
||||
echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET"
|
||||
echo "receiver_owner=$receiver_owner"
|
||||
echo "token=$TOKEN"
|
||||
echo "recipient=$RECIPIENT"
|
||||
echo "receiver_balance_raw=$receiver_balance_raw"
|
||||
echo "reserve_raw=$RESERVE_RAW"
|
||||
echo "exact_raw=$EXACT_RAW"
|
||||
echo "sweep_raw=$sweep_raw"
|
||||
|
||||
(
|
||||
cd "$SMOM"
|
||||
forge script script/flash/SweepAaveQuotePushFlashReceiverSurplus.s.sol:SweepAaveQuotePushFlashReceiverSurplus \
|
||||
--rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
"${BROADCAST[@]}" \
|
||||
-vvvv
|
||||
)
|
||||
|
||||
if [[ "$MODE" == "apply" ]]; then
|
||||
receiver_after="$(
|
||||
cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
| awk '{print $1}'
|
||||
)"
|
||||
recipient_after="$(
|
||||
cast call "$TOKEN" 'balanceOf(address)(uint256)' "$RECIPIENT" --rpc-url "$ETHEREUM_MAINNET_RPC" \
|
||||
| awk '{print $1}'
|
||||
)"
|
||||
echo "receiver_balance_after_raw=$receiver_after"
|
||||
echo "recipient_balance_after_raw=$recipient_after"
|
||||
fi
|
||||
Reference in New Issue
Block a user