閱讀時間 17 分鐘
概覽
想打造一個包含 10,000 件作品的 NFT 系列嗎?本指南將帶領您踏上這段旅程,讓您的 10,000 件 NFT 系列在Arbitrum 上煥發新生。您將學習如何建立元資料、使用 Hardhat 部署 NFT 智慧合約,並鑄造獨一無二的代幣,進而在 TofuNFT 等知名 NFT 交易平台上展示。
您需要準備的物品
- 具備 Solidity 和 JavaScript 的基礎知識
- 已安裝Node.js
- 非託管錢包(例如:Torus、MetaMask、Coinbase Wallet)
- Arbitrum 鏈上的 ETH(您可以使用Arbitrum 跨鏈橋)
- 程式碼編輯器(例如VSCode)
您將負責的工作內容
- 使用Hardhat建立 NFT 合約
- 為您的 NFT 系列建立圖片與元資料
- 測試您的 NFT 合約,並部署至Arbitrum
- 鑄造 NFT 並在 NFT 交易平台上瀏覽
Arbitrum 概覽
Arbitrum 是一項針對Ethereum 第二層擴容Ethereum 去中心化應用程式提供超快速且低成本的交易服務。它結合了 AnyTrust 技術與資料可用性委員會(DACs),藉此實現其目標,且成本遠低於Arbitrum 。
AnyTrust 是Arbitrum 技術的一種變體,透過假設存在輕微程度的信任來降低成本。AnyTrust 利用第三方資料可用性委員會(DAC)來儲存資料,並根據需求提供資料存取服務。 身為領先的區塊鏈服務供應商Quicknode 獲選為Arbitrum 的 DAC 委員會成員(與 Google Cloud、Reddit 及 Consensys 共同擔任)。身為 DAC 成員Quicknode 資料可用性伺服器,讓交易批次資料能透過 REST API 依需求提供。如欲進一步了解 DAC,請參閱這篇Quicknode 部落格文章。
Arbitrum 擁有多種應用場景,例如 Web3 遊戲和社交基礎設施,但在本指南中,我們將特別探討 NFT(非同質化代幣)。這些獨特的數位資產近年來日益普及,而人們可能選擇在Arbitrum 上開發 NFT 的原因有以下幾點:
- 超低的交易成本
- 交易速度快,區塊生成時間短
- 其他 EVM 鏈之間的互通性
這些優勢對於交易量龐大的專案而言同樣具有益處,例如遊戲開發、社群專案以及去中心化金融(DeFi)。
若想進一步了解Arbitrum 相較於Arbitrum 及其他區塊鏈的優勢,請參閱這份Quicknode
設定開發環境
步驟 1:透過Quicknode存取Arbitrum
您需要一個 APIendpoint Arbitrum 鏈endpoint 通訊。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。請點此註冊帳號。
登入後,請點擊「建立Endpoint 然後選擇Arbitrum Mainnet 。

endpoint 後,請將 HTTP 提供者 URL 備妥,因為您稍後在指南中設定.env檔案時會需要它。
步驟 2:建立錢包並存入 ETH
在本指南中,我們將使用Torus Wallet,這是一款支援多條鏈與網路的非託管錢包,包括Ethereum、Arbitrum 、Arbitrum 及其他與 EVM 相關的鏈。 請注意,若要在Arbitrum Mainnet進行部署,您需要持有實際資金(ETH)以支付交易手續費。這些手續費應相當低廉,且不應超過 0.25 美元。您可以在Uniswap等去中心化交易所,或Coinbase 等傳統交易所購入 ETH。您可使用Arbitrum Bridge將資金轉入Arbitrum 。
要開始使用,請前往Torus並依照指示生成私鑰。

在繼續閱讀本指南的技術內容之前,請確保您的Arbitrum mainnet 足夠的資金,以支付合約部署及互動所需的費用。若您需要跨鏈轉移資金,可使用Arbitrum 跨鏈橋。
步驟 3:建立新專案
若要使用 Hardhat,您首先需要在電腦上安裝 Node.js。您可以從官方網站nodejs.org 下載。
開啟終端機,確認已安裝 Node.js 且版本為 18>:
node -v
請導航至您要建立專案的目錄。在本指南中,我們將建立一個名為10k-collection 的資料夾:
mkdir 10k-collection
導航至您剛建立的資料夾,然後使用以下指令初始化一個新的 npm 專案:
npm init -y
接著,請執行以下指令來安裝 Hardhat:
npm install --save-dev hardhat
--save-dev 會將此項目新增至 package.json 中的 devDependencies 清單中
現在,我們將透過執行以下指令來初始化一個 Hardhat 專案:
npx hardhat create
當系統提示您選擇要建立的專案類型時,請選擇第三個選項(即「建立一個空的 hardhat 設定檔」)。
這將建立一個具有預設 Hardhat 專案結構的新目錄。接下來,我們需要為我們的10k-collection 建立所需的資料夾。
mkdir contracts
mkdir test
mkdir scripts
步驟 5:安裝必要的函式庫
在專案目錄中,執行以下指令以安裝專案所需的依賴項:
npm install dotenv @openzeppelin/contracts @nomicfoundation/hardhat-toolbox
步驟 6:設定部署所需的配置檔
為了保護您的私密金鑰和 RPC URL(若您將程式碼發佈至 GitHub),我們將建立一個.env檔案來儲存這些憑證。將程式碼推送至 GitHub 時,請勿將此檔案一併包含在內。
在您的主要專案目錄中,執行以下終端機指令以建立.env檔案:
echo > .env
請開啟該檔案並輸入以下變數。接著,請將佔位符的值更新為您的實際憑證。請記得儲存檔案!
RPC_URL=<YOUR_RPC_URL>
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
接下來,我們將設定hardhat.config.js檔案。開啟該檔案,並輸入以下程式碼。
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();
module.exports = {
solidity: "0.8.17",
networks: {
nova: {
url: process.env.RPC_URL,
accounts: [process.env.PRIVATE_KEY]
}
}
};
請記得儲存檔案!在下一節中,我們將為我們的 10K NFT 系列建立圖片和元資料。
建立元資料並上傳至IPFS
在本節中,我們將為 10K NFT 系列建立元資料。
具體來說,我們將使用Figma以及這個 GitHub儲存庫來生成圖像資源和元資料(感謝開發者!)。請注意,您也可以使用其他工具來處理元資料,這並非唯一的方法。
若要製作 10,000 個具有不同圖像的 NFT,您至少需要七個圖層,每個圖層包含四種不同的選項。請參閱此Figma 檔案以查看範例。請注意,此 Figma 檔案僅包含三個圖層,其餘四個圖層已預先建立在我們所使用的儲存庫中。此外,您也可以跳過此步驟,僅使用 GitHub儲存庫中的範例素材。
將圖像資源匯出至電腦後,請克隆以下儲存庫,並在您偏好的程式碼編輯器中開啟它。
git clone https://github.com/manuelpires/nft-collection-generator/
接著,請使用以下指令安裝所需的依賴項:
npm install
如果您使用的是 Mac OS X,且上述安裝指令出現錯誤,您可能需要先安裝以下函式庫:
brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman
& 接著安裝 canvas:
npm i canvas
現在,請建立兩個資料夾「metadata」和「images」:
mkdir metadata && mkdir images
接著,進入traits目錄,並為每個圖層建立資料夾。在本範例中,我們為箭頭、圓形和 星形各建立了一個資料夾。
注意:若您僅使用 traits 資料夾中已有的範例圖片,請忽略此步驟,直接執行node index.js指令。

接著,開啟config.js檔案,並將各層級新增至ORDERED_TRAITS_LIST物件中。範例如下:
{
type: "Square",
options: [
{
image: "./traits/square/bright-coral.png",
value: "Bright Coral",
weight: 1,
},
{
image: "./traits/square/liliac.png",
value: "Liliac",
weight: 1,
},
{
image: "./traits/square/pumpkin.png",
value: "Pumpkin",
weight: 1,
},
{
image: "./traits/square/spring.png",
value: "Spring",
weight: 1,
},
{
weight: 1,
},
],
},
請注意,各層級是依序新增的,因此請留意您使用的順序。「權重」選項是相對於同一選項陣列中其他項目的權重而言,且必須為不小於 1 的整數。若您將某個選項的權重設為 10,則該選項被選中的機率應為同一陣列中權重為 1 的選項的十倍。
在您於config.js中設定好所有元資料與圖片參照,並安裝完畢所需依賴項後,請執行以下指令來產生元資料與圖片:
node index.js
一旦圖片和元資料生成完成,請花幾分鐘時間檢視它們,以確保其生成結果符合預期。待我們將圖片和元資料上傳至IPFS 後,將需要將基礎 URL 替換為實際的元資料連結,因此請將此資料夾保留在手邊。
將元資料與圖片發佈至IPFS
既然我們的元資料和圖片都已建立,接下來我們需要將它們上傳至 IPFS——這是一個用於在分散式檔案系統中儲存與分享資料的協定、超媒體及點對點檔案共享網路。 我們選擇使用IPFS 集中式儲存方案(例如 Amazon),是因為其去中心化的特性與我們希望 NFT 系列所體現的理念相符。不過請注意IPFS 但有時速度可能會較慢,而且您需要主動固定您的內容(即保持IPFS 持續運行),才能確保您的元資料可被檢索。
此外,您也可以使用Pinata(提供免費與付費版本)或NFT.Storage(免費但儲存空間有限)等服務,輕鬆將資料上傳至IPFS 您的內容保持固定狀態以加快檢索速度;不過這些服務都有儲存空間限制,且可能需要付費。
無論如何,您需要將元資料上傳至一個資料夾中,以確保該目錄內所有檔案的根路徑皆相同。
例如:
https://ipfs.io/ipfs/bafybeidhtkrvmboa4pel3i3asl57rgmrtai4zelpoeccfulw7qxqbhwyw4/metadata/
上述網址指向IPFS 上的某個資料夾IPFS 包含 NFT 元資料檔案。您也可以在路徑末尾加上一個數字(例如 /metadata/1),以查看每個 NFT 的個別元資料。將這些資料標準化至關重要,這樣應用程式才能更輕鬆地顯示您的 NFT 並與其互動。
首先,我們將IPFS 以下連結安裝IPFS 。雖然IPFS 方式可以存取IPFS ,但我們將透過Kubo 二進位檔進行安裝。
接著,開啟一個新的終端機視窗(Mac 上按 CMD + T),並檢查IPFS 是否IPFS 安裝:
ipfs
接下來,我們將啟動IPFS ,用以將資料固定到IPFS 並確保其持久性。
ipfs
您應該會看到類似以下的內容:
initializing ipfs node at /Users/user/.ipfs
> generating 2048-bit RSA keypair...done
> peer identity: Qmcpo2iLBikrdf1d6QU6vXuNb6P7hwrbNPW9kLAH8eG67z
> to get started, enter:
>
> ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme
要將我們的IPFS 上線,請執行以下指令:
ipfs
請記錄該守護程式正在監聽的 TCP 埠號
接著,開啟另一個終端機視窗。若您已連線至網路,執行以下指令時,應該就能看到對等節點的IPFS :
ipfs 對等節點
您可以執行以下指令,測試您的IPFS 向網路請求資料:
ipfs ipfs> ~/Desktop/spaceship-launch.jpg
如果您成功下載了這張圖片,太好了!現在我們可以將圖片和元資料上傳至IPFS 了。
在專案的根目錄中,執行以下IPFS 以固定 images 資料夾:
ipfs -r images/
輸出結果的最後一行將顯示根目錄的 CID,該目錄即為您上傳的資料夾的頂層目錄。您只需將此 CID 添加至IPFS 網址「ipfs」的末尾,即可透過此IPFS 存取該資料夾。

既然圖片已經上傳完成,請從根目錄下的`images/`資料夾中取得 CID 雜湊值,然後返回`nft-collection-generator` 儲存庫。使用以下終端機指令,一次將所有佔位符 URL 替換為您實際的圖片 URL:
find metadata -type f -exec perl -pi -e 's#https://base-uri-to-my-nft-images.com/#https://ipfs.io/ipfs/{CID}/#g' {} +
請記得將 {CID} 請在上述指令中,將您的「images/」資料夾中上傳的圖片所對應的IPFS 雜湊值填入其中!
最終,您的元資料檔案中的內容應如下所示:
{
"tokenId": 0,
"name": "KT0",
"description": "KT Collection",
"image": "https://ipfs.io/ipfs/Qma5p2daHfdui4keZjMrJpgmL7JRjoZ6J5GcyLPUcmTTuT/0.png",
"attributes": [
{
"trait_type": "Background",
"value": "Robin"
},
{
"trait_type": "Square",
"value": "Spring"
},
{
"trait_type": "Triangle",
"value": "Green"
},
{
"trait_type": "Circle",
"value": "Blue"
},
{
"trait_type": "Arrows",
"value": "Up"
}
]
}
接下來,我們需要將元資料(JSON 檔案)打包成一個 .CAR(內容導向存檔)檔案。您可以使用ipfs 指令來執行此操作。
執行以下指令,以建立一個包含 JSON 檔案的 CAR 檔案:
npxipfs--pack metadata/
系統可能會要求您安裝外部函式庫
既然我們的 JSON 已打包成 .CAR 檔案,我們將IPFS 以下指令將其固定到IPFS 上:
ipfs import metadata.car
您應該會看到類似以下的回應:
固定根 bafybeihzssbfdo6cmprolorfimhda4yapkzkyukffsteta6exwcr4nipzi 成功
您可以透過前往上傳檔案中引用的 CID,來確認您的元資料是否可存取。請記得在網址末尾加上 /metadata/ 路徑:
https://ipfs.io/ipfs/{CID}/metadata/

You can also access the IPFS URL through your local IPFS node (daemon). Depending on the state of the network, curl may take a while due to public gateways being overloaded or having a hard time reaching you. To view the objects on your local gateway, try "http://127.0.0.1:8080/ipfs/{CID}". For the public gateway, use https://ipfs.io/ipfs/{CID}.
請注意,請使用IPFS 檢查工具來查看當前最快的閘道。
在下一節中,您將開發自己的 NFT 合約!
建立 NFT 合約
在 contracts 目錄中建立一個名為NFT.sol的新檔案。
開啟該檔案,並輸入以下程式碼:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
// Contract for creating 10k tokens, inherits from ERC721 and Ownable
contract KTokens is ERC721, Ownable {
// Max supply
uint256 public constant MAX_SUPPLY = 10000;
// Current supply
uint256 public totalSupply = 0;
// Use Counters library for token ID counter
using Counters for Counters.Counter;
// Private variable to keep track of token ID
Counters.Counter private _tokenIdCounter;
// Constructor to initialize the contract with the name "10K Tokens" and symbol "10KT"
constructor() ERC721("10K Tokens", "10KT") {}
// Internal function to return the base URI for the contract
function _baseURI() internal pure override returns (string memory) {
return "https://ipfs.io/ipfs/{CID}/metadata/";
}
// Function to mint a new token, only callable by the contract owner
function safeMint(address to) public onlyOwner {
//Require that the current supply is less than max supply
require(totalSupply <= MAX_SUPPLY, "Maximum supply reached");
//Increment total supply variable
totalSupply++;
// Get the current token ID
uint256 tokenId = _tokenIdCounter.current();
// Increment the token ID counter
_tokenIdCounter.increment();
// Mint the token to the specified address
_safeMint(to, tokenId);
}
}
請花幾分鐘時間瀏覽程式碼註解,以便更深入理解其中的邏輯
雖然此處未顯示,但我們從 OpenZeppelin 導入的ERC721.sol合約中繼承了tokenURI函式。此唯讀函式接受一個tokenId參數,並回傳應指向該特定代幣元資料的 URL。
You'll need to edit the placeholder (https://ipfs.io/ipfs/{CID}) in the _baseURI() function with the CID you obtained when uploading your metadata directory. This CID or URL, if you are not using IPFS, should point to the directory your metadata lives in. Remember to save the file before moving to the next step!
接下來,您需要編譯 NFT 合約。這涉及將 Solidity 程式碼編譯成位元組碼,並將其部署至區塊鏈上。
要編譯合約,請執行以下 Hardhat 指令:
npx hardhat compile
您應該會看到類似以下的內容:
已成功編譯 13 個 Solidity 檔案
在下一節中,我們將為 NFT 合約建立測試,以確保部署至Arbitrum mainnet時一切順利。
測試 NFT 合約
在本節中,我們將建立測試來驗證 NFT 合約的運作行為。測試 NFT 至關重要,因為這能讓開發者確保其智慧合約在部署至區塊鏈之前,能如預期般運作且不含錯誤。這點至關重要,因為一旦合約部署完成,便無法進行修改或刪除,因此任何錯誤或問題都將成為永久性問題。此外,測試還能協助防範合約中潛在的安全漏洞,以免遭惡意行為者利用。
在tests目錄中,建立一個名為NFT.js的檔案,並輸入以下程式碼:
const { expect } = require("chai");
describe("KTokens", () => {
let kTokens;
let owner;
beforeEach(async function () {
// Retrieve the default account from ethers
[owner] = await ethers.getSigners();
// A helper to get the contracts instance and deploy it locally
const KTokens = await ethers.getContractFactory("KTokens");
kTokens = await KTokens.deploy();
});
it("should have the correct name and symbol", async () => {
expect(await kTokens.name()).to.equal("10K Tokens");
expect(await kTokens.symbol()).to.equal("10KT");
});
it("should be able to mint new tokens", async () => {
// Mint a new token
await kTokens.safeMint(owner.address);
expect(await kTokens.ownerOf(0)).to.equal(owner.address);
});
});
請花幾分鐘時間檢視程式碼註解,以更深入理解其中的邏輯
要執行測試檔案,請執行以下指令:
npx hardhat test
您應該會看到以下輸出:
KTokens
✔ should have the correct name and symbol
✔ should be able to mint new tokens
2 passing (1s)
在下一節中,我們將把這套 10,000 件的 NFT 系列部署到Arbitrum !
部署 NFT 合約
在您的 scripts 資料夾中,建立一個名為deploy.js 的檔案:
echo > scripts/deploy.js
接著,開啟該檔案並輸入以下程式碼:
const hre = require("hardhat");
async function deploy() {
// Deploy the contract
const NFT = await hre.ethers.getContractFactory("KTokens");
const nft = await NFT.deploy();
// Print the deployed contracts address
console.log("NFT contract deployed at:", nft.address);
}
deploy()
.then(() => console.log("Deployment complete"))
.catch((error) => console.error("Error deploying contract:", error));
此檔案將包含將我們的合約部署至Arbitrum Mainnet所需的邏輯。
要部署合約,請在終端機中執行以下 hardhat 指令:
npx hardhat run --network nova scripts/deploy.js
該
nova該物件就是我們在 hardhat.config.js 中建立的那個
您應該會看到一則包含已部署合約地址的輸出訊息。
NFT contract deployed at: 0xf18802cb61EF336E30c5B93a7c9C961b1e80BeDE
Deployment complete
鑄造 NFT 並在 NFT 交易平台上查看
既然我們的 NFT 合約已經部署完成,接下來就來鑄造一個 NFT,並在 NFT 交易平台上查看它。為了配合本指南的說明,我們這裡只會鑄造 1 個 NFT,但您也可以使用相同的流程來鑄造多個 NFT。
在您的scripts資料夾中建立一個名為 mint.js的檔案:
echo > scripts/mint.js
接著,開啟該檔案並輸入以下程式碼:
const hre = require("hardhat");
async function main() {
let owner;
// Retrieve the default account from ethers
[owner] = await ethers.getSigners();
// Get contract factory for the NFT contract
const NFT = await ethers.getContractFactory("KTokens");
// Attach to deployed contract at the specified address
const nft = await NFT.attach(
"DEPLOYED_CONTRACT_ADDRESS" // Your deployed contract address
);
// Call the safeMint function to update the value
let safeMintTx = await nft.safeMint(owner.address)
console.log("safeMint function call. Waiting for confirmation...")
// Wait 3 blocks for the transaction to be confirmed
await safeMintTx.wait(confirm=3);
// Get the latest total Supply
let tokenSupply = (await nft.totalSupply()).toString()
//Decrease by one since tokenID starts at zero
let tokenIdInt = parseInt(tokenSupply) - 1
//Get owner of minted tokenID
let tokenOwner = await nft.ownerOf(tokenIdInt);
console.log(`Token ID ${tokenId} - tokenOwner ${tokenOwner}`)
}
// Start the script and handle any errors
main()
.then(() => console.log("Script complete"))
.catch((error) => console.error("Error running script:", error));
鑄造完成後,您可以前往 NFT 交易平台(例如tofuNFT.com——這是一個支援Arbitrum 的多鏈 NFT 交易平台),並輸入您的錢包地址來查看該 NFT。

如果您想了解如何一次鑄造 10,000 個代幣,請參閱這篇《如何使用 ERC721A 實作來鑄造 NFT》的指南。
Arbitrum
既然您已經在Arbitrum 上部署了第一個智慧合約,不妨探索一下Arbitrum 鏈所提供的部分資源:
其他資源
若您想進一步了解Arbitrum 和智慧合約,請參考以下資源:
結論
恭喜!您現在已經具備部署 10,000 件 NFT 系列的能力了!
