Hey everyone,
I am using Openzeppelin and Hardhat to build a Node.js server that can mint, transfer, and burn NFT’s. I am using Matic polygon testnet blockchain network to deploy my contracts
Here is my smart contract. (NFT.sol)
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFT is ERC721, Ownable {
using Counters for Counters.Counter;
using Strings for uint256;
Counters.Counter private _tokenIds;
mapping (uint256 => string) private _tokenURIs;
string private _baseURIextended;
constructor() ERC721("MyNFT", "MNFT") {}
function _setTokenURI(uint256 tokenId, string memory _tokenURI)
internal
virtual
{
_tokenURIs[tokenId] = _tokenURI;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory _tokenURI = _tokenURIs[tokenId];
return _tokenURI;
}
function mint(address recipient, string memory uri)
public
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, uri);
return newItemId;
}
function transfer(address _seller, address _buyer, uint256 _tokenId) external payable {
// transfer assets from seller to buyer
// seller pays the tx fees
setApprovalForAll(_seller, true);
setApprovalForAll(_buyer, true);
_transfer(_seller, _buyer, _tokenId);
}
function burn(uint256 _tokenId) public returns (bool) {
_burn(_tokenId);
return true;
}
}
Here is my command to deploy the SC in blockchain.
const hre = require("hardhat");
async function main() {
const NFT = await hre.ethers.getContractFactory("MyNFT");
const nft = await NFT.deploy();
await nft.deployed();
console.log("NFT deployed to:", nft.address);
}
main().then(() => process.exit(0)).catch(error => {
console.error(error);
process.exit(1);
});
This script is working fine and giving me the contract address after I run this command.
npx hardhat run scripts/deploy-script.js --network matic
Here is my Minting script.
const hre = require("hardhat");
async function main() {
const NFT = await hre.ethers.getContractFactory("MyNFT");
const URI = "ipfs://QmdnfzqwRuTmZwquauTxGs9hXzMaaVczmuSuQbpUU4pRng";
const WALLET_ADDRESS = "my metamask wallet address -- its funded";
const CONTRACT_ADDRESS = "contract address that I get from the command above";
const contract = NFT.attach(CONTRACT_ADDRESS);
const tokenId = await contract.mint(WALLET_ADDRESS, URI);
console.log("NFT minted:", contract);
console.log("TokenID:", tokenId);
}
main().then(() => process.exit(0)).catch(error => {
console.error(error);
process.exit(1);
});
This mints the token successfully and I get the response as well.
My problem arises when I am trying to transfer the NFT from one account to another or Burn the NFT.
Here is my transfer code.
const hre = require("hardhat");
async function main() {
const NFT = await hre.ethers.getContractFactory("MyNFT");
const WALLET_ADDRESS = "my meta mask account address that owns NFT";
const RECIEVER_ADDRESS = "the other meta mask account with 0 balance";
const CONTRACT_ADDRESS = "the contract address I get";
const TOKENID = "1";
const contract = NFT.attach(CONTRACT_ADDRESS);
await contract.transfer(WALLET_ADDRESS,RECIEVER_ADDRESS, TOKENID);
console.log("NFT transferred:", contract);
}
main().then(() => process.exit(0)).catch(error => {
console.error(error);
process.exit(1);
});
When i execute this script, i get this following error.
{ Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":-32000,"_isProviderError":true}, method="estimateGas", transaction={"from":"0xB705730CDdDb2Af877A92B8D21bee30A61C0a416","to":"0x6C1da88ACD16D6C3BCb0Fac3Fe2b4C7Aa95C68A0","data":"0x42966c680000000000000000000000003599fe1852aba39cf72d45f5b79f15fb0402eaed","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.2.0)
at Logger.makeError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/logger/src.ts/index.ts:213:28)
at Logger.throwError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/logger/src.ts/index.ts:225:20)
at checkError (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:76:16)
at EthersProviderWrapper.<anonymous> (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:512:20)
at step (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:48:23)
at Object.throw (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:29:53)
at rejected (/home/shahidshaikh/projects/polygon-nfts/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:21:65)
at process.internalTickCallback (internal/process/next_tick.js:77:7)
reason:
'cannot estimate gas; transaction may fail or may require manual gas limit',
code: 'UNPREDICTABLE_GAS_LIMIT',
error:
ProviderError: execution reverted
at HttpProvider.request (/home/shahidshaikh/projects/polygon-nfts/node_modules/hardhat/src/internal/core/providers/http.ts:46:19)
at LocalAccountsProvider.request (/home/shahidshaikh/projects/polygon-nfts/node_modules/hardhat/src/internal/core/providers/accounts.ts:142:34)
at process.internalTickCallback (internal/process/next_tick.js:77:7),
method: 'estimateGas',
transaction:
{ from: '0xB705730CDdDb2Af877A92B8D21bee30A61C0a416',
to: '0x6C1da88ACD16D6C3BCb0Fac3Fe2b4C7Aa95C68A0',
data:
'0x42966c680000000000000000000000003599fe1852aba39cf72d45f5b79f15fb0402eaed',
accessList: null } }
Same error when I am trying to burn the NFT using this command.
const hre = require("hardhat");
async function main() {
const NFT = await hre.ethers.getContractFactory("MyNFT");
const CONTRACT_ADDRESS = "contract address";
const TOKENID = "1";
const contract = NFT.attach(CONTRACT_ADDRESS);
await contract.burn(TOKENID);
console.log("NFT burned:", contract);
}
main().then(() => process.exit(0)).catch(error => {
console.error(error);
process.exit(1);
});
Please let me know where I am doing a silly mistake!