"File import callback not supported" on Truffle using Linux

I’m trying to compile a smart contract TestMinter.sol that inherits from ERC20PresetMinterPauser.sol using the @openzeppelin/contracts library and Truffle. TestMinter.sol seems to import the ERC20PresetMinterPauser.sol correctly using

import "node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";

But then when ERC20PresetMinterPauser.sol tries to import I get a File import callback not supported error:

$ truffle compile

Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/TestMinter.sol
> Compiling ./node_modules/@openzeppelin/contracts/GSN/Context.sol
> Compiling ./node_modules/@openzeppelin/contracts/access/AccessControl.sol
> Compiling ./node_modules/@openzeppelin/contracts/math/SafeMath.sol
> Compiling ./node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol
> Compiling ./node_modules/@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol
> Compiling ./node_modules/@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol
> Compiling ./node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
> Compiling ./node_modules/@openzeppelin/contracts/utils/Address.sol
> Compiling ./node_modules/@openzeppelin/contracts/utils/EnumerableSet.sol
> Compiling ./node_modules/@openzeppelin/contracts/utils/Pausable.sol
> Compiling node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol

CompileError: node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol:5:1: ParserError: Source "node_modules/@openzeppelin/contracts/access/AccessControl.sol" not found: File import callback not supported
import "../access/AccessControl.sol";
^-----------------------------------^
,node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol:6:1: ParserError: Source "node_modules/@openzeppelin/contracts/GSN/Context.sol" not found: File import callback not supported
import "../GSN/Context.sol";
^--------------------------^
,node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol:7:1: ParserError: Source "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol" not found: File import callback not supported
import "../token/ERC20/ERC20.sol";
^--------------------------------^
,node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol:8:1: ParserError: Source "node_modules/@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol" not found: File import callback not supported
import "../token/ERC20/ERC20Burnable.sol";
^----------------------------------------^
,node_modules/@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol:9:1: ParserError: Source "node_modules/@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol" not found: File import callback not supported
import "../token/ERC20/ERC20Pausable.sol";
^----------------------------------------^

Compilation failed. See above.
    at run (/home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/compile-solidity/run.js:52:1)
    at Object.sourcesWithDependencies (/home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/compile-solidity/index.js:107:56)
    at necessary (/home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/compile-solidity/index.js:69:1)
    at /home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/workflow-compile/index.js:33:1
    at async Promise.all (index 0)
    at compile (/home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/workflow-compile/index.js:23:1)
    at Object.compile (/home/contooter/.npm-global/lib/node_modules/truffle/build/webpack:/packages/workflow-compile/index.js:66:45)
Truffle v5.1.57 (core: 5.1.57)
Node v14.15.1

:computer: Environment

Truffle v5.1.57 (solc 0.6.2)
Node v14.15.1
@openzeppelin/contracts 3.3.0
Linux Mint 20

I could probably do a workaround and change all the smart contracts import paths to full paths but I rather not mess around with the preconfigured contracts from OZ because of security reasons.

1 Like

I am not sure, but I think if you have installed the package, you can use as following:

pragma solidity ^0.5.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";

contract SimpleToken is Context, ERC20, ERC20Detailed {
    constructor () public ERC20Detailed("SimpleToken", "SIM", 18) {
        _mint(_msgSender(), 1000000 * (10 ** uint256(decimals())));
    }
}

Just show a simple code to use OpenZeppelin dependency.

2 Likes

Hi @Lennard_Mulder,

Welcome to the community :wave:

Can you try changing your imports to what @Skyge suggested?

Hi @Skyge & @abcoathup, removing node_modules/ from the import solved the problem, thanks!

I’m using a truffle+react box which means I have another node_modules/ dir in the client dir. Could this have been the issue?

1 Like

Sorry, I am not familiar with the React, I think it is ok if you have two node_modules, but your folders may be like this:

--contracts
  --YourContract.sol
--node_modules      <<-- OpenZeppelin dependency should be at here
--client
  --src
  --node_modules

If I am wrong, please correct me.

1 Like

Hi @Skyge,

Absolutely right. Nice text diagram too. Thanks as always :pray:

1 Like

A post was split to a new topic: File import callback not supported when verify contracts

Hi @abcoathup,

Hope you are well.

I'm facing the same issue. When i deploy contracts, all imports work fine but i'm trying to generate the bytecode and ABI using solc package but in this way my import files are not working.

I've tried in both ways by defining path of node_modules and with defining path. Getting error in both cases.

Fixed by setting up --base-path in solc and defining import URLs to ../node_modules/@openzeppelin

Why not import "@openzeppelin/contracts/token/ERC721/ERC721.sol"?

I'd strongly recommend to follow @Skyge's advice and not import from npm packages using paths starting with ../node_modules/. I think it will not even work in latest Truffle now that imports from absolute locations are disallowed (see https://github.com/trufflesuite/truffle/pull/4190). Always use @openzeppelin/contracts/... form for importing from OZ.

You might get away with using ../node_modules/ with solc directly if you consistently use only that form but mixing different forms can backfire horribly and give you weird errors. For example if you import @openzeppelin/contracts/token/ERC721/ERC721.sol in one place and then ../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol in another, the compiler will see two different contracts called ERC721. If you then try to use various contracts importing them in the same file you will get errors about stuff being already declared.

1 Like

Solc is not able to pick inherited contracts from the write path. That's why i have to set the base path and then update the inherited contracts path.

Can you describe it in more detail? Maybe post a small code snippet that does not compile for you (along with paths you're using)? If it's broken, I'd like to get it fixed in the compiler. And if it's not, I can explain why it does not work and how to use it properly.

I mean, I'd understand if importing from @openzeppelin/ did not work for you and importing from ../node_modules/@openzeppelin/ did. But you seem to be using both in your screenshot.

solc when invoked on the CLI indeed won't on its own import from @openzeppelin/ since it's a feature of frameworks like Truffle that find stuff inside node_modules/ and make it available in Standard JSON input under the package name. If you have node_modules/ in your project directory and you use --base-path, you can import with ../node_modules/ (or even just node_modules/ because that directory is now at the VFS root) but imports from @openzeppelin/ will not work unless you actually have that directory directly inside the base path. A feature that will make it possible to import from @openzeppelin/ will very likely land in the next release of the compiler (https://github.com/ethereum/solidity/issues/11409). Until then I think the best workaround if you want your code to compile both with frameworks and directly with the compiler is to use import remapping (i.e. add @openzeppelin=node_modules/@openzeppelin to the command).

1 Like

@cameel

That was just for the example. I just want to show that in both cases i'm unable to access file but i gets solved by defining the basepath in solc

solcjs --bin --optimize --base-path /media/junaid/Codes/Other/nft-smartContracts/ contracts/NFTProject.sol