初探Move語言:Part 4-撰寫並發佈第一個Sui Move智能合約
這一系列的文章,我想談談Move相較於Solidity有什麼特別之處,不過許多人可能對於這兩種語言都很陌生,甚至不太了解區塊鏈以及去中心化的概念,為了能與大家分享我研究新技術時的喜悅 — — 特別是它們能帶來什麼樣的可能性,我想盡可能地用簡短的文字幫大家建構區塊鏈的世界觀,這個世界觀不免有我主觀的想像,但我認為在這樣的脈絡下,比較容易講述程式語言對區塊鏈世界的影響。
上一篇:
建立一個Package
每個Sui的開發專案,都是以Pakage為單位,我們用以下指令建立一個新的package
sui move new hello_world #hello_world為package name
我們可以看到package中包含了一個用來放原始碼的sources目錄,以及一個專案的組態設定檔Move.toml:
cd hello_world/; ls; #顯示package下的所有檔案或目錄
撰寫智能合約
我們在sources下建立一個檔名為hello_world.move的move原始碼檔案:
touch ./sources/hello_world.move
撰寫一個hello world智能合約:
// 第一個hello_world為package name,第二個hello_world為module name
module hello_world::hello_world {
// imports
use std::string;
use sui::object::{Self, UID};
use sui::transfer;
use sui::tx_context::{Self, TxContext};
// types
struct HelloWorldObject has key, store {
id: UID,
text: string::String
}
// functions
public entry fun mint (ctx: &mut TxContext) {
let object = HelloWorldObject {
id: object::new(ctx),
text: string::utf8(b"Hello World!")
};
}
}
這是一個名為 hello_world
的 Move 模組的定義,它包含了一個名為 HelloWorldObject
的結構體和一個名為 mint
的公開函數。
以下是該模組的詳細解釋:
use std::string;
:導入string
模組,該模組提供了與字符串相關的功能。use sui::object::{Self, UID};
:導入sui::object
模組,該模組可能提供了與物件相關的功能。Self
和UID
是該模組中的兩個元素。use sui::transfer;
和use sui::tx_context::{Self, TxContext};
:導入其他模組和元素。struct HelloWorldObject has key, store {...}
:定義了一個名為HelloWorldObject
的結構體,該結構體有兩個字段:id
和text
。has key, store
表示這個結構體是一個資源類型,它可以被存儲並且有一個唯一的鍵。public entry fun mint (ctx: &mut TxContext) {...}
:定義了一個名為mint
的公開函數,該函數接受一個可變引用到TxContext
類型的參數。在函數體中,創建了一個HelloWorldObject
的實例並初始化了其字段。
將智能合約發佈到鏈上
執行以下命令將智能合約發佈到鏈上:
sui client publish --gas-budget 30000000 --skip-dependency-verification
sui client publish
:這是主要的命令,表示要使用sui
client CLI來發布一個模組或腳本。--gas-budget 30000000
:這是一個選項,表示設置交易的 gas 預算為 30000000。在區塊鏈中,gas 是用來衡量執行交易所需的計算資源的單位,gas 預算就是執行這個交易所能使用的最大 gas 數量。--skip-dependency-verification
:表示在發布模組或腳本時跳過依賴性驗證。在一些情況下,一個模組或腳本可能依賴於其他的模組或腳本,依賴性驗證就是檢查這些依賴是否都已經被滿足。如果使用了這個選項,那麼就不會進行這種檢查。
發佈成功後,會得到一個Status: Success
的輸出提示,同時我們還會得到這個合約的ID,如本例為0xbdbd425511b8237fa142c7f9594585bb13d090ca227f80f85b25d9d5918edb66
:
我們將合約ID儲存到環境變數中,以便待會使用:
export PACKAGE_ID=0xbdbd425511b8237fa142c7f9594585bb13d090ca227f80f85b25d9d5918edb66
調用合約中的函數
sui client call --package $PACKAGE_ID --gas-budget 300000000 --module hello_world --function mint
sui client call
:這是主要的命令,表示要使用sui
Client CLI來呼叫一個函數。--package $PACKAGE_ID
:這是一個選項,表示要呼叫的函數所在的包的 ID。$PACKAGE_ID
是一個環境變數,它的值是要呼叫的函數所在的包的 ID。--gas-budget 300000000
:這是一個選項,表示設置交易的 gas 預算為 300000000。在區塊鏈中,gas 是用來衡量執行交易所需的計算資源的單位,gas 預算就是執行這個交易所能使用的最大 gas 數量。--module hello_world
:這是一個選項,表示要呼叫的函數所在的模組的名稱。--function mint
:這是一個選項,表示要呼叫的函數的名稱。
調用成功後我們會得到一個Status: Success
的輸出提示:
這裡我們可以注意到幾件事情:
- Sui Client使用MoveCall調用了我們剛剛的合約ID下的hello_world模組中的mint函數:
MoveCall(0xbdbd425511b8237fa142c7f9594585bb13d090ca227f80f85b25d9d5918edb66::hello_world::mint()),
- Created Objects為我們調用合約時建立的物件,本例為
0x25fe9c5cb0663cd26931cbca5b2f46efc0f5dd9be3b0f71cde4a5df67c5b4fb6
查詢鏈上資料
我們可以透過https://suiexplorer.com/這個服務來查詢鏈上資料,例如我們剛剛與合約互動的過程。首先,我們要先選擇Devnet作為查詢的鏈:
如果我們輸入剛剛的package id,可以看到合約的內容,或者你可以直接點擊此網址:https://suiexplorer.com/object/0xbdbd425511b8237fa142c7f9594585bb13d090ca227f80f85b25d9d5918edb66?network=devnet
這裡可以看到我們的合約以被轉換成Move Bytecode,Move採用一種介於組合語言與高階語言之間的Bytecode。
接著我們查詢剛剛調用mint函數建立的Object:
這裡我們可以注意幾件事情:
- 這個物件,如同程式碼所描述的,具有id與text兩個fields,其中text欄位也確實按照程式碼設定的,儲存為
Hello World!
- 其中Type為我們的Package ID底下的hello_world模組下定義的HelloWorldObject
總結
至此,我們已經學會了如何撰寫並發佈一個智能合約。並知道如何查詢鏈上數據來驗證合約發佈與調用的過程。