Skip to content

Conversation

@gakonst
Copy link
Member

@gakonst gakonst commented Jan 22, 2026

Fixes #178

Summary

The sources key in build info was ordered alphabetically by path instead of by source unit ID, which broke compatibility with solc's JSON output and Hardhat's build format. Tools that rely on the index of a source path in sources matching its source unit ID (e.g., for source map resolution) would fail.

Changes

  1. Custom serializer for CompilerOutput.sources - Added a sources_by_id serde module that serializes the sources map ordered by source unit ID rather than by path
  2. Enable preserve_order for serde_json - This ensures that when the output is converted to serde_json::Value (in RawBuildInfo::new), the insertion order is preserved
  3. Regression test - Added a test that verifies sources in the output JSON are ordered by their source unit ID

Before

{"output": {"sources": {"a_first.sol": {"id": 2}, "m_middle.sol": {"id": 1}, "z_last.sol": {"id": 0}}}}

After

{"output": {"sources": {"z_last.sol": {"id": 0}, "m_middle.sol": {"id": 1}, "a_first.sol": {"id": 2}}}}

Note: The input sources remain alphabetically ordered as that's the input to the compiler. The output sources are now ordered by ID to match solc's output.

Fixes #178

The `sources` key in build info was ordered alphabetically by path
instead of by source unit ID, which broke compatibility with solc's
JSON output and Hardhat's build format.

This PR:
1. Adds a custom serde serializer for `CompilerOutput.sources` that
   orders entries by their source unit ID instead of path
2. Enables `preserve_order` feature for `serde_json` to maintain
   insertion order when converting to `serde_json::Value`
3. Adds a regression test to verify sources are ordered by ID

Amp-Thread-ID: https://ampcode.com/threads/T-019be4d8-6ecf-72ef-94ba-ce4726744e00
Co-authored-by: Amp <[email protected]>
@gakonst gakonst force-pushed the fix/sources-ordering-by-id branch from 41a977e to e8887b5 Compare January 22, 2026 08:53
- Empty sources
- Single source file
- Non-sequential IDs with gaps (5, 50, 100)
- Roundtrip serialization/deserialization
- Many sources (50 files)
@gakonst gakonst force-pushed the fix/sources-ordering-by-id branch from e8887b5 to dfc5e7b Compare January 22, 2026 09:15
zerosnacks and others added 5 commits January 22, 2026 09:47
Adds an integration test that:
1. Creates a project with 3 Solidity files (Z_Last, A_First, M_Middle)
2. Compiles the project with build_info enabled
3. Reads the generated build info JSON
4. Verifies sources appear in order of source unit ID in the output
The fix was only applied to foundry_compilers::compilers::CompilerOutput,
but not to foundry_compilers_artifacts::CompilerOutput. Both structs need
the custom serializer to ensure sources are ordered by ID.

Also improved the E2E test to correctly search for source entry patterns
in the JSON output (avoiding false matches in AST content).
Move the sources_by_id serialization module to a single location in
foundry_compilers_artifacts::serde_helpers and use it from both:
- foundry_compilers_artifacts::CompilerOutput
- foundry_compilers::compilers::CompilerOutput

This removes ~110 lines of duplicated code.
@zerosnacks zerosnacks marked this pull request as ready for review January 22, 2026 11:04
semver = { version = "1.0", features = ["serde"] }
serde = { version = "1", features = ["derive", "rc"] }
serde_json = "1.0"
serde_json = { version = "1.0", features = ["preserve_order"] }
Copy link
Member

@zerosnacks zerosnacks Jan 22, 2026

Choose a reason for hiding this comment

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

This introduces some level of overhead but should be relatively small. I am unsure however if this causes any unexpected side effects.

Copy link
Member

Choose a reason for hiding this comment

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

why do we need this?

Copy link
Member

Choose a reason for hiding this comment

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

Without preserve_order, serde_json::to_value() captures into a BTreeMap-backed Map that re-sorts alphabetically, losing the ordering from the custom serializer

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.

sources key in build info is no longer in order of source unit id

4 participants