Search code examples
pythonnpmethereumsoliditybrownie

Getting compiler error when trying to verify a contract importing from @uniswap/v3-periphery


I'm trying to perform a simple Swap from DAI to WETH with Uniswap in my own SmartContract on the Kovan Testnet. Unfortunately my transaction keeps getting reverted even after setting the gas limit manually.

I also discovered that I can not verify the contract on Kovan via etherscan-API nor manually. Instead I keep getting this error for every library I import:

Source "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol" not found: File import callback not supported

Accordingly I have the feeling something is going wrong during compilation and I'm stuck without any further ideas to work out my problem.

Here are a couple infos on what I've tried so far and how to reproduce: Brownie Version 1.16.4, Tested on Windows 10 and Ubuntu 21.04

I've tried:

  • Importing libraries with Brownie package manager
  • Importing libraries with npm and using relative paths
  • All kinds of different compiler remappings in the brownie-config.yaml
  • Adding all dependency files to project folders manually

Here's a link to my code for reproducing my error: https://github.com/MjCage/swap-demo

It'd be fantastic if someone could help.


Solution

  • It's very unlikely that something is "going wrong during compilation". If your contract compiles but what it does does not match the sources, you have found a very serious codegen bug in the compiler and you should report it so that it can be fixed quickly. From experience I'd say that it's much more likely that you have a bug in your contract though.

    As for the error during verification - the problem is that to properly compile a multi-file project, you have to provide all the source files and have them in the right directories. This applies to library code as well so if your contract imports ISwapRouter.sol, you need to also submit that file and all files it in turn imports too.

    The next hurdle is that as far as I can tell, the multi-file verification option at Etherscan only allows you to submit files from a single directory so it only gets their names, not the whole paths (not sure if it's different via the API). You need Etherscan to see the file as @uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol but it sees just ISwapRouter.sol instead and the compiler will not treat them as the same (both could exist after all).

    The right solution is to use the Standard JSON verification option - this way you submit the whole JSON input that your framework passes to the compiler and that includes all files in the project (including libraries) and relevant compiler options. The issue is that Brownie does not give you this input directly. You might be able to recreate it from the JSON it stores on disk (Standard JSON input format is documented at Compiler Input and Output JSON Description) but that's a bit of manual work. Unfortunately Brownie does not provide any way to request this on the command line. The only other way to get it that I know of is to use Brownie's API and call compiler.generate_input_json().

    Since this is a simple project with just one contract and does not have deep dependencies, it might be easier for you to follow @Jacopo Mosconi's answer and just "flatten" the contract by replacing all imports by sources pasted directly into the main contract. You might also try copying the file to your project dir and altering the import so that it only contains the file name, without any path component - this might pass the multi-file verification. Flattening is ultimately how Brownie and many other frameworks currently do verification and Etherscan's check is lax enough to allow sources modified in such a way - it only checks bytecode so you can still verify even if you completely change the import structure, names, comments or even any code that gets removed by the optimizer.