我的问题有两部分,
我正在尝试使用带有元数据的Openzeppelin合约创建一个ERC721令牌,该令牌是可枚举的。我的理解是,在openzeppelin v4.0之后,他们删除了包含元数据和可枚举的ERC721Full.sol合同。我想使用0.8.0的solidity,这样那些旧合同就不起作用了,对吧?当将ERC721Enumerable.sol导入并继承到ERC721.sol合约中时,我得到TypeError: Definition of base has to precede definition of derived contract
我尝试在自己的合同中导入ERC721Enumerable.sol,但仍然有错误。我还尝试导入旧的ERC721Full.sol合同,并将所有的pragma 0.5.0更改为pragma 0.8.0,但它像其他十几个合同一样继承,更改所有这些合同似乎并不明智。我在IERC721Enumerable.sol上尝试了同样的操作,但仍然存在错误。有什么想法吗?任何帮助都将是惊人的!
第二部分。ERC__和IERC__之间有什么区别?IERC合同的目的是什么?
谢谢!!
这是我的合同(我正在学习教程(。我导入了常规的ERC721合约,继承它。当我测试和调用totalSupply函数时,它给了我一个错误,因为没有totalSupply:
// 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;
}
}
我的测试脚本:
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)
})
})
})
这是我的错误,没有可列举的合同/没有totalSupply
如果你愿意,我可以粘贴openzeppelin合同,或者将它们链接到这里
我也尝试过,导入ERC721Enumerable
得到了这个:
如果你需要更多信息,请告诉我!提前感谢
对于第一部分
默认情况下,ERC721没有totalSupply
方法,这就是出现错误的原因。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时给您错误的原因是您试图在Openzeppelin ERC721实现中导入它,但该约定必须在ERC721Enumberable之前存在。换句话说,继承链是
ERC721 <-- ERC721Enumerable
你想做的是
ERC721 <-- ERC721Enumerable
|_____________↑
Wich创建了一个无法满足的循环依赖关系。
第二部分
ERC契约就像每种OOP编程语言中的抽象类(首先想到的,可能最相关的是Java和C++(,而IERC是接口;这意味着,虽然两者都不能直接实例化(它们都需要子代来实现某些东西(,但ERC合同为相应的IERC方法提供了标准实现。这就是为什么你经常看到合同执行ERC合同而不是IERC合同的原因。
要使用ERC271可枚举扩展,需要实现它并覆盖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是代币合约的实现
重要的是确保合同实施具有正确的方法、正确的可见性、参数和返回值。