0

手把手從零發行 StarkNet NFT(一)

 1 year ago
source link: https://medium.com/taipei-ethereum-meetup/%E6%89%8B%E6%8A%8A%E6%89%8B%E5%BE%9E%E9%9B%B6%E7%99%BC%E8%A1%8C-starknet-nft-%E4%B8%80-3309afbca84
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

手把手從零發行 StarkNet NFT(一)

本次系列文除了介紹以 Cairo 語言在 StarkNet 實作 ERC-721 Token 的智能合約(包含開發環境、編譯、部署)之外,還會介紹如何撰寫一個 StarkNet 上的 Mint Dapp。

本文作為系列文的第一篇,會帶著大家先建置 StarkNet Contract 的開發環境,之後在 StarkNet 這個 L2 的 Goerli 測試網 Deploy 屬於自己的 NFT 合約。

Author: ChiHaoLu(chihaolu.eth) @ imToken Labs

0*dzPZCrWSWQ_DHQTo.png

Intro.

Cairo 作為 StarkNet 的底層語言(撰寫 StarkNet OS)和合約語言(StarkNet Contract),他之所以是一個強大的擴容工具的原因是:Validity Proof 能夠讓龐大的計算(也就是過往在 Layer1 Ethereum 會耗費大量 Gas 的那些 Operation)移動到鏈下,然後使用 ZKP(這邊是 STARKS)證明其運算(或者是 Transaction Batchs)的過程(trace)與結果,提交到 L1 鏈上驗證。

同時 Cairo 本身就是一個撰寫零知識證明 Program 的語言,可以說 StarkNet Contract 只是 Cairo Program 的一個子集合。

Cairo Official Link:

Background

本系列文會希望大家已經熟悉怎麼在 Ethereum 發 NFT 了,內容會著重在 StarkNet 開發時比較不一樣的地方,同樣在 L1 開發時有的概念我就不會再做敘述。

在 StarkNet 中只有合約帳戶(CA, Contract Account)存在,沒有像 Ethereum 一樣有 EOA 與 CA 之分。同時若非透過錢包商(ArgentX, Bravvos)建立一個帳戶的過程將會非常繁瑣,因此希望大家仔細地跟著步驟做!

Please Note

  1. Cairo 1.0 上線後,當前合約在未來可能需要進行升級,但本文不會實作可升級合約,因此如果想在主網上線的人請多加小心!不過目前還有許多功能 Cairo 1.0 沒有呈現,所以先用此文章版本的 Cairo 中短期是蠻穩定的!
  2. 本文不包含在 Mint 時收取 Ether 作為費用(因為那有點複雜),言下之意為這將會是一個 Free Mint NFT。

Development Environment

以 Cairo 撰寫 StarkNet Contract 的工具主要有以下,這次會選擇我覺得擴容性最佳且開發起來最穩定的 StarkNet CLI Tool。

StarkNet CLI

要使用 StarkNet CLI 我們必須在電腦中有 python3.9,因此請各位先按照自己的作業系統在電腦中下載 python3.9。檢查方式為打開 Terminal 或 Command Line 輸入指令能進入互動模式就為成功:

$ python
Python 3.9.7
>>> print("Hello World!")
Hello World!

首先我們找到一個自己喜歡的資料夾,未來這裡將會儲存我們的合約,然後使用以下指令進入 python3.9 的 VE(Vitual Environment)模式:

$ python3.9 -m venv myVE
$ cd myVE
$ source ./bin/activate
$ python --version
> Python 3.9.15 // ✅ Your python in the VE is 3.9

以上使用 MacOS 做為示範,Windows 需要使用 Docker 來進行 StarkNet 開發。

接下來是下載兩個我們主要會使用的套件,一是 cairo-lang(包含了我們將要使用的 StarkNet CLI),二是 openzeppelin-cairo-contracts,我們未來要引用的 NFT 合約依然是 OpenZeppelin 幫我們寫好的。

$ CFLAGS=-I`brew --prefix gmp`/include LDFLAGS=-L`brew --prefix gmp`/lib pip3 install ecdsa fastecdsa sympy cairo-lang
$ pip install openzeppelin-cairo-contracts

下載 fastecdsa 時可能會遇到問題,可以查看 官方 Repo 是否有缺少東西。

$ starknet --version
> starknet 0.10.1 // ✅
$ starknet get_block --network alpha-goerli
> { ... } // ✅ the terminal will print lots of block information

下載完之後接著要建置 StarkNet CLI 的環境變數,分別是設定當前 CLI Tool 指令會在哪個網路執行,以及 CLI Tool 操作的錢包設定檔為何,設定完之後打上 $ starknet tx_status 的指令應該要能印出當前該網路的交易資訊。

$ export STARKNET_NETWORK=alpha-goerli
$ export STARKNET_WALLET=starkware.starknet.wallets.open_zeppelin.OpenZeppelinAccount
$ starknet tx_status --hash 0x7067a0b671587f52adc49f11d79eb17b5df86820fc3bf0e71b82f460cc40738
>
// Print the tx which is accepted in L1✅

關於 StarkNet 上的主流帳戶設計有兩種,一是 OpenZeppelin 的帳戶合約,另一則是 ArgentX。設定檔的目的在於假設我們今天要使用 StarkNet CLI 以我們的帳戶去呼叫某個函式,CLI 要知道怎麼使用我們的帳戶合約。

所以這個設定檔會是一個 python 檔,他會藉由不同帳戶類型以不同方式(函式名、參數)去呼叫帳戶合約上的函式,以此完成我們輸入的指令想達到的目的。

Begin the StarkNet Journey

完成以上所有工作之後,接下來我們需要建立一個 StarkNet 的帳戶。這個帳戶將會預設在 StarkNet CLI 中完成所有我們輸入指令的操作,也可以做為大家在 StarkNet 上的錢包(能夠收發 Ether 和所有 Token,也能與合約互動等)。

輸入 $ starknet new_account 這個指令後,StarkNet 將會替我們隨機生產私鑰,並且對應出公鑰及合約帳戶地址。此時此刻僅僅是生出「帳戶資料」而已,並沒有部屬任何帳戶合約到鏈上,目前這個帳戶地址在 StarkNet 上也是空空如也。

$ starknet new_account
>
Account address: ...
Public key: ...
Move the appropriate amount of funds to the account, and then deploy the account
by invoking the 'starknet deploy_account' command.

輸入以下指令可以找到帳戶資訊:

$ ls ~/.starknet_accounts/starknet_open_zeppelin_accounts.json

在 StarkNet 中並沒有 EOA 的存在,所有帳戶都是 CA。一個合約帳戶想要被部屬在 StarkNet 上,他必須在自己的地址上有 Ether,之後自己部屬自己。

我知道聽起來有一點奇怪,這個帳戶沒有部屬的話,匯錢到帳戶地址然後讓他部署自己?但因為這裡如果解釋太多會變得過於複雜,因此大家先繼續照著做吧!有興趣的人可以再針對 StarkNet AA 和 deploy_account 的 Transaction Type 做深入探討。或者看看我之前寫過的Account Abstraction 介紹系列文!

首先我們到 StarkNet Goerli Faucet 貼上自己地址並且領取,我們就能夠到 StarkScan(就是 StarkNet 上的 Etherscan) 來查看這筆交易,完成後就可以繼續下一步。

0*OJ4SADhs3RKYsx1L.png

接下來我們要把自己的帳戶合約進行部署,輸入以下指令:

$ starknet deploy_account
>
Sending the transaction with max_fee: 0.000087 ETH (86844966419942 WEI).
Sent deploy account contract transaction.
Contract address: ...
Transaction hash: ...

完成之後到 StarkScan 上查看自己的帳戶地址(記得要選對網路),可以在 Portfolio 看見自己有一定的 ETH。到這裡就成功完成 StarkNet CLI 開發環境的建置了!

ERC-721 StarkNet Contract

Cairo 這個語言本身有點像 Rust 和 C 綜合起來的 Solidity,因此撰寫起來除了需要注意原本智能合約的語法不同,還需要多注意記憶體的指標和一些 hash 相關的內容。

但本篇文章不打算介紹 Cairo 的語法,主要是帶過一次簡單的開發流程,讓大家基本了解在 StarkNet 開發的感覺大概是怎麼樣,還有度過一開始最容易讓人怯步的環境建置環節。

Import OpenZeppelin Contract

首先在當前資料夾(也就是 myVE 之中)建立一個檔案叫做 MyBFT.cairo,Cairo 程式的副檔名就是 .cairo,之於 Solidity 程式的副檔名是 .sol

然後我們要做的事情就是把以下的文字貼上,最簡單的 NFT 合約就完工了!

// MyNFT.cairo
%lang starknet
from openzeppelin.token.erc721.presets.ERC721MintableBurnable.cairo import (
constructor,

// View Function
supportsInterface,
name,
symbol,
balanceOf,
ownerOf,
getApproved,
isApprovedForAll,
tokenURI,
owner,

// External Function
approve,
setApprovalForAll,
transferFrom,
safeTransferFrom,
mint,
burn,
setTokenURI,
transferOwnership,
renounceOwnership
)

基本上大家有寫過 Solidity 版本的 NFT 合約的話,應該都會知道以上引入的函式作用為何,那由於 Cairo 並沒有繼承(Inheritance)只有引用(Import),所以最簡單的情況下,我們就使用 import 導入 OZ 幫我們寫好的 NFT 合約即可。

那如果大家想要在自己的 NFT 合約增加更多功能,可以到模組資料夾找到 openzeppelin,然後順著路徑 openzeppelin.token.erc721.presets.ERC721MintableBurnable.cairo,就可以找到我們引用的合約了!

Deploy Contract on Goerli

有了合約之後我們就需要編譯他:

$ starknet-compile MyNFT.cairo \
--output MyNFT_compiled.json \
--abi MyNFT_abi.json

在 StarkNet 上部署(deploy)一個合約之前需要先宣告(declare)他,宣告之後我們就會將這個合約的編譯後資料存在鏈上,未來如果要部署「一模一樣的」合約,就可以直接用宣告得到的 Class Hash 進行部署即可,不用再自己重新編譯一次:

$ starknet declare --contract MyNFT_compiled.json
>
Declare transaction was sent.
Contract class hash: 0x4f583696b59f2c3b81becd117c14b95933d186111eff633d215e7a0e3fdb2d2
Transaction hash: ...

宣告完得到 Contract Class Hash 之後,我們準備部署這個合約,部署的指令如下,其中角括弧中代表的是我們需要放進去的參數。

$ starknet deploy --class_hash <Class_Hash> \
--inputs <name: felt> <symbol: felt> <owner: felt>

那由於在 Cairo 中並沒有 string,只有 felt(為 Cairo 最基本的單位,字串及數字都以 felt 表達),所以我們需要利用好用的 小工具string 轉為 felt,如果大家對 Nile 有興趣也可以使用以下指令:

$ pip install cairo-nile
$ python
>>> from nile.utils import str_to_felt
>>> str_to_felt('MyToken')
21806976760243566
>>> str_to_felt('MT')
19796
>>> str_to_felt('0x04112383E7deFC9A697aE0fE9452B22437f4c73A06D8330cEE4d147B1390FA26')
1839532911728319949577805561336351143590444159269087242333698784473075743270
>>> exit()

以上就萬事具備了,此時輸入指令就可以成功部署我們的 NFT 合約!

$ starknet deploy --class_hash 0x4f583696b59f2c3b81becd117c14b95933d186111eff633d215e7a0e3fdb2d2 \
--inputs 21806976760243566 19796 1839532911728319949577805561336351143590444159269087242333698784473075743270
>
Sending the transaction with max_fee: 0.000714 ETH (714047439973103 WEI).
Invoke transaction for contract deployment was sent.
Contract address: ...
Transaction hash: ...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK