Prechádzať zdrojové kódy

Fix ERC4906 compliance of ERC721URIStorage (#4055)

Co-authored-by: Francisco <fg@frang.io>
Hadrien Croubois 2 rokov pred
rodič
commit
08d085f2c9

+ 7 - 0
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}.
      */

+ 4 - 1
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);

+ 4 - 2
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);