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