Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements granular allowed_diffs allowlists for both source and bytecode comparisons, replacing the blanket --allow-source-diff/--allow-bytecode-diff CLI flags. Diffs can now be declared precisely in config files with mandatory reason fields and composable facets (immutables, cbor_metadata, byte_ranges, line_ranges, files, etc.). When uncovered diffs are detected, the tool prints ready-to-paste config snippets.
Changes:
- New
allowed_diffsvalidation, evaluation, normalization, and suggestion engine indiffyscan/utils/allowed_diffs.py - Refactored bytecode analysis into structured
analyze_bytecode_diff()returning detailed mismatch information, withdeep_match_bytecode()preserved as backward-compatible wrapper - Integrated allowlist evaluation into the main source/bytecode pipelines, with suggestion output in final summary
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
diffyscan/utils/allowed_diffs.py |
New module: validation, evaluation, normalization, suggestion engine for granular allowlists |
diffyscan/utils/binary_verifier.py |
Refactored to expose analyze_bytecode_diff() and log_bytecode_diff_analysis(); normalized 0x prefix |
diffyscan/diffyscan.py |
Integrated allowlist evaluation into source/bytecode pipelines; structured result dicts; suggestion printing |
diffyscan/utils/common.py |
Config validation for allowed_diffs, boolean fields, YAML hex quoting in allowlist entries |
diffyscan/utils/custom_types.py |
TypedDict definitions for allowlist rules and missing optional Config fields |
pyproject.toml |
Added mypy + type stubs to dev deps; mypy and black config |
tests/test_allowed_diffs.py |
New comprehensive tests for allowlist validation, evaluation, and suggestions |
tests/test_config_loading.py |
Tests for allowed_diffs config validation edge cases and boolean field validation |
tests/test_binary_verifier.py |
Tests for new analyze_bytecode_diff function |
tests/*.py (other) |
Type annotation fixes for mypy compliance |
tests/fixtures/full_config.* |
Added allowed_diffs sections to test fixtures |
config_samples/**/*.json |
Replaced CLI flags with in-config allowed_diffs entries |
.github/workflows/regression.yml |
Removed flags matrix and bash flag-parsing; simplified run command |
.pre-commit-config.yaml |
Added mypy pre-commit hook |
diffyscan/utils/explorer.py, compiler.py, etc. |
Type annotation fixes for mypy compliance |
uv.lock |
Updated lock file with new dev dependencies |
README.md |
Documentation for granular allowlists feature |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| files_with_diffs = sum(row[2] and row[3] > 0 for row in report) | ||
|
|
||
| logger.report_table(report) | ||
| files_with_diffs = sum(bool(file_result["hunks"]) for file_result in file_results) |
There was a problem hiding this comment.
haha, I disagree with Copilot here
|
Self-reminder: need to rebase on the latest main and update skills |
Summary
Implements granular
allowed_diffsallowlists for both source and bytecode comparisons (closes #136).Instead of blanket
--allow-source-diff/--allow-bytecode-diffCLI flags that silently suppress all diffs for an address, diffs can now be declared precisely in config with mandatoryreasonfields and composable facets.Bytecode facets
immutables— pin expected values at exact byte offsetscbor_metadata— allow Solidity CBOR metadata hash differencesbyte_ranges— allow arbitrary byte rangesconstructor_args/constructor_calldata— override constructor parameters per-ruleany— blanket allow (also suppresses RPC simulation errors)Source facets
line_ranges— allow diffs in specific file regions (github/explorer line counts)files— allow diffs in specific filesany— blanket allowAuto-suggestions
When diffs are detected but not covered by rules, the tool prints a ready-to-paste JSON
allowed_diffssnippet with the exact facets needed. This makes adopting granular rules trivial — run once, copy the suggestion, fill in thereason.Key changes
diffyscan/utils/allowed_diffs.py(new, 660 lines)diffyscan/diffyscan.py"any"bytecode rules now suppress RPC simulation errorsdiffyscan/utils/common.pyallowed_diffsstructure, boolean fields, and YAML hex quoting for allowlist addressesdiffyscan/utils/custom_types.pyConfigTypedDict includesallowed_diffsand missing optional fieldspyproject.toml[tool.mypy]config for incremental type checking--allow-*-diffflags with precise in-configallowed_diffsentries discovered via real runs against mainnet and hoodi RPCs.github/workflows/regression.ymlflagsmatrix,DIFFYSCAN_FLAGSenv var, and bash flag-parsing; run command is now justuv run diffyscan -Y -E -G "$DIFFYSCAN_CONFIG"Config example
{ "allowed_diffs": { "bytecode": { "0xd6A6...9426": [{ "reason": "Escrow stores own deployed address as immutable", "immutables": [ {"offset": 1093, "value": "0x000...9426"}, {"offset": 6887, "value": "0x000...9426"} ] }] }, "source": { "0x8aa3...9F3": [{ "reason": "Import paths differ between GitHub and explorer-verified source", "line_ranges": [{ "file": "contracts/CuratedSubmitExitRequestHashes.sol", "github": {"start": 6, "count": 7}, "explorer": {"start": 6, "count": 7} }] }] } } }Test plan
pytest -q) — covers validation, evaluation, edge cases, suggestions, and config loadingmypy diffyscan/— 0 errors across 16 source filesallowed_diffssection and confirm the printed snippet can be pasted back to make it pass