1

As a context I am trying to fork uniswap v2 contracts using my own compiler and deploy files. I am not using truffle, as I want to deeply understand before using a framework.

When I run my compiler, I get this error :

  formattedMessage: 'Contract:3:1: ParserError: Source "interfaces/IUniswapV2Factory.sol" not found: File import callback not supported\n' +
    "import './interfaces/IUniswapV2Factory.sol';\r\n" +
    '^------------------------------------------^\n',
  message: 'Source "interfaces/IUniswapV2Factory.sol" not found: File import callback not supported',

I tried to copy all contracts into the contract that I was trying to deploy, and it worked. But I can't do this for every contract ...

Here is my compiler file : `


const path = require("path");
const solc = require("solc"); //don't forget to install the right solc version !
const fs = require("fs-extra");

const buildPath = path.resolve(__dirname, "build");

fs.removeSync(buildPath);

function compileContract(Contract) {
    const contractPath = path.resolve(__dirname, "./", Contract);
    
    const contractSourceCode = fs.readFileSync(contractPath, "utf8");
    
    fs.ensureDirSync(buildPath);

    var input = {
        language: 'Solidity',
        sources: {
            Contract : {
                content: contractSourceCode
            }
        },
        settings: {
            optimizer: {
                enabled: true
            },
            outputSelection: {
                '*': {
                    '*': [ '*' ]
                }
            }
        }
    };

    const output = JSON.parse(solc.compile(JSON.stringify(input)));
    console.log(output);

    for(let contractName in output.contracts.Contract) {
        fs.outputJsonSync(
            path.resolve(buildPath, `${contractName}.json`),
            output.contracts.Contract[contractName]
        );
    }
    
}

// compileContract("UniswapV2Pair.sol");
compileContract("UniswapV2Factory.sol");
compileContract("UniswapV2ERC20.sol"); 

I am using solc@0.5.16

And here are the files I am trying to deploy : https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts

7
  • Check the import callback from the solidity docs. Also check the usage info on the solcjs. I hope it will help you understand what a monster are you dealing with. Also, maybe someone will help if you provide more of your compiling script and what command do you run to execute it. Please, be sure provide this information. Jul 23 at 20:56
  • Thank you mate, I'll read it now. About the compiling script this is all I have in the compile.js file. Basically it create a build folder and fill it with compiled contracts. And I use "node compile.js" to run it
    – Cizia
    Jul 24 at 3:46
  • Well, after reading those docs many times, and trying different solutions, I can't understand how to solve the problem .. i tried to import files directly from the @uniswap/v2-core dependency, doesn't work. Tried to put the file in the same folder, doesn't work. Tried to import with relative or direct import, doesn't change anything.
    – Cizia
    Jul 24 at 14:05
  • As far as I understood from the manual in github for solcjs and your error description you should implement import callback yourself because it doesn't work in solcjs. Did you see the example in the section from github? The function findImports specifically implements import callback to resolve imports. I cannot try it on my own, unfortunately because my OS doesn't support 0.5.16 solcjs Jul 24 at 18:20
  • 1
    Ok, so, I tried to use it yesterday, but I think I misunderstand something. Thank you for your great help Prorok, it's deeply appreciated. So, this findImport function basically take an import path from the contract we want to compile. And in the findImport function, we check the path, and if it's the one we want to import, we hardcode the content of the imported contract in the return statement ? I hope the question makes sense.
    – Cizia
    Jul 25 at 6:59
1

Here is the code that I wrote to compile files with import statements with solc@0.5.16. The script compile the files and put them into a build folder as a json file.

Thanks for helping me making this !

"use-strict";

const path = require("path");
const solc = require("solc"); //don"t forget to install the right solc version !
const fs = require("fs-extra");

// interfaces folder
const IERC20SourceCode = fs.readFileSync("./interfaces/IERC20.sol");
const IUniswapV2CalleeSourceCode = fs.readFileSync("./interfaces/IUniswapV2Callee.sol");
const IUniswapV2ERC20SourceCode = fs.readFileSync("./interfaces/IUniswapV2ERC20.sol");
const IUniswapV2FactorySourceCode = fs.readFileSync("./interfaces/IUniswapV2Factory.sol");
const IUniswapV2PairSourceCode = fs.readFileSync("./interfaces/IUniswapV2Pair.sol");

// libraries folder
const MathSourceCode = fs.readFileSync("./libraries/Math.sol");
const UQ112x112SourceCode = fs.readFileSync("./libraries/UQ112x112.sol");
const SafeMathSourceCode = fs.readFileSync("./libraries/SafeMath.sol");

// core folder
const UniswapV2PairSourceCode = fs.readFileSync("./UniswapV2Pair.sol");
const UniswapV2ERC20SourceCode = fs.readFileSync("./UniswapV2ERC20.sol");
const UniswapV2FactorySourceCode = fs.readFileSync("./UniswapV2Factory.sol");

const buildPath = path.resolve(__dirname, "build");

fs.removeSync(buildPath);

function compileContract(Contract) {
    const contractPath = path.resolve(__dirname, ...Contract);  
    
    const contractSourceCode = fs.readFileSync(contractPath, "utf8");
    
    fs.ensureDirSync(buildPath);

    var input = {
        language: "Solidity",
        sources: {
            Contract: {
                content: contractSourceCode
            }
        },
        settings: {
            optimizer: {
                enabled: true
            },
            outputSelection: {
                "*": {
                    "*": [ "*" ]
                }
            }
        }
    };

    function findImports(path) {
        if (path === "interfaces/IUniswapV2Factory.sol") return { contents: `${IUniswapV2FactorySourceCode}` };
        if (path === "interfaces/IERC20.sol") return { contents: `${IERC20SourceCode}` };
        if (path === "interfaces/IUniswapV2Callee.sol") return { contents: `${IUniswapV2CalleeSourceCode}` };
        if (path === "interfaces/IUniswapV2ERC20.sol") return { contents: `${IUniswapV2ERC20SourceCode}` };
        if (path === "interfaces/IUniswapV2Pair.sol") return { contents: `${IUniswapV2PairSourceCode}` };
        if (path === "libraries/Math.sol") return { contents: `${MathSourceCode}` };
        if (path === "libraries/UQ112x112.sol") return { contents: `${UQ112x112SourceCode}` };
        if (path === "libraries/SafeMath.sol") return { contents: `${SafeMathSourceCode}` };
        if (path === "UniswapV2Pair.sol") return { contents: `${UniswapV2PairSourceCode}` };
        if (path === "UniswapV2ERC20.sol") return { contents: `${UniswapV2ERC20SourceCode}` };
        if (path === "UniswapV2Factory.sol") return { contents: `${UniswapV2FactorySourceCode}` };
        else return { error: "File not found" };
      }

    let output = JSON.parse(solc.compile(JSON.stringify(input), { import: findImports }));

    for(let contractName in output.contracts.Contract) {
        fs.outputJsonSync(
            path.resolve(buildPath, `${contractName}.json`),
            output.contracts.Contract[contractName]
        );
    }    
}

compileContract(["./", "UniswapV2Factory.sol"]);
compileContract(["./", "UniswapV2Pair.sol"]);
compileContract(["./", "UniswapV2ERC20.sol"]);
compileContract(["./", "libraries", "Math.sol"]);
compileContract(["./", "libraries", "SafeMath.sol"]);
compileContract(["./", "libraries", "UQ112x112.sol"]);
compileContract(["./", "interfaces", "IUniswapV2Factory.sol"]);
compileContract(["./", "interfaces", "IERC20.sol"]);
compileContract(["./", "interfaces", "IUniswapV2Callee.sol"]);
compileContract(["./", "interfaces", "IUniswapV2ERC20.sol"]);
compileContract(["./", "interfaces", "IUniswapV2Pair.sol"]);
2
  • Actually what you can do is to remove questions from this answer, mark this as your self-answer and create a separate question post about whether you can improve the solution somehow with link to this question post. This would remove questions from the answer section which is always good and also it would draw more attention from the users because the question will be shown as with no answer. Jul 25 at 13:04
  • 1
    all right, thanks Prorok for taking the time, I'll do this !
    – Cizia
    Jul 25 at 13:49
0

You should use options like --base-path and --include-path to avoid it

here is an example

./node_modules/.bin/solcjs --include-path ./node_modules/ --base-path ./contracts/ --evm-version constantinople ./contracts/GnosisSafe.sol --bin --abi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.