智能合約編寫之Solidity的基礎特性 | FISCO BCOS超話區塊鏈專場(篇2)

做者.jpg

如前篇介紹,目前大部分的聯盟鏈平臺,包括FISCO BCOS,都採用Solidity做爲智能合約開發語言,所以熟悉並上手Solidity十分必要。html

做爲一門面向區塊鏈平臺設計的圖靈完備的編程語言,Solidity支持函數調用、修飾符、重載、事件、繼承等多種特性,在區塊鏈社區中,擁有普遍的影響力和踊躍的社區支持。但對於剛接觸區塊鏈的人而言,Solidity是一門陌生的語言。java

智能合約編寫階段將從Solidity基礎特性、高級特性、設計模式以及編程攻略分別展開,帶讀者認識Solidity並掌握其運用,更好地進行智能合約開發。git

本篇將圍繞Solidity的基礎特性,帶你們上手開發一個最基本的智能合約。github

智能合約代碼結構

任何編程語言都有其規範的代碼結構,用於表達在一個代碼文件中如何組織和編寫代碼,Solidity也同樣。web

本節,咱們將經過一個簡單的合約示例,來了解智能合約的代碼結構。編程

代碼1.png

上面這段程序包括瞭如下功能:設計模式

  • 經過構造函數來部署合約
  • 經過setValue函數設置合約狀態
  • 經過getValue函數查詢合約狀態

整個合約主要分爲如下幾個構成部分:數組

  • 狀態變量- _admin, _state,這些變量會被永久保存,也能夠被函數修改
  • 構造函數- 用於部署並初始化合約
  • 事件- SetState, 功能相似日誌,記錄了一個事件的發生
  • 修飾符- onlyAdmin, 用於給函數加一層"外衣"
  • 函數- setState, getState,用於讀寫狀態變量

下面將逐一介紹上述構成部分。網絡

 狀態變量

狀態變量是合約的骨髓,它記錄了合約的業務信息。用戶能夠經過函數來修改這些狀態變量,這些修改也會被包含到交易中;交易通過區塊鏈網絡確認後,修改即爲生效。
uint private _state;
狀態變量的聲明方式爲:[類型]  [訪問修飾符-可選] [字段名]數據結構

 構造函數

構造函數用於初始化合約,它容許用戶傳入一些基本的數據,寫入到狀態變量中。

在上述例子中,設置了_admin字段,做爲後面演示其餘功能的前提。
代碼2.png
和java不一樣的是,構造函數不支持重載,只能指定一個構造函數。

 函數

函數被用來讀寫狀態變量。對變量的修改將會被包含在交易中,經區塊鏈網絡確認後才生效。生效後,修改會被永久的保存在區塊鏈帳本中。

函數簽名定義了函數名、輸入輸出參數、訪問修飾符、自定義修飾符。
function setState(uint value) public onlyAdmin;

函數還能夠返回多個返回值:

代碼3.png

在本合約中,還有一個配備了view修飾符的函數。這個view表示了該函數不會修改任何狀態變量。

與view相似的還有修飾符pure,其代表該函數是純函數,連狀態變量都不用讀,函數的運行僅僅依賴於參數。

代碼4.png

若是在view函數中嘗試修改狀態變量,或者在pure函數中訪問狀態變量,編譯器均會報錯。

 事件

事件相似於日誌,會被記錄到區塊鏈中,客戶端能夠經過web3訂閱這些事件。

定義事件
event SetState(uint value);
構造事件
emit SetState(value);
這裏有幾點須要注意:

  • 事件的名稱能夠任意指定,不必定要和函數名掛鉤,但推薦二者掛鉤,以便清晰地表達發生的事情.
  • 構造事件時,也可不寫emit,但由於事件和函數不管是名稱仍是參數都高度相關,這樣操做很容易筆誤將事件寫成函數調用,所以不推薦。

代碼5.png

 修飾符

修飾符是合約中很是重要的一環。它掛在函數聲明上,爲函數提供一些額外的功能,例如檢查、清理等工做。

在本例中,修飾符onlyAdmin要求函數調用前,須要先檢測函數的調用者是否爲函數部署時設定的那個管理員(即合約的部署人)。

代碼6.png

值得注意的是,定義在修飾符中的下劃線「_」,表示函數的調用,指代的是開發者用修飾符修飾的函數。在本例中,表達的是setState函數調用的意思。

智能合約的運行

瞭解了上述的智能合約示例的結構,就能夠直接上手運行,運行合約的方式有多種,你們能夠任意採起其中一種:

  • 方法一:可使用FISCO BCOS控制檯的方式來部署合約,具體請參考

    https://fisco-bcos-documentat..._CN/latest/docs/installation.html#id7

  • 方法二:使用FISCO BCOS開源項目WeBASE提供的在線ide WEBASE-front運行
  • 方法三:經過在線ide remix來進行合約的部署與運行, remix的地址爲

    http://remix.ethereum.org/

本例中使用remix做爲運行示例。

 編譯

首先,在remix的文件ide中鍵入代碼後,經過編譯按鈕來編譯。成功後會在按鈕上出現一個綠色對勾:

圖片1.jpg

 部署

編譯成功後就可進行部署環節,部署成功後會出現合約實例。

圖片2.jpg

 setState

合約部署後,咱們來調用setState(4)。在執行成功後,會產生一條交易收據,裏面包含了交易的執行信息。

圖片3.jpg

在這裏,用戶能夠看到交易執行狀態(status)、交易執行人(from)、交易輸入輸出(decoded input, decoded output)、交易開銷(execution cost)以及交易日誌(logs)。

在logs中,咱們看到SetState事件被拋出,裏面的參數也記錄了事件傳入的值4。

若是咱們換一個帳戶來執行,那麼調用會失敗,由於onlyAdmin修飾符會阻止用戶調用。

圖片4.jpg

getState

調用getState後,能夠直接看到所獲得的值爲4,正好是咱們先前setState所傳入的值:

圖片5.jpg

Solidity數據類型

在前文的示例中,咱們用到了uint等數據類型。因爲Solidity類型設計比較特殊,這裏也會簡單介紹一下Solidity的數據類型。

 整型系列

Solidity提供了一組數據類型來表示整數, 包含無符號整數與有符號整數。每類整數還可根據長度細分,具體細分類型以下。

屏幕快照 2020-03-11 下午6.28.06.png

定長bytes系列

Solidity提供了bytes1到bytes32的類型,它們是固定長度的字節數組。

用戶能夠讀取定長bytes的內容。

代碼7.png

而且,能夠將整數類型轉換爲bytes。

屏幕快照 2020-03-11 下午9.24.55.png

這裏有一個關鍵細節,Solidity採起大端序編碼,高地址存的是整數的小端。例如,b[0]是低地址端,它存整數的高端,因此值爲0;取b[31]纔是1。

代碼9.png

變長bytes

從上文中,讀者可瞭解定長byte數組。此外,Solidity還提供了一個變長byte數組:bytes。使用方式相似數組,後文會有介紹。

 string

Solidity提供的string,本質是一串經UTF-8編碼的字節數組,它兼容於變長bytes類型。

目前Solidity對string的支持不佳,也沒有字符的概念。用戶能夠將string轉成bytes。

代碼10.png

要注意的是,當將string轉換成bytes時,數據內容自己不會被拷貝,如上文中,str和b變量指向的都是同一個字符串abc。

 address 

address表示帳戶地址,它由私鑰間接生成,是一個20字節的數據。一樣,它也能夠被轉換爲bytes20。

代碼11.png

 mapping

mapping表示映射, 是極其重要的數據結構。它與java中的映射存在以下幾點差異:

  • 它沒法迭代keys,由於它只保存鍵的哈希,而不保存鍵值,若是想迭代,能夠用開源的可迭代哈希類庫
  • 若是一個key未被保存在mapping中,同樣能夠正常讀取到對應value,只是value是空值(字節全爲0)。因此它也不須要put、get等操做,用戶直接去操做它便可。

代碼12.png

 數組

若是數組是狀態變量,那麼支持push等操做:

代碼13.png

數組也能夠以局部變量的方式使用,但稍有不一樣:

代碼14.png

 struct

Solidity容許開發者自定義結構對象。結構體既能夠做爲狀態變量存儲,也能夠在函數中做爲局部變量存在。

代碼15.png

本節中只介紹了比較常見的數據類型,更完整的列表可參考Solidity官方網站:

https://solidity.readthedocs....

全局變量

示例合約代碼的構造函數中,包含msg.sender。它屬於全局變量。在智能合約中,全局變量或全局方法可用於獲取和當前區塊、交易相關的一些基本信息,如塊高、塊時間、合約調用者等。

比較經常使用的全局變量是msg變量,表示調用上下文,常見的全局變量有如下幾種:

  • msg.sender:合約的直接調用者。

    因爲是直接調用者,因此當處於 用戶A->合約1->合約2 調用鏈下,若在合約2內使用msg.sender,獲得的會是合約1的地址。若是想獲取用戶A,能夠用tx.origin.

  • tx.origin:交易的"始做俑者",整個調用鏈的起點。
  • msg.calldata:包含完整的調用信息,包括函數標識、參數等。calldata的前4字節就是函數標識,與msg.sig相同。
  • msg.sig:msg.calldata的前4字節,用於標識函數。

  • block.number:表示當前所在的區塊高度。
  • now:表示當前的時間戳。也能夠用block.timestamp表示。

這裏只列出了部分常見全局變量,完整版本請參考:

https://solidity.readthedocs....

結語

本文以一個簡單的示例合約做爲引入,介紹了運用Solidity開發智能合約的基本知識。讀者能夠嘗試運行該合約,感覺智能合約的開發。

若想更深刻學習智能合約示例,推薦官方網站示例供讀者學習,也可關注本專題後續系列文章:

https://solidity.readthedocs....

在官網的示例中,提供了投票、競拍、微支付通道等多個案例,這些案例貼近實際生活,是很好的學習資料。

**

下期預告

活動預告2.jpg

FISCO BCOS的代碼徹底開源且免費

下載地址↓↓↓

https://github.com/FISCO-BCOS...

相關文章
相關標籤/搜索