Summary
The testnet.arcscan.app block explorer's contract verification API does not accept submissions via any standard Blockscout format. The only working verification path is the browser UI — which doesn't scale for multi-contract or multi-chain deployments.
Reproduction
Tested with four contracts (Paymaster, GasRelayer, FeeRouter, YieldVault) compiled with:
- Solidity
0.8.20
- Optimizer: enabled, 200 runs
evmVersion: "paris"
Format 1: Blockscout v1 flat source (POST /api?module=contract&action=verifysourcecode)
curl -X POST "https://testnet.arcscan.app/api?module=contract&action=verifysourcecode" \
--data-urlencode "addressHash=0x..." \
--data-urlencode "name=Paymaster" \
--data-urlencode "codeformat=solidity-single-file" \
--data-urlencode "compilerVersion=v0.8.20+commit.a1b79de6" \
--data-urlencode "optimization=true" \
--data-urlencode "optimizationRuns=200" \
--data-urlencode "evmVersion=paris" \
--data-urlencode "contractSourceCode@Paymaster.sol"
Response: {"message":"Missing codeformat field","result":null,"status":"0"}
This error is returned even when codeformat is included in the request body. Tested with both application/x-www-form-urlencoded and multipart/form-data content types.
Format 2: Blockscout v2 JSON (POST /api/v2/smart-contracts/{address}/verification/via/flattened-code)
curl -X POST "https://testnet.arcscan.app/api/v2/smart-contracts/0x.../verification/via/flattened-code" \
-H "Content-Type: application/json" \
-d '{"compiler_version":"v0.8.20+commit.a1b79de6","contract_name":"Paymaster","files":{"Paymaster.sol":"..."},"is_optimization_enabled":true,"optimization_runs":200,"evm_version":"paris","constructor_args":"..."}'
Response: "Bad request"
Format 3: Blockscout v2 multipart
curl -X POST "https://testnet.arcscan.app/api/v2/smart-contracts/0x.../verification/via/flattened-code" \
-F "compiler_version=v0.8.20+commit.a1b79de6" \
-F "contract_name=Paymaster" \
-F "files[]=@Paymaster.sol;type=text/plain" \
-F "is_optimization_enabled=true" \
-F "optimization_runs=200" \
-F "evm_version=paris" \
-F "constructor_args=..."
Response: "Bad request"
Hardhat and Foundry
npx hardhat verify --network arcTestnet 0x...
# Error: Failed to send contract verification request.
# Endpoint URL: https://testnet.arcscan.app/api?module=contract&action=verifysourcecode
# Reason: Missing codeformat field
forge verify-contract 0x... Paymaster \
--verifier blockscout \
--verifier-url https://testnet.arcscan.app/api
# same underlying v1 error
What works
The browser UI works:
- Open
https://testnet.arcscan.app/address/{address}
- Click Contract → Verify & Publish
- Choose Solidity (Single file)
- Fill in compiler version, optimizer settings, paste source, paste constructor args
This works but requires one browser session per contract per chain — not viable for a 4-contract × 4-chain deployment.
Impact
- Builders cannot use
hardhat-verify, forge verify-contract, or custom CI scripts to verify contracts on Arc
- All four standard Blockscout API formats fail
- No verified source means no ABI auto-read in Arcscan, which blocks contract UI and read/write tabs for users
Questions
- Is programmatic API verification intentionally disabled on
testnet.arcscan.app?
- If not, what field name or format does the endpoint actually expect?
- Is there a plan to expose a working verification endpoint, or to integrate with a hosted verification service (e.g. Sourcify)?
Workaround (until fixed)
Use the Blockscout UI manually per contract. If deploying multiple contracts, keep a script that generates the ABI-encoded constructor args for each — the UI accepts a hex-encoded constructor arguments field.
import { ethers } from "ethers";
const coder = ethers.AbiCoder.defaultAbiCoder();
// Paymaster: constructor(address usdc, address relayer, address feeRecipient, uint256 gasRate)
const args = coder.encode(
["address","address","address","uint256"],
[USDC_ADDRESS, RELAYER, FEE_RECIPIENT, GAS_RATE]
).slice(2); // remove 0x prefix — paste this into the Arcscan UI
Summary
The
testnet.arcscan.appblock explorer's contract verification API does not accept submissions via any standard Blockscout format. The only working verification path is the browser UI — which doesn't scale for multi-contract or multi-chain deployments.Reproduction
Tested with four contracts (Paymaster, GasRelayer, FeeRouter, YieldVault) compiled with:
0.8.20evmVersion: "paris"Format 1: Blockscout v1 flat source (
POST /api?module=contract&action=verifysourcecode)Response:
{"message":"Missing codeformat field","result":null,"status":"0"}This error is returned even when
codeformatis included in the request body. Tested with bothapplication/x-www-form-urlencodedandmultipart/form-datacontent types.Format 2: Blockscout v2 JSON (
POST /api/v2/smart-contracts/{address}/verification/via/flattened-code)Response:
"Bad request"Format 3: Blockscout v2 multipart
Response:
"Bad request"Hardhat and Foundry
forge verify-contract 0x... Paymaster \ --verifier blockscout \ --verifier-url https://testnet.arcscan.app/api # same underlying v1 errorWhat works
The browser UI works:
https://testnet.arcscan.app/address/{address}This works but requires one browser session per contract per chain — not viable for a 4-contract × 4-chain deployment.
Impact
hardhat-verify,forge verify-contract, or custom CI scripts to verify contracts on ArcQuestions
testnet.arcscan.app?Workaround (until fixed)
Use the Blockscout UI manually per contract. If deploying multiple contracts, keep a script that generates the ABI-encoded constructor args for each — the UI accepts a hex-encoded constructor arguments field.