I am writing a contract on solidity 0.8.3 and I get this strange error for _setTokenURI()
although the method is defined in OpenZeppelin 4.X.
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract NFTB is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
mapping(string => uint8) hashes;
constructor() public ERC721("NFTB", "NFTB") {}
function awardItem(address recipient, string memory hash, string memory metadata) public returns (uint256) {
require(hashes[hash] != 1);
hashes[hash] = 1;
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_setTokenURI(newItemId, metadata);
_mint(recipient, newItemId);
return newItemId;
} }
ERC721 is a standard for representing ownership of non-fungible tokens, that is, where each token is unique. ERC721 is a more complex standard than ERC20, with multiple optional extensions, and is split accross a number of contracts.
Here, safely transfer means that, when a recipient is a contract, you need to ensure that the recipient contract has callbacks registered to let the receiver contract get a notification when ERC721 token transfer is successful.
A token owner can approve another address (an operator) to spend a specific token using the approve() function, as well as all of the owner's tokens using setApprovalForAll() .
browser/Token.sol:73:17: DeclarationError: Undeclared identifier. if (approve (_spender, _value)) { ^-----^ Your code doesn't declare an approve function, hence the error. If you didn't write the code yourself, I suggest you check the original source of the code for the approve function.
If the function call returns false then OpenSea will not detect it as an ERC721 contract and any attempts at validation fails. OpenSea checks during deployment and after deployment (for any contract that passes step 1 above) if any ERC721 Transfer events have been emitted from a contract. If not then any validation fails.
A proxy contract that is upgraded after deployment to support ERC721 can fail validation. The reason is because OpenSea validates contracts when they are deployed, but such contracts don't implement ERC721 until after they are deployed.
You haven't included ERC20 or BasicToken contracts which is why StandardToken can't inherit them (i.e. contract StandardToken is ERC20, BasicToken doesn't work because the compiler doesn't know what ERC20 or BasicToken means).
Function _setTokenURI()
is defined in @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol
(source on GitHub), but this contract is not imported by your code (including nested imports). That's why the function is undeclared.
Since ERC721URIStorage
extends ERC721
, you can extend your NFTB
directly from ERC721URIStorage
.
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; // changed import
import "@openzeppelin/contracts/utils/Counters.sol";
contract NFTB is ERC721URIStorage { // changed parent
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With