Токены ERC721 с метаданными и перечисляемыми с помощью Openzeppelin v4.1.0
Мой вопрос состоит из двух частей,
Я пытаюсь создать токен ERC721, используя контракты Openzeppelin с метаданными, и это можно перечислить. Насколько я понимаю, после openzeppelin v4.0.0 они удалили контракт ERC721Full.sol, который включал метаданные и перечисляемый. Я хочу использовать Solidity 0.8.0, поэтому старые контракты работать не будут, верно? При импорте и наследовании ERC721Enumerable.sol в контракт ERC721.sol я получаю
TypeError: Definition of base has to precede definition of derived contract
Я попытался просто импортировать ERC721Enumerable.sol в свой собственный контракт, но все же ошибки. Я также попытался импортировать более старый контракт ERC721Full.sol и изменить всю прагму 0.5.0 на прагму 0.8.0, но он наследуется, как и дюжина других контрактов, и изменение всех из них не кажется разумным. Я пробовал то же самое с IERC721Enumerable.sol, все еще ошибки. Любые идеи? Любая помощь была бы потрясающей!
Вторая часть. В чем разница между ERC__ и IERC__? Какова цель контрактов IERC?
Спасибо!!
2 ответа
Для первой части
ERC721 по умолчанию не имеет метода, и это причина, по которой вы получаете ошибку. В
totalSupply
Метод исходит из IERC721Enumerable, который, как указано в документации , является дополнительным расширением стандарта ERC721 . Если вы хотите, чтобы ваш ERC721 был перечислимым, просто импортируйте перечислимое расширение из реализаций openzeppelin для вашего производного контракта , например:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721Enumerable {
string[] public colors;
mapping(string => bool) _colorExists;
constructor() ERC721("Color", "COLOR") {
}
function mint(string memory _color) public {
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
Причина, по которой компилятор выдал вам ошибку при попытке импортировать ERC721Enumerable, заключается в том, что вы пытались импортировать его в реализацию OpenzeppelinERC721, но этот контракт должен был существовать до ERC721Enumberable. Другими словами, цепочка наследования
ERC721 <-- ERC721Enumerable
То, что вы пытались сделать, было
ERC721 <-- ERC721Enumerable
|_____________↑
Это создает круговую зависимость, которая не может быть удовлетворена.
Для второй части
Контракты ERC похожи на классы абстрактов во всех языках программирования ООП (первое, что приходит мне в голову и, возможно, наиболее подходящие - это Java и C ++), в то время как IERC - это интерфейсы; это означает, что, хотя оба они не могут быть созданы напрямую (им обоим нужны дочерние элементы для реализации чего-либо), контракты ERC предоставляют стандартные реализации для соответствующих методов IERC. Это причина, по которой вы часто видите, что контракты реализуют контракты ERC, а не IERC.
Чтобы использовать расширение ERC271Enumerable, вам необходимо реализовать его и переопределить некоторые функции ERC271,
_beforeTokenTransfer
а также
supportsInterface
.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract Color is ERC721, ERC721Enumerable{
string[] public colors;
mapping(string => bool) _colorExists;
constructor () ERC721("Color", "COLORS") {}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function mint(string memory _color) public{
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
В чем разница между ERC__ и IERC__? Какова цель контрактов IERC?
- IERC - это интерфейс для контракта токена.
- ERC - это реализация токен-контракта.
Важно убедиться, что реализация контракта имеет правильные методы с правильной видимостью, параметрами и возвращаемыми значениями.