Introduction
Hi, I see almost NFT applications are using ERC721, so after the NFT start-up trend, there will be many companies that run out of capital and dissolve. At that time they will shutdown their servers and many of the images associated with the NFT will be inaccessible. Should we need create a contract that allows the holder to update the image URI.
Contract Interface
// SPDX-License-Identifier: MIT
// From: youngmonkeys.org
pragma solidity ^0.8.0;
/**
* @dev Required interface of an ERC722 compliant contract.
* After the NFT start-up trend, there will be many companies that run out of capital and dissolve.
* At that time they will shut down their servers and many of the images associated with the NFT will be inaccessible.
* Should we create a token that allows the holder to update the image URI
*/
interface IERC722 {
/**
* Get the owner of the tokens
*/
function tokensOwner() external view returns (address);
/**
* Get the contract created the tokens
*/
function tokensContract() external view returns (address);
/**
* Get the lastest URI of the `tokenId`
* Requirements:
*
* - `tokenId` must exist.
*/
function latestTokenURI(
uint256 tokenId
) external view returns (string memory);
/**
* Set the lastest URI of the `tokenId`
* Requirements:
*
* - `tokenId` must exist.
* - `tokenURI` must exist.
*/
function setLatestTokenURI(
uint256 tokenId,
string memory tokenURI
) external;
/**
* Set the lastest URI of the `tokenId`
* Requirements:
*
* - `submitter` must exist.
* - `tokenId` must exist.
* - `tokenURI` must exist.
*/
function safeSetLatestTokenURI(
address submitter,
uint256 tokenId,
string memory tokenURI
) external;
}
Implementation
// SPDX-License-Identifier: MIT
// From: youngmonkeys.org
pragma solidity ^0.8.0;
import "./IERC722.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC722] Replace URI of Non-Fungible Tokens
*/
contract ERC722 is IERC722 {
// Owner of the tokens
address private _tokensOwner;
// Contract of the tokens
address private _tokensContract;
// Mapping from token ID to an URI
mapping(uint256 => string) private _latestTokenURIs;
/**
* @dev Initializes the contract by setting a `tokensOwner` and a `tokensContract`
*/
constructor(address tokensOwner, address tokensContract) {
_tokensOwner = tokensOwner_;
_tokensContract = tokensContract_;
}
/**
* @dev See {IERC721-ownerOf}.
*/
function tokensOwner() public view override returns (address) {
return _tokensOwner;
}
/**
* @dev See {IERC721-ownerOf}.
*/
function tokensContract() public view override returns (address) {
return _tokensContract;
}
/**
* @dev See {IERC721-latestTokenURI}.
*/
function latestTokenURI(
uint256 tokenId
) public view override returns (string memory) {
return _latestTokenURIs[tokenId];
}
/**
* @dev See {IERC721-setLatestTokenURI}.
*/
function setLatestTokenURI(
uint256 tokenId,
string memory tokenURI
) public override {
require(_isTokenOwner(msg.sender), "You are not the token's owner.");
_latestTokenURIs[tokenId] = tokenURI;
}
/**
* @dev See {IERC721-safeSetLatestTokenURI}.
*/
function safeSetLatestTokenURI(
address submitter,
uint256 tokenId,
string memory tokenURI
) public override {
require(_isTokenOwner(submitter), "Submitter are not the token's owner.");
_latestTokenURIs[tokenId] = tokenURI;
}
function _isTokenOwner(address sender) internal view virtual returns (bool) {
return _tokensOwner == sender_;
}
}