I am making an NFT marketplace. When I deployed my contract on the 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. (Error image and text is present below.)
STEPS which I follow
npm hardhat node
npm run dev
then the error occurs.
Here is my NFT contract
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
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.
The Error
MetaMask - RPC Error: Internal JSON-RPC error.
data:
code: 3
message: "execution reverted: ERC721: transfer caller is not owner nor approved"
If any other info is required please comment
Thank You for your efforts. I got the solution to it(After Searching for 3 days).
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.
Try using Mainnet (yes, you'll have to use real money) but it works!
Here's a workaround deploy script that will make it work on Mumbai. Replace main() in deploy.js with:
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
.