Using Ownable + Upgradeable

I’ve successfully built/compiled/deployed my upgradeable, ownable, EC721 to my local devnet. :tada:

However, when I attempt to send-tx to a function modified as onlyOwner, it fails with:

Error while trying to send transaction to 0x0E696947A06550DEf604e82C26fd9E493e576337.
Error: Returned error: VM Exception while processing transaction: revert
Ownable: caller is not the owner

This makes sense, I think, since it was deployed as upgradeable, and there is now a proxy contract (as I understand it) in place, which is now actually the owner(?).

In order for onlyOwner and other access control methods to work, do I need to explicitly set the _msgSender in the initializer, or have I done something else incorrectly?

This is solved.

First, Ownable is not necessary/appropriate if one is using the ERC721PresetMinterPauserAutoId.sol package, since AccessControl is included and preferred.

Then, to make certain functions “onlyOwner,” or, in AccessControl default language, the MINTER_ROLE, add this to one’s function:

require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");


1 Like

Hi @EvilJordan,

Glad you were able to resolve.

With upgradeable contracts we need to import OpenZeppelin Contracts Ethereum Package which is the version created for upgrades.

If we wanted to use Ownable we would need to initialize Ownable UpgradeSafe:


// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

// Import Ownable from the OpenZeppelin Contracts Ethereum Package library
import "@openzeppelin/contracts-ethereum-package/contracts/access/Ownable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";

// Make Box inherit from the Ownable contract
contract Box is OwnableUpgradeSafe {
    uint256 private value;

    event ValueChanged(uint256 newValue);

    function initialize() public initializer {

    // The onlyOwner modifier restricts who can call the store function
    function store(uint256 newValue) public onlyOwner {
        value = newValue;
        emit ValueChanged(newValue);

    function retrieve() public view returns (uint256) {
        return value;
1 Like