简体   繁体   English

ERC721 令牌与元数据和 Enumerable 与 Openzeppelin v4.1.0

[英]ERC721 Tokens with Metadata and Enumerable with Openzeppelin v4.1.0

My question has two parts,我的问题有两个部分,

I am trying to create an ERC721 token using the Openzeppelin contracts with metadata and that is enumerable.我正在尝试使用带有元数据的 Openzeppelin 合同创建一个 ERC721 令牌,这是可枚举的。 My understanding is after openzeppelin v4.0.0 they removed the ERC721Full.sol contract which included metadata and enummerable.我的理解是在 openzeppelin v4.0.0 之后,他们删除了包含元数据和可枚举的 ERC721Full.sol 合约。 I want to use solidity 0.8.0 and so those old contracts wont work, right?我想使用solidity 0.8.0,所以那些旧合同不起作用,对吧? When importing and inheriting ERC721Enumerable.sol into the ERC721.sol contract, I get TypeError: Definition of base has to precede definition of derived contract I tried just importing ERC721Enumerable.sol in my own contract, but still errors.在将 ERC721Enumerable.sol 导入并继承到 ERC721.sol 合约中时,我得到TypeError: Definition of base has to precede definition of derived contract我尝试在自己的合约中导入 ERC721Enumerable.sol,但仍然出现错误。 I also tried importing the older ERC721Full.sol contract and changing all the pragma 0.5.0 to pragma 0.8.0, but it inherits like a dozen other contracts and changing all of them doesn't seem wise.我还尝试导入较旧的 ERC721Full.sol 合同并将所有 pragma 0.5.0 更改为 pragma 0.8.0,但它像十几个其他合同一样继承并且更改所有合同似乎并不明智。 I tried the same with IERC721Enumerable.sol, still errors.我对 IERC721Enumerable.sol 进行了同样的尝试,但仍然有错误。 Any ideas?有任何想法吗? Any help would be amazing!任何帮助都会很棒!

Second part.第二部分。 What's the difference between ERC__ and IERC__? ERC__ 和 IERC__ 有什么区别? What's the purpose of IERC contracts? IERC 合约的目的是什么?

Thanks!!谢谢!!

Here's my contract (I'm following a tutorial).这是我的合同(我正在学习教程)。 I import the regular ERC721 contract, inherit it.我导入常规的 ERC721 合约,继承它。 it gives me an error when I test and call the totalSupply function because there is no totalSupply function:当我测试并调用 totalSupply function 时,它给了我一个错误,因为没有 totalSupply function:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";


contract Color is ERC721 {
    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;

    }
}

my test script:我的测试脚本:

const Color = artifacts.require('./Color.sol')

require('chai')
    .use(require('chai-as-promised'))
    .should()

contract('Color', (accounts) => {
    let contract

    before(async () => {
        contract = await Color.deployed()
    })

    describe('deployment', async () => {
        it('deploys successfully', async () => {
            contract = await Color.deployed()
            const address = contract.address
            console.log(address)
            assert.notEqual(address, 0x0)
            assert.notEqual(address,'')
            assert.notEqual(address, null)
            assert.notEqual(address, undefined)


        })
        it('has a name', async () => {
            const name = await contract.name()
            assert.equal(name, 'Color')

        })
        it('has a symbol', async () => {
            const symbol = await contract.symbol()
            assert.equal(symbol, 'COLOR')

        })
    })

    describe('minting', async () => {
        it('creates a new token', async () => {
            const result = await contract.mint('#00CD22')
            const totalSupply = await contract.totalSupply()

            // SUCCESS
            asert.equal(totalSupply, 1)
        })
    })
})

this is my error without the enumerable contract/without totalSupply这是我的错误,没有可枚举的合同/没有 totalSupply

I can paste the openzeppelin contracts if you like, or link them here如果您愿意,我可以粘贴 openzeppelin 合同,或在此处链接它们

I also tried this, importing ERC721Enumerable我也试过这个,导入 ERC721Enumerable

And got this:得到了这个:

let me know fi you need anymore info!让我知道你需要更多信息! thanks in advance提前致谢

For the first part对于第一部分

An ERC721 by default does not have a totalSupply method, and that's the reason you're getting the error.默认情况下,ERC721 没有totalSupply方法,这就是您收到错误的原因。 The totalSupply method comes from the IERC721Enumerable, wich is an optional extension of the standard ERC721 as the documentation states . totalSupply方法来自 IERC721Enumerable,它是标准 ERC721 的可选扩展,如文档所述 If you want your ERC721 to be enumerable just import the enumerable extension from the openzeppelin implementations for your derived contract , like so:如果您希望 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;

    }
}

The reason the compiler gave you the error when trying to import ERC721Enumerable is that you were tryning to import it in the Openzeppelin ERC721 implementation, but that contract had to exists prior to the ERC721Enumberable.尝试导入 ERC721Enumerable 时编译器给您错误的原因是您试图在 Openzeppelin ERC721 实现中导入它,但该合约必须在 ERC721Enumerable 之前存在。 In other words the inheritance chain is换句话说,inheritance 链是

ERC721 <-- ERC721Enumerable

What you were trying to do was你想做的是

ERC721 <-- ERC721Enumerable
   |_____________↑

Wich creates a circular dependency that cannot be satisfied. Wich 创建了一个无法满足的循环依赖。

For the second part对于第二部分

ERC contracts are like abstracts classes in every OOP programming languages (first that come to my mind and maybe most relatable are Java and C++), while IERC are interfaces; ERC 合约就像 OOP 编程语言中的抽象类(首先想到的可能最相关的是 Java 和 C++),而 IERC 是接口; this means that while both cannot be instanciated directly (they both need the children to implement something) ERC contracts provide standard implementations for the corresponding IERC methods.这意味着虽然两者都不能直接实例化(它们都需要孩子来实现某些东西),但 ERC 合约为相应的 IERC 方法提供了标准实现。 This is the reason often you see contracts implement the ERC contracts and not the IERC ones.这就是你经常看到合约执行 ERC 合约而不是 IERC 合约的原因。

To use the ERC271Enumerable extension you need to implement it and override some functions of ERC271, _beforeTokenTransfer and supportsInterface .要使用 ERC271Enumerable 扩展,您需要实现它并覆盖 ERC271、 _beforeTokenTransfersupportsInterface的一些功能。

// 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;
  }
}

What's the difference between ERC__ and IERC__? ERC__ 和 IERC__ 有什么区别? What's the purpose of IERC contracts? IERC 合约的目的是什么?

  • IERC is the Interface for the token contract. IERC 是代币合约的接口。
  • ERC is the implementation of the token contract. ERC 是代币合约的实现。

The importance is to make sure a Contract implementation has the right methods, with the right visibility, parameters, and return values.重要的是确保合约实现具有正确的方法、正确的可见性、参数和返回值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM