Which package to use for upgradable and ownable contracts?

Hi,

I want to create an ERC721 upgradable and ownable contract. I followed the box tutorial for creating an upgradable contract and added the ERC721Upable.sol. Later on, I followed the tutorial for adding ownable to the upgradable contract. I am very confused about the packages that I have to add to my contract and they introduced compiling errors. There are two Initializable files that were introduced by the tutorials, one is from contract-ethereum-package and another one is from contracts-upgradeable. Which one should I use?

here is my base contract

MyContract.sol

    pragma solidity >=0.6.0 <0.8.0;

    import "@openzeppelin/contracts-ethereum-package/contracts/access/Ownable.sol";
    import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";
    import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
    import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";

        import "hardhat/console.sol";

        contract MyContract is 
            Initializable, 
            OwnableUpgradeSafe,
            ContextUpgradeable, 
            ERC721Upgradeable
        {
          ...
            function initialize() public initializer {
                __ERC721_init("MyCollectible", "MCO");
                OwnableUpgradeSafe.__Ownable_init();
            }
           ...
        }

And here is my hardhat.config.js file:

    /**
     * @type import('hardhat/config').HardhatUserConfig
     */

    require("@nomiclabs/hardhat-waffle");
    require('@nomiclabs/hardhat-ethers');
    require('@openzeppelin/hardhat-upgrades');
    require('dotenv').config()

    module.exports = {
      solidity: {
        compilers: [
          {
            version: "0.6.2"
          },
          {
            version: "0.7.3"
          }
        ]
      },
      settings: {
        optimizer: {
          enabled: true,
          runs: 200
        }
      },
      paths: {
        sources: './contracts',
        cache: './cache',
        tests: './tests',
        artifacts: './artifacts'
      }
    };

And here is my compiler error:

Compiling 5 files with 0.6.2
contracts/MyContract.sol:7:1: DeclarationError: Identifier already declared.
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
^-------------------------------------------------------------------^
@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol:16:1: The previous declaration is here:
contract Initializable {
^ (Relevant source part starts here and spans across multiple lines).

contracts/MyContract.sol:8:1: DeclarationError: Identifier already declared.
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
^------------------------------------------------------------------------------^
@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol:16:1: The previous declaration is here:
contract Initializable {
^ (Relevant source part starts here and spans across multiple lines).

Error HH600: Compilation failed

Can you please tell me what is the proper way to work with a nERC721 upgradeable and ownable contract? Thanks

1 Like

Hi @dappCoder,

Welcome to the community :wave:

We should use OpenZeppelin Contracts Upgradeable (OpenZeppelin Contracts Ethereum Package was the previous OpenZeppelin Contracts upgradeable version).

See the documentation for how to use:

https://docs.openzeppelin.com/contracts/3.x/upgradeable#multiple-inheritance

If you need an example, you can check out the ERC721 preset:

Your contract could look something like the following:

// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";

contract MyContract is
    Initializable,
    ContextUpgradeable,
    OwnableUpgradeable,
    ERC721Upgradeable
{
    function initialize() public initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __ERC721_init_unchained("MyCollectible", "MCO");
        __Ownable_init_unchained();
    }
}

Please note OpenZeppelin Contracts 4.0 Beta is going to be released soon, see: Contracts 4.0 Timeline.

Depending on your timeline you may want to use OpenZeppelin Contracts 4 when it is released.


As an aside you can Format code in the forum.

Thank you. It was very helpful. I got my problem fixed.

1 Like