ERC-721 NFT — Web3

ERC-721 NFT ERC-721 adalah standar untuk Non-Fungible Token (NFT) — token yang unik dan tidak bisa ditukar 1:1. Setiap token memiliki tokenId yang berbeda dan…

ERC-721 NFT

ERC-721 adalah standar untuk Non-Fungible Token (NFT) — token yang unik dan tidak bisa ditukar 1:1. Setiap token memiliki tokenId yang berbeda dan bisa punya metadata unik (gambar, atribut, dll.).

Perbedaan ERC-20 vs ERC-721

AspekERC-20 (Fungible)ERC-721 (Non-Fungible)
KeunikanSetiap token identikSetiap token unik (tokenId)
DivisibleYa (decimals)Tidak (1 NFT = 1 NFT)
ContohUSDC, UNI, LINKCryptoPunks, BAYC, Art
Transfertransfer(to, amount)transferFrom(from, to, tokenId)

Implementasi NFT dengan OpenZeppelin

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract BelajarNFT is ERC721, ERC721URIStorage, Ownable {
    uint256 private _nextTokenId;
    uint256 public constant MAX_SUPPLY = 1000;
    uint256 public mintPrice = 0.01 ether;

    constructor() ERC721("BelajarNFT", "BNFT") Ownable(msg.sender) {}

    function mint(string memory uri) public payable {
        require(_nextTokenId < MAX_SUPPLY, "Sold out");
        require(msg.value >= mintPrice, "Insufficient ETH");

        uint256 tokenId = _nextTokenId++;
        _safeMint(msg.sender, tokenId);
        _setTokenURI(tokenId, uri);
    }

    // Override required by Solidity
    function tokenURI(uint256 tokenId)
        public view override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public view override(ERC721, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

Metadata Standard

NFT metadata biasanya disimpan di IPFS atau server, dengan format JSON standard:

// tokenURI mengembalikan URL ke JSON ini:
{
  "name": "BelajarNFT #42",
  "description": "Proof of Learning - Web3 Module",
  "image": "ipfs://QmXxx.../42.png",
  "attributes": [
    { "trait_type": "Level", "value": "Advanced" },
    { "trait_type": "Module", "value": "Smart Contract Security" },
    { "trait_type": "Score", "value": 95, "display_type": "number" }
  ]
}

Minting dari Frontend

async function mintNFT() {
  const contract = new ethers.Contract(nftAddress, nftAbi, signer);

  // Upload metadata ke IPFS terlebih dahulu
  const metadataURI = "ipfs://QmYourMetadata...";

  const tx = await contract.mint(metadataURI, {
    value: ethers.parseEther("0.01"), // mint price
  });

  const receipt = await tx.wait();

  // Ambil tokenId dari event Transfer
  const transferEvent = receipt.logs.find(
    (log) => log.topics[0] === ethers.id("Transfer(address,address,uint256)")
  );
  console.log("Minted NFT!");
}

Enumeration & Ownership

Yang akan kamu pelajari