OpenZeppelin ERC721URIStorage _setTokenURI - solidity

i'm trying to create a smart contract for minting NFT's. When i try to import and use _setTokenUri from OpenZeppelin, there is an error accours in Remix ide says that "Undeclared identifier". I wonder why, so here is my code ;
pragma solidity ^0.8.9;
import '#openzeppelin/contracts/token/ERC721/ERC721.sol';
import '#openzeppelin/contracts/access/Ownable.sol';
import '#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
contract MintNft is ERC721, Ownable {
uint256 public mintPrice = 0.005 ether;
uint public totalSupply;
uint public maxSupply;
bool public isMintEnabled;
// Mapping for amount of minted nfts by an address
mapping(address => uint256) public mintedWallets;
constructor() payable ERC721('Pokemon Card', 'POKE') {
maxSupply = 20;
}
function toggleIsMintEnabled() external onlyOwner {
isMintEnabled = !isMintEnabled;
}
function setMaxSupply(uint256 _maxSupply) external onlyOwner {
maxSupply = _maxSupply;
}
function mint(string memory tokenURI) external payable {
require(isMintEnabled,"Minting is not enable");
require(mintedWallets[msg.sender] < 2, 'You have reached maximum mint number');
require(msg.value == mintPrice, "Wrong value");
require(maxSupply > totalSupply, "Sold Out ! ");
mintedWallets[msg.sender]++;
totalSupply++;
uint256 tokenId = totalSupply;
_safeMint(msg.sender, tokenId);
_setTokenURI(tokenId,tokenURI);
}
}
Thanks already.

Okay i figured out that i forget to implement ERC721URIStorage when naming my contract.
i changed it to contract MintNft is ERC721URIStorage, Ownable
Now it works fine.

Related

How to deposit eth to contract writen in solidity on front-end app using useDapp

Given i have this smart contract in remix
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract DepositWithdraw {
mapping(address => uint256) private balances;
event Deposit(address indexed depositor, uint256 amount);
event Withdrawal(address indexed withdrawer, uint256 amount);
function deposit() public payable {
balances[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
emit Withdrawal(msg.sender, amount);
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}
Deposit by remix ide works, but when I'm trying to deposit using useDapp lib in javascript by using useContractFunction I can't pass the amount to deposit. When I'm redirected to meta mask to accept transaction there is no amount shown.
my front-end code:
import { Contract } from 'ethers';
import { Interface } from 'ethers/lib/utils';
import { useContractFunction } from '#usedapp/core';
const contractAddress = // my contract address;
const ABI = new Interface(
//...copied contract ABI from remix
);
const contract = new Contract(contractAddress, ABI);
const { send } = useContractFunction(contract, 'deposit');
// send(value) will error that deposit function argument length is no correct (it want 0 arguments)
tried adding third argument with options to useContractFunction but no success.
When i call send without arguments it will process to metamask but no amount shown, only gas fees
any ideas?

Allow ERC20 token for minting ERC721 NFT

I'm new in Solidity and trying to allow purchasing using ETH and other token such as USDT but I keep getting this error no matter what I tried.
DeclarationError: Identifier already declared. --> contract-9b5b02c5de.sol:9:1:
|
9 | import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
This is my code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "#openzeppelin/contracts#4.8.0/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts#4.8.0/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts#4.8.0/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts#4.8.0/access/Ownable.sol";
import "#openzeppelin/contracts#4.8.0/utils/Counters.sol";
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Combat is ERC721, ERC721Enumerable, ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
ERC20 public tokenUsdt;
uint256 public ethPrice = 0;
uint256 public usdtPrice = 0;
uint256 public maxSupply; //Maximum amount token
bool public isMintEnabled; //default : false
mapping(address=>uint256) public mintedWallets;
constructor(address _tokenUsdt) ERC721("XXX", "QAZ") {
maxSupply = 100;
tokenUsdt = ERC20(_tokenUsdt);
}
function setToken(address _tokenUsdt) external onlyOwner {
tokenUsdt = _tokenUsdt;
}
function setPrice(uint256 _ethPrice, uint256 _usdtPrice) external onlyOwner {
ethPrice = _ethPrice;
usdtPrice = _usdtPrice;
}
function buyMembershipUsdt() external payable {
require(msg.value >= usdtPrice, "Price Error");
tokenUsdt.safeTransferFrom(msg.sender, owner(), _amount);
mintMembership();
}
function buyMembershipEth() external payable {
require(msg.value >= ethPrice, "Price Error");
mintMembership();
}
function mintMembership() internal {
require(isMintEnabled, "Not For Sale");
require(totalSupply() < maxSupply, "Sold Out");
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(msg.sender, tokenId);
}
function setMintEnabled(bool isMintEnabled_) external onlyOwner {
isMintEnabled = isMintEnabled_;
}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://bafybeiebgbvibloa3p3vge7ecxobwxxnuyg4pdozbcfjigfglhz2ogidq4/";
}
function setMaxSupply(uint256 maxSupply_) external onlyOwner{
maxSupply = maxSupply_;
}
function withdraw() public onlyOwner {
require(address(this).balance > 0, "Balance is 0");
payable(owner()).transfer(address(this).balance);
}
function withdrawToken() external onlyOwner {
uint256 tokenBalance = tokenUsdt.balanceOf(address(this));
require(tokenBalance > 0, "Insufficient balance");
tokenUsdt.safeTransfer(msg.sender, tokenBalance);
}
// The following functions are overrides required by Solidity.
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
}
I seen some guides our there but none seems to help because it uses custom token which I'm not using it. Regardless whether I'm using IERC20 or ERC20, I will keep getting error above I mentioned. Am I missing something or what?
You import should be
import "#openzeppelin/contracts#4.8.0/token/ERC20/ERC20.sol";
instead of
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";

ERC2981 NFT Royalties Implementation in a ERC721 Marketplace

I've read already many posts regarding this topic, but I just can't wrap my head around this Royalty implementation thing.
Pls help me out, I don't know how I should play with this thing.
what is feeNumerator? _setDefaultRoyalty(address receiver, uint96 feeNumerator)
is it NFT Price? Nft Royalty Percent?
Pls take a look at the following contract and help me with how I can implement NftRoyalty in this contract. Am I doing it right? if not then pls correct me. Thanks.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.8;
import "hardhat/console.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/token/common/ERC2981.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract PodShip is ERC721URIStorage, ERC2981, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _podcastId;
Counters.Counter private _nftId;
struct Podcast {
address nftCreator;
address nftOwner;
string nftName;
string nftDescription;
uint256 nftPrice;
uint256 nftRoyaltyPercent;
uint256 nftId;
bool listed;
}
mapping(uint256 => Podcast) podcastId;
constructor() ERC721("PodShip NFTs", "PODSHIP") {}
function mintNft(
string memory ipfsURI,
string memory _nftName,
string memory _nftDescription,
uint256 _nftPrice,
uint256 _nftRoyaltyPercent) public returns(uint256) {
require(_nftPrice > 0, "NFT Price not set correctly");
require(_nftRoyaltyPercent > 0 && _nftRoyaltyPercent <= 50, "NFT Royalty should be in-between 1 & 50");
_podcastId.increment();
_nftId.increment();
uint256 nft_Id = _nftId.current();
_safeMint(msg.sender, nft_Id);
_setTokenURI(nft_Id, ipfsURI);
podcastId[_podcastId.current()] = Podcast(
payable(msg.sender),
payable(msg.sender),
_nftName,
_nftDescription,
_nftPrice,
_nftRoyaltyPercent,
nft_Id,
false
);
console.log(nft_Id);
console.log(_podcastId.current());
return nft_Id;
}
function listNFT(uint256 _podcastID) public {
require(msg.sender == podcastId[_podcastID].nftOwner && msg.sender == podcastId[_podcastID].nftCreator, "Only Owner can list his NFT");
podcastId[_podcastID].listed = true;
approve(address(this), podcastId[_podcastID].nftId);
setApprovalForAll(address(this), true);
_setDefaultRoyalty(podcastId[_podcastID].nftCreator, uint96(podcastId[_podcastID].nftRoyaltyPercent));
}

How do I accept an ERC20 token for Nft mint payment instead of ETH

How do I accept an ERC 20 token for minting NFTS on my smart contract. I’m currently paying for the minting using ETH, and I will like to accept another ERC 20 token.
You can change your mint function in order to accept the preferred token type as payment. And in order to prevent paying gas in eth, you can use biconomy forward.Check out their docs.
https://docs.biconomy.io/products/enable-paying-gas-in-erc20
You need a reference from the NFT contract to your token contract.
Let's say we have these two contracts: NFTContract, TokenContract.
contract NFTContract {
TokenContract tokenContract;
...
mint() {
tokensContract.transfer(msg.sender(), addressReceiver, tokensToSend);
...
}
}
contract TokenContract {
transfer(sender, receiver, balance) {}
}
You can check an example of how I did this in my repo I'm developing for my thesis.
https://github.com/NickVanzo/Contracts_For_Thesis
Maybe it will work for you but be careful you can take errors for solidity versions.
pragma solidity ^0.8.9;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract LSTNFT is ERC721, ERC721Burnable, Ownable {
uint256 public cost;
uint256 maxSupply = 20;
uint256 maxMintAmountPerTx = 2;
// address of the ERC-20 contract
address public erc20Contract = "ERC-20 address is here";
// instance of the ERC-20 contract
ERC20 public erc20;
constructor() ERC721("Lestonz NFT", "LSTN") {
erc20 = ERC20(erc20Contract);
}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://your ipfs url";
}
modifier mintPriceCompliance(uint256 _mintAmount) {
if (msg.sender != owner()) {
require(msg.value >= cost * _mintAmount, 'Insufficient funds!');
}
_;
}
function mint(uint256 _mintAmount) public payable mintPriceCompliance(_mintAmount) {
require(erc20.balanceOf(msg.sender) >= msg.value, "Not enough ERC-20 tokens");
_safeMint(_msgSender(), _mintAmount);
}
function setCost(uint256 _cost) public onlyOwner {
cost = _cost;
}
}

Exclusive NFT per smart contract in SOLIDITY

I want to mint only one exclusive NFT per smart contract. All tutorials and books shows how to make collectables through inheritance of ERC721. So the simple code is:
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";
contract SimpleCollectible is ERC721 {
uint256 public tokenCounter;
constructor () public ERC721 ("Dogie", "DOG"){
tokenCounter = 0;
}
function createCollectible(string memory tokenURI) public returns (uint256) {
uint256 newItemId = tokenCounter;
_safeMint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
tokenCounter = tokenCounter + 1;
return newItemId;
}
}
How restrict minting to 1 piece of art?
Add a condition to tokenCounter. You could use the following:
function createCollectible(string memory tokenURI) public returns(uint256) {
require(tokenCounter == 0, "error msg here");
uint256 newItemId = tokenCounter;
_safeMint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
tokenCounter = tokenCounter + 1;
return newItemId;
}
In fact, there are tons of ways of achieving the same result. Maybe you could use a simple boolean to save a little bit on gas.
I hope you fin this useful :)