Compare commits
3 Commits
docs/explo
...
chore/igno
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abfca65342 | ||
|
|
8511bf092b | ||
|
|
dc21a3f302 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -68,6 +68,7 @@ out/
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
.tmp-*.cjs
|
||||
|
||||
# Environment backup files (Security: Prevent committing backup files with secrets)
|
||||
*.env.backup
|
||||
@@ -97,6 +98,10 @@ reports/status/live_inventory_*.json
|
||||
reports/status/hardware_poll_*.txt
|
||||
reports/status/lxc_cluster_health_*.json
|
||||
reports/status/lxc_cluster_health_*.txt
|
||||
reports/status/*runtime-env*.env
|
||||
reports/status/*operator-rpcs*.env
|
||||
reports/status/*_runtime.env
|
||||
reports/status/*.tar.gz
|
||||
|
||||
# Wormhole AI docs mirror (sync with scripts/doc/sync-wormhole-ai-resources.sh; keep manifest.json committable)
|
||||
third-party/wormhole-ai-docs/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
## Chain 138 Blockscout Route and Flash Lineage Report
|
||||
|
||||
Date: 2026-04-16
|
||||
|
||||
### Summary
|
||||
|
||||
- The Chain `138` Blockscout publication set is now fully closed.
|
||||
- `dodo_v3_core`, `flash_infra`, `native_v2`, and `route_execution_stack` are all `verified` on the public explorer.
|
||||
- The historical route and flash deployments were not produced by the current local default build outputs.
|
||||
- The exact recovered historical source/build profile for the deployed route and flash families is:
|
||||
- source family rooted at commit `6817f53`
|
||||
- compiler `solc 0.8.20`
|
||||
- `evm_version = london`
|
||||
- `optimizer_runs = 200`
|
||||
- `via_ir = false`
|
||||
|
||||
### Important provenance note
|
||||
|
||||
The Foundry broadcast files for the route and flash deployments record:
|
||||
|
||||
- `commit: 7678218`
|
||||
|
||||
That field is not the true source commit for the deployed route and flash contract families.
|
||||
|
||||
The exact source lineage was recovered by:
|
||||
|
||||
1. tracing the relevant contract families through `git log`
|
||||
2. testing historical worktrees directly
|
||||
3. comparing candidate creation bytecode plus ABI-encoded constructor args against the original broadcast `transaction.input`
|
||||
|
||||
Recovered deployment family:
|
||||
|
||||
- `6817f53`
|
||||
|
||||
### Route execution lineage
|
||||
|
||||
Broadcast files:
|
||||
|
||||
- `smom-dbis-138/broadcast/DeployEnhancedSwapRouterV2.s.sol/138/run-latest.json`
|
||||
- `smom-dbis-138/broadcast/DeployEnhancedSwapRouterV2.s.sol/138/run-1775195187069.json`
|
||||
|
||||
Recovered historical build/profile:
|
||||
|
||||
- source root: `6817f53`
|
||||
- compiler: `0.8.20`
|
||||
- `evm_version = london`
|
||||
- `optimizer_runs = 200`
|
||||
- `via_ir = false`
|
||||
|
||||
Recovered live lineage and publication outcome:
|
||||
|
||||
- `EnhancedSwapRouterV2`
|
||||
- address: `0xF1c93F54A5C2fc0d7766Ccb0Ad8f157DFB4C99Ce`
|
||||
- create tx: `0x30e68f519243377006e93dd82823305729a1ede5f03e744e27e5d57c7b6766a7`
|
||||
- exact historical creation bytecode/input match: yes
|
||||
- explorer verification: `verified`
|
||||
- `IntentBridgeCoordinatorV2`
|
||||
- address: `0x7D0022B7e8360172fd9C0bB6778113b7Ea3674E7`
|
||||
- create tx: `0x73fc5f883eda73370e3a4f0d800453e095cee07ef5f37793ed4576f47b4fa5fb`
|
||||
- exact historical creation bytecode/input match: yes
|
||||
- explorer verification: `verified`
|
||||
- `DodoRouteExecutorAdapter`
|
||||
- address: `0x88495B3dccEA93b0633390fDE71992683121Fa62`
|
||||
- create tx: `0xc574dde65e90421ed1ff5600c1f9dd71a6b8afb5a1b8416b1dde38bd2961120c`
|
||||
- exact historical runtime lineage match used as canary: yes
|
||||
- explorer verification: `verified`
|
||||
- `DodoV3RouteExecutorAdapter`
|
||||
- address: `0x9Cb97adD29c52e3B81989BcA2E33D46074B530eF`
|
||||
- explorer verification: `verified`
|
||||
- `UniswapV3RouteExecutorAdapter`
|
||||
- address: `0x960D6db4E78705f82995690548556fb2266308EA`
|
||||
- explorer verification: `verified`
|
||||
- `BalancerRouteExecutorAdapter`
|
||||
- address: `0x4E1B71B69188Ab45021c797039b4887a4924157A`
|
||||
- explorer verification: `verified`
|
||||
- `CurveRouteExecutorAdapter`
|
||||
- address: `0x5f0E07071c41ACcD2A1b1032D3bd49b323b9ADE6`
|
||||
- explorer verification: `verified`
|
||||
- `OneInchRouteExecutorAdapter`
|
||||
- address: `0x8168083d29b3293F215392A49D16e7FeF4a02600`
|
||||
- explorer verification: `verified`
|
||||
- `Chain138PilotUniswapV3Router`
|
||||
- address: `0xD164D9cCfAcf5D9F91698f296aE0cd245D964384`
|
||||
- explorer verification: `verified`
|
||||
- `Chain138PilotBalancerVault`
|
||||
- address: `0x96423d7C1727698D8a25EbFB88131e9422d1a3C3`
|
||||
- explorer verification: `verified`
|
||||
- `Chain138PilotCurve3Pool`
|
||||
- address: `0xE440Ec15805BE4C7BabCD17A63B8C8A08a492e0f`
|
||||
- explorer verification: `verified`
|
||||
- `Chain138PilotOneInchAggregationRouter`
|
||||
- address: `0x500B84b1Bc6F59C1898a5Fe538eA20A758757A4F`
|
||||
- explorer verification: `verified`
|
||||
|
||||
### Flash-infrastructure lineage
|
||||
|
||||
Broadcast file:
|
||||
|
||||
- `smom-dbis-138/broadcast/DeployCrossChainFlashInfrastructure.s.sol/138/run-latest.json`
|
||||
|
||||
Recovered historical build/profile:
|
||||
|
||||
- source root: `6817f53`
|
||||
- compiler: `0.8.20`
|
||||
- `evm_version = london`
|
||||
- `optimizer_runs = 200`
|
||||
- `via_ir = false`
|
||||
|
||||
Recovered live lineage and publication outcome:
|
||||
|
||||
- `UniversalCCIPFlashBridgeAdapter`
|
||||
- address: `0xBe9e0B2d4cF6A3b2994d6f2f0904D2B165eB8ffC`
|
||||
- create tx: `0x8cc4ba611a3d0a6e880f9e21f6390f67aadd6a234df1dc2828788ad775849844`
|
||||
- exact historical creation bytecode/input match: yes
|
||||
- explorer verification: `verified`
|
||||
- `CrossChainFlashRepayReceiver`
|
||||
- address: `0xD084b68cB4B1ef2cBA09CF99FB1B6552fd9b4859`
|
||||
- create tx: `0xf1fc28c10956cf368ebfc3d1cdd3150caf8aceacae86964f547a91e66a801e33`
|
||||
- exact historical creation bytecode/input match: yes
|
||||
- explorer verification: `verified`
|
||||
- `CrossChainFlashVaultCreditReceiver`
|
||||
- address: `0x89F7a1fcbBe104BeE96Da4b4b6b7d3AF85f7E661`
|
||||
- create tx: `0x085e1cad6e8fbe6642db420563b7b75194a88ec6649fae99cd940c2a894ec1ad`
|
||||
- exact historical creation bytecode/input match: yes
|
||||
- explorer verification: `verified`
|
||||
|
||||
### DODO publication status
|
||||
|
||||
The earlier Blockscout insert/materialization blocker is closed.
|
||||
|
||||
Published now:
|
||||
|
||||
- `D3Oracle`
|
||||
- `D3Vault`
|
||||
- `DODOApprove`
|
||||
- `DODOApproveProxy`
|
||||
- `D3MMFactory`
|
||||
- `D3Proxy`
|
||||
|
||||
All six `dodo_v3_core` contracts are fully verified on the public explorer.
|
||||
|
||||
### Current truthful end state
|
||||
|
||||
- `dodo_v3_core`: `6/6 verified`
|
||||
- `flash_infra`: `3/3 verified`
|
||||
- `native_v2`: `4/4 verified`
|
||||
- `route_execution_stack`: `12/12 verified`
|
||||
|
||||
The historical build/profile recovery work is complete for the deployed route contracts and flash trio, and the dedicated verifiers have now been rerun successfully against those recovered artifacts.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Chain 138 Deployed Smart Contract Verification Status
|
||||
|
||||
This report is generated from the canonical Chain `138` inventory in `config/smart-contracts-master.json`, on-chain bytecode checks against the Core RPC, and Blockscout smart-contract metadata from the internal explorer API.
|
||||
|
||||
## Summary
|
||||
|
||||
| Group | Total | Deployed | Verified | Bytecode only | Pending |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| `dodo_v3_core` | 6 | 6 | 6 | 0 | 0 |
|
||||
| `flash_infra` | 3 | 3 | 3 | 0 | 0 |
|
||||
| `native_v2` | 4 | 4 | 4 | 0 | 0 |
|
||||
| `route_execution_stack` | 12 | 12 | 12 | 0 | 0 |
|
||||
|
||||
## Inventory
|
||||
|
||||
| Group | Label | Address | Deployed | Verification | Blockscout name | Compiler |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `dodo_v3_core` | `D3Oracle` | `0xD7459aEa8bB53C83a1e90262777D730539A326F0` | yes | `verified` | `D3Oracle` | `v0.8.16+commit.07a7930e` |
|
||||
| `dodo_v3_core` | `D3Vault` | `0x42b6867260Fb9eE6d09B7E0233A1fAD65D0133D1` | yes | `verified` | `D3Vault` | `v0.8.16+commit.07a7930e` |
|
||||
| `dodo_v3_core` | `DODOApprove` | `0xbF8D5CB7E8F333CA686a27374Ae06F5dfd772E9E` | yes | `verified` | `DODOApprove` | `v0.8.16+commit.07a7930e` |
|
||||
| `dodo_v3_core` | `DODOApproveProxy` | `0x08d764c03C42635d8ef9046752b5694243E21Fe9` | yes | `verified` | `DODOApproveProxy` | `v0.8.16+commit.07a7930e` |
|
||||
| `dodo_v3_core` | `D3MMFactory` | `0x78470C7d2925B6738544E2DD4FE7c07CcA21AC31` | yes | `verified` | `D3MMFactory` | `v0.8.16+commit.07a7930e` |
|
||||
| `dodo_v3_core` | `D3Proxy` | `0xc9a11abB7C63d88546Be24D58a6d95e3762cB843` | yes | `verified` | `D3Proxy` | `v0.8.16+commit.07a7930e` |
|
||||
| `flash_infra` | `UniversalCCIPFlashBridgeAdapter` | `0xBe9e0B2d4cF6A3b2994d6f2f0904D2B165eB8ffC` | yes | `verified` | `UniversalCCIPFlashBridgeAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `flash_infra` | `CrossChainFlashRepayReceiver` | `0xD084b68cB4B1ef2cBA09CF99FB1B6552fd9b4859` | yes | `verified` | `CrossChainFlashRepayReceiver` | `v0.8.20+commit.a1b79de6` |
|
||||
| `flash_infra` | `CrossChainFlashVaultCreditReceiver` | `0x89F7a1fcbBe104BeE96Da4b4b6b7d3AF85f7E661` | yes | `verified` | `CrossChainFlashVaultCreditReceiver` | `v0.8.20+commit.a1b79de6` |
|
||||
| `native_v2` | `UniswapV2Factory` | `0x0C30F6e67Ab3667fCc2f5CEA8e274ef1FB920279` | yes | `verified` | `UniswapV2Factory` | `v0.5.16+commit.9c3226ce` |
|
||||
| `native_v2` | `UniswapV2Router` | `0x3019A7fDc76ba7F64F18d78e66842760037ee638` | yes | `verified` | `UniswapV2Router02` | `v0.6.6+commit.6c089d02` |
|
||||
| `native_v2` | `SushiSwapFactory` | `0x2871207ff0d56089D70c0134d33f1291B6Fce0BE` | yes | `verified` | `UniswapV2Factory` | `v0.6.12+commit.27d51765` |
|
||||
| `native_v2` | `SushiSwapRouter` | `0xB37b93D38559f53b62ab020A14919f2630a1aE34` | yes | `verified` | `UniswapV2Router02` | `v0.6.12+commit.27d51765` |
|
||||
| `route_execution_stack` | `EnhancedSwapRouterV2` | `0xF1c93F54A5C2fc0d7766Ccb0Ad8f157DFB4C99Ce` | yes | `verified` | `EnhancedSwapRouterV2` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `IntentBridgeCoordinatorV2` | `0x7D0022B7e8360172fd9C0bB6778113b7Ea3674E7` | yes | `verified` | `IntentBridgeCoordinatorV2` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `DodoRouteExecutorAdapter` | `0x88495B3dccEA93b0633390fDE71992683121Fa62` | yes | `verified` | `DodoRouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `DodoV3RouteExecutorAdapter` | `0x9Cb97adD29c52e3B81989BcA2E33D46074B530eF` | yes | `verified` | `DodoV3RouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `UniswapV3RouteExecutorAdapter` | `0x960D6db4E78705f82995690548556fb2266308EA` | yes | `verified` | `UniswapV3RouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `BalancerRouteExecutorAdapter` | `0x4E1B71B69188Ab45021c797039b4887a4924157A` | yes | `verified` | `BalancerRouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `CurveRouteExecutorAdapter` | `0x5f0E07071c41ACcD2A1b1032D3bd49b323b9ADE6` | yes | `verified` | `CurveRouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `OneInchRouteExecutorAdapter` | `0x8168083d29b3293F215392A49D16e7FeF4a02600` | yes | `verified` | `OneInchRouteExecutorAdapter` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `PilotUniswapV3Router` | `0xD164D9cCfAcf5D9F91698f296aE0cd245D964384` | yes | `verified` | `Chain138PilotUniswapV3Router` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `PilotBalancerVault` | `0x96423d7C1727698D8a25EbFB88131e9422d1a3C3` | yes | `verified` | `Chain138PilotBalancerVault` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `PilotCurve3Pool` | `0xE440Ec15805BE4C7BabCD17A63B8C8A08a492e0f` | yes | `verified` | `Chain138PilotCurve3Pool` | `v0.8.20+commit.a1b79de6` |
|
||||
| `route_execution_stack` | `PilotOneInchRouter` | `0x500B84b1Bc6F59C1898a5Fe538eA20A758757A4F` | yes | `verified` | `Chain138PilotOneInchAggregationRouter` | `v0.8.20+commit.a1b79de6` |
|
||||
|
||||
## Notes
|
||||
|
||||
- `verified` means Blockscout currently exposes both a contract name and compiler version.
|
||||
- `bytecode-only` means the address is known to the explorer, but source metadata has not materialized yet.
|
||||
- `pending` means the contract is deployed in the canonical inventory, but the current Blockscout API response does not yet expose verification metadata.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "D3Oracle",
|
||||
"address": "0xD7459aEa8bB53C83a1e90262777D730539A326F0",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "D3Oracle",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "D3Vault",
|
||||
"address": "0x42b6867260Fb9eE6d09B7E0233A1fAD65D0133D1",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "D3Vault",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "DODOApprove",
|
||||
"address": "0xbF8D5CB7E8F333CA686a27374Ae06F5dfd772E9E",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "DODOApprove",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "DODOApproveProxy",
|
||||
"address": "0x08d764c03C42635d8ef9046752b5694243E21Fe9",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "DODOApproveProxy",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "D3MMFactory",
|
||||
"address": "0x78470C7d2925B6738544E2DD4FE7c07CcA21AC31",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "D3MMFactory",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "dodo_v3_core",
|
||||
"label": "D3Proxy",
|
||||
"address": "0xc9a11abB7C63d88546Be24D58a6d95e3762cB843",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "D3Proxy",
|
||||
"compilerVersion": "v0.8.16+commit.07a7930e"
|
||||
},
|
||||
{
|
||||
"group": "flash_infra",
|
||||
"label": "UniversalCCIPFlashBridgeAdapter",
|
||||
"address": "0xBe9e0B2d4cF6A3b2994d6f2f0904D2B165eB8ffC",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniversalCCIPFlashBridgeAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "flash_infra",
|
||||
"label": "CrossChainFlashRepayReceiver",
|
||||
"address": "0xD084b68cB4B1ef2cBA09CF99FB1B6552fd9b4859",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "CrossChainFlashRepayReceiver",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "flash_infra",
|
||||
"label": "CrossChainFlashVaultCreditReceiver",
|
||||
"address": "0x89F7a1fcbBe104BeE96Da4b4b6b7d3AF85f7E661",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "CrossChainFlashVaultCreditReceiver",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "native_v2",
|
||||
"label": "UniswapV2Factory",
|
||||
"address": "0x0C30F6e67Ab3667fCc2f5CEA8e274ef1FB920279",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniswapV2Factory",
|
||||
"compilerVersion": "v0.5.16+commit.9c3226ce"
|
||||
},
|
||||
{
|
||||
"group": "native_v2",
|
||||
"label": "UniswapV2Router",
|
||||
"address": "0x3019A7fDc76ba7F64F18d78e66842760037ee638",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniswapV2Router02",
|
||||
"compilerVersion": "v0.6.6+commit.6c089d02"
|
||||
},
|
||||
{
|
||||
"group": "native_v2",
|
||||
"label": "SushiSwapFactory",
|
||||
"address": "0x2871207ff0d56089D70c0134d33f1291B6Fce0BE",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniswapV2Factory",
|
||||
"compilerVersion": "v0.6.12+commit.27d51765"
|
||||
},
|
||||
{
|
||||
"group": "native_v2",
|
||||
"label": "SushiSwapRouter",
|
||||
"address": "0xB37b93D38559f53b62ab020A14919f2630a1aE34",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniswapV2Router02",
|
||||
"compilerVersion": "v0.6.12+commit.27d51765"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "EnhancedSwapRouterV2",
|
||||
"address": "0xF1c93F54A5C2fc0d7766Ccb0Ad8f157DFB4C99Ce",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "EnhancedSwapRouterV2",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "IntentBridgeCoordinatorV2",
|
||||
"address": "0x7D0022B7e8360172fd9C0bB6778113b7Ea3674E7",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "IntentBridgeCoordinatorV2",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "DodoRouteExecutorAdapter",
|
||||
"address": "0x88495B3dccEA93b0633390fDE71992683121Fa62",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "DodoRouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "DodoV3RouteExecutorAdapter",
|
||||
"address": "0x9Cb97adD29c52e3B81989BcA2E33D46074B530eF",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "DodoV3RouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "UniswapV3RouteExecutorAdapter",
|
||||
"address": "0x960D6db4E78705f82995690548556fb2266308EA",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "UniswapV3RouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "BalancerRouteExecutorAdapter",
|
||||
"address": "0x4E1B71B69188Ab45021c797039b4887a4924157A",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "BalancerRouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "CurveRouteExecutorAdapter",
|
||||
"address": "0x5f0E07071c41ACcD2A1b1032D3bd49b323b9ADE6",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "CurveRouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "OneInchRouteExecutorAdapter",
|
||||
"address": "0x8168083d29b3293F215392A49D16e7FeF4a02600",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "OneInchRouteExecutorAdapter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "PilotUniswapV3Router",
|
||||
"address": "0xD164D9cCfAcf5D9F91698f296aE0cd245D964384",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "Chain138PilotUniswapV3Router",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "PilotBalancerVault",
|
||||
"address": "0x96423d7C1727698D8a25EbFB88131e9422d1a3C3",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "Chain138PilotBalancerVault",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "PilotCurve3Pool",
|
||||
"address": "0xE440Ec15805BE4C7BabCD17A63B8C8A08a492e0f",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "Chain138PilotCurve3Pool",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
},
|
||||
{
|
||||
"group": "route_execution_stack",
|
||||
"label": "PilotOneInchRouter",
|
||||
"address": "0x500B84b1Bc6F59C1898a5Fe538eA20A758757A4F",
|
||||
"deployed": true,
|
||||
"verificationState": "verified",
|
||||
"blockscoutName": "Chain138PilotOneInchAggregationRouter",
|
||||
"compilerVersion": "v0.8.20+commit.a1b79de6"
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"dodo_v3_core": {
|
||||
"total": 6,
|
||||
"deployed": 6,
|
||||
"verified": 6,
|
||||
"bytecode_only": 0,
|
||||
"pending": 0
|
||||
},
|
||||
"flash_infra": {
|
||||
"total": 3,
|
||||
"deployed": 3,
|
||||
"verified": 3,
|
||||
"bytecode_only": 0,
|
||||
"pending": 0
|
||||
},
|
||||
"native_v2": {
|
||||
"total": 4,
|
||||
"deployed": 4,
|
||||
"verified": 4,
|
||||
"bytecode_only": 0,
|
||||
"pending": 0
|
||||
},
|
||||
"route_execution_stack": {
|
||||
"total": 12,
|
||||
"deployed": 12,
|
||||
"verified": 12,
|
||||
"bytecode_only": 0,
|
||||
"pending": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
130
scripts/deployment/deploy-phoenix-deploy-api-to-dev-vm.sh
Executable file
130
scripts/deployment/deploy-phoenix-deploy-api-to-dev-vm.sh
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy Phoenix Deploy API to the dev VM (canonical: VMID 5700, IP_DEV_VM).
|
||||
# Installs to /opt/phoenix-deploy-api and enables systemd (see phoenix-deploy-api/scripts/install-systemd.sh).
|
||||
#
|
||||
# Layout on the workstation: repo root must contain phoenix-deploy-api/ and
|
||||
# config/public-sector-program-manifest.json (copied into /opt by install-systemd).
|
||||
# Include phoenix-deploy-api/.env in your tree before deploy (not committed); it is packed if present.
|
||||
#
|
||||
# Requires: LAN SSH to the Proxmox node that hosts VMID 5700 (see get_host_for_vmid in
|
||||
# scripts/lib/load-project-env.sh). Default PVE: r630-02 for 5700.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/deploy-phoenix-deploy-api-to-dev-vm.sh --dry-run
|
||||
# ./scripts/deployment/deploy-phoenix-deploy-api-to-dev-vm.sh --apply
|
||||
# ./scripts/deployment/deploy-phoenix-deploy-api-to-dev-vm.sh --apply --start-ct # pct start 5700 on PVE if stopped
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || {
|
||||
echo "ERROR: load-project-env.sh not found at ${PROJECT_ROOT}/scripts/lib/load-project-env.sh" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
VMID="${PHOENIX_DEPLOY_DEV_VM_VMID:-5700}"
|
||||
PVE_HOST="${PHOENIX_DEPLOY_PVE_HOST:-$(get_host_for_vmid "$VMID")}"
|
||||
PVE_USER="${PHOENIX_DEPLOY_PVE_USER:-root}"
|
||||
SSH_OPTS="${PHOENIX_DEPLOY_SSH_OPTS:--o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new}"
|
||||
IP_DEV_VM="${IP_DEV_VM:-192.168.11.59}"
|
||||
|
||||
DRY_RUN=1
|
||||
START_CT=0
|
||||
for a in "$@"; do
|
||||
if [[ "$a" == "--apply" ]]; then DRY_RUN=0; fi
|
||||
if [[ "$a" == "--dry-run" ]]; then DRY_RUN=1; fi
|
||||
if [[ "$a" == "--start-ct" ]]; then START_CT=1; fi
|
||||
done
|
||||
|
||||
MANIFEST="${PROJECT_ROOT}/config/public-sector-program-manifest.json"
|
||||
if [[ ! -f "$MANIFEST" ]]; then
|
||||
echo "WARN: missing ${MANIFEST} — install on CT will warn; add file or fix path." >&2
|
||||
fi
|
||||
|
||||
if [[ ! -d "${PROJECT_ROOT}/phoenix-deploy-api" ]]; then
|
||||
echo "ERROR: ${PROJECT_ROOT}/phoenix-deploy-api not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=============================================="
|
||||
echo "Phoenix Deploy API → dev VM"
|
||||
echo " VMID: $VMID (expected IP: $IP_DEV_VM)"
|
||||
echo " PVE host: ${PVE_USER}@${PVE_HOST}"
|
||||
echo " Dry-run: $DRY_RUN"
|
||||
echo "=============================================="
|
||||
|
||||
REMOTE_TAR="/tmp/pda-deploy-bundle.tar.gz"
|
||||
STAGE="/tmp/proxmox-pda-stage"
|
||||
|
||||
remote_block() {
|
||||
# shellcheck disable=SC2029
|
||||
ssh $SSH_OPTS "${PVE_USER}@${PVE_HOST}" "$@"
|
||||
}
|
||||
|
||||
if [[ "$DRY_RUN" -eq 1 ]]; then
|
||||
echo "Dry-run only. Would:"
|
||||
echo " 1. tar czf (phoenix-deploy-api + config/public-sector-program-manifest.json)"
|
||||
echo " 2. scp bundle → ${PVE_USER}@${PVE_HOST}:${REMOTE_TAR}"
|
||||
echo " 3. pct push ${VMID} … /root/pda-deploy.tar.gz && pct exec ${VMID} -- install-systemd.sh"
|
||||
echo " 4. curl http://${IP_DEV_VM}:4001/health"
|
||||
echo "Optional: --start-ct starts VMID ${VMID} on ${PVE_HOST} if it is stopped (pct must target a running CT)."
|
||||
echo "Re-run with --apply to execute."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP_TAR="$(mktemp /tmp/pda-deploy-XXXXXX.tar.gz)"
|
||||
cleanup() { rm -f "$TMP_TAR"; }
|
||||
trap cleanup EXIT
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
tar czf "$TMP_TAR" phoenix-deploy-api config/public-sector-program-manifest.json
|
||||
|
||||
ensure_ct_running() {
|
||||
if remote_block "pct exec ${VMID} -- true 2>/dev/null"; then
|
||||
return 0
|
||||
fi
|
||||
echo "CT ${VMID} is not running or not reachable (pct exec failed)." >&2
|
||||
if [[ "$START_CT" -eq 1 ]]; then
|
||||
echo "Starting CT ${VMID} on ${PVE_HOST} (--start-ct)..."
|
||||
if ! remote_block "pct start ${VMID}"; then
|
||||
echo "pct start failed — CT may not exist on this node. Find VMID: ssh ${PVE_USER}@${PVE_HOST} \"pct list\"" >&2
|
||||
echo "Override: PHOENIX_DEPLOY_PVE_HOST=<node-ip> PHOENIX_DEPLOY_DEV_VM_VMID=<id> $0 --apply" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 3
|
||||
if ! remote_block "pct exec ${VMID} -- true 2>/dev/null"; then
|
||||
echo "CT ${VMID} still not reachable after start." >&2
|
||||
exit 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
echo "Start the dev VM first, e.g. on ${PVE_HOST}: pct start ${VMID}" >&2
|
||||
echo "Or re-run with --apply --start-ct (scoped to this script only)." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
run_deploy() {
|
||||
ensure_ct_running
|
||||
echo "[1/3] Upload bundle to PVE..."
|
||||
scp $SSH_OPTS "$TMP_TAR" "${PVE_USER}@${PVE_HOST}:${REMOTE_TAR}"
|
||||
|
||||
echo "[2/3] pct push → CT ${VMID}, extract, install-systemd..."
|
||||
remote_block bash -s <<REMOTE_EOF
|
||||
set -euo pipefail
|
||||
pct push ${VMID} ${REMOTE_TAR} /root/pda-deploy.tar.gz
|
||||
pct exec ${VMID} -- bash -c "set -euo pipefail; rm -rf ${STAGE}; mkdir -p ${STAGE}; tar xzf /root/pda-deploy.tar.gz -C ${STAGE}; cd ${STAGE} && bash phoenix-deploy-api/scripts/install-systemd.sh; rm -f /root/pda-deploy.tar.gz"
|
||||
rm -f ${REMOTE_TAR}
|
||||
REMOTE_EOF
|
||||
|
||||
echo "[3/3] Health check on dev VM (LAN)..."
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -sS --max-time 10 -o /dev/null -w " http://${IP_DEV_VM}:4001/health → HTTP %{http_code}\n" "http://${IP_DEV_VM}:4001/health" || echo " (curl failed — check firewall or service)"
|
||||
else
|
||||
echo " (curl not installed locally; skip health check)"
|
||||
fi
|
||||
}
|
||||
|
||||
run_deploy
|
||||
echo "Done."
|
||||
@@ -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}."
|
||||
@@ -131,6 +131,7 @@ export DBIS_CORE_DIR="${DBIS_CORE_DIR:-${PROJECT_ROOT}/dbis_core}"
|
||||
# Covers: DBIS (101xx), RPC (2101-2103, 2201, 2301, etc.), Blockscout (5000), CCIP (5400-5476), NPMplus (10233, 10234), Sankofa stack (7800–7806)
|
||||
# Live placement (2026-04-09): validators 1003/1004, sentries 1503-1510, and RPCs 2102, 2301, 2304, 2400, 2402, 2403 on r630-03;
|
||||
# RPCs 2201, 2303, 2305-2308, 2401 on r630-02; 2101 + 2103 remain on r630-01 — see ALL_VMIDS_ENDPOINTS.md
|
||||
# Dev VM (GitOps / Gitea sidecar target): VMID 5700 on r630-04 (verified cluster API 2026-04-17)
|
||||
get_host_for_vmid() {
|
||||
local vmid="$1"
|
||||
case "$vmid" in
|
||||
@@ -138,7 +139,8 @@ get_host_for_vmid() {
|
||||
10130|10150|10151|106|107|108|10000|10001|10020|10100|10101|10120|10203|10233|10235) echo "${PROXMOX_HOST_R630_01}";;
|
||||
1000|1001|1002|1500|1501|1502|2101|2103) echo "${PROXMOX_HOST_R630_01}";;
|
||||
1003|1004|1503|1504|1505|1506|1507|1508|1509|1510|2102|2301|2304|2400|2402|2403) echo "${PROXMOX_HOST_R630_03}";;
|
||||
5000|5700|7810|2201|2303|2305|2306|2307|2308|2401|6200|6201|6202|6203|6204|6205|10234|10237|5800|5801) echo "${PROXMOX_HOST_R630_02}";;
|
||||
5700) echo "${PROXMOX_HOST_R630_04}";;
|
||||
5000|7810|2201|2303|2305|2306|2307|2308|2401|6200|6201|6202|6203|6204|6205|10234|10237|5800|5801) echo "${PROXMOX_HOST_R630_02}";;
|
||||
2420|2430|2440|2460|2470|2480) echo "${PROXMOX_HOST_R630_01}";;
|
||||
5400|5401|5402|5403|5410|5411|5412|5413|5414|5415|5416|5417|5418|5419|5420|5421|5422|5423|5424|5425|5440|5441|5442|5443|5444|5445|5446|5447|5448|5449|5450|5451|5452|5453|5454|5455|5470|5471|5472|5473|5474|5475|5476) echo "${PROXMOX_HOST_R630_02}";;
|
||||
*) echo "${PROXMOX_HOST_R630_01:-${PROXMOX_R630_02}}";;
|
||||
|
||||
417
scripts/verify/verify-chain138-flash-infra-blockscout.sh
Normal file
417
scripts/verify/verify-chain138-flash-infra-blockscout.sh
Normal file
@@ -0,0 +1,417 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Verify the deployed Chain 138 cross-chain flash infrastructure on Blockscout
|
||||
# using the exact Foundry deployment lineage from
|
||||
# DeployCrossChainFlashInfrastructure.s.sol.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/verify/verify-chain138-flash-infra-blockscout.sh
|
||||
# bash scripts/verify/verify-chain138-flash-infra-blockscout.sh --status-only
|
||||
# bash scripts/verify/verify-chain138-flash-infra-blockscout.sh --only UniversalCCIPFlashBridgeAdapter
|
||||
# bash scripts/verify/verify-chain138-flash-infra-blockscout.sh --force-submit
|
||||
#
|
||||
# Notes:
|
||||
# - By default this script refuses to submit when the current local Foundry
|
||||
# runtime artifact does not match the deployed Chain 138 runtime bytecode.
|
||||
# - Use --force-submit only after you intentionally decide to test a candidate
|
||||
# historical source/build lineage anyway.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM_SOURCE_ROOT="${CHAIN138_VERIFY_SOURCE_ROOT:-${PROJECT_ROOT}/smom-dbis-138}"
|
||||
SMOM_BROADCAST_ROOT="${CHAIN138_VERIFY_BROADCAST_ROOT:-${PROJECT_ROOT}/smom-dbis-138}"
|
||||
FLASH_BROADCAST="${SMOM_BROADCAST_ROOT}/broadcast/DeployCrossChainFlashInfrastructure.s.sol/138/run-latest.json"
|
||||
|
||||
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; }
|
||||
|
||||
[[ -f "${FLASH_BROADCAST}" ]] || { echo "ERROR: missing broadcast ${FLASH_BROADCAST}"; 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}"
|
||||
WAIT_ATTEMPTS="${CHAIN138_FLASH_VERIFY_WAIT_ATTEMPTS:-18}"
|
||||
WAIT_SECONDS="${CHAIN138_FLASH_VERIFY_WAIT_SECONDS:-5}"
|
||||
|
||||
ONLY_LIST=""
|
||||
STATUS_ONLY=0
|
||||
NO_WAIT=0
|
||||
FORCE_SUBMIT=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 ;;
|
||||
--force-submit) FORCE_SUBMIT=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
|
||||
|
||||
log() { printf '%s\n' "$*"; }
|
||||
ok() { printf '[ok] %s\n' "$*"; }
|
||||
warn() { printf '[warn] %s\n' "$*" >&2; }
|
||||
fail() { printf '[fail] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
should_handle() {
|
||||
local name="$1"
|
||||
[[ -n "${ONLY_LIST}" ]] && [[ ",${ONLY_LIST}," != *",${name},"* ]] && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
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-flash-infra-blockscout-proxy.log 2>&1 &
|
||||
PROXY_PID=$!
|
||||
sleep 2
|
||||
proxy_listening || fail "Forge verification proxy failed to start. See /tmp/chain138-flash-infra-blockscout-proxy.log"
|
||||
}
|
||||
|
||||
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}" ]]
|
||||
}
|
||||
|
||||
wait_for_verification() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local expected_name="$3"
|
||||
local attempt json name compiler
|
||||
for (( attempt=1; attempt<=WAIT_ATTEMPTS; attempt++ )); do
|
||||
json="$(verification_status_json "${addr}")" || json=""
|
||||
name="$(jq -r '.name // empty' <<<"${json}" 2>/dev/null || true)"
|
||||
compiler="$(jq -r '.compiler_version // empty' <<<"${json}" 2>/dev/null || true)"
|
||||
if [[ -n "${name}" && -n "${compiler}" && "${name}" == "${expected_name}" ]]; then
|
||||
ok "${label} verified on Blockscout as ${name} (${compiler})."
|
||||
return 0
|
||||
fi
|
||||
sleep "${WAIT_SECONDS}"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
broadcast_commit() {
|
||||
jq -r '.commit' "${FLASH_BROADCAST}"
|
||||
}
|
||||
|
||||
broadcast_timestamp() {
|
||||
jq -r '.timestamp' "${FLASH_BROADCAST}"
|
||||
}
|
||||
|
||||
broadcast_address() {
|
||||
local name="$1"
|
||||
jq -r --arg name "${name}" '.transactions[] | select(.transactionType=="CREATE" and .contractName==$name) | .contractAddress' "${FLASH_BROADCAST}" | head -n1
|
||||
}
|
||||
|
||||
broadcast_tx_hash() {
|
||||
local name="$1"
|
||||
jq -r --arg name "${name}" '.transactions[] | select(.transactionType=="CREATE" and .contractName==$name) | .hash' "${FLASH_BROADCAST}" | head -n1
|
||||
}
|
||||
|
||||
broadcast_arg() {
|
||||
local name="$1"
|
||||
local index="$2"
|
||||
jq -r --arg name "${name}" --argjson index "${index}" '.transactions[] | select(.transactionType=="CREATE" and .contractName==$name) | .arguments[$index]' "${FLASH_BROADCAST}" | head -n1
|
||||
}
|
||||
|
||||
contract_path() {
|
||||
case "$1" in
|
||||
UniversalCCIPFlashBridgeAdapter) printf '%s' 'contracts/flash/UniversalCCIPFlashBridgeAdapter.sol:UniversalCCIPFlashBridgeAdapter' ;;
|
||||
CrossChainFlashRepayReceiver) printf '%s' 'contracts/flash/CrossChainFlashRepayReceiver.sol:CrossChainFlashRepayReceiver' ;;
|
||||
CrossChainFlashVaultCreditReceiver) printf '%s' 'contracts/flash/CrossChainFlashVaultCreditReceiver.sol:CrossChainFlashVaultCreditReceiver' ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
artifact_json_path() {
|
||||
case "$1" in
|
||||
UniversalCCIPFlashBridgeAdapter)
|
||||
if [[ -f "${SMOM_SOURCE_ROOT}/out/scopes/flash/UniversalCCIPFlashBridgeAdapter.sol/UniversalCCIPFlashBridgeAdapter.json" ]]; then
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/scopes/flash/UniversalCCIPFlashBridgeAdapter.sol/UniversalCCIPFlashBridgeAdapter.json"
|
||||
else
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/UniversalCCIPFlashBridgeAdapter.sol/UniversalCCIPFlashBridgeAdapter.json"
|
||||
fi
|
||||
;;
|
||||
CrossChainFlashRepayReceiver)
|
||||
if [[ -f "${SMOM_SOURCE_ROOT}/out/scopes/flash/CrossChainFlashRepayReceiver.sol/CrossChainFlashRepayReceiver.json" ]]; then
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/scopes/flash/CrossChainFlashRepayReceiver.sol/CrossChainFlashRepayReceiver.json"
|
||||
else
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/CrossChainFlashRepayReceiver.sol/CrossChainFlashRepayReceiver.json"
|
||||
fi
|
||||
;;
|
||||
CrossChainFlashVaultCreditReceiver)
|
||||
if [[ -f "${SMOM_SOURCE_ROOT}/out/scopes/flash/CrossChainFlashVaultCreditReceiver.sol/CrossChainFlashVaultCreditReceiver.json" ]]; then
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/scopes/flash/CrossChainFlashVaultCreditReceiver.sol/CrossChainFlashVaultCreditReceiver.json"
|
||||
else
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/CrossChainFlashVaultCreditReceiver.sol/CrossChainFlashVaultCreditReceiver.json"
|
||||
fi
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
constructor_signature() {
|
||||
printf '%s' 'constructor(address)'
|
||||
}
|
||||
|
||||
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" ]]
|
||||
}
|
||||
|
||||
creation_input_report() {
|
||||
local label="$1"
|
||||
local constructor_sig="$2"
|
||||
local constructor_arg="$3"
|
||||
local artifact_json artifact_bytecode tx_input encoded candidate candidate_keccak tx_keccak
|
||||
|
||||
artifact_json="$(artifact_json_path "${label}")" || return 2
|
||||
[[ -f "${artifact_json}" ]] || return 2
|
||||
|
||||
artifact_bytecode="$(jq -r '.bytecode.object // empty' "${artifact_json}" | tr '[:upper:]' '[:lower:]')"
|
||||
tx_input="$(jq -r --arg name "${label}" '.transactions[] | select(.transactionType=="CREATE" and .contractName==$name) | .transaction.input' "${FLASH_BROADCAST}" | head -n1 | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
[[ -n "${artifact_bytecode}" && -n "${tx_input}" ]] || return 2
|
||||
|
||||
encoded="$(cast abi-encode "${constructor_sig}" "${constructor_arg}")"
|
||||
candidate="${artifact_bytecode}${encoded#0x}"
|
||||
candidate_keccak="$(cast keccak "${candidate}")"
|
||||
tx_keccak="$(cast keccak "${tx_input}")"
|
||||
|
||||
if [[ "${candidate}" == "${tx_input}" ]]; then
|
||||
ok "${label}: recovered exact historical creation bytecode/input (${candidate_keccak})."
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "${label}: creation bytecode/input does not match recorded deployment transaction."
|
||||
warn "${label}: candidate_keccak=${candidate_keccak} tx_input_keccak=${tx_keccak}"
|
||||
return 1
|
||||
}
|
||||
|
||||
runtime_hash_report() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local constructor_sig="$3"
|
||||
local constructor_arg="$4"
|
||||
local artifact_json artifact_runtime chain_runtime artifact_keccak chain_keccak
|
||||
local immutable_count
|
||||
|
||||
artifact_json="$(artifact_json_path "${label}")" || return 2
|
||||
[[ -f "${artifact_json}" ]] || return 2
|
||||
|
||||
immutable_count="$(jq -r '(.deployedBytecode.immutableReferences // {}) | length' "${artifact_json}")"
|
||||
if [[ "${immutable_count}" != "0" ]]; then
|
||||
creation_input_report "${label}" "${constructor_sig}" "${constructor_arg}"
|
||||
return $?
|
||||
fi
|
||||
|
||||
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 2
|
||||
|
||||
artifact_keccak="$(cast keccak "${artifact_runtime}")"
|
||||
chain_keccak="$(cast keccak "${chain_runtime}")"
|
||||
|
||||
if [[ "${artifact_runtime}" != "${chain_runtime}" ]]; then
|
||||
warn "${label}: Foundry artifact runtime bytecode does not match deployed bytecode."
|
||||
warn "${label}: artifact_keccak=${artifact_keccak} chain_keccak=${chain_keccak}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
ok "${label}: current Foundry runtime bytecode matches deployed bytecode (${artifact_keccak})."
|
||||
return 0
|
||||
}
|
||||
|
||||
submit_standard_input_from_forge() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local path="$3"
|
||||
local constructor_args="$4"
|
||||
local input_file response message
|
||||
local compiler_version evm_version optimization_runs via_ir_flag artifact_json mismatch_rc
|
||||
|
||||
artifact_json="$(artifact_json_path "${label}")" || fail "${label}: missing artifact mapping"
|
||||
[[ -f "${artifact_json}" ]] || fail "${label}: missing artifact ${artifact_json}"
|
||||
|
||||
if runtime_hash_report "${label}" "${addr}" "$(constructor_signature)" "$(broadcast_arg "${label}" 0)"; then
|
||||
mismatch_rc=0
|
||||
else
|
||||
mismatch_rc=$?
|
||||
fi
|
||||
if (( mismatch_rc == 1 && FORCE_SUBMIT == 0 )); then
|
||||
warn "${label}: skipping submission because the current local artifact does not match deployed runtime bytecode."
|
||||
warn "${label}: recover the exact historical source/build lineage first, then rerun with --force-submit if you intentionally want to test a candidate."
|
||||
return 0
|
||||
fi
|
||||
|
||||
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}")"
|
||||
via_ir_flag=(--via-ir)
|
||||
if [[ "$(jq -r '.metadata.settings.viaIR // false' "${artifact_json}")" != "true" ]]; then
|
||||
via_ir_flag=()
|
||||
fi
|
||||
|
||||
input_file="$(mktemp)"
|
||||
(
|
||||
cd "${SMOM_SOURCE_ROOT}"
|
||||
forge verify-contract "${addr}" "${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=${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 encoded
|
||||
|
||||
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
|
||||
|
||||
encoded="$(cast abi-encode "$(constructor_signature)" "$(broadcast_arg "${label}" 0)")"
|
||||
submit_standard_input_from_forge "${label}" "${addr}" "${path}" "${encoded}"
|
||||
}
|
||||
|
||||
log "Chain 138 flash-infra Blockscout verification"
|
||||
log "RPC: ${RPC_URL}"
|
||||
log "Explorer API: ${BLOCKSCOUT_API_BASE}"
|
||||
log "Flash broadcast commit: $(broadcast_commit)"
|
||||
log "Flash broadcast timestamp: $(broadcast_timestamp)"
|
||||
log
|
||||
|
||||
if (( STATUS_ONLY )); then
|
||||
for label in UniversalCCIPFlashBridgeAdapter CrossChainFlashRepayReceiver CrossChainFlashVaultCreditReceiver; do
|
||||
should_handle "${label}" || continue
|
||||
addr="$(broadcast_address "${label}")"
|
||||
if is_verified "${addr}" "${label}"; then
|
||||
ok "${label} already verified on Blockscout."
|
||||
else
|
||||
warn "${label} not yet verified on Blockscout."
|
||||
fi
|
||||
runtime_hash_report "${label}" "${addr}" "$(constructor_signature)" "$(broadcast_arg "${label}" 0)" || true
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for label in UniversalCCIPFlashBridgeAdapter CrossChainFlashRepayReceiver CrossChainFlashVaultCreditReceiver; do
|
||||
should_handle "${label}" || continue
|
||||
addr="$(broadcast_address "${label}")"
|
||||
tx_hash="$(broadcast_tx_hash "${label}")"
|
||||
log "Processing ${label} at ${addr} (create tx ${tx_hash})"
|
||||
submit_best_verification "${label}" "${addr}" "$(contract_path "${label}")" "${label}"
|
||||
done
|
||||
|
||||
if (( NO_WAIT )); then
|
||||
ok "Submission pass complete; skipping wait/poll because --no-wait was passed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for label in UniversalCCIPFlashBridgeAdapter CrossChainFlashRepayReceiver CrossChainFlashVaultCreditReceiver; do
|
||||
should_handle "${label}" || continue
|
||||
addr="$(broadcast_address "${label}")"
|
||||
if is_verified "${addr}" "${label}"; then
|
||||
ok "${label} already verified on Blockscout."
|
||||
continue
|
||||
fi
|
||||
if ! wait_for_verification "${label}" "${addr}" "${label}"; then
|
||||
warn "${label} did not materialize as fully verified within the wait window."
|
||||
fi
|
||||
done
|
||||
@@ -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."
|
||||
@@ -11,7 +11,8 @@ set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
SMOM_ROOT="${PROJECT_ROOT}/smom-dbis-138"
|
||||
SMOM_SOURCE_ROOT="${CHAIN138_VERIFY_SOURCE_ROOT:-${PROJECT_ROOT}/smom-dbis-138}"
|
||||
SMOM_BROADCAST_ROOT="${CHAIN138_VERIFY_BROADCAST_ROOT:-${PROJECT_ROOT}/smom-dbis-138}"
|
||||
|
||||
if [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
@@ -28,6 +29,7 @@ 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}"
|
||||
ROUTE_BROADCAST="${SMOM_BROADCAST_ROOT}/broadcast/DeployEnhancedSwapRouterV2.s.sol/138/run-latest.json"
|
||||
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}"
|
||||
@@ -144,7 +146,7 @@ submit_verification() {
|
||||
fi
|
||||
|
||||
log "Submitting Blockscout verification for ${label} (${addr})"
|
||||
if (cd "${SMOM_ROOT}" && "${cmd[@]}" 2>&1); then
|
||||
if (cd "${SMOM_SOURCE_ROOT}" && "${cmd[@]}" 2>&1); then
|
||||
ok "${label} verification submission accepted."
|
||||
else
|
||||
warn "${label} verification submission did not complete cleanly. Check Blockscout manually."
|
||||
@@ -153,47 +155,77 @@ submit_verification() {
|
||||
|
||||
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" ;;
|
||||
EnhancedSwapRouterV2) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/EnhancedSwapRouterV2.sol/EnhancedSwapRouterV2.dbg.json" ;;
|
||||
IntentBridgeCoordinatorV2) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/IntentBridgeCoordinatorV2.sol/IntentBridgeCoordinatorV2.dbg.json" ;;
|
||||
DodoRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/DodoRouteExecutorAdapter.sol/DodoRouteExecutorAdapter.dbg.json" ;;
|
||||
DodoV3RouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/DodoV3RouteExecutorAdapter.sol/DodoV3RouteExecutorAdapter.dbg.json" ;;
|
||||
UniswapV3RouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/UniswapV3RouteExecutorAdapter.sol/UniswapV3RouteExecutorAdapter.dbg.json" ;;
|
||||
BalancerRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/BalancerRouteExecutorAdapter.sol/BalancerRouteExecutorAdapter.dbg.json" ;;
|
||||
CurveRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/CurveRouteExecutorAdapter.sol/CurveRouteExecutorAdapter.dbg.json" ;;
|
||||
OneInchRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/adapters/OneInchRouteExecutorAdapter.sol/OneInchRouteExecutorAdapter.dbg.json" ;;
|
||||
Chain138PilotUniswapV3Router) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotUniswapV3Router.dbg.json" ;;
|
||||
Chain138PilotBalancerVault) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotBalancerVault.dbg.json" ;;
|
||||
Chain138PilotCurve3Pool) printf '%s' "${SMOM_SOURCE_ROOT}/artifacts/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol/Chain138PilotCurve3Pool.dbg.json" ;;
|
||||
Chain138PilotOneInchAggregationRouter) printf '%s' "${SMOM_SOURCE_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" ;;
|
||||
EnhancedSwapRouterV2) printf '%s' "${SMOM_SOURCE_ROOT}/out/EnhancedSwapRouterV2.sol/EnhancedSwapRouterV2.json" ;;
|
||||
IntentBridgeCoordinatorV2) printf '%s' "${SMOM_SOURCE_ROOT}/out/IntentBridgeCoordinatorV2.sol/IntentBridgeCoordinatorV2.json" ;;
|
||||
DodoRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/DodoRouteExecutorAdapter.sol/DodoRouteExecutorAdapter.json" ;;
|
||||
DodoV3RouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/DodoV3RouteExecutorAdapter.sol/DodoV3RouteExecutorAdapter.json" ;;
|
||||
UniswapV3RouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/UniswapV3RouteExecutorAdapter.sol/UniswapV3RouteExecutorAdapter.json" ;;
|
||||
BalancerRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/BalancerRouteExecutorAdapter.sol/BalancerRouteExecutorAdapter.json" ;;
|
||||
CurveRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/CurveRouteExecutorAdapter.sol/CurveRouteExecutorAdapter.json" ;;
|
||||
OneInchRouteExecutorAdapter) printf '%s' "${SMOM_SOURCE_ROOT}/out/OneInchRouteExecutorAdapter.sol/OneInchRouteExecutorAdapter.json" ;;
|
||||
Chain138PilotUniswapV3Router|Chain138PilotBalancerVault|Chain138PilotCurve3Pool|Chain138PilotOneInchAggregationRouter)
|
||||
printf '%s' "${SMOM_ROOT}/out/Chain138PilotDexVenues.sol/${1}.json"
|
||||
printf '%s' "${SMOM_SOURCE_ROOT}/out/Chain138PilotDexVenues.sol/${1}.json"
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
route_broadcast_input() {
|
||||
local label="$1"
|
||||
[[ -f "${ROUTE_BROADCAST}" ]] || return 1
|
||||
jq -r --arg name "${label}" '.transactions[] | select(.transactionType=="CREATE" and .contractName==$name) | .transaction.input' "${ROUTE_BROADCAST}" | head -n1
|
||||
}
|
||||
|
||||
runtime_hash_report() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local constructor_sig="$3"
|
||||
shift 3
|
||||
local constructor_args=("$@")
|
||||
local artifact_json artifact_runtime chain_runtime
|
||||
|
||||
artifact_json="$(foundry_artifact_json_path "${label}")" || return 0
|
||||
[[ -f "${artifact_json}" ]] || return 0
|
||||
|
||||
local immutable_count
|
||||
immutable_count="$(jq -r '(.deployedBytecode.immutableReferences // {}) | length' "${artifact_json}")"
|
||||
if [[ "${immutable_count}" != "0" && -n "${constructor_sig}" ]]; then
|
||||
local bytecode tx_input encoded candidate candidate_keccak tx_keccak
|
||||
bytecode="$(jq -r '.bytecode.object // empty' "${artifact_json}" | tr '[:upper:]' '[:lower:]')"
|
||||
tx_input="$(route_broadcast_input "${label}" | tr '[:upper:]' '[:lower:]')" || tx_input=""
|
||||
if [[ -n "${bytecode}" && -n "${tx_input}" ]]; then
|
||||
encoded="$(cast abi-encode "${constructor_sig}" "${constructor_args[@]}")"
|
||||
candidate="${bytecode}${encoded#0x}"
|
||||
candidate_keccak="$(cast keccak "${candidate}")"
|
||||
tx_keccak="$(cast keccak "${tx_input}")"
|
||||
if [[ "${candidate}" == "${tx_input}" ]]; then
|
||||
ok "${label}: recovered exact historical creation bytecode/input (${candidate_keccak})."
|
||||
else
|
||||
warn "${label}: creation bytecode/input does not match recorded deployment transaction."
|
||||
warn "${label}: candidate_keccak=${candidate_keccak} tx_input_keccak=${tx_keccak}"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
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
|
||||
|
||||
@@ -291,7 +323,7 @@ PY
|
||||
rm -f "${input_file}"
|
||||
|
||||
message="$(jq -r '.message // empty' <<<"${response}")"
|
||||
if [[ "${message}" == "Smart-contract verification started" ]]; then
|
||||
if [[ "${message}" == "Smart-contract verification started" || "${message}" == "Already verified" ]]; then
|
||||
ok "${label} standard-input verification submission accepted."
|
||||
return 0
|
||||
fi
|
||||
@@ -304,7 +336,10 @@ submit_standard_input_from_forge() {
|
||||
local label="$1"
|
||||
local addr="$2"
|
||||
local contract_path="$3"
|
||||
local constructor_args="$4"
|
||||
local constructor_sig="$4"
|
||||
shift 4
|
||||
local constructor_args_raw=("$@")
|
||||
local constructor_args=""
|
||||
local input_file response message
|
||||
local compiler_version evm_version optimization_runs via_ir_flag artifact_json
|
||||
|
||||
@@ -323,10 +358,14 @@ submit_standard_input_from_forge() {
|
||||
fi
|
||||
fi
|
||||
|
||||
runtime_hash_report "${label}" "${addr}"
|
||||
if [[ -n "${constructor_sig}" ]]; then
|
||||
constructor_args="$(cast abi-encode "${constructor_sig}" "${constructor_args_raw[@]}")"
|
||||
fi
|
||||
|
||||
runtime_hash_report "${label}" "${addr}" "${constructor_sig}" "${constructor_args_raw[@]}"
|
||||
input_file="$(mktemp)"
|
||||
(
|
||||
cd "${SMOM_ROOT}"
|
||||
cd "${SMOM_SOURCE_ROOT}"
|
||||
forge verify-contract "${addr}" "${contract_path}" \
|
||||
--chain-id 138 \
|
||||
--root . \
|
||||
@@ -359,7 +398,7 @@ submit_standard_input_from_forge() {
|
||||
rm -f "${input_file}"
|
||||
|
||||
message="$(jq -r '.message // empty' <<<"${response}")"
|
||||
if [[ "${message}" == "Smart-contract verification started" ]]; then
|
||||
if [[ "${message}" == "Smart-contract verification started" || "${message}" == "Already verified" ]]; then
|
||||
ok "${label} Foundry standard-input verification submission accepted."
|
||||
return 0
|
||||
fi
|
||||
@@ -385,7 +424,7 @@ submit_best_verification() {
|
||||
# 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
|
||||
if submit_standard_input_from_forge "${label}" "${addr}" "${path}" "${constructor_sig}" "${constructor_args[@]}"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -420,6 +459,10 @@ PILOT_ONEINCH="$(jq -r '.chains["138"].contracts.PilotOneInchRouter' "${PROJECT_
|
||||
log "Chain 138 route execution stack Blockscout verification"
|
||||
log "RPC: ${RPC_URL}"
|
||||
log "Explorer API: ${BLOCKSCOUT_API_BASE}"
|
||||
if [[ -f "${ROUTE_BROADCAST}" ]]; then
|
||||
log "Route broadcast commit: $(jq -r '.commit' "${ROUTE_BROADCAST}")"
|
||||
log "Route broadcast timestamp: $(jq -r '.timestamp' "${ROUTE_BROADCAST}")"
|
||||
fi
|
||||
log
|
||||
|
||||
if (( STATUS_ONLY )); then
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user