Non-Fungible Tokens (NFTs)
ERC-721, ERC-1155, metadata, marketplaces, and NFT development.
Overview
NFTs represent unique digital assets on the blockchain.
ERC-721 Standard
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFT is ERC721, ERC721URIStorage {
uint256 private _tokenIdCounter;
constructor() ERC721("MyNFT", "MNFT") {}
function mint(string memory uri) public {
uint256 tokenId = _tokenIdCounter;
_tokenIdCounter++;
_safeMint(msg.sender, tokenId);
_setTokenURI(tokenId, uri);
}
}
ERC-1155 (Multi-Token)
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
contract GameItems is ERC1155 {
uint256 public constant SWORD = 0;
uint256 public constant SHIELD = 1;
constructor() ERC1155("https://game.com/{id}.json") {
_mint(msg.sender, SWORD, 100, "");
_mint(msg.sender, SHIELD, 50, "");
}
}
Metadata Structure
{
"name": "Cool NFT #1",
"description": "A unique digital collectible",
"image": "ipfs://QmHash...",
"attributes": [
{"trait_type": "Background", "value": "Blue"},
{"trait_type": "Rarity", "value": "Legendary"},
{"trait_type": "Power", "display_type": "number", "value": 100}
]
}
Marketplace Contract
contract Marketplace {
struct Listing {
address seller;
uint256 price;
bool active;
}
mapping(uint256 => Listing) public listings;
function list(uint256 tokenId, uint256 price) public {
require(ownerOf(tokenId) == msg.sender);
listings[tokenId] = Listing(msg.sender, price, true);
}
function buy(uint256 tokenId) public payable {
Listing memory listing = listings[tokenId];
require(listing.active);
require(msg.value >= listing.price);
// Transfer NFT and payment
safeTransferFrom(listing.seller, msg.sender, tokenId);
payable(listing.seller).transfer(msg.value);
}
}
Practice
Mint and list an NFT on a marketplace.