--- tags: Blockchain --- # 初步探討 NFT -- 智能合約 ![](https://i.imgur.com/ceCZ4TU.png =320x) ## 什麼是 NFT ? NFT 全名 Non-fungible token,非同質化代幣。 > fungible : easy to exchange or trade for something else of the same type and value 簡而言之就是這個 token 是獨一無二的,例如說:你可以用同一顆 bitcoin 交換到同一顆等值的bitcoin,但是你用 NFT 只會交換到不一樣的 NFT,很像是小時候玩的卡片遊戲,每個人的卡片都是不一樣的。 NFT 是在區塊鏈上的 cryptographic 產品,有著獨特的 ID 跟 metadata 來區分不同的 NFT。 也因為 NFT 不可替代的原因,NFT 可以在不同領域中被使用,NFT用來代表實體的資產是一個很理想的載具,像是房地產或是藝術品。NFT 還可以用來繞過 intermediates,直接把藝術家跟顧客連結,或也可以當作身份認證。 總而言之,NFT 能達到移除 intermediate、簡化流程、創立新市場這些功能。 ![](https://i.imgur.com/2Efh6wH.png =320x) ## 智能合約又是什麼? 智能合約可以說是 NFT 裡的核心,沒有智能合約,那一顆 NFT 也就是一張照片而已。 智能合約是被儲存在區塊鏈上的程式,當預設的條件被達到就會運作。而這些運作都是完全自動的,並不需要我們去進行控制。也就是說智能合約的流程是自動化的,讓交易的參與者馬上得知 agreement 的 outcome,不需要第三方的介入或是時間損失。 智能合約是使用 Solidity 寫的,Solidity 是一個合約導向的程式語言,受到 C++、Python、Javascript 這些語言的影響,語法設計參考了 `ECMAScript` ,所以語法跟 javascript 非常相似。 Solidity 程式碼編譯好可以在 ```EVM``` 上運行,因為現在 solidity 還在開發中,所以更新非常快速,要小心語法的變動。 > EVM:Ethernet Virtual Machine,是智能合約運行的環境。 > ![](https://i.imgur.com/P5OmFxj.png =320x) ## 智能合約優點 1. 快速、效率且準確 當達到一個智能合約的條件時,對應的動作會被立即執行。因為智能合約是數位且自動化的,所以不需要任何紙張的契約,也不會出現人工填入紙本契約發生填錯的問題,就不會有更改錯誤所要花費的時間。 2. 信任和透明 因為雙方之間沒有第三方的介入,且雙方的交易紀錄都是雙方可以看到的,所以不會有資料被其中一方更改的問題出現。 3. 安全 區塊鏈的交易紀錄都是經過加密的,讓他們變得不好破解。並且每一個紀錄都是接著上一個紀錄以 subsequent 方式儲存在一個分散式帳本上,所以駭客要破解一整條鏈才可以更動一個紀錄。 ![](https://i.imgur.com/IeTFvO1.png) 4. 省錢 因為智能合約不需要第三方介入交易過程,所以可以減少這其中交易成本或時間成本。 ## 我們會使用到的工具 ### ERC721A 我們要實作出一個 NFT 智能合約,那總得要有一個藍圖參考,不然大家寫出來的智能合約功能都不太一樣那就不能進行操作了。所以也會有一個針對 NFT 的 protocol,也就是 ERC721。ERC721 就是 NFT 智能合約的標準,大家都是透過這個 protocol 去實作功能,可以想像成電腦硬體的浮點數數值系統都是按照 IEEE754 的標準下去實作。 我們選擇的 protocol 是 ERC721A,是 ERC721 的改良版,主要的目的就是減少 gas fee。 > ERC721A 跟 ERC721 更詳細的探討可以看這篇[文章](https://hackmd.io/@steven1lung/erc721a)。 ![](https://i.imgur.com/yLAu1O7.png =450x) ### IPFS 因為我們會幫自己的 NFT 加上圖片,就跟大家在外面買到的 NFT 一樣都會有一個圖片。所以我們會將 NFT 的圖片放上 IPFS (一個儲存空間) 來讓我們可以進行存取。 我們要自己上傳到 IPFS 或是其他的空間都可以,這邊使用 IPFS 是因為 IPFS 也是去中心化的儲存空間。 >對 IPFS 更詳細的介紹可以去看我另外一篇[文章](https://hackmd.io/@steven1lung/ipfs)。 ![](https://i.imgur.com/y7PMPcL.png =350x) ## 直接看智能合約的程式碼 ```solidity= //SPDX-License-Identifier: MIT pragma solidity ^0.8.11; import "erc721a/contracts/ERC721A.sol"; contract Steven_Test is ERC721A { uint256 public price = 0.001 ether; //自己的 json 位址 string public picURI = "ipfs://xxxxxxxx"; constructor() ERC721A("Steven Test", "ST") {} function mint(uint256 quantity) external payable { require(quantity <= 1, "Allow only one NFT per mint"); require(price <= msg.value, "Not enough ether"); _safeMint(msg.sender, quantity); } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { return picURI; } } ``` 這邊是一個非常簡單的智能合約範例,只有最基本的功能,程式碼在[這裡](https://gist.github.com/steven1lung/985222ef28530ced446f95185808f0d7)。 ### Mint ```solidity function mint(uint256 quantity) external payable { require(quantity <= 1, "Allow only one NFT per mint"); require(price <= msg.value, "Not enough ether"); _safeMint(msg.sender, quantity); } ``` `mint` 這個函式就是實作買一顆 NFT 的功能,呼叫這個函示並且傳入要的數量就可以進行購買。這邊我們的示範有加入一些限制,像是一次最多只能 mint 一顆 NFT。 可以看到我們使用了兩個 `require` 來確認一些基本的條件,我們這邊設定最多只能 mint 一顆 NFT,並且我們所要付的 ether 要大於價格(也就是我們在第 7 行設定的 `price`)。 ### URI ```solidity function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { return picURI; } ``` 這邊就是實作出 NFT 有圖片的地方,如果沒有這個函式,那我們所購買到的 NFT 就會是一張空白的圖片。 ## 進行發布 ### 1. 註冊 metamask 錢包 ### 2. 領取測試幣 在 rinkeby faucet 領一些測試幣(領大概 0.4 0.5 eth 就夠了)。 ### 3. 將圖片打包上傳到 ipfs 可以使用 [pinata](https://www.pinata.cloud/) 上傳,上傳後複製 CID 貼 json 裡。 會長這樣: ```json { "name": "Steven Test", "description": "hi this is my first NFT", "image": "ipfs://QmQTHrZzcf7KeYdECkRXySiit9z3nUrDfdnHHhw1WbEYmu" } ``` 接著再把這個 json 上傳到 ipfs,並且複製這個檔案的 CID 貼到上面的 [picURI](https://hackmd.io/JTlFKxLIQLieVAJbQdSWNg?view#%E7%9B%B4%E6%8E%A5%E7%9C%8B%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%A2%BC) 第 10 行的地方。 :warning: 注意是要把 JSON 的 CID 放到 `picURI` 的地方,不是圖片的 CID 歐。 ### 3. 將智能合約編譯 在 remix 貼上剛剛的智能合約程式碼,並進行編譯。 ### 4. 發佈到測試鏈上 deploy 到 injected web3。 ### 5. Mint NFT 在下面 deployed contract 的 mint 輸入 1 並且點選。 記得 mint 的時候要在上面選擇要付多少 gwei。因為我們價格定 0.001 eth,所以是 1000000 gwei。 ### 6. 到 opensea testnet 查看成果 點[這裡](https://testnets.opensea.io/)查看有沒有成功,因為要經過區塊鏈操作,所以會需要等個 1 分鐘左右。