Токены 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 - это реализация токен-контракта.

Важно убедиться, что реализация контракта имеет правильные методы с правильной видимостью, параметрами и возвращаемыми значениями.

Другие вопросы по тегам