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.

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.