2020 * - Uploads reports as artifacts
2121 *
2222 * ============================================================================
23- * VERIFICATION CRITERIA (7 Checks)
23+ * VERIFICATION CRITERIA (8 Checks)
2424 * ============================================================================
2525 *
2626 * 1. STANDARD LISTING
116116 * - Pass: Either side has usd_amount >= $50 at 2% depth
117117 * - Fail: Both sides < $50, or no pool found
118118 *
119+ * 8. CHAIN STATUS
120+ * - Verifies the asset's chain is not marked as "killed"
121+ * - Check: chain_reg.getFileProperty(chainName, 'chain', 'status') !== 'killed'
122+ * - Exemption: Meme tokens (category includes "meme") skip this check
123+ * - Pass: Chain status is "live" or "upcoming" OR asset is a meme token
124+ * - Fail: Chain status is "killed" (unless meme token)
125+ * - Purpose: Prevents verification of assets on killed/deprecated chains
126+ * while allowing historical meme tokens to remain verified
127+ *
119128 * ============================================================================
120129 * ALLOY AUTO-VERIFICATION
121130 * ============================================================================
@@ -521,6 +530,22 @@ function isMemeToken(zoneAsset) {
521530 return hasCategories ( zoneAsset , [ 'meme' ] ) ;
522531}
523532
533+ /**
534+ * Check if a chain is marked as killed in the chain registry
535+ *
536+ * @param {string } chainName - Chain name to check
537+ * @returns {boolean } True if chain is killed, false otherwise
538+ */
539+ function isChainKilled ( chainName ) {
540+ try {
541+ const chainStatus = chain_reg . getFileProperty ( chainName , 'chain' , 'status' ) ;
542+ return chainStatus === 'killed' ;
543+ } catch ( error ) {
544+ // If we can't read the chain status, assume it's not killed
545+ return false ;
546+ }
547+ }
548+
524549//-- Verification Check Functions --
525550
526551/**
@@ -1112,6 +1137,53 @@ async function checkBidDepth(chainName, baseDenom, numiaPairs) {
11121137 }
11131138}
11141139
1140+ /**
1141+ * Check 8: Killed Chain Status
1142+ * Verifies that the asset's chain is not marked as "killed" in the chain registry
1143+ *
1144+ * Assets on killed chains should not be verified, and already-verified assets
1145+ * should be de-verified.
1146+ *
1147+ * Exemption: Meme tokens (category includes "meme") are allowed to remain verified
1148+ * even on killed chains, as they may have historical/cultural value.
1149+ *
1150+ * Per LISTING.md chain status requirement
1151+ *
1152+ * @param {string } chainName - Chain name to check
1153+ * @param {boolean } isMeme - Whether the asset is a meme token
1154+ */
1155+ async function checkChainStatus ( chainName , isMeme ) {
1156+ try {
1157+ // Exemption: Meme tokens can remain verified on killed chains
1158+ if ( isMeme ) {
1159+ return {
1160+ passed : true ,
1161+ details : 'Meme category: exempt from chain status check' ,
1162+ skipped : true
1163+ } ;
1164+ }
1165+
1166+ const chainIsKilled = isChainKilled ( chainName ) ;
1167+
1168+ if ( chainIsKilled ) {
1169+ return {
1170+ passed : false ,
1171+ details : `Chain "${ chainName } " is marked as killed in the chain registry`
1172+ } ;
1173+ }
1174+
1175+ return {
1176+ passed : true ,
1177+ details : 'Chain is active'
1178+ } ;
1179+ } catch ( error ) {
1180+ return {
1181+ passed : true , // Assume chain is active if we can't check
1182+ details : `Could not verify chain status: ${ error . message } `
1183+ } ;
1184+ }
1185+ }
1186+
11151187//-- Main Verification Function --
11161188
11171189/**
@@ -1134,6 +1206,7 @@ async function verifyAsset(zoneAsset, numiaTokens, numiaPairs, alloyMembersMap)
11341206 comment : zoneAsset . _comment || '' ,
11351207 currently_verified : zoneAsset . osmosis_verified || false ,
11361208 is_meme : isMeme ,
1209+ chainIsKilled : isChainKilled ( chain_name ) ,
11371210 checks : { } ,
11381211 alloyInfo : null
11391212 } ;
@@ -1153,6 +1226,7 @@ async function verifyAsset(zoneAsset, numiaTokens, numiaPairs, alloyMembersMap)
11531226 results . checks . logo = await checkLogo ( chain_name , base_denom ) ;
11541227 results . checks . poolLiquidity = await checkPoolLiquidity ( chain_name , base_denom , numiaTokens ) ;
11551228 results . checks . bidDepth = await checkBidDepth ( chain_name , base_denom , numiaPairs ) ;
1229+ results . checks . chainStatus = await checkChainStatus ( chain_name , isMeme ) ;
11561230
11571231 // Determine overall pass/fail
11581232 results . allChecksPassed = Object . values ( results . checks ) . every ( check => check . passed ) ;
@@ -1179,9 +1253,15 @@ function generateMarkdownReport(verificationResults) {
11791253 const alreadyVerified = verificationResults . filter ( r => r . currently_verified ) ;
11801254 const failedChecks = verificationResults . filter ( r => ! r . allChecksPassed && ! r . currently_verified ) ;
11811255
1256+ // Filter killed chain assets (excluding meme tokens)
1257+ const killedChainAssetsVerified = verificationResults . filter ( r => r . chainIsKilled && r . currently_verified && ! r . is_meme ) ;
1258+ const killedChainAssetsUnverified = verificationResults . filter ( r => r . chainIsKilled && ! r . currently_verified && ! r . is_meme ) ;
1259+
11821260 markdown += `## Summary\n\n` ;
11831261 markdown += `- **Ready for Verification**: ${ readyForVerification . length } \n` ;
11841262 markdown += `- **Failed Checks**: ${ failedChecks . length } \n` ;
1263+ markdown += `- **Killed Chain Assets (Verified)**: ${ killedChainAssetsVerified . length } (require de-verification)\n` ;
1264+ markdown += `- **Killed Chain Assets (Unverified)**: ${ killedChainAssetsUnverified . length } (cannot be verified)\n` ;
11851265 markdown += `- **Total Checked**: ${ verificationResults . length } \n\n` ;
11861266
11871267 // Ready for Verification section with asset links
@@ -1423,12 +1503,52 @@ function generateMarkdownReport(verificationResults) {
14231503 } ) ;
14241504 }
14251505
1506+ // Killed Chain Assets Section
1507+ if ( killedChainAssetsVerified . length > 0 || killedChainAssetsUnverified . length > 0 ) {
1508+ markdown += `## ⚠️ Killed Chain Assets Requiring De-verification\n\n` ;
1509+ markdown += `Assets from chains marked as "killed" in the chain registry (excluding meme tokens):\n\n` ;
1510+
1511+ // Currently Verified subsection
1512+ if ( killedChainAssetsVerified . length > 0 ) {
1513+ markdown += `### Currently Verified (${ killedChainAssetsVerified . length } )\n\n` ;
1514+ markdown += `These verified assets belong to killed chains and should be de-verified:\n\n` ;
1515+ markdown += `| Asset | Chain | Base Denom | Comment |\n` ;
1516+ markdown += `|-------|-------|------------|----------|\n` ;
1517+
1518+ killedChainAssetsVerified . forEach ( r => {
1519+ const symbol = r . comment || r . base_denom . substring ( 0 , 40 ) ;
1520+ markdown += `| ${ symbol } | ${ r . chain_name } | \`${ r . base_denom } \` | ${ r . comment || 'N/A' } |\n` ;
1521+ } ) ;
1522+ markdown += '\n' ;
1523+ }
1524+
1525+ // Unverified subsection
1526+ if ( killedChainAssetsUnverified . length > 0 ) {
1527+ markdown += `### Unverified (${ killedChainAssetsUnverified . length } )\n\n` ;
1528+ markdown += `These unverified assets belong to killed chains and cannot be verified:\n\n` ;
1529+ markdown += `| Asset | Chain | Base Denom | Comment |\n` ;
1530+ markdown += `|-------|-------|------------|----------|\n` ;
1531+
1532+ killedChainAssetsUnverified . forEach ( r => {
1533+ const symbol = r . comment || r . base_denom . substring ( 0 , 40 ) ;
1534+ markdown += `| ${ symbol } | ${ r . chain_name } | \`${ r . base_denom } \` | ${ r . comment || 'N/A' } |\n` ;
1535+ } ) ;
1536+ markdown += '\n' ;
1537+ }
1538+
1539+ markdown += `**Note:** Meme tokens are exempt from this requirement and may remain verified on killed chains due to their historical/cultural value.\n\n` ;
1540+ }
1541+
14261542 return markdown ;
14271543}
14281544
14291545function generateJSONReport ( verificationResults ) {
14301546 const failedChecks = verificationResults . filter ( r => ! r . allChecksPassed && ! r . currently_verified ) ;
14311547
1548+ // Filter killed chain assets (excluding meme tokens)
1549+ const killedChainAssetsVerified = verificationResults . filter ( r => r . chainIsKilled && r . currently_verified && ! r . is_meme ) ;
1550+ const killedChainAssetsUnverified = verificationResults . filter ( r => r . chainIsKilled && ! r . currently_verified && ! r . is_meme ) ;
1551+
14321552 // Calculate failure breakdown
14331553 const failureCounts = {
14341554 standardListing : 0 ,
@@ -1437,7 +1557,8 @@ function generateJSONReport(verificationResults) {
14371557 socials : 0 ,
14381558 logo : 0 ,
14391559 poolLiquidity : 0 ,
1440- bidDepth : 0
1560+ bidDepth : 0 ,
1561+ chainStatus : 0
14411562 } ;
14421563
14431564 const socialsFailureReasons = { } ;
@@ -1488,12 +1609,30 @@ function generateJSONReport(verificationResults) {
14881609 readyForVerification : verificationResults . filter ( r => r . readyForVerification ) . length ,
14891610 alreadyVerified : verificationResults . filter ( r => r . currently_verified ) . length ,
14901611 failedChecks : failedChecks . length ,
1612+ killedChainAssetsVerified : killedChainAssetsVerified . length ,
1613+ killedChainAssetsUnverified : killedChainAssetsUnverified . length ,
14911614 totalChecked : verificationResults . length
14921615 } ,
14931616 analysis : {
14941617 failureBreakdown,
14951618 socialsFailureReasons,
1496- highLiquidityFailing
1619+ highLiquidityFailing,
1620+ killedChainAssets : {
1621+ verified : killedChainAssetsVerified . map ( r => ( {
1622+ chain_name : r . chain_name ,
1623+ base_denom : r . base_denom ,
1624+ comment : r . comment ,
1625+ is_meme : r . is_meme ,
1626+ chainIsKilled : r . chainIsKilled
1627+ } ) ) ,
1628+ unverified : killedChainAssetsUnverified . map ( r => ( {
1629+ chain_name : r . chain_name ,
1630+ base_denom : r . base_denom ,
1631+ comment : r . comment ,
1632+ is_meme : r . is_meme ,
1633+ chainIsKilled : r . chainIsKilled
1634+ } ) )
1635+ }
14971636 } ,
14981637 results : verificationResults
14991638 } , null , 2 ) ;
0 commit comments