2

I am deploying a proxy on an ERC721 and Ownable contract. The problem is that the constructor of Ownable is not called on the initialize function so the owner is not defined and the onlyOwner modifier is therefore not working appropriately. Any solution to this issue?

The beginning of the contract is the following:

contract Collection is ERC721URIStorage, Initializable, Ownable {
    string private __name;
    string private __symbol;
    string public collectionURI;
    uint256 public totalSupply;
    uint256 public maxTotalSupply;
    uint256 mintFee;

    constructor(
        string memory _name,
        string memory _token,
        uint256 _maxTotalSupply,
        string memory _collectionURI,
        uint256 _mintFee
    ) ERC721(_name, _token) {
        __name = _name;
        __symbol = _token;
        collectionURI = _collectionURI;
        maxTotalSupply = _maxTotalSupply;
        mintFee = _mintFee;
    }

    function initialize(
        string memory _name,
        string memory _token,
        uint256 _maxTotalSupply,
        string memory _collectionURI,
        uint256 _mintFee
    ) public initializer {
        __name = _name;
        __symbol = _token;
        collectionURI = _collectionURI;
        maxTotalSupply = _maxTotalSupply;
        mintFee = _mintFee;
    }

The variables __name and __symbol are the workaround I created so that it is not needed to call the ERC721 constructor. The problem is the Ownable contract that has the following line:

_transferOwnership(_msgSender());

Actually adding that line to the end of the initialize function on the contract works perfectly. I am wondering if there is a more elegant solution than those workarounds.

1 Answer 1

0

TLDR: There is not. You are following the correct patterns, you should delete the constructor

Constructors are only called during the contract deployment, proxies can't access that information as it's stored on the original contract not on the proxy.

This is why the ownable contract contains the internal function _transferOwnership(); You are following the correct pattern, it would be called in at the end of your initialize function.

You should get rid of the constructor in your example to avoid confusions and save gas as it will only be called during the deployment of the original contract, but any proxies pointing to it won't be able to see or access that information (Proxies need to leverage the initialize function)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.