Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7304c6e
feat: add mantle meta core config
arwer13 Apr 4, 2026
4344cc7
feat: add Cancun EVM opcodes (EIP-1153, EIP-4844, EIP-5656, EIP-7516)
tamtamchik Apr 5, 2026
19813d9
feat: add --contract flag to check specific addresses
tamtamchik Apr 5, 2026
55761f1
feat: add per-config RPC URL, local RPC override, and configurable ga…
tamtamchik Apr 5, 2026
97a646c
feat: update mantle meta core config
tamtamchik Apr 5, 2026
037f203
refactor: remove skip_user_input local var, use args.yes directly
tamtamchik Apr 5, 2026
de92d2d
feat: add arbitrum meta core config
tamtamchik Apr 5, 2026
d830945
feat: add base meta configs with mainnet directory scheme
tamtamchik Apr 5, 2026
a98d7c1
chore: update .env.example with chain-specific RPC URLs
tamtamchik Apr 5, 2026
83dcece
style: apply black formatting
tamtamchik Apr 5, 2026
e0673a2
Merge branch 'main' into feat/mantle-meta-updates
tamtamchik Apr 7, 2026
fb8909e
feat: rewrite arbitrum config with new CREATE2 deployment addresses
tamtamchik Apr 7, 2026
24f8521
feat: update base SyncDepositQueue to new CREATE2 address
tamtamchik Apr 7, 2026
c74a1cb
feat: add plasma meta core config
tamtamchik Apr 7, 2026
15db6b4
feat: add earnUSDe contracts to meta USD config
tamtamchik Apr 7, 2026
56e08ed
feat: add earnUSDe plasma meta config
tamtamchik Apr 7, 2026
ed042f7
feat: add earnUSDe meta configs for Arbitrum and Mantle
tamtamchik Apr 7, 2026
099f57b
docs: update skills with troubleshooting and proxy calldata tips
tamtamchik Apr 7, 2026
f8b455b
Merge remote-tracking branch 'origin/main' into feat/mantle-meta-updates
tamtamchik Apr 14, 2026
143a149
Merge branch 'main' into feat/mantle-meta-updates
tamtamchik Apr 30, 2026
922bcac
feat: update earnUSDe meta configs with AaveOracle and SwapModule
tamtamchik Apr 30, 2026
ed1fc01
Merge remote-tracking branch 'origin/main' into feat/mantle-meta-updates
tamtamchik Jun 1, 2026
231d1a2
fix: update earnUSDe SwapModule to redeployed proxies
tamtamchik Jun 1, 2026
bab053b
fix: update earnUSDe to full redeploy
tamtamchik Jun 2, 2026
4c25dde
fix: update earnUSDe Mantle deploy to new proxies
tamtamchik Jun 2, 2026
8db5583
chore: reorder Mantle earnUSDe contracts, enable TimelockController
tamtamchik Jun 2, 2026
285a5b4
fix: update earnUSDe Plasma deploy to new contracts
tamtamchik Jun 2, 2026
0688b41
fix: update earnUSDe Mantle to latest redeploy
tamtamchik Jun 2, 2026
ab8575b
chore: remove outdated Arbitrum earnUSDe config
tamtamchik Jun 2, 2026
ea789f0
fix: don't abort the run when a contract errors
tamtamchik Jun 2, 2026
b93d6e1
fix: add missing impl constructor_calldata to Ethereum meta_core
tamtamchik Jun 2, 2026
b756645
refactor: make bytecode comparison errors fatal, drop dead ExceptionH…
tamtamchik Jun 2, 2026
2c0911d
revert: drop error-handling changes from this PR
tamtamchik Jun 2, 2026
ee8b45f
Merge pull request #162 from lidofinance/fix/earnusde-swapmodule-rede…
tamtamchik Jun 2, 2026
e6b8c30
Merge pull request #149 from lidofinance/feat/mantle-meta-updates
tamtamchik Jun 2, 2026
35e96db
docs: fix AI-doc drift vs code
tamtamchik Jun 2, 2026
69a4ace
docs: correct fail_on_bytecode_comparison_error description
tamtamchik Jun 2, 2026
09e81b9
Merge pull request #164 from lidofinance/docs/ai-doc-accuracy
TheDZhon Jun 2, 2026
2769ec9
Merge remote-tracking branch 'origin/main' into feat/mantle-meta
tamtamchik Jun 2, 2026
d8c9c8e
chore: remove arbitrum
tamtamchik Jun 2, 2026
7f679cb
feat: error when --contract filter matches nothing
tamtamchik Jun 2, 2026
3135973
chore: align meta config env and gas settings
tamtamchik Jun 2, 2026
6802c2f
chore: remove --local-rpc option
tamtamchik Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .claude/skills/debug-diff/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ ls digest/<timestamp>/diffs/<contract_address>/
- Missing or wrong constructor arguments -- see `constructor_calldata` or `constructor_args` under the `bytecode_comparison` config key
- Missing libraries -- check if the contract uses external libraries that need addresses in `bytecode_comparison.libraries`
- Wrong EVM version -- the explorer may report a different version than expected
- Immutable variables -- `deep_match_bytecode()` in `diffyscan/utils/binary_verifier.py` compares instruction-by-instruction and tolerates differences that fall within known immutable reference regions. If all diffs are in immutable positions it logs a warning and returns `False` (still reported as a non-match — use `--allow-bytecode-diff 0xAddr` to accept). Differences outside immutable regions raise `BinVerifierError`
- Immutable variables -- `deep_match_bytecode()` in `diffyscan/utils/binary_verifier.py` compares instruction-by-instruction and tolerates differences that fall within known immutable reference regions. If all diffs are in immutable positions it logs a warning and returns `False` (still reported as a non-match — use `--allow-bytecode-diff 0xAddr` to accept). Differences outside immutable regions raise `BinVerifierError`, which `process_config` catches and records as a non-match (`match=False`) — it does not abort the run
- Optimizer settings mismatch -- the solcInput from the explorer includes optimizer settings; the GitHub recompilation must match
- Flat-source contracts -- see **Known limitations** section below

Expand All @@ -68,8 +68,13 @@ ls digest/<timestamp>/diffs/<contract_address>/
| `"Failed to infer source path for library '...' from explorer metadata"` | Add library addresses to `bytecode_comparison.libraries` keyed by `"path/to/File.sol": {"LibName": "0xAddr"}` |
| All files show diffs | Wrong `commit` or `relative_root` in `github_repo` |
| Single contract fails | May need a per-contract `constructor_calldata` or `constructor_args` entry |
| `"Bytecodes have differences not on the immutable reference position"` | Real bytecode mismatch -- check compiler version, optimizer settings, EVM version, and library addresses |
| `"Failed in binary comparison: Bytecodes have differences not on the immutable reference position"` | Real bytecode mismatch -- check compiler version, optimizer settings, EVM version, and library addresses |
| `"Exiting with non-zero code due to unallowed diffs"` | Either fix the diffs or use `--allow-source-diff 0xAddr` / `--allow-bytecode-diff 0xAddr` for known acceptable diffs |
| `"Contract name in config does not match with blockchain explorer ... !="` | Contract not verified on explorer — comment it out or verify it on the explorer first |
| `"Failed to get calldata: Explorer metadata has empty constructor calldata for 0x..."` | Factory-created contract — Etherscan has no constructor args. Add `constructor_calldata` manually (extract via `getsourcecode` API `ConstructorArguments`, `debug_traceTransaction` trace, or cross-chain reuse) |
| `"HTTP error: 404 ... contents/<path>.sol"` | Missing or wrong `dependencies` entry — the explorer source uses a path prefix not covered by config dependencies. Add a mapping for that prefix |
| `"err: intrinsic gas too low"` | Chain gas model needs a higher deployment gas cap (known on Mantle) — set `deployment_gas_limit` in the config (e.g. `30000000000`) |
| All proxy bytecode diffs say "immutable reference position" | Normal for TransparentUpgradeableProxy — ProxyAdmin address baked in as immutable. Use `--allow-bytecode-diff` or accept as expected |

### 4. Suggest a re-run command
After fixing, suggest:
Expand Down
45 changes: 42 additions & 3 deletions .claude/skills/new-config/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ YAML gotcha: addresses and hex strings MUST be quoted (`"0xabc..."`) — unquote
- `constructor_args` — typed args per address: `{"0xAddr": ["0xarg1", true, 42]}`
- `libraries` — per source path: `{"contracts/lib/Foo.sol": {"Foo": "0xLibAddr"}}`
- `hardhat_config_name` — (deprecated) name of a hardhat config file
- `fail_on_bytecode_comparison_error` — set to `true` for strict mode
- `fail_on_bytecode_comparison_error` — defaults to `true`; when `false`, a per-contract exception (e.g. failing to fetch/verify a contract from the explorer) is logged and the run continues instead of aborting. Despite the name, an actual error inside `run_bytecode_diff` is always caught and recorded as a mismatch (`match=False`) regardless of this flag.
- `source_comparison` — set to `false` to skip source diffs (bytecode-only check)
- `rpc_url_env_var` — name of the env var holding the RPC URL for bytecode comparison (defaults to `REMOTE_RPC_URL`; e.g. `MANTLE_RPC_URL`, `PLASMA_RPC_URL`)
- `deployment_gas_limit` — optional gas limit for the `eth_call` deployment simulation (helps on chains where the default reverts with "intrinsic gas too low")
- `explorer_hostname_env_var` — config convention for external CI/tooling to pass the explorer hostname via env var (used for soneium, unichain). Note: diffyscan itself does NOT resolve this at runtime — `get_explorer_hostname()` only reads `explorer_hostname`. External scripts must set `explorer_hostname` before invoking diffyscan.
- `audit_url` — optional link to an audit report for documentation purposes
- `metadata` — optional object for deployment metadata (e.g. `chain_name`, `deployment_date`, `timelock_address`, `timelock_requirements`)
Expand Down Expand Up @@ -119,9 +121,46 @@ Save configs to `config_samples/<chain>/<network>/` following existing naming co
- **Include `audit_url`** — link to the relevant audit report when available for cross-reference
- **Keep configs strict** — prefer explicit over implicit; include all fields even if optional, so verification is as thorough as possible

## Extracting proxy constructor calldata

Factory-created proxies (e.g. TransparentUpgradeableProxy) often need `constructor_calldata` for bytecode comparison. Three methods, in order of preference:

**Method 1: Etherscan v2 API** (preferred)
```bash
curl -s "https://api.etherscan.io/v2/api?chainid=<CHAIN_ID>&module=contract&action=getsourcecode&address=<ADDR>&apikey=<TOKEN>" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['result'][0].get('ConstructorArguments',''))"
```
Factory-created contracts sometimes return empty — fall through to Method 2.

**Method 2: debug_traceTransaction** (when Etherscan has empty args)
1. Get creation tx hash via `getcontractcreation` API
2. Trace with `{"tracer": "callTracer"}` to find CREATE/CREATE2 opcodes
3. Constructor args are appended to initcode in the CREATE2 input. Find the implementation address (padded to 32 bytes) in the hex input — everything from that point on is the constructor args.
4. Alternatively, if you know the exact initcode size (e.g. from a reference deployment on another chain), slice at that offset.

**Method 3: Cross-chain reuse** (when traces unavailable)
CREATE2 with same factory + same init code + same salt = same address on every chain. If a proxy has the same address on two chains, its constructor calldata is identical. Copy from the chain where you already have it.

### Verifying proxy implementations
Always verify implementations on-chain before writing the config:
```bash
cast implementation <proxy_address> --rpc-url <RPC_URL>
```

### Chain-specific RPC limitations
- Some chains (Arbitrum, Mantle) do NOT support `debug_traceTransaction` on public RPCs — use Etherscan API or cross-chain reuse instead.
- Mantle's gas model causes `eth_call` to fail with "intrinsic gas too low" for large deployment simulations — use `--skip-binary-comparison`.
- Unverified contracts on a chain's explorer should be commented out in the config.

### Dependencies: matching explorer source paths
If diffyscan fails with 404 fetching a GitHub file, the explorer source uses a path prefix that isn't covered by `dependencies`. Each key in `dependencies` maps a source path prefix → a GitHub repo. Check the explorer source file paths and add the missing prefix mapping.

## Workflow

1. Gather required info from user (ask for missing pieces)
2. Look at existing configs in the same chain directory for reference patterns
3. Create the config file
4. Suggest running: `uv run diffyscan <config-path> --yes --cache-explorer --cache-github`
3. Verify implementations on-chain with `cast implementation`
4. Extract constructor calldata (Etherscan API → trace → cross-chain reuse)
5. Create the config file with all needed dependencies
6. Run: `uv run diffyscan <config-path> --yes --cache-explorer --cache-github`
7. Expected: source diffs = 0; bytecode diffs on proxies (immutable reference) is normal
13 changes: 5 additions & 8 deletions .env.example
Comment thread
tamtamchik marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ GITHUB_API_TOKEN=github_pat_xxx
# Explorer API tokens (set the ones you need for your target chains)
ETHERSCAN_TOKEN=
ETHERSCAN_EXPLORER_TOKEN=
BSCSCAN_TOKEN=
OPTISCAN_EXPLORER_TOKEN=
LINEA_EXPLORER_TOKEN=
INK_API_KEY=
MEGAETH_API_KEY=
PLASMA_API_KEY=

# Explorer hostnames (used when hostname is not hardcoded in config)
L1_EXPLORER_API_HOSTNAME=
L2_EXPLORER_API_HOSTNAME=

# RPC URLs (required for bytecode comparison)
LOCAL_RPC_URL=http://127.0.0.1:7545
REMOTE_RPC_URL=
REMOTE_RPC_URL=https://eth.drpc.org
ETHEREUM_RPC_URL=https://eth.drpc.org
MANTLE_RPC_URL=https://rpc.mantle.xyz
PLASMA_RPC_URL=https://rpc.plasma.to
BASE_RPC_URL=https://base.drpc.org
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

Diffyscan verifies deployed EVM smart contracts match their GitHub source by:
1. Fetching verified source from blockchain explorers (Etherscan, Blockscout, zkSync, Mantle)
2. Diffing against GitHub repo sources (HTML diff reports saved to `digest/`)
2. Diffing against GitHub repo sources (HTML diff reports saved under `digest/<timestamp>/diffs/`)
3. Optionally recompiling from GitHub and comparing bytecode against on-chain bytecode, handling constructor args, libraries, and immutable references

## Commands
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ diffyscan /path/to/config.json
diffyscan /path/to/config.yaml
```

To check only specific contracts (can be passed multiple times):

```bash
diffyscan /path/to/config.json -C 0xContractAddress
diffyscan /path/to/config.json -C 0xFirst -C 0xSecond
```

To skip binary comparison (which is enabled by default):

```bash
Expand Down
Loading
Loading