chore: update .env.master.example with new deployment scripts and treasury manager parameters; enhance AGENTS.md with GRU reference primacy details
- Added new deployment script references for Aave quote-push and treasury manager in .env.master.example. - Updated AGENTS.md to include information on GRU reference primacy versus public PMM mesh execution model. - Minor updates to various documentation files to reflect changes in policy and operational guidelines. Made-with: Cursor
This commit is contained in:
@@ -54,6 +54,7 @@ if $DRY_RUN; then
|
||||
echo " REQUIRED_FILES: ${REQUIRED_FILES:-<default: config/ip-addresses.conf, .env.example, token-mapping*.json, gru-transport-active.json, gru-iso4217-currency-manifest.json, gru-governance-supervision-profile.json>}"
|
||||
echo " OPTIONAL_ENV: ${OPTIONAL_ENV:-<empty; set VALIDATE_OPTIONAL_ENV for Proxmox API vars>}"
|
||||
echo " config/xdc-zero: validate-xdc-zero-config.sh (when config/xdc-zero exists)"
|
||||
echo " GRU reference primacy: scripts/verify/check-gru-reference-primacy-integration.sh (doc links + peg-bands hook)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -126,6 +127,12 @@ function readJson(relativePath) {
|
||||
return JSON.parse(fs.readFileSync(path.join(projectRoot, relativePath), 'utf8'));
|
||||
}
|
||||
|
||||
function readJsonMaybe(relativePath) {
|
||||
const full = path.join(projectRoot, relativePath);
|
||||
if (!fs.existsSync(full)) return null;
|
||||
return JSON.parse(fs.readFileSync(full, 'utf8'));
|
||||
}
|
||||
|
||||
function normalizeAddress(address) {
|
||||
return typeof address === 'string' ? address.trim().toLowerCase() : '';
|
||||
}
|
||||
@@ -144,8 +151,17 @@ function refConfigured(ref) {
|
||||
|
||||
const active = readJson('config/gru-transport-active.json');
|
||||
const multichain = readJson('config/token-mapping-multichain.json');
|
||||
const deployment = readJson('cross-chain-pmm-lps/config/deployment-status.json');
|
||||
const poolMatrix = readJson('cross-chain-pmm-lps/config/pool-matrix.json');
|
||||
const deploymentRel = 'cross-chain-pmm-lps/config/deployment-status.json';
|
||||
const poolMatrixRel = 'cross-chain-pmm-lps/config/pool-matrix.json';
|
||||
const deployment = readJsonMaybe(deploymentRel);
|
||||
const poolMatrix = readJsonMaybe(poolMatrixRel);
|
||||
const hasDeploymentOverlay = deployment !== null && poolMatrix !== null;
|
||||
if (!hasDeploymentOverlay) {
|
||||
console.warn(
|
||||
'[WARN] Missing cross-chain-pmm-lps deployment overlay (one of deployment-status.json / pool-matrix.json). '
|
||||
+ 'Skipping deployment/pool-matrix cross-checks. For full checks: git submodule update --init cross-chain-pmm-lps'
|
||||
);
|
||||
}
|
||||
const currencyManifest = readJson('config/gru-iso4217-currency-manifest.json');
|
||||
const monetaryUnitManifest = readJson('config/gru-monetary-unit-manifest.json');
|
||||
|
||||
@@ -186,7 +202,8 @@ function getMappingToken(fromChainId, toChainId, mappingKey) {
|
||||
}
|
||||
|
||||
function getExpectedPoolKey(chainId, mirroredSymbol) {
|
||||
const chain = poolMatrix.chains?.[String(chainId)];
|
||||
if (!hasDeploymentOverlay || !poolMatrix?.chains) return null;
|
||||
const chain = poolMatrix.chains[String(chainId)];
|
||||
const hubStable = typeof chain?.hubStable === 'string' ? chain.hubStable.trim() : '';
|
||||
if (!hubStable) return null;
|
||||
return `${chainId}-${mirroredSymbol}-${hubStable}`;
|
||||
@@ -279,12 +296,14 @@ for (const pair of active.transportPairs || []) {
|
||||
}
|
||||
}
|
||||
|
||||
const deploymentChain = deployment.chains?.[String(destinationChainId)];
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol] || deploymentChain?.gasMirrors?.[mirroredSymbol];
|
||||
if (!deploymentChain || !isNonZeroAddress(deployedMirror)) {
|
||||
errors.push(`transportPairs[${pair.key}] mapping exists but deployment-status.json has no deployed ${mirroredSymbol} for chain ${destinationChainId}`);
|
||||
} else if (mappingToken && normalizeAddress(deployedMirror) !== normalizeAddress(mappingToken.addressTo)) {
|
||||
errors.push(`transportPairs[${pair.key}] deployment-status.json ${mirroredSymbol} does not match token-mapping-multichain.json addressTo`);
|
||||
if (hasDeploymentOverlay) {
|
||||
const deploymentChain = deployment.chains?.[String(destinationChainId)];
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol] || deploymentChain?.gasMirrors?.[mirroredSymbol];
|
||||
if (!deploymentChain || !isNonZeroAddress(deployedMirror)) {
|
||||
errors.push(`transportPairs[${pair.key}] mapping exists but deployment-status.json has no deployed ${mirroredSymbol} for chain ${destinationChainId}`);
|
||||
} else if (mappingToken && normalizeAddress(deployedMirror) !== normalizeAddress(mappingToken.addressTo)) {
|
||||
errors.push(`transportPairs[${pair.key}] deployment-status.json ${mirroredSymbol} does not match token-mapping-multichain.json addressTo`);
|
||||
}
|
||||
}
|
||||
|
||||
if (pair.assetClass === 'gas_native') {
|
||||
@@ -349,19 +368,21 @@ for (const pool of active.publicPools || []) {
|
||||
errors.push(`publicPools[${pool.key}] is active but has no poolAddress`);
|
||||
continue;
|
||||
}
|
||||
const deploymentChain = deployment.chains?.[String(pool.chainId)];
|
||||
const deployedStable = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : [];
|
||||
const deployedVolatile = Array.isArray(deploymentChain?.pmmPoolsVolatile) ? deploymentChain.pmmPoolsVolatile : [];
|
||||
const deployedGas = Array.isArray(deploymentChain?.gasPmmPools) ? deploymentChain.gasPmmPools : [];
|
||||
const deploymentMatch = [...deployedStable, ...deployedVolatile].some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const gasDeploymentMatch = deployedGas.some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const stagedPlaceholder = String(pool.phase || '').toLowerCase().includes('staged');
|
||||
if (!deploymentMatch && !gasDeploymentMatch && !stagedPlaceholder) {
|
||||
errors.push(`publicPools[${pool.key}] is active but deployment-status.json does not contain its poolAddress`);
|
||||
if (hasDeploymentOverlay) {
|
||||
const deploymentChain = deployment.chains?.[String(pool.chainId)];
|
||||
const deployedStable = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : [];
|
||||
const deployedVolatile = Array.isArray(deploymentChain?.pmmPoolsVolatile) ? deploymentChain.pmmPoolsVolatile : [];
|
||||
const deployedGas = Array.isArray(deploymentChain?.gasPmmPools) ? deploymentChain.gasPmmPools : [];
|
||||
const deploymentMatch = [...deployedStable, ...deployedVolatile].some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const gasDeploymentMatch = deployedGas.some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const stagedPlaceholder = String(pool.phase || '').toLowerCase().includes('staged');
|
||||
if (!deploymentMatch && !gasDeploymentMatch && !stagedPlaceholder) {
|
||||
errors.push(`publicPools[${pool.key}] is active but deployment-status.json does not contain its poolAddress`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,59 +444,61 @@ for (const exposure of active.gasProtocolExposure || []) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains || {})) {
|
||||
const destinationChainId = Number(chainIdKey);
|
||||
if (destinationChainId === canonicalChainId) continue;
|
||||
if (deploymentChain?.bridgeAvailable !== true) continue;
|
||||
if (hasDeploymentOverlay) {
|
||||
for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains || {})) {
|
||||
const destinationChainId = Number(chainIdKey);
|
||||
if (destinationChainId === canonicalChainId) continue;
|
||||
if (deploymentChain?.bridgeAvailable !== true) continue;
|
||||
|
||||
const mappingPair = getMappingPair(canonicalChainId, destinationChainId);
|
||||
if (!mappingPair) continue;
|
||||
const mappingPair = getMappingPair(canonicalChainId, destinationChainId);
|
||||
if (!mappingPair) continue;
|
||||
|
||||
let compatible = true;
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const mappingKey = String(token.mappingKey || '');
|
||||
const mirroredSymbol = String(token.mirroredSymbol || '');
|
||||
const mappingToken = mappingKey ? (mappingPair.tokens || []).find((entry) => entry.key === mappingKey) : null;
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol];
|
||||
const expectedPoolKey = getExpectedPoolKey(destinationChainId, mirroredSymbol);
|
||||
let compatible = true;
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const mappingKey = String(token.mappingKey || '');
|
||||
const mirroredSymbol = String(token.mirroredSymbol || '');
|
||||
const mappingToken = mappingKey ? (mappingPair.tokens || []).find((entry) => entry.key === mappingKey) : null;
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol];
|
||||
const expectedPoolKey = getExpectedPoolKey(destinationChainId, mirroredSymbol);
|
||||
|
||||
if (
|
||||
!mappingKey ||
|
||||
!mappingToken ||
|
||||
!isNonZeroAddress(mappingToken.addressTo) ||
|
||||
!isNonZeroAddress(deployedMirror) ||
|
||||
normalizeAddress(mappingToken.addressTo) !== normalizeAddress(deployedMirror) ||
|
||||
!expectedPoolKey
|
||||
) {
|
||||
compatible = false;
|
||||
break;
|
||||
if (
|
||||
!mappingKey ||
|
||||
!mappingToken ||
|
||||
!isNonZeroAddress(mappingToken.addressTo) ||
|
||||
!isNonZeroAddress(deployedMirror) ||
|
||||
normalizeAddress(mappingToken.addressTo) !== normalizeAddress(deployedMirror) ||
|
||||
!expectedPoolKey
|
||||
) {
|
||||
compatible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!compatible) continue;
|
||||
if (!compatible) continue;
|
||||
|
||||
const enabledChain = enabledChainsArray.find((chain) => Number(chain.chainId) === destinationChainId);
|
||||
if (!enabledChain) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} (${deploymentChain?.name || 'unknown'}) is missing from enabledDestinationChains`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const expectedPairKey = `${canonicalChainId}-${destinationChainId}-${token.symbol}-${token.mirroredSymbol}`;
|
||||
const expectedPoolKey = getExpectedPoolKey(destinationChainId, String(token.mirroredSymbol || ''));
|
||||
const pair = transportPairsByKey.get(expectedPairKey);
|
||||
|
||||
if (!pair) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} is missing transport pair ${expectedPairKey}`);
|
||||
const enabledChain = enabledChainsArray.find((chain) => Number(chain.chainId) === destinationChainId);
|
||||
if (!enabledChain) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} (${deploymentChain?.name || 'unknown'}) is missing from enabledDestinationChains`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expectedPoolKey && !publicPoolsByKey.has(expectedPoolKey)) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} is missing public pool placeholder ${expectedPoolKey}`);
|
||||
}
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const expectedPairKey = `${canonicalChainId}-${destinationChainId}-${token.symbol}-${token.mirroredSymbol}`;
|
||||
const expectedPoolKey = getExpectedPoolKey(destinationChainId, String(token.mirroredSymbol || ''));
|
||||
const pair = transportPairsByKey.get(expectedPairKey);
|
||||
|
||||
if (expectedPoolKey && !(pair.publicPoolKeys || []).includes(expectedPoolKey)) {
|
||||
errors.push(`transportPairs[${pair.key}] must include the pool-matrix first-hop key ${expectedPoolKey}`);
|
||||
if (!pair) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} is missing transport pair ${expectedPairKey}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expectedPoolKey && !publicPoolsByKey.has(expectedPoolKey)) {
|
||||
errors.push(`compatible destination chain ${destinationChainId} is missing public pool placeholder ${expectedPoolKey}`);
|
||||
}
|
||||
|
||||
if (expectedPoolKey && !(pair.publicPoolKeys || []).includes(expectedPoolKey)) {
|
||||
errors.push(`transportPairs[${pair.key}] must include the pool-matrix first-hop key ${expectedPoolKey}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -791,6 +814,15 @@ if command -v python3 &>/dev/null; then
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -f "$PROJECT_ROOT/scripts/verify/check-gru-reference-primacy-integration.sh" ]]; then
|
||||
if bash "$PROJECT_ROOT/scripts/verify/check-gru-reference-primacy-integration.sh"; then
|
||||
log_ok "GRU reference primacy (doc links + peg-bands gruPolicyIntegration when submodule present)"
|
||||
else
|
||||
log_err "GRU reference primacy integration check failed (see scripts/verify/check-gru-reference-primacy-integration.sh)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
log_err "Validation failed with $ERRORS error(s). Set VALIDATE_REQUIRED_FILES='path1 path2' to require specific files."
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user