When creating contracts automatically, I have had some doubts about the import of some contracts and some of the functions shown.
For example, we create an updatable contract that is minteable, enumerable and ownable:
The first question I have is about the need to import ERC721EnumerableUpgradeable.sol together with ERC721Upgradeable.sol.
The Enumerable contract already imports internally the ERC721Upgradeable, so it seems to me an unnecessary import.
In fact, if you ONLY import ERC721EnumerableUpgradeablel, the contract works correctly:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MyToken is Initializable, ERC721EnumerableUpgradeable, OwnableUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner) initializer public {
__ERC721_init("MyToken", "MTK");
__ERC721Enumerable_init();
__Ownable_init(initialOwner);
}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
// The following functions are overrides required by Solidity.
function _update(address to, uint256 tokenId, address auth)
internal
override( ERC721EnumerableUpgradeable)
returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value)
internal
override( ERC721EnumerableUpgradeable)
{
super._increaseBalance(account, value);
}
function supportsInterface(bytes4 interfaceId)
public
view
override( ERC721EnumerableUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
The second question is somewhat similar. What is the need to override the functions _update
, _increaseBalance
?
Especially because there is a comment that warns about it and I don't understand its necessity:
If I remove them, it compiles perfectly:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MyToken is Initializable, ERC721EnumerableUpgradeable, OwnableUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address initialOwner) initializer public {
__ERC721_init("MyToken", "MTK");
__ERC721Enumerable_init();
__Ownable_init(initialOwner);
}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override( ERC721EnumerableUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Obviously that doesn't mean I'm doing it right. And if you put a comment it must be for a reason unknown to me.
Would you be so kind as to explain to me the reasons for this required by solidity?