Skip to content

Commit

Permalink
Add IERC4906 interface and use in ERC721 (#4012)
Browse files Browse the repository at this point in the history
Co-authored-by: Francisco Giordano <fg@frang.io>
  • Loading branch information
Amxx and frangio committed Feb 17, 2023
1 parent d64d7aa commit 96a2297
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-dragons-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`IERC4906`: Add an interface for ERC-4906 that is now Final.
5 changes: 5 additions & 0 deletions .changeset/thirty-swans-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`ERC721URIStorage`: Emit ERC-4906 `MetadataUpdate` in `_setTokenURI`.
19 changes: 19 additions & 0 deletions contracts/interfaces/IERC4906.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";
import "./IERC721.sol";

/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
/// @dev This event emits when the metadata of a token is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFT.
event MetadataUpdate(uint256 _tokenId);

/// @dev This event emits when the metadata of a range of tokens is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFTs.
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
7 changes: 6 additions & 1 deletion contracts/token/ERC721/extensions/ERC721URIStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../interfaces/IERC4906.sol";

/**
* @dev ERC721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is ERC721 {
abstract contract ERC721URIStorage is IERC4906, ERC721 {
using Strings for uint256;

// Optional mapping for token URIs
Expand Down Expand Up @@ -38,13 +39,17 @@ abstract contract ERC721URIStorage is ERC721 {
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Emits {MetadataUpdate}.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;

emit MetadataUpdate(tokenId);
}

/**
Expand Down
8 changes: 7 additions & 1 deletion test/token/ERC721/extensions/ERC721URIStorage.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { BN, expectRevert } = require('@openzeppelin/test-helpers');
const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');

const { expect } = require('chai');

Expand Down Expand Up @@ -38,6 +38,12 @@ contract('ERC721URIStorage', function (accounts) {
expect(await this.token.tokenURI(firstTokenId)).to.be.equal(sampleUri);
});

it('setting the uri emits an event', async function () {
expectEvent(await this.token.$_setTokenURI(firstTokenId, sampleUri), 'MetadataUpdate', {
_tokenId: firstTokenId,
});
});

it('reverts when setting for non existent token id', async function () {
await expectRevert(
this.token.$_setTokenURI(nonExistentTokenId, sampleUri),
Expand Down

0 comments on commit 96a2297

Please sign in to comment.