// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
contract ERC721Example is Initializable, ERC721Upgradeable, OwnableUpgradeable {
uint256 private _nextTokenId;
string private _baseUri;
// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner, string memory name, string memory symbol, string memory baseUri) initializer public {
__ERC721_init(name, symbol);
__Ownable_init();
_baseUri = baseUri;
transferOwnership(initialOwner);
}
// Override _baseURI function to return the base URI for token metadata
function _baseURI() internal view override returns (string memory) {
return _baseUri;
}
// Mint function to create a new token
function mint(address to) external onlyOwner {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
}
// Internal function to update the base URI
function setBaseURI(string memory baseUri) external onlyOwner {
_baseUri = baseUri;
}
// Return token URI with tokenId appended to base URI
function tokenURI(uint256 tokenId) public view override returns (string memory) {
return string(abi.encodePacked(_baseURI(), StringsUpgradeable.toString(tokenId)));
}
}
Initialization with baseUri
: Instead of using extendData
to store the base URI, I switched to directly using the baseUri
parameter in the initialize
function. This simplifies deployment and makes it easier to customize after deployment.
setBaseURIfunction: Added a
setBaseURIfunction, allowing the contract owner to change the
baseUriafter the contract is deployed. Added
tokenURIfunction: Updated the token URI for each token based on its
tokenId, allowing easy retrieval of metadata for each specific token. Optimized ownership management: Used
transferOwnershipin
initialize` to transfer ownership of the contract, making the code easier to manage.