如前篇介紹,目前大部分的聯盟鏈平臺,包括FISCO BCOS,都採用Solidity做爲智能合約開發語言,所以熟悉並上手Solidity十分必要。html
做爲一門面向區塊鏈平臺設計的圖靈完備的編程語言,Solidity支持函數調用、修飾符、重載、事件、繼承等多種特性,在區塊鏈社區中,擁有普遍的影響力和踊躍的社區支持。但對於剛接觸區塊鏈的人而言,Solidity是一門陌生的語言。java
智能合約編寫階段將從Solidity基礎特性、高級特性、設計模式以及編程攻略分別展開,帶讀者認識Solidity並掌握其運用,更好地進行智能合約開發。git
本篇將圍繞Solidity的基礎特性,帶你們上手開發一個最基本的智能合約。github
任何編程語言都有其規範的代碼結構,用於表達在一個代碼文件中如何組織和編寫代碼,Solidity也同樣。web
本節,咱們將經過一個簡單的合約示例,來了解智能合約的代碼結構。編程
上面這段程序包括瞭如下功能:設計模式
整個合約主要分爲如下幾個構成部分:數組
下面將逐一介紹上述構成部分。網絡
狀態變量是合約的骨髓,它記錄了合約的業務信息。用戶能夠經過函數來修改這些狀態變量,這些修改也會被包含到交易中;交易通過區塊鏈網絡確認後,修改即爲生效。uint private _state;
狀態變量的聲明方式爲:[類型] [訪問修飾符-可選] [字段名]數據結構
構造函數用於初始化合約,它容許用戶傳入一些基本的數據,寫入到狀態變量中。
在上述例子中,設置了_admin字段,做爲後面演示其餘功能的前提。
和java不一樣的是,構造函數不支持重載,只能指定一個構造函數。
函數被用來讀寫狀態變量。對變量的修改將會被包含在交易中,經區塊鏈網絡確認後才生效。生效後,修改會被永久的保存在區塊鏈帳本中。
函數簽名定義了函數名、輸入輸出參數、訪問修飾符、自定義修飾符。function setState(uint value) public onlyAdmin;
函數還能夠返回多個返回值:
在本合約中,還有一個配備了view修飾符的函數。這個view表示了該函數不會修改任何狀態變量。
與view相似的還有修飾符pure,其代表該函數是純函數,連狀態變量都不用讀,函數的運行僅僅依賴於參數。
若是在view函數中嘗試修改狀態變量,或者在pure函數中訪問狀態變量,編譯器均會報錯。
事件相似於日誌,會被記錄到區塊鏈中,客戶端能夠經過web3訂閱這些事件。
定義事件event SetState(uint value);
構造事件emit SetState(value);
這裏有幾點須要注意:
修飾符是合約中很是重要的一環。它掛在函數聲明上,爲函數提供一些額外的功能,例如檢查、清理等工做。
在本例中,修飾符onlyAdmin要求函數調用前,須要先檢測函數的調用者是否爲函數部署時設定的那個管理員(即合約的部署人)。
值得注意的是,定義在修飾符中的下劃線「_」,表示函數的調用,指代的是開發者用修飾符修飾的函數。在本例中,表達的是setState函數調用的意思。
瞭解了上述的智能合約示例的結構,就能夠直接上手運行,運行合約的方式有多種,你們能夠任意採起其中一種:
https://fisco-bcos-documentat..._CN/latest/docs/installation.html#id7
本例中使用remix做爲運行示例。
首先,在remix的文件ide中鍵入代碼後,經過編譯按鈕來編譯。成功後會在按鈕上出現一個綠色對勾:
編譯成功後就可進行部署環節,部署成功後會出現合約實例。
合約部署後,咱們來調用setState(4)。在執行成功後,會產生一條交易收據,裏面包含了交易的執行信息。
在這裏,用戶能夠看到交易執行狀態(status)、交易執行人(from)、交易輸入輸出(decoded input, decoded output)、交易開銷(execution cost)以及交易日誌(logs)。
在logs中,咱們看到SetState事件被拋出,裏面的參數也記錄了事件傳入的值4。
若是咱們換一個帳戶來執行,那麼調用會失敗,由於onlyAdmin修飾符會阻止用戶調用。
調用getState後,能夠直接看到所獲得的值爲4,正好是咱們先前setState所傳入的值:
在前文的示例中,咱們用到了uint等數據類型。因爲Solidity類型設計比較特殊,這裏也會簡單介紹一下Solidity的數據類型。
Solidity提供了一組數據類型來表示整數, 包含無符號整數與有符號整數。每類整數還可根據長度細分,具體細分類型以下。
Solidity提供了bytes1到bytes32的類型,它們是固定長度的字節數組。
用戶能夠讀取定長bytes的內容。
而且,能夠將整數類型轉換爲bytes。
這裏有一個關鍵細節,Solidity採起大端序編碼,高地址存的是整數的小端。例如,b[0]是低地址端,它存整數的高端,因此值爲0;取b[31]纔是1。
從上文中,讀者可瞭解定長byte數組。此外,Solidity還提供了一個變長byte數組:bytes。使用方式相似數組,後文會有介紹。
Solidity提供的string,本質是一串經UTF-8編碼的字節數組,它兼容於變長bytes類型。
目前Solidity對string的支持不佳,也沒有字符的概念。用戶能夠將string轉成bytes。
要注意的是,當將string轉換成bytes時,數據內容自己不會被拷貝,如上文中,str和b變量指向的都是同一個字符串abc。
address表示帳戶地址,它由私鑰間接生成,是一個20字節的數據。一樣,它也能夠被轉換爲bytes20。
mapping
mapping表示映射, 是極其重要的數據結構。它與java中的映射存在以下幾點差異:
若是數組是狀態變量,那麼支持push等操做:
數組也能夠以局部變量的方式使用,但稍有不一樣:
Solidity容許開發者自定義結構對象。結構體既能夠做爲狀態變量存儲,也能夠在函數中做爲局部變量存在。
本節中只介紹了比較常見的數據類型,更完整的列表可參考Solidity官方網站:
https://solidity.readthedocs....
示例合約代碼的構造函數中,包含msg.sender。它屬於全局變量。在智能合約中,全局變量或全局方法可用於獲取和當前區塊、交易相關的一些基本信息,如塊高、塊時間、合約調用者等。
比較經常使用的全局變量是msg變量,表示調用上下文,常見的全局變量有如下幾種:
msg.sender:合約的直接調用者。
因爲是直接調用者,因此當處於 用戶A->合約1->合約2 調用鏈下,若在合約2內使用msg.sender,獲得的會是合約1的地址。若是想獲取用戶A,能夠用tx.origin.
msg.sig:msg.calldata的前4字節,用於標識函數。
now:表示當前的時間戳。也能夠用block.timestamp表示。
這裏只列出了部分常見全局變量,完整版本請參考:
https://solidity.readthedocs....。
本文以一個簡單的示例合約做爲引入,介紹了運用Solidity開發智能合約的基本知識。讀者能夠嘗試運行該合約,感覺智能合約的開發。
若想更深刻學習智能合約示例,推薦官方網站示例供讀者學習,也可關注本專題後續系列文章:
https://solidity.readthedocs....。
在官網的示例中,提供了投票、競拍、微支付通道等多個案例,這些案例貼近實際生活,是很好的學習資料。
**
FISCO BCOS的代碼徹底開源且免費
下載地址↓↓↓