撰文:Sui Network

Sui 是基於第一原理重新設計和構建而成的L1 公有鏈,旨在為創作者和開發者提供能夠承載Web3 中下一個十億用戶的開發平台。 Sui 上的應用基於Move 智能合約語言,並具有水平可擴展性,讓開發者能夠快速且低成本支持廣泛的應用開發。 Sui 主網已於2023 年5 月3 日正式上線

本文將為開發人員在Sui Network 上的最佳實踐做快速參考。

Move

常規知識

閱讀有關包升級的詳細信息並編寫對升級友好的代碼。

  • 包是不可變的,有漏洞的包代碼可以永遠調用,解決方案是在對象層面添加保護。
  • 如果將包從P 升級到P',依賴於P 的其他包和客戶端將繼續使用P,而不是自動更新到P'。因此,依賴於包和客戶端的代碼都必須更新以明確地指向P'。
  • 期望被依賴包擴展的包,可以通過提供符合所有版本標準的(不變的)接口,來避免每次升級時破壞它們之前的擴展。以Wormhole 跨鏈橋為例,通過Wormhole 作為橋樑發送消息,要想生成發送消息的擴展包,可以使用任意版本Wormhole 包中的prepare_message 指令來生成MessageTicket,而發送消息的客戶端代碼必須將該MessageTicket 傳遞到最新版本包中的publish_message。
  • public 函數不能刪除或更改,但public(friend) 函數可以。您可以自由地使用public(friend) 或僅自己可見功能,除非您要將現在的庫函數永遠公開。
  • 不能刪除struct 類型、不能添加新字段(儘管您可以添加動態字段)或通過升級新功能。添加新類型時請謹慎思考,一旦添加後將永遠存在!

使用vector 支持的集合(如vector, VecSet, VecMap, PriorityQueue),最多不超過1000 個數據項。

  • 使用動態字段支持的集合(如Table、Bag、ObjectBag、ObjectTable、LinkedTable)用於任何允許第三方添加的集合、更大的集合和未知大小的集合。
  • Sui Move 對象最大為250KB——任何創建更大對象的嘗試都將導致事務中止,請確保您的對像沒有不斷增長大過vector 支持的集合。

如果您的函數f 需要來自調用者的付款,例如使用SUI ,請使用fun f(payment: Coin) 函數而不是fun f(payment: &mut Coin, amount: u64) 函數。這對調用者來說更安全,因為他們可以準確地知道具體支付數額,並且不需要依靠函數f 來提取正確的數額。

不需要小幅度優化gas 消耗。在Sui 上計算花費成本時,使用四捨五入的方法計算出其最接近的bucket,因此只有非常劇烈的波動才會導致gas 的變化。特別是,如果您的交易已經在最低成本範圍內,那就不能更便宜了。詳情請參照下圖。

Sui開發者必讀:MOVE語言及技術特性

遵循Move 編碼慣例(Move coding conventions)來獲得統一的式樣。

可組合性

  • 使用display 標準自定義您的對像在錢包、應用程序和瀏覽器中的顯示方式。
  • 避免使用「自我轉移」功能——任何時候都有可能,從當前函數返回obj,而不是寫入transfer::transfer(obj, tx_context::sender(ctx)),這允許調用者或可編程交易塊(programmable transaction block)使用obj。

測試

  • 使用sui::test_scenario`模擬多次交易和多位發送者的測試場景。
  • 使用sui::test_utilsmodule 通過assert_eq 測試獲得更好的糾錯消息,通過print 調試打印,以及通過destroy 進行test-only 銷毀。
  • 使用sui move test --coverage 計算測試時代碼覆蓋的信息,使用sui move coverage source --module 查看以紅色突出顯示的未覆蓋行。如果可行,建議將覆蓋率設置為100%。

應用程序

  • 為了獲得最佳性能和數據一致性,應用程序應該在同一個全節點上提交寫入和讀取請求。在TS SDK 中,這意味著應用程序應使用錢包的signTransactionBlock API,然後通過調用應用程序全節點上的execute_transactionBlock 來提交交易,而不是使用錢包的signAndExecuteTransactionBlock API。這確保了先寫後讀的一致性——從應用程序的全節點讀取將立即反映事務的寫入,而不是等待checkpoint。
  • 為了降低延遲,如果您的應用程序需要知道交易已確認,但不需要立即查看交易效果或讀取交易寫入的對象/ 事件,請使用帶有"showEffects": false 和"showEvents": false 的executeTransactionBlock 。
  • 應用程序應該將頻繁讀取的數據本地緩存,而不是從全節點頻繁抓取。
  • 盡可能地使用可編程交易塊(programmable transaction blocks)來組合現有的鏈上功能,而不是發布新的智能合約代碼。可編程交易塊允許大規模批次處理和異構組合,進一步降低已經很低的gas 費。
  • 應用程序應該將對gas 預算、gas 價格和coin 選擇權留給錢包,這將為錢包提供了更大的靈活性,並且錢包有責任試運行交易以確保交易不會失敗。

簽名

  • 永遠不要簽署兩筆觸及同一獨享對象的並發交易,要么單獨使用獨享對象,要么等待一筆交易結束後再發送下一筆交易。違反此規則可能會導致客戶端模棱兩可,從而同時鎖定兩個交易中涉及的獨享對象,直到當前epoch 結束。
  • 任何發起交易的sui client 命令(例如sui client publish、sui client call)都可以接受--serialize-output 標誌以輸出要簽名的base64 交易。
  • Sui 支持多種簽名方案(signature schemes)進行交易簽名,包括包括本機多重簽名。