Validate the diffyscan config file at $ARGUMENTS (or ask for the path if not provided).
Read the config file using the Read tool. Use the TypedDict definitions in diffyscan/utils/custom_types.py as the schema reference.
Schema reference
The Config TypedDict (diffyscan/utils/custom_types.py) defines:
Required fields:
contracts—dict[str, str]mapping address to contract namenetwork—str(declared required in TypedDict but currently unused at runtime; include it for forward-compatibility)explorer_hostname—strgithub_repo—GithubRepowith required keys:url,commit,relative_root
Optional fields (NotRequired):
dependencies—dict[str, GithubRepo]explorer_token_env_var—strexplorer_chain_id—intbytecode_comparison—BinaryConfigfail_on_bytecode_comparison_error—boolsource_comparison—bool
Additional fields found in real configs but not in the TypedDict:
explorer_hostname_env_var—str(CI convention only — diffyscan does NOT resolve this at runtime; external tooling must setexplorer_hostnamebefore invoking)audit_url—strmetadata—dict(free-form project metadata)
The BinaryConfig TypedDict has all-optional fields:
hardhat_config_name—str(deprecated, ignored at runtime)constructor_calldata—dict[str, str]mapping address to raw hex calldataconstructor_args—dict[str, list]mapping address to a list of ABI-encodable argumentslibraries—dict[str, dict[str, str]]mapping source path to{LibraryName: "0xAddress"}
Checks to perform
1. Required fields
contractsmust be present and be a non-empty dictexplorer_hostnamemust be a string (or alternativelyexplorer_hostname_env_varmust be present; real configs use one or both -- seetests/test_configs.pyline 32)github_repomust be present and contain all three keys:url,commit,relative_rootnetworkis declared required in the TypedDict. Warn if missing, noting it is not used at runtime today but may be in the future
2. YAML hex coercion (what the codebase actually validates)
The function _validate_yaml_hex_keys in diffyscan/utils/common.py checks YAML configs for hex values that PyYAML silently coerced from strings to integers. It raises ValueError if any are found. Specifically it checks:
contractskeys (address) -- raises if parsed asintcontractsvalues (contract name) -- raises if parsed asintbytecode_comparison.constructor_argskeys -- raises if parsed asintbytecode_comparison.constructor_calldatakeys -- raises if parsed asintbytecode_comparison.librariesvalues (the library address strings) -- raises if parsed asint
This validation only runs for YAML files, not JSON. It only detects int coercion; it does NOT validate address format (0x prefix, 42 chars, valid hex, checksum).
3. Address format (best-practice recommendation only)
The codebase does NOT validate address format at config load time. There is no runtime check for 0x prefix, 42-character length, or hex validity on addresses in the config. Addresses are passed directly to the explorer API and RPC node.
However, the test suite (tests/test_configs.py:test_contract_addresses_format) asserts all contracts keys start with 0x and are 42 characters. Recommend the same for any address in the config:
- Contract addresses in
contractskeys - Addresses in
bytecode_comparison.constructor_calldatakeys - Addresses in
bytecode_comparison.constructor_argskeys - Library addresses in
bytecode_comparison.librariesvalues
4. Explorer configuration
- If
explorer_token_env_varis missing, the runtime warns and falls back toETHERSCAN_EXPLORER_TOKEN(see_load_explorer_tokenindiffyscan/diffyscan.py). Warn if absent. explorer_chain_idis optional; the runtime does not warn if missing (retrieved withwarn_if_missing=False)explorer_hostnameis retrieved withwarn_if_missing=True; if absent the runtime logs a warning
5. GitHub repo fields
github_repo.urlshould look like a GitHub URLgithub_repo.commitshould ideally be a full 40-character SHA hex string (warn if short or non-hex)github_repo.relative_rootcan be an empty string (commonly is for root-level repos)
6. Dependencies
- Each dependency value must have
url,commit,relative_root(sameGithubReposhape) - Dependency keys should match import path prefixes used in Solidity sources (e.g.
@openzeppelin/contracts,lib/openzeppelin-contracts-upgradeable/contracts) - The runtime resolves dependencies by checking if a source file path starts with
"{dep_name}/"(seeresolve_depindiffyscan/utils/github.py)
7. Bytecode comparison
constructor_calldatavalues should be hex strings (the runtime strips0xprefix vianormalize_calldataand validates hex content)constructor_argsvalues must be lists (arrays of ABI-encodable values)- A contract address must NOT appear in both
constructor_calldataandconstructor_args-- the runtime raisesCalldataErrorif it does (seeget_calldataindiffyscan/utils/calldata.py) librariesmaps Solidity source file paths to{LibraryName: "0xAddress"}dictshardhat_config_nameis deprecated and ignored at runtime (a warning is logged)
8. Cross-reference checks
What the runtime actually does:
- Addresses in
bytecode_comparison.constructor_calldataandconstructor_argsare looked up by contract address at runtime -- if a contract has a constructor but its address is not in either dict and the explorer has no constructor arguments, the runtime raisesCalldataError - Contracts listed in
contractsthat have no corresponding entry inbytecode_comparisonwill still work -- they fall back to explorer-provided constructor arguments - There is no compile-time cross-reference validation in the codebase; all checks happen at runtime
Recommended cross-reference warnings:
- Warn if an address appears in
constructor_calldataorconstructor_argsbut not incontracts(it would be unused) - Warn if a contract is in both
constructor_calldataandconstructor_args(runtime error)
9. Optional flags
fail_on_bytecode_comparison_errordefaults totrueif absentsource_comparisondefaults totrueif absent; set tofalseto skip source diffs
Output
Report issues in two categories:
- Errors (must fix): missing required fields, type mismatches, YAML hex coercion, duplicate entries in both
constructor_calldataandconstructor_args - Warnings (should review): missing
explorer_token_env_var, short commit SHA, addresses not matching 0x/42-char format, missingnetwork, deprecatedhardhat_config_name, unused bytecode_comparison entries
If the config looks good, confirm it passes validation.
Source: lidofinance/diffyscan — distributed by TomeVault.