Compare commits

..

1 Commits

Author SHA1 Message Date
defiQUG
ea29ca7309 Refresh canonical token lists 2026-04-16 11:49:25 -07:00
24 changed files with 763 additions and 3464 deletions

View File

@@ -59,32 +59,6 @@ pct exec 5000 -- bash -c 'cd /opt/blockscout && docker-compose up -d blockscout'
---
## Fix: Smart-Contract Verifier Sidecar Missing
**Symptom:** verification endpoints exist and submissions appear accepted, but deployed contracts remain `bytecode-only` and never promote into full source metadata.
**Root cause:** CT `5000` is running only `blockscout` and `postgres`, without the upstream `smart-contract-verifier` sidecar and without the required verifier wiring env:
- `MICROSERVICE_SC_VERIFIER_ENABLED=true`
- `MICROSERVICE_SC_VERIFIER_TYPE=sc_verifier`
- `MICROSERVICE_SC_VERIFIER_URL=http://smart-contract-verifier:8050/`
**Recommended fix:**
```bash
bash scripts/deployment/ensure-blockscout-smart-contract-verifier-5000.sh --dry-run
bash scripts/deployment/ensure-blockscout-smart-contract-verifier-5000.sh --apply
```
The script:
1. Backs up `/opt/blockscout/docker-compose.yml`
2. Adds the upstream `smart-contract-verifier` sidecar
3. Wires Blockscout to the sidecar with `MICROSERVICE_SC_VERIFIER_*`
4. Restarts the stack cleanly
5. Verifies `/api/v2/smart-contracts/verification/config`
---
## Fix: Migrate VM 5000 to thin5 (has free space)
**Run on Proxmox host r630-02 (192.168.11.12):**
@@ -135,8 +109,6 @@ source smom-dbis-138/.env 2>/dev/null
./scripts/verify/run-contract-verification-with-proxy.sh
```
**Important:** native `Uniswap v2` / `SushiSwap` verification should pin the exact historical compiler version. The repo submitter now does that explicitly so Forge defaults do not silently downgrade the verification attempt.
---
## Forge Verification Compatibility

View File

@@ -1,18 +1,34 @@
# Token Lists E2E Verification Report
**Date:** 2026-02-28
**Status:** Verification complete
**Date:** 2026-04-14
**Status:** Repo validation current; live E2E still depends on explorer VM / NPM
---
## 1. Token List Validation
## 1. Token List Validation (repo)
| List | Status | Tokens | Notes |
|------|--------|--------|-------|
| dbis-138.tokenlist.json | ✅ Valid | 6 | All IPFS logos, EIP-55 checksummed |
| cronos.tokenlist.json | ✅ Valid | 10 | All IPFS logos, ISO-4217 W tokens |
| all-mainnet.tokenlist.json | ✅ Valid | 9 | All 9 tokens have logoURI (IPFS) |
| DUAL_CHAIN_TOKEN_LIST | ✅ Valid | 22 | Chains 138, 1, 25, 651940 |
|------|--------|--------|------|
| `token-lists/lists/dbis-138.tokenlist.json` | ✅ Schema + checksums + logos + on-chain verify | **29** | Uniswap Token Lists schema; EIP-55; `verify-on-chain.js` against public Chain 138 RPC |
| `token-lists/lists/cronos.tokenlist.json` | ✅ `validate-token-list.js` | **11** | Tag **`gasnative`** (schema-safe) |
| `token-lists/lists/avalanche.tokenlist.json` | ✅ | **3** | |
| `token-lists/lists/arbitrum.tokenlist.json` | | **3** | |
| `token-lists/lists/ethereum-mainnet.tokenlist.json` | ✅ | **17** | |
| `token-lists/lists/all-mainnet.tokenlist.json` | ✅ | **9** | |
| `explorer-monorepo/.../DUAL_CHAIN_TOKEN_LIST.tokenlist.json` (canonical) | Not run in CI as strict Uniswap schema | **190** | Same bytes: `backend/config/metamask/`, `backend/api/rest/config/metamask/`, `metamask-integration/provider/config/` |
| `docs/04-configuration/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` | Mirror | **190** | **Synced from** explorer `backend/config/metamask/` copy (this commit) |
Run locally:
```bash
cd token-lists
for f in lists/dbis-138.tokenlist.json lists/cronos.tokenlist.json lists/avalanche.tokenlist.json lists/arbitrum.tokenlist.json lists/ethereum-mainnet.tokenlist.json lists/all-mainnet.tokenlist.json; do
node scripts/validate-token-list.js "$f" || exit 1
done
node scripts/checksum-addresses.js lists/dbis-138.tokenlist.json
node scripts/validate-logos.js lists/dbis-138.tokenlist.json
node scripts/verify-on-chain.js lists/dbis-138.tokenlist.json
```
---
@@ -20,17 +36,15 @@
| Check | Result |
|-------|--------|
| Chain 138 addresses (dbis-138 vs DUAL_CHAIN) | ✅ Consistent |
| Cronos addresses (cronos vs DUAL_CHAIN) | ✅ Consistent |
| DUAL_CHAIN synced to backend/config, docs, metamask | ✅ Done |
| Chain 138 addresses (`dbis-138` vs `DUAL_CHAIN` 138 subset) | ✅ Align with [EXPLORER_TOKEN_LIST_CROSSCHECK.md](../11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md) §5 |
| `docs/.../metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` | ✅ Byte-synced to explorer canonical path |
---
## 3. IPFS Manifest
## 3. IPFS manifest / logos
- **addressToUrl:** 14 of 22 DUAL_CHAIN addresses covered
- **Missing:** Chain 1 (USDT, USDC, DAI, ETH-USD, WETH) and Chain 651940 USDC, Cronos WETH9/LINK — these use external logo URLs in token lists (TrustWallet, ethereum.org)
- **Our tokens (138, 25):** All covered
- **dbis-138:** Mix of HTTPS (explorer icons, TrustWallet) and IPFS `logoURI` where applicable; `validate-logos.js` passes.
- **DUAL_CHAIN:** Large multichain list; logo coverage varies by chain (external URLs on mainnet staples are normal).
---
@@ -38,57 +52,46 @@
| Check | Result |
|-------|--------|
| Public URL | ❌ Returns 400 (Blockscout error) |
| Cause | Nginx config not yet applied on VMID 5000 |
| Fix | Run on Proxmox host: |
| | 1. `fix-nginx-conflicts-vmid5000.sh` (inside VMID 5000) |
| | 2. `deploy-explorer-config-to-vmid5000.sh` (from repo root, with pct or EXEC_MODE=ssh) |
| **Source of truth in repo** | `explorer-monorepo/backend/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` |
| **Public URL** | **2026-04-14:** Live probe returned **190** tokens from `https://explorer.d-bis.org/api/config/token-list`. If you see **400**, fix nginx/deploy per explorer runbooks (VMID **5000** or current explorer CT). |
---
## 5. Deploy Script
## 5. Deploy script
| Check | Result |
|-------|--------|
| Config source path | ✅ Correct |
| pct mode | Requires Proxmox host |
| ssh mode | `EXEC_MODE=ssh EXPLORER_IP=192.168.11.140 ./explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh` |
| Config source path | ✅ `explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh` (paths may vary by deployment) |
| `pct` / `ssh` | Operator LAN; see explorer deployment docs |
---
## 6. Nginx Location Order
## 6. Nginx location order (reference)
```
location = /api/config/token-list # Exact match (highest priority)
location = /api/config/networks
location /api/v1/ # Token-aggregation
location /api/ # Blockscout (fallback)
```
✅ Correct — `/api/config/*` takes precedence over `/api/`
Exact-match `/api/config/token-list` should win over generic `/api/` Blockscout proxy. Confirm on live nginx for the explorer host.
---
## 7. Frontend tokenIcons.ts
## 7. Frontend `tokenIcons.ts`
- Chain 138: 6 addresses ✅
- Cronos WETH9, LINK, ISO-4217 W tokens: 9 addresses ✅
Reconcile icon map counts with **§5** + DUAL 138 entries whenever tokens change (see explorer frontend paths).
---
## 8. E2E Checklist (Operator)
## 8. E2E checklist (operator)
To achieve full E2E:
1. [ ] SSH to Proxmox host (or VMID 5000)
2. [ ] Run `fix-nginx-conflicts-vmid5000.sh` inside VMID 5000
3. [ ] Run `deploy-explorer-config-to-vmid5000.sh` from repo root (pct or ssh)
4. [ ] Verify: `curl -s https://explorer.d-bis.org/api/config/token-list | jq '.tokens | length'` → 22
5. [ ] Verify: `curl -s https://explorer.d-bis.org/api/config/networks | jq '.chains | length'` → 4
1. [ ] Deploy/sync explorer config when you change **`explorer-monorepo/.../DUAL_CHAIN_TOKEN_LIST.tokenlist.json`** (so live matches git).
2. [x] **2026-04-14:** `curl -sS 'https://explorer.d-bis.org/api/config/token-list' | jq '.tokens | length'`**190** (live matches current canonical DUAL size).
3. [ ] Optional: publish **`token-lists/lists/dbis-138.tokenlist.json`** to public list URL (O-5) and refresh **minisign** signature if your release process signs lists (`token-lists/scripts/sign-list.sh`; requires private key / CI secret).
---
## 9. Completed Improvements
## 9. Release signing (dbis-138)
- ✅ all-mainnet: logoURI added for HYDX, HYBX, CHT, AUDA
- ✅ tokenIcons.ts: Cronos WETH9, LINK added to TOKEN_ICON_BY_ADDRESS
- **`dbis-138.tokenlist.json.sig`** is not committed by default; generate with `bash token-lists/scripts/sign-list.sh sign` when **`MINISIGN_PRIVATE_KEY`** or **`minisign.key`** is available (see `release.yml`).
---
## 10. Historical note
Older completion markdown under `token-lists/` may cite legacy token counts; canonical inventory is **`EXPLORER_TOKEN_LIST_CROSSCHECK.md` §5** and **`lists/dbis-138.tokenlist.json`**.

View File

@@ -3,9 +3,9 @@
"version": {
"major": 1,
"minor": 3,
"patch": 5
"patch": 4
},
"timestamp": "2026-04-05T23:30:00.000Z",
"timestamp": "2026-04-04T04:23:46.263Z",
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/chain138-list.svg",
"keywords": [
"chain138",
@@ -46,10 +46,6 @@
"iso4217w": {
"name": "ISO4217W",
"description": "ISO 4217 compliant wrapped fiat tokens"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
}
},
"extensions": {
@@ -2564,510 +2560,6 @@
"defi",
"bridge"
]
},
{
"chainId": 138,
"address": "0xf8e9802a1766422e33a269556ad5fc032338eefc",
"name": "Ethereum Mainnet Gas (Compliant)",
"symbol": "cETH",
"familyKey": "eth_mainnet",
"mirroredSymbol": "cWETH",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_mainnet",
"mirroredSymbol": "cWETH",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x18a6b163d255cc0cb32b99697843b487d059907d",
"name": "Ethereum L2 Gas (Compliant)",
"symbol": "cETHL2",
"familyKey": "eth_l2",
"mirroredSymbol": "cWETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_l2",
"mirroredSymbol": "cWETHL2",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x94517875f32680984a5921da7abf78e22f65d70f",
"name": "BNB Gas (Compliant)",
"symbol": "cBNB",
"familyKey": "bnb",
"mirroredSymbol": "cWBNB",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "bnb",
"mirroredSymbol": "cWBNB",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x19fec21edede9edb91d1fbec7c4095c5ac1fc10c",
"name": "Polygon Gas (Compliant)",
"symbol": "cPOL",
"familyKey": "pol",
"mirroredSymbol": "cWPOL",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "pol",
"mirroredSymbol": "cWPOL",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x9c8f6f4fe1e535e6f85a78ee95249ded5540a2d0",
"name": "Avalanche Gas (Compliant)",
"symbol": "cAVAX",
"familyKey": "avax",
"mirroredSymbol": "cWAVAX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "avax",
"mirroredSymbol": "cWAVAX",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0xfb48bb6c623571f9795b535b73f0d660e8643fd4",
"name": "Cronos Gas (Compliant)",
"symbol": "cCRO",
"familyKey": "cro",
"mirroredSymbol": "cWCRO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "cro",
"mirroredSymbol": "cWCRO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0xa39a59138f8a45b4a31455875b8a29ff31e76ec8",
"name": "Gnosis Gas (Compliant)",
"symbol": "cXDAI",
"familyKey": "xdai",
"mirroredSymbol": "cWXDAI",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/xdai/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "xdai",
"mirroredSymbol": "cWXDAI",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x1814661dae0933bf397b1274f5a62411b94195c7",
"name": "Celo Gas (Compliant)",
"symbol": "cCELO",
"familyKey": "celo",
"mirroredSymbol": "cWCELO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/celo/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "celo",
"mirroredSymbol": "cWCELO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x4d82206bec5b4dfa17759ffede07e35f4f63a050",
"name": "Wemix Gas (Compliant)",
"symbol": "cWEMIX",
"familyKey": "wemix",
"mirroredSymbol": "cWWEMIX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/wemix/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "wemix",
"mirroredSymbol": "cWWEMIX",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 1,
"address": "0xf6dc5587e18f27adff60e303fdd98f35b50fa8a5",
"name": "Wrapped Ethereum Mainnet Gas (Compliant)",
"symbol": "cWETH",
"familyKey": "eth_mainnet",
"canonicalSymbol": "cETH",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_mainnet",
"canonicalSymbol": "cETH",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 10,
"address": "0x95007ec50d0766162f77848edf7bdc4eba147fb4",
"name": "Wrapped Ethereum L2 Gas (Compliant)",
"symbol": "cWETHL2",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 25,
"address": "0x9b10eb0f77c45322dbd1fcb07176fd9a7609c164",
"name": "Wrapped CRO Gas (Compliant)",
"symbol": "cWCRO",
"familyKey": "cro",
"canonicalSymbol": "cCRO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "cro",
"canonicalSymbol": "cCRO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 56,
"address": "0x179034a08ac2c9c35d2e41239f68c79dca6f18fa",
"name": "Wrapped BNB Gas (Compliant)",
"symbol": "cWBNB",
"familyKey": "bnb",
"canonicalSymbol": "cBNB",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "bnb",
"canonicalSymbol": "cBNB",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 100,
"address": "0x9f833b4f1012f52eb3317b09922a79c6edfca77d",
"name": "Wrapped XDAI Gas (Compliant)",
"symbol": "cWXDAI",
"familyKey": "xdai",
"canonicalSymbol": "cXDAI",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/xdai/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "xdai",
"canonicalSymbol": "cXDAI",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 137,
"address": "0x25980244aacecb6d8c4b887261ed27f87cb2fc73",
"name": "Wrapped POL Gas (Compliant)",
"symbol": "cWPOL",
"familyKey": "pol",
"canonicalSymbol": "cPOL",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "pol",
"canonicalSymbol": "cPOL",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 42161,
"address": "0xe27be001bc55cb2a8ed5ba5a62c834ca135244a3",
"name": "Wrapped Ethereum L2 Gas (Compliant)",
"symbol": "cWETHL2",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 42220,
"address": "0xb0fa7ec4123c7c275b3a89d9239569707ea3c66a",
"name": "Wrapped CELO Gas (Compliant)",
"symbol": "cWCELO",
"familyKey": "celo",
"canonicalSymbol": "cCELO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/celo/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "celo",
"canonicalSymbol": "cCELO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 43114,
"address": "0xe1d4aee2ef8f48a20338935188a8fe7f7c7de7d0",
"name": "Wrapped AVAX Gas (Compliant)",
"symbol": "cWAVAX",
"familyKey": "avax",
"canonicalSymbol": "cAVAX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "avax",
"canonicalSymbol": "cAVAX",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 8453,
"address": "0x2a0840e5117683b11682ac46f5cf5621e67269e3",
"name": "Wrapped Ethereum L2 Gas (Compliant)",
"symbol": "cWETHL2",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"canonicalChainId": 138,
"wave": "wave1"
}
}
]
}

View File

@@ -1,6 +1,6 @@
# Contract Verification And Publication Matrix (All Networks)
**Generated:** 2026-04-16T19:20:09.634Z
**Generated:** 2026-04-11T21:10:30.092Z
**Authoritative sources:** `config/smart-contracts-master.json`, `cross-chain-pmm-lps/config/deployment-status.json`
This matrix is the canonical repo-level inventory for **what still needs explorer verification and publication coverage across every network currently tracked in the workspace**.
@@ -15,18 +15,18 @@ This matrix is the canonical repo-level inventory for **what still needs explore
| Chain ID | Chain | Total Entries | Canonical Contracts | cW / Gas Mirrors | PMM Pools | Explorer |
| --- | --- | ---: | ---: | ---: | ---: | --- |
| 1 | Ethereum Mainnet | 40 | 3 | 14 | 17 | https://etherscan.io |
| 10 | Optimism | 31 | 0 | 14 | 12 | https://optimistic.etherscan.io |
| 25 | Cronos | 29 | 0 | 14 | 12 | https://cronoscan.com |
| 56 | BSC | 28 | 0 | 16 | 10 | https://bscscan.com |
| 100 | Gnosis | 28 | 0 | 14 | 10 | https://gnosisscan.io |
| 137 | Polygon | 32 | 0 | 15 | 12 | https://polygonscan.com |
| 1 | Ethereum Mainnet | 36 | 3 | 14 | 13 | https://etherscan.io |
| 10 | Optimism | 21 | 0 | 14 | 2 | https://optimistic.etherscan.io |
| 25 | Cronos | 19 | 0 | 14 | 2 | https://cronoscan.com |
| 56 | BSC | 18 | 0 | 16 | 0 | https://bscscan.com |
| 100 | Gnosis | 18 | 0 | 14 | 0 | https://gnosisscan.io |
| 137 | Polygon | 22 | 0 | 15 | 2 | https://polygonscan.com |
| 138 | Chain 138 | 115 | 115 | 0 | 0 | https://blockscout.defi-oracle.io |
| 1111 | Wemix | 4 | 0 | 2 | 0 | https://explorer.wemix.com |
| 8453 | Base | 29 | 0 | 14 | 10 | https://basescan.org |
| 42161 | Arbitrum | 29 | 0 | 14 | 10 | https://arbiscan.io |
| 42220 | Celo | 29 | 0 | 16 | 10 | https://celoscan.io |
| 43114 | Avalanche | 29 | 0 | 16 | 10 | https://snowtrace.io |
| 8453 | Base | 19 | 0 | 14 | 0 | https://basescan.org |
| 42161 | Arbitrum | 19 | 0 | 14 | 0 | https://arbiscan.io |
| 42220 | Celo | 19 | 0 | 16 | 0 | https://celoscan.io |
| 43114 | Avalanche | 19 | 0 | 16 | 0 | https://snowtrace.io |
## Required operator path
@@ -71,17 +71,13 @@ The JSON report in `reports/status/contract_verification_publish_matrix.json` co
| 1 | Ethereum Mainnet | pmm_pool | cWCADC/USDC | `0xE0F35b5736FDd0a2F4B618621b0A08F8D8A3f92A` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWCHFC/USDC | `0x776Ca556deD3245984F504F4bef8Eeec55C50190` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWEURC/USDC | `0x0bC750F9c6DbDcd76B205695A356491b1B9ef098` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWEURT/USDC | `0x9cF3DeDAaC0984c530801b9b4881c8f99Bb329c3` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWGBPC/USDC | `0x5488042dF882893a3e7074453E2005CaDE4101b0` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWGBPT/USDC | `0xA42566bb730AD6D551Db32d50c0877132fc07c32` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWJPYC/USDC | `0x8A4187dF0A8FE855cC53A4F7B2D8346588Ee9794` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWUSDC/USDC | `0x69776fc607e9edA8042e320e7e43f54d06c68f0E` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWUSDC/USDT | `0xCC0fd27A40775c9AfcD2BBd3f7c902b0192c247A` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWUSDT/cWUSDC | `0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWUSDT/USDC | `0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWUSDT/USDT | `0x79156F6B7bf71a1B72D78189B540A89A6C13F6FC` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWXAUC/USDC | `0xf6470219ce7749f8860dEABe9c347Ef2c1075E08` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool | cWXAUT/USDC | `0x1D51a38C924382287d770AbB61deb9C39ACa96E9` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool_volatile | cWUSDC/TRUU | `0x9A632F35078b6A4A9bf27806Bb7aFfAA2F16C846` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | pmm_pool_volatile | cWUSDT/TRUU | `0x508E5e80B66204b8CD9869323Fdd3A289ea50993` | etherscan | inventory-only | https://etherscan.io | pending | pending |
| 1 | Ethereum Mainnet | reference_venue | balancer:cWETH/USDC | `0xba11000000000000000000000000000000000001` | etherscan | inventory-only | https://etherscan.io | pending | pending |
@@ -103,18 +99,8 @@ The JSON report in `reports/status/contract_verification_publish_matrix.json` co
| 10 | Optimism | cw_token | cWXAUC | `0xddc4063f770f7c49d00b5a10fb552e922aa39b2c` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | cw_token | cWXAUT | `0x145e8e8c49b6a021969dd9d2c01c8fea44374f61` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | gas_mirror | cWETHL2 | `0x95007ec50d0766162f77848edf7bdc4eba147fb4` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWAUDC/USDC | `0x4B452800f6cD50326F14a6f089f4bB04e8079250` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWCADC/USDC | `0x19e1fdd037F1651AcEE11c5A5Aa246b85FA63f8e` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWCHFC/USDC | `0xA97D7dfB93CBf0C10243931d93FFEda745222ec6` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWEURC/USDC | `0x78C6aC6D7CbFcd85A3291D656F2154979a92c00B` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWEURT/USDC | `0x631DfC86A03cB05319d7165198f8099dacF78e56` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWGBPC/USDC | `0x79BE2b70A94E954d095f9F537FAf0741D15dfA31` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWGBPT/USDC | `0x5D6b5d7CA165c39c350083255774DdBf1c858e12` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWJPYC/USDC | `0x68C1c8a945ddCF3482b73aC09b6B5D4177D564AF` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWUSDC/USDC | `0x8F1038dE06d799a30D16d8B0b0ADEe629e7d4547` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWUSDT/USDT | `0xFCB0b0Ac36d67EDBA91100c75C27De945357CD62` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWXAUC/USDC | `0xCE25c324e41049D75abfB81c23257984A2A97a79` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | pmm_pool | cWXAUT/USDC | `0xb3Ee650019d7F756ce0F79b69614Fa2761871775` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | reference_venue | balancer:cWETHL2/USDC | `0xba2100000000000000000000000000000000000a` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | reference_venue | curve:cWETHL2/USDC | `0xc72100000000000000000000000000000000000a` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
| 10 | Optimism | reference_venue | uniswap_v3:cWETHL2/WETH | `0x712100000000000000000000000000000000000a` | etherscan-family | inventory-only | https://optimistic.etherscan.io | pending | pending |
@@ -127,6 +113,20 @@ The JSON report in `reports/status/contract_verification_publish_matrix.json` co
| 25 | Cronos | cw_token | cWEURC | `0x7574d37F42528B47c88962931e48FC61608a4050` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWEURT | `0x9f833b4f1012F52eb3317b09922a79c6EdFca77D` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWGBPC | `0xe5c65A76A541368d3061fe9E7A2140cABB903dbF` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWGBPT | `0xBb58fa16bAc8E789f09C14243adEE6480D8213A2` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWJPYC | `0x52aD62B8bD01154e2A4E067F8Dc4144C9988d203` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWUSDC | `0x932566E5bB6BEBF6B035B94f3DE1f75f126304Ec` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWUSDT | `0x72948a7a813B60b37Cd0c920C4657DbFF54312b8` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWXAUC | `0xf1B771c95573113E993374c0c7cB2dc1a7908B12` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | cw_token | cWXAUT | `0xD517C0cF7013f988946A468c880Cc9F8e2A4BCbE` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | gas_mirror | cWCRO | `0x9b10eb0f77c45322dbd1fcb07176fd9a7609c164` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | pmm_pool | cWUSDC/USDC | `0x8F1038dE06d799a30D16d8B0b0ADEe629e7d4547` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | pmm_pool | cWUSDT/USDT | `0xFCB0b0Ac36d67EDBA91100c75C27De945357CD62` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 25 | Cronos | reference_venue | uniswap_v3:cWCRO/WCRO | `0x7161000000000000000000000000000000000019` | etherscan-family | inventory-only | https://cronoscan.com | pending | pending |
| 56 | BSC | anchor_token | USDT | `0x55d398326f99059fF775485246999027B3197955` | etherscan-family | reference-only | https://bscscan.com | pending | pending |
| 56 | BSC | cw_token | cWAUDC | `0x7062f35567BBAb4d98dc33af03B0d14Df42294D5` | etherscan-family | inventory-only | https://bscscan.com | pending | pending |
| 56 | BSC | cw_token | cWAUSDT | `0xe1a51Bc037a79AB36767561B147eb41780124934` | etherscan-family | inventory-only | https://bscscan.com | pending | pending |
| 56 | BSC | cw_token | cWBTC | `0xcb7c000000000000000000000000000000000038` | etherscan-family | inventory-only | https://bscscan.com | pending | pending |
## Notes

View File

@@ -1,6 +1,6 @@
# Explorer Token List Cross-Check
**Last Updated:** 2026-04-14
**Last Updated:** 2026-04-02
**Purpose:** Cross-check the token list shown at [https://explorer.d-bis.org/tokens](https://explorer.d-bis.org/tokens) against repo token lists, canonical addresses, and CONTRACT_ADDRESSES_REFERENCE.
---
@@ -89,7 +89,6 @@ and use `dbis-138.tokenlist.json` as the curated source. See §9.
| LINK (0xb7721d…) | Yes | Match |
| cUSDT (0x93E6…) | Yes | Match |
| cUSDC (0xf22258…) | Yes | Match |
| cUSDT V2, cUSDC V2, mirror USDT/USDC | Yes | Match §5; list uses tag **`fwdcanon`** (Uniswap schema tag length); gas rows use **`gasnative`** |
| cEURC (0x808596…) | Yes | Match |
**Historical gap (closed 2026-02-28):**
@@ -97,7 +96,7 @@ cEURT, cGBPC, cGBPT, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT were initially mis
### 3.2 `explorer-monorepo/backend/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json`
Chain 138 entries were originally the same 7 as `dbis-138`, but the additional compliant tokens were added on 2026-02-28. **cUSDT/cUSDC V2** and **official mirror USDT/USDC** (D3) are now part of the canonical set in **§5** and appear in `DUAL_CHAIN_TOKEN_LIST`; keep `dbis-138.tokenlist.json` aligned with §5 for packaging parity. Keep this file focused on live Explorer cross-checks rather than the closed token-list gap.
Chain 138 entries were originally the same 7 as `dbis-138`, but the additional compliant tokens were added on 2026-02-28. Keep this file focused on live Explorer cross-checks rather than the closed token-list gap.
### 3.3 `ADDRESS_MATRIX_AND_STATUS.md` / `CONTRACT_ADDRESSES_REFERENCE.md`
@@ -111,9 +110,9 @@ All **canonical** Chain 138 token addresses (WETH, WETH10, LINK, cUSDT, cUSDC, c
|------|--------|----------------|
| **Explorer token list source** | Confirmed: Blockscout `GET /api/v2/tokens` | No change; document only. |
| **WETH9 on Blockscout** | First token has `decimals: "0"`, `name`/`symbol`: null | Verify WETH9 contract metadata on-chain; fix in contract or in Blockscout indexing if needed. |
| **dbis-138.tokenlist.json** | Done (2026-02-28; mirrors 2026-04-14) | Added cEURT, cGBPC, cGBPT, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT; **official mirror USDT/USDC** per §5. |
| **DUAL_CHAIN_TOKEN_LIST (MetaMask)** | Done (2026-02-28) | Added same 9 tokens to backend and api/rest copies; **V2 + mirrors** tracked in §5 / DUAL. |
| **ADDRESS_MATRIX / docs** | Done | cEURT and **§1.1 / §5** token inventory; TransactionMirror 0x7131…; summary updated. |
| **dbis-138.tokenlist.json** | Done (2026-02-28) | Added cEURT, cGBPC, cGBPT, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT. |
| **DUAL_CHAIN_TOKEN_LIST (MetaMask)** | Done (2026-02-28) | Added same 9 tokens to backend and api/rest copies. |
| **ADDRESS_MATRIX / docs** | Done | cEURT and all 16 tokens in §1.1; TransactionMirror 0x7131…; summary updated. |
| **Extra LINK/cUSDT/cUSDC on Blockscout** | 6 additional contracts | Non-canonical; use §5 canonical addresses only. |
---
@@ -129,10 +128,6 @@ Use this table to align token lists and docs with the Explorer (Blockscout) and
| LINK | `0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03` | 18 |
| cUSDT | `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22` | 6 |
| cUSDC | `0xf22258f57794CC8E06237084b353Ab30fFfa640b` | 6 |
| cUSDT V2 | `0x9FBfab33882Efe0038DAa608185718b772EE5660` | 6 |
| cUSDC V2 | `0x219522c60e83dEe01FC5b0329d6fA8fD84b9D13d` | 6 |
| USDT (official mirror, D3) | `0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1` | 6 |
| USDC (official mirror, D3) | `0x71D6687F38b93CCad569Fa6352c876eea967201b` | 6 |
| cEURC | `0x8085961F9cF02b4d800A3c6d386D31da4B34266a` | 6 |
| cEURT | `0xdf4b71c61E5912712C1Bdd451416B9aC26949d72` | 6 |
| cGBPC | `0x003960f16D9d34F2e98d62723B6721Fb92074aD2` | 6 |
@@ -159,7 +154,7 @@ Use this table to align token lists and docs with the Explorer (Blockscout) and
| `explorer-monorepo/backend/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` | Multi-chain token list (138, 1, 651940, 25) for MetaMask |
| `token-lists/lists/dbis-138.tokenlist.json` | Chain 138 curated token list (Uniswap-style) |
| `smom-dbis-138/services/token-aggregation/src/config/canonical-tokens.ts` | Canonical addresses and env overrides for indexing/reporting |
| `docs/11-references/ADDRESS_MATRIX_AND_STATUS.md` | Correlated address matrix; §1.1 aligned with **§5** canonical rows; TransactionMirror and summary updated |
| `docs/11-references/ADDRESS_MATRIX_AND_STATUS.md` | Correlated address matrix; §1.1 includes all 16 tokens; TransactionMirror and summary updated |
---

View File

@@ -76,7 +76,7 @@
| **DODO Vending Machine / Adapter** | Deployed | `0xb6D9EF3575bc48De3f011C310DC24d87bEC6087C` — adapter used by `DODOPMMIntegration`. |
| **PMM pools (current canonical stack)** | 3 created | Public pools are `0x9e89bAe009adf128782E19e8341996c596ac40dC` (cUSDT/cUSDC), `0x866Cb44b59303d8dc5f4F9E3E7A8e8b0bf238d66` (cUSDT/USDT), `0xc39B7D0F40838cbFb54649d327f49a6DAC964062` (cUSDC/USDC). |
| **DODOPMMProvider** | **Deployed** | `0x3f729632E9553EBacCdE2e9b4c8F2B285b014F2e`; supports the three canonical stable pools above. |
| **D3Oracle** | Deployed (private pilot) | `0xD7459aEa8bB53C83a1e90262777D730539A326F0`; `WETH10` uses keeper-synced **MockPriceFeed** `0x3e8725b8De386feF3eFE5678c92eA6aDB41992B2` (avoids managed-aggregator staleness on Besu). Legacy slot `0x99b3511a2d315a497c8112c1fdd8d508d4b1e506` remains for audits. Stables use managed USD feeds. |
| **D3Oracle** | Deployed (private pilot) | `0xD7459aEa8bB53C83a1e90262777D730539A326F0`; `WETH10` now uses live `Oracle_Aggregator=0x99b3511a2d315a497c8112c1fdd8d508d4b1e506`, and the stable assets use dedicated managed USD feeds. |
| **D3Vault / D3Proxy / D3MMFactory** | Deployed (private pilot) | `D3Vault=0x42b6867260Fb9eE6d09B7E0233A1fAD65D0133D1`, `D3Proxy=0xc9a11abB7C63d88546Be24D58a6d95e3762cB843`, `D3MMFactory=0x78470C7d2925B6738544E2DD4FE7c07CcA21AC31`. |
| **D3MM pools** | 2 created | `0xE71Bc2cCb62dA5B18F88647db2b4a721Db416fc5` is a superseded bootstrap pool on the placeholder `WETH9` path. `0x6550A3a59070061a262a893A1D6F3F490afFDBDA` is the canonical private `WETH10` pilot pool. |
| **EnhancedSwapRouterV2 + public venue layer** | Live | Router-v2 is deployed and the canonical upstream-native `Uniswap_v3` lane plus the funded pilot-compatible `Balancer`, `Curve_3`, and `1inch` venues are publicly exposed for the canonical Chain 138 routing asset lanes. |

View File

@@ -17,25 +17,6 @@ import http from 'node:http';
const PORT = parseInt(process.env.PORT || '3080', 10);
const BLOCKSCOUT_URL = (process.env.BLOCKSCOUT_URL || 'http://192.168.11.140:4000').replace(/\/$/, '');
function parseOptimizationRuns(payload) {
const raw = payload.runs ?? payload.optimization_runs ?? '200';
return parseInt(raw, 10) || 200;
}
function inferOptimizationEnabled(payload) {
const explicit = payload.optimizationUsed ?? payload.optimization_used;
if (explicit !== undefined && explicit !== null && explicit !== '') {
return [true, '1', 1, 'true'].includes(explicit);
}
// Forge often supplies runs without optimizationUsed for legacy compiler paths.
// When runs is positive, assume optimization was intentionally enabled.
return parseOptimizationRuns(payload) > 0;
}
function inferEvmVersion(payload) {
return payload.evmversion || payload.evm_version || 'default';
}
/** Parse body as JSON or application/x-www-form-urlencoded (Forge/Etherscan style). */
function parseBody(req) {
return new Promise((resolve, reject) => {
@@ -142,9 +123,9 @@ async function forwardV2Flattened(payload) {
compiler_version: payload.compilerversion || payload.compilerVersion || 'v0.8.20+commit.a1b79de6',
contract_name: payload.contractname || payload.contractName || 'Contract',
license_type: payload.licensetype || payload.licenseType || 'mit',
is_optimization_enabled: inferOptimizationEnabled(payload),
optimization_runs: parseOptimizationRuns(payload),
evm_version: inferEvmVersion(payload),
is_optimization_enabled: [true, '1', 1, 'true'].includes(payload.optimizationUsed ?? payload.optimization_used),
optimization_runs: parseInt(payload.runs ?? payload.optimization_runs ?? '200', 10) || 200,
evm_version: payload.evmversion || payload.evm_version || 'london',
autodetect_constructor_args: payload.autodetectConstructorArguments !== false,
source_code: typeof sourceCode === 'string' ? sourceCode : JSON.stringify(sourceCode),
};
@@ -225,9 +206,13 @@ async function forwardV2StandardInput(payload) {
appendField('autodetect_constructor_args', String(payload.autodetectConstructorArguments !== false));
appendField('license_type', licenseType);
appendField('constructor_args', constructorArgs);
appendField('evm_version', inferEvmVersion(payload));
appendField('is_optimization_enabled', String(inferOptimizationEnabled(payload)));
appendField('optimization_runs', String(parseOptimizationRuns(payload)));
if (payload.evmversion || payload.evm_version) appendField('evm_version', payload.evmversion || payload.evm_version);
if (payload.optimizationUsed !== undefined || payload.optimization_used !== undefined) {
appendField('is_optimization_enabled', String([true, '1', 1, 'true'].includes(payload.optimizationUsed ?? payload.optimization_used)));
}
if (payload.runs !== undefined || payload.optimization_runs !== undefined) {
appendField('optimization_runs', String(parseInt(payload.runs ?? payload.optimization_runs ?? '200', 10) || 200));
}
appendFile('files[0]', 'standard-input.json', standardJson, 'application/json');
parts.push(Buffer.from(`--${boundary}--\r\n`));
const body = Buffer.concat(parts);
@@ -269,15 +254,7 @@ function toEtherscanResponse(result) {
return { status: '1', message: data.message || 'OK', result: data.result ?? 'Verification submitted' };
}
if (status >= 200 && status < 300) {
const successMessage = typeof data?.message === 'string' ? data.message : '';
const successResult = typeof data?.result === 'string' ? data.result : '';
if (
/verification started/i.test(successMessage) ||
/verification submitted/i.test(successMessage) ||
/verification submitted/i.test(successResult)
) {
return { status: '1', message: successMessage || 'OK', result: successResult || 'Verification submitted' };
}
return { status: '1', message: 'OK', result: data?.result ?? 'Verification submitted' };
}
// Blockscout may return HTML (502/500) or invalid JSON when DB/migrations fail
let msg = data?.message || data?.error;

File diff suppressed because it is too large Load Diff

View File

@@ -1,171 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Enable the upstream Blockscout smart-contract verifier sidecar on CT 5000 and
# wire Blockscout to use it.
#
# Usage:
# bash scripts/deployment/ensure-blockscout-smart-contract-verifier-5000.sh --dry-run
# bash scripts/deployment/ensure-blockscout-smart-contract-verifier-5000.sh --apply
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
if [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]]; then
# shellcheck source=/dev/null
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
fi
HOST="${PROXMOX_HOST_R630_02:-192.168.11.12}"
VMID="${BLOCKSCOUT_DB_CT_VMID:-5000}"
APPLY=0
while [[ $# -gt 0 ]]; do
case "$1" in
--apply) APPLY=1; shift ;;
--dry-run) APPLY=0; shift ;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
read -r -d '' REMOTE_SCRIPT <<'EOF_REMOTE' || true
set -euo pipefail
cd /opt/blockscout
stamp="$(date +%Y%m%d_%H%M%S)"
cp docker-compose.yml "docker-compose.yml.bak.${stamp}.pre_verifier"
cat > smart-contract-verifier.env <<'EOF_VERIFIER'
SMART_CONTRACT_VERIFIER__SERVER__HTTP__ENABLED=true
SMART_CONTRACT_VERIFIER__SERVER__HTTP__ADDR=0.0.0.0:8050
SMART_CONTRACT_VERIFIER__SERVER__HTTP__MAX_BODY_SIZE=8388608
SMART_CONTRACT_VERIFIER__SERVER__GRPC__ENABLED=false
SMART_CONTRACT_VERIFIER__SERVER__GRPC__ADDR=0.0.0.0:8051
SMART_CONTRACT_VERIFIER__SOLIDITY__ENABLED=true
SMART_CONTRACT_VERIFIER__SOLIDITY__COMPILERS_DIR=/tmp/solidity-compilers
SMART_CONTRACT_VERIFIER__SOLIDITY__REFRESH_VERSIONS_SCHEDULE=0 0 * * * * *
SMART_CONTRACT_VERIFIER__SOLIDITY__FETCHER__LIST__LIST_URL=https://binaries.soliditylang.org/linux-amd64/list.json
SMART_CONTRACT_VERIFIER__VYPER__ENABLED=true
SMART_CONTRACT_VERIFIER__VYPER__COMPILERS_DIR=/tmp/vyper-compilers
SMART_CONTRACT_VERIFIER__VYPER__REFRESH_VERSIONS_SCHEDULE=0 0 * * * * *
SMART_CONTRACT_VERIFIER__VYPER__FETCHER__LIST__LIST_URL=https://raw.githubusercontent.com/blockscout/solc-bin/main/vyper.list.json
SMART_CONTRACT_VERIFIER__SOURCIFY__ENABLED=true
SMART_CONTRACT_VERIFIER__SOURCIFY__API_URL=https://sourcify.dev/server/
SMART_CONTRACT_VERIFIER__SOURCIFY__VERIFICATION_ATTEMPTS=3
SMART_CONTRACT_VERIFIER__SOURCIFY__REQUEST_TIMEOUT=10
SMART_CONTRACT_VERIFIER__METRICS__ENABLED=false
SMART_CONTRACT_VERIFIER__JAEGER__ENABLED=false
EOF_VERIFIER
cat > docker-compose.yml <<'EOF_COMPOSE'
version: "3.8"
services:
postgres:
image: postgres:15-alpine
container_name: blockscout-postgres
environment:
POSTGRES_USER: blockscout
POSTGRES_PASSWORD: blockscout
POSTGRES_DB: blockscout
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
networks:
- blockscout-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blockscout"]
interval: 10s
timeout: 5s
retries: 5
smart-contract-verifier:
image: ghcr.io/blockscout/smart-contract-verifier:latest
container_name: smart-contract-verifier
env_file:
- ./smart-contract-verifier.env
restart: unless-stopped
networks:
- blockscout-network
blockscout:
image: blockscout/blockscout:latest
container_name: blockscout
command: bin/blockscout start
depends_on:
postgres:
condition: service_healthy
smart-contract-verifier:
condition: service_started
environment:
- DISABLE_WEBAPP=false
- DISABLE_INDEXER=false
- INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER=true
- DATABASE_URL=postgresql://blockscout:blockscout@postgres:5432/blockscout?sslmode=disable
- ETHEREUM_JSONRPC_HTTP_URL=http://192.168.11.221:8545
- ETHEREUM_JSONRPC_WS_URL=ws://192.168.11.221:8546
- ETHEREUM_JSONRPC_TRACE_URL=http://192.168.11.221:8545
- ETHEREUM_JSONRPC_VARIANT=besu
- CHAIN_ID=138
- COIN=ETH
- BLOCKSCOUT_HOST=explorer.d-bis.org
- BLOCKSCOUT_PROTOCOL=https
- SECRET_KEY_BASE=73159c7d10b9a5a75ddf10710773078c078bf02124d35b72fa2a841b30b4f88c7c43e5caaf7f9f7f87d16dd66e7870931ae11039c428d1dedae187af762531fa
- POOL_SIZE=50
- POOL_SIZE_API=50
- DATABASE_QUEUE_TARGET=5s
- ECTO_USE_SSL=false
- MICROSERVICE_SC_VERIFIER_ENABLED=true
- MICROSERVICE_SC_VERIFIER_TYPE=sc_verifier
- MICROSERVICE_SC_VERIFIER_URL=http://smart-contract-verifier:8050/
ports:
- "4000:4000"
volumes:
- blockscout-data:/app/apps/explorer/priv/static
restart: unless-stopped
networks:
- blockscout-network
volumes:
postgres-data:
blockscout-data:
networks:
blockscout-network:
driver: bridge
EOF_COMPOSE
docker pull ghcr.io/blockscout/smart-contract-verifier:latest
docker rm -f blockscout 2>/dev/null || true
docker rm -f smart-contract-verifier 2>/dev/null || true
# Older docker-compose v1 can leave an orphaned auto-generated verifier container
# that breaks recreation with a `ContainerConfig` KeyError. Clear it first.
docker ps -a --format '{{.Names}}' | grep -E 'smart-contract-verifier$' | xargs -r docker rm -f
if command -v docker-compose >/dev/null 2>&1; then
docker-compose -f docker-compose.yml up -d
else
docker compose -f docker-compose.yml up -d
fi
sleep 10
docker ps --format "table {{.Names}}\t{{.Status}}"
curl -fsS http://127.0.0.1:4000/api/v2/smart-contracts/verification/config >/dev/null
EOF_REMOTE
echo "Blockscout smart-contract verifier enablement"
echo "Host: ${HOST}"
echo "VMID: ${VMID}"
echo
if (( APPLY == 0 )); then
echo "[dry-run] Would patch /opt/blockscout/docker-compose.yml on CT ${VMID}, add smart-contract-verifier, and restart Blockscout."
exit 0
fi
ssh root@"${HOST}" "pct exec ${VMID} -- bash -lc $(printf '%q' "${REMOTE_SCRIPT}")"
echo
echo "[ok] Blockscout verifier sidecar enabled on CT ${VMID}."

View File

@@ -1,224 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Verify the Chain 138 native Uniswap v2 and SushiSwap deployments on Blockscout.
#
# Usage:
# bash scripts/verify/verify-chain138-native-v2-blockscout.sh
# bash scripts/verify/verify-chain138-native-v2-blockscout.sh --status-only
# bash scripts/verify/verify-chain138-native-v2-blockscout.sh --only UniswapV2Factory,SushiSwapRouter
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
SMOM_ROOT="${PROJECT_ROOT}/smom-dbis-138"
if [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]]; then
# shellcheck source=/dev/null
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
fi
command -v forge >/dev/null 2>&1 || { echo "ERROR: forge not found"; exit 1; }
command -v node >/dev/null 2>&1 || { echo "ERROR: node not found"; exit 1; }
command -v cast >/dev/null 2>&1 || { echo "ERROR: cast not found"; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "ERROR: jq not found"; exit 1; }
command -v curl >/dev/null 2>&1 || { echo "ERROR: curl not found"; exit 1; }
RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-http://192.168.11.211:8545}}"
BLOCKSCOUT_URL="${CHAIN138_BLOCKSCOUT_INTERNAL_URL:-http://${IP_BLOCKSCOUT:-192.168.11.140}:4000}"
BLOCKSCOUT_API_BASE="${CHAIN138_BLOCKSCOUT_API_BASE:-${BLOCKSCOUT_URL}/api/v2}"
BLOCKSCOUT_PUBLIC_API_BASE="${CHAIN138_BLOCKSCOUT_PUBLIC_API_BASE:-https://explorer.d-bis.org/api/v2}"
VERIFIER_PORT="${FORGE_VERIFIER_PROXY_PORT:-3080}"
FORGE_VERIFIER_URL="${FORGE_VERIFIER_URL:-http://127.0.0.1:${VERIFIER_PORT}/api}"
UNISWAP_JSON="${SMOM_ROOT}/deployments/chain138/uniswap-v2-native.json"
SUSHI_JSON="${SMOM_ROOT}/deployments/chain138/sushiswap-native.json"
ONLY_LIST=""
STATUS_ONLY=0
PROXY_PID=""
while [[ $# -gt 0 ]]; do
case "$1" in
--only) ONLY_LIST="${2:-}"; shift 2 ;;
--status-only) STATUS_ONLY=1; shift ;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
cleanup_proxy() {
[[ -n "${PROXY_PID:-}" ]] && kill "${PROXY_PID}" 2>/dev/null || true
}
trap cleanup_proxy EXIT
should_handle() {
local name="$1"
[[ -n "${ONLY_LIST}" ]] && [[ ",${ONLY_LIST}," != *",${name},"* ]] && return 1
return 0
}
log() { printf '%s\n' "$*"; }
ok() { printf '[ok] %s\n' "$*"; }
warn() { printf '[warn] %s\n' "$*" >&2; }
fail() { printf '[fail] %s\n' "$*" >&2; exit 1; }
proxy_listening() {
if command -v nc >/dev/null 2>&1; then
nc -z -w 2 127.0.0.1 "${VERIFIER_PORT}" 2>/dev/null
else
timeout 2 bash -c "echo >/dev/tcp/127.0.0.1/${VERIFIER_PORT}" 2>/dev/null
fi
}
start_proxy_if_needed() {
if proxy_listening; then
ok "Forge verification proxy already listening on ${VERIFIER_PORT}."
return 0
fi
log "Starting forge verification proxy on ${VERIFIER_PORT} -> ${BLOCKSCOUT_URL}"
PORT="${VERIFIER_PORT}" BLOCKSCOUT_URL="${BLOCKSCOUT_URL}" node "${PROJECT_ROOT}/forge-verification-proxy/server.js" >/tmp/chain138-native-v2-blockscout-proxy.log 2>&1 &
PROXY_PID=$!
sleep 2
proxy_listening || fail "Forge verification proxy failed to start. See /tmp/chain138-native-v2-blockscout-proxy.log"
}
has_contract_bytecode() {
local addr="$1"
local code
code="$(cast code "${addr}" --rpc-url "${RPC_URL}" 2>/dev/null | tr -d '\n\r \t' | tr '[:upper:]' '[:lower:]')" || true
[[ -n "${code}" && "${code}" != "0x" && "${code}" != "0x0" ]]
}
verification_status_json() {
local addr="$1"
local raw
local base
for base in "${BLOCKSCOUT_API_BASE}" "${BLOCKSCOUT_PUBLIC_API_BASE}"; do
raw="$(curl --max-time 20 -fsS "${base}/smart-contracts/${addr}" 2>/dev/null || true)"
if [[ -n "${raw}" ]] && jq -e 'type == "object"' >/dev/null 2>&1 <<<"${raw}"; then
printf '%s' "${raw}"
return 0
fi
done
return 1
}
is_verified() {
local addr="$1"
local expected_name="$2"
local json name compiler
json="$(verification_status_json "${addr}")" || return 1
name="$(jq -r '.name // empty' <<<"${json}")"
compiler="$(jq -r '.compiler_version // empty' <<<"${json}")"
[[ -n "${name}" && -n "${compiler}" && "${name}" == "${expected_name}" ]]
}
submit_verification() {
local label="$1"
local addr="$2"
local path="$3"
local expected_name="$4"
local constructor_sig="$5"
local compiler_version="$6"
local force_flag="${7:-0}"
shift 6
local constructor_args=("$@")
start_proxy_if_needed
has_contract_bytecode "${addr}" || fail "${label} has no bytecode at ${addr}"
if is_verified "${addr}" "${expected_name}"; then
ok "${label} already verified on Blockscout."
return 0
fi
local cmd=(forge verify-contract "${addr}" "${path}" --chain-id 138 --verifier blockscout --verifier-url "${FORGE_VERIFIER_URL}" --rpc-url "${RPC_URL}" --flatten)
[[ -n "${compiler_version}" ]] && cmd+=(--compiler-version "${compiler_version}")
if [[ "${force_flag}" == "1" ]]; then
cmd+=(--force)
fi
if [[ -n "${constructor_sig}" ]]; then
local encoded
encoded="$(cast abi-encode "${constructor_sig}" "${constructor_args[@]:1}")"
cmd+=(--constructor-args "${encoded}")
fi
log "Submitting Blockscout verification for ${label} (${addr})"
if (cd "${SMOM_ROOT}" && "${cmd[@]}" 2>&1); then
ok "${label} verification submission accepted."
else
warn "${label} verification submission did not complete cleanly. Check Blockscout manually."
fi
}
[[ -f "${UNISWAP_JSON}" ]] || fail "Missing deployment artifact ${UNISWAP_JSON}"
[[ -f "${SUSHI_JSON}" ]] || fail "Missing deployment artifact ${SUSHI_JSON}"
UNISWAP_FACTORY="$(jq -r '.factory' "${UNISWAP_JSON}")"
UNISWAP_ROUTER="$(jq -r '.router' "${UNISWAP_JSON}")"
UNISWAP_WETH="$(jq -r '.weth' "${UNISWAP_JSON}")"
UNISWAP_DEPLOYER="$(jq -r '.deployer' "${UNISWAP_JSON}")"
SUSHI_FACTORY="$(jq -r '.factory' "${SUSHI_JSON}")"
SUSHI_ROUTER="$(jq -r '.router' "${SUSHI_JSON}")"
SUSHI_WETH="$(jq -r '.weth' "${SUSHI_JSON}")"
SUSHI_FEE_TO_SETTER="$(jq -r '.feeToSetter // .deployer' "${SUSHI_JSON}")"
log "Chain 138 native V2 Blockscout verification"
log "RPC: ${RPC_URL}"
log "Explorer API: ${BLOCKSCOUT_API_BASE}"
log
if (( STATUS_ONLY )); then
should_handle "UniswapV2Factory" && { is_verified "${UNISWAP_FACTORY}" "UniswapV2Factory" && ok "UniswapV2Factory already verified on Blockscout." || warn "UniswapV2Factory not yet verified on Blockscout."; }
should_handle "UniswapV2Router" && { is_verified "${UNISWAP_ROUTER}" "UniswapV2Router02" && ok "UniswapV2Router already verified on Blockscout." || warn "UniswapV2Router not yet verified on Blockscout."; }
should_handle "SushiSwapFactory" && { is_verified "${SUSHI_FACTORY}" "UniswapV2Factory" && ok "SushiSwapFactory already verified on Blockscout." || warn "SushiSwapFactory not yet verified on Blockscout."; }
should_handle "SushiSwapRouter" && { is_verified "${SUSHI_ROUTER}" "UniswapV2Router02" && ok "SushiSwapRouter already verified on Blockscout." || warn "SushiSwapRouter not yet verified on Blockscout."; }
exit 0
fi
should_handle "UniswapV2Factory" && submit_verification \
"UniswapV2Factory" \
"${UNISWAP_FACTORY}" \
"contracts/vendor/uniswap-v2-core/UniswapV2Factory.sol:UniswapV2Factory" \
"UniswapV2Factory" \
"constructor(address)" \
"v0.5.16+commit.9c3226ce" \
"1" \
"${UNISWAP_DEPLOYER}"
should_handle "UniswapV2Router" && submit_verification \
"UniswapV2Router" \
"${UNISWAP_ROUTER}" \
"contracts/vendor/uniswap-v2-periphery/UniswapV2Router02.sol:UniswapV2Router02" \
"UniswapV2Router02" \
"constructor(address,address)" \
"v0.6.6+commit.6c089d02" \
"1" \
"${UNISWAP_FACTORY}" "${UNISWAP_WETH}"
should_handle "SushiSwapFactory" && submit_verification \
"SushiSwapFactory" \
"${SUSHI_FACTORY}" \
"contracts/vendor/sushiswap-v2/UniswapV2Factory.sol:UniswapV2Factory" \
"UniswapV2Factory" \
"constructor(address)" \
"v0.6.12+commit.27d51765" \
"1" \
"${SUSHI_FEE_TO_SETTER}"
should_handle "SushiSwapRouter" && submit_verification \
"SushiSwapRouter" \
"${SUSHI_ROUTER}" \
"contracts/vendor/sushiswap-v2/UniswapV2Router02.sol:UniswapV2Router02" \
"UniswapV2Router02" \
"constructor(address,address)" \
"v0.6.12+commit.27d51765" \
"1" \
"${SUSHI_FACTORY}" "${SUSHI_WETH}"
log
ok "Chain 138 native V2 verification flow complete."

View File

@@ -1,545 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Verify the deployed Chain 138 route execution stack and pilot venue contracts on Blockscout.
#
# Usage:
# bash scripts/verify/verify-chain138-route-execution-stack-blockscout.sh
# bash scripts/verify/verify-chain138-route-execution-stack-blockscout.sh --status-only
# bash scripts/verify/verify-chain138-route-execution-stack-blockscout.sh --no-wait
# bash scripts/verify/verify-chain138-route-execution-stack-blockscout.sh --only EnhancedSwapRouterV2,Chain138PilotCurve3Pool
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
SMOM_ROOT="${PROJECT_ROOT}/smom-dbis-138"
if [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]]; then
# shellcheck source=/dev/null
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
fi
command -v forge >/dev/null 2>&1 || { echo "ERROR: forge not found"; exit 1; }
command -v node >/dev/null 2>&1 || { echo "ERROR: node not found"; exit 1; }
command -v cast >/dev/null 2>&1 || { echo "ERROR: cast not found"; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "ERROR: jq not found"; exit 1; }
command -v curl >/dev/null 2>&1 || { echo "ERROR: curl not found"; exit 1; }
RPC_URL="${RPC_URL_138:-${CHAIN138_RPC_URL:-http://192.168.11.211:8545}}"
BLOCKSCOUT_URL="${CHAIN138_BLOCKSCOUT_INTERNAL_URL:-http://${IP_BLOCKSCOUT:-192.168.11.140}:4000}"
BLOCKSCOUT_API_BASE="${CHAIN138_BLOCKSCOUT_API_BASE:-${BLOCKSCOUT_URL}/api/v2}"
BLOCKSCOUT_PUBLIC_API_BASE="${CHAIN138_BLOCKSCOUT_PUBLIC_API_BASE:-https://explorer.d-bis.org/api/v2}"
VERIFIER_PORT="${FORGE_VERIFIER_PROXY_PORT:-3080}"
FORGE_VERIFIER_URL="${FORGE_VERIFIER_URL:-http://127.0.0.1:${VERIFIER_PORT}/api}"
ROUTE_STACK_SOLC_VERSION="${ROUTE_STACK_SOLC_VERSION:-v0.8.20+commit.a1b79de6}"
ROUTE_STACK_EVM_VERSION="${ROUTE_STACK_EVM_VERSION:-shanghai}"
ROUTE_STACK_OPT_RUNS="${ROUTE_STACK_OPT_RUNS:-200}"
ONLY_LIST=""
STATUS_ONLY=0
NO_WAIT=0
PROXY_PID=""
while [[ $# -gt 0 ]]; do
case "$1" in
--only) ONLY_LIST="${2:-}"; shift 2 ;;
--status-only) STATUS_ONLY=1; shift ;;
--no-wait) NO_WAIT=1; shift ;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
cleanup_proxy() {
[[ -n "${PROXY_PID:-}" ]] && kill "${PROXY_PID}" 2>/dev/null || true
}
trap cleanup_proxy EXIT
should_handle() {
local name="$1"
[[ -n "${ONLY_LIST}" ]] && [[ ",${ONLY_LIST}," != *",${name},"* ]] && return 1
return 0
}
log() { printf '%s\n' "$*"; }
ok() { printf '[ok] %s\n' "$*"; }
warn() { printf '[warn] %s\n' "$*" >&2; }
fail() { printf '[fail] %s\n' "$*" >&2; exit 1; }
proxy_listening() {
if command -v nc >/dev/null 2>&1; then
nc -z -w 2 127.0.0.1 "${VERIFIER_PORT}" 2>/dev/null
else
timeout 2 bash -c "echo >/dev/tcp/127.0.0.1/${VERIFIER_PORT}" 2>/dev/null
fi
}
start_proxy_if_needed() {
if proxy_listening; then
ok "Forge verification proxy already listening on ${VERIFIER_PORT}."
return 0
fi
log "Starting forge verification proxy on ${VERIFIER_PORT} -> ${BLOCKSCOUT_URL}"
PORT="${VERIFIER_PORT}" BLOCKSCOUT_URL="${BLOCKSCOUT_URL}" node "${PROJECT_ROOT}/forge-verification-proxy/server.js" >/tmp/chain138-route-execution-blockscout-proxy.log 2>&1 &
PROXY_PID=$!
sleep 2
proxy_listening || fail "Forge verification proxy failed to start. See /tmp/chain138-route-execution-blockscout-proxy.log"
}
has_contract_bytecode() {
local addr="$1"
local code
code="$(cast code "${addr}" --rpc-url "${RPC_URL}" 2>/dev/null | tr -d '\n\r \t' | tr '[:upper:]' '[:lower:]')" || true
[[ -n "${code}" && "${code}" != "0x" && "${code}" != "0x0" ]]
}
verification_status_json() {
local addr="$1"
local raw
local base
for base in "${BLOCKSCOUT_API_BASE}" "${BLOCKSCOUT_PUBLIC_API_BASE}"; do
raw="$(curl --max-time 20 -fsS "${base}/smart-contracts/${addr}" 2>/dev/null || true)"
if [[ -n "${raw}" ]] && jq -e 'type == "object"' >/dev/null 2>&1 <<<"${raw}"; then
printf '%s' "${raw}"
return 0
fi
done
return 1
}
is_verified() {
local addr="$1"
local expected_name="$2"
local json name compiler
json="$(verification_status_json "${addr}")" || return 1
name="$(jq -r '.name // empty' <<<"${json}")"
compiler="$(jq -r '.compiler_version // empty' <<<"${json}")"
[[ -n "${name}" && -n "${compiler}" && "${name}" == "${expected_name}" ]]
}
submit_verification() {
local label="$1"
local addr="$2"
local path="$3"
local expected_name="$4"
local constructor_sig="$5"
shift 5
local constructor_args=("$@")
start_proxy_if_needed
has_contract_bytecode "${addr}" || fail "${label} has no bytecode at ${addr}"
if is_verified "${addr}" "${expected_name}"; then
ok "${label} already verified on Blockscout."
return 0
fi
local cmd=(forge verify-contract "${addr}" "${path}" --chain-id 138 --verifier blockscout --verifier-url "${FORGE_VERIFIER_URL}" --rpc-url "${RPC_URL}" --flatten)
if [[ -n "${constructor_sig}" ]]; then
local encoded
encoded="$(cast abi-encode "${constructor_sig}" "${constructor_args[@]}")"
cmd+=(--constructor-args "${encoded}")
fi
log "Submitting Blockscout verification for ${label} (${addr})"
if (cd "${SMOM_ROOT}" && "${cmd[@]}" 2>&1); then
ok "${label} verification submission accepted."
else
warn "${label} verification submission did not complete cleanly. Check Blockscout manually."
fi
}
artifact_dbg_path() {
case "$1" in
EnhancedSwapRouterV2) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/EnhancedSwapRouterV2.sol/EnhancedSwapRouterV2.dbg.json" ;;
IntentBridgeCoordinatorV2) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/IntentBridgeCoordinatorV2.sol/IntentBridgeCoordinatorV2.dbg.json" ;;
DodoRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/DodoRouteExecutorAdapter.sol/DodoRouteExecutorAdapter.dbg.json" ;;
DodoV3RouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/DodoV3RouteExecutorAdapter.sol/DodoV3RouteExecutorAdapter.dbg.json" ;;
UniswapV3RouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/UniswapV3RouteExecutorAdapter.sol/UniswapV3RouteExecutorAdapter.dbg.json" ;;
BalancerRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/BalancerRouteExecutorAdapter.sol/BalancerRouteExecutorAdapter.dbg.json" ;;
CurveRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/CurveRouteExecutorAdapter.sol/CurveRouteExecutorAdapter.dbg.json" ;;
OneInchRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/adapters/OneInchRouteExecutorAdapter.sol/OneInchRouteExecutorAdapter.dbg.json" ;;
Chain138PilotUniswapV3Router) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotUniswapV3Router.dbg.json" ;;
Chain138PilotBalancerVault) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotBalancerVault.dbg.json" ;;
Chain138PilotCurve3Pool) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotCurve3Pool.dbg.json" ;;
Chain138PilotOneInchAggregationRouter) printf '%s' "${SMOM_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotOneInchAggregationRouter.dbg.json" ;;
*) return 1 ;;
esac
}
foundry_artifact_json_path() {
case "$1" in
EnhancedSwapRouterV2) printf '%s' "${SMOM_ROOT}/out/EnhancedSwapRouterV2.sol/EnhancedSwapRouterV2.json" ;;
IntentBridgeCoordinatorV2) printf '%s' "${SMOM_ROOT}/out/IntentBridgeCoordinatorV2.sol/IntentBridgeCoordinatorV2.json" ;;
DodoRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/DodoRouteExecutorAdapter.sol/DodoRouteExecutorAdapter.json" ;;
DodoV3RouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/DodoV3RouteExecutorAdapter.sol/DodoV3RouteExecutorAdapter.json" ;;
UniswapV3RouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/UniswapV3RouteExecutorAdapter.sol/UniswapV3RouteExecutorAdapter.json" ;;
BalancerRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/BalancerRouteExecutorAdapter.sol/BalancerRouteExecutorAdapter.json" ;;
CurveRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/CurveRouteExecutorAdapter.sol/CurveRouteExecutorAdapter.json" ;;
OneInchRouteExecutorAdapter) printf '%s' "${SMOM_ROOT}/out/OneInchRouteExecutorAdapter.sol/OneInchRouteExecutorAdapter.json" ;;
Chain138PilotUniswapV3Router|Chain138PilotBalancerVault|Chain138PilotCurve3Pool|Chain138PilotOneInchAggregationRouter)
printf '%s' "${SMOM_ROOT}/out/Chain138PilotDexVenues.sol/${1}.json"
;;
*) return 1 ;;
esac
}
runtime_hash_report() {
local label="$1"
local addr="$2"
local artifact_json artifact_runtime chain_runtime
artifact_json="$(foundry_artifact_json_path "${label}")" || return 0
[[ -f "${artifact_json}" ]] || return 0
artifact_runtime="$(jq -r '.deployedBytecode.object // empty' "${artifact_json}" | tr '[:upper:]' '[:lower:]')"
chain_runtime="$(cast code "${addr}" --rpc-url "${RPC_URL}" 2>/dev/null | tr -d '\n\r \t' | tr '[:upper:]' '[:lower:]')" || true
[[ -n "${artifact_runtime}" && -n "${chain_runtime}" && "${chain_runtime}" != "0x" ]] || return 0
if [[ "${artifact_runtime}" != "${chain_runtime}" ]]; then
warn "${label}: Foundry artifact runtime bytecode does not match deployed bytecode."
warn "${label}: artifact_keccak=$(cast keccak "${artifact_runtime}") chain_keccak=$(cast keccak "${chain_runtime}")"
fi
}
submit_standard_input_from_artifact() {
local label="$1"
local addr="$2"
local contract_path="$3"
local constructor_args="$4"
local dbg build input_file compiler_version evm_version optimization_runs optimization_enabled license_type response message
dbg="$(artifact_dbg_path "${label}")" || fail "${label}: missing dbg path mapping"
[[ -f "${dbg}" ]] || fail "${label}: missing dbg artifact ${dbg}"
build="$(jq -r '.buildInfo // .build_info // empty' "${dbg}")"
[[ -n "${build}" && "${build}" != "null" ]] || fail "${label}: missing build-info reference in ${dbg}"
build="$(cd "$(dirname "${dbg}")" && realpath "${build}")"
[[ -f "${build}" ]] || fail "${label}: missing build-info file ${build}"
input_file="$(mktemp)"
python3 - "${dbg}" "${build}" "${input_file}" "${contract_path%%:*}" <<'PY'
import json
import os
import posixpath
import re
import sys
dbg_path, build_path, out_path, fallback_source = sys.argv[1:5]
with open(dbg_path, "r", encoding="utf-8") as fh:
dbg = json.load(fh)
with open(build_path, "r", encoding="utf-8") as fh:
build = json.load(fh)
source_name = dbg.get("sourceName") or dbg.get("source_name") or fallback_source
if not source_name:
raise SystemExit(f"missing sourceName in {dbg_path}")
input_data = build["input"]
sources = input_data.get("sources", {})
if source_name not in sources:
raise SystemExit(f"source {source_name} missing from build-info input")
import_re = re.compile(r'import\s+(?:[^;]*?\s+from\s+)?["\']([^"\']+)["\']\s*;')
closure = set()
stack = [source_name]
while stack:
current = stack.pop()
if current in closure or current not in sources:
continue
closure.add(current)
content = sources[current].get("content", "")
for entry in import_re.findall(content):
if entry.startswith("."):
target = posixpath.normpath(posixpath.join(posixpath.dirname(current), entry))
else:
target = entry
if target in sources and target not in closure:
stack.append(target)
reduced = json.loads(json.dumps(input_data))
reduced["sources"] = {name: sources[name] for name in sorted(closure)}
with open(out_path, "w", encoding="utf-8") as fh:
json.dump(reduced, fh, separators=(",", ":"))
PY
compiler_version="$(jq -r '.solcLongVersion | "v" + .' "${build}")"
evm_version="$(jq -r '.input.settings.evmVersion // "default"' "${build}")"
optimization_runs="$(jq -r '.input.settings.optimizer.runs // 200' "${build}")"
optimization_enabled="$(jq -r '.input.settings.optimizer.enabled // true' "${build}")"
license_type="mit"
response="$(
curl --max-time 180 -fsS -X POST \
-F "compiler_version=${compiler_version}" \
-F "contract_name=${contract_path}" \
-F "autodetect_constructor_args=false" \
-F "constructor_args=${constructor_args}" \
-F "optimization_runs=${optimization_runs}" \
-F "is_optimization_enabled=${optimization_enabled}" \
-F "evm_version=${evm_version}" \
-F "license_type=${license_type}" \
-F "files[0]=@${input_file};type=application/json" \
"${BLOCKSCOUT_URL}/api/v2/smart-contracts/${addr}/verification/via/standard-input"
)" || {
rm -f "${input_file}"
fail "${label}: Blockscout standard-input submission failed."
}
rm -f "${input_file}"
message="$(jq -r '.message // empty' <<<"${response}")"
if [[ "${message}" == "Smart-contract verification started" ]]; then
ok "${label} standard-input verification submission accepted."
return 0
fi
warn "${label} standard-input verification returned: ${response}"
return 1
}
submit_standard_input_from_forge() {
local label="$1"
local addr="$2"
local contract_path="$3"
local constructor_args="$4"
local input_file response message
local compiler_version evm_version optimization_runs via_ir_flag artifact_json
compiler_version="${ROUTE_STACK_SOLC_VERSION}"
evm_version="${ROUTE_STACK_EVM_VERSION}"
optimization_runs="${ROUTE_STACK_OPT_RUNS}"
via_ir_flag=(--via-ir)
artifact_json="$(foundry_artifact_json_path "${label}" || true)"
if [[ -n "${artifact_json}" && -f "${artifact_json}" ]]; then
compiler_version="v$(jq -r '.metadata.compiler.version // empty' "${artifact_json}")"
evm_version="$(jq -r '.metadata.settings.evmVersion // "default"' "${artifact_json}")"
optimization_runs="$(jq -r '.metadata.settings.optimizer.runs // 200' "${artifact_json}")"
if [[ "$(jq -r '.metadata.settings.viaIR // false' "${artifact_json}")" != "true" ]]; then
via_ir_flag=()
fi
fi
runtime_hash_report "${label}" "${addr}"
input_file="$(mktemp)"
(
cd "${SMOM_ROOT}"
forge verify-contract "${addr}" "${contract_path}" \
--chain-id 138 \
--root . \
--compiler-version "${compiler_version}" \
--num-of-optimizations "${optimization_runs}" \
"${via_ir_flag[@]}" \
--evm-version "${evm_version}" \
--show-standard-json-input >"${input_file}"
) || {
rm -f "${input_file}"
fail "${label}: failed to render Foundry standard-input from deployment sources."
}
response="$(
curl --max-time 180 -fsS -X POST \
-F "compiler_version=${compiler_version}" \
-F "contract_name=${contract_path}" \
-F "autodetect_constructor_args=false" \
-F "constructor_args=${constructor_args}" \
-F "optimization_runs=${optimization_runs}" \
-F "is_optimization_enabled=true" \
-F "evm_version=${evm_version}" \
-F "license_type=mit" \
-F "files[0]=@${input_file};type=application/json" \
"${BLOCKSCOUT_URL}/api/v2/smart-contracts/${addr}/verification/via/standard-input"
)" || {
rm -f "${input_file}"
fail "${label}: Blockscout Foundry standard-input submission failed."
}
rm -f "${input_file}"
message="$(jq -r '.message // empty' <<<"${response}")"
if [[ "${message}" == "Smart-contract verification started" ]]; then
ok "${label} Foundry standard-input verification submission accepted."
return 0
fi
warn "${label} Foundry standard-input verification returned: ${response}"
return 1
}
submit_best_verification() {
local label="$1"
local addr="$2"
local path="$3"
local expected_name="$4"
local constructor_sig="$5"
shift 5
local constructor_args=("$@")
local encoded=""
if [[ -n "${constructor_sig}" ]]; then
encoded="$(cast abi-encode "${constructor_sig}" "${constructor_args[@]}")"
fi
# Prefer the Foundry deployment lineage for the route stack. The earlier
# Hardhat dbg/build-info path drifted away from the actual deployed compiler/EVM
# settings and is kept only as a compatibility fallback.
if submit_standard_input_from_forge "${label}" "${addr}" "${path}" "${encoded}"; then
return 0
fi
if artifact_dbg_path "${label}" >/dev/null 2>&1; then
warn "${label}: falling back to artifact-derived standard-input after Foundry mismatch."
submit_standard_input_from_artifact "${label}" "${addr}" "${path}" "${encoded}" || return 1
return 0
fi
warn "${label}: falling back to legacy Forge flattened verification path."
submit_verification "${label}" "${addr}" "${path}" "${expected_name}" "${constructor_sig}" "${constructor_args[@]}"
}
WETH="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
USDT="0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1"
USDC="0x71D6687F38b93CCad569Fa6352c876eea967201b"
DAI_PLACEHOLDER="0x6B175474E89094C44Da98b954EedeAC495271d0F"
ROUTER_V2="$(jq -r '.chains["138"].contracts.EnhancedSwapRouterV2' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
COORDINATOR_V2="$(jq -r '.chains["138"].contracts.IntentBridgeCoordinatorV2' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
DODO_ADAPTER="$(jq -r '.chains["138"].contracts.DodoRouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
DODO_V3_ADAPTER="$(jq -r '.chains["138"].contracts.DodoV3RouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
UNISWAP_V3_ADAPTER="$(jq -r '.chains["138"].contracts.UniswapV3RouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
BALANCER_ADAPTER="$(jq -r '.chains["138"].contracts.BalancerRouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
CURVE_ADAPTER="$(jq -r '.chains["138"].contracts.CurveRouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
ONEINCH_ADAPTER="$(jq -r '.chains["138"].contracts.OneInchRouteExecutorAdapter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
PILOT_UNISWAP="$(jq -r '.chains["138"].contracts.PilotUniswapV3Router' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
PILOT_BALANCER="$(jq -r '.chains["138"].contracts.PilotBalancerVault' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
PILOT_CURVE="$(jq -r '.chains["138"].contracts.PilotCurve3Pool' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
PILOT_ONEINCH="$(jq -r '.chains["138"].contracts.PilotOneInchRouter' "${PROJECT_ROOT}/config/smart-contracts-master.json")"
log "Chain 138 route execution stack Blockscout verification"
log "RPC: ${RPC_URL}"
log "Explorer API: ${BLOCKSCOUT_API_BASE}"
log
if (( STATUS_ONLY )); then
for pair in \
"EnhancedSwapRouterV2:${ROUTER_V2}:EnhancedSwapRouterV2" \
"IntentBridgeCoordinatorV2:${COORDINATOR_V2}:IntentBridgeCoordinatorV2" \
"DodoRouteExecutorAdapter:${DODO_ADAPTER}:DodoRouteExecutorAdapter" \
"DodoV3RouteExecutorAdapter:${DODO_V3_ADAPTER}:DodoV3RouteExecutorAdapter" \
"UniswapV3RouteExecutorAdapter:${UNISWAP_V3_ADAPTER}:UniswapV3RouteExecutorAdapter" \
"BalancerRouteExecutorAdapter:${BALANCER_ADAPTER}:BalancerRouteExecutorAdapter" \
"CurveRouteExecutorAdapter:${CURVE_ADAPTER}:CurveRouteExecutorAdapter" \
"OneInchRouteExecutorAdapter:${ONEINCH_ADAPTER}:OneInchRouteExecutorAdapter" \
"Chain138PilotUniswapV3Router:${PILOT_UNISWAP}:Chain138PilotUniswapV3Router" \
"Chain138PilotBalancerVault:${PILOT_BALANCER}:Chain138PilotBalancerVault" \
"Chain138PilotCurve3Pool:${PILOT_CURVE}:Chain138PilotCurve3Pool" \
"Chain138PilotOneInchAggregationRouter:${PILOT_ONEINCH}:Chain138PilotOneInchAggregationRouter"
do
IFS=":" read -r label addr expected <<<"${pair}"
should_handle "${label}" || continue
if is_verified "${addr}" "${expected}"; then
ok "${label} already verified on Blockscout."
else
warn "${label} not yet verified on Blockscout."
fi
done
exit 0
fi
should_handle "EnhancedSwapRouterV2" && submit_best_verification \
"EnhancedSwapRouterV2" \
"${ROUTER_V2}" \
"contracts/bridge/trustless/EnhancedSwapRouterV2.sol:EnhancedSwapRouterV2" \
"EnhancedSwapRouterV2" \
"constructor(address,address,address,address)" \
"${WETH}" "${USDT}" "${USDC}" "${DAI_PLACEHOLDER}"
should_handle "IntentBridgeCoordinatorV2" && submit_best_verification \
"IntentBridgeCoordinatorV2" \
"${COORDINATOR_V2}" \
"contracts/bridge/trustless/IntentBridgeCoordinatorV2.sol:IntentBridgeCoordinatorV2" \
"IntentBridgeCoordinatorV2" \
"constructor(address)" \
"${ROUTER_V2}"
should_handle "DodoRouteExecutorAdapter" && submit_best_verification \
"DodoRouteExecutorAdapter" \
"${DODO_ADAPTER}" \
"contracts/bridge/trustless/adapters/DodoRouteExecutorAdapter.sol:DodoRouteExecutorAdapter" \
"DodoRouteExecutorAdapter" \
""
should_handle "DodoV3RouteExecutorAdapter" && submit_best_verification \
"DodoV3RouteExecutorAdapter" \
"${DODO_V3_ADAPTER}" \
"contracts/bridge/trustless/adapters/DodoV3RouteExecutorAdapter.sol:DodoV3RouteExecutorAdapter" \
"DodoV3RouteExecutorAdapter" \
""
should_handle "UniswapV3RouteExecutorAdapter" && submit_best_verification \
"UniswapV3RouteExecutorAdapter" \
"${UNISWAP_V3_ADAPTER}" \
"contracts/bridge/trustless/adapters/UniswapV3RouteExecutorAdapter.sol:UniswapV3RouteExecutorAdapter" \
"UniswapV3RouteExecutorAdapter" \
""
should_handle "BalancerRouteExecutorAdapter" && submit_best_verification \
"BalancerRouteExecutorAdapter" \
"${BALANCER_ADAPTER}" \
"contracts/bridge/trustless/adapters/BalancerRouteExecutorAdapter.sol:BalancerRouteExecutorAdapter" \
"BalancerRouteExecutorAdapter" \
""
should_handle "CurveRouteExecutorAdapter" && submit_best_verification \
"CurveRouteExecutorAdapter" \
"${CURVE_ADAPTER}" \
"contracts/bridge/trustless/adapters/CurveRouteExecutorAdapter.sol:CurveRouteExecutorAdapter" \
"CurveRouteExecutorAdapter" \
""
should_handle "OneInchRouteExecutorAdapter" && submit_best_verification \
"OneInchRouteExecutorAdapter" \
"${ONEINCH_ADAPTER}" \
"contracts/bridge/trustless/adapters/OneInchRouteExecutorAdapter.sol:OneInchRouteExecutorAdapter" \
"OneInchRouteExecutorAdapter" \
""
should_handle "Chain138PilotUniswapV3Router" && submit_best_verification \
"Chain138PilotUniswapV3Router" \
"${PILOT_UNISWAP}" \
"contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol:Chain138PilotUniswapV3Router" \
"Chain138PilotUniswapV3Router" \
""
should_handle "Chain138PilotBalancerVault" && submit_best_verification \
"Chain138PilotBalancerVault" \
"${PILOT_BALANCER}" \
"contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol:Chain138PilotBalancerVault" \
"Chain138PilotBalancerVault" \
""
should_handle "Chain138PilotCurve3Pool" && submit_best_verification \
"Chain138PilotCurve3Pool" \
"${PILOT_CURVE}" \
"contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol:Chain138PilotCurve3Pool" \
"Chain138PilotCurve3Pool" \
"constructor(address,address,address,uint256)" \
"${USDT}" "${USDC}" "0x0000000000000000000000000000000000000000" "4"
should_handle "Chain138PilotOneInchAggregationRouter" && submit_best_verification \
"Chain138PilotOneInchAggregationRouter" \
"${PILOT_ONEINCH}" \
"contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol:Chain138PilotOneInchAggregationRouter" \
"Chain138PilotOneInchAggregationRouter" \
""
if (( NO_WAIT )); then
log
ok "Chain 138 route execution stack verification submissions complete."
exit 0
fi
log
ok "Chain 138 route execution stack verification flow complete."

View File

@@ -273,16 +273,9 @@ submit_v2_standard_input() {
compiler_version="v0.8.16+commit.07a7930e"
license_type="busl_1_1"
input_file="$(mktemp)"
jq '
del(.settings.libraries[""].__CACHE_BREAKER__)
| if (.settings.libraries[""]? == {}) then del(.settings.libraries[""]) else . end
| if (.settings.libraries? == {}) then del(.settings.libraries) else . end
' "${input}" > "${input_file}"
response="$(
curl --max-time 120 -fsS -X POST \
curl --max-time 30 -fsS -X POST \
-F "compiler_version=${compiler_version}" \
-F "contract_name=${path}" \
-F "autodetect_constructor_args=false" \
@@ -290,13 +283,9 @@ submit_v2_standard_input() {
-F "optimization_runs=200" \
-F "is_optimization_enabled=true" \
-F "license_type=${license_type}" \
-F "files[0]=@${input_file};type=application/json" \
-F "files[0]=@${input};type=application/json" \
"${BLOCKSCOUT_URL}/api/v2/smart-contracts/${addr}/verification/via/standard-input"
)" || {
rm -f "${input_file}"
fail "${label}: Blockscout standard-input submission failed."
}
rm -f "${input_file}"
)" || fail "${label}: Blockscout standard-input submission failed."
message="$(jq -r '.message // empty' <<<"${response}")"
if [[ "${message}" == "Smart-contract verification started" ]]; then

View File

@@ -1,21 +1,29 @@
{
"name": "SMOM-DBIS-138 Token List",
"name": "DBIS Chain 138 Token List",
"version": {
"major": 1,
"minor": 1,
"patch": 2
"minor": 7,
"patch": 4
},
"timestamp": "2025-12-24T00:00:00.000Z",
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
"timestamp": "2026-04-14T22:00:00.000Z",
"keywords": [
"dbis",
"chain138",
"defi oracle meta"
],
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/chain138-list.svg",
"tokens": [
{
"chainId": 138,
"address": "0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6",
"address": "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6",
"name": "ETH/USD Price Feed",
"symbol": "ETH-USD",
"decimals": 8,
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
"tags": ["oracle", "price-feed"]
"logoURI": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
"tags": [
"oracle",
"pricefeed"
]
},
{
"chainId": 138,
@@ -23,17 +31,23 @@
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
"tags": ["defi", "wrapped"]
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 138,
"address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f",
"address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F",
"name": "Wrapped Ether v10",
"symbol": "WETH10",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
"tags": ["defi", "wrapped"]
"logoURI": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 138,
@@ -41,8 +55,454 @@
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/chainlink/chainlink-docs/main/docs/images/chainlink-logo.svg",
"tags": ["defi", "oracle", "ccip"]
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 138,
"address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22",
"name": "Tether USD (Compliant)",
"symbol": "cUSDT",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDT.png",
"tags": [
"stablecoin",
"defi",
"compliant"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v1",
"forwardCanonical": false,
"x402Ready": false
}
},
{
"chainId": 138,
"address": "0x9FBfab33882Efe0038DAa608185718b772EE5660",
"name": "Tether USD (Compliant V2)",
"symbol": "cUSDT",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDT.png",
"tags": [
"stablecoin",
"defi",
"compliant",
"v2",
"x402",
"fwdcanon"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v2",
"forwardCanonical": true,
"x402Ready": true,
"explorerLabel": "Chain 138 cUSDT V2 forward canonical"
}
},
{
"chainId": 138,
"address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b",
"name": "USD Coin (Compliant)",
"symbol": "cUSDC",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDC.png",
"tags": [
"stablecoin",
"defi",
"compliant"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v1",
"forwardCanonical": false,
"x402Ready": false
}
},
{
"chainId": 138,
"address": "0x219522c60e83dEe01FC5b0329d6fA8fD84b9D13d",
"name": "USD Coin (Compliant V2)",
"symbol": "cUSDC",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDC.png",
"tags": [
"stablecoin",
"defi",
"compliant",
"v2",
"x402",
"fwdcanon"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v2",
"forwardCanonical": true,
"x402Ready": true,
"explorerLabel": "Chain 138 cUSDC V2 forward canonical"
}
},
{
"chainId": 138,
"address": "0x71D6687F38b93CCad569Fa6352c876eea967201b",
"name": "USD Coin (Chain 138)",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 138,
"address": "0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1",
"name": "Tether USD (Chain 138)",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 138,
"address": "0x8085961F9cF02b4d800A3c6d386D31da4B34266a",
"name": "Euro Coin (Compliant)",
"symbol": "cEURC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cEURC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0xdf4b71c61E5912712C1Bdd451416B9aC26949d72",
"name": "Tether EUR (Compliant)",
"symbol": "cEURT",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cEURT.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0x003960f16D9d34F2e98d62723B6721Fb92074aD2",
"name": "Pound Sterling (Compliant)",
"symbol": "cGBPC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cGBPC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0x350f54e4D23795f86A9c03988c7135357CCaD97c",
"name": "Tether GBP (Compliant)",
"symbol": "cGBPT",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cGBPT.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0xD51482e567c03899eecE3CAe8a058161FD56069D",
"name": "Australian Dollar (Compliant)",
"symbol": "cAUDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cAUDC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0xEe269e1226a334182aace90056EE4ee5Cc8A6770",
"name": "Japanese Yen (Compliant)",
"symbol": "cJPYC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cJPYC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0x873990849DDa5117d7C644f0aF24370797C03885",
"name": "Swiss Franc (Compliant)",
"symbol": "cCHFC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cCHFC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0x54dBd40cF05e15906A2C21f600937e96787f5679",
"name": "Canadian Dollar (Compliant)",
"symbol": "cCADC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru/cCADC.svg",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0x290E52a8819A4fbD0714E517225429aA2B70EC6b",
"name": "Gold (Compliant)",
"symbol": "cXAUC",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cXAUC.png",
"tags": [
"defi",
"compliant"
],
"extensions": {
"unitOfAccount": "troy_ounce",
"unitDescription": "1 full token = 1 troy oz fine gold"
}
},
{
"chainId": 138,
"address": "0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E",
"name": "Tether XAU (Compliant)",
"symbol": "cXAUT",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cXAUT.png",
"tags": [
"defi",
"compliant"
],
"extensions": {
"unitOfAccount": "troy_ounce",
"unitDescription": "1 full token = 1 troy oz fine gold"
}
},
{
"chainId": 138,
"address": "0xF8e9802a1766422e33a269556AD5fC032338EeFc",
"name": "Ethereum Mainnet Gas (Compliant)",
"symbol": "cETH",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_mainnet",
"mirroredSymbol": "cWETH",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x18A6B163d255cC0Cb32B99697843b487D059907d",
"name": "Ethereum L2 Gas (Compliant)",
"symbol": "cETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "eth_l2",
"mirroredSymbol": "cWETHL2",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x94517875f32680984a5921DA7abf78E22f65d70F",
"name": "BNB Gas (Compliant)",
"symbol": "cBNB",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "bnb",
"mirroredSymbol": "cWBNB",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x19fec21eDedE9EdB91D1FbeC7C4095C5Ac1FC10c",
"name": "Polygon Gas (Compliant)",
"symbol": "cPOL",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "pol",
"mirroredSymbol": "cWPOL",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x9c8f6F4fe1e535e6F85a78Ee95249deD5540A2D0",
"name": "Avalanche Gas (Compliant)",
"symbol": "cAVAX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "avax",
"mirroredSymbol": "cWAVAX",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0xFb48bb6c623571F9795B535B73f0D660E8643fd4",
"name": "Cronos Gas (Compliant)",
"symbol": "cCRO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "cro",
"mirroredSymbol": "cWCRO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0xA39A59138F8a45b4a31455875b8A29FF31E76Ec8",
"name": "Gnosis Gas (Compliant)",
"symbol": "cXDAI",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/xdai/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "xdai",
"mirroredSymbol": "cWXDAI",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x1814661DAE0933Bf397b1274f5a62411B94195C7",
"name": "Celo Gas (Compliant)",
"symbol": "cCELO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/celo/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "celo",
"mirroredSymbol": "cWCELO",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
},
{
"chainId": 138,
"address": "0x4D82206BeC5B4Dfa17759FFEDE07E35f4f63a050",
"name": "Wemix Gas (Compliant)",
"symbol": "cWEMIX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/wemix/info/logo.png",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
"familyKey": "wemix",
"mirroredSymbol": "cWWEMIX",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"canonicalChainId": 138,
"wave": "wave1"
}
}
],
"tags": {
@@ -58,9 +518,41 @@
"name": "Oracle",
"description": "Oracle price feed tokens"
},
"price-feed": {
"pricefeed": {
"name": "Price Feed",
"description": "Price feed oracle contracts"
},
"stablecoin": {
"name": "Stablecoin",
"description": "Stable value tokens pegged to fiat currencies"
},
"compliant": {
"name": "Compliant",
"description": "Regulatory compliant tokens with compliance features"
},
"ccip": {
"name": "CCIP",
"description": "Cross Chain Interoperability Protocol tokens"
},
"v2": {
"name": "Version 2",
"description": "Next generation GRU token contracts"
},
"x402": {
"name": "x402 Ready",
"description": "Permit or authorization capable payment tokens"
},
"staged": {
"name": "Staged",
"description": "Deployed and discoverable, not yet canonical"
},
"fwdcanon": {
"name": "Forward canonical",
"description": "GRU v2 forward canonical token variant"
},
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -3,6 +3,8 @@
**Date**: 2026-01-26
**Status**: ✅ **100% COMPLETE**
> **2026-04-14 note:** This file is a historical milestone snapshot. Current canonical Chain 138 inventory is in `docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md` §5 and `lists/dbis-138.tokenlist.json` (29 entries as of 1.7.4).
---
## 🎉 Executive Summary

View File

@@ -59,18 +59,19 @@ token-lists/
## Token List Contents
Current version: **1.7.0**
Current version: **1.7.4**
Canonical currency and lifecycle state are also tracked in [`../config/gru-iso4217-currency-manifest.json`](../config/gru-iso4217-currency-manifest.json). The token list is the wallet/explorer-facing projection of that broader GRU asset inventory. Canonical GRU SVG logos now live under [`logos/gru/`](logos/gru) and are referenced through raw HTTPS URLs so wallets and explorers can use the same source artwork.
### Tokens
Current token count: **18**
Current token count: **29** (includes official mirror **USDT/USDC**, Wave 1 gas-family `c*` entries, and the ETH-USD oracle row).
Notable current state:
- `cUSDT` and `cUSDC` each have both V1 and V2 entries on Chain 138.
- Duplicate symbols for V1/V2 are intentional during coexistence and cutover.
- The V2 entries are the forward-canonical x402 surfaces and include IPFS-backed metadata/disclosure/reporting URIs in `extensions`.
- V2 entries are forward-canonical x402 surfaces; **Uniswap Token Lists schema** allows only short `extensions` string values, so long `ipfs://…` disclosure URIs are **not** embedded in the JSON list (see on-chain `tokenURI` / [`CONTRACT_ADDRESSES_REFERENCE.md`](../docs/11-references/CONTRACT_ADDRESSES_REFERENCE.md)). V2 rows use tag **`fwdcanon`** (≤10 characters per schema).
- Gas-family rows use tag **`gasnative`** and keep transport metadata under `extensions` only (no extra top-level token fields), per the same schema.
- Non-USD GRU currencies currently covered in the list are `EUR`, `GBP`, `AUD`, `JPY`, `CHF`, `CAD`, and `XAU`.
1. **ETH/USD Price Feed** (Oracle)
@@ -113,12 +114,26 @@ Notable current state:
- Decimals: 6
- Category: Stablecoin, DeFi, Compliant, V2, x402-ready
9. **Additional GRU currencies**
9. **USDC** / **USDT** (Chain 138 mirror labels; D3 official mirror addresses) — see [`docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md`](../docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md) §5.
10. **Additional GRU currencies**
- `cEURC`, `cEURT`, `cGBPC`, `cGBPT`, `cAUDC`, `cJPYC`, `cCHFC`, `cCADC`, `cXAUC`, `cXAUT`
- See `lists/dbis-138.tokenlist.json` for the full current set.
---
## Checksums (dbis-138)
After editing **`lists/dbis-138.tokenlist.json`**, refresh integrity checksum (same output as release workflow):
```bash
bash scripts/update-sha256sums.sh
```
Committed file: **`lists/SHA256SUMS`**. **minisign** signature (`.sig`) is produced in CI or locally via **`scripts/sign-list.sh`** when a private key is available.
---
## Validation
All token lists are validated against:
@@ -128,7 +143,7 @@ All token lists are validated against:
- Chain ID strict validation (must be 138)
- Duplicate detection (addresses and symbols)
- Logo URL accessibility
- On-chain contract verification
- On-chain contract verification (`verify-on-chain.js`: **pricefeed**-tagged rows use oracle ABI; **LINK** uses ERC-20; canonical **WETH9** may return `decimals() == 0` on-chain while the list keeps **18** — logged as a warning)
- Expected duplicate-symbol warnings during V1/V2 coexistence
### Running Validations

View File

@@ -25,11 +25,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Planned
- Additional token entries as requested
- Enhanced metadata and documentation
- Logo updates for controlled hosting
---
[1.1.0]: https://github.com/dbis/token-lists/releases/tag/v1.1.0
## [1.7.4] - 2026-04-14
### Added
- Official mirror **USDT** / **USDC** (Chain 138) rows; Wave 1 gas-family `c*` entries with schema-safe **`gasnative`** tag; **`fwdcanon`** tag for GRU V2 USD surfaces.
- **`lists/SHA256SUMS`** for `dbis-138.tokenlist.json` (integrity helper; release workflow regenerates on tag).
### Changed
- V2 **`extensions`**: removed long `ipfs://` URI strings from the JSON list (Uniswap schema length); on-chain `tokenURI` remains canonical per contract docs.
- Display **`name`** fields aligned with on-chain token metadata where verify surfaced drift.
- Gas rows: transport fields only under **`extensions`**; EIP-55 on all affected addresses; tag **`gasnative`** (replaces hyphenated tag id for schema).
### Security
- **`verify-on-chain.js`**: oracle ABI only for **`pricefeed`**-tagged rows; **LINK** verified as ERC-20; canonical **WETH9** decimals mismatch downgraded to warning when list keeps 18 for UX.
---
## [1.7.3] - 2026-04-14
### Changed
- Uniswap schema compliance sweep (tags ≤10 chars, no extra top-level token properties, root tag map keys).
---
[1.1.0]: https://github.com/dbis/token-lists/releases/tag/v1.1.0
[1.7.3]: https://github.com/Order-of-Hospitallers/proxmox-cp/releases
[1.7.4]: https://github.com/Order-of-Hospitallers/proxmox-cp/releases

View File

@@ -0,0 +1 @@
6beddb60a7c8a355bb5b5ac02aed82c701323c07ce0c216b3e3370a5f6e6c6ef dbis-138.tokenlist.json

View File

@@ -41,20 +41,16 @@
},
{
"chainId": 42161,
"address": "0xe27be001bc55cb2a8ed5ba5a62c834ca135244a3",
"address": "0xE27bE001BC55cb2a8ED5Ba5A62C834cA135244a3",
"name": "Wrapped Ethereum L2 Gas (Compliant)",
"symbol": "cWETHL2",
"familyKey": "eth_l2",
"canonicalSymbol": "cETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -76,9 +72,9 @@
"name": "Wrapped",
"description": "Wrapped tokens representing native assets"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -41,20 +41,16 @@
},
{
"chainId": 43114,
"address": "0xe1d4aee2ef8f48a20338935188a8fe7f7c7de7d0",
"address": "0xE1D4Aee2ef8f48A20338935188A8fe7f7c7dE7d0",
"name": "Wrapped AVAX Gas (Compliant)",
"symbol": "cWAVAX",
"familyKey": "avax",
"canonicalSymbol": "cAVAX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -76,9 +72,9 @@
"name": "Wrapped",
"description": "Wrapped tokens representing native assets"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -138,20 +138,16 @@
},
{
"chainId": 25,
"address": "0x9b10eb0f77c45322dbd1fcb07176fd9a7609c164",
"address": "0x9b10eB0f77c45322DBd1fCb07176Fd9A7609c164",
"name": "Wrapped CRO Gas (Compliant)",
"symbol": "cWCRO",
"familyKey": "cro",
"canonicalSymbol": "cCRO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -189,9 +185,9 @@
"name": "CCIP",
"description": "Cross Chain Interoperability Protocol tokens"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -3,9 +3,9 @@
"version": {
"major": 1,
"minor": 7,
"patch": 1
"patch": 4
},
"timestamp": "2026-04-05T23:30:00.000Z",
"timestamp": "2026-04-14T22:00:00.000Z",
"keywords": [
"dbis",
"chain138",
@@ -65,7 +65,7 @@
{
"chainId": 138,
"address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22",
"name": "Compliant Tether USD",
"name": "Tether USD (Compliant)",
"symbol": "cUSDT",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDT.png",
@@ -84,7 +84,7 @@
{
"chainId": 138,
"address": "0x9FBfab33882Efe0038DAa608185718b772EE5660",
"name": "Compliant Tether USD V2",
"name": "Tether USD (Compliant V2)",
"symbol": "cUSDT",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDT.png",
@@ -94,23 +94,20 @@
"compliant",
"v2",
"x402",
"forward-canonical"
"fwdcanon"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v2",
"forwardCanonical": true,
"x402Ready": true,
"explorerLabel": "Chain 138 cUSDT V2 (forward-canonical)",
"metadataURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdt-v2/metadata.json",
"regulatoryDisclosureURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdt-v2/regulatory-disclosure.json",
"reportingURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdt-v2/reporting.json"
"explorerLabel": "Chain 138 cUSDT V2 forward canonical"
}
},
{
"chainId": 138,
"address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b",
"name": "Compliant USD Coin",
"name": "USD Coin (Compliant)",
"symbol": "cUSDC",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDC.png",
@@ -129,7 +126,7 @@
{
"chainId": 138,
"address": "0x219522c60e83dEe01FC5b0329d6fA8fD84b9D13d",
"name": "Compliant USD Coin V2",
"name": "USD Coin (Compliant V2)",
"symbol": "cUSDC",
"decimals": 6,
"logoURI": "https://explorer.d-bis.org/token-icons/cUSDC.png",
@@ -139,19 +136,40 @@
"compliant",
"v2",
"x402",
"forward-canonical"
"fwdcanon"
],
"extensions": {
"currencyCode": "USD",
"gruVersion": "v2",
"forwardCanonical": true,
"x402Ready": true,
"explorerLabel": "Chain 138 cUSDC V2 (forward-canonical)",
"metadataURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdc-v2/metadata.json",
"regulatoryDisclosureURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdc-v2/regulatory-disclosure.json",
"reportingURI": "ipfs://QmNQ61ABKhBPsZY2UEE7fPbMdV6EUWJxWyML2eWXLn2d9M/cusdc-v2/reporting.json"
"explorerLabel": "Chain 138 cUSDC V2 forward canonical"
}
},
{
"chainId": 138,
"address": "0x71D6687F38b93CCad569Fa6352c876eea967201b",
"name": "USD Coin (Chain 138)",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 138,
"address": "0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1",
"name": "Tether USD (Chain 138)",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 138,
"address": "0x8085961F9cF02b4d800A3c6d386D31da4B34266a",
@@ -290,19 +308,15 @@
},
{
"chainId": 138,
"address": "0xf8e9802a1766422e33a269556ad5fc032338eefc",
"address": "0xF8e9802a1766422e33a269556AD5fC032338EeFc",
"name": "Ethereum Mainnet Gas (Compliant)",
"symbol": "cETH",
"familyKey": "eth_mainnet",
"mirroredSymbol": "cWETH",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -316,19 +330,15 @@
},
{
"chainId": 138,
"address": "0x18a6b163d255cc0cb32b99697843b487d059907d",
"address": "0x18A6B163d255cC0Cb32B99697843b487D059907d",
"name": "Ethereum L2 Gas (Compliant)",
"symbol": "cETHL2",
"familyKey": "eth_l2",
"mirroredSymbol": "cWETHL2",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_fungible_inventory_gated",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -342,19 +352,15 @@
},
{
"chainId": 138,
"address": "0x94517875f32680984a5921da7abf78e22f65d70f",
"address": "0x94517875f32680984a5921DA7abf78E22f65d70F",
"name": "BNB Gas (Compliant)",
"symbol": "cBNB",
"familyKey": "bnb",
"mirroredSymbol": "cWBNB",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -368,19 +374,15 @@
},
{
"chainId": 138,
"address": "0x19fec21edede9edb91d1fbec7c4095c5ac1fc10c",
"address": "0x19fec21eDedE9EdB91D1FbeC7C4095C5Ac1FC10c",
"name": "Polygon Gas (Compliant)",
"symbol": "cPOL",
"familyKey": "pol",
"mirroredSymbol": "cWPOL",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -394,19 +396,15 @@
},
{
"chainId": 138,
"address": "0x9c8f6f4fe1e535e6f85a78ee95249ded5540a2d0",
"address": "0x9c8f6F4fe1e535e6F85a78Ee95249deD5540A2D0",
"name": "Avalanche Gas (Compliant)",
"symbol": "cAVAX",
"familyKey": "avax",
"mirroredSymbol": "cWAVAX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -420,19 +418,15 @@
},
{
"chainId": 138,
"address": "0xfb48bb6c623571f9795b535b73f0d660e8643fd4",
"address": "0xFb48bb6c623571F9795B535B73f0D660E8643fd4",
"name": "Cronos Gas (Compliant)",
"symbol": "cCRO",
"familyKey": "cro",
"mirroredSymbol": "cWCRO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -446,19 +440,15 @@
},
{
"chainId": 138,
"address": "0xa39a59138f8a45b4a31455875b8a29ff31e76ec8",
"address": "0xA39A59138F8a45b4a31455875b8A29FF31E76Ec8",
"name": "Gnosis Gas (Compliant)",
"symbol": "cXDAI",
"familyKey": "xdai",
"mirroredSymbol": "cWXDAI",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/xdai/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -472,19 +462,15 @@
},
{
"chainId": 138,
"address": "0x1814661dae0933bf397b1274f5a62411b94195c7",
"address": "0x1814661DAE0933Bf397b1274f5a62411B94195C7",
"name": "Celo Gas (Compliant)",
"symbol": "cCELO",
"familyKey": "celo",
"mirroredSymbol": "cWCELO",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/celo/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -498,19 +484,15 @@
},
{
"chainId": 138,
"address": "0x4d82206bec5b4dfa17759ffede07e35f4f63a050",
"address": "0x4D82206BeC5B4Dfa17759FFEDE07E35f4f63a050",
"name": "Wemix Gas (Compliant)",
"symbol": "cWEMIX",
"familyKey": "wemix",
"mirroredSymbol": "cWWEMIX",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/wemix/info/logo.png",
"backingMode": "hybrid_cap",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -564,9 +546,13 @@
"name": "Staged",
"description": "Deployed and discoverable, not yet canonical"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
"fwdcanon": {
"name": "Forward canonical",
"description": "GRU v2 forward canonical token variant"
},
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -232,20 +232,16 @@
},
{
"chainId": 1,
"address": "0xf6dc5587e18f27adff60e303fdd98f35b50fa8a5",
"address": "0xf6dC5587e18F27Adff60E303fDD98F35b50FA8a5",
"name": "Wrapped Ethereum Mainnet Gas (Compliant)",
"symbol": "cWETH",
"familyKey": "eth_mainnet",
"canonicalSymbol": "cETH",
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
"backingMode": "strict_escrow",
"redeemPolicy": "family_only",
"decimals": 18,
"tags": [
"defi",
"compliant",
"wrapped",
"gas-native"
"gasnative"
],
"extensions": {
"assetClass": "gas_native",
@@ -283,9 +279,9 @@
"name": "CCIP",
"description": "Assets related to CCIP and bridge infrastructure"
},
"gas-native": {
"name": "Gas Native",
"description": "Gas-native compliant families and wrapped gas mirrors"
"gasnative": {
"name": "Gas native",
"description": "Gas native compliant families and wrapped gas mirrors"
}
}
}

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Regenerate SHA256SUMS for dbis-138 (matches release.yml "Generate checksums" step).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LISTS_DIR="$(cd "$SCRIPT_DIR/../lists" && pwd)"
cd "$LISTS_DIR"
sha256sum dbis-138.tokenlist.json > SHA256SUMS
echo "Wrote $LISTS_DIR/SHA256SUMS"
cat SHA256SUMS

View File

@@ -87,10 +87,21 @@ async function verifyERC20Token(provider, token, index) {
try {
const onChainDecimals = await contract.decimals();
if (Number(onChainDecimals) !== token.decimals) {
results.push({
type: 'error',
message: `${prefix}: Decimals mismatch - list: ${token.decimals}, on-chain: ${onChainDecimals}`
});
const wethNineCanonical =
token.address?.toLowerCase() === '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
if (wethNineCanonical && token.decimals === 18) {
results.push({
type: 'warning',
message:
`${prefix}: Decimals differ (list: ${token.decimals}, on-chain: ${onChainDecimals}) — ` +
'list keeps 18 for canonical WETH9 UX; on-chain may be bridge placeholder metadata'
});
} else {
results.push({
type: 'error',
message: `${prefix}: Decimals mismatch - list: ${token.decimals}, on-chain: ${onChainDecimals}`
});
}
} else {
results.push({ type: 'success', message: `${prefix}: Decimals verified (${token.decimals})` });
}
@@ -184,7 +195,8 @@ async function verifyOracleToken(provider, token, index) {
}
function isOracleToken(token) {
return token.tags && (token.tags.includes('oracle') || token.tags.includes('pricefeed'));
// Only true price-feed contracts (e.g. ETH-USD). LINK uses ERC-20 surface and must not use ORACLE_ABI.
return Array.isArray(token.tags) && token.tags.includes('pricefeed');
}
async function verifyOnChain(filePath, required = false) {