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

ERC721无效Token ID问题:跨合约调用无法识别已铸造代币

问题根源

你的代码核心问题在于Marketplace合约内部自行创建了一个独立的MyToken实例,而测试中你单独部署了另一个MyToken合约并在其中铸造代币。这两个MyToken合约是完全独立的部署,状态互不共享——Marketplace里的MyToken实例根本不存在ID为1的代币,所以调用sell时会触发ownerOf的无效Token ID错误。

修复方案

方案1:让Marketplace对接外部已部署的MyToken合约(推荐)

这种方式符合NFT市场的常规逻辑:市场对接已有的NFT合约,而非自行创建新合约。

修改Marketplace合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "./MyToken.sol";

contract Marketplace {
    MyToken public token;

    // 构造函数接收外部已部署的MyToken合约地址
    constructor(MyToken _token) {
        token = _token;
    }

    function sell(address _address, uint256 tokenId) public {
       require(token.ownerOf(tokenId) == msg.sender, "Unauthorized.");
       require(_address != address(0));
       // 可在此添加实际的代币转移/托管逻辑,原代码未实现
    }
}

修改测试代码

const { expect } = require("chai");
const { ethers } = require("hardhat");

it("should sell the minted token", async function() {
  const [owner] = await ethers.getSigners();

  // 先部署MyToken合约并铸造代币
  const Token = await ethers.getContractFactory("MyToken");
  const tokenContract = await Token.deploy();
  await tokenContract.safeMint(owner.address, 1);

  // 部署Marketplace时传入已部署的MyToken合约地址
  const Market = await ethers.getContractFactory("Marketplace");
  const marketContract = await Market.deploy(tokenContract.address);
  
  // 此时调用sell可通过校验
  await marketContract.sell(owner.address, 1);
})

方案2:通过Marketplace内部的MyToken实例铸造代币

如果你的业务逻辑确实需要Marketplace自行创建NFT合约,那么测试时要使用Marketplace内部的实例来铸造代币:

修改测试代码

const { expect } = require("chai");
const { ethers } = require("hardhat");

it("should sell the minted token", async function() {
  const [owner] = await ethers.getSigners();

  const Market = await ethers.getContractFactory("Marketplace");
  const marketContract = await Market.deploy();
  
  // 获取Marketplace内部的MyToken合约实例
  const tokenContract = await ethers.getContractAt("MyToken", await marketContract.token());
  
  // 通过该实例铸造代币
  await tokenContract.safeMint(owner.address, 1);
  
  // 调用sell
  await marketContract.sell(owner.address, 1);
})

内容的提问来源于stack exchange,提问作者XypriL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 09:20:22