Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
3.7 KiB
3.7 KiB
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):
{
"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:
- Accepts Forge’s Etherscan-style JSON POST.
- Maps fields to Blockscout v2 parameters.
- Forwards to
/api/v2/smart-contracts/{address}/verification/via/standard-input(or flattened). - 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/ for:
- Node.js/Express proxy
- Field mapping and v2 API calls
- Usage and deployment notes
4. Usage
# 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 <ADDR> <PATH> \
--chain-id 138 \
--verifier blockscout \
--verifier-url "http://<proxy-host>:3080/" \
--rpc-url "http://192.168.11.211:8545"