Summary
The zkSync explorer fetcher (_get_contract_from_zksync in diffyscan/utils/explorer.py) returns a contract dict incompatible with downstream code, and has a key-casing inconsistency. zkSync contract verification appears to be broken (surfaced during an audit of the docs vs code).
1. Missing solcInput → KeyError downstream
The fetcher returns (explorer.py ~251-255):
contract = {
"name": data["ContractName"],
"sources": json.loads(data["sourceCode"]["sources"]),
"compiler": data["CompilerVersion"],
}
There is no solcInput key. But downstream, both:
run_source_diff → diffyscan.py:204: get_solc_sources(contract_code["solcInput"])
run_bytecode_diff → diffyscan.py:70: solc_input = contract_source_code["solcInput"]
read contract["solcInput"] unconditionally — there is no zkSync-specific branch anywhere in diffyscan.py. A verified zkSync contract reaching this path raises KeyError: 'solcInput'.
2. ContractName casing inconsistency
data = response["request"]
if "contractName" not in data: # lowercase presence check
_error_no_source_code_and_exit(contract)
contract = {
"name": data["ContractName"], # uppercase read
"compiler": data["CompilerVersion"],
...
}
The presence guard checks lowercase contractName, but the reads use ContractName / CompilerVersion. Depending on the real API casing this either always trips the "not verified / no source" branch, or raises KeyError on the read.
Impact
zkSync source/bytecode verification likely fails for every contract via this path.
Suggested next steps
- Confirm the live zkSync explorer API response shape (key casing; whether it returns standard-json solc input).
- Construct a proper
solcInput for the zkSync path (or add a downstream branch), and align the key casing.
Found via a docs-vs-code audit; not yet reproduced against a live zkSync contract.
Summary
The zkSync explorer fetcher (
_get_contract_from_zksyncindiffyscan/utils/explorer.py) returns a contract dict incompatible with downstream code, and has a key-casing inconsistency. zkSync contract verification appears to be broken (surfaced during an audit of the docs vs code).1. Missing
solcInput→ KeyError downstreamThe fetcher returns (
explorer.py~251-255):There is no
solcInputkey. But downstream, both:run_source_diff→diffyscan.py:204:get_solc_sources(contract_code["solcInput"])run_bytecode_diff→diffyscan.py:70:solc_input = contract_source_code["solcInput"]read
contract["solcInput"]unconditionally — there is no zkSync-specific branch anywhere indiffyscan.py. A verified zkSync contract reaching this path raisesKeyError: 'solcInput'.2.
ContractNamecasing inconsistencyThe presence guard checks lowercase
contractName, but the reads useContractName/CompilerVersion. Depending on the real API casing this either always trips the "not verified / no source" branch, or raisesKeyErroron the read.Impact
zkSync source/bytecode verification likely fails for every contract via this path.
Suggested next steps
solcInputfor the zkSync path (or add a downstream branch), and align the key casing.Found via a docs-vs-code audit; not yet reproduced against a live zkSync contract.