chore(sim): refresh deployment status, pool matrix, schemas, and scenario scripts
- deployment-status and pool-matrix snapshots aligned with validate-deployment-status.cjs. - Micro-trade / scorecard docs and run-scenario wiring. Made-with: Cursor
This commit is contained in:
@@ -5,8 +5,9 @@
|
||||
*
|
||||
* Rules:
|
||||
* - If bridgeAvailable === true on a chain, cwTokens must include at least cWUSDT and cWUSDC (phase 1).
|
||||
* - For each pmmPool: role in {defense, public_routing}, feeBps and k present,
|
||||
* base/quote (or tokenIn/tokenOut) exist in cwTokens or anchorAddresses.
|
||||
* - For each pmmPool / pmmPoolsVolatile[]: role in {defense, public_routing, truu_routing},
|
||||
* feeBps and k present, base/quote (or tokenIn/tokenOut) exist in cwTokens or anchorAddresses.
|
||||
* TRUU must be listed under anchorAddresses when used as quote (e.g. mainnet chain 1).
|
||||
*
|
||||
* Exit code: 0 if valid, 1 if invalid (and prints errors to stderr).
|
||||
*/
|
||||
@@ -18,12 +19,41 @@ const CONFIG_DIR = path.join(__dirname, '..', 'config');
|
||||
const DEPLOYMENT_STATUS_PATH = path.join(CONFIG_DIR, 'deployment-status.json');
|
||||
|
||||
const PHASE1_CW = ['cWUSDT', 'cWUSDC'];
|
||||
const VALID_ROLES = ['defense', 'public_routing'];
|
||||
const VALID_ROLES = ['defense', 'public_routing', 'truu_routing'];
|
||||
const VALID_REFERENCE_PROTOCOLS = ['uniswap_v3', 'balancer', 'curve', '1inch'];
|
||||
|
||||
function loadJson(p) {
|
||||
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
||||
}
|
||||
|
||||
function validatePoolEntries(chainId, pools, listLabel, knownTokens, errors) {
|
||||
for (let i = 0; i < pools.length; i++) {
|
||||
const pool = pools[i];
|
||||
const base = pool.base ?? pool.tokenIn;
|
||||
const quote = pool.quote ?? pool.tokenOut;
|
||||
|
||||
if (!VALID_ROLES.includes(pool.role)) {
|
||||
errors.push(`Chain ${chainId} ${listLabel}[${i}]: role must be one of ${VALID_ROLES.join(', ')}`);
|
||||
}
|
||||
if (pool.feeBps == null || pool.k == null) {
|
||||
errors.push(`Chain ${chainId} ${listLabel}[${i}]: feeBps and k required`);
|
||||
}
|
||||
if (base && !knownTokens.has(base)) {
|
||||
errors.push(`Chain ${chainId} ${listLabel}[${i}]: base/tokenIn "${base}" not in cwTokens or anchorAddresses`);
|
||||
}
|
||||
if (quote && !knownTokens.has(quote)) {
|
||||
errors.push(`Chain ${chainId} ${listLabel}[${i}]: quote/tokenOut "${quote}" not in cwTokens or anchorAddresses`);
|
||||
}
|
||||
const addr = pool.poolAddress;
|
||||
if (addr != null && addr !== '') {
|
||||
const z = String(addr).toLowerCase();
|
||||
if (z === '0x0000000000000000000000000000000000000000') {
|
||||
errors.push(`Chain ${chainId} ${listLabel}[${i}]: poolAddress must not be zero when set`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
const status = loadJson(DEPLOYMENT_STATUS_PATH);
|
||||
const chains = status.chains || {};
|
||||
@@ -31,8 +61,13 @@ function main() {
|
||||
|
||||
for (const [chainId, chain] of Object.entries(chains)) {
|
||||
const cwTokens = chain.cwTokens || {};
|
||||
const gasMirrors = chain.gasMirrors || {};
|
||||
const anchorAddresses = chain.anchorAddresses || {};
|
||||
const gasQuoteAddresses = chain.gasQuoteAddresses || {};
|
||||
const pmmPools = chain.pmmPools || [];
|
||||
const pmmPoolsVolatile = chain.pmmPoolsVolatile || [];
|
||||
const gasPmmPools = chain.gasPmmPools || [];
|
||||
const gasReferenceVenues = chain.gasReferenceVenues || [];
|
||||
const bridgeAvailable = chain.bridgeAvailable;
|
||||
|
||||
if (bridgeAvailable === true) {
|
||||
@@ -43,24 +78,63 @@ function main() {
|
||||
}
|
||||
}
|
||||
|
||||
const knownTokens = new Set([...Object.keys(cwTokens), ...Object.keys(anchorAddresses)]);
|
||||
const knownTokens = new Set([
|
||||
...Object.keys(cwTokens),
|
||||
...Object.keys(gasMirrors),
|
||||
...Object.keys(anchorAddresses),
|
||||
...Object.keys(gasQuoteAddresses),
|
||||
]);
|
||||
|
||||
for (let i = 0; i < pmmPools.length; i++) {
|
||||
const pool = pmmPools[i];
|
||||
const base = pool.base ?? pool.tokenIn;
|
||||
const quote = pool.quote ?? pool.tokenOut;
|
||||
validatePoolEntries(chainId, pmmPools, 'pmmPools', knownTokens, errors);
|
||||
validatePoolEntries(chainId, pmmPoolsVolatile, 'pmmPoolsVolatile', knownTokens, errors);
|
||||
validatePoolEntries(chainId, gasPmmPools, 'gasPmmPools', knownTokens, errors);
|
||||
|
||||
if (!VALID_ROLES.includes(pool.role)) {
|
||||
errors.push(`Chain ${chainId} pmmPools[${i}]: role must be one of ${VALID_ROLES.join(', ')}`);
|
||||
const gasPoolsByFamily = new Map();
|
||||
for (const pool of gasPmmPools) {
|
||||
if (!pool.familyKey || typeof pool.familyKey !== 'string') {
|
||||
errors.push(`Chain ${chainId} gasPmmPools entry is missing familyKey`);
|
||||
continue;
|
||||
}
|
||||
if (pool.feeBps == null || pool.k == null) {
|
||||
errors.push(`Chain ${chainId} pmmPools[${i}]: feeBps and k required`);
|
||||
if (!gasPoolsByFamily.has(pool.familyKey)) gasPoolsByFamily.set(pool.familyKey, []);
|
||||
gasPoolsByFamily.get(pool.familyKey).push(pool);
|
||||
}
|
||||
|
||||
for (const [familyKey, pools] of gasPoolsByFamily.entries()) {
|
||||
const poolTypes = new Set(pools.map((pool) => pool.poolType));
|
||||
if (!poolTypes.has('wrapped_native')) {
|
||||
errors.push(`Chain ${chainId} gas family ${familyKey}: missing wrapped_native DODO pool`);
|
||||
}
|
||||
if (base && !knownTokens.has(base)) {
|
||||
errors.push(`Chain ${chainId} pmmPools[${i}]: base/tokenIn "${base}" not in cwTokens or anchorAddresses`);
|
||||
if (!poolTypes.has('stable_quote')) {
|
||||
errors.push(`Chain ${chainId} gas family ${familyKey}: missing stable_quote DODO pool`);
|
||||
}
|
||||
if (quote && !knownTokens.has(quote)) {
|
||||
errors.push(`Chain ${chainId} pmmPools[${i}]: quote/tokenOut "${quote}" not in cwTokens or anchorAddresses`);
|
||||
}
|
||||
|
||||
const referenceVenuesByFamily = new Map();
|
||||
for (let i = 0; i < gasReferenceVenues.length; i++) {
|
||||
const venue = gasReferenceVenues[i];
|
||||
if (!VALID_REFERENCE_PROTOCOLS.includes(venue.protocol)) {
|
||||
errors.push(`Chain ${chainId} gasReferenceVenues[${i}]: protocol must be one of ${VALID_REFERENCE_PROTOCOLS.join(', ')}`);
|
||||
}
|
||||
if (!venue.familyKey || typeof venue.familyKey !== 'string') {
|
||||
errors.push(`Chain ${chainId} gasReferenceVenues[${i}]: familyKey required`);
|
||||
continue;
|
||||
}
|
||||
if (!referenceVenuesByFamily.has(venue.familyKey)) referenceVenuesByFamily.set(venue.familyKey, []);
|
||||
referenceVenuesByFamily.get(venue.familyKey).push(venue);
|
||||
}
|
||||
|
||||
for (const [familyKey, venues] of referenceVenuesByFamily.entries()) {
|
||||
const protocols = new Set(venues.map((venue) => venue.protocol));
|
||||
if (!protocols.has('uniswap_v3')) {
|
||||
errors.push(`Chain ${chainId} gas family ${familyKey}: missing uniswap_v3 reference venue`);
|
||||
}
|
||||
const oneInch = venues.find((venue) => venue.protocol === '1inch');
|
||||
if (oneInch?.routingVisible === true || oneInch?.live === true) {
|
||||
const hasUniswap = venues.some((venue) => venue.protocol === 'uniswap_v3' && venue.live === true);
|
||||
const hasDodo = (gasPoolsByFamily.get(familyKey) || []).some((pool) => pool.publicRoutingEnabled === true);
|
||||
if (!hasUniswap || !hasDodo) {
|
||||
errors.push(`Chain ${chainId} gas family ${familyKey}: 1inch cannot be live/routingVisible before DODO and Uniswap venues are live`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user