如何修复ReferenceError: totalSupply未定义错误?
区块链开发错误修复:ReferenceError: totalSupply is not defined
错误信息
ReferenceError: totalSupply is not defined
问题代码
Truffle测试代码
const { assert } = require("chai"); const KryptoBird = artifacts.require("KryptoBird"); // check for chai require('chai') .use(require('chai-as-promised')) .should() contract('KryptoBird', (accounts) => { let contract before( async () => { contract = await KryptoBird.deployed() }) describe('deployment', async() => { it("deploys successfully", async () => { const address = contract.address; assert.notEqual(address, '') assert.notEqual(address, null) assert.notEqual(address, undefined) assert.notEqual(address, 0x0) }) it('has a name', async() => { const name = await contract.name() assert.equal(name, 'KryptoBird') }) it('has a symbol', async() => { const symbol = await contract.symbol() assert.equal(symbol, 'KBIRDZ') }) }) describe('minting', async ()=> { it('creates a new token', async () => { const result = await contract.mint('https...1') const totalSupply = await contract.totalSupply(); assert.equal(totalSupply, 1) const event = result.logs[0].args assert.equal(event._from, '0x0000000000000000000000000000000000000000', 'from is the contract') assert.equal(event._to, accounts[0], 'to is msg.sender') await contract.mint('https...1').should.be.rejected }) }) describe('indexing', async()=> { it('lists KryptoBirdz', async()=> { // Mint three new tokens await contract.mint('https...2') await contract.mint('https...3') await contract.mint('https...4') const totalSupply = await contract.totalSupply() }) let result = [] let KryptoBird for(i = 1; i <= totalSupply; i++) { KryptoBird = await contract.kryptoBirdz(i) result.push(KryptoBird) } let expected = ['https...1','https...2','https...3','https...4'] assert.equal(result.join(','), expected.join(',')) }) })
Solidity合约代码
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import './ERC721Connecter.sol'; contract KryptoBird is ERC721Connecter { string[] public kryptoBirdz; mapping(string => bool) _kryptoBirdzExists; function mint(string memory _kryptoBird) public { require(!_kryptoBirdzExists[_kryptoBird], 'Error - kryptoBird already exists'); // this is deprecated - uint _id = KryptoBirdz.push(_kryptoBird); kryptoBirdz.push(_kryptoBird); uint _id = kryptoBirdz.length - 1; // .push no logner returns the length but a ref to the added element _mint(msg.sender, _id); _kryptoBirdzExists[_kryptoBird]=true; } constructor() ERC721Connecter('KryptoBird','KBIRDZ') {} }
错误原因
- 变量作用域问题:在
indexing测试块中,totalSupply变量是在it('lists KryptoBirdz', async()=> { ... })函数内部声明的,但后续的for循环和断言逻辑写在了it函数外部,超出了变量的作用域范围,导致JS无法找到该变量,抛出ReferenceError。 - 合约方法缺失(潜在问题):ERC721标准并未强制实现
totalSupply()方法,如果你的ERC721Connecter父合约没有实现这个方法,调用contract.totalSupply()会触发合约层面的错误,需要额外处理。
修复方案
1. 修正测试代码的作用域问题
将indexing块中的for循环和断言逻辑全部移到it函数内部,确保totalSupply变量能被正确访问:
describe('indexing', async()=> { it('lists KryptoBirdz', async()=> { // Mint three new tokens await contract.mint('https...2') await contract.mint('https...3') await contract.mint('https...4') const totalSupply = await contract.totalSupply() let result = [] let KryptoBird for(let i = 1; i <= totalSupply; i++) { // 添加let声明i,避免全局变量污染 KryptoBird = await contract.kryptoBirdz(i) result.push(KryptoBird) } let expected = ['https...1','https...2','https...3','https...4'] assert.equal(result.join(','), expected.join(',')) }) })
2. 实现合约的totalSupply()方法(如果父合约未提供)
在KryptoBird合约中添加totalSupply()方法,直接返回kryptoBirdz数组的长度:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import './ERC721Connecter.sol'; contract KryptoBird is ERC721Connecter { string[] public kryptoBirdz; mapping(string => bool) _kryptoBirdzExists; function mint(string memory _kryptoBird) public { require(!_kryptoBirdzExists[_kryptoBird], 'Error - kryptoBird already exists'); kryptoBirdz.push(_kryptoBird); uint _id = kryptoBirdz.length - 1; _mint(msg.sender, _id); _kryptoBirdzExists[_kryptoBird]=true; } // 添加totalSupply方法 function totalSupply() public view returns(uint256) { return kryptoBirdz.length; } constructor() ERC721Connecter('KryptoBird','KBIRDZ') {} }
验证修复
- 重新编译合约:
truffle compile - 运行测试:
truffle test
内容的提问来源于stack exchange,提问作者Koruma
相关产品推荐
相关产品推荐

