You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 23:54:06