`ParserError` file not found on truffle-compilation of scribble instrumented code
cd1m0 opened this issue · 0 comments
If you have a truffle repo with
invariant
annotation on a contract X, which inherits from contract Y, where Y is defined in a package undernode_modules/
- And you instrument and arm the code
- Try to run
truffle compile
You will run into compilation failures like this one:
ParserError: Source "contracts/__scribble_ReentrancyUtils.sol" not found
--> @openzeppelin/contracts/access/AccessControlEnumerable.sol:8:1:
|
8 | import "./../../../../contracts/__scribble_ReentrancyUtils.sol";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The issue is that our instrumentation needs to modify all base contracts, including the ones under node_modules/
. As part of the modification, they need to inherit from the __scribble_ReentrancyUtils
contract, which is usually placed at the root of the contracts/
directory. This adds an import from the node_modules/
directory back into the contracts/
directory.
In other development environments, to compile such contracts users need to specify a path remapping like @openzeppelin=node_modules/@openzeppelin
. As a result, the solc compiler will preform the following steps when resolving the import declaration above:
- Append the relative import path to the current file directory path. In the above example we would append
./../../../../contracts/__scribble_ReentrancyUtils.sol
to@openzeppelin/contracts/access/
to obtain
@openzeppelin/contracts/access/./../../../../contracts/__scribble_ReentrancyUtils.sol
- Apply any path remappings. In the above example we would apply
@openzeppelin=node_modules/@openzeppelin
to@openzeppelin/contracts/access/./../../../../contracts/__scribble_ReentrancyUtils.sol
to obtain
node_modules/@openzeppelin/contracts/access/./../../../../contracts/__scribble_ReentrancyUtils.sol
- Normalize the path, collapsing any . and .. In the above example this would transform
node_modules/@openzeppelin/contracts/access/./../../../../contracts/__scribble_ReentrancyUtils.sol
intocontracts/__scribble_ReentrancyUtils.sol
- Resolve the obtained path.
However in the case of truffle, it seems to be doing its own separate import path resolution, and building the complete standard json input to pass in to the compiler (around here). That doesn't seem to like our relative imports.
Steps to reproduce:
git clone git@github.com:cd1m0/scribble-truffle-remapping-bug.git
cd scribble-truffle-remapping-bug/
npm install
scribble contracts/Foo.sol --output-mode files --arm --path-remapping '@openzeppelin=node_modules/@openzeppelin' --compiler-version 0.8.11
truffle compile
You should see the following errors:
ParserError: Source "contracts/__scribble_ReentrancyUtils.sol" not found
--> @openzeppelin/contracts/token/ERC20/ERC20.sol:8:1:
|
8 | import "./../../../../../contracts/__scribble_ReentrancyUtils.sol";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
,ParserError: Source "contracts/__scribble_ReentrancyUtils.sol" not found
--> @openzeppelin/contracts/utils/Context.sol:5:1:
|
5 | import "./../../../../contracts/__scribble_ReentrancyUtils.sol";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compilation failed. See above.