Closed tash-2s closed 6 months ago
Thank you for your review! I've added the doc to the function.
@mattsse Thank you for taking the time to review this pull request.
I've created a companion PR in foundry with this patch. Also, I have confirmed that the tests in foundry passed successfully.
I've addressed these comments.
Appreciate your review on the PR. 🙏
Currently, when a project includes symbolic links to Solidity files,
Project::standard_json_input
returns a Standard JSON Input struct that is unusable for contract verification on block explorers.solc
cannot compile these contracts based on the json, leading to verification failures. This pull request addresses this issue.I encountered this problem when using the
forge verify-contract
command, which internally uses this function. Whileforge build
completes successfully, the verification command fails, indicating that the block explorer cannot find a source file.This problem occurs in projects that contain symlinked Solidity files and when these files are imported from other files. My project, structured as a monorepo, uses external libraries installed via pnpm. These libraries, accessible from the
./node_modules/
directory, are set up with remappings in my Foundry project. However, directories under./node_modules/
are symlinks pointing to other locations, leading to this issue.Reproduction
I added a test named
can_create_standard_json_input_with_symlink
to demonstrate the issue within this repository. Also, the error can be reproduced using theforge verify-contract
command and steps below:Environment: macOS (Apple silicon), forge 0.2.0 (
c312c0d
2023-12-22T00:20:29.297186000Z)Manually editing the host filesystem's absolute path as shown below allows the
solc
command to succeed.Cause
The issue arises because import paths in Solidity files are processed by the
std::fs::canonicalize
function. This function resolves symlinks and normalizes paths. When symlinks are resolved, it results insolc
being unable to locate the corresponding source paths in the json, as it relies on Solidity import statements. Therefore, symlinks should not be resolved here. The paths should be maintained as specified in the Solidity files, except for basic normalization.Solution
To address this, I implemented an import path normalization function and replaced the canonicalization function where necessary. Based on the Solidity documentation page, this function resolves
.
and..
segments/components without resolving symlinks.The Standard JSON's source paths, for verification purposes, should be based on the project root. This allows the compiler to find sources within the json. The conversion of normalized paths to project root-based paths occurs after all sources are processed. That conversion is already implemented, so this PR doesn't need to address it. (It seems like the path conversion needs improvement, but it is a separate issue and should be handled in another PR.)
https://github.com/foundry-rs/compilers/blob/b1561d807c246c066c7c4b0c72c8eb64c696a43d/src/lib.rs#L514-L525
With the changes proposed in this PR, I confirmed the fix of the issue by building
forge
with this patch and testing both the reproduction case and my project. The resulting json matches the manually edited json diff mentioned earlier.A potential downside of this approach is that the same file could be represented differently in the json if accessed via both symlinked and real paths. However, I see no issues with this, and it aligns with the behavior of the compiler's virtual filesystem.