1

I have a contract that starts with the following import statements:

import 'https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/interfaces/ILendingPool.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/interfaces/ILendingPoolAddressesProvider.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/dependencies/openzeppelin/contracts/IERC20.sol';

Every time I compile this contract with brownie I get the following error for each import statement:

contracts/FlashLoan.sol:5:1: ParserError: Source "https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol" not found: File outside of allowed directories.
import 'https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol';
^----------------------------------------------------------------------------------------------------------^

I have tried this with both ganache and an infura network (I doubt this matters since its a compiler error, but thought I'd mention it). I have tried to change the import statements to not include https://github.com/ and replaced that portion of the url with @ and still get the same errors. My machine is definitely connected to the internet as I am able to deploy and interact with contracts without import statements on both the ganache chain and testnets.

I've checked the syntax and it looks like I'm doing it right, am I missing something here? Is there a better way to import?

Surely, I don't need to download each .sol file my contract depends on and put it in the contracts folder do I? Because each dependency for my contract has its own dependencies that I'd have to track down as well.

Any help is much appreciated.

this is the full contract:

   // SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import 'https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/interfaces/ILendingPool.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/interfaces/ILendingPoolAddressesProvider.sol';
import 'https://github.com/aave/protocol-v2/blob/master/contracts/dependencies/openzeppelin/contracts/IERC20.sol';

contract TheFlashLoan is FlashLoanReceiverBase {

    constructor() public {
        address owner = msg.sender; 
    }

    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params) external override returns (bool) {

        //
        // This contract now has the funds requested.
        // Your logic goes here.
        //

        // At the end of your logic above, this contract owes
        // the flashloaned amounts + premiums.
        // Therefore ensure your contract has enough to repay
        // these amounts.

        // Approve the LendingPool contract allowance to *pull* the owed amount
        for (uint i = 0; i < assets.length; i++) {
            // add lending fee to amount owed
            uint amountOwing = amounts[i].add(premiums[i]);
            IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
        }

        return true;
    }

    function startFlashLoan() public onlyOwner {
        address receiverAddress = address(this);

        address[] memory assets = new address[];
        //assets[0] = address(0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063); // DAI on Polygon
        assets[0] = address(0xaD6D458402F60fD3Bd25163575031ACDce07538D); // DAI on Ropsten

        uint256[] memory amounts = new uint256[];
        amounts[0] = 100;

        // 0 = no debt, 1 = stable, 2 = variable
        uint256[] memory modes = new uint256[];
        modes[0] = 0;

        address onBehalfOf = address(this);
        bytes memory params = "";
        uint16 referralCode = 0;

        LENDING_POOL.flashLoan(
            receiverAddress,
            assets,
            amounts,
            modes,
            onBehalfOf,
            params,
            referralCode
        );
    }

    modifier onlyOwner {
        assert(owner == msg.sender);
        _;
    }

    function Withdraw(address payable _to, uint256 _amount) external onlyOwner {
        _to.transfer(_amount);
    }

    function ShowBalance() public view onlyOwner returns(uint256) {
        return address(this).balance;
    }
}

I tried moving the contract to Remix and the import statements work but oddly enough Remix threw errors for each of the lines that look like this:

 uint256[] memory amounts = new uint256[];

For some reason it throws this error, which only goes away when I delete new uint256[]

The error it throws is:

contracts/Arbitrage/FL.sol:52:9: TypeError: Type function (uint256) pure returns (uint256[] memory) is not implicitly convertible to expected type uint256[] memory.
    uint256[] memory amounts = new uint256[];
    ^--------------------------------------^

If I delete the new uint256[] lines the code runs but now it throws an error saying my contract needs to be marked as abstract:

contracts/Arbitrage/FL.sol:10:1: TypeError: Contract "TheFlashLoan" should be marked as abstract.
    contract TheFlashLoan is FlashLoanReceiverBase {
    ^ (Relevant source part starts here and spans across multiple lines).
    https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol:18:3: Missing implementation: 
      constructor(ILendingPoolAddressesProvider provider) public {
      ^ (Relevant source part starts here and spans across multiple lines).

Could someone could also help enlighten me why it is doing this?

1

1 Answer 1

2

In order to import directly from github, you need to add the dependencies to your brownie-config.yaml file.

ie if you're trying to import from https://github.com/aave/protocol-v2/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol you'd need to have in your brownie-config.yaml:

dependencies:
  - aave/protocol-v2@1.0.1

Typically, this is combined with remappings:

compiler:
  solc:
    remappings:
      - '@aave=aave/protocol-v2@1.0.1'

And then in your solidity code you can do:

import '@aave/contracts/flashloan/base/FlashLoanReceiverBase.sol';

Additionally, you don't want to have stuff like "blob" and "master" in your imports. The brownie imports pull from specific releases and not from URLs. enter image description here

In our example, we used the 1.0.1 release version of Aave.

1
  • Thanks Patrick!! Just realized it was you who answered this. I'm currently working thru your Solidity Tutorial from freecodecamp. Amazing work! Oct 18, 2021 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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