Ownable contract owner is always the 0 address

When using Ownable, the owner of the contract is always the null address.

pragma solidity ^0.5.0;

import "@openzeppelin/contracts/ownership/Ownable.sol";

contract Tester is Ownable {
    function sayHi() public view returns(string memory) {
        return "hi";
    }
}

Then deploy it to my local blockchain with openzeppelin create. Calling openzeppelin call on the owner function will result in 0x0000000000000000000000000000000000000000. I have no clue how to proceed.

1 Like

Hi @Chrissie,

Sorry to hear that you got stuck with this.

To learn more on using OpenZeppelin Contracts and initializing with upgradeable contracts I would recommend reading:
Linking OpenZeppelin contracts and Writing upgradeable contracts

The key points in this case are:

We need to use @openzeppelin/contracts-ethereum-package with upgradeable contracts
Though use version 2.2.3 due to OpenZeppelin/openzeppelin-contracts-ethereum-package#70
oz link @openzeppelin/contracts-ethereum-package@2.2.3

https://docs.openzeppelin.com/sdk/2.5/linking
Make sure you install @openzeppelin/contracts-ethereum-package and not the vanilla @openzeppelin/contracts. The latter is set up for general usage, while @openzeppelin/contracts-ethereum-package is tailored for being used with the OpenZeppelin SDK. This means that its contracts are already set up to be upgradeable.

We also need to call initialize of Ownable. https://docs.openzeppelin.com/sdk/2.5/writing-contracts#use-upgradeable-packages


The following walks through creating example Tester contract with Ownable:

Install and Link

npm install @openzeppelin/upgrades 
openzeppelin link @openzeppelin/contracts-ethereum-package@2.2.3

Tester.sol

pragma solidity ^0.5.0;

// Import base Initializable contract
import "@openzeppelin/upgrades/contracts/Initializable.sol";

// Import ownable from OpenZeppelin contracts
import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol";

contract Tester is Initializable, Ownable {

    // Initializer function (replaces constructor)
    function initialize(address sender) public initializer {
        Ownable.initialize(sender);
    }

    function sayHi() public pure returns(string memory) {
        return "hi";
    }
}

Create contract

When creating, we need to call the initialize function initialize(sender: address) with the address that we want to be the owner (we can call oz accounts to get a list of accounts in ganache-cli)

$ oz create
βœ“ Compiled contracts with solc 0.5.12 (commit.7709ece9)
? Pick a contract to instantiate Tester
? Pick a network development
βœ“ Deploying @openzeppelin/contracts-ethereum-package dependency to network dev-1572237440500
βœ“ Contract Tester deployed
All contracts have been deployed
? Call a function to initialize the instance after creating it? Yes
? Select which function * initialize(sender: address)
? sender (address): 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
βœ“ Setting everything up to create contract instances
βœ“ Instance created at 0xe93e3B649d4E01e47dd2170CAFEf0651477649Da
0xe93e3B649d4E01e47dd2170CAFEf0651477649Da

Check

$ oz call
? Pick a network development
? Pick an instance Tester at 0xe93e3B649d4E01e47dd2170CAFEf0651477649Da
? Select which function owner()
βœ“ Method 'owner()' returned: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1

Let me know if you have any questions or if the documentation can be improved.

1 Like

Hi @Chrissie,

I wanted to check that you are no longer stuck on this?

Hi Andrew,
You were absolutely right, it was about the difference between @openzeppelin/contracts-ethereum-package and @openzeppelin/contracts.
Maybe we can clarify this in some way, because the first Google result on openzeppelin upgradeable ownable results in https://openzeppelin.com/contracts/ without any mention of the upgradeable version.

1 Like

Hi @Chrissie,

It would be good to improve this experience to save other community members from what you went through.
Where would you have expected to see a note on the upgradeable version, so that we can look to add one there.

Linking the Contracts Ethereum Package OpenZeppelin SDK documentation has the following note:

Make sure you install @openzeppelin/contracts-ethereum-package and not the vanilla @openzeppelin/contracts. The latter is set up for general usage, while @openzeppelin/contracts-ethereum-package is tailored for being used with the OpenZeppelin SDK. This means that its contracts are already set up to be upgradeable.

There is also a discussion on how contracts and contracts-ethereum-package could be made into a single offering:

Hey @Chrissie! Starting with 2.7 RC, the OpenZeppelin CLI will warn if you try to use the vanilla @openzeppelin/contracts instead of @openzeppelin/contracts-ethereum-package. This is temporary though, as we are working on unifying both of them. Give the new RC a try and let us know what you think!

1 Like