OpenZeppelin/contracts-wizard

Correct generation of supportsInterface for ERC Tokens using Access Control

johnwhitton opened this issue · 1 comments

When generating ERC tokens using the open zeppelin wizard
erc1155OpenZeppelinWizard
The code generated is as follows

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "[@openzeppelin/contracts/token/ERC1155/ERC1155.sol](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.3/contracts/token/ERC1155/ERC1155.sol)";
import "[@openzeppelin/contracts/access/AccessControl.sol](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.3/contracts/access/AccessControl.sol)";

contract MyToken is ERC1155, AccessControl {
    bytes32 public constant URI_SETTER_ROLE = keccak256("URI_SETTER_ROLE");

    constructor() ERC1155("") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(URI_SETTER_ROLE, msg.sender);
    }

    function setURI(string memory newuri) public onlyRole(URI_SETTER_ROLE) {
        _setURI(newuri);
    }

    // The following functions are overrides required by Solidity.

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC1155, AccessControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

However the supportsInterface function should be

 function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC1155, AccessControl)
        returns (bool)
    {
        return (ERC1155.supportsInterface(interfaceId) ||
            AccessControl.supportsInterface(interfaceId));
    }

This was discussed here on the open zeppelin forum. Where it was stated

The generated code should be more like this

function supportsInterface(bytes4 interfaceId) public view override(ERC721, AccessControl, ERC2981, IERC165, ERC165) returns (bool) {
        return (
            ERC1155.supportsInterface(interfaceId) || 
            AccessControl.supportsInterface(interfaceId) ||
            ERC2981.supportsInterface(interfaceId) ||
            ERC165.supportsInterface(interfaceId)
        );
    }

This is not correct. The code generated by the Wizard is the right way to override this function. The super calls will get chained and will execute all of the parent implementations.

I added an explanation in the forum: https://forum.openzeppelin.com/t/derived-contract-must-override-function-supportsinterface/6315/12?u=frangio