# Blockscout Forge Verification — Fix Evaluation & Dedicated API **Date:** 2026-02-02 **Status:** Evaluation complete; dedicated proxy implemented --- ## 1. Fix Evaluation ### What Was Attempted | Change | Purpose | Result | |--------|---------|--------| | `location = /api` + `rewrite ^ /api/$is_args$args last` | Internal redirect `/api` → `/api/` to avoid 301 on POST | **Partial**: Eliminates nginx 301; does not fix API format mismatch | | `proxy_set_header Host 127.0.0.1` | Avoid Blockscout redirect when Host is IP | **Unclear**: 301 may originate elsewhere | | `VERIFIER_URL="http://${IP}/api/"` | Correct base URL per Blockscout docs | **Correct**: URL format is fine | ### Root Cause Forge sends a **single JSON body** (Etherscan-style): ```json { "contractaddress": "0x...", "sourceCode": "{\"language\":\"Solidity\",\"sources\":{...}}", "codeformat": "solidity-standard-json-input", "contractname": "CCIPSender", "compilerversion": "v0.8.20+...", ... } ``` Blockscout’s **Etherscan-compatible handler** (`/api?module=contract&action=verifysourcecode`) expects `module` and `action` in the **query string**. Forge does not add them and puts all data in the body. That produces: > `Params 'module' and 'action' are required parameters` ### Conclusion The nginx changes help routing and redirects but do **not** resolve the format mismatch. Forge’s payload is not compatible with the Etherscan-compatible RPC API. --- ## 2. Dedicated API Approach ### Blockscout v2 Smart Contract API Blockscout exposes a **v2 verification API** that accepts JSON: - **Flattened code:** `POST /api/v2/smart-contracts/{address}/verification/via/flattened-code` - **Standard JSON input:** `POST /api/v2/smart-contracts/{address}/verification/via/standard-input` This matches what Forge uses when it sends Standard JSON in `sourceCode`. ### Solution: Forge Verification Proxy A small proxy service: 1. **Accepts** Forge’s Etherscan-style JSON POST. 2. **Maps** fields to Blockscout v2 parameters. 3. **Forwards** to `/api/v2/smart-contracts/{address}/verification/via/standard-input` (or flattened). 4. **Returns** Blockscout’s response to Forge. ### Field Mapping | Forge (Etherscan) | Blockscout v2 | |-------------------|---------------| | `contractaddress` | URL path `{address}` | | `sourceCode` | `files` (standard JSON) or `source_code` (flattened) | | `codeformat` | Chooses `/via/standard-input` vs `/via/flattened-code` | | `contractname` | `contract_name` | | `compilerversion` | `compiler_version` | | `optimizationUsed` | `is_optimization_enabled` | | `runs` | `optimization_runs` | | `constructorArguments` | `constructor_args` | | `evmversion` | `evm_version` | --- ## 3. Implementation See [`forge-verification-proxy/`](../../forge-verification-proxy/) for: - Node.js/Express proxy - Field mapping and v2 API calls - Usage and deployment notes --- ## 4. Usage ```bash # 1. Start the proxy (from project root; Blockscout API at 192.168.11.140:4000) BLOCKSCOUT_URL=http://192.168.11.140:4000 node forge-verification-proxy/server.js # 2. Verify via proxy (preferred: ./scripts/verify/run-contract-verification-with-proxy.sh; or run verify-contracts-blockscout.sh) ./scripts/verify-contracts-blockscout.sh # Or directly: forge verify-contract \ --chain-id 138 \ --verifier blockscout \ --verifier-url "http://:3080/" \ --rpc-url "http://192.168.11.211:8545" ``` --- ## 5. References - [Blockscout Smart Contract Verification API v2](https://docs.blockscout.com/devs/verification/blockscout-smart-contract-verification-api) - [Blockscout Foundry Verification](https://docs.blockscout.com/devs/verification/foundry-verification) - [Etherscan RPC Contract API](https://docs.blockscout.com/devs/apis/rpc/contract) — module/action format