foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.33k stars 1.76k forks source link

bug(`config`): Error: `Could not read source code for analysis` w/ remappings #2915

Closed fedealconada closed 3 days ago

fedealconada commented 2 years ago

Component

Forge

Have you ensured that all of these are up to date?

What version of Foundry are you on?

forge 0.2.0 (4e11d1f 2022-08-24T00:12:55.883067Z)

What command(s) is the bug in?

forge coverage

Operating System

macOS (Intel)

Describe the bug

After running forge coverage on this directory I'm getting the following message:

Analysing contracts...
Error:
Could not read source code for analysis

Context:
- Error #0: failed to read from "/src/Divider.sol": No such file or directory (os error 2)
- Error #1: No such file or directory (os error 2)

We are using yarn as dependency manager and we are using yarn workspaces to handle multiple packages on the same repo.

onbjerg commented 2 years ago

So it seems like it is because of the way the remappings are set up, but I'm still investigating exactly what happens.

Essentially, each of your packages has a remapping for itself. I think this is because all the packages depend on each other somehow, so you need to have all of the remappings defined in case the dependency uses it, correct?

In any case, if you build e.g. the package core, then any source file in that package will end up having an invalid absolute path. You can verify this by just running forge build and inspecting the .ast.absolutePath field in the artifact for e.g. Divider.sol. All other paths are well-formed, which is interesting - if you instead compile e.g. fuse, then all paths are well-formed, except for any file in the fuse package, e.g. PoolManager.sol.

onbjerg commented 2 years ago

Changing up the remappings a bit makes it sort of work, but the report is very cluttered because none of the sub-packages are actually dependencies, it just looks at it as one big source tree.

Changing core/foundry.toml to this:

[profile.default]
root = "."
libs = ['../../node_modules/', '../utils', '../fuse']
tests = "./src/tests"
ffi = true
verbosity = 3
remappings = [
    '@sense-finance/v1-utils=../utils',
    '@sense-finance/v1-core/=../core',
    '@sense-finance/v1-fuse/=../fuse',
    '@rari-capital/solmate=../../node_modules/@rari-capital/solmate',
    '@openzeppelin/contracts=../../node_modules/@openzeppelin/contracts',
    'ds-test/=./src/tests/test-helpers/'
]

Makes it get past the error. I couldn't get the tests to run without failing though so unsure how valid the report is

fedealconada commented 2 years ago

Thanks so much for investigating the issue! I tried only changing the core/foundry.toml file as you suggested and got this error:

[⠊] Compiling...
Error:
Failed to resolve file: "/src/libs/Errors.sol": No such file or directory (os error 2).
    --> "/Users/fedealconada/Development/sense-v1/pkg/core/src/Divider.sol"
        "@sense-finance/v1-utils/src/libs/Errors.sol"
    Check configured remappings.

I have then "fixed" the other .toml files (following the same logic) and the error is gone but I got a new one:

forge coverage

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
[7]    43932 abort      forge coverage
onbjerg commented 2 years ago

Can you post the tomls? Some parts of the toml are very important here since a misconfiguration leads to recursion in your repository

fedealconada commented 2 years ago

Here they are!

core/foundry.toml

[profile.default]
root = "."
libs = ['../../node_modules/', '../utils', '../fuse']
tests = "./src/tests"
ffi = true
verbosity = 3
remappings = [
    '@sense-finance/v1-utils=../utils',
    '@sense-finance/v1-core/=./',
    '@sense-finance/v1-fuse/=../fuse',
    '@rari-capital/solmate=../../node_modules/@rari-capital/solmate',
    '@openzeppelin/contracts=../../node_modules/@openzeppelin/contracts',
    'ds-test/=./src/tests/test-helpers/'
]

fuse/foundry.toml

[profile.default]
root = "."
libs = ['../../node_modules/', '../utils', '../core']
tests = "./src/tests"
ffi = true
verbosity = 3
# Fork block mined on Apr 18 2022 at 12:00:10 AM UTC
fork_block_number = 14605885
remappings = [
    '@sense-finance/v1-utils=../utils',
    '@sense-finance/v1-core=../core',
    '@sense-finance/v1-fuse=./',
    '@rari-capital/solmate=../../node_modules/@rari-capital/solmate',
    '@openzeppelin/contracts=../../node_modules/@openzeppelin/contracts'
]

utils/foundry.toml

[profile.default]
root = "."
libs = ['../../node_modules/', '../fuse', '../core']
tests = "./src/tests"
ffi = true
verbosity = 3
remappings = [
    '@sense-finance/v1-utils=./',
    '@sense-finance/v1-core=../core',
    '@sense-finance/v1-fuse=../fuse',
    '@rari-capital/solmate=../../node_modules/@rari-capital/solmate',
    '@openzeppelin/contracts=../../node_modules/@openzeppelin/contracts'
]
mattsse commented 2 years ago

@fedealconada sorry for taking so long,

I had a look, and one thing that's obvious is that this setup uses circular dependencies, (core imports from fuse, fuse imports from core)

I checked the solc compilerinput which looks ok, there's something weird with the output however because it contains duplicate entries for Divider.sol: src/Divider.sol and /src/Divider.sol, this is usually a sign that solc fails to look up an import of a file in the json compilerinput (which works like a virtual file system) and instead tries to find it on disk and also adds this to the compileroutput.

I wasn't able to find the root cause for this but it's definitely related to the relative imports, perhaps in combination with circular setup there are some weird edge cases...

however I was able to resolve this by tuning the remappings and point to the src dir instead, this is also the default dapptools style

    '@sense-finance/v1-utils=../utils/src',
    '@sense-finance/v1-core/=./src',
    '@sense-finance/v1-fuse=../fuse/src',

after I replaced the imports in the sol files, the issue was resolved

fedealconada commented 2 years ago

Hey @mattsse , thanks a ton for the follow up! I've just tried what you suggested (changing the re-mappings and replacing imports on the sol files) but I'm getting the same error as before:

forge coverage

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
[68]    42352 abort      forge coverage

Just to double check, I pushed the changes on this branch. This is the commit with the .toml files changes and this one the one where I'm replacing the .sol files.

fedealconada commented 2 years ago

Any follow up on this @mattsse ? :)

davidlaprade commented 2 years ago

Thanks for reporting this @fedealconada. Another data-point here.

I'm working on a project that was seeing the same "could not read source code" error when I ran forge coverage. In our case, there weren't circular dependencies there were circular dependencies, but they didn't have to be resolved in order to get the coverage tool working. The real issue seemed to be a nested dependency tree. The project had one submodule (call it A), and A itself had a submodule (call it B). The project imported from both A and B, and thus had remappings to shorten imports from B.

I eventually got forge coverage to work on a frankenstein branch by moving the two submodules directly into src and deleting the corresponding remappings. But it'd obviously be great if this didn't have to be done.

EDIT: see above

fedealconada commented 2 years ago

@mattsse we finally got this fixed. Not sure exactly why, but seems like our remappings in the foundry.toml needed the /src (and I removed them from the contracts). The other way around was throwing an error.

xenide commented 1 year ago

Another data point here. In our case we don't have any circular dependencies, the repo imports dependencies from lib/v3-core. forge test works with no issues and it's only coverage that's complaining.

foundry.toml in the root directory:

[profile.default]
solc           = "0.8.17"
bytecode_hash  = "none"
optimizer_runs = 1_000_000
remappings     = ["@openzeppelin/=lib/openzeppelin-contracts/contracts/", "v3-core/=lib/v3-core"]
match_path     = "test/unit/*.sol"
verbosity      = 3

Also, doing export RUST_LOG=trace doesn't give much more helpful info.

fedealconada commented 8 months ago

It's been a while but I'm facing again this issue, any hint on this @mattsse?

xenide commented 5 months ago

It's been a while but I'm facing again this issue, any hint on this @mattsse?

me too. I'm positive that we don't have circular dependencies, just submodules which we import from

drinkius commented 4 months ago

A hint for someone who might be researching similar issue: in my case the issue was indeed in remappings but related to OS case-sensitivity, all worked well on macOS but failed in CI on Ubunutu. Re-check the cases of your remappings, this might help

grandizzy commented 2 weeks ago

forge test works with no issues and it's only coverage that's complaining

The coverage issue is related to optimizer being disabled, see https://github.com/foundry-rs/foundry/issues/8840#issuecomment-2341742571 I am not able to reproduce the initial report related to remappings / build failures, @zerosnacks could you also pls give it a try? thanks!

grandizzy commented 3 days ago

closing as it's no longer reproducible with latest version

image

please reopen if still an issue. thank you!