Files
proxmox/scripts/analytics/pmm-flash-push-break-even.mjs
defiQUG dbd517b279 Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains
- Omit embedded publish git dirs and empty placeholders from index

Made-with: Cursor
2026-04-12 06:12:20 -07:00

4635 lines
177 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* PMM / reserve-style flash-loan "push trade": slippage, VWAP, PnL, break-even external price,
* and quote-seeding / liquidity-loop planning.
*
* Matches the quote-in → base-out fallback used in DODOPMMProvider._fallbackReserveQuote:
* amountOut = (netAmountIn * baseReserve) / (quoteReserve + netAmountIn)
* (see smom-dbis-138/contracts/liquidity/providers/DODOPMMProvider.sol)
*
* Not a full DODO PMM (i, k, oracle) simulation — use pool querySellQuote on-chain for production.
* Amounts: use consistent token base units (e.g. USDC 6 decimals, so 1 USDC = 1_000_000 raw units).
* JS Number is safe below ~9e15.
*
* -----------------------------------------------------------------------------
* Ethereum Mainnet — live cWUSDC / USDC PMM (repo registry)
* -----------------------------------------------------------------------------
* "xWUSDC" in ops shorthand = **cWUSDC** (compliant wrapped USDC on public mesh).
* Canonical addresses + pool row: cross-chain-pmm-lps/config/deployment-status.json (chain "1").
*
* **Funded loop (not necessarily Aave flash):** USDC working capital x funds:
* (1) USDC → ETH on Uniswap (or other deep venue) — fees + slippage → factor f_eth
* (2) ETH → cWUSDC — often extra hop if no WETH/cWUSDC book; fold into composite acquisition cost
* (3) cWUSDC → USDC on DODO PMM — **sell base** leg:
* quoteOut = (netBaseIn * Q) / (B + netBaseIn) [sellBase branch]
* Model the first two legs as a single **effective USDC per cWUSDC** you need before the PMM exit,
* or run this script on the PMM leg only with -B/-Q from getVaultReserve().
*
* **Deepening the pool with cWUSDC:** increases base reserve B. For **USDC → cWUSDC** (quote in),
* larger B → **more** Δy and **lower** VWAP for the same x (tighter book for buyers). For **cWUSDC → USDC**
* (base in), larger B → **less** USDC per unit base for a large sell (pool absorbs more base without
* draining quote). Size both sides for balanced inventory if you route flow in both directions.
*
* -----------------------------------------------------------------------------
* Baseline recalc (vs liquidity-ratio heuristic)
* -----------------------------------------------------------------------------
* Reserves B = Q = 10e6 (10M each side). Gross quote in x = 10e6.
*
* Zero LP fee:
* Δy = B * x / (Q + x) = 10M * 10M / 20M = 5M base out
* VWAP = x / Δy = 2.00 quote per base (not ~1.25 from impact/2 linearization)
*
* With DEFAULT_LP_FEE = 3 bps (netIn = x * 9997/10000):
* Δy slightly below 5M; VWAP slightly above 2.00
*
* x = 2e6 quote in, B = Q = 10e6, no LP fee:
* Δy = 2 * 10 / 12 M ≈ 1.667M, VWAP ≈ 1.20 (not ~1.083)
*
* -----------------------------------------------------------------------------
* Break-even (plug-in)
* -----------------------------------------------------------------------------
* Let x = gross quote swapped in, f_lp = LP fee on pool input (fraction of x),
* Δx_net = x * (1 - f_lp) [same as contract: netAmountIn]
* Δy = B * Δx_net / (Q + Δx_net)
* Flash fee f_flash on repayment: repay = x * (1 + f_flash)
* Effective external proceeds: model exit DEX fee / impact as P_eff = P_ext * (1 - f_exit)
*
* Π = P_eff * Δy - x * (1 + f_flash)
*
* Break-even spot P_ext (given exit fee on sell proceeds):
* P_ext* = x * (1 + f_flash) / (Δy * (1 - f_exit))
*
* Fold routing into one number: set --external-price to your net USDC per base after all exits.
*
* Usage:
* node scripts/analytics/pmm-flash-push-break-even.mjs --examples
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 10000000 -Q 10000000 -x 10000000 \
* --lp-fee-bps 3 --flash-fee-bps 5 --external-price 1.0
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 10e6 -Q 10e6 --scan 1e6,2e6,5e6,10e6 \
* --lp-fee-bps 3 --flash-fee-bps 5
* node scripts/analytics/pmm-flash-push-break-even.mjs --mainnet-map
* node scripts/analytics/pmm-flash-push-break-even.mjs --mainnet-map --compare-deepen 5e6 \
* -B 2000000 -Q 2000000 --scan 500000,1000000,2000000 --flash-fee-bps 0
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4000000 -Q 12000000 \
* --seed-pools 6 --target-quote-per-pool 500000000000 --lp-fee-bps 10 --inventory-base 8000000
* node scripts/analytics/pmm-flash-push-break-even.mjs --external-price 0.992 \
* --seed-pools 6 --target-quote-per-pool 500000000000 --exit-fee-bps 20 --inventory-base 4000000
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 \
* --inventory-loop-scan --scan 50000,100000,150000,200000,250000 --lp-fee-bps 10 \
* --flash-fee-bps 5 --min-retained-usdc 10000
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 \
* --inventory-loop-rank --scan 50000,100000,150000,200000,250000 --lp-fee-bps 10 \
* --flash-fee-bps 5 --min-retained-usdc 10000 --target-flash-borrow 90000
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 \
* --inventory-loop-rank --scan 50000,100000,150000 --lp-fee-bps 10 --flash-fee-bps 5 \
* --min-retained-usdc 10000 --inventory-base 1000000 --gas-tx-count 3 --gas-per-tx 250000 \
* --max-fee-gwei 40 --native-token-price 3200 --max-post-trade-deviation-bps 250 \
* --max-cw-burn-fraction 0.1 --cooldown-blocks 12 --rank-profile conservative
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 \
* --inventory-loop-rank --scan 100000,250000,500000 --lp-fee-bps 10 --flash-fee-bps 5 \
* --target-flash-borrow 1000000 --flash-add-to-pool
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 -x 1000000 \
* --full-loop-dry-run --external-price 1.01 --flash-fee-bps 5 --lp-fee-bps 10 \
* --seed-pools 3 --target-quote-per-pool 250000 --gas-tx-count 3 --gas-per-tx 250000 \
* --max-fee-gwei 40 --native-token-price 3200 --max-post-trade-deviation-bps 500
* node scripts/analytics/pmm-flash-push-break-even.mjs -B 4854640 -Q 4854839 -x 1000000 \
* --full-loop-dry-run --owned-base-add 500000 --external-exit-price 1.12 --flash-fee-bps 5 \
* --lp-fee-bps 10 --base-asset cWUSDC --quote-asset USDC
* node scripts/analytics/pmm-flash-push-break-even.mjs --public-live-sweep --loop-strategy both \
* --external-exit-price 1.12 --external-entry-price 0.74 --external-via-asset ETH \
* --gas-tx-count 3 --gas-per-tx 250000 --max-fee-gwei 40 --native-token-price 3200 \
* --max-post-trade-deviation-bps 500
* node scripts/analytics/pmm-flash-push-break-even.mjs --sequential-matched-loops 100 \
* -B 256763253 -Q 256763253 --loop-strategy quote-push \
* --base-asset cWUSDC --quote-decimals 6 --quote-asset USDC \
* --external-exit-price 1.12 --lp-fee-bps 3 --flash-fee-bps 5 \
* --gas-tx-count 3 --gas-per-tx 185000 --max-fee-gwei 60 --native-token-price 3200 \
* --max-post-trade-deviation-bps 500 --oracle-price 1 --flash-provider-cap 1000000000000
*/
import { parseArgs } from 'node:util'
import { readFileSync, existsSync, readdirSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { execFileSync } from 'node:child_process'
const __dirname = dirname(fileURLToPath(import.meta.url))
const REPO_ROOT = resolve(__dirname, '../..')
const DEPLOYMENT_STATUS = resolve(REPO_ROOT, 'cross-chain-pmm-lps/config/deployment-status.json')
const SMART_CONTRACTS_MASTER = resolve(REPO_ROOT, 'config/smart-contracts-master.json')
const DEPLOYER_TOKEN_AUDIT_DIR = resolve(REPO_ROOT, 'reports/deployer-token-audit')
const DEFAULT_MAINNET_BALANCER_VAULT =
process.env.MAINNET_BALANCER_VAULT ?? '0xBA12222222228d8Ba445958a75a0704d566BF2C8'
const DEFAULT_MAINNET_AAVE_V3_POOL =
process.env.MAINNET_AAVE_V3_POOL ?? '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2'
const DEFAULT_MAINNET_AAVE_V3_PROVIDER =
process.env.MAINNET_AAVE_V3_POOL_ADDRESSES_PROVIDER ?? '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e'
function netQuoteIn(grossX, lpFeeBps) {
const bps = Math.min(10000, Math.max(0, lpFeeBps))
return (grossX * (10000 - bps)) / 10000
}
function grossInputForNet(netIn, lpFeeBps) {
const bps = Math.min(10000, Math.max(0, lpFeeBps))
const mult = (10000 - bps) / 10000
if (mult <= 0) return Infinity
return netIn / mult
}
/** Quote in → base out (same branch as sellBase === false in DODOPMMProvider) */
function quoteInToBaseOut(baseReserve, quoteReserve, grossQuoteIn, lpFeeBps) {
if (baseReserve <= 0 || quoteReserve <= 0 || grossQuoteIn <= 0) {
return { deltaXNet: 0, baseOut: 0, vwap: NaN }
}
const deltaXNet = netQuoteIn(grossQuoteIn, lpFeeBps)
if (deltaXNet <= 0) return { deltaXNet: 0, baseOut: 0, vwap: NaN }
const baseOut = (deltaXNet * baseReserve) / (quoteReserve + deltaXNet)
const vwap = grossQuoteIn / baseOut
return { deltaXNet, baseOut, vwap }
}
/** Base in → quote out (sellBase branch in DODOPMMProvider) */
function baseInToQuoteOut(baseReserve, quoteReserve, grossBaseIn, lpFeeBps) {
if (baseReserve <= 0 || quoteReserve <= 0 || grossBaseIn <= 0) {
return { deltaBaseNet: 0, quoteOut: 0, vwapQuotePerBase: NaN }
}
const deltaBaseNet = netQuoteIn(grossBaseIn, lpFeeBps)
if (deltaBaseNet <= 0) return { deltaBaseNet: 0, quoteOut: 0, vwapQuotePerBase: NaN }
const quoteOut = (deltaBaseNet * quoteReserve) / (baseReserve + deltaBaseNet)
const vwapQuotePerBase = quoteOut / grossBaseIn
return { deltaBaseNet, quoteOut, vwapQuotePerBase }
}
/** Inverse of sell-base branch: required base in to harvest a target quote amount */
function baseInRequiredForQuoteOut(baseReserve, quoteReserve, targetQuoteOut, lpFeeBps) {
if (baseReserve <= 0 || quoteReserve <= 0 || targetQuoteOut <= 0) {
return {
feasible: false,
deltaBaseNet: 0,
grossBaseIn: 0,
feeBase: 0,
vwapQuotePerBase: NaN,
}
}
if (targetQuoteOut >= quoteReserve) {
return {
feasible: false,
deltaBaseNet: Infinity,
grossBaseIn: Infinity,
feeBase: Infinity,
vwapQuotePerBase: 0,
}
}
const deltaBaseNet = (targetQuoteOut * baseReserve) / (quoteReserve - targetQuoteOut)
const grossBaseIn = grossInputForNet(deltaBaseNet, lpFeeBps)
const feeBase = grossBaseIn - deltaBaseNet
const vwapQuotePerBase = targetQuoteOut / grossBaseIn
return { feasible: true, deltaBaseNet, grossBaseIn, feeBase, vwapQuotePerBase }
}
function loadMainnetCwUsdcUsdc() {
if (!existsSync(DEPLOYMENT_STATUS)) return null
const raw = JSON.parse(readFileSync(DEPLOYMENT_STATUS, 'utf8'))
const chain = raw.chains?.['1']
if (!chain?.pmmPools || !chain.cwTokens) return null
const row = chain.pmmPools.find((p) => p.base === 'cWUSDC' && p.quote === 'USDC')
if (!row) return null
const cWUSDC = chain.cwTokens.cWUSDC
const USDC = chain.anchorAddresses?.USDC
return { row, cWUSDC, USDC, feeBps: row.feeBps ?? 10, poolAddress: row.poolAddress }
}
function loadMainnetPool(base, quote) {
if (!existsSync(DEPLOYMENT_STATUS)) return null
const raw = JSON.parse(readFileSync(DEPLOYMENT_STATUS, 'utf8'))
const chain = raw.chains?.['1']
if (!chain?.pmmPools) return null
const row = chain.pmmPools.find((p) => p.base === base && p.quote === quote)
if (!row) return null
return {
row,
chain,
baseAddress: chain.cwTokens?.[base] ?? chain.anchorAddresses?.[base] ?? null,
quoteAddress: chain.anchorAddresses?.[quote] ?? chain.cwTokens?.[quote] ?? null,
feeBps: row.feeBps ?? 10,
poolAddress: row.poolAddress,
}
}
function loadLiveMainnetPublicUsdPools() {
if (!existsSync(DEPLOYMENT_STATUS)) return []
const raw = JSON.parse(readFileSync(DEPLOYMENT_STATUS, 'utf8'))
const chain = raw.chains?.['1']
if (!chain?.pmmPools) return []
return chain.pmmPools
.filter(
(row) =>
['cWUSDT', 'cWUSDC'].includes(row.base) &&
['USDC', 'USDT'].includes(row.quote) &&
row.poolAddress,
)
.map((row) => ({
...row,
baseAddress: chain.cwTokens?.[row.base] ?? null,
quoteAddress: chain.anchorAddresses?.[row.quote] ?? null,
feeBps: row.feeBps ?? 10,
}))
}
function loadChain138TokenAddress(symbol) {
if (!existsSync(SMART_CONTRACTS_MASTER)) return null
const raw = JSON.parse(readFileSync(SMART_CONTRACTS_MASTER, 'utf8'))
return raw.chains?.['138']?.contracts?.[symbol] ?? null
}
function inferSourceAsset(inventoryAsset) {
const match = /^cW(.+)$/.exec(inventoryAsset)
return match ? `c${match[1]}` : inventoryAsset
}
function latestBalanceReportPath() {
if (!existsSync(DEPLOYER_TOKEN_AUDIT_DIR)) return null
const entries = readdirSync(DEPLOYER_TOKEN_AUDIT_DIR)
.filter((name) => /^deployer-token-balances-.*\.json$/.test(name))
.sort()
if (entries.length === 0) return null
return resolve(DEPLOYER_TOKEN_AUDIT_DIR, entries[entries.length - 1])
}
function loadBalanceReport(reportPath) {
if (!reportPath || !existsSync(reportPath)) return null
return JSON.parse(readFileSync(reportPath, 'utf8'))
}
function sumReportBalance(report, chainId, symbol) {
if (!report?.balances) return null
let total = 0
let matched = false
for (const row of report.balances) {
if (
row?.chain_id === chainId &&
row?.token_symbol === symbol &&
row?.query_status === 'ok' &&
row?.balance_raw != null &&
row?.decimals != null
) {
total += Number(row.balance_raw) / 10 ** Number(row.decimals)
matched = true
}
}
return matched ? total : null
}
function sumReportBalanceInfo(report, chainId, symbol) {
if (!report?.balances) return null
let totalRaw = 0
let decimals = null
let matched = false
for (const row of report.balances) {
if (
row?.chain_id === chainId &&
row?.token_symbol === symbol &&
row?.query_status === 'ok' &&
row?.balance_raw != null &&
row?.decimals != null
) {
const rowDecimals = Number(row.decimals)
if (!Number.isFinite(rowDecimals)) continue
if (decimals == null) decimals = rowDecimals
if (decimals !== rowDecimals) return null
totalRaw += Number(row.balance_raw)
matched = true
}
}
if (!matched || decimals == null) return null
return {
balance: totalRaw / 10 ** decimals,
raw: totalRaw,
decimals,
}
}
function rpcUrlForChain(chainId) {
switch (chainId) {
case 1:
return process.env.ETHEREUM_MAINNET_RPC ?? process.env.ETH_MAINNET_RPC ?? null
case 138:
return process.env.CHAIN138_RPC_URL ?? process.env.RPC_URL_138 ?? null
default:
return null
}
}
function tryReadTokenDecimalsViaCast(chainId, tokenAddress) {
const rpcUrl = rpcUrlForChain(chainId)
if (!rpcUrl || !tokenAddress) return null
try {
const raw = execFileSync(
'cast',
['call', tokenAddress, 'decimals()(uint8)', '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const decimals = Number(parseCastScalar(raw))
return Number.isFinite(decimals) ? decimals : null
} catch {
return null
}
}
function parseCastScalar(raw) {
if (!raw) return null
const token = String(raw).trim().split(/\s+/)[0]
if (token === '') return null
return token
}
function extractNthAddress(raw, index) {
if (!raw || !(index > 0)) return null
const matches = String(raw).match(/0x[a-fA-F0-9]{40}/g) ?? []
return matches[index - 1] ?? null
}
function tryCastCallRaw(address, signature, args, rpcUrl) {
if (!address || !signature || !rpcUrl) return null
try {
return execFileSync(
'cast',
['call', address, signature, ...args.map(String), '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
).trim()
} catch {
return null
}
}
function tryReadCastCode(address, rpcUrl) {
if (!address || !rpcUrl) return null
try {
return execFileSync('cast', ['code', address, '--rpc-url', rpcUrl], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim()
} catch {
return null
}
}
function tryReadTokenRawBalanceViaCast(rpcUrl, tokenAddress, walletAddress) {
if (!rpcUrl || !tokenAddress || !walletAddress) return null
const raw = tryCastCallRaw(tokenAddress, 'balanceOf(address)(uint256)', [walletAddress], rpcUrl)
const scalar = raw != null ? Number(parseCastScalar(raw)) : NaN
return Number.isFinite(scalar) ? scalar : null
}
function resolveDeployerAddressViaCast() {
if (!process.env.PRIVATE_KEY) return null
try {
return execFileSync('cast', ['wallet', 'address', '--private-key', process.env.PRIVATE_KEY], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim()
} catch {
return null
}
}
function tryReadPoolReservesViaCast(chainId, poolAddress) {
const rpcUrl = rpcUrlForChain(chainId)
if (!rpcUrl || !poolAddress) return null
try {
const out = execFileSync(
'cast',
['call', poolAddress, 'getVaultReserve()(uint256,uint256)', '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
.trim()
.split(/\r?\n/)
.map((line) => parseCastScalar(line))
.filter(Boolean)
if (out.length < 2) return null
return {
baseReserve: Number(out[0]),
quoteReserve: Number(out[1]),
source: `live cast via chain ${chainId} RPC`,
}
} catch {
return null
}
}
function tryReadTokenBalanceViaCast(chainId, tokenAddress, walletAddress) {
const rpcUrl = rpcUrlForChain(chainId)
if (!rpcUrl || !tokenAddress || !walletAddress) return null
try {
const decimalsRaw = execFileSync(
'cast',
['call', tokenAddress, 'decimals()(uint8)', '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const balanceRaw = execFileSync(
'cast',
['call', tokenAddress, 'balanceOf(address)(uint256)', walletAddress, '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const decimals = Number(parseCastScalar(decimalsRaw))
const raw = Number(parseCastScalar(balanceRaw))
if (!Number.isFinite(decimals) || !Number.isFinite(raw)) return null
return {
balance: raw / 10 ** decimals,
decimals,
raw,
source: `live cast via chain ${chainId} RPC`,
}
} catch {
return null
}
}
function tryReadPoolFeeBpsViaCast(chainId, poolAddress) {
const rpcUrl = rpcUrlForChain(chainId)
if (!rpcUrl || !poolAddress) return null
try {
const raw = execFileSync(
'cast',
['call', poolAddress, '_LP_FEE_RATE_()(uint256)', '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const feeBps = Number(parseCastScalar(raw))
return Number.isFinite(feeBps) ? feeBps : null
} catch {
return null
}
}
function tryProbePoolQuoteSurfaceViaCast(chainId, poolAddress, traderAddress, probeAmount = 1_000_000) {
const rpcUrl = rpcUrlForChain(chainId)
if (!rpcUrl || !poolAddress || !traderAddress || !(probeAmount > 0)) return null
const baseToken = tryCastCallRaw(poolAddress, '_BASE_TOKEN_()(address)', [], rpcUrl)
const quoteToken = tryCastCallRaw(poolAddress, '_QUOTE_TOKEN_()(address)', [], rpcUrl)
const midPrice = tryCastCallRaw(poolAddress, 'getMidPrice()(uint256)', [], rpcUrl)
let sellBaseOk = false
let sellQuoteOk = false
let integrationSellBaseOk = false
let integrationSellQuoteOk = false
try {
execFileSync(
'cast',
[
'call',
poolAddress,
'querySellBase(address,uint256)(uint256,uint256)',
traderAddress,
String(probeAmount),
'--rpc-url',
rpcUrl,
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
sellBaseOk = true
} catch {}
try {
execFileSync(
'cast',
[
'call',
poolAddress,
'querySellQuote(address,uint256)(uint256,uint256)',
traderAddress,
String(probeAmount),
'--rpc-url',
rpcUrl,
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
sellQuoteOk = true
} catch {}
if (chainId === 1 && baseToken && quoteToken) {
const integrationAddress = process.env.DODO_PMM_INTEGRATION_MAINNET ?? null
if (integrationAddress) {
try {
execFileSync(
'cast',
[
'call',
integrationAddress,
'swapExactIn(address,address,uint256,uint256)(uint256)',
poolAddress,
String(parseCastScalar(quoteToken)),
String(probeAmount),
'1',
'--from',
traderAddress,
'--rpc-url',
rpcUrl,
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
integrationSellQuoteOk = true
} catch {}
try {
execFileSync(
'cast',
[
'call',
integrationAddress,
'swapExactIn(address,address,uint256,uint256)(uint256)',
poolAddress,
String(parseCastScalar(baseToken)),
String(probeAmount),
'1',
'--from',
traderAddress,
'--rpc-url',
rpcUrl,
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
integrationSellBaseOk = true
} catch {}
}
}
const hasReserveSurface = tryReadPoolReservesViaCast(chainId, poolAddress) != null
const hasMidPriceSurface = midPrice != null
const quotePushOk = sellQuoteOk || integrationSellQuoteOk
const baseUnwindOk = sellBaseOk || integrationSellBaseOk
let surface = 'unknown'
if (quotePushOk && baseUnwindOk) {
surface = 'full_quote_surface'
} else if (quotePushOk || baseUnwindOk) {
surface = 'strategy_specific_quote_surface'
} else if (hasReserveSurface && hasMidPriceSurface) {
surface = 'partial_dodo_surface_integration_only'
} else if (hasReserveSurface) {
surface = 'reserve_only'
}
return {
surface,
sellBaseOk,
sellQuoteOk,
integrationSellBaseOk,
integrationSellQuoteOk,
quotePushOk,
baseUnwindOk,
hasReserveSurface,
hasMidPriceSurface,
baseToken: baseToken ? String(parseCastScalar(baseToken)) : null,
quoteToken: quoteToken ? String(parseCastScalar(quoteToken)) : null,
source: `live pool probe via chain ${chainId} RPC`,
}
}
function extractFirstNumericToken(raw) {
if (!raw) return null
const match = String(raw).match(/-?\d+(?:\.\d+)?(?:e[+-]?\d+)?/i)
if (!match) return null
const value = Number(match[0])
return Number.isFinite(value) ? value : null
}
function tryReadNumericCommand(command, sourceLabel) {
if (!command) return null
try {
const raw = execFileSync('bash', ['-lc', command], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
}).trim()
const value = extractFirstNumericToken(raw)
if (!(value > 0)) return null
return {
value,
source: sourceLabel ?? `live command: ${command}`,
raw,
}
} catch {
return null
}
}
function tryEstimateIntegrationSwapGasViaCast({
integrationAddress,
poolAddress,
tokenIn,
amountIn,
minOut,
fromAddress,
rpcUrl,
}) {
if (!integrationAddress || !poolAddress || !tokenIn || !fromAddress || !rpcUrl || !(amountIn > 0)) {
return null
}
try {
const raw = execFileSync(
'cast',
[
'estimate',
'--from',
fromAddress,
integrationAddress,
'swapExactIn(address,address,uint256,uint256)(uint256)',
poolAddress,
tokenIn,
String(amountIn),
String(Math.max(1, minOut ?? 1)),
'--rpc-url',
rpcUrl,
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const gasUnits = Number(parseCastScalar(raw))
return Number.isFinite(gasUnits) ? gasUnits : null
} catch {
return null
}
}
function tryProbeErc3156FlashProvider(providerAddress, tokenAddress, amount, rpcUrl) {
if (!providerAddress || !tokenAddress || !(amount >= 0) || !rpcUrl) return null
try {
const maxLoanRaw = execFileSync(
'cast',
['call', providerAddress, 'maxFlashLoan(address)(uint256)', tokenAddress, '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const feeRaw = execFileSync(
'cast',
['call', providerAddress, 'flashFee(address,uint256)(uint256)', tokenAddress, String(amount), '--rpc-url', rpcUrl],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },
)
const maxFlashLoan = Number(parseCastScalar(maxLoanRaw))
const flashFeeAmount = Number(parseCastScalar(feeRaw))
if (!Number.isFinite(maxFlashLoan) || !Number.isFinite(flashFeeAmount)) return null
return {
maxFlashLoan,
flashFeeAmount,
source: `live ERC-3156 probe via ${providerAddress}`,
}
} catch {
return null
}
}
function tryReadMainnetBalancerFlashSource(tokenAddress) {
const rpcUrl = rpcUrlForChain(1)
if (!rpcUrl || !tokenAddress) return null
const code = tryReadCastCode(DEFAULT_MAINNET_BALANCER_VAULT, rpcUrl)
if (!code || code === '0x') return null
const collector = tryCastCallRaw(
DEFAULT_MAINNET_BALANCER_VAULT,
'getProtocolFeesCollector()(address)',
[],
rpcUrl,
)
const feeRaw = collector
? tryCastCallRaw(collector, 'getFlashLoanFeePercentage()(uint256)', [], rpcUrl)
: null
const feeScalar = feeRaw != null ? Number(parseCastScalar(feeRaw)) : NaN
const feeBps = Number.isFinite(feeScalar) ? feeScalar / 1e14 : 0
const capRaw = tryReadTokenRawBalanceViaCast(rpcUrl, tokenAddress, DEFAULT_MAINNET_BALANCER_VAULT)
return {
providerKey: 'balancer',
providerName: 'Balancer mainnet vault',
providerAddress: DEFAULT_MAINNET_BALANCER_VAULT,
capRaw,
feeBps,
feeRaw: feeRaw != null ? parseCastScalar(feeRaw) : null,
source: 'live Balancer mainnet vault probe',
}
}
function tryReadMainnetAaveFlashSource(tokenAddress) {
const rpcUrl = rpcUrlForChain(1)
if (!rpcUrl || !tokenAddress) return null
const code = tryReadCastCode(DEFAULT_MAINNET_AAVE_V3_POOL, rpcUrl)
if (!code || code === '0x') return null
const provider = tryCastCallRaw(
DEFAULT_MAINNET_AAVE_V3_POOL,
'ADDRESSES_PROVIDER()(address)',
[],
rpcUrl,
)
const feeRaw = tryCastCallRaw(
DEFAULT_MAINNET_AAVE_V3_POOL,
'FLASHLOAN_PREMIUM_TOTAL()(uint128)',
[],
rpcUrl,
)
const feeBps = feeRaw != null ? Number(parseCastScalar(feeRaw)) : NaN
const reserveData = tryCastCallRaw(
DEFAULT_MAINNET_AAVE_V3_POOL,
'getReserveData(address)((uint256,uint128,uint128,uint128,uint128,uint128,uint40,address,address,address,address,uint8))',
[tokenAddress],
rpcUrl,
)
const aTokenAddress = extractNthAddress(reserveData, 2)
const capRaw =
aTokenAddress != null ? tryReadTokenRawBalanceViaCast(rpcUrl, tokenAddress, aTokenAddress) : null
return {
providerKey: 'aave',
providerName: 'Aave V3 mainnet',
providerAddress: DEFAULT_MAINNET_AAVE_V3_POOL,
providerAuxAddress: provider ?? DEFAULT_MAINNET_AAVE_V3_PROVIDER,
capRaw,
feeBps: Number.isFinite(feeBps) ? feeBps : null,
feeRaw: feeRaw != null ? parseCastScalar(feeRaw) : null,
source: 'live Aave V3 mainnet probe',
}
}
function tryEstimateMainnetIntegrationGasQuote({
poolAddress,
tokenIn,
amountIn,
quoteDecimals,
nativeTokenPrice,
fromAddress,
}) {
const rpcUrl = rpcUrlForChain(1)
const integrationAddress = process.env.DODO_PMM_INTEGRATION_MAINNET ?? null
if (
!rpcUrl ||
!integrationAddress ||
!poolAddress ||
!tokenIn ||
!(amountIn > 0) ||
!(quoteDecimals >= 0) ||
!(nativeTokenPrice > 0) ||
!fromAddress
) {
return null
}
const gasUnits = tryEstimateIntegrationSwapGasViaCast({
integrationAddress,
poolAddress,
tokenIn,
amountIn,
minOut: 1,
fromAddress,
rpcUrl,
})
if (!(gasUnits > 0)) return null
let gasPriceWei = null
try {
const raw = execFileSync('cast', ['gas-price', '--rpc-url', rpcUrl], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore'],
})
gasPriceWei = Number(parseCastScalar(raw))
} catch {}
if (!(gasPriceWei > 0)) return null
const nativeCost = gasUnits * gasPriceWei * 1e-18
const quoteCost = nativeCost * nativeTokenPrice
if (!(quoteCost > 0)) return null
return {
gasUnits,
gasPriceWei,
quoteCost,
source: `live cast estimate on DODOPMMIntegration mainnet swap path (${gasUnits} gas @ ${fmt(gasPriceWei)} wei)`,
}
}
function resolveTokenBalance({
chainId,
symbol,
tokenAddress,
report,
reportPath,
deployerAddress,
}) {
const live = tokenAddress && deployerAddress ? tryReadTokenBalanceViaCast(chainId, tokenAddress, deployerAddress) : null
if (live) return live
const reportBalance = sumReportBalance(report, chainId, symbol)
const reportInfo = sumReportBalanceInfo(report, chainId, symbol)
if (reportInfo) {
return {
...reportInfo,
source: reportPath ? `audit report ${reportPath}` : 'audit report',
}
}
if (reportBalance != null) {
return {
balance: reportBalance,
source: reportPath ? `audit report ${reportPath}` : 'audit report',
}
}
return null
}
function repayUsdc(grossQuoteIn, flashFeeBps) {
const bps = Math.max(0, flashFeeBps)
return grossQuoteIn * (1 + bps / 10000)
}
function repayUsdcWithExactFee(grossQuoteIn, flashFeeAmount, flashFeeBps) {
if (flashFeeAmount != null) return grossQuoteIn + flashFeeAmount
return repayUsdc(grossQuoteIn, flashFeeBps)
}
/** Net USDC per base after external sale (fold slippage + fees into P_eff) */
function effectiveExternalPrice(externalPrice, exitFeeBps) {
const bps = Math.min(10000, Math.max(0, exitFeeBps))
return externalPrice * ((10000 - bps) / 10000)
}
function effectiveExternalEntryPrice(externalPrice, entryFeeBps) {
const bps = Math.min(10000, Math.max(0, entryFeeBps))
return externalPrice * ((10000 + bps) / 10000)
}
function externalQuoteToBaseOut(grossQuoteIn, externalPrice, entryFeeBps, quoteDecimals, baseDecimals) {
const pEff = effectiveExternalEntryPrice(externalPrice, entryFeeBps)
const quoteInHuman = rawToHuman(grossQuoteIn, quoteDecimals)
const baseOutHuman = pEff > 0 ? quoteInHuman / pEff : 0
const baseOut = humanToRaw(baseOutHuman, baseDecimals)
return { effectivePrice: pEff, baseOut }
}
function externalBaseToQuoteOut(baseIn, externalPrice, exitFeeBps, baseDecimals, quoteDecimals) {
const pEff = effectiveExternalPrice(externalPrice, exitFeeBps)
const baseInHuman = rawToHuman(baseIn, baseDecimals)
const quoteOutHuman = baseInHuman * pEff
const quoteOut = humanToRaw(quoteOutHuman, quoteDecimals)
return { effectivePrice: pEff, quoteOut }
}
function formatExternalRoute(fromAsset, toAsset, viaAsset) {
return viaAsset ? `${fromAsset} -> ${viaAsset} -> ${toAsset}` : `${fromAsset} -> ${toAsset}`
}
function profit(grossQuoteIn, baseOut, externalPrice, flashFeeBps, exitFeeBps) {
const pEff = effectiveExternalPrice(externalPrice, exitFeeBps)
const proceeds = pEff * baseOut
const repay = repayUsdc(grossQuoteIn, flashFeeBps)
return proceeds - repay
}
function breakEvenExternalPrice(grossQuoteIn, baseOut, flashFeeBps, exitFeeBps) {
if (baseOut <= 0) return Infinity
const repay = repayUsdc(grossQuoteIn, flashFeeBps)
const exitMult = (10000 - Math.min(10000, Math.max(0, exitFeeBps))) / 10000
if (exitMult <= 0) return Infinity
return repay / (baseOut * exitMult)
}
function fmt(n) {
if (!Number.isFinite(n)) return String(n)
if (Math.abs(n) >= 1e9) return n.toExponential(4)
return n.toLocaleString('en-US', { maximumFractionDigits: 6 })
}
function rawToHuman(raw, decimals) {
if (!Number.isFinite(raw) || !Number.isFinite(decimals)) return NaN
return raw / 10 ** decimals
}
function humanToRaw(amount, decimals) {
if (!Number.isFinite(amount) || !Number.isFinite(decimals)) return NaN
return amount * 10 ** decimals
}
function convertRawAmount(raw, fromDecimals, toDecimals) {
if (!Number.isFinite(raw) || !Number.isFinite(fromDecimals) || !Number.isFinite(toDecimals)) {
return NaN
}
return humanToRaw(rawToHuman(raw, fromDecimals), toDecimals)
}
function fmtAmount(raw, decimals, symbol) {
if (!Number.isFinite(raw) || !Number.isFinite(decimals)) {
return symbol ? `${fmt(raw)} ${symbol}` : fmt(raw)
}
const human = rawToHuman(raw, decimals)
const humanLabel = symbol ? `${fmt(human)} ${symbol}` : fmt(human)
return `${humanLabel} (raw ${fmt(raw)})`
}
function approxBpsFromAmount(amount, feeAmount) {
if (!(amount > 0) || !Number.isFinite(feeAmount)) return NaN
return (feeAmount / amount) * 10000
}
function parseNum(s) {
const n = Number(s)
if (!Number.isFinite(n)) throw new Error(`Invalid number: ${s}`)
return n
}
function parsePositiveInt(s, label) {
const n = parseNum(s)
if (!Number.isInteger(n) || n <= 0) {
throw new Error(`${label} must be a positive integer`)
}
return n
}
function parseNonNegativeInt(s, label) {
const n = parseNum(s)
if (!Number.isInteger(n) || n < 0) {
throw new Error(`${label} must be a non-negative integer`)
}
return n
}
function marginalQuotePerBase(baseReserve, quoteReserve) {
if (!(baseReserve > 0) || !(quoteReserve >= 0)) return NaN
return quoteReserve / baseReserve
}
function deviationBps(price, oraclePrice) {
if (!(price >= 0) || !(oraclePrice > 0)) return NaN
return ((price - oraclePrice) / oraclePrice) * 10000
}
function calcNativeGasReserve(gasTxCount, gasPerTx, maxFeeGwei) {
if (!(gasTxCount > 0) || !(gasPerTx > 0) || !(maxFeeGwei > 0)) return 0
return gasTxCount * gasPerTx * maxFeeGwei * 1e-9
}
function buildInventoryLoopGuardConfig({
minRetainedUsdc,
gasTxCount,
gasPerTx,
maxFeeGwei,
nativeTokenPrice,
quoteDecimals,
oraclePrice,
maxPostTradeDeviationBps,
maxCwBurnFraction,
cooldownBlocks,
measuredGasQuote,
measuredGasSource,
estimatedGasQuote,
estimatedGasSource,
}) {
const measuredGasQuoteRaw =
measuredGasQuote != null && measuredGasQuote > 0 ? humanToRaw(measuredGasQuote, quoteDecimals) : 0
const estimatedGasQuoteRaw =
estimatedGasQuote != null && estimatedGasQuote > 0 ? humanToRaw(estimatedGasQuote, quoteDecimals) : 0
const gasReserveNative =
gasTxCount != null && gasPerTx != null && maxFeeGwei != null
? calcNativeGasReserve(gasTxCount, gasPerTx, maxFeeGwei)
: 0
const modeledGasReserveQuoteHuman =
gasReserveNative > 0 && nativeTokenPrice != null ? gasReserveNative * nativeTokenPrice : 0
const gasReserveQuoteRaw =
measuredGasQuoteRaw > 0
? measuredGasQuoteRaw
: estimatedGasQuoteRaw > 0
? estimatedGasQuoteRaw
: modeledGasReserveQuoteHuman > 0
? humanToRaw(modeledGasReserveQuoteHuman, quoteDecimals)
: 0
const gasReserveQuoteHuman =
measuredGasQuoteRaw > 0
? measuredGasQuote
: estimatedGasQuoteRaw > 0
? estimatedGasQuote
: modeledGasReserveQuoteHuman
return {
minRetainedUsdc,
gasTxCount,
gasPerTx,
maxFeeGwei,
nativeTokenPrice,
quoteDecimals,
gasReserveNative,
gasReserveQuoteHuman,
gasReserveQuote: gasReserveQuoteRaw,
gasReserveMode:
measuredGasQuoteRaw > 0
? 'measured_quote'
: estimatedGasQuoteRaw > 0
? 'estimated_quote'
: 'modeled_native',
gasReserveSource:
measuredGasQuoteRaw > 0
? measuredGasSource ?? 'CLI measured gas quote override'
: estimatedGasQuoteRaw > 0
? estimatedGasSource ?? 'live integration gas estimate'
: 'modeled from gas policy inputs',
requiredRetainedUsdc: minRetainedUsdc + gasReserveQuoteRaw,
oraclePrice,
maxPostTradeDeviationBps,
maxCwBurnFraction,
cooldownBlocks,
}
}
function summarizeGasReserve(guardConfig) {
if (!(guardConfig.gasReserveQuote > 0)) return null
if (guardConfig.gasReserveMode === 'measured_quote') {
return `${fmt(guardConfig.gasReserveQuoteHuman ?? rawToHuman(guardConfig.gasReserveQuote, guardConfig.quoteDecimals))} quote units from ${guardConfig.gasReserveSource}`
}
if (guardConfig.gasReserveMode === 'estimated_quote') {
return `${fmt(guardConfig.gasReserveQuoteHuman ?? rawToHuman(guardConfig.gasReserveQuote, guardConfig.quoteDecimals))} quote units from ${guardConfig.gasReserveSource}`
}
return `${guardConfig.gasTxCount} tx * ${fmt(guardConfig.gasPerTx)} gas * ${fmt(guardConfig.maxFeeGwei)} gwei @ native price ${fmt(guardConfig.nativeTokenPrice)}`
}
function classifyExecutionReadiness({
strategyLabel,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode,
maxPostTradeDeviationBps,
}) {
const missing = listExecutionReadinessBlocks({
strategyLabel,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode,
maxPostTradeDeviationBps,
})
if (missing.length === 0) return 'execution-ready'
if (missing.some((item) => item.includes('live pool quote surface'))) return 'blocked'
return 'planning'
}
function hasRequiredLivePoolQuoteSurface(strategyLabel, quoteSurface) {
if (!quoteSurface) return false
if (typeof quoteSurface === 'string') return quoteSurface === 'full_quote_surface'
if (quoteSurface.surface === 'full_quote_surface') return true
if (strategyLabel === 'quote-push') return quoteSurface.quotePushOk === true
if (strategyLabel === 'base-unwind') return quoteSurface.baseUnwindOk === true
if (strategyLabel === 'both') {
return quoteSurface.quotePushOk === true && quoteSurface.baseUnwindOk === true
}
return false
}
function listExecutionReadinessBlocks({
strategyLabel,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode,
maxPostTradeDeviationBps,
}) {
const hasLivePoolQuote = hasRequiredLivePoolQuoteSurface(strategyLabel, quoteSurface)
const needsLiveEntry = strategyLabel === 'base-unwind' || strategyLabel === 'both'
const needsLiveExit = strategyLabel === 'quote-push' || strategyLabel === 'both'
const hasLiveExternalEntry =
!needsLiveEntry || externalEntrySource == null || externalEntrySource === 'live'
const hasLiveExternalExit =
!needsLiveExit || externalExitSource == null || externalExitSource === 'live'
const hasMeasuredGas = gasReserveMode === 'measured_quote' || gasReserveMode === 'estimated_quote'
const hasExplicitDeviationCap = maxPostTradeDeviationBps != null
const missing = []
if (!hasLivePoolQuote) {
missing.push(
strategyLabel === 'both'
? 'full live pool quote surface'
: `live pool quote surface for ${strategyLabel}`,
)
}
if (!hasLiveExternalEntry) missing.push('live external entry quote source')
if (!hasLiveExternalExit) missing.push('live external exit quote source')
if (!hasMeasuredGas) missing.push('measured or live-estimated gas')
if (!hasExplicitDeviationCap) missing.push('explicit post-trade deviation cap')
return missing
}
function formatGuardStatus(candidate) {
return candidate.recommendationOk ? 'pass' : candidate.guardFailures.join('+')
}
function cmpAsc(a, b) {
return a - b
}
function cmpDesc(a, b) {
return b - a
}
function compareRankProfileMetrics(a, b, metrics) {
for (const metric of metrics) {
const av = metric.pick(a)
const bv = metric.pick(b)
if (av !== bv) return metric.order(av, bv)
}
return 0
}
function eligibleRankMetrics(targetFlashBorrow, rankProfile) {
const efficiencyMetric =
targetFlashBorrow != null
? (candidate) => candidate.retainedAfterTargetFlashPerCw
: (candidate) => candidate.retainedPerCw
switch (rankProfile) {
case 'conservative':
return [
{ pick: (candidate) => candidate.postTradeDeviationAbsBps, order: cmpAsc },
{ pick: (candidate) => candidate.inventoryBurnFraction ?? Infinity, order: cmpAsc },
{ pick: (candidate) => candidate.grossBaseIn, order: cmpAsc },
...(targetFlashBorrow != null
? [
{ pick: (candidate) => candidate.floorMarginAfterTargetFlash, order: cmpDesc },
{ pick: (candidate) => candidate.repayMargin, order: cmpDesc },
]
: [
{ pick: (candidate) => candidate.maxFlashKeepFloor, order: cmpDesc },
{ pick: (candidate) => candidate.floorSurplusNoFlash, order: cmpDesc },
]),
{ pick: efficiencyMetric, order: cmpDesc },
]
case 'efficiency':
return [
{ pick: efficiencyMetric, order: cmpDesc },
...(targetFlashBorrow != null
? [
{ pick: (candidate) => candidate.floorMarginAfterTargetFlash, order: cmpDesc },
{ pick: (candidate) => candidate.repayMargin, order: cmpDesc },
]
: [
{ pick: (candidate) => candidate.maxFlashKeepFloor, order: cmpDesc },
{ pick: (candidate) => candidate.floorSurplusNoFlash, order: cmpDesc },
]),
{ pick: (candidate) => candidate.postTradeDeviationAbsBps, order: cmpAsc },
{ pick: (candidate) => candidate.inventoryBurnFraction ?? Infinity, order: cmpAsc },
{ pick: (candidate) => candidate.grossBaseIn, order: cmpAsc },
]
case 'balanced':
default:
return [
...(targetFlashBorrow != null
? [
{ pick: (candidate) => candidate.repayMargin, order: cmpDesc },
{ pick: (candidate) => candidate.floorMarginAfterTargetFlash, order: cmpDesc },
]
: [
{ pick: (candidate) => candidate.maxFlashKeepFloor, order: cmpDesc },
{ pick: (candidate) => candidate.floorSurplusNoFlash, order: cmpDesc },
]),
{ pick: efficiencyMetric, order: cmpDesc },
{ pick: (candidate) => candidate.postTradeDeviationAbsBps, order: cmpAsc },
{ pick: (candidate) => candidate.inventoryBurnFraction ?? Infinity, order: cmpAsc },
{ pick: (candidate) => candidate.grossBaseIn, order: cmpAsc },
]
}
}
function efficiencyMetricLabel(targetFlashBorrow) {
return targetFlashBorrow != null ? 'retained_after_repay_per_cw' : 'retained_per_cw'
}
function candidateEfficiencyValue(candidate, targetFlashBorrow) {
return targetFlashBorrow != null ? candidate.retainedAfterTargetFlashPerCw : candidate.retainedPerCw
}
function rankProfileSummary(rankProfile, targetFlashBorrow) {
switch (rankProfile) {
case 'conservative':
return targetFlashBorrow != null
? 'lowest post-trade deviation, lowest cW burn, then stronger post-repay safety headroom'
: 'lowest post-trade deviation, lowest cW burn, then stronger retained-floor headroom'
case 'efficiency':
return targetFlashBorrow != null
? 'best retained USDC after repay per cW, then safety headroom, then lower impact'
: 'best retained USDC per cW, then retained-floor headroom, then lower impact'
case 'balanced':
default:
return targetFlashBorrow != null
? 'strongest repay margin and post-repay floor headroom, then better efficiency and lower impact'
: 'largest flash/floor headroom, then better efficiency and lower impact'
}
}
function explainWinningCandidate(recommended, runnerUp, rankProfile, targetFlashBorrow) {
if (!recommended) return null
const efficiencyLabel = efficiencyMetricLabel(targetFlashBorrow)
const recommendedEfficiency = fmt(candidateEfficiencyValue(recommended, targetFlashBorrow))
switch (rankProfile) {
case 'conservative':
if (runnerUp) {
return `Won on lower post-trade deviation (${fmt(recommended.postTradeDeviationAbsBps)} vs ${fmt(runnerUp.postTradeDeviationAbsBps)} bps) and lower cW burn (${fmt(recommended.inventoryBurnFraction)} vs ${fmt(runnerUp.inventoryBurnFraction)}).`
}
return `Won by minimizing post-trade deviation (${fmt(recommended.postTradeDeviationAbsBps)} bps) and cW burn (${fmt(recommended.inventoryBurnFraction)}).`
case 'efficiency':
if (runnerUp) {
return `Won on better ${efficiencyLabel} (${recommendedEfficiency} vs ${fmt(candidateEfficiencyValue(runnerUp, targetFlashBorrow))}) while still passing the active guard set.`
}
return `Won on best ${efficiencyLabel} (${recommendedEfficiency}) among the eligible set.`
case 'balanced':
default:
if (targetFlashBorrow != null) {
if (runnerUp) {
return `Won on stronger repay margin (${fmt(recommended.repayMargin)} vs ${fmt(runnerUp.repayMargin)}) and post-repay floor margin (${fmt(recommended.floorMarginAfterTargetFlash)} vs ${fmt(runnerUp.floorMarginAfterTargetFlash)}).`
}
return `Won on strongest repay margin (${fmt(recommended.repayMargin)}) and post-repay floor margin (${fmt(recommended.floorMarginAfterTargetFlash)}).`
}
if (runnerUp) {
return `Won on higher max flash-with-floor headroom (${fmt(recommended.maxFlashKeepFloor)} vs ${fmt(runnerUp.maxFlashKeepFloor)}) and higher floor surplus (${fmt(recommended.floorSurplusNoFlash)} vs ${fmt(runnerUp.floorSurplusNoFlash)}).`
}
return `Won on highest flash-with-floor headroom (${fmt(recommended.maxFlashKeepFloor)}) and floor surplus (${fmt(recommended.floorSurplusNoFlash)}).`
}
}
function printScenario(label, B, Q, x, lpFeeBps, flashFeeBps, externalPrice, exitFeeBps) {
const { deltaXNet, baseOut, vwap } = quoteInToBaseOut(B, Q, x, lpFeeBps)
const repay = repayUsdc(x, flashFeeBps)
const pStar = breakEvenExternalPrice(x, baseOut, flashFeeBps, exitFeeBps)
const pi =
externalPrice != null && Number.isFinite(externalPrice)
? profit(x, baseOut, externalPrice, flashFeeBps, exitFeeBps)
: null
console.log(`--- ${label} ---`)
console.log(` baseReserve B=${fmt(B)} quoteReserve Q=${fmt(Q)} gross quote in x=${fmt(x)}`)
console.log(` lpFeeBps=${lpFeeBps} flashFeeBps=${flashFeeBps} exitFeeBps=${exitFeeBps}`)
console.log(` Δx_net (after LP fee)=${fmt(deltaXNet)}`)
console.log(` base out Δy=${fmt(baseOut)}`)
console.log(` VWAP (gross quote / base)=${fmt(vwap)}`)
console.log(` repay (x * (1+flash))=${fmt(repay)}`)
console.log(` break-even P_ext*=${fmt(pStar)} quote per base`)
if (pi != null) console.log(` PnL @ externalPrice=${externalPrice} (after exit fee)=${fmt(pi)}`)
console.log('')
}
function printMainnetMap(
compareDeepenDelta,
B,
Q,
scanStr,
lpFeeBps,
registryFeeBps,
preferRegistryFeeForDeepen,
) {
const m = loadMainnetCwUsdcUsdc()
console.log('Ethereum Mainnet — cWUSDC / USDC PMM mapping (repo registry)\n')
if (!m) {
console.log(' (Could not read cross-chain-pmm-lps/config/deployment-status.json)\n')
return
}
const feeForTables =
compareDeepenDelta != null && preferRegistryFeeForDeepen && registryFeeBps != null
? registryFeeBps
: lpFeeBps
const feeSource =
compareDeepenDelta != null && preferRegistryFeeForDeepen && registryFeeBps != null
? 'registry row fee (default for --compare-deepen)'
: '--lp-fee-bps'
console.log(' Token cWUSDC (ops shorthand xWUSDC):', m.cWUSDC)
console.log(' Token USDC (anchor): ', m.USDC)
console.log(' DODO PMM pool: ', m.poolAddress)
console.log(' Registered LP fee: ', m.feeBps, 'bps')
console.log('')
console.log(' Loop (funded USDC inventory, not necessarily flash credit):')
console.log(' USDC → ETH (Uniswap / deep CLOB): charge slippage + pool fee into leg-1')
console.log(' ETH → cWUSDC: use any liquid route; if none, extra hop(s) — fold into acquisition cost')
console.log(' cWUSDC → USDC on this PMM: sell-base formula')
console.log(' quoteOut = netBaseIn * Q / (B + netBaseIn)')
console.log('')
console.log(' For acquisition via PMM (USDC → cWUSDC) use quote-in branch (this script default):')
console.log(' baseOut = netQuoteIn * B / (Q + netQuoteIn)')
console.log('')
console.log(' Model Aave-style flash: keep --flash-fee-bps 5; funded pool loop: often --flash-fee-bps 0.')
console.log('')
if (compareDeepenDelta != null && Number.isFinite(compareDeepenDelta) && compareDeepenDelta > 0) {
if (B == null || Q == null) {
console.log(' --compare-deepen requires -B and -Q (live reserves from pool getVaultReserve).')
return
}
const sizes = scanStr
? scanStr.split(',').map((s) => parseNum(s.trim()))
: [500_000, 1_000_000, 2_000_000, 5_000_000]
const B2 = B + compareDeepenDelta
console.log(
` Depth add: +${fmt(compareDeepenDelta)} cWUSDC to base → B: ${fmt(B)}${fmt(B2)} (Q fixed ${fmt(Q)})`,
)
console.log(` Table LP fee: ${feeForTables} bps (${feeSource})`)
console.log('')
console.log(' USDC→cWUSDC (quote in): trade_x | baseOut_before | VWAP_before | baseOut_after | VWAP_after')
for (const x of sizes) {
const a = quoteInToBaseOut(B, Q, x, feeForTables)
const b = quoteInToBaseOut(B2, Q, x, feeForTables)
console.log(
[fmt(x), fmt(a.baseOut), fmt(a.vwap), fmt(b.baseOut), fmt(b.vwap)].join('\t'),
)
}
console.log('')
console.log(' cWUSDC→USDC (base in, same sizes as cWUSDC sold): | quoteOut_before | USDC/base | quoteOut_after | USDC/base')
for (const x of sizes) {
const a = baseInToQuoteOut(B, Q, x, feeForTables)
const b = baseInToQuoteOut(B2, Q, x, feeForTables)
console.log(
[fmt(x), fmt(a.quoteOut), fmt(a.vwapQuotePerBase), fmt(b.quoteOut), fmt(b.vwapQuotePerBase)].join(
'\t',
),
)
}
console.log('')
}
}
function printInventoryCoverage(inventoryBase, requiredBase, label = 'Required cW base inventory') {
if (inventoryBase == null) return
const remaining = inventoryBase - requiredBase
console.log(` inventoryBase available=${fmt(inventoryBase)}`)
console.log(` ${label}=${fmt(requiredBase)}`)
console.log(
` inventory coverage=${remaining >= 0 ? 'enough' : 'short'} (${remaining >= 0 ? 'remaining' : 'shortfall'} ${fmt(Math.abs(remaining))})`,
)
}
function printSeedingPlanFromPmm(
B,
Q,
totalQuoteTarget,
lpFeeBps,
inventoryBase,
loopCount,
seedPools,
targetQuotePerPool,
) {
console.log('Quote seeding plan — source PMM sell-base path\n')
console.log(` source reserves: B=${fmt(B)} cW base, Q=${fmt(Q)} USDC quote`)
console.log(` pool fee=${lpFeeBps} bps`)
console.log(` target USDC to raise=${fmt(totalQuoteTarget)}`)
if (seedPools != null) console.log(` target pools=${seedPools}`)
if (targetQuotePerPool != null) console.log(` target USDC per pool=${fmt(targetQuotePerPool)}`)
console.log(` loop count=${loopCount}`)
console.log('')
const direct = baseInRequiredForQuoteOut(B, Q, totalQuoteTarget, lpFeeBps)
if (!direct.feasible) {
console.log(' Target quote exceeds available source quote reserve; cannot fully harvest that much in this PMM.')
return
}
console.log(' Single-shot requirement from current reserves:')
console.log(` gross cW base sacrifice=${fmt(direct.grossBaseIn)}`)
console.log(` net cW base into pool=${fmt(direct.deltaBaseNet)}`)
console.log(` LP fee paid in base=${fmt(direct.feeBase)}`)
console.log(` realized USDC per gross cW base=${fmt(direct.vwapQuotePerBase)}`)
printInventoryCoverage(inventoryBase, direct.grossBaseIn)
console.log('')
const splitTargets =
targetQuotePerPool != null && seedPools != null && loopCount === seedPools
? Array.from({ length: loopCount }, () => targetQuotePerPool)
: Array.from({ length: loopCount }, () => totalQuoteTarget / loopCount)
let runningB = B
let runningQ = Q
let cumulativeQuote = 0
let cumulativeGrossBase = 0
let cumulativeNetBase = 0
let cumulativeFeeBase = 0
console.log(' Liquidity loop table:')
console.log(
'loop\tquote_target\tgross_base_in\tnet_base_in\tfee_base\tUSDC/gross_base\tend_B\tend_Q\tcum_quote\tcum_gross_base',
)
for (let i = 0; i < splitTargets.length; i += 1) {
const quoteTarget = splitTargets[i]
const leg = baseInRequiredForQuoteOut(runningB, runningQ, quoteTarget, lpFeeBps)
if (!leg.feasible) {
console.log(`${i + 1}\t${fmt(quoteTarget)}\tINFEASIBLE\tINFEASIBLE\tINFEASIBLE\tINFEASIBLE\t${fmt(runningB)}\t${fmt(runningQ)}\t${fmt(cumulativeQuote)}\t${fmt(cumulativeGrossBase)}`)
break
}
runningB += leg.deltaBaseNet
runningQ -= quoteTarget
cumulativeQuote += quoteTarget
cumulativeGrossBase += leg.grossBaseIn
cumulativeNetBase += leg.deltaBaseNet
cumulativeFeeBase += leg.feeBase
console.log(
[
i + 1,
fmt(quoteTarget),
fmt(leg.grossBaseIn),
fmt(leg.deltaBaseNet),
fmt(leg.feeBase),
fmt(leg.vwapQuotePerBase),
fmt(runningB),
fmt(runningQ),
fmt(cumulativeQuote),
fmt(cumulativeGrossBase),
].join('\t'),
)
}
console.log('')
console.log(' End state after loops:')
console.log(` total quote raised=${fmt(cumulativeQuote)}`)
console.log(` cumulative gross cW base sacrifice=${fmt(cumulativeGrossBase)}`)
console.log(` cumulative net cW base into source pool=${fmt(cumulativeNetBase)}`)
console.log(` cumulative LP fee paid in base=${fmt(cumulativeFeeBase)}`)
console.log(` final source reserves: B=${fmt(runningB)} Q=${fmt(runningQ)}`)
printInventoryCoverage(inventoryBase, cumulativeGrossBase, 'Looped cW base inventory required')
console.log('')
}
function printSeedingPlanExternal(
totalQuoteTarget,
externalPrice,
exitFeeBps,
inventoryBase,
loopCount,
seedPools,
targetQuotePerPool,
) {
const pEff = effectiveExternalPrice(externalPrice, exitFeeBps)
console.log('Quote seeding plan — external monetization rate\n')
console.log(` gross external price=${fmt(externalPrice)} USDC per cW base`)
console.log(` net effective price=${fmt(pEff)} USDC per cW base`)
console.log(` target USDC to raise=${fmt(totalQuoteTarget)}`)
if (seedPools != null) console.log(` target pools=${seedPools}`)
if (targetQuotePerPool != null) console.log(` target USDC per pool=${fmt(targetQuotePerPool)}`)
console.log(` loop count=${loopCount}`)
console.log('')
if (!(pEff > 0)) {
console.log(' Effective monetization price is zero or negative; cannot size required cW inventory.')
return
}
const grossBaseRequired = totalQuoteTarget / pEff
console.log(` gross cW base sacrifice required=${fmt(grossBaseRequired)}`)
console.log(` realized USDC per gross cW base=${fmt(pEff)}`)
printInventoryCoverage(inventoryBase, grossBaseRequired)
console.log('')
if (loopCount > 1) {
const perLoopQuote = totalQuoteTarget / loopCount
const perLoopBase = perLoopQuote / pEff
let cumulativeQuote = 0
let cumulativeBase = 0
console.log(' Liquidity loop table:')
console.log('loop\tquote_target\tgross_base_in\tUSDC/gross_base\tcum_quote\tcum_gross_base')
for (let i = 0; i < loopCount; i += 1) {
cumulativeQuote += perLoopQuote
cumulativeBase += perLoopBase
console.log(
[i + 1, fmt(perLoopQuote), fmt(perLoopBase), fmt(pEff), fmt(cumulativeQuote), fmt(cumulativeBase)].join(
'\t',
),
)
}
console.log('')
}
}
function printFundingReadiness({
inventoryAsset,
sourceAsset,
quoteAsset,
totalQuoteTarget,
lpFeeBps,
baseReserve,
quoteReserve,
reserveSource,
poolAddress,
report,
reportPath,
}) {
const mainnetPool = loadMainnetPool(inventoryAsset, quoteAsset)
const direct = baseInRequiredForQuoteOut(baseReserve, quoteReserve, totalQuoteTarget, lpFeeBps)
const deployerAddress = resolveDeployerAddressViaCast()
const mainnetTokenAddress = mainnetPool?.baseAddress ?? null
const mainnetQuoteAddress = mainnetPool?.quoteAddress ?? null
const chain138TokenAddress = loadChain138TokenAddress(sourceAsset)
const mainnetBalance = resolveTokenBalance({
chainId: 1,
symbol: inventoryAsset,
tokenAddress: mainnetTokenAddress,
report,
reportPath,
deployerAddress,
})
const chain138Balance = resolveTokenBalance({
chainId: 138,
symbol: sourceAsset,
tokenAddress: chain138TokenAddress,
report,
reportPath,
deployerAddress,
})
const inventoryDecimals =
mainnetBalance?.decimals ?? tryReadTokenDecimalsViaCast(1, mainnetTokenAddress) ?? 6
const sourceDecimals =
chain138Balance?.decimals ?? tryReadTokenDecimalsViaCast(138, chain138TokenAddress) ?? inventoryDecimals
const quoteDecimals = tryReadTokenDecimalsViaCast(1, mainnetQuoteAddress) ?? inventoryDecimals
const mainnetAvailableHuman = mainnetBalance?.balance ?? 0
const chain138AvailableHuman = chain138Balance?.balance ?? 0
const mainnetAvailableRawOnPoolScale = humanToRaw(mainnetAvailableHuman, inventoryDecimals)
const chain138AvailableRawOnPoolScale = humanToRaw(chain138AvailableHuman, inventoryDecimals)
const mainnetImmediateQuoteRaw =
mainnetAvailableRawOnPoolScale > 0
? baseInToQuoteOut(baseReserve, quoteReserve, mainnetAvailableRawOnPoolScale, lpFeeBps).quoteOut
: 0
const bridgeReachableQuoteRaw =
chain138AvailableRawOnPoolScale > 0
? baseInToQuoteOut(baseReserve, quoteReserve, chain138AvailableRawOnPoolScale, lpFeeBps).quoteOut
: 0
const requiredGrossHuman = rawToHuman(direct.grossBaseIn, inventoryDecimals)
const requiredNetHuman = rawToHuman(direct.deltaBaseNet, inventoryDecimals)
const feeBaseHuman = rawToHuman(direct.feeBase, inventoryDecimals)
const mainnetEnough = direct.feasible && mainnetAvailableHuman >= requiredGrossHuman
const bridgeEnough = direct.feasible && chain138AvailableHuman >= requiredGrossHuman
console.log('Funding readiness — live mainnet vs bridge-reachable inventory\n')
console.log(` inventory asset=${inventoryAsset} source asset=${sourceAsset} quote asset=${quoteAsset}`)
console.log(` target ${quoteAsset} to raise=${fmtAmount(totalQuoteTarget, quoteDecimals, quoteAsset)}`)
console.log(` pool fee=${lpFeeBps} bps`)
console.log(
` mainnet pool reserves: B=${fmtAmount(baseReserve, inventoryDecimals, inventoryAsset)}, Q=${fmtAmount(quoteReserve, quoteDecimals, quoteAsset)}`,
)
console.log(` reserve source=${reserveSource}`)
if (poolAddress) console.log(` mainnet pool=${poolAddress}`)
if (deployerAddress) console.log(` deployer=${deployerAddress}`)
if (reportPath) console.log(` balance report fallback=${reportPath}`)
console.log('')
if (!direct.feasible) {
console.log(' Target quote exceeds available quote reserve in the current PMM; no readiness conclusion can be made.')
console.log('')
return
}
console.log(' Requirement at current live pool state:')
console.log(` required gross ${inventoryAsset}=${fmt(requiredGrossHuman)} ${inventoryAsset} (raw ${fmt(direct.grossBaseIn)})`)
console.log(` required net ${inventoryAsset} into pool=${fmt(requiredNetHuman)} ${inventoryAsset} (raw ${fmt(direct.deltaBaseNet)})`)
console.log(` implied LP fee in base=${fmt(feeBaseHuman)} ${inventoryAsset} (raw ${fmt(direct.feeBase)})`)
console.log(` realized ${quoteAsset} per gross ${inventoryAsset}=${fmt(direct.vwapQuotePerBase)}`)
console.log('')
console.log(' View 1 — already funded on mainnet today:')
console.log(` available ${inventoryAsset} on mainnet=${fmt(mainnetAvailableHuman)} ${inventoryAsset}${mainnetBalance?.raw != null ? ` (raw ${fmt(mainnetBalance.raw)})` : ''}`)
console.log(` balance source=${mainnetBalance?.source ?? 'unavailable'}`)
console.log(` immediate quote capacity at current pool=${fmt(rawToHuman(mainnetImmediateQuoteRaw, quoteDecimals))} ${quoteAsset} (raw ${fmt(mainnetImmediateQuoteRaw)})`)
console.log(
` status=${mainnetEnough ? 'enough now' : 'short'} (${mainnetEnough ? 'remaining' : 'shortfall'} ${fmt(Math.abs(mainnetAvailableHuman - requiredGrossHuman))} ${inventoryAsset})`,
)
console.log('')
console.log(' View 2 — reachable after bridging from current Chain 138 inventory:')
console.log(` available ${sourceAsset} on Chain 138=${fmt(chain138AvailableHuman)} ${sourceAsset}${chain138Balance?.raw != null ? ` (raw ${fmt(chain138Balance.raw)})` : ''}`)
console.log(` balance source=${chain138Balance?.source ?? 'unavailable'}`)
console.log(` bridge-reachable quote capacity at current pool=${fmt(rawToHuman(bridgeReachableQuoteRaw, quoteDecimals))} ${quoteAsset} (raw ${fmt(bridgeReachableQuoteRaw)})`)
console.log(
` status=${bridgeEnough ? 'enough after bridge' : 'short'} (${bridgeEnough ? 'remaining' : 'shortfall'} ${fmt(Math.abs(chain138AvailableHuman - requiredGrossHuman))} ${sourceAsset})`,
)
console.log('')
console.log(' Assumption for View 2: 1:1 nominal c* -> cW* corridor, ignoring bridge fees, caps, and transfer latency.')
console.log('')
}
function buildQuoteDeploymentSteps({
retainedQuote,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
}) {
if (targetQuotePerPool == null && targetTotalQuote == null) return null
const totalTarget =
targetTotalQuote != null
? targetTotalQuote
: (seedPools ?? loopCount ?? 1) * targetQuotePerPool
const steps =
targetQuotePerPool != null && seedPools != null
? Array.from({ length: seedPools }, (_, index) => ({
label: `pool_${index + 1}`,
targetQuote: targetQuotePerPool,
}))
: Array.from({ length: loopCount ?? 1 }, (_, index) => ({
label: `loop_${index + 1}`,
targetQuote: totalTarget / (loopCount ?? 1),
}))
let remainingQuote = Math.max(0, retainedQuote)
const rows = steps.map((step) => {
const deployedQuote = Math.min(step.targetQuote, remainingQuote)
remainingQuote -= deployedQuote
return {
...step,
deployedQuote,
shortfallQuote: step.targetQuote - deployedQuote,
fullyFunded: deployedQuote >= step.targetQuote,
remainingQuote,
}
})
const fullyFundedCount = rows.filter((row) => row.fullyFunded).length
const deployedTotal = rows.reduce((sum, row) => sum + row.deployedQuote, 0)
return {
totalTarget,
rows,
fullyFundedCount,
deployedTotal,
remainingQuote,
shortfallQuote: Math.max(0, totalTarget - deployedTotal),
}
}
function printQuoteDeploymentPlan({
retainedQuote,
quoteAsset,
quoteDecimals,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
}) {
const plan = buildQuoteDeploymentSteps({
retainedQuote,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
})
if (!plan) {
console.log(` no destination pool target provided; retained ${quoteAsset} remains unallocated`)
return
}
console.log('Destination pool deployment')
console.log(` retained ${quoteAsset} available=${fmtAmount(retainedQuote, quoteDecimals, quoteAsset)}`)
if (seedPools != null) console.log(` target pools=${seedPools}`)
if (targetQuotePerPool != null) console.log(` target ${quoteAsset} per pool=${fmtAmount(targetQuotePerPool, quoteDecimals, quoteAsset)}`)
if (targetTotalQuote != null) console.log(` target total ${quoteAsset}=${fmtAmount(targetTotalQuote, quoteDecimals, quoteAsset)}`)
if (loopCount != null) console.log(` deployment loops=${loopCount}`)
console.log(
` status=${plan.shortfallQuote > 0 ? 'short' : 'enough'} (${plan.shortfallQuote > 0 ? 'shortfall' : 'leftover'} ${fmtAmount(
plan.shortfallQuote > 0 ? plan.shortfallQuote : plan.remainingQuote,
quoteDecimals,
quoteAsset,
)})`,
)
if (targetQuotePerPool != null) {
console.log(` fully funded pools=${plan.fullyFundedCount}`)
}
console.log('')
console.log('step\ttarget_quote\tdeployed_quote\tshortfall_quote\tremaining_quote\tstatus')
for (const row of plan.rows) {
console.log(
[
row.label,
fmtAmount(row.targetQuote, quoteDecimals, quoteAsset),
fmtAmount(row.deployedQuote, quoteDecimals, quoteAsset),
fmtAmount(row.shortfallQuote, quoteDecimals, quoteAsset),
fmtAmount(row.remainingQuote, quoteDecimals, quoteAsset),
row.fullyFunded ? 'funded' : 'partial',
].join('\t'),
)
}
console.log('')
}
function simulateFullLoopDryRun({
B,
Q,
x,
lpFeeBps,
flashFeeBps,
loopStrategy,
ownedBaseAdd,
flashTopupQuote,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig,
flashProviderCap,
flashProviderName,
flashFeeAmount,
flashFeeSource,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
}) {
const repay = repayUsdcWithExactFee(x, flashFeeAmount, flashFeeBps)
const effectiveBaseReserve = B + ownedBaseAdd
const effectiveQuoteReserve = Q + flashTopupQuote
const strategyQuote = Math.max(0, x - flashTopupQuote)
const strategyLabel = loopStrategy === 'base-unwind' ? 'base-unwind' : 'quote-push'
let leg
let externalLeg
let availableForRepay
let endBaseReserve
let endQuoteReserve
let step2MetricA
let step2MetricB
let step2MetricC
let step3MetricA
let step3MetricB
let strategyNote
let atomicBaseReserved = 0
let atomicBaseRequested = atomicBridgeBaseAmount ?? 0
let atomicDestinationFulfilled = 0
let unwindBaseAmount = 0
let atomicBridgeShortfall = 0
if (strategyLabel === 'base-unwind') {
externalLeg = externalQuoteToBaseOut(
strategyQuote,
externalEntryPrice,
externalEntryFeeBps,
quoteDecimals,
baseDecimals,
)
leg = baseInToQuoteOut(effectiveBaseReserve, effectiveQuoteReserve, externalLeg.baseOut, lpFeeBps)
availableForRepay = leg.quoteOut
endBaseReserve = effectiveBaseReserve + leg.deltaBaseNet
endQuoteReserve = Math.max(0, effectiveQuoteReserve - leg.quoteOut)
step2MetricA = ['2', `external_route_${formatExternalRoute(quoteAsset, baseAsset, externalViaAsset).replaceAll(' ', '_')}`, fmtAmount(strategyQuote, quoteDecimals, quoteAsset)]
step2MetricB = ['2', 'external_entry_price_effective', fmt(externalLeg.effectivePrice)]
step2MetricC = ['2', 'external_base_acquired', fmtAmount(externalLeg.baseOut, baseDecimals, baseAsset)]
step3MetricA = ['3', 'pmm_base_in_net', fmtAmount(leg.deltaBaseNet, baseDecimals, baseAsset)]
step3MetricB = ['3', 'pmm_quote_out', fmtAmount(leg.quoteOut, quoteDecimals, quoteAsset)]
strategyNote =
ownedBaseAdd > 0
? ' note: this is the owned-base-add + external-acquire -> PMM sell-base path, so the source pool starts deeper on base, then gains more base reserve and loses quote reserve. Any temporary flash quote top-up left in the source pool is bounded by the PMM quote out used for repayment.'
: ' note: this is the external-acquire -> PMM sell-base path, so the source pool gains base reserve and loses quote reserve. Any temporary flash quote top-up left in the source pool is bounded by the PMM quote out used for repayment.'
} else {
leg = quoteInToBaseOut(effectiveBaseReserve, effectiveQuoteReserve, strategyQuote, lpFeeBps)
atomicBaseReserved = Math.min(Math.max(0, atomicBaseRequested), leg.baseOut)
atomicBridgeShortfall = Math.max(0, atomicBaseRequested - leg.baseOut)
unwindBaseAmount = Math.max(0, leg.baseOut - atomicBaseReserved)
atomicDestinationFulfilled =
atomicBaseReserved > 0
? (atomicDestinationAmount ??
convertRawAmount(
atomicBaseReserved,
baseDecimals,
atomicDestinationDecimals ?? baseDecimals,
))
: 0
externalLeg = externalBaseToQuoteOut(
unwindBaseAmount,
externalExitPrice,
externalExitFeeBps,
baseDecimals,
quoteDecimals,
)
availableForRepay = externalLeg.quoteOut
endBaseReserve = effectiveBaseReserve - leg.baseOut
endQuoteReserve = effectiveQuoteReserve + leg.deltaXNet
step2MetricA = ['2', 'pmm_quote_in_net', fmtAmount(leg.deltaXNet, quoteDecimals, quoteAsset)]
step2MetricB = ['2', 'pmm_base_out', fmtAmount(leg.baseOut, baseDecimals, baseAsset)]
step2MetricC = ['2', 'pmm_vwap_quote_per_base', fmt(rawToHuman(strategyQuote, quoteDecimals) / rawToHuman(leg.baseOut, baseDecimals))]
step3MetricA = ['3', `external_route_${formatExternalRoute(baseAsset, quoteAsset, externalViaAsset).replaceAll(' ', '_')}`, fmtAmount(unwindBaseAmount, baseDecimals, baseAsset)]
step3MetricB = ['3', 'external_exit_price_effective', fmt(externalLeg.effectivePrice)]
strategyNote =
ownedBaseAdd > 0
? ' note: this is the owned-base-add + flash-backed quote-in path, so the source pool starts deeper on base, then permanently gains quote reserve and loses some base reserve if the external unwind covers repayment.'
: ' note: this is the flash-backed quote-in path, so the source pool permanently gains quote reserve and loses base reserve if the external unwind covers repayment.'
if (atomicBaseReserved > 0) {
strategyNote += ` ${fmtAmount(atomicBaseReserved, baseDecimals, baseAsset)} is reserved into the atomic corridor${atomicCorridorLabel ? ` (${atomicCorridorLabel})` : ''}, and only the remaining ${fmtAmount(unwindBaseAmount, baseDecimals, baseAsset)} is unwound back into ${quoteAsset} for flash repayment.`
}
}
const retainedBeforeGas = availableForRepay - repay
const retainedAfterGas = retainedBeforeGas - guardConfig.gasReserveQuote
const postTradeMarginalPrice =
rawToHuman(endBaseReserve, baseDecimals) > 0
? rawToHuman(endQuoteReserve, quoteDecimals) / rawToHuman(endBaseReserve, baseDecimals)
: NaN
const postTradeDeviationBps = deviationBps(postTradeMarginalPrice, guardConfig.oraclePrice)
const postTradeDeviationAbsBps = Math.abs(postTradeDeviationBps)
const gasReserveSummary = summarizeGasReserve(guardConfig)
const providerCapOk = flashProviderCap == null ? null : x <= flashProviderCap
const effectiveFlashFeeBps = flashFeeAmount != null ? approxBpsFromAmount(x, flashFeeAmount) : flashFeeBps
const deviationOk =
guardConfig.maxPostTradeDeviationBps == null
? null
: postTradeDeviationAbsBps <= guardConfig.maxPostTradeDeviationBps
const deploymentPlan = buildQuoteDeploymentSteps({
retainedQuote: retainedAfterGas,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
})
const retainedFloorActive = guardConfig.minRetainedUsdc > 0
const retainedFloorOk = retainedAfterGas >= guardConfig.minRetainedUsdc
const deploymentOk =
deploymentPlan == null ? null : deploymentPlan.shortfallQuote <= 0
const guardFailures = []
if (providerCapOk === false) guardFailures.push('flash_cap')
if (!(availableForRepay >= repay)) guardFailures.push('repay')
if (!(retainedAfterGas >= 0)) guardFailures.push('gas')
if (retainedFloorActive && !retainedFloorOk) guardFailures.push('retained_floor')
if (deviationOk === false) guardFailures.push('post_trade_dev')
if (deploymentOk === false) guardFailures.push('deploy_target')
if (strategyLabel !== 'quote-push' && atomicBaseRequested > 0) guardFailures.push('atomic_bridge_strategy')
if (atomicBridgeShortfall > 0) guardFailures.push('atomic_bridge_base')
return {
strategyLabel,
effectiveBaseReserve,
effectiveQuoteReserve,
strategyQuote,
repay,
retainedBeforeGas,
retainedAfterGas,
endBaseReserve,
endQuoteReserve,
postTradeMarginalPrice,
postTradeDeviationBps,
postTradeDeviationAbsBps,
gasReserveSummary,
providerCapOk,
effectiveFlashFeeBps,
deviationOk,
deploymentPlan,
retainedFloorActive,
retainedFloorOk,
deploymentOk,
guardFailures,
leg,
externalLeg,
availableForRepay,
step2MetricA,
step2MetricB,
step2MetricC,
step3MetricA,
step3MetricB,
strategyNote,
atomicBaseRequested,
atomicBaseReserved,
atomicBridgeShortfall,
atomicDestinationFulfilled,
atomicDestinationAsset: atomicDestinationAsset ?? baseAsset,
atomicDestinationDecimals: atomicDestinationDecimals ?? baseDecimals,
atomicCorridorLabel,
unwindBaseAmount,
}
}
/**
* Whitepaper-style ladder: repeated quote-push full-loop dry-runs; after each iteration,
* rebalance reserves to matched at the post-trade quote depth (B := Q := endQuoteReserve).
* Flash size per step: round(matched * flashNumerator / flashDenominator); defaults match
* MAINNET_CWUSD_HYBRID_FLASH_LOOP_CALCULATION_WHITEPAPER.md row 0→1 (6342691 / 256763253).
*/
function printSequentialMatchedLadder({
iterations,
startB,
startQ,
flashNumerator,
flashDenominator,
lpFeeBps,
flashFeeBps,
externalExitPrice,
externalExitFeeBps,
externalViaAsset,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig,
flashProviderCap,
flashProviderName,
ownedBaseAdd,
flashTopupQuote,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
}) {
if (startB !== startQ) {
console.error('Error: --sequential-matched-loops requires matched -B and -Q (equal raw reserves)')
process.exit(1)
}
if (!(flashNumerator > 0) || !(flashDenominator > 0)) {
console.error('Error: matched flash fraction numerator/denominator must be positive')
process.exit(1)
}
let B = startB
let Q = startQ
let cumRetained = 0
let cumFlash = 0
let cumBaseRebalance = 0
let completed = 0
let firstFailure = null
console.log('Sequential matched-ladder simulation (modeled quote-push + rebalance B=Q=endQuote)\n')
console.log(` iterations=${iterations}`)
console.log(
` flash sizing: x=round(matched*${flashNumerator}/${flashDenominator}) raw ${quoteAsset} per loop`,
)
console.log(` start matched=${rawToHuman(B, quoteDecimals)} ${baseAsset} / ${rawToHuman(Q, quoteDecimals)} ${quoteAsset} (raw ${B})\n`)
for (let i = 1; i <= iterations; i++) {
const matched = Math.min(B, Q)
const x = Math.max(1, Math.round((matched * flashNumerator) / flashDenominator))
const sim = simulateFullLoopDryRun({
B,
Q,
x,
lpFeeBps,
flashFeeBps,
loopStrategy: 'quote-push',
ownedBaseAdd,
flashTopupQuote,
externalEntryPrice: null,
externalExitPrice,
externalEntryFeeBps: 0,
externalExitFeeBps,
externalViaAsset,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig,
flashProviderCap,
flashProviderName,
flashFeeAmount: null,
flashFeeSource: null,
seedPools: null,
targetQuotePerPool: null,
targetTotalQuote: null,
loopCount: null,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
})
cumRetained += sim.retainedAfterGas
cumFlash += x
const baseAddRaw = Math.max(0, Math.round(sim.endQuoteReserve - sim.endBaseReserve))
cumBaseRebalance += baseAddRaw
completed = i
if (sim.guardFailures.length > 0) {
firstFailure = { i, x, sim }
break
}
const nextMatched = Math.round(sim.endQuoteReserve)
B = nextMatched
Q = nextMatched
}
const endMatchedHuman = rawToHuman(B, quoteDecimals)
console.log('Summary')
console.log(` completed_loops=${completed}${firstFailure ? ` (stopped at failure on loop ${firstFailure.i})` : ''}`)
console.log(
` end_matched_pool=${fmtAmount(B, quoteDecimals, baseAsset)} / ${fmtAmount(Q, quoteDecimals, quoteAsset)} (human ${endMatchedHuman} each side)`,
)
console.log(` cumulative_retained_after_gas=${fmtAmount(cumRetained, quoteDecimals, quoteAsset)}`)
console.log(` cumulative_flash_borrowed=${fmtAmount(cumFlash, quoteDecimals, quoteAsset)}`)
console.log(
` cumulative_modeled_base_rebalance_raw=${Math.round(cumBaseRebalance)} (${fmtAmount(Math.round(cumBaseRebalance), baseDecimals, baseAsset)} ${baseAsset} added to match quote depth)`,
)
console.log('')
if (firstFailure) {
const { i, x, sim } = firstFailure
console.log(`Loop ${i} failed guards: ${sim.guardFailures.join(', ')} (x=${x} raw)`)
console.log(
` post_trade_marginal_price=${fmt(sim.postTradeMarginalPrice)} quote/base, deviation_bps=${fmt(sim.postTradeDeviationBps)}`,
)
process.exit(2)
}
}
function deriveEstimatedGasQuoteForMainnetStrategy({
strategy,
poolAddress,
baseAddress,
quoteAddress,
amountInQuoteRaw,
externalEntryPrice,
externalEntryFeeBps,
quoteDecimals,
baseDecimals,
nativeTokenPrice,
fromAddress,
}) {
if (!(nativeTokenPrice > 0)) return null
if (strategy === 'quote-push') {
return tryEstimateMainnetIntegrationGasQuote({
poolAddress,
tokenIn: quoteAddress,
amountIn: amountInQuoteRaw,
quoteDecimals,
nativeTokenPrice,
fromAddress,
})
}
if (strategy === 'base-unwind' && externalEntryPrice != null) {
const externalLeg = externalQuoteToBaseOut(
amountInQuoteRaw,
externalEntryPrice,
externalEntryFeeBps ?? 0,
quoteDecimals,
baseDecimals,
)
return tryEstimateMainnetIntegrationGasQuote({
poolAddress,
tokenIn: baseAddress,
amountIn: externalLeg.baseOut,
quoteDecimals,
nativeTokenPrice,
fromAddress,
})
}
return null
}
function scaleFixableGuardFailures(guardFailures) {
return guardFailures.filter((failure) => failure !== 'flash_cap')
}
function findMinimumUniformDepthMultiplierForPass(params, maxFactor = 1e6, iterations = 40) {
const baseline = simulateFullLoopDryRun(params)
if (scaleFixableGuardFailures(baseline.guardFailures).length === 0) {
return {
factor: 1,
addedBase: 0,
addedQuote: 0,
simulation: baseline,
}
}
let lo = 1
let hi = 1
let hiSimulation = baseline
while (hi < maxFactor) {
hi *= 2
hiSimulation = simulateFullLoopDryRun({
...params,
B: params.B * hi,
Q: params.Q * hi,
})
if (scaleFixableGuardFailures(hiSimulation.guardFailures).length === 0) break
}
if (scaleFixableGuardFailures(hiSimulation.guardFailures).length !== 0) {
return null
}
for (let i = 0; i < iterations; i += 1) {
const mid = (lo + hi) / 2
const midSimulation = simulateFullLoopDryRun({
...params,
B: params.B * mid,
Q: params.Q * mid,
})
if (scaleFixableGuardFailures(midSimulation.guardFailures).length === 0) {
hi = mid
hiSimulation = midSimulation
} else {
lo = mid
}
}
return {
factor: hi,
addedBase: params.B * (hi - 1),
addedQuote: params.Q * (hi - 1),
simulation: hiSimulation,
}
}
function findMaxAtomicBridgeReservation(params, maxBaseReserve = null, iterations = 40) {
if (params.loopStrategy !== 'quote-push') return null
const baseline = simulateFullLoopDryRun({
...params,
atomicBridgeBaseAmount: 0,
atomicDestinationAmount: 0,
})
const availableBase = Math.max(0, maxBaseReserve ?? baseline.leg?.baseOut ?? 0)
if (!(availableBase > 0)) {
return {
maxBaseAvailable: 0,
positiveAfterGas: { amount: 0, simulation: baseline },
repayOnly: { amount: 0, simulation: baseline },
}
}
const positivePredicate = (simulation) =>
simulation.guardFailures.length === 0
const repayOnlyPredicate = (simulation) => {
const failures = simulation.guardFailures.filter((failure) => !['gas', 'retained_floor', 'deploy_target'].includes(failure))
return failures.length === 0 && simulation.availableForRepay >= simulation.repay
}
function solve(predicate) {
let lo = 0
let hi = availableBase
let bestSimulation = baseline
for (let i = 0; i < iterations; i += 1) {
const mid = Math.floor((lo + hi + 1) / 2)
const simulation = simulateFullLoopDryRun({
...params,
atomicBridgeBaseAmount: mid,
atomicDestinationAmount: params.atomicDestinationAmount ?? mid,
})
if (predicate(simulation)) {
lo = mid
bestSimulation = simulation
} else {
hi = mid - 1
}
}
const finalSimulation =
lo === 0
? simulateFullLoopDryRun({
...params,
atomicBridgeBaseAmount: 0,
atomicDestinationAmount: params.atomicDestinationAmount ?? 0,
})
: bestSimulation
return { amount: lo, simulation: finalSimulation }
}
return {
maxBaseAvailable: availableBase,
positiveAfterGas: solve(positivePredicate),
repayOnly: solve(repayOnlyPredicate),
}
}
function fullLoopFailureScore(candidate) {
const { simulation, x } = candidate
let score = simulation.guardFailures.length * 1e12
if (simulation.guardFailures.includes('flash_cap') && candidate.flashProviderCap != null) {
score += Math.max(0, x - candidate.flashProviderCap) * 1e3
}
if (simulation.guardFailures.includes('repay')) {
score += Math.max(0, simulation.repay - simulation.availableForRepay) * 1e2
}
if (simulation.guardFailures.includes('gas')) {
score += Math.max(0, -simulation.retainedAfterGas) * 10
}
if (simulation.guardFailures.includes('retained_floor')) {
score += Math.max(0, candidate.guardConfig.minRetainedUsdc - simulation.retainedAfterGas) * 10
}
if (simulation.guardFailures.includes('deploy_target') && simulation.deploymentPlan?.totalTarget > 0) {
score +=
(simulation.deploymentPlan.shortfallQuote / simulation.deploymentPlan.totalTarget) * 1e6
}
if (simulation.guardFailures.includes('post_trade_dev')) {
score += simulation.postTradeDeviationAbsBps
}
return score
}
function compareFullLoopCandidates(a, b) {
const aPass = a.simulation.guardFailures.length === 0
const bPass = b.simulation.guardFailures.length === 0
if (aPass !== bPass) return Number(bPass) - Number(aPass)
if (aPass && bPass) {
const aFunded = a.simulation.deploymentPlan?.fullyFundedCount ?? 0
const bFunded = b.simulation.deploymentPlan?.fullyFundedCount ?? 0
if (aFunded !== bFunded) return bFunded - aFunded
const aDeployed = a.simulation.deploymentPlan?.deployedTotal ?? 0
const bDeployed = b.simulation.deploymentPlan?.deployedTotal ?? 0
if (aDeployed !== bDeployed) return bDeployed - aDeployed
if (a.simulation.retainedAfterGas !== b.simulation.retainedAfterGas) {
return b.simulation.retainedAfterGas - a.simulation.retainedAfterGas
}
if (a.simulation.postTradeDeviationAbsBps !== b.simulation.postTradeDeviationAbsBps) {
return a.simulation.postTradeDeviationAbsBps - b.simulation.postTradeDeviationAbsBps
}
return b.x - a.x
}
if (a.simulation.guardFailures.length !== b.simulation.guardFailures.length) {
return a.simulation.guardFailures.length - b.simulation.guardFailures.length
}
const aScore = fullLoopFailureScore(a)
const bScore = fullLoopFailureScore(b)
if (aScore !== bScore) return aScore - bScore
if (a.simulation.postTradeDeviationAbsBps !== b.simulation.postTradeDeviationAbsBps) {
return a.simulation.postTradeDeviationAbsBps - b.simulation.postTradeDeviationAbsBps
}
if (a.simulation.retainedAfterGas !== b.simulation.retainedAfterGas) {
return b.simulation.retainedAfterGas - a.simulation.retainedAfterGas
}
return a.x - b.x
}
function buildFullLoopMethodologies(params, simulation, depthPlan) {
const methods = []
const {
strategyLabel,
deploymentPlan,
retainedAfterGas,
guardFailures,
availableForRepay,
repay,
} = simulation
const {
x,
baseAsset,
quoteAsset,
baseDecimals,
quoteDecimals,
ownedBaseAdd,
flashTopupQuote,
flashProviderCap,
guardConfig,
atomicBridgeBaseAmount,
atomicDestinationAsset,
} = params
if (guardFailures.length === 0) {
methods.push(
`Repay first, then seed only retained ${quoteAsset}. This run leaves ${fmtAmount(retainedAfterGas, quoteDecimals, quoteAsset)} after gas${deploymentPlan ? ` and can fully fund ${deploymentPlan.fullyFundedCount}/${deploymentPlan.rows.length} planned pool targets` : ''}.`,
)
if (ownedBaseAdd > 0) {
methods.push(
`The owned ${baseAsset} contribution is durable base-side depth. In this hybrid mode, the flash loan is only temporary ${quoteAsset} working capital while the owned base stays in the pool.`,
)
}
} else {
if (depthPlan && depthPlan.factor > 1) {
methods.push(
`Uniformly deepen the source PMM by about ${fmt(depthPlan.factor)}x before retrying this exact tranche: add roughly ${fmtAmount(depthPlan.addedBase, baseDecimals, baseAsset)} and ${fmtAmount(depthPlan.addedQuote, quoteDecimals, quoteAsset)}.`,
)
}
if (guardFailures.includes('repay')) {
methods.push(
`Improve the external unwind or reduce size before retrying: current proceeds ${fmtAmount(availableForRepay, quoteDecimals, quoteAsset)} do not cover flash repayment ${fmtAmount(repay, quoteDecimals, quoteAsset)}.`,
)
}
if (guardFailures.includes('gas')) {
methods.push(
`Reserve or top up native gas before execution. Retained quote after gas is ${fmtAmount(retainedAfterGas, quoteDecimals, quoteAsset)} under the current gas assumptions.`,
)
}
if (guardFailures.includes('retained_floor')) {
methods.push(
`Lower the retained-${quoteAsset} floor, improve external execution, or shrink the tranche so the loop leaves at least ${fmtAmount(guardConfig.minRetainedUsdc, quoteDecimals, quoteAsset)} after gas.`,
)
}
if (guardFailures.includes('deploy_target') && deploymentPlan) {
methods.push(
`Current retained quote only funds ${deploymentPlan.fullyFundedCount}/${deploymentPlan.rows.length} target pool steps. Either lower the deployment target or accumulate retained ${quoteAsset} off-venue first, then seed the public pools.`,
)
}
if (guardFailures.includes('flash_cap')) {
methods.push(
`The requested borrow ${fmtAmount(x, quoteDecimals, quoteAsset)} exceeds the current flash source cap${flashProviderCap != null ? ` ${fmtAmount(flashProviderCap, quoteDecimals, quoteAsset)}` : ''}. Switch flash source or shrink the tranche.`,
)
}
}
if (strategyLabel === 'quote-push') {
methods.push(
`${strategyLabel} permanently deepens quote reserve Q and drains base reserve B. If your end goal is stronger public quote liquidity, this is the right direction, but seed base-side depth first or use smaller staged tranches so the base side does not become the peg bottleneck.`,
)
} else {
methods.push(
`${strategyLabel} deepens base reserve B but drains quote reserve Q. Use it when the public pool needs more ${baseAsset}, but pair it with direct ${quoteAsset} seeding or a prior quote-build phase if quote-side liquidity is the end goal.`,
)
}
if (flashTopupQuote > 0) {
methods.push(
`Treat --flash-topup-quote as temporary execution support only. It helps the strategy leg, but it does not create durable pool depth unless retained ${quoteAsset} remains after repayment and is left in the pool on purpose.`,
)
}
if (ownedBaseAdd > 0) {
methods.push(
`Hybrid methodology: add owned ${baseAsset} first, use flash-borrowed ${quoteAsset} only for the execution leg, repay from external ${quoteAsset} proceeds, and leave only retained ${quoteAsset} behind. That is the durable two-sided depth-building path.`,
)
}
if (atomicBridgeBaseAmount > 0) {
methods.push(
`Atomic bridge split methodology: reserve ${fmtAmount(atomicBridgeBaseAmount, baseDecimals, baseAsset)} of acquired ${baseAsset} into the destination corridor${atomicDestinationAsset ? ` for immediate ${atomicDestinationAsset} fulfillment` : ''}, and only unwind the remaining ${baseAsset} back into ${quoteAsset}. This improves cross-chain destination liquidity but reduces same-chain repayment headroom.`,
)
}
if (guardFailures.includes('post_trade_dev')) {
methods.push(
'If the public pool is still canary-sized, run the profit leg on a deeper internal/private venue first and only deploy the retained quote into the public PMM afterward. The flash loop should support deployment, not force the public pool to absorb the whole trade at once.',
)
methods.push(
'Use staged tranches from --scan to find the largest size that stays inside the deviation cap, then only scale size after the prior loop has already deepened the pool.',
)
}
return [...new Set(methods)]
}
function printFullLoopRecommendation(params, simulation, options = {}) {
const { executionClass = null, executionGradeRequired = false } = options
const depthPlan =
simulation.guardFailures.length === 0 ? null : findMinimumUniformDepthMultiplierForPass(params)
const methods = buildFullLoopMethodologies(params, simulation, depthPlan)
const deploymentPlan = simulation.deploymentPlan
const canaryThreshold = humanToRaw(1, params.quoteDecimals)
const canarySizedPass =
simulation.guardFailures.length === 0 &&
!deploymentPlan &&
simulation.retainedAfterGas < canaryThreshold
console.log('Recommendation')
if (simulation.guardFailures.length === 0) {
if (executionGradeRequired && executionClass !== 'execution-ready') {
console.log(
` Economically passes as modeled, but do not execute it yet. The tranche at ${fmtAmount(params.x, params.quoteDecimals, params.quoteAsset)} using ${simulation.strategyLabel} is still blocked by the execution-grade gate.`,
)
} else if (executionClass != null && executionClass !== 'execution-ready') {
console.log(
` Economically passes as modeled at ${fmtAmount(params.x, params.quoteDecimals, params.quoteAsset)} using ${simulation.strategyLabel}, but this remains planning-only until the live execution inputs are upgraded.`,
)
} else {
console.log(
` Executable as modeled: start with ${fmtAmount(params.x, params.quoteDecimals, params.quoteAsset)} using ${simulation.strategyLabel}. It retains ${fmtAmount(simulation.retainedAfterGas, params.quoteDecimals, params.quoteAsset)} after gas${deploymentPlan ? ` and deploys ${fmtAmount(deploymentPlan.deployedTotal, params.quoteDecimals, params.quoteAsset)} into target pools` : ''}.`,
)
}
if (canarySizedPass) {
console.log(
` This is still canary-sized, not a meaningful public depth program yet: retained quote is below ${fmtAmount(canaryThreshold, params.quoteDecimals, params.quoteAsset)}.`,
)
}
} else {
console.log(
` Do not execute this tranche as modeled. Failing guards=${simulation.guardFailures.join(', ')}.`,
)
if (depthPlan && depthPlan.factor > 1) {
console.log(
` Closest structural fix: deepen the source pool by about ${fmt(depthPlan.factor)}x before retrying this exact tranche.`,
)
} else if (simulation.guardFailures.includes('post_trade_dev')) {
console.log(
' Current external assumptions plus current public-pool depth are not enough; improve venue economics, lower size, or seed depth first.',
)
}
}
console.log('')
console.log('Methodologies to increase depth')
methods.forEach((method, index) => {
console.log(` ${index + 1}. ${method}`)
})
console.log('')
}
function isMaterialPublicCandidate(candidate) {
if (!candidate || candidate.simulation.guardFailures.length !== 0) return false
if (candidate.simulation.deploymentPlan) {
return candidate.simulation.deploymentPlan.deployedTotal > 0
}
return candidate.simulation.retainedAfterGas >= humanToRaw(1, candidate.params.quoteDecimals)
}
function printFullLoopDryRun(params) {
const {
B,
Q,
x,
lpFeeBps,
ownedBaseAdd,
flashTopupQuote,
externalEntryFeeBps,
externalExitFeeBps,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig,
flashProviderCap,
flashProviderName,
flashFeeSource,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
quoteSurface,
externalEntrySource,
externalExitSource,
livePoolFeeBps,
executionGradeRequired,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
} = params
const simulation = simulateFullLoopDryRun(params)
const executionBlocks = listExecutionReadinessBlocks({
strategyLabel: params.loopStrategy,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode: guardConfig.gasReserveMode,
maxPostTradeDeviationBps: guardConfig.maxPostTradeDeviationBps,
})
const executionClass = classifyExecutionReadiness({
strategyLabel: params.loopStrategy,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode: guardConfig.gasReserveMode,
maxPostTradeDeviationBps: guardConfig.maxPostTradeDeviationBps,
})
const modeledStatusLabel = executionClass === 'execution-ready' ? 'status' : 'modeled status'
const {
strategyLabel,
effectiveBaseReserve,
effectiveQuoteReserve,
strategyQuote,
repay,
retainedBeforeGas,
retainedAfterGas,
endBaseReserve,
endQuoteReserve,
postTradeMarginalPrice,
postTradeDeviationBps,
postTradeDeviationAbsBps,
gasReserveSummary,
providerCapOk,
effectiveFlashFeeBps,
deviationOk,
deploymentPlan,
retainedFloorActive,
retainedFloorOk,
guardFailures,
leg,
availableForRepay,
step2MetricA,
step2MetricB,
step2MetricC,
step3MetricA,
step3MetricB,
strategyNote,
atomicBaseRequested,
atomicBaseReserved,
atomicBridgeShortfall,
atomicDestinationFulfilled,
unwindBaseAmount,
} = simulation
const atomicBridgeScan =
params.scanAtomicBridgeMax && strategyLabel === 'quote-push'
? findMaxAtomicBridgeReservation(params, leg?.baseOut ?? null)
: null
console.log('Full loop dry-run — flexible flash-backed PMM loop, repay, and retained quote deployment\n')
console.log(` strategy=${strategyLabel}`)
console.log(` execution class=${executionClass}`)
if (quoteSurface) {
console.log(` pool quote surface=${quoteSurface.surface} (${quoteSurface.source})`)
}
console.log(` flash provider=${flashProviderName}`)
console.log(
` source PMM reserves: B=${fmtAmount(B, baseDecimals, baseAsset)}, Q=${fmtAmount(Q, quoteDecimals, quoteAsset)}`,
)
if (ownedBaseAdd > 0) {
console.log(
` owned base add to source pool=${fmtAmount(ownedBaseAdd, baseDecimals, baseAsset)} (effective source B=${fmtAmount(effectiveBaseReserve, baseDecimals, baseAsset)})`,
)
}
console.log(` flash borrow size=${fmtAmount(x, quoteDecimals, quoteAsset)}`)
if (flashTopupQuote > 0) {
console.log(
` temporary flash quote top-up to source pool=${fmtAmount(flashTopupQuote, quoteDecimals, quoteAsset)} (effective source Q=${fmtAmount(effectiveQuoteReserve, quoteDecimals, quoteAsset)})`,
)
}
console.log(` strategy quote budget=${fmtAmount(strategyQuote, quoteDecimals, quoteAsset)}`)
console.log(
` pool fee=${fmt(livePoolFeeBps ?? lpFeeBps)} bps flash fee=${fmt(effectiveFlashFeeBps)} bps external entry fee=${fmt(externalEntryFeeBps)} bps external exit fee=${fmt(externalExitFeeBps)} bps`,
)
if (flashFeeSource) {
console.log(` flash fee source=${flashFeeSource}`)
}
console.log(` external entry source=${externalEntrySource ?? 'n/a'}`)
console.log(` external exit source=${externalExitSource ?? 'n/a'}`)
if (atomicBridgeBaseAmount > 0) {
console.log(
` atomic corridor reservation=${fmtAmount(atomicBridgeBaseAmount, baseDecimals, baseAsset)}${atomicCorridorLabel ? ` via ${atomicCorridorLabel}` : ''}`,
)
console.log(
` atomic destination fulfillment target=${fmtAmount(
atomicDestinationAmount ?? convertRawAmount(atomicBridgeBaseAmount, baseDecimals, atomicDestinationDecimals),
atomicDestinationDecimals,
atomicDestinationAsset,
)}`,
)
}
console.log(` oracle price=${fmt(guardConfig.oraclePrice)} ${quoteAsset} per ${baseAsset}`)
if (flashProviderCap != null) {
console.log(
` flash source cap=${fmtAmount(flashProviderCap, quoteDecimals, quoteAsset)} (${providerCapOk ? 'pass' : 'exceeds cap'})`,
)
} else {
console.log(' flash source cap=not checked (set --flash-provider-cap to enforce borrow ceiling)')
}
if (guardConfig.gasReserveQuote > 0) {
console.log(
` native gas reserve=${fmt(guardConfig.gasReserveNative)} native = ${fmt(guardConfig.gasReserveQuoteHuman)} ${quoteAsset} (${gasReserveSummary})`,
)
}
if (executionClass !== 'execution-ready') {
console.log(
' warning: this output is planning-only until the tool has the required live pool quote surface, live external quote source(s), measured or live-estimated gas, and an explicit post-trade deviation cap.',
)
}
if (retainedFloorActive) {
console.log(` retained ${quoteAsset} floor after gas=${fmtAmount(guardConfig.minRetainedUsdc, quoteDecimals, quoteAsset)}`)
}
if (guardConfig.maxPostTradeDeviationBps != null) {
console.log(` max post-trade deviation=${fmt(guardConfig.maxPostTradeDeviationBps)} bps`)
}
console.log('')
console.log('step\tmetric\tvalue')
if (ownedBaseAdd > 0) {
console.log(`0\towned_base_added_to_pool\t${fmtAmount(ownedBaseAdd, baseDecimals, baseAsset)}`)
console.log(`0\teffective_source_base_reserve\t${fmtAmount(effectiveBaseReserve, baseDecimals, baseAsset)}`)
}
console.log(`1\tflash_quote_borrowed\t${fmtAmount(x, quoteDecimals, quoteAsset)}`)
if (flashTopupQuote > 0) {
console.log(`1\tflash_quote_temp_pool_topup\t${fmtAmount(flashTopupQuote, quoteDecimals, quoteAsset)}`)
console.log(`1\tflash_quote_left_for_strategy\t${fmtAmount(strategyQuote, quoteDecimals, quoteAsset)}`)
}
console.log(step2MetricA.join('\t'))
console.log(step2MetricB.join('\t'))
console.log(step2MetricC.join('\t'))
if (atomicBaseRequested > 0) {
console.log(`3\tatomic_base_requested\t${fmtAmount(atomicBaseRequested, baseDecimals, baseAsset)}`)
console.log(`3\tatomic_base_reserved\t${fmtAmount(atomicBaseReserved, baseDecimals, baseAsset)}`)
console.log(
`3\tatomic_destination_fulfilled\t${fmtAmount(atomicDestinationFulfilled, atomicDestinationDecimals, atomicDestinationAsset)}`,
)
console.log(`3\tbase_remaining_for_unwind\t${fmtAmount(unwindBaseAmount, baseDecimals, baseAsset)}`)
if (atomicBridgeShortfall > 0) {
console.log(`3\tatomic_bridge_shortfall\t${fmtAmount(atomicBridgeShortfall, baseDecimals, baseAsset)}`)
}
}
console.log(step3MetricA.join('\t'))
console.log(step3MetricB.join('\t'))
if (strategyLabel === 'quote-push') {
console.log(`3\texternal_quote_proceeds\t${fmtAmount(availableForRepay, quoteDecimals, quoteAsset)}`)
} else {
console.log(`3\tpmm_vwap_quote_per_base\t${fmt(leg.vwapQuotePerBase)}`)
console.log(`3\tquote_available_for_repay\t${fmtAmount(availableForRepay, quoteDecimals, quoteAsset)}`)
}
console.log(`4\tflash_fee_amount\t${fmtAmount(repay - x, quoteDecimals, quoteAsset)}`)
console.log(`4\tflash_repay\t${fmtAmount(repay, quoteDecimals, quoteAsset)}`)
console.log(`4\tretained_before_gas\t${fmtAmount(retainedBeforeGas, quoteDecimals, quoteAsset)}`)
console.log(`5\tgas_reserve_quote\t${fmtAmount(guardConfig.gasReserveQuote, quoteDecimals, quoteAsset)}`)
console.log(`5\tretained_after_gas\t${fmtAmount(retainedAfterGas, quoteDecimals, quoteAsset)}`)
console.log(`6\tsource_pool_base_delta\t${fmtAmount(endBaseReserve - B, baseDecimals, baseAsset)}`)
console.log(`6\tsource_pool_quote_delta\t${fmtAmount(endQuoteReserve - Q, quoteDecimals, quoteAsset)}`)
console.log(`6\tpost_trade_marginal_price\t${fmt(postTradeMarginalPrice)}`)
console.log(`6\tpost_trade_dev_bps\t${fmt(postTradeDeviationBps)}`)
console.log('')
console.log(
` ${modeledStatusLabel}=${guardFailures.length === 0 ? 'pass' : 'fail'}${guardFailures.length === 0 ? '' : ` (${guardFailures.join('+')})`}`,
)
console.log(
` repay check=${availableForRepay >= repay ? 'pass' : 'fail'} (${fmtAmount(availableForRepay, quoteDecimals, quoteAsset)} proceeds vs ${fmtAmount(repay, quoteDecimals, quoteAsset)} repay)`,
)
console.log(
` retained after gas=${retainedAfterGas >= 0 ? 'pass' : 'fail'} (${fmtAmount(retainedAfterGas, quoteDecimals, quoteAsset)})`,
)
if (retainedFloorActive) {
console.log(
` retained floor after gas=${retainedFloorOk ? 'pass' : 'fail'} (${fmtAmount(retainedAfterGas, quoteDecimals, quoteAsset)} vs floor ${fmtAmount(
guardConfig.minRetainedUsdc,
quoteDecimals,
quoteAsset,
)})`,
)
}
if (deviationOk != null) {
console.log(
` post-trade deviation guard=${deviationOk ? 'pass' : 'fail'} (${fmt(postTradeDeviationAbsBps)} bps abs)`,
)
}
console.log(
` source pool end state: B=${fmtAmount(endBaseReserve, baseDecimals, baseAsset)}, Q=${fmtAmount(endQuoteReserve, quoteDecimals, quoteAsset)}`,
)
console.log(` source pool base deepening=${endBaseReserve > B ? 'yes' : 'no'} quote deepening=${endQuoteReserve > Q ? 'yes' : 'no'}`)
console.log(strategyNote)
console.log('')
if (atomicBridgeScan) {
console.log('Atomic bridge reservation scan')
console.log(
` PMM-acquired base available=${fmtAmount(atomicBridgeScan.maxBaseAvailable, baseDecimals, baseAsset)}`,
)
console.log(
` max reservation with positive retained-after-gas=${fmtAmount(
atomicBridgeScan.positiveAfterGas.amount,
baseDecimals,
baseAsset,
)}`,
)
console.log(
` retained_after_gas=${fmtAmount(
atomicBridgeScan.positiveAfterGas.simulation.retainedAfterGas,
quoteDecimals,
quoteAsset,
)}`,
)
console.log(
` max reservation with repay-only pass=${fmtAmount(
atomicBridgeScan.repayOnly.amount,
baseDecimals,
baseAsset,
)}`,
)
console.log(
` retained_after_gas=${fmtAmount(
atomicBridgeScan.repayOnly.simulation.retainedAfterGas,
quoteDecimals,
quoteAsset,
)}`,
)
console.log('')
}
if (executionGradeRequired && executionClass !== 'execution-ready') {
console.log('Execution-grade gate')
console.log(' status=blocked')
console.log(` reason=missing ${executionBlocks.join(', ')}`)
console.log('')
return
}
printQuoteDeploymentPlan({
retainedQuote: retainedAfterGas,
quoteAsset,
quoteDecimals,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
})
printFullLoopRecommendation(params, simulation, {
executionClass,
executionGradeRequired,
})
}
function strategyListForPublicSweep(loopStrategy) {
return loopStrategy === 'both' ? ['quote-push', 'base-unwind'] : [loopStrategy]
}
function defaultPublicSweepSizes(quoteDecimals) {
return [0.1, 0.25, 0.5, 1, 2, 4].map((amount) => humanToRaw(amount, quoteDecimals))
}
function resolvePublicFlashSource({
publicFlashSource,
quoteAddress,
flashProviderCap,
flashProviderName,
flashFeeBps,
}) {
if (publicFlashSource === 'manual') {
return {
providerKey: 'manual',
providerName: flashProviderName,
providerAddress: null,
capRaw: flashProviderCap,
feeBps: flashFeeBps,
feeRaw: null,
source: 'manual CLI/env flash source',
}
}
const liveSource =
publicFlashSource === 'balancer'
? tryReadMainnetBalancerFlashSource(quoteAddress)
: tryReadMainnetAaveFlashSource(quoteAddress)
if (!liveSource) return null
return {
...liveSource,
capRaw:
liveSource.capRaw != null && flashProviderCap != null
? Math.min(liveSource.capRaw, flashProviderCap)
: (flashProviderCap ?? liveSource.capRaw),
}
}
function buildPublicFlashTerms(flashSource, amount, fallbackFlashFeeBps) {
const effectiveFlashFeeBps = flashSource?.feeBps ?? fallbackFlashFeeBps
return {
flashProviderCap: flashSource?.capRaw ?? null,
flashProviderName: flashSource?.providerName ?? 'flash provider',
flashFeeAmount: null,
flashFeeBps: effectiveFlashFeeBps,
flashFeeSource:
flashSource?.source ?? `manual flash fee bps (${fmt(effectiveFlashFeeBps)})`,
effectiveFlashFeeBps,
}
}
function buildPublicLiveSweepCandidate({
pool,
reserves,
livePoolFeeBps,
quoteSurface,
x,
strategy,
ownedBaseAdd,
flashSource,
fallbackFlashFeeBps,
baseDecimals,
quoteDecimals,
guardConfig,
flashTopupQuote,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
externalEntrySource,
externalExitSource,
fromAddress,
}) {
const estimatedGasQuote = deriveEstimatedGasQuoteForMainnetStrategy({
strategy,
poolAddress: pool.poolAddress,
baseAddress: pool.baseAddress,
quoteAddress: pool.quoteAddress,
amountInQuoteRaw: x,
externalEntryPrice,
externalEntryFeeBps,
quoteDecimals,
baseDecimals,
nativeTokenPrice: guardConfig.nativeTokenPrice,
fromAddress,
})
const candidateGuardConfig =
guardConfig.gasReserveMode === 'modeled_native' && estimatedGasQuote
? buildInventoryLoopGuardConfig({
minRetainedUsdc: guardConfig.minRetainedUsdc,
gasTxCount: null,
gasPerTx: null,
maxFeeGwei: null,
nativeTokenPrice: guardConfig.nativeTokenPrice,
quoteDecimals,
oraclePrice: guardConfig.oraclePrice,
maxPostTradeDeviationBps: guardConfig.maxPostTradeDeviationBps,
maxCwBurnFraction: guardConfig.maxCwBurnFraction,
cooldownBlocks: guardConfig.cooldownBlocks,
measuredGasQuote: null,
measuredGasSource: null,
estimatedGasQuote: estimatedGasQuote.quoteCost,
estimatedGasSource: estimatedGasQuote.source,
})
: guardConfig
const flashTerms = buildPublicFlashTerms(flashSource, x, fallbackFlashFeeBps)
const params = {
B: reserves.baseReserve,
Q: reserves.quoteReserve,
x,
lpFeeBps: livePoolFeeBps ?? pool.feeBps ?? 10,
flashFeeBps: flashTerms.flashFeeBps,
loopStrategy: strategy,
ownedBaseAdd,
flashTopupQuote,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
quoteAsset: pool.quote,
baseAsset: pool.base,
quoteDecimals,
baseDecimals,
guardConfig: candidateGuardConfig,
flashProviderCap: flashTerms.flashProviderCap,
flashProviderName: flashTerms.flashProviderName,
flashFeeAmount: flashTerms.flashFeeAmount,
flashFeeSource: flashTerms.flashFeeSource,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
}
const simulation = simulateFullLoopDryRun(params)
const depthPlan =
simulation.guardFailures.length === 0 ? null : findMinimumUniformDepthMultiplierForPass(params)
return {
pool,
x,
strategy,
flashSource,
quoteSurface,
livePoolFeeBps,
params,
simulation,
depthPlan,
flashProviderCap: flashTerms.flashProviderCap,
executionClass: classifyExecutionReadiness({
strategyLabel: strategy,
quoteSurface,
externalEntrySource,
externalExitSource,
gasReserveMode: candidateGuardConfig.gasReserveMode,
maxPostTradeDeviationBps: candidateGuardConfig.maxPostTradeDeviationBps,
}),
}
}
function printPublicLiveSweep({
scanStr,
loopStrategy,
ownedBaseAdd,
flashTopupQuote,
flashProviderCap,
flashProviderName,
flashFeeBps,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
guardConfig,
publicFlashSource,
externalEntrySource,
externalExitSource,
executionGradeRequired,
}) {
const pools = loadLiveMainnetPublicUsdPools()
if (pools.length === 0) {
console.error('Error: no live mainnet cWUSD*/USD* PMM pools were found in deployment-status.json')
process.exit(1)
}
const rpcUrl = rpcUrlForChain(1)
if (!rpcUrl) {
console.error('Error: --public-live-sweep requires ETHEREUM_MAINNET_RPC')
process.exit(1)
}
const strategies = strategyListForPublicSweep(loopStrategy)
const sweepRows = []
const fromAddress = process.env.DEPLOYER_ADDRESS ?? '0x4A666F96fC8764181194447A7dFdb7d471b301C8'
for (const pool of pools) {
const reserves = tryReadPoolReservesViaCast(1, pool.poolAddress)
if (!reserves) {
sweepRows.push({
pool,
strategy: 'n/a',
best: null,
error: `could not read live reserves for ${pool.poolAddress}`,
})
continue
}
const baseDecimals = tryReadTokenDecimalsViaCast(1, pool.baseAddress) ?? 6
const quoteDecimals = tryReadTokenDecimalsViaCast(1, pool.quoteAddress) ?? 6
const scanSizes = scanStr
? scanStr.split(',').map((size) => parseNum(size.trim()))
: defaultPublicSweepSizes(quoteDecimals)
const flashSource = resolvePublicFlashSource({
publicFlashSource,
quoteAddress: pool.quoteAddress,
flashProviderCap,
flashProviderName,
flashFeeBps,
})
const livePoolFeeBps = tryReadPoolFeeBpsViaCast(1, pool.poolAddress)
const quoteSurface = tryProbePoolQuoteSurfaceViaCast(
1,
pool.poolAddress,
fromAddress,
)
for (const strategy of strategies) {
const candidates = scanSizes.map((x) =>
buildPublicLiveSweepCandidate({
pool,
reserves,
livePoolFeeBps,
quoteSurface,
x,
strategy,
ownedBaseAdd,
flashSource,
fallbackFlashFeeBps: flashFeeBps,
baseDecimals,
quoteDecimals,
guardConfig,
flashTopupQuote,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset,
atomicDestinationDecimals,
atomicCorridorLabel,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount,
externalEntrySource,
externalExitSource,
fromAddress,
}),
)
const best = [...candidates].sort(compareFullLoopCandidates)[0] ?? null
sweepRows.push({
pool,
strategy,
best,
candidates,
reserves,
flashSource,
quoteSurface,
livePoolFeeBps,
error: flashSource == null ? `could not resolve ${publicFlashSource} flash source for ${pool.quote}` : null,
})
}
}
console.log('Public live sweep — mainnet cWUSD*/USD* PMM pools\n')
console.log(' chain=Ethereum mainnet')
console.log(` flash source mode=${publicFlashSource}`)
console.log(` strategies=${strategies.join(', ')}`)
console.log(
` scan sizes=${(scanStr ? scanStr.split(',').map((size) => parseNum(size.trim())) : defaultPublicSweepSizes(6))
.map((size) => fmt(size))
.join(', ')} raw quote units`,
)
if (guardConfig.gasReserveQuote > 0) {
console.log(
` gas reserve=${fmt(guardConfig.gasReserveQuote)} raw quote units (${summarizeGasReserve(guardConfig)})`,
)
}
if (guardConfig.maxPostTradeDeviationBps != null) {
console.log(` max post-trade deviation=${fmt(guardConfig.maxPostTradeDeviationBps)} bps`)
}
console.log('')
console.log(
'pool\tstrategy\texecution_class\tquote_surface\tfee_bps\tbest_x\tstatus\tguards\tretained_after_gas\tpost_trade_dev_bps\tfunded_steps\tdepth_needed',
)
for (const row of sweepRows) {
if (row.error || !row.best) {
console.log(
[
row.pool?.poolAddress ?? 'unknown',
row.strategy,
'blocked',
'unknown',
'n/a',
'n/a',
'error',
row.error ?? 'n/a',
'n/a',
'n/a',
'n/a',
'n/a',
].join('\t'),
)
continue
}
const { best } = row
const fundedSteps = best.simulation.deploymentPlan
? `${best.simulation.deploymentPlan.fullyFundedCount}/${best.simulation.deploymentPlan.rows.length}`
: 'n/a'
const depthNeeded =
best.depthPlan && best.depthPlan.factor > 1 ? `${fmt(best.depthPlan.factor)}x` : 'pass'
const executionClass = row.best.executionClass
const rowModeledPass = best.simulation.guardFailures.length === 0
const rowStatus =
executionGradeRequired && executionClass !== 'execution-ready'
? 'blocked'
: rowModeledPass
? executionClass === 'execution-ready'
? 'pass'
: 'planning-pass'
: 'closest'
const rowGuards =
executionGradeRequired && executionClass !== 'execution-ready'
? 'execution_gate'
: rowModeledPass
? executionClass === 'execution-ready'
? 'pass'
: 'modeled_only'
: best.simulation.guardFailures.join('+')
console.log(
[
`${row.pool.base}/${row.pool.quote}`,
row.strategy,
executionClass,
row.quoteSurface?.surface ?? 'unknown',
fmt(row.livePoolFeeBps ?? row.pool.feeBps ?? NaN),
fmtAmount(best.x, best.params.quoteDecimals, best.params.quoteAsset),
rowStatus,
rowGuards,
fmtAmount(
best.simulation.retainedAfterGas,
best.params.quoteDecimals,
best.params.quoteAsset,
),
fmt(best.simulation.postTradeDeviationBps),
fundedSteps,
depthNeeded,
].join('\t'),
)
}
const viable = sweepRows
.map((row) => row.best)
.filter(
(candidate) =>
candidate &&
candidate.simulation.guardFailures.length === 0 &&
(!executionGradeRequired ||
candidate.executionClass === 'execution-ready'),
)
.sort(compareFullLoopCandidates)
const materiallyUseful = viable.filter(isMaterialPublicCandidate)
const closest = sweepRows
.map((row) => row.best)
.filter(Boolean)
.sort(compareFullLoopCandidates)[0]
const failedCandidates = sweepRows
.flatMap((row) => row.candidates ?? [])
.filter((candidate) => candidate.simulation.guardFailures.length > 0)
const preferredFailedCandidates = failedCandidates.filter(
(candidate) => candidate.strategy === 'quote-push',
)
const closestFail =
[...(preferredFailedCandidates.length > 0 ? preferredFailedCandidates : failedCandidates)].sort(
compareFullLoopCandidates,
)[0]
console.log('')
console.log('Overall recommendation')
if (materiallyUseful.length > 0) {
const winner = materiallyUseful[0]
const winnerExecutionClass = winner.executionClass
console.log(
` Best current live public candidate: ${winner.pool.base}/${winner.pool.quote} via ${winner.strategy} at ${fmtAmount(winner.x, winner.params.quoteDecimals, winner.params.quoteAsset)} using ${winner.flashSource?.providerName ?? 'manual flash source'}.`,
)
printFullLoopRecommendation(winner.params, winner.simulation, {
executionClass: winnerExecutionClass,
executionGradeRequired,
})
} else if (viable.length > 0) {
const canary = viable[0]
const recommendationCandidate = closestFail ?? canary
const recommendationExecutionClass = recommendationCandidate.executionClass
console.log(
` Only canary-sized pass candidates exist right now. Best technical pass: ${canary.pool.base}/${canary.pool.quote} via ${canary.strategy} at ${fmtAmount(canary.x, canary.params.quoteDecimals, canary.params.quoteAsset)}, but it does not retain enough quote to count as a meaningful public-liquidity program.`,
)
printFullLoopRecommendation(recommendationCandidate.params, recommendationCandidate.simulation, {
executionClass: recommendationExecutionClass,
executionGradeRequired,
})
} else if (closest) {
const closestExecutionClass = closest.executionClass
console.log(
` No current live public pool passes the active guard set. Closest candidate: ${closest.pool.base}/${closest.pool.quote} via ${closest.strategy} at ${fmtAmount(closest.x, closest.params.quoteDecimals, closest.params.quoteAsset)}.`,
)
printFullLoopRecommendation(closest.params, closest.simulation, {
executionClass: closestExecutionClass,
executionGradeRequired,
})
} else {
console.log(' No live public sweep candidates could be evaluated.')
console.log('')
}
}
function buildInventoryLoopCandidates(
B,
Q,
scanStr,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
guardConfig,
flashAddToPool,
) {
const sizes = scanStr
? scanStr.split(',').map((s) => parseNum(s.trim()))
: [50_000, 100_000, 150_000, 200_000, 250_000]
return sizes.map((grossBaseIn) => {
const effectiveQuoteReserve =
flashAddToPool && targetFlashBorrow != null ? Q + targetFlashBorrow : Q
const leg = baseInToQuoteOut(B, effectiveQuoteReserve, grossBaseIn, lpFeeBps)
const endBaseReserve = B + leg.deltaBaseNet
const endQuoteReserve = Math.max(0, effectiveQuoteReserve - leg.quoteOut)
const postTradeMarginalPrice = marginalQuotePerBase(endBaseReserve, endQuoteReserve)
const postTradeDeviationBps = deviationBps(postTradeMarginalPrice, guardConfig.oraclePrice)
const postTradeDeviationAbsBps = Math.abs(postTradeDeviationBps)
const maxFlashNoLoss = leg.quoteOut / (1 + flashFeeBps / 10000)
const maxFlashKeepFloor = Math.max(
0,
(leg.quoteOut - guardConfig.requiredRetainedUsdc) / (1 + flashFeeBps / 10000),
)
const retainedNoFlash = leg.quoteOut
const floorSurplusNoFlash = retainedNoFlash - guardConfig.requiredRetainedUsdc
const retainedPerCw = retainedNoFlash / grossBaseIn
const inventoryOk = inventoryBase == null ? null : inventoryBase >= grossBaseIn
const inventoryBurnFraction =
inventoryBase == null || inventoryBase <= 0 ? null : grossBaseIn / inventoryBase
const postTradeDeviationOk =
guardConfig.maxPostTradeDeviationBps == null
? null
: postTradeDeviationAbsBps <= guardConfig.maxPostTradeDeviationBps
const cwBurnFractionOk =
guardConfig.maxCwBurnFraction == null
? null
: inventoryBurnFraction <= guardConfig.maxCwBurnFraction
const targetRepay = targetFlashBorrow == null ? null : repayUsdc(targetFlashBorrow, flashFeeBps)
const repayMargin = targetRepay == null ? null : leg.quoteOut - targetRepay
const retainedAfterTargetFlash = targetRepay == null ? null : leg.quoteOut - targetRepay
const retainedAfterTargetFlashPerCw =
retainedAfterTargetFlash == null ? null : retainedAfterTargetFlash / grossBaseIn
const floorMarginAfterTargetFlash =
retainedAfterTargetFlash == null ? null : retainedAfterTargetFlash - guardConfig.requiredRetainedUsdc
const poolBaseDelta = endBaseReserve - B
const poolQuoteDelta = endQuoteReserve - Q
const samePoolRepayPossible = targetRepay == null ? null : leg.quoteOut >= targetRepay
const samePoolQuoteEndsHigher = flashAddToPool ? endQuoteReserve > Q : null
const samePoolQuoteDeepeningWithPmmRepayPossible =
flashAddToPool && targetRepay != null ? samePoolRepayPossible && samePoolQuoteEndsHigher : null
const guardFailures = []
if (inventoryOk === false) guardFailures.push('inventory')
if (postTradeDeviationOk === false) guardFailures.push('post_trade_dev')
if (cwBurnFractionOk === false) guardFailures.push('cw_burn')
if (targetFlashBorrow != null) {
if (!(repayMargin >= 0)) guardFailures.push('repay')
if (!(floorMarginAfterTargetFlash >= 0)) guardFailures.push('retained_floor')
} else if (!(floorSurplusNoFlash >= 0)) {
guardFailures.push('retained_floor')
}
return {
grossBaseIn,
deltaBaseNet: leg.deltaBaseNet,
quoteOut: leg.quoteOut,
usdcPerCw: leg.vwapQuotePerBase,
endBaseReserve,
endQuoteReserve,
postTradeMarginalPrice,
postTradeDeviationBps,
postTradeDeviationAbsBps,
maxFlashNoLoss,
maxFlashKeepFloor,
retainedNoFlash,
floorSurplusNoFlash,
retainedPerCw,
inventoryOk,
inventoryBurnFraction,
postTradeDeviationOk,
cwBurnFractionOk,
targetRepay,
repayMargin,
retainedAfterTargetFlash,
retainedAfterTargetFlashPerCw,
floorMarginAfterTargetFlash,
effectiveQuoteReserve,
poolBaseDelta,
poolQuoteDelta,
samePoolRepayPossible,
samePoolQuoteEndsHigher,
samePoolQuoteDeepeningWithPmmRepayPossible,
guardFailures,
recommendationOk: guardFailures.length === 0,
}
})
}
function compareInventoryLoopCandidates(a, b, targetFlashBorrow, rankProfile) {
if (a.recommendationOk !== b.recommendationOk) {
return Number(b.recommendationOk) - Number(a.recommendationOk)
}
if (a.recommendationOk && b.recommendationOk) {
const eligibleCompare = compareRankProfileMetrics(
a,
b,
eligibleRankMetrics(targetFlashBorrow, rankProfile),
)
if (eligibleCompare !== 0) return eligibleCompare
}
if (a.guardFailures.length !== b.guardFailures.length) {
return a.guardFailures.length - b.guardFailures.length
}
if (targetFlashBorrow != null) {
if ((a.repayMargin >= 0) !== (b.repayMargin >= 0)) return Number(b.repayMargin >= 0) - Number(a.repayMargin >= 0)
if ((a.floorMarginAfterTargetFlash >= 0) !== (b.floorMarginAfterTargetFlash >= 0)) {
return Number(b.floorMarginAfterTargetFlash >= 0) - Number(a.floorMarginAfterTargetFlash >= 0)
}
if (a.repayMargin !== b.repayMargin) return b.repayMargin - a.repayMargin
if (a.floorMarginAfterTargetFlash !== b.floorMarginAfterTargetFlash) {
return b.floorMarginAfterTargetFlash - a.floorMarginAfterTargetFlash
}
} else {
if (a.maxFlashKeepFloor !== b.maxFlashKeepFloor) return b.maxFlashKeepFloor - a.maxFlashKeepFloor
if (a.floorSurplusNoFlash !== b.floorSurplusNoFlash) return b.floorSurplusNoFlash - a.floorSurplusNoFlash
}
if (a.retainedPerCw !== b.retainedPerCw) return b.retainedPerCw - a.retainedPerCw
return a.grossBaseIn - b.grossBaseIn
}
function printInventoryLoopSafetyScan(
B,
Q,
scanStr,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
guardConfig,
flashAddToPool,
) {
const candidates = buildInventoryLoopCandidates(
B,
Q,
scanStr,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
guardConfig,
flashAddToPool,
)
const eligibleCandidates = candidates.filter((candidate) => candidate.recommendationOk)
const gasReserveSummary = summarizeGasReserve(guardConfig)
const currentMarginalPrice = marginalQuotePerBase(B, Q)
const currentDeviation = deviationBps(currentMarginalPrice, guardConfig.oraclePrice)
console.log('Inventory-backed flash safety scan — sell cW base into PMM, borrow only what can be repaid\n')
console.log(` source reserves: B=${fmt(B)} cW base, Q=${fmt(Q)} USDC quote`)
console.log(` pool fee=${lpFeeBps} bps`)
console.log(` flash fee=${flashFeeBps} bps`)
console.log(` oracle price=${fmt(guardConfig.oraclePrice)} quote per cW base`)
console.log(` current marginal price=${fmt(currentMarginalPrice)} current deviation=${fmt(currentDeviation)} bps`)
console.log(` retained USDC floor=${fmtAmount(guardConfig.requiredRetainedUsdc, guardConfig.quoteDecimals, 'USDC')}`)
if (guardConfig.gasReserveQuote > 0) {
console.log(
` native gas reserve=${fmt(guardConfig.gasReserveNative)} native = ${fmt(guardConfig.gasReserveQuoteHuman)} USDC (${gasReserveSummary})`,
)
}
if (inventoryBase != null) console.log(` inventoryBase available=${fmt(inventoryBase)}`)
if (targetFlashBorrow != null) console.log(` target flash borrow=${fmt(targetFlashBorrow)} target repay=${fmt(repayUsdc(targetFlashBorrow, flashFeeBps))}`)
if (flashAddToPool && targetFlashBorrow != null) {
console.log(` flash loop mode=temporary quote top-up before PMM leg (effective Q=${fmt(Q + targetFlashBorrow)})`)
}
if (guardConfig.maxPostTradeDeviationBps != null) {
console.log(` max post-trade deviation=${fmt(guardConfig.maxPostTradeDeviationBps)} bps`)
}
if (guardConfig.maxCwBurnFraction != null) {
console.log(` max cW burn fraction=${fmt(guardConfig.maxCwBurnFraction)} of inventory-base`)
}
if (guardConfig.cooldownBlocks > 0) {
console.log(` cooldown after execution=${guardConfig.cooldownBlocks} blocks before next tranche`)
}
console.log('')
console.log(
'gross_cw_in\tquote_out\tUSDC_per_cw\tmax_flash_no_loss\tmax_flash_keep_floor\tpool_base_delta\tpool_quote_delta\tpost_trade_dev_bps\tcw_burn_frac\tguard_status',
)
let bestBorrow = null
let bestEfficiency = null
for (const candidate of candidates) {
if (
candidate.recommendationOk &&
(bestBorrow == null || candidate.maxFlashKeepFloor > bestBorrow.maxFlashKeepFloor)
) {
bestBorrow = candidate
}
if (
candidate.recommendationOk &&
(bestEfficiency == null || candidate.retainedPerCw > bestEfficiency.retainedPerCw)
) {
bestEfficiency = candidate
}
console.log(
[
fmt(candidate.grossBaseIn),
fmt(candidate.quoteOut),
fmt(candidate.usdcPerCw),
fmt(candidate.maxFlashNoLoss),
fmt(candidate.maxFlashKeepFloor),
fmt(candidate.poolBaseDelta),
fmt(candidate.poolQuoteDelta),
fmt(candidate.postTradeDeviationBps),
candidate.inventoryBurnFraction == null ? 'n/a' : fmt(candidate.inventoryBurnFraction),
formatGuardStatus(candidate),
].join('\t'),
)
}
console.log('')
if (bestBorrow) {
console.log(
` Max safe flash borrow while keeping the floor is highest at gross_cw_in=${fmt(bestBorrow.grossBaseIn)} → max_flash_keep_floor=${fmt(bestBorrow.maxFlashKeepFloor)}.`,
)
}
if (bestEfficiency) {
console.log(
` Best USDC retained per cW sacrificed is the smallest tested leg: gross_cw_in=${fmt(bestEfficiency.grossBaseIn)} → retained_per_cw=${fmt(bestEfficiency.retainedPerCw)}.`,
)
}
if (eligibleCandidates.length === 0) {
const closest = candidates[0]
console.log(
` No tranche passes the active guards. Top-ranked ineligible candidate gross_cw_in=${fmt(closest.grossBaseIn)} fails ${formatGuardStatus(closest)}.`,
)
}
if (guardConfig.cooldownBlocks > 0 && eligibleCandidates.length > 0) {
console.log(` Execute at most one eligible tranche per ${guardConfig.cooldownBlocks}-block window.`)
}
if (flashAddToPool && targetFlashBorrow != null) {
const anySamePoolQuoteDeepening = candidates.some(
(candidate) => candidate.samePoolQuoteDeepeningWithPmmRepayPossible,
)
if (!anySamePoolQuoteDeepening) {
console.log(
' Invariant: if the flash-borrowed quote is temporarily added to the same PMM and repaid from that same PMM quote-out leg, the pool cannot finish with a higher quote reserve Q. This loop deepens base B; permanent quote-side deepening requires outside proceeds.',
)
}
}
console.log(' Execution rule: repay flash first, then seed only the retained USDC remainder.')
console.log('')
}
function printInventoryLoopRanking(
B,
Q,
scanStr,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
guardConfig,
rankProfile,
flashAddToPool,
) {
const candidates = buildInventoryLoopCandidates(
B,
Q,
scanStr,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
guardConfig,
flashAddToPool,
).sort((a, b) => compareInventoryLoopCandidates(a, b, targetFlashBorrow, rankProfile))
const eligibleCandidates = candidates.filter((candidate) => candidate.recommendationOk)
const recommended = eligibleCandidates[0] ?? null
const runnerUp = eligibleCandidates[1] ?? null
const gasReserveSummary = summarizeGasReserve(guardConfig)
const currentMarginalPrice = marginalQuotePerBase(B, Q)
const currentDeviation = deviationBps(currentMarginalPrice, guardConfig.oraclePrice)
const profileSummary = rankProfileSummary(rankProfile, targetFlashBorrow)
const winningExplanation = explainWinningCandidate(recommended, runnerUp, rankProfile, targetFlashBorrow)
const efficiencyLabel = efficiencyMetricLabel(targetFlashBorrow)
console.log('Inventory-backed tranche ranking\n')
console.log(` source reserves: B=${fmt(B)} cW base, Q=${fmt(Q)} USDC quote`)
console.log(` pool fee=${lpFeeBps} bps`)
console.log(` flash fee=${flashFeeBps} bps`)
console.log(` oracle price=${fmt(guardConfig.oraclePrice)} quote per cW base`)
console.log(` current marginal price=${fmt(currentMarginalPrice)} current deviation=${fmt(currentDeviation)} bps`)
console.log(` retained USDC floor=${fmtAmount(guardConfig.requiredRetainedUsdc, guardConfig.quoteDecimals, 'USDC')}`)
if (guardConfig.gasReserveQuote > 0) {
console.log(
` native gas reserve=${fmt(guardConfig.gasReserveNative)} native = ${fmt(guardConfig.gasReserveQuoteHuman)} USDC (${gasReserveSummary})`,
)
}
if (inventoryBase != null) console.log(` inventoryBase available=${fmt(inventoryBase)}`)
if (targetFlashBorrow != null) {
console.log(` ranking against target flash borrow=${fmt(targetFlashBorrow)} repay=${fmt(repayUsdc(targetFlashBorrow, flashFeeBps))}`)
} else {
console.log(' ranking mode: eligible tranches are ordered by the selected rank profile')
}
if (flashAddToPool && targetFlashBorrow != null) {
console.log(` flash loop mode=temporary quote top-up before PMM leg (effective Q=${fmt(Q + targetFlashBorrow)})`)
}
console.log(` rank profile=${rankProfile}`)
console.log(` profile priorities=${profileSummary}`)
if (guardConfig.maxPostTradeDeviationBps != null) {
console.log(` max post-trade deviation=${fmt(guardConfig.maxPostTradeDeviationBps)} bps`)
}
if (guardConfig.maxCwBurnFraction != null) {
console.log(` max cW burn fraction=${fmt(guardConfig.maxCwBurnFraction)} of inventory-base`)
}
if (guardConfig.cooldownBlocks > 0) {
console.log(` cooldown after execution=${guardConfig.cooldownBlocks} blocks before next tranche`)
}
console.log('')
if (targetFlashBorrow != null) {
console.log(
`rank\tgross_cw_in\trepay_margin\tfloor_margin_after_repay\tpool_base_delta\tpool_quote_delta\tpost_trade_dev_bps\tcw_burn_frac\t${efficiencyLabel}\tguard_status`,
)
} else {
console.log(
`rank\tgross_cw_in\tmax_flash_keep_floor\tfloor_surplus_no_flash\tpool_base_delta\tpool_quote_delta\tpost_trade_dev_bps\tcw_burn_frac\t${efficiencyLabel}\tguard_status`,
)
}
candidates.forEach((candidate, index) => {
if (targetFlashBorrow != null) {
console.log(
[
index + 1,
fmt(candidate.grossBaseIn),
fmt(candidate.repayMargin),
fmt(candidate.floorMarginAfterTargetFlash),
fmt(candidate.poolBaseDelta),
fmt(candidate.poolQuoteDelta),
fmt(candidate.postTradeDeviationBps),
candidate.inventoryBurnFraction == null ? 'n/a' : fmt(candidate.inventoryBurnFraction),
fmt(candidateEfficiencyValue(candidate, targetFlashBorrow)),
formatGuardStatus(candidate),
].join('\t'),
)
return
}
console.log(
[
index + 1,
fmt(candidate.grossBaseIn),
fmt(candidate.maxFlashKeepFloor),
fmt(candidate.floorSurplusNoFlash),
fmt(candidate.poolBaseDelta),
fmt(candidate.poolQuoteDelta),
fmt(candidate.postTradeDeviationBps),
candidate.inventoryBurnFraction == null ? 'n/a' : fmt(candidate.inventoryBurnFraction),
fmt(candidateEfficiencyValue(candidate, targetFlashBorrow)),
formatGuardStatus(candidate),
].join('\t'),
)
})
if (recommended) {
console.log('')
if (targetFlashBorrow != null) {
console.log(
` Recommended tranche: gross_cw_in=${fmt(recommended.grossBaseIn)} with repay_margin=${fmt(recommended.repayMargin)}, floor_margin_after_repay=${fmt(recommended.floorMarginAfterTargetFlash)}, post_trade_dev_bps=${fmt(recommended.postTradeDeviationBps)}, ${efficiencyLabel}=${fmt(candidateEfficiencyValue(recommended, targetFlashBorrow))}.`,
)
} else {
console.log(
` Recommended tranche: gross_cw_in=${fmt(recommended.grossBaseIn)} with max_flash_keep_floor=${fmt(recommended.maxFlashKeepFloor)}, floor_surplus_no_flash=${fmt(recommended.floorSurplusNoFlash)}, post_trade_dev_bps=${fmt(recommended.postTradeDeviationBps)}, ${efficiencyLabel}=${fmt(candidateEfficiencyValue(recommended, targetFlashBorrow))}.`,
)
}
if (winningExplanation) console.log(` Why it won: ${winningExplanation}`)
if (guardConfig.cooldownBlocks > 0) {
console.log(` Execute once, then wait ${guardConfig.cooldownBlocks} blocks before the next tranche.`)
}
if (flashAddToPool && targetFlashBorrow != null && !recommended.samePoolQuoteDeepeningWithPmmRepayPossible) {
console.log(
' Reserve invariant: this recommendation can still deepen base B, but it cannot both repay the same PMM-funded flash top-up and leave quote reserve Q above the starting level without outside proceeds.',
)
}
} else if (candidates[0]) {
console.log('')
console.log(
` No tranche passes the active guards. Top-ranked ineligible candidate gross_cw_in=${fmt(candidates[0].grossBaseIn)} fails ${formatGuardStatus(candidates[0])}.`,
)
}
if (flashAddToPool && targetFlashBorrow != null) {
const anySamePoolQuoteDeepening = candidates.some(
(candidate) => candidate.samePoolQuoteDeepeningWithPmmRepayPossible,
)
if (!anySamePoolQuoteDeepening) {
console.log(
' Invariant: no tested tranche can both repay the same-pool flash top-up and end with higher quote reserve Q. Use outside proceeds if quote-side deepening is the goal.',
)
}
}
console.log('')
}
function runExamples() {
console.log('PMM flash push — baseline recalc (same units on all amounts)\n')
const B = 10e6
const Q = 10e6
const flash = 5
printScenario('$10M trade, 0 LP fee, external 1.00', B, Q, 10e6, 0, flash, 1.0, 0)
printScenario('$10M trade, 3 LP fee bps, external 1.00', B, Q, 10e6, 3, flash, 1.0, 0)
printScenario('$2M trade, 0 LP fee, external 1.00', B, Q, 2e6, 0, flash, 1.0, 0)
printScenario('$2M trade, 3 LP fee bps, external 1.00', B, Q, 2e6, 3, flash, 1.0, 0)
printScenario('$10M trade, 0 LP fee — break-even check P_ext=2.001', B, Q, 10e6, 0, flash, 2.001, 0)
printScenario('$2M trade, 0 LP fee — break-even check P_ext≈1.201', B, Q, 2e6, 0, flash, 1.2006, 0)
}
function main() {
const { values, tokens } = parseArgs({
options: {
examples: { type: 'boolean', short: 'e' },
'base-reserve': { type: 'string', short: 'B' },
'quote-reserve': { type: 'string', short: 'Q' },
trade: { type: 'string', short: 'x' },
'lp-fee-bps': { type: 'string', default: '3' },
'flash-fee-bps': { type: 'string', default: '5' },
'external-price': { type: 'string' },
'exit-fee-bps': { type: 'string', default: '0' },
scan: { type: 'string' },
'seed-pools': { type: 'string' },
'target-quote-per-pool': { type: 'string' },
'target-total-quote': { type: 'string' },
'inventory-base': { type: 'string' },
'loop-count': { type: 'string' },
'sequential-matched-loops': { type: 'string' },
'matched-flash-numerator': { type: 'string' },
'matched-flash-denominator': { type: 'string' },
'inventory-loop-scan': { type: 'boolean' },
'inventory-loop-rank': { type: 'boolean' },
'min-retained-usdc': { type: 'string', default: '0' },
'target-flash-borrow': { type: 'string' },
'flash-add-to-pool': { type: 'boolean' },
'full-loop-dry-run': { type: 'boolean' },
'public-live-sweep': { type: 'boolean' },
'public-flash-source': { type: 'string', default: 'aave' },
'loop-strategy': { type: 'string', default: 'quote-push' },
'owned-base-add': { type: 'string', default: '0' },
'flash-topup-quote': { type: 'string', default: '0' },
'atomic-bridge-base-amount': { type: 'string', default: '0' },
'atomic-destination-amount': { type: 'string' },
'atomic-destination-asset': { type: 'string' },
'atomic-destination-decimals': { type: 'string' },
'atomic-corridor-label': { type: 'string' },
'scan-atomic-bridge-max': { type: 'boolean' },
'flash-provider-cap': { type: 'string' },
'flash-provider-name': { type: 'string', default: 'flash provider' },
'flash-provider-address': { type: 'string' },
'flash-provider-token-address': { type: 'string' },
'flash-provider-rpc-url': { type: 'string' },
'external-via-asset': { type: 'string' },
'external-fee-bps': { type: 'string' },
'external-entry-price': { type: 'string' },
'external-exit-price': { type: 'string' },
'external-entry-fee-bps': { type: 'string' },
'external-exit-fee-bps': { type: 'string' },
'external-entry-price-cmd': { type: 'string' },
'external-exit-price-cmd': { type: 'string' },
'external-entry-source': { type: 'string', default: 'manual' },
'external-exit-source': { type: 'string', default: 'manual' },
'measured-gas-quote': { type: 'string' },
'measured-gas-source': { type: 'string', default: 'CLI measured gas quote override' },
'execution-grade': { type: 'boolean' },
'rank-profile': { type: 'string', default: 'balanced' },
'funding-readiness': { type: 'boolean' },
'inventory-asset': { type: 'string', default: 'cWUSDC' },
'base-asset': { type: 'string', default: 'base' },
'base-decimals': { type: 'string', default: '6' },
'source-asset': { type: 'string' },
'quote-asset': { type: 'string', default: 'USDC' },
'quote-decimals': { type: 'string', default: '6' },
'balance-report': { type: 'string' },
'gas-tx-count': { type: 'string' },
'gas-per-tx': { type: 'string' },
'max-fee-gwei': { type: 'string' },
'native-token-price': { type: 'string' },
'oracle-price': { type: 'string', default: '1' },
'max-post-trade-deviation-bps': { type: 'string' },
'max-cw-burn-fraction': { type: 'string' },
'cooldown-blocks': { type: 'string', default: '0' },
'mainnet-map': { type: 'boolean' },
'compare-deepen': { type: 'string' },
help: { type: 'boolean', short: 'h' },
},
allowPositionals: false,
tokens: true,
})
if (values.help) {
console.log(`Usage:
--examples, -e Print $10M / $2M baseline vs plan (10M/10M reserves)
--mainnet-map Print Ethereum mainnet cWUSDC/USDC pool map from deployment-status.json
--compare-deepen D With --mainnet-map: add D to base reserve and tabulate slippage (-B -Q required)
-B, --base-reserve Base token reserve (units)
-Q, --quote-reserve Quote token reserve (units)
-x, --trade Gross quote amount in (flash borrow / swap size)
--lp-fee-bps Pool fee on input (default 3 = 0.03%%; with --compare-deepen, overrides registry fee)
--flash-fee-bps Flash fee on repayment (default 5 = 0.05%%; use 0 for funded-inventory loop)
--external-price Generic gross quote-per-base external price; used as exit price in quote-push mode or entry price in base-unwind mode
--exit-fee-bps Legacy generic external fee/slippage bps (default 0); full-loop mode prefers the more specific external-* fee flags
--scan Comma-separated trade sizes (same units as -x)
--seed-pools Number of destination pools to seed with USDC quote
--target-quote-per-pool Target quote to add per pool in raw token units (e.g. 1000000 = 1 USDC if decimals=6)
--target-total-quote Total quote to raise in raw token units (alternative to per-pool target)
--inventory-base Available cW base inventory to compare against requirement
--loop-count Split the seeding plan into this many sequential loops (defaults to seed-pools or 1)
--sequential-matched-loops N Run N modeled quote-push loops; after each, set B=Q=endQuote (whitepaper ladder). Requires matched -B/-Q. Flash size: round(matched*num/den); defaults num/den=6342691/256763253
--matched-flash-numerator Override numerator for --sequential-matched-loops flash sizing (default 6342691)
--matched-flash-denominator Override denominator for --sequential-matched-loops flash sizing (default 256763253)
--inventory-loop-scan Treat --scan as gross cW sizes; compute safe flash ceilings and retained USDC
--inventory-loop-rank Rank tranche sizes by repay safety, retained floor, and retained-USDC-per-cW efficiency
--min-retained-usdc In inventory-loop-scan mode, keep at least this much USDC after flash repayment
--target-flash-borrow Optional borrow size to rank against actual repay/floor margins
--flash-add-to-pool Assume --target-flash-borrow is temporarily added to PMM quote reserve before the PMM leg
--full-loop-dry-run Simulate borrow -> strategy legs -> repay -> gas reserve -> pool seeding
--public-live-sweep Probe live mainnet public cWUSD*/USD* PMM pools and scan tranche sizes with recommendations
--public-flash-source Flash source for --public-live-sweep: aave|balancer|manual (default aave)
--loop-strategy quote-push (PMM quote-in then external unwind) or base-unwind (external acquire then PMM base-in)
--owned-base-add Permanently add this much owned base inventory to the source PMM before the modeled flash loop
--flash-topup-quote Temporarily add this much borrowed quote to source PMM before the modeled strategy leg
--atomic-bridge-base-amount Reserve this much PMM-acquired base into the atomic corridor before the external unwind
--atomic-destination-amount Immediate destination fulfillment amount to report for the atomic corridor (defaults to the reserved base amount, scaled by decimals)
--atomic-destination-asset Destination asset label for the atomic corridor report (e.g. cUSDC)
--atomic-destination-decimals Destination asset decimals for the atomic corridor report (default base decimals)
--atomic-corridor-label Human label for the atomic corridor, e.g. 1->138 cWUSDC->cUSDC
--scan-atomic-bridge-max Solve for the largest atomic corridor reservation that still passes repay-only and full positive-after-gas guards
--flash-provider-cap Optional flash source cap to enforce in full-loop dry-run or public-live-sweep
--flash-provider-name Label for the flash source in full-loop dry-run or manual public-live-sweep output
--flash-provider-address ERC-3156 flash lender address to probe live in full-loop dry-run (defaults to env FLASH_VAULT)
--flash-provider-token-address Token address to use with the ERC-3156 flash lender probe (defaults to env FLASH_VAULT_TOKEN)
--flash-provider-rpc-url RPC URL for the flash lender probe (defaults to FLASH_PROVIDER_RPC_URL, then RPC_URL_138_PUBLIC, RPC_URL_138, CHAIN138_RPC_URL, ETHEREUM_MAINNET_RPC)
--external-via-asset Optional intermediate asset label for reporting, e.g. ETH
--external-fee-bps Generic external-route fee/slippage bps fallback for full-loop mode
--external-entry-price Effective gross quote-per-base acquisition price for external quote->base leg
--external-exit-price Effective gross quote-per-base monetization price for external base->quote leg
--external-entry-fee-bps Entry-leg fee/slippage bps override for full-loop mode
--external-exit-fee-bps Exit-leg fee/slippage bps override for full-loop mode
--external-entry-price-cmd Shell command that prints a live entry price; overrides --external-entry-price and marks the source live
--external-exit-price-cmd Shell command that prints a live exit price; overrides --external-exit-price and marks the source live
--external-entry-source Source label for entry pricing: live|manual|scenario (default manual)
--external-exit-source Source label for exit pricing: live|manual|scenario (default manual)
--measured-gas-quote Measured end-to-end gas reserve in human quote units; overrides modeled gas reserve
--measured-gas-source Label for the measured gas input
--execution-grade Require live pool quote surface + the strategy's live external quote source(s) + measured or live-estimated gas + an explicit post-trade deviation cap before calling a tranche executable
--rank-profile Rank eligible tranches as conservative|balanced|efficiency (default balanced)
--funding-readiness Compare live mainnet funded inventory vs bridge-reachable Chain 138 inventory for a target raise
--inventory-asset Inventory asset on mainnet for readiness mode (default cWUSDC)
--base-asset Base asset label for --full-loop-dry-run output (default base)
--base-decimals Base asset decimals for --full-loop-dry-run output/math (default 6)
--source-asset Source asset on Chain 138 for readiness mode (default inferred from inventory asset)
--quote-asset Quote asset label for readiness mode and --full-loop-dry-run (default USDC)
--quote-decimals Quote asset decimals for --full-loop-dry-run output/math (default 6)
--balance-report Optional explicit deployer balance report JSON path for readiness fallback
--gas-tx-count Reserve native gas for this many follow-up transactions (inventory-loop or full-loop dry-run)
--gas-per-tx Gas limit per reserved transaction, in native gas units
--max-fee-gwei Gas price cap in gwei for native reserve sizing
--native-token-price Quote price of the native gas token (e.g. ETH price in USDC)
--oracle-price Peg/oracle target in quote per cW base (default 1)
--max-post-trade-deviation-bps Hard cap on absolute post-trade peg deviation
--max-cw-burn-fraction Hard cap on gross cW burn as a fraction of --inventory-base
--cooldown-blocks Execution note: wait this many blocks between eligible tranches
-h, --help This help
`)
process.exit(0)
}
if (values.examples) {
runExamples()
process.exit(0)
}
const B = values['base-reserve'] != null ? parseNum(values['base-reserve']) : null
const Q = values['quote-reserve'] != null ? parseNum(values['quote-reserve']) : null
const lpFeeBps = parseNum(values['lp-fee-bps'] ?? '3')
const lpFeeBpsWasExplicit = tokens.some((token) => token.kind === 'option' && token.name === 'lp-fee-bps')
const flashFeeBps = parseNum(values['flash-fee-bps'] ?? '5')
const exitFeeBps = parseNum(values['exit-fee-bps'] ?? '0')
const externalPrice =
values['external-price'] != null ? parseNum(values['external-price']) : undefined
const seedPools =
values['seed-pools'] != null ? parsePositiveInt(values['seed-pools'], '--seed-pools') : null
const targetQuotePerPool =
values['target-quote-per-pool'] != null ? parseNum(values['target-quote-per-pool']) : null
const targetTotalQuote =
values['target-total-quote'] != null ? parseNum(values['target-total-quote']) : null
const inventoryBase =
values['inventory-base'] != null ? parseNum(values['inventory-base']) : null
const loopCountOverride =
values['loop-count'] != null ? parsePositiveInt(values['loop-count'], '--loop-count') : null
const sequentialMatchedLoops =
values['sequential-matched-loops'] != null
? parsePositiveInt(values['sequential-matched-loops'], '--sequential-matched-loops')
: null
const matchedFlashNumerator =
values['matched-flash-numerator'] != null
? parsePositiveInt(values['matched-flash-numerator'], '--matched-flash-numerator')
: 6342691
const matchedFlashDenominator =
values['matched-flash-denominator'] != null
? parsePositiveInt(values['matched-flash-denominator'], '--matched-flash-denominator')
: 256763253
const minRetainedUsdc = parseNum(values['min-retained-usdc'] ?? '0')
const targetFlashBorrow =
values['target-flash-borrow'] != null ? parseNum(values['target-flash-borrow']) : null
const flashAddToPool = values['flash-add-to-pool']
const fullLoopDryRunMode = values['full-loop-dry-run']
const loopStrategy = String(values['loop-strategy'] ?? 'quote-push')
const ownedBaseAdd = parseNum(values['owned-base-add'] ?? '0')
const flashTopupQuote = parseNum(values['flash-topup-quote'] ?? '0')
const atomicBridgeBaseAmount = parseNum(values['atomic-bridge-base-amount'] ?? '0')
const atomicDestinationAmount =
values['atomic-destination-amount'] != null ? parseNum(values['atomic-destination-amount']) : null
const atomicDestinationAsset =
values['atomic-destination-asset'] != null ? String(values['atomic-destination-asset']) : null
const atomicDestinationDecimals =
values['atomic-destination-decimals'] != null
? parseNonNegativeInt(values['atomic-destination-decimals'], '--atomic-destination-decimals')
: null
const atomicCorridorLabel =
values['atomic-corridor-label'] != null ? String(values['atomic-corridor-label']) : null
const scanAtomicBridgeMax = values['scan-atomic-bridge-max']
const flashProviderCap =
values['flash-provider-cap'] != null ? parseNum(values['flash-provider-cap']) : null
const flashProviderName = String(values['flash-provider-name'] ?? 'flash provider')
const flashProviderAddress =
values['flash-provider-address'] != null
? String(values['flash-provider-address'])
: (process.env.FLASH_VAULT ?? null)
const flashProviderTokenAddress =
values['flash-provider-token-address'] != null
? String(values['flash-provider-token-address'])
: (process.env.FLASH_VAULT_TOKEN ?? null)
const flashProviderRpcUrl =
values['flash-provider-rpc-url'] != null
? String(values['flash-provider-rpc-url'])
: process.env.FLASH_PROVIDER_RPC_URL ??
process.env.RPC_URL_138_PUBLIC ??
process.env.RPC_URL_138 ??
process.env.CHAIN138_RPC_URL ??
process.env.ETHEREUM_MAINNET_RPC ??
null
const externalViaAsset = values['external-via-asset'] != null ? String(values['external-via-asset']) : null
const externalFeeBps =
values['external-fee-bps'] != null ? parseNum(values['external-fee-bps']) : exitFeeBps
const externalEntryPriceCmd =
values['external-entry-price-cmd'] != null ? String(values['external-entry-price-cmd']) : null
const externalExitPriceCmd =
values['external-exit-price-cmd'] != null ? String(values['external-exit-price-cmd']) : null
const liveExternalEntryPrice = tryReadNumericCommand(
externalEntryPriceCmd,
externalEntryPriceCmd ? `live command: ${externalEntryPriceCmd}` : null,
)
const liveExternalExitPrice = tryReadNumericCommand(
externalExitPriceCmd,
externalExitPriceCmd ? `live command: ${externalExitPriceCmd}` : null,
)
const externalEntryPrice =
liveExternalEntryPrice?.value ??
(values['external-entry-price'] != null ? parseNum(values['external-entry-price']) : externalPrice)
const externalExitPrice =
liveExternalExitPrice?.value ??
(values['external-exit-price'] != null ? parseNum(values['external-exit-price']) : externalPrice)
const externalEntryFeeBps =
values['external-entry-fee-bps'] != null ? parseNum(values['external-entry-fee-bps']) : externalFeeBps
const externalExitFeeBps =
values['external-exit-fee-bps'] != null ? parseNum(values['external-exit-fee-bps']) : externalFeeBps
const externalEntrySource = liveExternalEntryPrice ? 'live' : String(values['external-entry-source'] ?? 'manual')
const externalExitSource = liveExternalExitPrice ? 'live' : String(values['external-exit-source'] ?? 'manual')
const measuredGasQuote =
values['measured-gas-quote'] != null ? parseNum(values['measured-gas-quote']) : null
const measuredGasSource = String(values['measured-gas-source'] ?? 'CLI measured gas quote override')
const executionGradeRequired = values['execution-grade']
const rankProfile = String(values['rank-profile'] ?? 'balanced')
const fundingReadinessMode = values['funding-readiness']
const inventoryAsset = String(values['inventory-asset'] ?? 'cWUSDC')
const baseAsset = String(values['base-asset'] ?? 'base')
const baseDecimals = parseNonNegativeInt(values['base-decimals'] ?? '6', '--base-decimals')
const sourceAsset = values['source-asset'] != null ? String(values['source-asset']) : inferSourceAsset(inventoryAsset)
const quoteAsset = String(values['quote-asset'] ?? 'USDC')
const quoteDecimals = parseNonNegativeInt(values['quote-decimals'] ?? '6', '--quote-decimals')
const balanceReportPath =
values['balance-report'] != null ? resolve(process.cwd(), String(values['balance-report'])) : latestBalanceReportPath()
const gasTxCount =
values['gas-tx-count'] != null ? parsePositiveInt(values['gas-tx-count'], '--gas-tx-count') : null
const gasPerTx = values['gas-per-tx'] != null ? parseNum(values['gas-per-tx']) : null
const maxFeeGwei = values['max-fee-gwei'] != null ? parseNum(values['max-fee-gwei']) : null
const nativeTokenPrice =
values['native-token-price'] != null ? parseNum(values['native-token-price']) : null
const oraclePrice = parseNum(values['oracle-price'] ?? '1')
const maxPostTradeDeviationBps =
values['max-post-trade-deviation-bps'] != null
? parseNum(values['max-post-trade-deviation-bps'])
: null
const maxCwBurnFraction =
values['max-cw-burn-fraction'] != null ? parseNum(values['max-cw-burn-fraction']) : null
const cooldownBlocks = parseNonNegativeInt(values['cooldown-blocks'] ?? '0', '--cooldown-blocks')
const inventoryLoopScanMode = values['inventory-loop-scan']
const inventoryLoopRankMode = values['inventory-loop-rank']
const inventoryLoopMode = inventoryLoopScanMode || inventoryLoopRankMode
const publicLiveSweepMode = values['public-live-sweep']
const publicFlashSource = String(values['public-flash-source'] ?? 'aave')
const gasReserveFlagsUsed = gasTxCount != null || gasPerTx != null || maxFeeGwei != null
const extraGuardFlagsUsed =
gasReserveFlagsUsed ||
measuredGasQuote != null ||
maxPostTradeDeviationBps != null ||
maxCwBurnFraction != null ||
cooldownBlocks > 0
const seedMode =
!fundingReadinessMode &&
!inventoryLoopMode &&
!publicLiveSweepMode &&
(
seedPools != null ||
targetQuotePerPool != null ||
targetTotalQuote != null ||
inventoryBase != null ||
loopCountOverride != null
)
if (
!fundingReadinessMode &&
tokens.some(
(token) =>
token.kind === 'option' &&
['inventory-asset', 'source-asset', 'balance-report'].includes(token.name),
)
) {
console.error(
'Error: --inventory-asset, --source-asset, and --balance-report are only supported with --funding-readiness',
)
process.exit(1)
}
if (!['conservative', 'balanced', 'efficiency'].includes(rankProfile)) {
console.error('Error: --rank-profile must be one of conservative, balanced, efficiency')
process.exit(1)
}
if (!['live', 'manual', 'scenario'].includes(externalEntrySource)) {
console.error('Error: --external-entry-source must be one of live, manual, scenario')
process.exit(1)
}
if (!['live', 'manual', 'scenario'].includes(externalExitSource)) {
console.error('Error: --external-exit-source must be one of live, manual, scenario')
process.exit(1)
}
if (!['aave', 'balancer', 'manual'].includes(publicFlashSource)) {
console.error('Error: --public-flash-source must be one of aave, balancer, manual')
process.exit(1)
}
if (tokens.some((token) => token.kind === 'option' && token.name === 'public-flash-source') && !publicLiveSweepMode) {
console.error('Error: --public-flash-source is only supported with --public-live-sweep')
process.exit(1)
}
if (tokens.some((token) => token.kind === 'option' && token.name === 'rank-profile') && !inventoryLoopRankMode) {
console.error('Error: --rank-profile is only supported with --inventory-loop-rank')
process.exit(1)
}
if (!['quote-push', 'base-unwind', 'both'].includes(loopStrategy)) {
console.error('Error: --loop-strategy must be one of quote-push, base-unwind, both')
process.exit(1)
}
if (loopStrategy === 'both' && !publicLiveSweepMode) {
console.error('Error: --loop-strategy both is only supported with --public-live-sweep')
process.exit(1)
}
if (flashAddToPool && !inventoryLoopMode) {
console.error('Error: --flash-add-to-pool is only supported with --inventory-loop-scan or --inventory-loop-rank')
process.exit(1)
}
if (
tokens.some((token) => token.kind === 'option' && token.name === 'flash-provider-cap') &&
!fullLoopDryRunMode &&
!publicLiveSweepMode &&
sequentialMatchedLoops == null
) {
console.error(
'Error: --flash-provider-cap is only supported with --full-loop-dry-run, --public-live-sweep, or --sequential-matched-loops',
)
process.exit(1)
}
if (
tokens.some((token) => token.kind === 'option' && token.name === 'flash-provider-name') &&
!fullLoopDryRunMode &&
!publicLiveSweepMode &&
sequentialMatchedLoops == null
) {
console.error(
'Error: --flash-provider-name is only supported with --full-loop-dry-run, --public-live-sweep, or --sequential-matched-loops',
)
process.exit(1)
}
if (
tokens.some((token) =>
token.kind === 'option' &&
['flash-provider-address', 'flash-provider-token-address', 'flash-provider-rpc-url'].includes(token.name),
) &&
!fullLoopDryRunMode
) {
console.error(
'Error: --flash-provider-address, --flash-provider-token-address, and --flash-provider-rpc-url are only supported with --full-loop-dry-run',
)
process.exit(1)
}
if (
tokens.some((token) =>
token.kind === 'option' &&
[
'loop-strategy',
'owned-base-add',
'flash-topup-quote',
'atomic-bridge-base-amount',
'atomic-destination-amount',
'atomic-destination-asset',
'atomic-destination-decimals',
'atomic-corridor-label',
'scan-atomic-bridge-max',
'external-via-asset',
'external-fee-bps',
'external-entry-price',
'external-exit-price',
'external-entry-fee-bps',
'external-exit-fee-bps',
'external-entry-source',
'external-exit-source',
'measured-gas-quote',
'measured-gas-source',
'execution-grade',
].includes(token.name),
) &&
!fullLoopDryRunMode &&
!publicLiveSweepMode &&
sequentialMatchedLoops == null
) {
console.error(
'Error: strategy routing flags are only supported with --full-loop-dry-run, --public-live-sweep, or --sequential-matched-loops',
)
process.exit(1)
}
if (flashAddToPool && targetFlashBorrow == null) {
console.error('Error: --flash-add-to-pool requires --target-flash-borrow')
process.exit(1)
}
if (
extraGuardFlagsUsed &&
!inventoryLoopMode &&
!fullLoopDryRunMode &&
!publicLiveSweepMode &&
sequentialMatchedLoops == null
) {
console.error(
'Error: gas reserve and peg-safety guard flags are only supported with --inventory-loop-scan, --inventory-loop-rank, --full-loop-dry-run, --public-live-sweep, or --sequential-matched-loops',
)
process.exit(1)
}
if ((fullLoopDryRunMode || publicLiveSweepMode || sequentialMatchedLoops != null) && maxCwBurnFraction != null) {
console.error('Error: --max-cw-burn-fraction is only supported with --inventory-loop-scan or --inventory-loop-rank')
process.exit(1)
}
if ((fullLoopDryRunMode || publicLiveSweepMode || sequentialMatchedLoops != null) && cooldownBlocks > 0) {
console.error('Error: --cooldown-blocks is only supported with --inventory-loop-scan or --inventory-loop-rank')
process.exit(1)
}
if (!(flashTopupQuote >= 0)) {
console.error('Error: --flash-topup-quote must be non-negative')
process.exit(1)
}
if (!(atomicBridgeBaseAmount >= 0)) {
console.error('Error: --atomic-bridge-base-amount must be non-negative')
process.exit(1)
}
if (atomicDestinationAmount != null && !(atomicDestinationAmount >= 0)) {
console.error('Error: --atomic-destination-amount must be non-negative')
process.exit(1)
}
if (!(ownedBaseAdd >= 0)) {
console.error('Error: --owned-base-add must be non-negative')
process.exit(1)
}
if (!(oraclePrice > 0)) {
console.error('Error: --oracle-price must be greater than zero')
process.exit(1)
}
if (gasReserveFlagsUsed && measuredGasQuote != null) {
console.error('Error: use either modeled gas inputs or --measured-gas-quote, not both')
process.exit(1)
}
if (gasReserveFlagsUsed) {
if (gasTxCount == null || gasPerTx == null || maxFeeGwei == null || nativeTokenPrice == null) {
console.error(
'Error: native gas reserve requires --gas-tx-count, --gas-per-tx, --max-fee-gwei, and --native-token-price together',
)
process.exit(1)
}
if (!(gasPerTx > 0) || !(maxFeeGwei > 0) || !(nativeTokenPrice > 0)) {
console.error('Error: --gas-per-tx, --max-fee-gwei, and --native-token-price must be greater than zero')
process.exit(1)
}
}
if (measuredGasQuote != null && !(measuredGasQuote > 0)) {
console.error('Error: --measured-gas-quote must be greater than zero')
process.exit(1)
}
if (maxPostTradeDeviationBps != null && !(maxPostTradeDeviationBps >= 0)) {
console.error('Error: --max-post-trade-deviation-bps must be non-negative')
process.exit(1)
}
if (!(externalFeeBps >= 0) || !(externalEntryFeeBps >= 0) || !(externalExitFeeBps >= 0)) {
console.error('Error: external fee/slippage bps values must be non-negative')
process.exit(1)
}
if (maxCwBurnFraction != null) {
if (inventoryBase == null) {
console.error('Error: --max-cw-burn-fraction requires --inventory-base')
process.exit(1)
}
if (!(maxCwBurnFraction >= 0 && maxCwBurnFraction <= 1)) {
console.error('Error: --max-cw-burn-fraction must be between 0 and 1')
process.exit(1)
}
}
const deployerAddressForLiveProbe =
process.env.DEPLOYER_ADDRESS ?? '0x4A666F96fC8764181194447A7dFdb7d471b301C8'
const inventoryLoopGuardConfig = buildInventoryLoopGuardConfig({
minRetainedUsdc,
gasTxCount,
gasPerTx,
maxFeeGwei,
nativeTokenPrice,
quoteDecimals,
oraclePrice,
maxPostTradeDeviationBps,
maxCwBurnFraction,
cooldownBlocks,
measuredGasQuote,
measuredGasSource,
estimatedGasQuote: null,
estimatedGasSource: null,
})
if (sequentialMatchedLoops != null) {
if (
fullLoopDryRunMode ||
publicLiveSweepMode ||
fundingReadinessMode ||
inventoryLoopScanMode ||
inventoryLoopRankMode ||
seedMode
) {
console.error('Error: --sequential-matched-loops cannot be combined with other primary modes')
process.exit(1)
}
if (scanAtomicBridgeMax) {
console.error('Error: --scan-atomic-bridge-max is only supported with --full-loop-dry-run')
process.exit(1)
}
if (B == null || Q == null) {
console.error('Error: --sequential-matched-loops requires -B and -Q')
process.exit(1)
}
if (loopStrategy !== 'quote-push') {
console.error('Error: --sequential-matched-loops requires --loop-strategy quote-push')
process.exit(1)
}
if (externalExitPrice == null) {
console.error(
'Error: --sequential-matched-loops (quote-push) requires --external-exit-price or --external-price',
)
process.exit(1)
}
const firstLoopFlash = Math.max(
1,
Math.round((Math.min(B, Q) * matchedFlashNumerator) / matchedFlashDenominator),
)
if (flashTopupQuote > firstLoopFlash) {
console.error('Error: --flash-topup-quote cannot exceed the first-loop modeled flash borrow size')
process.exit(1)
}
if (flashProviderAddress && flashProviderTokenAddress) {
console.error(
'Error: --sequential-matched-loops does not support ERC-3156 flash probes; omit --flash-provider-address/--flash-provider-token-address',
)
process.exit(1)
}
const mainnetPoolContextSeq = loadMainnetPool(baseAsset, quoteAsset)
const livePoolFeeBpsSeq =
mainnetPoolContextSeq?.poolAddress != null
? tryReadPoolFeeBpsViaCast(1, mainnetPoolContextSeq.poolAddress)
: null
const lpFeeSequential = !lpFeeBpsWasExplicit && livePoolFeeBpsSeq != null ? livePoolFeeBpsSeq : lpFeeBps
printSequentialMatchedLadder({
iterations: sequentialMatchedLoops,
startB: B,
startQ: Q,
flashNumerator: matchedFlashNumerator,
flashDenominator: matchedFlashDenominator,
lpFeeBps: lpFeeSequential,
flashFeeBps,
externalExitPrice,
externalExitFeeBps,
externalViaAsset,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig: inventoryLoopGuardConfig,
flashProviderCap,
flashProviderName,
ownedBaseAdd,
flashTopupQuote,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset: atomicDestinationAsset ?? baseAsset,
atomicDestinationDecimals: atomicDestinationDecimals ?? baseDecimals,
atomicCorridorLabel,
})
process.exit(0)
}
if (fundingReadinessMode) {
if (targetQuotePerPool != null && targetTotalQuote != null) {
console.error('Error: use either --target-quote-per-pool or --target-total-quote with --funding-readiness, not both')
process.exit(1)
}
if (targetQuotePerPool == null && targetTotalQuote == null) {
console.error('Error: --funding-readiness requires --target-quote-per-pool or --target-total-quote')
process.exit(1)
}
if (targetQuotePerPool != null && seedPools == null && loopCountOverride == null) {
console.error('Error: --target-quote-per-pool requires --seed-pools or --loop-count with --funding-readiness')
process.exit(1)
}
const totalQuoteTarget =
targetTotalQuote != null ? targetTotalQuote : (seedPools ?? loopCountOverride) * targetQuotePerPool
if (!(totalQuoteTarget > 0)) {
console.error('Error: readiness target quote must be positive')
process.exit(1)
}
const mainnetPool = loadMainnetPool(inventoryAsset, quoteAsset)
if (!mainnetPool) {
console.error(
`Error: could not find a mainnet pool row for ${inventoryAsset}/${quoteAsset} in cross-chain-pmm-lps/config/deployment-status.json`,
)
process.exit(1)
}
const resolvedReserves =
B != null && Q != null
? { baseReserve: B, quoteReserve: Q, source: 'CLI -B/-Q' }
: tryReadPoolReservesViaCast(1, mainnetPool.poolAddress)
if (!resolvedReserves) {
console.error(
'Error: --funding-readiness requires -B/-Q or a reachable Ethereum mainnet RPC to read live pool reserves',
)
process.exit(1)
}
const readinessLpFeeBps = !lpFeeBpsWasExplicit && mainnetPool.feeBps != null ? mainnetPool.feeBps : lpFeeBps
const report = loadBalanceReport(balanceReportPath)
printFundingReadiness({
inventoryAsset,
sourceAsset,
quoteAsset,
totalQuoteTarget,
lpFeeBps: readinessLpFeeBps,
baseReserve: resolvedReserves.baseReserve,
quoteReserve: resolvedReserves.quoteReserve,
reserveSource: resolvedReserves.source,
poolAddress: mainnetPool.poolAddress,
report,
reportPath: balanceReportPath,
})
process.exit(0)
}
if (fullLoopDryRunMode) {
const x = values.trade != null ? parseNum(values.trade) : null
if (B == null || Q == null || x == null) {
console.error('Error: --full-loop-dry-run requires -B, -Q, and -x')
process.exit(1)
}
if (!(x > 0)) {
console.error('Error: -x must be greater than zero for --full-loop-dry-run')
process.exit(1)
}
if (flashTopupQuote > x) {
console.error('Error: --flash-topup-quote cannot exceed the flash borrow size -x')
process.exit(1)
}
if (atomicBridgeBaseAmount > 0 && loopStrategy !== 'quote-push') {
console.error('Error: --atomic-bridge-base-amount is only supported with --loop-strategy quote-push')
process.exit(1)
}
if (scanAtomicBridgeMax && loopStrategy !== 'quote-push') {
console.error('Error: --scan-atomic-bridge-max is only supported with --loop-strategy quote-push')
process.exit(1)
}
if (loopStrategy === 'quote-push' && externalExitPrice == null) {
console.error('Error: quote-push full-loop dry-run requires --external-exit-price or --external-price')
process.exit(1)
}
if (loopStrategy === 'base-unwind' && externalEntryPrice == null) {
console.error('Error: base-unwind full-loop dry-run requires --external-entry-price or --external-price')
process.exit(1)
}
if (flashProviderCap != null && !(flashProviderCap > 0)) {
console.error('Error: --flash-provider-cap must be greater than zero')
process.exit(1)
}
if ((flashProviderAddress == null) !== (flashProviderTokenAddress == null)) {
console.error('Error: --flash-provider-address and --flash-provider-token-address must be provided together')
process.exit(1)
}
if (targetQuotePerPool != null && targetTotalQuote != null) {
console.error('Error: use either --target-quote-per-pool or --target-total-quote with --full-loop-dry-run, not both')
process.exit(1)
}
if (targetQuotePerPool != null && seedPools == null && loopCountOverride == null) {
console.error('Error: --target-quote-per-pool requires --seed-pools or --loop-count with --full-loop-dry-run')
process.exit(1)
}
const probedFlashProvider =
flashProviderAddress && flashProviderTokenAddress
? tryProbeErc3156FlashProvider(flashProviderAddress, flashProviderTokenAddress, x, flashProviderRpcUrl)
: null
const effectiveFlashProviderCap =
probedFlashProvider?.maxFlashLoan != null && flashProviderCap != null
? Math.min(flashProviderCap, probedFlashProvider.maxFlashLoan)
: (probedFlashProvider?.maxFlashLoan ?? flashProviderCap)
const effectiveFlashFeeAmount = probedFlashProvider?.flashFeeAmount ?? null
const effectiveFlashFeeSource =
probedFlashProvider?.source ??
(flashProviderAddress && flashProviderTokenAddress
? `manual flash fee bps (${flashFeeBps}) — probe failed via ${flashProviderAddress}`
: null)
const mainnetPoolContext = loadMainnetPool(baseAsset, quoteAsset)
const livePoolFeeBps =
mainnetPoolContext?.poolAddress != null ? tryReadPoolFeeBpsViaCast(1, mainnetPoolContext.poolAddress) : null
const quoteSurface =
mainnetPoolContext?.poolAddress != null
? tryProbePoolQuoteSurfaceViaCast(
1,
mainnetPoolContext.poolAddress,
deployerAddressForLiveProbe,
)
: null
const estimatedMainnetGasQuote =
measuredGasQuote == null &&
mainnetPoolContext?.poolAddress != null &&
mainnetPoolContext.baseAddress != null &&
mainnetPoolContext.quoteAddress != null
? deriveEstimatedGasQuoteForMainnetStrategy({
strategy: loopStrategy,
poolAddress: mainnetPoolContext.poolAddress,
baseAddress: mainnetPoolContext.baseAddress,
quoteAddress: mainnetPoolContext.quoteAddress,
amountInQuoteRaw: x,
externalEntryPrice,
externalEntryFeeBps,
quoteDecimals,
baseDecimals,
nativeTokenPrice,
fromAddress: deployerAddressForLiveProbe,
})
: null
const fullLoopGuardConfig =
measuredGasQuote == null && estimatedMainnetGasQuote
? buildInventoryLoopGuardConfig({
minRetainedUsdc,
gasTxCount: null,
gasPerTx: null,
maxFeeGwei: null,
nativeTokenPrice,
quoteDecimals,
oraclePrice,
maxPostTradeDeviationBps,
maxCwBurnFraction,
cooldownBlocks,
measuredGasQuote: null,
measuredGasSource: null,
estimatedGasQuote: estimatedMainnetGasQuote.quoteCost,
estimatedGasSource: estimatedMainnetGasQuote.source,
})
: inventoryLoopGuardConfig
printFullLoopDryRun({
B,
Q,
x,
lpFeeBps: livePoolFeeBps ?? lpFeeBps,
flashFeeBps,
loopStrategy,
ownedBaseAdd,
flashTopupQuote,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
quoteAsset,
baseAsset,
quoteDecimals,
baseDecimals,
guardConfig: fullLoopGuardConfig,
flashProviderCap: effectiveFlashProviderCap,
flashProviderName,
flashFeeAmount: effectiveFlashFeeAmount,
flashFeeSource: effectiveFlashFeeSource,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount: loopCountOverride ?? seedPools ?? 1,
quoteSurface,
externalEntrySource,
externalExitSource,
livePoolFeeBps,
executionGradeRequired,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset: atomicDestinationAsset ?? baseAsset,
atomicDestinationDecimals: atomicDestinationDecimals ?? baseDecimals,
atomicCorridorLabel,
scanAtomicBridgeMax,
})
process.exit(0)
}
if (publicLiveSweepMode) {
if (targetQuotePerPool != null && targetTotalQuote != null) {
console.error('Error: use either --target-quote-per-pool or --target-total-quote with --public-live-sweep, not both')
process.exit(1)
}
if (targetQuotePerPool != null && seedPools == null && loopCountOverride == null) {
console.error('Error: --target-quote-per-pool requires --seed-pools or --loop-count with --public-live-sweep')
process.exit(1)
}
if ((loopStrategy === 'quote-push' || loopStrategy === 'both') && externalExitPrice == null) {
console.error('Error: quote-push public live sweep requires --external-exit-price or --external-price')
process.exit(1)
}
if ((loopStrategy === 'base-unwind' || loopStrategy === 'both') && externalEntryPrice == null) {
console.error('Error: base-unwind public live sweep requires --external-entry-price or --external-price')
process.exit(1)
}
if (publicFlashSource === 'manual' && flashProviderCap == null) {
console.error('Error: --public-flash-source manual requires --flash-provider-cap')
process.exit(1)
}
printPublicLiveSweep({
scanStr: values.scan ?? null,
loopStrategy,
ownedBaseAdd,
flashTopupQuote,
flashProviderCap,
flashProviderName,
flashFeeBps,
externalEntryPrice,
externalExitPrice,
externalEntryFeeBps,
externalExitFeeBps,
externalViaAsset,
atomicBridgeBaseAmount,
atomicDestinationAmount,
atomicDestinationAsset: atomicDestinationAsset ?? baseAsset,
atomicDestinationDecimals: atomicDestinationDecimals ?? baseDecimals,
atomicCorridorLabel,
seedPools,
targetQuotePerPool,
targetTotalQuote,
loopCount: loopCountOverride ?? seedPools ?? 1,
guardConfig: inventoryLoopGuardConfig,
publicFlashSource,
externalEntrySource,
externalExitSource,
executionGradeRequired,
})
process.exit(0)
}
if (seedMode) {
if (targetQuotePerPool != null && targetTotalQuote != null) {
console.error('Error: use either --target-quote-per-pool or --target-total-quote, not both')
process.exit(1)
}
if (targetQuotePerPool == null && targetTotalQuote == null) {
console.error('Error: seeding mode requires --target-quote-per-pool or --target-total-quote')
process.exit(1)
}
if (targetQuotePerPool != null && seedPools == null && loopCountOverride == null) {
console.error('Error: --target-quote-per-pool requires --seed-pools or --loop-count')
process.exit(1)
}
const totalQuoteTarget =
targetTotalQuote != null
? targetTotalQuote
: seedPools * targetQuotePerPool
const loopCount = loopCountOverride ?? seedPools ?? 1
if (!(totalQuoteTarget > 0)) {
console.error('Error: total quote target must be positive')
process.exit(1)
}
if (B != null || Q != null) {
if (B == null || Q == null) {
console.error('Error: PMM seeding mode requires both -B and -Q')
process.exit(1)
}
printSeedingPlanFromPmm(
B,
Q,
totalQuoteTarget,
lpFeeBps,
inventoryBase,
loopCount,
seedPools,
targetQuotePerPool,
)
process.exit(0)
}
if (externalPrice == null) {
console.error('Error: seeding mode requires either -B/-Q for PMM source math or --external-price for external monetization')
process.exit(1)
}
printSeedingPlanExternal(
totalQuoteTarget,
externalPrice,
exitFeeBps,
inventoryBase,
loopCount,
seedPools,
targetQuotePerPool,
)
process.exit(0)
}
if (inventoryLoopScanMode) {
if (B == null || Q == null) {
console.error('Error: --inventory-loop-scan requires -B and -Q')
process.exit(1)
}
printInventoryLoopSafetyScan(
B,
Q,
values.scan ?? null,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
inventoryLoopGuardConfig,
flashAddToPool,
)
process.exit(0)
}
if (inventoryLoopRankMode) {
if (B == null || Q == null) {
console.error('Error: --inventory-loop-rank requires -B and -Q')
process.exit(1)
}
printInventoryLoopRanking(
B,
Q,
values.scan ?? null,
lpFeeBps,
flashFeeBps,
inventoryBase,
targetFlashBorrow,
inventoryLoopGuardConfig,
rankProfile,
flashAddToPool,
)
process.exit(0)
}
if (values['mainnet-map']) {
const delta =
values['compare-deepen'] != null ? parseNum(values['compare-deepen']) : null
const m = loadMainnetCwUsdcUsdc()
printMainnetMap(
delta,
B,
Q,
values.scan ?? null,
lpFeeBps,
m?.feeBps ?? null,
!lpFeeBpsWasExplicit,
)
process.exit(0)
}
if (values.scan) {
if (B == null || Q == null) {
console.error('Error: --scan requires -B and -Q')
process.exit(1)
}
const sizes = values.scan.split(',').map((s) => parseNum(s.trim()))
console.log('trade_x\tbase_out\tvwap\trepay\tP_ext*\tPnL@ext')
for (const x of sizes) {
const { baseOut, vwap } = quoteInToBaseOut(B, Q, x, lpFeeBps)
const repay = repayUsdc(x, flashFeeBps)
const pStar = breakEvenExternalPrice(x, baseOut, flashFeeBps, exitFeeBps)
const pi =
externalPrice != null
? profit(x, baseOut, externalPrice, flashFeeBps, exitFeeBps)
: NaN
console.log(
[fmt(x), fmt(baseOut), fmt(vwap), fmt(repay), fmt(pStar), Number.isFinite(pi) ? fmt(pi) : '—'].join(
'\t',
),
)
}
process.exit(0)
}
const x = values.trade != null ? parseNum(values.trade) : null
if (B == null || Q == null || x == null) {
console.error('Error: provide -B, -Q, -x or use --examples')
process.exit(1)
}
printScenario('custom', B, Q, x, lpFeeBps, flashFeeBps, externalPrice, exitFeeBps)
}
main()