Skip to content

Conversation

s2imonovic
Copy link
Collaborator

@s2imonovic s2imonovic commented Oct 14, 2025

Fix @skosito's review comments

closes: #589 (review)

Summary by CodeRabbit

  • New Features
    • Compare two smart contract implementations by fetching sources from supported explorers based on network.
    • Automatically handles Etherscan and Blockscout, supporting both single-file and multi-file verifications.
    • Normalizes and flattens sources, removes duplicate headers, and reorders files to align declarations for accurate diffs.
    • Saves processed sources to disk and outputs a clear side-by-side comparison summary.
    • Works with existing configuration; provide an API key when required by the chosen explorer.

@s2imonovic s2imonovic requested review from a team as code owners October 14, 2025 20:05
@github-actions github-actions bot added the fix label Oct 14, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

📝 Walkthrough

Walkthrough

Introduces a new orchestration to fetch contract sources from Etherscan or Blockscout, normalize single vs multi-file formats, flatten/reorder sources, remove duplicate headers, and save comparable outputs for two contract addresses. Adds utilities for declaration parsing, file lookup, and file I/O, plus an exported main function to coordinate the process.

Changes

Cohort / File(s) Summary of Changes
Contract diff orchestration & utilities
scripts/contractDiff/contractDiffTool.ts
Added explorer dispatching (fetchContractSource), Blockscout and Etherscan fetchers, Solidity declaration parsing and file lookup helpers, header deduplication, source flattening and multi-file reordering, file saving utility, and new exported fetchAndFlattenContract(oldAddress, newAddress, network) to orchestrate fetching, processing, and persisting comparison outputs.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as Caller
  participant C as fetchAndFlattenContract
  participant D as fetchContractSource
  participant E as Etherscan API
  participant B as Blockscout API
  participant F as Flatten/Reorder Utils
  participant FS as File System

  U->>C: fetchAndFlattenContract(oldAddr, newAddr, network)
  activate C

  Note over C,D: Fetch old contract
  C->>D: get source (oldAddr, network)
  alt explorerType == "etherscan"
    D->>E: GET contract source
    E-->>D: ContractSource (single/multi)
  else explorerType == "blockscout"
    D->>B: GET contract source
    B-->>D: ContractSource (normalized)
  end
  D-->>C: ContractSource (old)

  Note over C,D: Fetch new contract
  C->>D: get source (newAddr, network)
  alt explorerType == "etherscan"
    D->>E: GET contract source
    E-->>D: ContractSource (single/multi)
  else explorerType == "blockscout"
    D->>B: GET contract source
    B-->>D: ContractSource (normalized)
  end
  D-->>C: ContractSource (new)

  Note over C,F: Normalize and flatten
  C->>F: detect format, clean headers
  C->>F: flatten multi-file or pass-through single-file
  F-->>C: flatOld, flatNew

  Note over C,F: Reorder multi-file to match single-file declaration order (if needed)
  C->>F: extractDeclarationOrder(single)
  C->>F: reorderMultiFileToMatchSingleFile(multi, order)
  F-->>C: reordered content(s)

  C->>FS: saveContractToFile(old)
  C->>FS: saveContractToFile(new)
  FS-->>C: saved paths

  C-->>U: Completion + summary paths
  deactivate C
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The pull request title is "chore: fix review comments," which is a vague and generic descriptor that fails to convey meaningful information about the changeset. While the title is technically related to the PR's purpose (addressing review feedback), it provides no insight into what was actually implemented. The actual changes include substantial new functionality in the contract diff tool—multiple helper functions for fetching from different blockchain explorers, parsing Solidity source code, flattening multi-file sources, and a new main orchestration function. A developer scanning the repository history would not be able to understand what this change accomplishes from the title alone, making it equivalent to terms like "misc updates." Consider revising the title to be more descriptive of the actual implementation rather than just referencing review feedback. A better title might be something like "Add contract fetching and flattening utilities to diff tool" or "Implement contract source orchestration for contract diff" to clearly communicate what functionality was added or improved.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/contract-diff

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
scripts/contractDiff/contractDiffTool.ts (2)

16-16: Remove non-null assertion operator to prevent runtime failures.

Using process.env.ETHERSCAN_API_KEY! with the non-null assertion operator is unsafe. If the environment variable is not set, apiKeyEnv will be undefined at runtime, bypassing TypeScript's type safety. This could lead to silent failures or confusing errors when the API is called.

Apply this diff to handle undefined API keys properly:

 eth_mainnet: {
     name: "Ethereum Mainnet",
     apiUrl: "https://api.etherscan.io/v2/api?chainid=1",
-    apiKeyEnv: process.env.ETHERSCAN_API_KEY!,
+    apiKeyEnv: process.env.ETHERSCAN_API_KEY,
     explorerType: "etherscan",
 },

Apply similar changes to lines 22, 28, 34, 40, and 46. The validation at line 237-239 should then properly catch missing API keys.

Also applies to: 22-22, 28-28, 34-34, 40-40, 46-46


224-242: API key validation is ineffective with current type assertions.

The check !config.apiKeyEnv at line 237 is currently ineffective because apiKeyEnv is assigned using the non-null assertion operator (!) in the config. This means TypeScript treats it as always defined, even when process.env.ETHERSCAN_API_KEY is undefined.

Once you remove the non-null assertions from lines 16, 22, 28, 34, 40, and 46 (as suggested in the previous comment), this validation will work correctly and catch missing API keys before attempting to call the API.

🧹 Nitpick comments (4)
scripts/contractDiff/contractDiffTool.ts (4)

272-285: Consider stronger typing for sources parameter.

The sources parameter is typed as any, which reduces type safety. Consider defining a more specific type for the sources structure.

Add a type definition at the top of the file:

type SourceFiles = Record<string, { content: string } | string>;

Then update the function signature:

-function findFileByContractName(sources: any, contractName: string): string | null {
+function findFileByContractName(sources: SourceFiles, contractName: string): string | null {

335-365: Consider logging parsing errors instead of silent fallback.

The catch block at lines 359-361 silently returns the original sourceCode without any indication that parsing failed. This could mask issues during contract processing.

Apply this diff to add error logging:

         return cleanDuplicateHeaders(allCode);
     } catch (error) {
+        console.warn(`⚠️  Failed to parse multi-file format, using as-is: ${error instanceof Error ? error.message : error}`);
         return sourceCode;
     }

375-431: Consider logging reordering errors for better debugging.

Similar to flattenSourceCode, the catch block at lines 428-430 silently returns the original code without logging. This makes it difficult to debug when reordering fails.

Apply this diff:

         return cleanDuplicateHeaders(reorderedCode);
     } catch (error) {
+        console.warn(`⚠️  Failed to reorder multi-file format, using as-is: ${error instanceof Error ? error.message : error}`);
         return multiFileCode;
     }

467-526: Consider making output directory configurable.

The OUTPUT_DIR is hardcoded at line 472. While this works for the current use case, making it configurable would improve flexibility.

Add an optional parameter:

 export async function fetchAndFlattenContract(
     oldAddress: string,
     newAddress: string,
     network: string,
+    outputDir: string = "./contract-diffs"
 ) {
-    const OUTPUT_DIR = "./contract-diffs"
     try {
         console.log("\n📥 Fetching OLD implementation...");
         const oldContract = await fetchContractSource(oldAddress, network);

And update the function calls to use outputDir:

-        const oldPath = saveContractToFile(oldFlattened, oldFile, OUTPUT_DIR);
-        const newPath = saveContractToFile(newFlattened, newFile, OUTPUT_DIR);
+        const oldPath = saveContractToFile(oldFlattened, oldFile, outputDir);
+        const newPath = saveContractToFile(newFlattened, newFile, outputDir);

Otherwise, the orchestration logic is well-structured and handles different file format combinations correctly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9d7c0 and beb4917.

📒 Files selected for processing (1)
  • scripts/contractDiff/contractDiffTool.ts (10 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
scripts/**

⚙️ CodeRabbit configuration file

Review the Hardhat scripts for best practices.

Files:

  • scripts/contractDiff/contractDiffTool.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: slither
  • GitHub Check: test
🔇 Additional comments (5)
scripts/contractDiff/contractDiffTool.ts (5)

106-163: LGTM: Blockscout integration is well-structured.

The function properly handles Blockscout's response format, including multi-file contracts, and converts it to a unified ContractSource interface. Error handling covers both 404 cases and general failures appropriately.


174-213: LGTM: Etherscan integration follows best practices.

The function correctly handles Etherscan's API responses with proper error checking for unverified contracts and API failures.


251-263: LGTM: Declaration extraction is correctly implemented.

The regex pattern properly matches contract, interface, library, and abstract contract declarations, and the exec() loop correctly extracts all declarations in order.


294-325: LGTM: Duplicate header removal is correctly implemented.

The function properly preserves the first SPDX license identifier and pragma statement while removing subsequent duplicates, which is essential for valid Solidity compilation.


442-455: LGTM: File saving logic is appropriate for a script.

The function correctly handles directory creation and file writing. Using synchronous operations is acceptable in this script context.

Copy link
Member

@lumtis lumtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would keep it as a chore because we don't fix a bug in the core contracts here

@s2imonovic s2imonovic changed the title fix: review comments chore: fix review comments Oct 17, 2025
@github-actions github-actions bot added chore and removed fix labels Oct 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants