I'm actually trying to create an NFT Marketplace, where a user can upload his NFT (create/mint new NFT) and other users can give some Ether and mint the same NFT. Trying to achieve this with the ERC721 standard. Maybe ERC1155 will be a better choice but I have to use ERC721.
So, I think how I can achieve this using ERC721 by minting NFTs with different tokenIDs but with pointing to the same NFT metadata or TokenURI.
I know this is possible as mentioned in this post: https://ethereum.stackexchange.com/questions/59765/two-erc721-tokens-that-refer-to-the-same-metadata
But I can't fo it programatically.
This is how I'm trying: (It's not working, even 1 NFT is not showing on he opensea testnet)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/utils/Strings.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract navich is ERC721URIStorage, Ownable {
using Strings for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenId;
string public baseURI = "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq/";
constructor() ERC721("Wagmi", "Wagmi") {}
function mintNFT() public payable {
uint256 dynamic = 1;
_tokenId.increment();
_mint(msg.sender, _tokenId.current());
_setTokenURI(dynamic, baseURI);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
return
string(
abi.encodePacked(
baseURI,
tokenId.toString(),
".json"
)
);
}
// function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
// return "ipfs://QmRyezUtChrpvH4i4wKEoPngwTFKHuu4YYjZrSg89wvqVq";
// }
}
Incidentally, this is not the full Marketplace code.
I wrote a factory contract for generating some tokens and it is able to successfully create tokens. However, when I import the generated token address to my wallet, the supply is 0 even though I have set it to a value:
Factory contract snippet:
contract TokenFactory {
event MyTokenCreated(address contractAddress);
function createNewMyToken() public returns (address) {
MyToken myToken = new MyToken(2000000);
emit MyTokenCreated(address(myToken));
return address(myToken);
}
MyToken.sol
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor (uint256 initialSupply) ERC20("MyToken", "MY") {
_mint(msg.sender, initialSupply * 10 ** 18);
}
}
After generating MyToken from TokenFactory and importing the generated token's address to my wallet, I expected the supply to be 2000000, but it is 0.
Does anyone have any idea why this is happening?
Note that you are sending tokens to msg.sender, and in this case, the msg.sender will always be the factory contract. So if you want to mint those tokens to your own wallet, you can either give MyToken a new address param where your factory contract will pass your address, or just use tx.origin, so that it references the transaction original creator address.
I am working on a contract with openzeppelin and remix ide.
In this contract I have written a fallback function to get ether from consumer and send them the token automatically.
here is my code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelincontracts/blob/master/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20{
address public owner;
uint256 public value;
constructor() ERC20("MtToken", "TKN"){
owner = msg.sender;
_mint(owner, 1000000 ether);
increaseAllowance(owner, 1000000 ether);
}
fallback() external payable{
value += msg.value;
if(msg.value > (0.01 ether)){
transferFrom(owner, msg.sender, (1000 ether));
}
}
}
but when I try to send BNB or ETH in test net to get back the token transaction fails.
I am trying to receive the funds into a specific address during mint process. This is my code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-
contracts/blob/master/contracts/token/ERC1155/ERC1155.sol";
contract NFTContract is ERC1155 {
uint256 public constant Jack = 0;
constructor() ERC1155("") {
_mint(msg.sender, Jack, 0, "");
}
function mint(address account, uint256 id, uint256 amount) public payable {
payable(address(0xdD870fA1b7C4700F2BD7f44238821C26f7392148)).transfer(100000000000000000);
_mint(account, id, amount, "");
}
}
But I get an error saying:
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
How do I receive a payment during the mint?
Just needed to do regular transfer:
addr.transfer(amount)
My question has two parts,
I am trying to create an ERC721 token using the Openzeppelin contracts with metadata and that is enumerable. My understanding is after openzeppelin v4.0.0 they removed the ERC721Full.sol contract which included metadata and enummerable. I want to use solidity 0.8.0 and so those old contracts wont work, right? When importing and inheriting ERC721Enumerable.sol into the ERC721.sol contract, I get TypeError: Definition of base has to precede definition of derived contract
I tried just importing ERC721Enumerable.sol in my own contract, but still errors. I also tried importing the older ERC721Full.sol contract and changing all the pragma 0.5.0 to pragma 0.8.0, but it inherits like a dozen other contracts and changing all of them doesn't seem wise. I tried the same with IERC721Enumerable.sol, still errors. Any ideas? Any help would be amazing!
Second part. What's the difference between ERC__ and IERC__? What's the purpose of IERC contracts?
Thanks!!
Here's my contract (I'm following a tutorial). I import the regular ERC721 contract, inherit it. it gives me an error when I test and call the totalSupply function because there is no totalSupply function:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721 {
string[] public colors;
mapping(string => bool) _colorExists;
constructor() ERC721("Color", "COLOR") {
}
function mint(string memory _color) public {
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
my test script:
const Color = artifacts.require('./Color.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Color', (accounts) => {
let contract
before(async () => {
contract = await Color.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
contract = await Color.deployed()
const address = contract.address
console.log(address)
assert.notEqual(address, 0x0)
assert.notEqual(address,'')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await contract.name()
assert.equal(name, 'Color')
})
it('has a symbol', async () => {
const symbol = await contract.symbol()
assert.equal(symbol, 'COLOR')
})
})
describe('minting', async () => {
it('creates a new token', async () => {
const result = await contract.mint('#00CD22')
const totalSupply = await contract.totalSupply()
// SUCCESS
asert.equal(totalSupply, 1)
})
})
})
this is my error without the enumerable contract/without totalSupply
I can paste the openzeppelin contracts if you like, or link them here
I also tried this, importing ERC721Enumerable
And got this:
let me know fi you need anymore info!
thanks in advance
For the first part
An ERC721 by default does not have a totalSupply method, and that's the reason you're getting the error. The totalSupply method comes from the IERC721Enumerable, wich is an optional extension of the standard ERC721 as the documentation states. If you want your ERC721 to be enumerable just import the enumerable extension from the openzeppelin implementations for your derived contract, like so:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721Enumerable {
string[] public colors;
mapping(string => bool) _colorExists;
constructor() ERC721("Color", "COLOR") {
}
function mint(string memory _color) public {
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
The reason the compiler gave you the error when trying to import ERC721Enumerable is that you were tryning to import it in the Openzeppelin ERC721 implementation, but that contract had to exists prior to the ERC721Enumberable. In other words the inheritance chain is
ERC721 <-- ERC721Enumerable
What you were trying to do was
ERC721 <-- ERC721Enumerable
|_____________↑
Wich creates a circular dependency that cannot be satisfied.
For the second part
ERC contracts are like abstracts classes in every OOP programming languages (first that come to my mind and maybe most relatable are Java and C++), while IERC are interfaces; this means that while both cannot be instanciated directly (they both need the children to implement something) ERC contracts provide standard implementations for the corresponding IERC methods. This is the reason often you see contracts implement the ERC contracts and not the IERC ones.
To use the ERC271Enumerable extension you need to implement it and override some functions of ERC271, _beforeTokenTransfer and supportsInterface.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract Color is ERC721, ERC721Enumerable{
string[] public colors;
mapping(string => bool) _colorExists;
constructor () ERC721("Color", "COLORS") {}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function mint(string memory _color) public{
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
What's the difference between ERC__ and IERC__? What's the purpose of IERC contracts?
IERC is the Interface for the token contract.
ERC is the implementation of the token contract.
The importance is to make sure a Contract implementation has the right methods, with the right visibility, parameters, and return values.