3

我正在尝试从 open zeppelin 导入一些合约文件,以便我的solidity 智能合约可以继承它们的功能,当尝试编写在编译时在我的智能合约上运行的 chai 测试时,我的 chai 测试出现错误。

  3 passing (2s)
  1 failing

  1) Contract: Color
       minting
         creates a new token:
     TypeError: contract.totalSupply is not a function

我的合同导入了 openzeppelin 合同

pragma solidity 0.8.7;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; //import base functionality
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; //import totalsupply()

contract color is ERC721 {
    string[] public colors;
    mapping(string => bool) _colorExists; //mappings are like json objects where value a is searched and its value is returned
    constructor() ERC721("Color", "COLOR") {
    }

    function mint(string memory _color) public{
      colors.push(_color);
      uint _id = colors.length -1;

      _mint(msg.sender,_id);
      _colorExists[_color] = true;
 
    }
}

最后是我的测试文件(我已将其缩短以仅显示给我错误的测试)

const { assert } = require('chai')
const Color = artifacts.require('./Color.sol')

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

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

    before(async ()=>{
        contract = 
        await Color.deployed()
    })
    
    describe('minting', async ()=>{
        
        it('creates a new token', async ()=>{
            const result = await contract.mint('#EC058E')
            console.log(result)
            const totalSupply = await contract.totalSupply()

            assert.equal(totalSupply,1)
            console.log(result)
        })
    })
})

此外,如果我们查看包含函数的文件,totalSupply()它是公共范围的,因此它应该通过导入在函数外部可见

我做了一些挖掘并从openzeppelin导入了实际函数所在的文件,但是似乎我仍然遇到相同的错误,我尝试单独编译以查看更改后重新编译是否可以解决,但它没有

不确定最近是否有其他人经历过这个或可能有解决方案我也在此处导入当前版本 https://www.npmjs.com/package/@openzeppelin/contracts

谢谢!

4

2 回答 2

6

我们必须扩展IERC721Enumerable合约,并实现它的虚拟功能。

contract Color is ERC721, IERC721Enumerable { // We must extends IERC721Enumerable 
    string[] public colors;
    mapping(string => bool) _colorExists;

    constructor() ERC721("Color", "COLOR") {}

    function mint(string memory _color) public {
        colors.push(_color);
        uint256 _id = colors.length - 1;

        // _mint(msg.sender,_id);
        _colorExists[_color] = true;
    }
    

    // And must override below three functions

    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        // You need update this logic.
        // ...
        return 3;
    }

    function totalSupply() external  view override returns (uint256) {
      // You need update this logic.
      // ...
      return 1;
    }

    function tokenByIndex(uint256 index) external view  override returns (uint256) {
      // You need update this logic.
      // ...
      return 5;
    }
}

在此处输入图像描述

然后,我们可以调用totalSupply() 方法

于 2021-08-17T05:31:12.590 回答
3

下面是智能合约的完整实现。

正如您在问题中提到的,它使用比教程更新的版本:

  • 坚固性(0.8.0)
  • 打开 Zeppelin (4.3.2)
pragma solidity ^0.8.0; // Note that this is using a newer version than in 

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", "COLOR") public {
    }

    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 - 1;
        _mint(msg.sender, _id);
        _colorExists[_color] = true;
    }
}


您还可以查看 OpenZeppelin 关于扩展合同的部分以了解overridessuper.

于 2021-10-04T08:12:47.043 回答