Skip to content

fix: sort Foundry sources by ID for correct sourceList ordering#653

Open
Mike4751 wants to merge 4 commits intocrytic:masterfrom
Mike4751:fix-foundry-sourcelist-order
Open

fix: sort Foundry sources by ID for correct sourceList ordering#653
Mike4751 wants to merge 4 commits intocrytic:masterfrom
Mike4751:fix-foundry-sourcelist-order

Conversation

@Mike4751
Copy link
Copy Markdown

Fixes #652

Summary

When building Foundry projects with subdirectories that use relative paths in their foundry.toml, the sourceList indices in exported combined_solc.json become misaligned with source IDs in bytecode source maps.

Files Changed

compilation_unit.py

  • Add _source_id_to_filename dict to track ID→filename mapping
  • Add filenames_for_export property returning filenames ordered by source ID
  • Add set_source_id() method to store the mapping

hardhat.py

  • Sort sources by ID before processing
  • Call set_source_id() to store the mapping for each source

solc.py

  • Use filenames_for_export instead of filenames for correct ordering

Testing

Minimal reproduction: https://github.com/Mike4751/crytic-compile-sourcelist-bug

Test Case Unpatched Patched
Simple project (3 files) 0 mismatches 0 mismatches ✓
Relative paths (8 files) 8 mismatches 0 mismatches ✓
Large project (~470 files) 470 mismatches 0 mismatches ✓

Backwards Compatibility

✅ Simple/standard projects continue to work correctly
✅ Complex projects with relative paths are now fixed

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jan 30, 2026

CLA assistant check
All committers have signed the CLA.

When processing Foundry/Hardhat build-info, the sourceList was generated
in JSON iteration order rather than by source ID. This caused bytecode
source maps to reference wrong files when Echidna/Slither processed
coverage data.

Changes:
- Add source_id_to_filename mapping to CompilationUnit
- Sort sources by ID when parsing build-info
- Store source ID mapping during parsing
- Use filenames_for_export in solc export to maintain correct indices

Fixes source map index mismatch where e.g. sourceList[185] would point
to the wrong file because sources were not indexed by their compiler-
assigned IDs.
@Mike4751 Mike4751 force-pushed the fix-foundry-sourcelist-order branch from e13a126 to 4a9ab22 Compare January 31, 2026 00:15

# Build list indexed by source ID
max_id = max(self._source_id_to_filename.keys())
result: list[Filename | None] = [None] * (max_id + 1)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's not clear to me why 1 is added, also shouldn't be max(max_id, len(self._filenames)) to handle the case of self._filenames > max_id?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sorry for the delay! The Solidity compiler assigns source IDs starting at 0. Also, you're right I included this change.

pass

# Filter out None entries and return
return [f for f in result if f is not None]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Filtering out None elements can move indices, i think is better if there would be a warning or error if a None is present

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'll change to an error.

@Mike4751 Mike4751 force-pushed the fix-foundry-sourcelist-order branch from 3dcba28 to 57e6f5c Compare March 24, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Foundry sourceList indices don't match bytecode source map file references

3 participants