iT邦幫忙

2021 iThome 鐵人賽

DAY 20
1
Modern Web

All In One NFT Website Development系列 第 20

Day 20【ERC-721】They don't know I own this song's non-fungible token

  • 分享至 

  • xImage
  •  

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f821ec11-341b-4b56-9a3a-2e259b1b5b07/Elon-Musk-NFT-meme.jpg

【前言】
就我們所知,所謂的鏈上數據通常都是一串的數字或者是文字,但藝術品通常都有其相當的外觀,那這些「圖像」甚至「影片」到底是怎麼儲存,並且出現在我們眼前的呢?

【把圖片存在以太坊上到底要多少錢?】

首先要知道,如果我們把 NFT 的 MetaData 以及相關數據全部儲存在鏈上,那將耗費極大的成本。

在以太坊之中是以 256 bits 為主,假設我們要儲存一張大小為 1 MB 的圖片:

在 Ethereum 中每"單位"是 256 bits = 32 bytes = 2^5 bytes
1 MB =  1,024 KB = 1024 * 1024 bytes = 2^20 bytes

也就是說我們需要 2^20 / 2^5 = 2^15 = 32,768 "單位"

從以下這個網站我們可以發現當前的 STANDARD Gas Prices 是 68 Gwei( in 2021/8/30)。

ETH Gas Station

從 yellow paper 以及 EIP-2200 之中我們可以得知,如果要儲存 32,768 單位的資料,需要 call SSTORE 32,768 次,這個函數是表示把一個值從零設置為非零,而每次需要耗費 20000 的 Gas。

GitHub - ethereum/yellowpaper: The "Yellow Paper": Ethereum's formal specification
EIPs/eip-2200.md at master · ethereum/EIPs

每筆交易的 gas limit 是 21,000 gas,從以下這個網站我們可以發現得到 1 ETH 的價值為 3,163.08 USD ( in 2021/8/30)。

CoinDesk: Bitcoin, Ethereum, Crypto News and Price Data

每一次 call SSTORE 都需要耗費 20000 Gas:


儲存並且交易 1 MB 的資料需耗費 20,000 * 32,768 + 21000 = 655381000 GAS

其價值 655381000 * 68 = 44565908000 Gwei;已知 10^9 Gwei = 1 ETH

= 44.565908 ETH
 
= 140,965.532 USD

= 3,913,696.555. NTD 

沒錯,如果你需要儲存 1 MB 的資料,就需要 3,913,696.555 NTD。所以我們不可能把資料存在鏈上面對吧!

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/45ad6f6d-cabc-47b8-8e39-16f80ad24329/39bcf1b4b69c391c998fd0a41808e5de.jpg

【tokenURI 元數據方法】
當然如果這張圖片的價值超過所需要付出的 Gas,也許有人會決定把所有資訊放上鏈。不過如果不要把 JPEG 放在鏈上的話,那 NFT 的 JPEG 會出現在哪,以何種方式「安全地」呈現呢?

我們接續昨天介紹的 ERC-721 API 與內置函數,

interface ERC721 {
    event Transfer(...);
    event Approval(...);
    event ApprovalForAll(...);

    function balanceOf(...);
    function ownerOf(...);
    function safeTransferFrom(...);
    function safeTransferFrom(...);
    function transferFrom(...);
    function approve(...);
    function setApprovalForAll(...);
    function getApproved(...);
    function isApprovedForAll(...);
}
interface ERC721Metadata {
    function name(...);
    function symbol(...);
    function tokenURI(...);
}

我們要聚焦在 tokenURI 之上。

function tokenURI(uint256 _tokenId) external view returns (string);
// A distinct Uniform Resource Identifier (URI) for a given asset.

觀察之後會發現 NFT 在鏈上其實是儲存成一個 256-bit 的整數。

如果我們去到任何 Etherscan 上的 NFT 合約查看 Contract Source Code,像是我們查看有名的 BAYC 可以發現以下程式碼。

圖片 22.png

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    ...
    // Optional mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;
		...

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

也就是說當我們查看 tokenURI 的時候他執行一個內部的 map 函數,有點像 python 的 dict 雜湊,並不是一個從合約外部來 hash 的函數。

圖片 23.png

此時我們去 Read Contract 的部分查看 tokenURI ,並輸入任意的 tokenId (uint256) 即可查看回傳的 string 是長什麼樣子。我在 Bored Ape Yacht Club 的合約底下查詢 9946 的猴子後,回傳的是:

string :  ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/9946

那圖片到底是儲存在哪並且顯示的呢?我們接下來查看 IPFS 這個東西。

【IPFS】
所謂的 IPFS 譯為 星際文件系統 (Inter Planetary File System),是一個分散式的網站點到點網路傳輸協議。提供一個可用於存取檔案、網站、應用程式與資料的分散式系統。IPFS 協議的目標是取代傳統的互聯網協議 HTTP,因為 HTTP 是中心化且低效的,成本也更高。此外 HTTP 的生存週期也大概只有三個月,Web 文件有可能在儲存成本太高的情況下被刪除。

這邊我們不多加敘述 IPFS 的塊儲存模型、加密方法和與眾不同的服務,回來聚焦在我們的主題上!

如果我們把字串中的 ipfs:// 改成 https://ipfs.io/ipfs/ 就可以來到一個神祕的地方!

https://ipfs.io/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/9946

我們可以發現這是一個 JSON 的檔案格式,裡面儲存的就是這個 NFT 該要有的資料,也就是 NFT 的 MetaData!

{"image":"ipfs://QmQn9BnEMHrbqApJ59wDnFqEjtoZE6pKy4LoxFhWA7MKPw",
 "attributes":[{"trait_type":"Hat","value":"Sea Captain's Hat"},
						 	 {"trait_type":"Mouth","value":"Phoneme Vuh"},
							 {"trait_type":"Eyes","value":"Sad"},
							 {"trait_type":"Background","value":"New Punk Blue"},
							 {"trait_type":"Fur","value":"Golden Brown"}]}

最重要的是我們會看到心心念念的 "image",如果我們使用一樣的方法把字串中的 ipfs:// 改成 https://ipfs.io/ipfs/ 後,就可以看見圖片啦!

https://ipfs.io/ipfs/QmQn9BnEMHrbqApJ59wDnFqEjtoZE6pKy4LoxFhWA7MKPw

現在我們知道了 ERC-721 上的 Token 不管是圖片還是元數據,其實都是藉由合約訪問,並且儲存在 IPFS 上的!

【小結】
相信各位在看完這兩天的文章之後對 ERC-721 Token 以及 NFT 加密藝術品都更有了解!明天就會開始進入查詢 Token Owner 的環節,回到我們的 Project 之中囉!

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9373891c-36c1-4f20-8dda-3a08e1c45399/52hdm4.jpg

【參考資料】
EIPs/eip-721.md at master · ethereum/EIPs
LEVELUPUP
ERC-721 Token with on chain metadata
EIPs/eip-721.md at master · ethereum/EIPs
Your CryptoKitty Isn't Forever - Why DApps Aren't as Decentralized as You Think


上一篇
Day 19【ERC-721】用兵之道在一個奇字,2999兵分2999路
下一篇
Day 21【Tokens' Owner】[問卦] 宋芸樺和夏宇喬到底是不同一個人?
系列文
All In One NFT Website Development32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Capillary J
iT邦新手 4 級 ‧ 2021-10-10 10:45:04

好文!之前也是很好奇NFT的影音檔到底存在哪裡
不過想請問,這樣看起來圖片是存進了ipfs裡
但是ipfs.io 這網站不會有掛掉的一天嗎? 如果掛掉了那是不是一堆展示NFT的服務也會掛?

foodchain iT邦新手 3 級 ‧ 2022-05-25 11:13:21 檢舉

同問XD

我要留言

立即登入留言