7

教你製作完全 On-Chain 的 NFT

 3 years ago
source link: https://www.frank.hk/blog/on-chain-nft/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
教你製作完全 On-Chain 的 NFT

首先看看我做的這個 demo: https://testnets.opensea.io/collection/onchainnft-demo

screen 20220402100140 2x

這些 NFT 的特別之處在於,每個 NFT 的圖案都不一樣( ID 不一樣),所有 NFT 的資料都是保存在區塊鏈上,沒有用到任何的伺服器或者 IPFS。

我在製作 ERC721 智能合約那篇文章中說過,NFT 之所以會顯示圖案,是因為根據 NFT 的標準,每一個 NFT 都有一個 json 格式的 metadata 與之對應, metadata 中有一個參數是指定 NFT 的圖案,所以只要訪問這個 NFT 的 metadata,然後再得到圖像地址,就可以顯示出 NFT 的圖案了。

meta

一般的 NFT,metadata 和 NFT 的圖案都是保存在非區塊鏈上,例如伺服器,或者是去中心化的 IPFS。這樣做其中有一個問題就是有可能會導致資料遺失。中心化伺服器自然不用多說,而即便是 IPFS 也是不能保證資料永遠在線(如果對 IPFS 有興趣,可以參考我之前寫的 IPFS 問與答)。如果所有資料都保存在區塊鏈上,則能夠完美解決這個問題。但是,在區塊鏈上保存大量數據非常昂貴,所以想要這樣做,必須盡量減少儲存的數據量,那我們今天就來看看可以怎麼做。

首先我們不可能將所有 NFT 的圖案都「原封不動」的保存在區塊鏈,這樣成本太高。如果有辦法能「即時產生」圖案,則可以大大降低成本。這時我們想到了 SVG 圖案檔。SVG 的本質其實就是一段文字,因此我們可以根據一定的要求隨時「拼湊」出來。

查看 OpenSea metadata 的標準,除了 image 欄位,還有一個 image_data 可供使用,這個image_data 則為我們「即時產生」圖案提供了可能性。

screen 20220402102119 2x

既然 NFT 的圖案可以做到「即時產生」,那純文字的 NFT metadata 更不在話下,我們也可以按照這個思路,讓 tokenURI() 直接返回 NFT 的 metadata JSON, 而不是一個 http 或 ipfs 連接。

好了廢話不多說我們看看程式怎麼寫吧。

tokenURI() 我們做如下處理,拼湊出符合要求的 metadata JSON ,用 Base64 編碼之後直接返回。 注意對 string 進行拼接需要用到 abi.encodePacked , Base64 編碼使用到一個公用 library,文後會給出源碼。

1function tokenURI(uint256 tokenId)
2 public
3 view
4 override(ERC721)
5 returns (string memory)
7 require(
8 _exists(tokenId),
9 "ERC721Metadata: URI query for nonexistent token"
12 string memory json = Base64.encode(
13 bytes(
14 string(
15 abi.encodePacked(
16 '{"name": "On Chain NFT #',
17 uint2str(tokenId),
18 '",',
19 '"image_data": "',
20 onChainSVG.getSvgImage(tokenId),
21 '"',
22 "}"
27 return string(abi.encodePacked("data:application/json;base64,", json));

留意到上面拼接 json 時有一句 onChainSVG.getSvgImage(tokenId) 這個 function 的作用是根據傳入的 tokenId ,即時「產生」一個 SVG 數據。產生 SVG 的邏輯我們調用了另外一個智能合約進行處理,而不是寫在同一個智能合約中。 原因是根據 2016 年實施的 EIP-170 標準,每張智能合約的大小不能夠超過 24.576 kb。所以如果寫在同一張智能合約中會導致智能合約超出要求而無法發佈。

合約部署後,調用 tokenURI() 我們會看到合約直接給出了 metadata 的完整 JSON (Base64 編碼)

screen 20220402104714 2x

如果想測試一下的話,可以到 etherscan 上,連接錢包(Rinkeby 測試網路),調用 mint function mint 一個 NFT 給你自己哦。

screen 20220402110752 2x

兩張智能合約的原始碼:
https://gitlab.com/0x0016/smart-contract-demo/-/tree/main/contracts/nft

OpenSea:
https://testnets.opensea.io/collection/onchainnft-demo

EtherScan:
https://rinkeby.etherscan.io/address/0x5b97a3663d6a9be5ef6a21fb2108b93f93f8b2e5#writeContract

技術交流,其他諮詢等,請按此聯絡

訂閱我的網站,接收更新以及其他有趣的消息 😙 。 訂閱不收費,走過路過別錯過。
Subscribe to my website, I will email you if any new posts or interesting stuff available.

如果你喜歡我的內容,請考慮用一杯咖啡支持我一下吧,非常感謝 🥰 。
If you like my contents, please support me via BuyMeCoffee, Thanks a lot.

其它相關文章

聊一聊 Zombie Club NFT 的技術八卦
2022-03-20
Zombie Club NFT 最近可謂紅的不得了。這個有潮流明星余文樂站台的項目一開始就引人關注。寫這篇文章的初衷,是因為昨天晚上聽了官方團隊的一個技術 AMA,聽到了來自官方對技術上的一些分析和解釋。兩個多小時的 AMA,在最後的聽眾問答環節被推上高潮, 過程有聽眾對於智能合約的處理發出了質疑,問答的重點是關於公售時期幾百筆 out of gas 的原因追問。官方也花了很長時間解釋。但坦白講對於官方的回答有些地方我也不是十分認同。 星期日沒什麼事那這裡我們就來聊一聊這個 out of gas 是怎麼個回事。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK