gakonst / ethers-rs

Complete Ethereum & Celo library and wallet implementation in Rust. https://docs.rs/ethers
Apache License 2.0
2.49k stars 797 forks source link

import path canonicalization results in file paths that are not on disk #2609

Open 0xalpharush opened 1 year ago

0xalpharush commented 1 year ago

Version Via Foundry forge 0.2.0 (8c1a569 2023-09-19T00:32:46.118501000Z)

Platform Darwin macbook arm64

Description The build artifacts output by forge using ethers-solc are not consistently converting import paths into absolute paths with the root of the project resolved. These file paths cannot be opened bc they are not on disk and it's not ideal to have to search the project directory for candidates as there's potentially duplicates that are not interchangeable.

I think when foundry projects are nested, the root resolution is relative to the context of the dependency and not the project (however the example below demonstrates two different behaviors). This causes issues for tools like Slither because when a project takes a dependency on solmate and solady, there's ambiguity about which src/tokens/ERC20.sol is referenced and the given path isn't truly absolute.

How to create the project:

git clone git@github.com:0xalpharush/ethers-issue-2609.git && cd ethers-issue-2609
forge build --build-info

If I run cat out/ERC20Mock.sol/ERC20Mock.json | grep 'absolutePath": "src/tokens/ERC20.sol', there is a result that I do not expect.

Instead, I would expect the path for ERC20Mock to be absolute relative to the project root i.e. only the following command would return a result:

cat out/ERC20Mock.sol/ERC20Mock.json | grep 'absolutePath": "lib/solady/src/tokens/ERC20.sol'`

This expectation reflects the behavior of the import path resolution for Counter artifact which references the path, lib/solady/src/tokens/ERC20.sol :

cat out/Counter.sol/Counter.json | grep 'absolutePath": "lib/solady/src/tokens/ERC20.sol'`

Anywhere src/tokens/ERC20.sol appears in the build artifacts in reference to Solady, I would expect to see lib/solady/src/tokens/ERC20.sol (this is the behavior of hardhat and what I would consider correct as it's unambiguous)

I think the relevant code is here but I haven't figured out a solution yet. Also, I imagine this is particularly delicate and probably requires more context and consideration that I can provide... https://github.com/gakonst/ethers-rs/blob/08bcb67c36d9a2869950e51ecf76124c9febe035/ethers-solc/src/config.rs#L240-L261

mattsse commented 1 year ago

ethers-solc are not consistently converting import paths into absolute paths with the root of the project resolved.

if this is about the absolutePath json field, I'm pretty sure that we never touch that since this is solc output

But I think you found the buggy code already.

Looking at:

    "sources": {
      "lib/solady/ext/woke/ERC20Mock.sol": {
        "keccak256": "0x508149a04ca17da422e50df1d25fcc5dd88ef666398eeca6800686a6987f95ff",
        "urls": [
          "bzz-raw://30e858817901565516da9416fb800c3f64cc3dc95b38736ef008248e4b71891c",
          "dweb:/ipfs/QmcKh4wdg7Gy5QWawJavG694W3RjLmmaifALFFZyu6adGp"
        ],
        "license": "MIT"
      },
      "src/tokens/ERC20.sol": {
        "keccak256": "0x264e4675697d05dfb9bbe9cc91c6bda7962d934f1e940336fd75d509b7f396c4",
        "urls": [
          "bzz-raw://5856338689f03f36c057203c5085243e104b8487274432062ebf076b512edeea",
          "dweb:/ipfs/QmXrqgaWQikKkHfoBkYPxeMTJWUY5uf7kSmipNbpU35XwK"
        ],
        "license": "MIT"
      },
      "src/utils/SafeTransferLib.sol": {
        "keccak256": "0x64af21dfdc2042a9dc0c6e970072523f11c934e14aba05696b17e8f736d2a70e",
        "urls": [
          "bzz-raw://4f9ffeb99b644857294b1535ad3d952ee705237d4208e48e18f54a20818aa09c",
          "dweb:/ipfs/QmQKmo7qqxUsyivySvbvSe3cgyvJRAqztejcdgGEWRCddx"
        ],
        "license": "MIT"
      }

for some reason the relative path from project dir to solady lib/solady is stripped from the path. But this is only the case for src, not ext.

need to debug what's going on here.

thanks for this.

0xalpharush commented 1 year ago

Yeah, I think the root cause is related to the path prefix being stripped in the sources which I believe ultimately affects solc's absolutePath

mattsse commented 1 year ago

fyi @Evalir

plotchy commented 1 year ago

Ive recently been messing with ethers_solc, remappings, paths and also am familiar enough with slither. I wouldn't mind giving this fix a try.

A question for @mattsse, @DaniPopes and @Evalir. since this includes foundry and ethers, what's the easiest way to iterate on a fix? Build foundry from source, and change all the Cargo.toml's within to have the ethers dependency point to a local ethers path?

mattsse commented 1 year ago

@Evalir was looking into this but no fix yet, sharing some context:

    "sources": {
      "lib/solady/ext/woke/ERC20Mock.sol": {
        "keccak256": "0x508149a04ca17da422e50df1d25fcc5dd88ef666398eeca6800686a6987f95ff",
        "urls": [
          "bzz-raw://30e858817901565516da9416fb800c3f64cc3dc95b38736ef008248e4b71891c",
          "dweb:/ipfs/QmcKh4wdg7Gy5QWawJavG694W3RjLmmaifALFFZyu6adGp"
        ],
        "license": "MIT"
      },
      "src/tokens/ERC20.sol": {
        "keccak256": "0x264e4675697d05dfb9bbe9cc91c6bda7962d934f1e940336fd75d509b7f396c4",
        "urls": [
          "bzz-raw://5856338689f03f36c057203c5085243e104b8487274432062ebf076b512edeea",
          "dweb:/ipfs/QmXrqgaWQikKkHfoBkYPxeMTJWUY5uf7kSmipNbpU35XwK"
        ],
        "license": "MIT"
      },
      "src/utils/SafeTransferLib.sol": {
        "keccak256": "0x64af21dfdc2042a9dc0c6e970072523f11c934e14aba05696b17e8f736d2a70e",
        "urls": [
          "bzz-raw://4f9ffeb99b644857294b1535ad3d952ee705237d4208e48e18f54a20818aa09c",
          "dweb:/ipfs/QmQKmo7qqxUsyivySvbvSe3cgyvJRAqztejcdgGEWRCddx"
        ],
        "license": "MIT"
      }

see lib/solady/ext/woke/ERC20Mock.sol? That’s passed in correctly, since it’s an import coming from an user test file, not a library file

src/tokens/ERC20.sol and the SafeTransferLib imports are coming from solady itself. ERC20Mock imports both of these so we get these import_paths, but there’s no post-processing of these once we know they’re coming from a library

so the issue is, “internal” library import paths are passed in to solc without appending the library they correspond to to the path

(“internal” library import = any internal file that solady imports inside a contract)

I think the fix here might just be to canonicalize every import path we pass

@plotchy

you can check out both repos, then uncomment this in foundry, so it uses your local ethers and compile forge locally, I recommend compiling in debug mode cargo build --bin forge which reasonably fast

https://github.com/foundry-rs/foundry/blob/87283bc9f5657eed126ecb2d2370a471ff409bb7/Cargo.toml#L170-L180

I think the bug is somewhere here:

https://github.com/gakonst/ethers-rs/blob/edf3353cb419451a5eb2e89685e3e26e10783670/ethers-solc/src/config.rs#L272-L277

https://github.com/gakonst/ethers-rs/blob/edf3353cb419451a5eb2e89685e3e26e10783670/ethers-solc/src/config.rs#L328-L328

https://github.com/gakonst/ethers-rs/blob/edf3353cb419451a5eb2e89685e3e26e10783670/ethers-solc/src/config.rs#L361-L361

plotchy commented 1 year ago

Thanks for the tips @mattsse. I built the debug bin as you said and then symlinked the bin to forge2 on my PATH and that worked great.

Started digging into this. I have a feeling that ethers is handling this correctly.

I looked through the resolve_* functions and was finding that the imports all looked solid with absolute paths. I ended up chasing this down to see what we provide to solc, and even these objects look good to me.

Here is CompilerInput for alpharush's repro (i minified the contract code to be readable):

[ethers-rs/ethers-solc/src/compile/project.rs:555] &input = CompilerInput {
    language: "Solidity",
    sources: {
        "lib/solady/ext/woke/ERC20Mock.sol": Source {
            content: "pragma solidity ^0.8.4;\nimport \"src/tokens/ERC20.sol\";\ncontract ERC20Mock is ERC20 {}",
        },
        "lib/solady/src/tokens/ERC20.sol": Source {
            content: "pragma solidity ^0.8.4;\nabstract contract ERC20 {}",
        },
        "src/Counter.sol": Source {
            content: "pragma solidity 0.8.13;\nimport \"lib/solady/src/tokens/ERC20.sol\";\ncontract Counter {}",
        },
        "test/Counter.t.sol": Source {
            content: "pragma solidity 0.8.13;\nimport {Counter} from \"../src/Counter.sol\";\nimport {ERC20Mock} from \"lib/solady/ext/woke/ERC20Mock.sol\";\ncontract CounterTest {}",
        },
    },
    settings: Settings {
        remappings: [
            Remapping {
                context: None,
                name: "ds-test/",
                path: "lib/forge-std/lib/ds-test/src",
            },
            Remapping {
                context: None,
                name: "forge-std/",
                path: "lib/forge-std/src",
            },
            Remapping {
                context: None,
                name: "solady/",
                path: "lib/solady",
            },
        ],
        ...,
        libraries: Libraries {
            libs: {},
        },
    },
}

Notice that all these paths are absolute from the root of the repo.

Then i followed this object to see what the actual solc command is:

[ethers-rs/ethers-solc/src/compile/mod.rs:579] &cmd = Command {
    program: "/Users/plotchy/.svm/0.8.13/solc-0.8.13",
    args: [
        "/Users/plotchy/.svm/0.8.13/solc-0.8.13",
        "--base-path",
        "/Users/plotchy/code/learning/ethers-issue-2609",
    ],
    cwd: Some(
        "/Users/plotchy/code/learning/ethers-issue-2609",
    ),
}
[ethers-rs/ethers-solc/src/compile/mod.rs:579] &self.args = [
    "--allow-paths",
    "/Users/plotchy/code/learning/ethers-issue-2609,/Users/plotchy/code/learning/ethers-issue-2609/lib",
    "--include-path",
    "/Users/plotchy/code/learning/ethers-issue-2609/lib/solady",
]

This is what i'd expect again. From here, we add on --standard-json and write to stdin with that CompilerInput object above.

the full command is something like: /Users/plotchy/.svm/0.8.13/solc-0.8.13 --base-path /Users/plotchy/code/learning/ethers-issue-2609 --allow-paths /Users/plotchy/code/learning/ethers-issue-2609,/Users/plotchy/code/learning/ethers-issue-2609/lib --standard-json <stdin CompilerInput>

Leaving these breadcrumbs here if anyone sees something out of place. Do we know what solc command hardhat uses?

mattsse commented 1 year ago

thanks for this!

hmm, it maybe there's something wrong with postprocessing of the compileroutput then

you can run with env var ETHERS_SOLC_LOG=in=in.json,out=out.json forge ... to get the raw compiler in/out json as files

plotchy commented 1 year ago

Ok, here are the jsons for in and out. I pruned the out.json in this post to contain relevant portions.

full jsons are here: https://gist.github.com/plotchy/f09b4e92d7fbb9379c20ee6fd351559a

in.json has all absolute paths.

out.json's main points of contention are that the ast for "lib/solady/ext/woke/ERC20Mock.sol" has an ImportDirective with "absolutePath": "src/tokens/ERC20.sol". solc then appends "src/tokens/ERC20.sol" to both the list of sources and the list of contracts. I'm not sure why!

Knowing that in.json has all absolute paths for the sources, I'm not sure how ethers could provide the input differently. As far as I can tell, postprocessing for build info doesnt touch the output ast absolutePaths. There could be an opportunity to touch them up for sure. Does hardhat do that? Or do they provide the input differently?

in.json

{
  "language": "Solidity",
  "sources": {
    "lib/solady/ext/woke/ERC20Mock.sol": {
      "content": "pragma solidity ^0.8.4;\nimport \"src/tokens/ERC20.sol\";\ncontract ERC20Mock is ERC20 {}"
    },
    "lib/solady/src/tokens/ERC20.sol": {
      "content": "pragma solidity ^0.8.4;\nabstract contract ERC20 {}"
    },
    "src/Counter.sol": {
      "content": "pragma solidity 0.8.13;\nimport \"lib/solady/src/tokens/ERC20.sol\";\ncontract Counter {}"
    },
    "test/Counter.t.sol": {
      "content": "pragma solidity 0.8.13;\nimport {Counter} from \"../src/Counter.sol\";\nimport {ERC20Mock} from \"lib/solady/ext/woke/ERC20Mock.sol\";\ncontract CounterTest {}"
    }
  },
  "settings": {
    "remappings": [
      "ds-test/=lib/forge-std/lib/ds-test/src/",
      "forge-std/=lib/forge-std/src/",
      "solady/=lib/solady/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs"
    },
    "outputSelection": {
      "*": {
        "": [
          "ast"
        ],
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata"
        ]
      }
    },
    "evmVersion": "london",
    "libraries": {}
  }
}

out.json

{
  "sources": {
    "lib/solady/ext/woke/ERC20Mock.sol": {
      "id": 0,
      "ast": {
        "absolutePath": "lib/solady/ext/woke/ERC20Mock.sol",
        "id": 6,
        "exportedSymbols": {
          "ERC20": [
            22
          ],
          "ERC20Mock": [
            5
          ]
        },
        "nodeType": "SourceUnit",
        "src": "0:85:0",
        "nodes": [
          {
            "id": 2,
            "nodeType": "ImportDirective",
            "src": "24:30:0",
            "nodes": [],
            "absolutePath": "src/tokens/ERC20.sol",
            "file": "src/tokens/ERC20.sol",
            "nameLocation": "-1:-1:-1",
            "scope": 6,
            "sourceUnit": 23,
            "symbolAliases": [],
            "unitAlias": ""
          }
        ]
      }
    },
    "lib/solady/src/tokens/ERC20.sol": {
      "id": 1,
      "ast": {
        "absolutePath": "lib/solady/src/tokens/ERC20.sol",
      }
    },
    "src/Counter.sol": {
      "id": 2,
      "ast": {
        "absolutePath": "src/Counter.sol",
        "id": 13,
        "exportedSymbols": {
          "Counter": [
            12
          ],
          "ERC20": [
            8
          ]
        },
        "nodeType": "SourceUnit",
        "src": "0:85:2",
        "nodes": [
          {
            "id": 11,
            "nodeType": "ImportDirective",
            "src": "24:41:2",
            "nodes": [],
            "absolutePath": "lib/solady/src/tokens/ERC20.sol",
            "file": "lib/solady/src/tokens/ERC20.sol",
            "nameLocation": "-1:-1:-1",
            "scope": 13,
            "sourceUnit": 9,
            "symbolAliases": [],
            "unitAlias": ""
          }
        ]
      }
    },
    "src/tokens/ERC20.sol": {
      "id": 3,
      "ast": {
        "absolutePath": "src/tokens/ERC20.sol",
        "id": 23,
      }
    },
    "test/Counter.t.sol": {}
  },
  "contracts": {
    "lib/solady/ext/woke/ERC20Mock.sol": {},
    "lib/solady/src/tokens/ERC20.sol": {},
    "src/Counter.sol": {},
    "src/tokens/ERC20.sol": {},
    "test/Counter.t.sol": {}
  }
}
plotchy commented 1 year ago

Since solc appends "src/tokens/ERC20.sol" to sources&contracts and uses that relative path as the key, now I was curious, and copied/renamed the solady lib as solmate. Then I imported another ERC20Mock into the Counter test file so that there would be two imports of the same relative path (colliding key).

Counter.t.sol

pragma solidity 0.8.13;
import {Counter} from "../src/Counter.sol";

// these both import "src/tokens/ERC20.sol"
import {ERC20Mock} from "lib/solady/ext/woke/ERC20Mock.sol"; 
import {ERC20Mock2} from "lib/solmate/ext/woke/ERC20Mock.sol";

contract CounterTest {}

Now the compiler run fails.

Error: 
Compiler run failed:
Error (6275): Source "src/tokens/ERC20.sol" not found: Ambiguous import. Multiple matching files found inside base path and/or include paths: "/Users/plotchy/code/learning/ethers-issue-2609/lib/solady/src/tokens/ERC20.sol", "/Users/plotchy/code/learning/ethers-issue-2609/lib/solmate/src/tokens/ERC20.sol".
 --> lib/solady/ext/woke/ERC20Mock.sol:2:1:
  |
2 | import "src/tokens/ERC20.sol";
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Error (6275): Source "src/tokens/ERC20.sol" not found: Ambiguous import. Multiple matching files found inside base path and/or include paths: "/Users/plotchy/code/learning/ethers-issue-2609/lib/solady/src/tokens/ERC20.sol", "/Users/plotchy/code/learning/ethers-issue-2609/lib/solmate/src/tokens/ERC20.sol".
 --> lib/solmate/ext/woke/ERC20Mock.sol:2:1:
  |
2 | import "src/tokens/ERC20.sol";
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I dont quite know how to digest all this info. If there is a way for ethers to help make the sources more unambiguous then we should we do that. From what I see in the input commands, we are already doing this as best we can. Postprocessing adjustments don't seem to fix this compiler issue with multiple libs colliding on names.

plotchy commented 1 year ago

@0xalpharush do you have a hardhat repro that complies with your needs that I could take a look at? Their docs do mention some special preprocess and postprocess steps.

Hardhat optimizes compilation by compiling the smallest possible set of files at a time. Files that are compiled together have the same solc input and output. Since having this in each debug file would be meaningfully wasteful, this information is deduplicated in build info files that are placed in artifacts/build-info

0xalpharush commented 1 year ago

Thanks for taking this on and thorough investigation @plotchy. I realize now hardhat works because it doesn't seem to include the test/ directory in the original project I opened this for.

It looks like we can use the remapping context feature to translate imports in dependencies to be relative to the root of the project. For example, import src/tokens/ERC20.sol in root/lib/solady can be translated to lib/solady/src/tokens/ERC20.sol by adding "lib/solady/:src/=lib/solady/src/" to the remappings object of the standard input. (Maybe related to https://github.com/foundry-rs/foundry/pull/5397 and https://github.com/foundry-rs/foundry/pull/5532)

in.json

{
    "language": "Solidity",
    "sources": {
      "lib/solady/ext/woke/ERC20Mock.sol": {
        "content": "pragma solidity ^0.8.4;\nimport \"src/tokens/ERC20.sol\";\ncontract ERC20Mock is ERC20 {}"
      },
      "lib/solady/src/tokens/ERC20.sol": {
        "content": "pragma solidity ^0.8.4;\nabstract contract ERC20 {}"
      },
      "src/Counter.sol": {
        "content": "pragma solidity 0.8.13;\nimport \"lib/solady/src/tokens/ERC20.sol\";\ncontract Counter {}"
      },
      "test/Counter.t.sol": {
        "content": "pragma solidity 0.8.13;\nimport {Counter} from \"../src/Counter.sol\";\nimport {ERC20Mock} from \"lib/solady/ext/woke/ERC20Mock.sol\";\ncontract CounterTest {}"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "solady/=lib/solady/",
        "lib/solady/:src/=lib/solady/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "": [
            "ast"
          ],
          "*": [
            "abi",
            "evm.bytecode",
            "evm.deployedBytecode",
            "evm.methodIdentifiers",
            "metadata"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {}
    }
  }

out.json

"sources": {
        "lib/solady/ext/woke/ERC20Mock.sol": {
            "ast": {
                "absolutePath": "lib/solady/ext/woke/ERC20Mock.sol",
                "exportedSymbols": {
                    "ERC20": [
                        8
                    ],
                    "ERC20Mock": [
                        5
                    ]
                },
                "id": 6,
                "nodeType": "SourceUnit",
                "nodes": [
                    {
                        "id": 1,
                        "literals": [
                            "solidity",
                            "^",
                            "0.8",
                            ".4"
                        ],
                        "nodeType": "PragmaDirective",
                        "src": "0:23:0"
                    },
                    {
                        "absolutePath": "lib/solady/src/tokens/ERC20.sol",
                        "file": "src/tokens/ERC20.sol",
                        "id": 2,
                        "nameLocation": "-1:-1:-1",
                        "nodeType": "ImportDirective",
                        "scope": 6,
                        "sourceUnit": 9,
                        "src": "24:30:0",
                        "symbolAliases": [],
                        "unitAlias": ""
                    },
                    {
                        "abstract": false,
                        "baseContracts": [
                            {
                                "baseName": {
                                    "id": 3,
                                    "name": "ERC20",
                                    "nodeType": "IdentifierPath",
                                    "referencedDeclaration": 8,
                                    "src": "77:5:0"
                                },
                                "id": 4,
                                "nodeType": "InheritanceSpecifier",
                                "src": "77:5:0"
                            }
                        ],
                        "canonicalName": "ERC20Mock",
                        "contractDependencies": [],
                        "contractKind": "contract",
                        "fullyImplemented": true,
                        "id": 5,
                        "linearizedBaseContracts": [
                            5,
                            8
                        ],
                        "name": "ERC20Mock",
                        "nameLocation": "64:9:0",
                        "nodeType": "ContractDefinition",
                        "nodes": [],
                        "scope": 6,
                        "src": "55:30:0",
                        "usedErrors": []
                    }
                ],
                "src": "0:85:0"
            },
            "id": 0
        },
        "lib/solady/src/tokens/ERC20.sol": {
            "ast": {
                "absolutePath": "lib/solady/src/tokens/ERC20.sol",
                "exportedSymbols": {
                    "ERC20": [
                        8
                    ]
                },
                "id": 9,
                "nodeType": "SourceUnit",
                "nodes": [
                    {
                        "id": 7,
                        "literals": [
                            "solidity",
                            "^",
                            "0.8",
                            ".4"
                        ],
                        "nodeType": "PragmaDirective",
                        "src": "0:23:1"
                    },
                    {
                        "abstract": true,
                        "baseContracts": [],
                        "canonicalName": "ERC20",
                        "contractDependencies": [],
                        "contractKind": "contract",
                        "fullyImplemented": true,
                        "id": 8,
                        "linearizedBaseContracts": [
                            8
                        ],
                        "name": "ERC20",
                        "nameLocation": "42:5:1",
                        "nodeType": "ContractDefinition",
                        "nodes": [],
                        "scope": 9,
                        "src": "24:26:1",
                        "usedErrors": []
                    }
                ],
                "src": "0:50:1"
            },
            "id": 1
        },
        "src/Counter.sol": {
            "ast": {
                "absolutePath": "src/Counter.sol",
                "exportedSymbols": {
                    "Counter": [
                        12
                    ],
                    "ERC20": [
                        8
                    ]
                },
                "id": 13,
                "nodeType": "SourceUnit",
                "nodes": [
                    {
                        "id": 10,
                        "literals": [
                            "solidity",
                            "0.8",
                            ".13"
                        ],
                        "nodeType": "PragmaDirective",
                        "src": "0:23:2"
                    },
                    {
                        "absolutePath": "lib/solady/src/tokens/ERC20.sol",
                        "file": "lib/solady/src/tokens/ERC20.sol",
                        "id": 11,
                        "nameLocation": "-1:-1:-1",
                        "nodeType": "ImportDirective",
                        "scope": 13,
                        "sourceUnit": 9,
                        "src": "24:41:2",
                        "symbolAliases": [],
                        "unitAlias": ""
                    },
                    {
                        "abstract": false,
                        "baseContracts": [],
                        "canonicalName": "Counter",
                        "contractDependencies": [],
                        "contractKind": "contract",
                        "fullyImplemented": true,
                        "id": 12,
                        "linearizedBaseContracts": [
                            12
                        ],
                        "name": "Counter",
                        "nameLocation": "75:7:2",
                        "nodeType": "ContractDefinition",
                        "nodes": [],
                        "scope": 13,
                        "src": "66:19:2",
                        "usedErrors": []
                    }
                ],
                "src": "0:85:2"
            },
            "id": 2
        },
        "test/Counter.t.sol": {
            "ast": {
                "absolutePath": "test/Counter.t.sol",
                "exportedSymbols": {
                    "Counter": [
                        12
                    ],
                    "CounterTest": [
                        19
                    ],
                    "ERC20Mock": [
                        5
                    ]
                },
                "id": 20,
                "nodeType": "SourceUnit",
                "nodes": [
                    {
                        "id": 14,
                        "literals": [
                            "solidity",
                            "0.8",
                            ".13"
                        ],
                        "nodeType": "PragmaDirective",
                        "src": "0:23:3"
                    },
                    {
                        "absolutePath": "src/Counter.sol",
                        "file": "../src/Counter.sol",
                        "id": 16,
                        "nameLocation": "-1:-1:-1",
                        "nodeType": "ImportDirective",
                        "scope": 20,
                        "sourceUnit": 13,
                        "src": "24:43:3",
                        "symbolAliases": [
                            {
                                "foreign": {
                                    "id": 15,
                                    "name": "Counter",
                                    "nodeType": "Identifier",
                                    "overloadedDeclarations": [],
                                    "referencedDeclaration": 12,
                                    "src": "32:7:3",
                                    "typeDescriptions": {}
                                },
                                "nameLocation": "-1:-1:-1"
                            }
                        ],
                        "unitAlias": ""
                    },
                    {
                        "absolutePath": "lib/solady/ext/woke/ERC20Mock.sol",
                        "file": "lib/solady/ext/woke/ERC20Mock.sol",
                        "id": 18,
                        "nameLocation": "-1:-1:-1",
                        "nodeType": "ImportDirective",
                        "scope": 20,
                        "sourceUnit": 6,
                        "src": "68:60:3",
                        "symbolAliases": [
                            {
                                "foreign": {
                                    "id": 17,
                                    "name": "ERC20Mock",
                                    "nodeType": "Identifier",
                                    "overloadedDeclarations": [],
                                    "referencedDeclaration": 5,
                                    "src": "76:9:3",
                                    "typeDescriptions": {}
                                },
                                "nameLocation": "-1:-1:-1"
                            }
                        ],
                        "unitAlias": ""
                    },
                    {
                        "abstract": false,
                        "baseContracts": [],
                        "canonicalName": "CounterTest",
                        "contractDependencies": [],
                        "contractKind": "contract",
                        "fullyImplemented": true,
                        "id": 19,
                        "linearizedBaseContracts": [
                            19
                        ],
                        "name": "CounterTest",
                        "nameLocation": "138:11:3",
                        "nodeType": "ContractDefinition",
                        "nodes": [],
                        "scope": 20,
                        "src": "129:23:3",
                        "usedErrors": []
                    }
                ],
                "src": "0:152:3"
            },
            "id": 3
        }
0xalpharush commented 3 months ago

@klkvr can this be migrated to foundry-compilers as I believe it is still an issue