diff --git a/contracts/token/ERC721/extensions/ERC721URIStorage.sol b/contracts/token/ERC721/extensions/ERC721URIStorage.sol index 4b919b79e..201b05a81 100644 --- a/contracts/token/ERC721/extensions/ERC721URIStorage.sol +++ b/contracts/token/ERC721/extensions/ERC721URIStorage.sol @@ -15,6 +15,13 @@ abstract contract ERC721URIStorage is IERC4906, ERC721 { // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; + /** + * @dev See {IERC165-supportsInterface} + */ + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) { + return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId); + } + /** * @dev See {IERC721Metadata-tokenURI}. */ diff --git a/test/token/ERC721/extensions/ERC721URIStorage.test.js b/test/token/ERC721/extensions/ERC721URIStorage.test.js index 0835505e9..60c80066c 100644 --- a/test/token/ERC721/extensions/ERC721URIStorage.test.js +++ b/test/token/ERC721/extensions/ERC721URIStorage.test.js @@ -1,7 +1,8 @@ const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); - const { expect } = require('chai'); +const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior'); + const ERC721URIStorageMock = artifacts.require('$ERC721URIStorageMock'); contract('ERC721URIStorage', function (accounts) { @@ -17,6 +18,8 @@ contract('ERC721URIStorage', function (accounts) { this.token = await ERC721URIStorageMock.new(name, symbol); }); + shouldSupportInterfaces(['0x49064906']); + describe('token URI', function () { beforeEach(async function () { await this.token.$_mint(owner, firstTokenId); diff --git a/test/utils/introspection/SupportsInterface.behavior.js b/test/utils/introspection/SupportsInterface.behavior.js index ba5aca2fc..02d147884 100644 --- a/test/utils/introspection/SupportsInterface.behavior.js +++ b/test/utils/introspection/SupportsInterface.behavior.js @@ -100,20 +100,22 @@ function shouldSupportInterfaces(interfaces = []) { it('supportsInterface uses less than 30k gas', async function () { for (const k of interfaces) { - const interfaceId = INTERFACE_IDS[k]; + const interfaceId = INTERFACE_IDS[k] ?? k; expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.be.lte(30000); } }); it('all interfaces are reported as supported', async function () { for (const k of interfaces) { - const interfaceId = INTERFACE_IDS[k]; + const interfaceId = INTERFACE_IDS[k] ?? k; expect(await this.contractUnderTest.supportsInterface(interfaceId)).to.equal(true); } }); it('all interface functions are in ABI', async function () { for (const k of interfaces) { + // skip interfaces for which we don't have a function list + if (INTERFACES[k] === undefined) continue; for (const fnName of INTERFACES[k]) { const fnSig = FN_SIGNATURES[fnName]; expect(this.contractUnderTest.abi.filter(fn => fn.signature === fnSig).length).to.equal(1);