Hardhat测试遇ERC721无效Token ID错误,求原因与解决方案
错误成因与解决方案
错误原因
这个错误的核心是调用tokenURI(uint256)时传入了未被铸造的无效tokenId,问题出在tokenId的对应关系上:
- 你的
NFT合约中createToken函数的tokenId生成逻辑大概率从0开始计数(比如用初始值为0的计数器,铸造后自增)。 - 你调用两次
createToken实际生成的tokenId是0和1,但调用market.createMarketItem时传入的是1和2,这两个tokenId从未被铸造。 - 当测试代码遍历市场物品并调用
tokenURI(i.tokenId)时,无效的tokenId触发了ERC721标准的invalid token ID回滚错误。
解决方案
两种修复方式二选一即可:
方式一:修改测试代码,使用正确的tokenId
把测试中使用的tokenId改为0、1,匹配NFT合约实际生成的tokenId:
// 替换原有的createMarketItem调用 await market.createMarketItem(nftContractAddress, 0, auctionPrice, { value:listingPrice }) await market.createMarketItem(nftContractAddress, 1, auctionPrice, { value:listingPrice }) // 替换createMarketSale的tokenId参数 await market.connect(buyerAddress).createMarketSale(nftContractAddress, 0, {value: auctionPrice})
方式二:修改NFT合约,让tokenId从1开始生成
如果希望tokenId从1开始计数,调整NFT合约中createToken的计数器逻辑:
// 假设合约中有类似计数器定义 uint256 private _tokenIdCounter; function createToken(string memory tokenURI) public returns (uint256) { // 先自增再铸造,让第一个tokenId为1 _tokenIdCounter++; uint256 newTokenId = _tokenIdCounter; _safeMint(msg.sender, newTokenId); _setTokenURI(newTokenId, tokenURI); // 其他业务逻辑 return newTokenId; }
或者直接将计数器初始值设为1:
uint256 private _tokenIdCounter = 1;
验证修复
修改完成后重新运行测试,tokenURI调用将传入有效的tokenId,不会再触发回滚错误。
内容的提问来源于stack exchange,提问作者Iyodo Michael
相关产品推荐
相关产品推荐

