foundry icon indicating copy to clipboard operation
foundry copied to clipboard

Could not read source code for analysis

Open fedealconada opened this issue 3 years ago • 7 comments

Component

Forge

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

  • [X] Foundry
  • [X] Foundryup

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.

fedealconada avatar Aug 24 '22 10:08 fedealconada

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 avatar Aug 24 '22 21:08 onbjerg

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

onbjerg avatar Aug 24 '22 21:08 onbjerg

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

fedealconada avatar Aug 25 '22 13:08 fedealconada

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

onbjerg avatar Aug 25 '22 19:08 onbjerg

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'
]

fedealconada avatar Aug 27 '22 08:08 fedealconada

@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

mattsse avatar Sep 08 '22 13:09 mattsse

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 avatar Sep 12 '22 10:09 fedealconada

Any follow up on this @mattsse ? :)

fedealconada avatar Sep 26 '22 14:09 fedealconada

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

davidlaprade avatar Sep 28 '22 18:09 davidlaprade

@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.

fedealconada avatar Nov 04 '22 09:11 fedealconada

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.

xenide avatar Jan 04 '23 08:01 xenide

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

fedealconada avatar Mar 26 '24 12:03 fedealconada

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

xenide avatar Jun 06 '24 13:06 xenide