Brownie – Issue with Importing Chainlink & OpenZeppelin in Python

browniechainlinkopenzeppelinpython

Advanced Collectible Contract

Brownie Config

brownie run scripts/advanced_collectible/deploy_advanced.py

Currently trying to run a script and keep running into an error when trying to import chainlink and openzeppelin contracts. Not sure why, I looked at brownie pm list to make sure I have the correct versions install as well.

Any advice would be appreciated. Thanks!

Code from AdvancedCollectible.sol:

pragma solidity 0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

contract AdvancedCollectible is ERC721, VRFConsumerBase{
    uint256 public tokenCounter;
    enum Breed{PUG, SHIBA_INU, ST_BERNARD}
    //add other things
    mapping(bytes32 => address) public requestIdToSender;
    mapping(bytes32 => string) public requestIdToTokenURI;
    mapping(uint256 => Breed) public tokenIdToBreed;
    mapping(bytes32 => uint256) public requestIdToTokenId;
    event requestedCollectible(bytes32 indexed requestId); 

    bytes32 internal keyHash;
    uint256 public fee;

    constructor(address _VRFCoordinator, address _LinkToken, bytes32 _keyhash)
    public
    VRFConsumerBase(_VRFCoordinator, _LinkToken)
    ERC721("Dogges", "DOGGE")
    {
        keyHash = _keyhash;
        fee = 0.1 * 10 ** 18; //0.1 LINK
    }
    function createCollectable(uint256 userProvidedSeed, string memory tokenURI) public returns (bytes32){
        bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
        requestIdToSender[requestId] = msg.sender;
        requestIdToTokenURI[requestId] = tokenURI;
        emit requestedCollectible(requestId);
    }
    function fulfillRandomness(bytes32 requestId, uint256 randomNumber) internal override{
        address dogOwner = requestIdToSender[requestId];
        string memory tokenURI = requestIdToTokenURI[requestId];
        uint256 newItemId = tokenCounter;
        _safeMint(dogOwner, newItemId);
        _setTokenURI(newItemId, tokenURI);
        Breed dogBreed = Breed(randomNumber % 3); 
        tokenIdToBreed[newItemId] = dogBreed;
        requestIdToTokenId[requestId] = newItemId;
        tokenCounter = tokenCounter + 1;
    }
    function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );
        _setTokenURI(tokenId, _tokenURI);
    }
}

Code from brownie.config.yaml

# exclude SafeMath when calculating test coverage
# https://eth-brownie.readthedocs.io/en/v1.10.3/config.html#exclude_paths
reports:
  exclude_contracts:
    - SafeMath
dependencies:
  - smartcontractkit/chainlink-brownie-contracts@1.0.2
  - OpenZeppelin/openzeppelin-contracts@3.4.0
compiler:
  solc:
    remappings:
      - '@chainlink=smartcontractkit/chainlink-brownie-contracts@1.0.2'
      - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@3.4.0'

Error:

Brownie v1.14.3 - Python development framework for Ethereum

Compiling contracts...
  Solc version: 0.6.6
  Optimizer: Enabled  Runs: 200
  EVM Version: Istanbul
CompilerError: solc returned the following errors:

contracts/AdvancedCollectible.sol:3:1: ParserError: Source "@openzeppelin/contracts/token/ERC721/ERC721.sol" not found: File outside of allowed directories.
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
^--------------------------------------------------------^

contracts/AdvancedCollectible.sol:4:1: ParserError: Source "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol" not found: File outside of allowed directories.
import ""@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
^-----------------------------------------------------------^

Update

Solution: corrected imports in AdvancedCollectible.sol to the following:

pragma solidity 0.6.6;

import "OpenZeppelin/openzeppelin-contracts@3.4.0/contracts/token/ERC721/ERC721.sol";
import "smartcontractkit/chainlink-brownie-contracts@1.0.2/contracts/src/v0.6/VRFConsumerBase.sol";

contract AdvancedCollectible is ERC721, VRFConsumerBase{
    uint256 public tokenCounter;
    enum Breed{PUG, SHIBA_INU, ST_BERNARD}
    //add other things
    mapping(bytes32 => address) public requestIdToSender;
    mapping(bytes32 => string) public requestIdToTokenURI;
    mapping(uint256 => Breed) public tokenIdToBreed;
    mapping(bytes32 => uint256) public requestIdToTokenId;
    event requestedCollectible(bytes32 indexed requestId); 

    bytes32 internal keyHash;
    uint256 public fee;

    constructor(address _VRFCoordinator, address _LinkToken, bytes32 _keyhash)
    public
    VRFConsumerBase(_VRFCoordinator, _LinkToken)
    ERC721("Dogges", "DOGGE")
    {
        keyHash = _keyhash;
        fee = 0.1 * 10 ** 18; //0.1 LINK
    }
    function createCollectable(uint256 userProvidedSeed, string memory tokenURI) public returns (bytes32){
        bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
        requestIdToSender[requestId] = msg.sender;
        requestIdToTokenURI[requestId] = tokenURI;
        emit requestedCollectible(requestId);
    }
    function fulfillRandomness(bytes32 requestId, uint256 randomNumber) internal override{
        address dogOwner = requestIdToSender[requestId];
        string memory tokenURI = requestIdToTokenURI[requestId];
        uint256 newItemId = tokenCounter;
        _safeMint(dogOwner, newItemId);
        _setTokenURI(newItemId, tokenURI);
        Breed dogBreed = Breed(randomNumber % 3); 
        tokenIdToBreed[newItemId] = dogBreed;
        requestIdToTokenId[requestId] = newItemId;
        tokenCounter = tokenCounter + 1;
    }
    function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );
        _setTokenURI(tokenId, _tokenURI);
    }
}

Best Answer

In your brownie.config.yaml, you are importing OpenZeppelin/openzeppelin-contracts@3.4.0, but in your .sol you are importing @oppenzeppelin/contracts/etc.... You should import the dependency as it says in your config. import "OpenZeppelin/openzeppelin-contracts@3.4.0/contracts/token/ERC721/ERC721.sol

Related Topic