简体   繁体   English

多边形区块链上 MetaMask 的内部 JSON-RPC 错误。 `ERC721:转接呼叫者既不是所有者也不是批准的。`

[英]Internal JSON-RPC error with MetaMask on Polygon Blockchain. `ERC721: transfer caller is not owner nor approved.`

I am making an NFT marketplace.我正在创建一个 NFT 市场。 When I deployed my contract on the Mumbai-testnet.当我在 Mumbai-testnet 上部署我的合约时。 The createToken function might work cause it brings up the Metamask for the Gas Fee but after that, the Error occurs something regarding the ONWNERSHIP . createToken function 可能会起作用,因为它会显示 Gas Fee 的 Metamask,但在那之后,会出现关于ONWNERSHIP的错误。 (Error image and text is present below.) (错误图像和文本如下所示。)

STEPS which I follow我遵循的步骤

  1. npm hardhat node
  2. npm run dev
  3. Selecting the Creating Page.选择创建页面。
  4. Enter all the details.输入所有详细信息。
  5. Click on Create an Asset which calls the createToken function.单击调用createToken function 的创建资产。

then the error occurs.然后发生错误。

Here is my NFT contract这是我的 NFT 合约

contract NFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address contractAddress;

constructor(address marketplaceAddress) ERC721("Metaverse Tokens", "METT") {
    contractAddress = marketplaceAddress;
}

function createToken(string memory tokenURI) public returns (uint256) {
    _tokenIds.increment();
    uint256 newItemId = _tokenIds.current();

    _mint(msg.sender, newItemId);
    _setTokenURI(newItemId, tokenURI);
    setApprovalForAll(contractAddress, true);

    return newItemId;
}}

Here is my NFTMarket contract这是我的 NFTMarket 合约

contract NFTMarket is ReentrancyGuard {
using Counters for Counters.Counter;

Counters.Counter private _itemIds;
Counters.Counter private _itemSold;

address payable owner;
uint256 listingPrice = 0.025 ether; // Here ether is denoting the MATIC

constructor() {
    owner = payable(msg.sender);
}

struct MarketItem {
    uint256 itemId;
    address nftContract;
    uint256 tokenId;
    address payable seller;
    address payable owner;
    uint256 price;
    bool sold;
}

mapping(uint256 => MarketItem) private idToMarketItem;

event MarketItemCreated(
    uint256 indexed itemId,
    address indexed nftContract,
    uint256 indexed tokenId,
    address seller,
    address owner,
    uint256 price,
    bool sold
);

function getListingPrice() public view returns (uint256) {
    return listingPrice;
}

//Function to create an NFT
function createMarketItem(
    address nftContract,
    uint256 tokenId,
    uint256 price
) public payable nonReentrant {
    //Conditions for creating the Item.
    require(price > 0, "Price must be at least 1 wei");
    require(
        msg.value == listingPrice,
        "Price must be equal to listing price"
    );

    _itemIds.increment();
    uint256 itemId = _itemIds.current();

    idToMarketItem[itemId] = MarketItem(
        itemId,
        nftContract,
        tokenId,
        payable(msg.sender),
        payable(address(0)), // When new NFT is created its ownership add is set to 0.
        price,
        false
    );

    IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);

    //Trigger the Event
    emit MarketItemCreated(
        itemId,
        nftContract,
        tokenId,
        msg.sender,
        address(0),
        price,
        false
    );
}

//Function to Transfer the Ownership
function createMarketSale(address nftContract, uint256 itemId)
    public
    payable
    nonReentrant
{
    uint256 price = idToMarketItem[itemId].price;
    uint256 tokenId = idToMarketItem[itemId].tokenId;

    require(
        msg.value == price,
        "Please submit the asking value in order to Purchase"
    );

    //Will transfer the MATIC to the seller address.
    idToMarketItem[itemId].seller.transfer(msg.value);

    //Will transfer the ownership from the owner of this contract to the Buyer.
    IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);

    //Set the local value of the owner to the Buyer(msg.sender).
    idToMarketItem[itemId].owner = payable(msg.sender);

    //Set this NFT as sold.
    idToMarketItem[itemId].sold = true;
    _itemSold.increment();

    payable(owner).transfer(listingPrice);
}

//Returns number of items unsold
function fetchMarketItems() public view returns (MarketItem[] memory) {
    uint256 itemCount = _itemIds.current();
    uint256 unsoldItemCount = _itemIds.current() - _itemSold.current();
    uint256 currentIndex = 0;

    MarketItem[] memory items = new MarketItem[](unsoldItemCount);

    for (uint256 i = 0; i < itemCount; i++) {
        if (idToMarketItem[i + 1].owner == address(0)) {
            uint256 currentId = idToMarketItem[i + 1].itemId;
            MarketItem storage currentItem = idToMarketItem[currentId];
            items[currentIndex] = currentItem;
            currentIndex += 1;
        }
    }
    return items;
}

//Returns number of Own(Created or Bought) NFTs
function fetchMyNFTs() public view returns (MarketItem[] memory) {
    uint256 totalItemCount = _itemIds.current();
    uint256 itemCount = 0;
    uint256 currentIndex = 0;

    for (uint256 i = 0; i < totalItemCount; i++) {
        if (idToMarketItem[i + 1].owner == msg.sender) {
            itemCount += 1;
        }
    }

    MarketItem[] memory items = new MarketItem[](itemCount);
    for (uint256 i = 0; i < totalItemCount; i++) {
        if (idToMarketItem[i + 1].owner == msg.sender) {
            uint256 currentId = idToMarketItem[i + 1].itemId;
            MarketItem storage currentItem = idToMarketItem[currentId];
            items[currentIndex] = currentItem;
            currentIndex += 1;
        }
    }
    return items;
}

//Returns the no of NFT created
function fetchItemsCreated() public view returns (MarketItem[] memory) {
    uint256 totalItemCount = _itemIds.current();
    uint256 itemCount = 0;
    uint256 currentIndex = 0;

    for (uint256 i = 0; i < totalItemCount; i++) {
        if (idToMarketItem[i + 1].seller == msg.sender) {
            itemCount += 1;
        }
    }

    MarketItem[] memory items = new MarketItem[](itemCount);
    for (uint256 i = 0; i < totalItemCount; i++) {
        if (idToMarketItem[i + 1].seller == msg.sender) {
            uint256 currentId = idToMarketItem[i + 1].itemId;
            MarketItem storage currentItem = idToMarketItem[currentId];
            items[currentIndex] = currentItem;
            currentIndex += 1;
        }
    }
    return items;
}}

I tried changing the RPC in the MetaMask and the configuration files and redeployed it many times with different accounts, but still, nothing changes.我尝试更改 MetaMask 和配置文件中的 RPC,并使用不同的帐户重新部署了很多次,但仍然没有任何变化。

The Error错误

 MetaMask - RPC Error: Internal JSON-RPC error. 
data:
code: 3
message: "execution reverted: ERC721: transfer caller is not owner nor approved"

Image of the console控制台的图像

If any other info is required please comment如果需要任何其他信息,请发表评论

Link of Blockchain Explorer 区块链浏览器链接

You are inheriting from ERC721URIStorage which inherits from ERC721 If you check the transferFrom inside ERC721 :您是从继承自ERC721URIStorageERC721继承如果您检查ERC721内部的transferFrom

function transferFrom(address from,address to,uint256 tokenId
        ) public virtual override {
        // *****  THIS REQUIRE IS NOT SATISFIED *****
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _transfer(from, to, tokenId);
    }

you are getting that error, because require statement inside transferFrom is not satisfied.您收到该错误,因为transferFrom中的require语句不满足。 So somewhere inside your contract you are calling transferFrom and it is failing.因此,在您的合同中某处您正在调用transferFrom并且它失败了。 it should be written like this:它应该这样写:

  // in this case transfer the ownership from the owner to the  contract 
    IERC721(contractAddress).transferFrom(msg.sender,address(this),tokenId);

    

During development, every time you compile your smart contract (using something like hardhat compile.. ), you have to copy the new smart contract addresses generated in your command prompt and paste them in the designated location in your source code.在开发过程中,每次编译智能合约(使用类似hardhat compile..之类的东西)时,都必须复制在命令提示符下生成的新智能合约地址,并将它们粘贴到源代码中的指定位置。

Thank You for your efforts.感谢你付出的努力。 I got the solution to it(After Searching for 3 days).我得到了解决方案(搜索3天后)。

SOLUTION =>解决方案=>

There's currently a bug on Mumbai causing deployed addresses to be incorrect.孟买目前存在一个错误,导致部署的地址不正确。 This is causing the constructor of the NFT contract to approve the wrong address for NFT purchases (because it uses the address of the Market deployment for approval) — causing the annoying "execution reverted: ERC721: approve caller is not owner nor approved for all" error.这导致NFT合约的构造函数批准了错误的 NFT 购买地址(因为它使用 Market 部署的地址进行批准)——导致烦人的"execution reverted: ERC721: approve caller is not owner nor approved for all"错误。

Try using Mainnet (yes, you'll have to use real money) but it works!尝试使用主网(是的,你必须使用真钱)但它有效!

Reference参考

Here's a workaround deploy script that will make it work on Mumbai.这是一个解决方法部署脚本,可以让它在孟买工作。 Replace main() in deploy.js with:将 deploy.js 中的 main() 替换为:

const hre = require("hardhat");

async function main() {
  const [deployer] = await hre.ethers.getSigners();

  console.log(
    "Deploying contracts with the account:",
    deployer.address
  );

  let txHash, txReceipt
  const NFTMarket = await hre.ethers.getContractFactory("NFTMarket");
  const nftMarket = await NFTMarket.deploy();
  await nftMarket.deployed();

  txHash = nftMarket.deployTransaction.hash;
  txReceipt = await ethers.provider.waitForTransaction(txHash);
  let nftMarketAddress = txReceipt.contractAddress

  console.log("nftMarket deployed to:", nftMarketAddress);

  const NFT = await hre.ethers.getContractFactory("NFT");
  const nft = await NFT.deploy(nftMarketAddress);
  await nft.deployed();


  txHash = nft.deployTransaction.hash;
  // console.log(`NFT hash: ${txHash}\nWaiting for transaction to be mined...`);
  txReceipt = await ethers.provider.waitForTransaction(txHash);
  let nftAddress = txReceipt.contractAddress

  console.log("nft deployed to:", nftAddress);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Redeploy the Contracts with this Script, and change the config.js .使用此脚本重新部署合同,并更改config.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MetaMask RPC 错误? “MetaMask - RPC 错误:内部 JSON-RPC 错误。” - MetaMask RPC error? 'MetaMask - RPC Error: Internal JSON-RPC error.' Ethers.js - “ERC721A:从不正确的所有者转移” MetaMask 错误 - Ethers.js - "ERC721A: transfer from incorrect owner" MetaMask Error 来自 web3 的 MintTo 合同给出错误 - ERC721:转移到非 ERC721Receiver 实施者 - MintTo contract from web3 gives error - ERC721: transfer to non ERC721Receiver implementer 如何使用版税调用 Openzeppelin safeTransferFrom() function 以避免错误,ERC721:所有者查询不存在的令牌? - How to call Openzeppelin safeTransferFrom() function with Royalty to avoid error, ERC721: owner query for nonexistent token? 如何跨网络传输 ERC721 代币 - How to transfer an ERC721 token across networks 可铸造的ERC721的众筹 - CappedCrowdsale of mintable ERC721 我们可以在实施ERC721令牌的同时将应付款修改器添加到转移功能吗? - Can we add payable modifier to transfer function while implementing ERC721 token? 如何创建标准 ERC721 代币 - how to create standard ERC721 token 与智能合约erc721中的输入反应中的大数字相关的错误 - Error while related to big number in react for input in smart contract erc721 SetApprovalForAll:不是所有者也不是批准的 - SetApprovalForAll: not owner nor approved
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM