聊聊以太坊智能合約的結構?
知道智能合約的結構後,寫起合約來才得心應手,我們將分兩個角度討論,一個是從Solidity合約文件結構上看,一個是從合約內容上看。
Solidity 文件結構
Solidity合約源文件使用的擴展名為.sol,從文件結構上看,一個合約文件,通常包含以下幾個部分:合約版本申明、引入其他源文件、定義一個合約及注釋。
?
版本申明
Solidity的源文件需要進行一個版本聲明,告知編譯器此源文件所支持的編譯器版本,當出現不兼容的新的編譯器版本時,它會拒絕編譯老的源文件。
常常閱讀版本更新日誌是一個好習慣,尤其當大版本發布時。
版本申明方式如下:
pragma solidity ^0.4.0;
這樣一個源文件不兼容0.4.0之前的版本,以及不兼容0.5.0之後的版本(符號用來控制版本號的第2部分)。
通常版本號第3部分的升級僅僅一些小變化(不會有任何兼容性問題),所有通常使用這種方式,而不是指定特定的版本,這樣當編譯器有bug修復時,不需要更改代碼。
如果要使用更複雜的版本聲明,其聲明表達式和npm保持了一致,可以參考:https://docs.npmjs.com/misc/semver
引入其他源文件
Solidity 支持import語句,非常類似於JavaScript(ES6),雖然Solidity沒有「預設導出」的概念。
1. 全局引入
引入形式如下:
import "filename";
將會從"filename"導入所有的全局符號(包括filename從其他文件導入的),導入到當前的全局作用域。
自定義命名空間引入 引入形式如下:
import * as symbolName from "filename";
創建了一個全局的命名空間 symbolName,成員來自filename的全局符號。
有一種非es6兼容的簡寫語法與其等價:
import "filename" as symbolName;
分別定義引入 引入形式如下:
import from "filename";
將創建一個新的全局變數別名:alias 和 symbol2, 它們將分別從filename引入symbol1 和 symbol2。
定義一個合約
合約的定義和類相似,一個合約需要包含哪些內容,將在下一節詳細講。
代碼注釋
有兩種注釋方式,單行注釋使用//,多行注釋使用/…/
示例:
// this is a single-line comment/*
this is a
mulit-line comment
*/
此外還有一種稱為文檔注釋(natspec comment),使用/// 或/** ... */, 通常用於函數或語句上方,在注釋中可以使用Doxygen風格的標籤(tags)來說明函數作用、參數驗證的註解,同時支持文檔的生成。
示例:
pragma solidity ^0.4.0;
/** @title Shape calculator. */contract shapeCalculator {
/** @dev Calculates a rectangle"s surface and perimeter.
* @param w Width of the rectangle.
* @param h Height of the rectangle.
* @return s The calculated surface.
* @return p The calculated perimeter.
*/
function rectangle(uint w, uint h) returns (uint s, uint p) {
s = w * h;
p = 2 * (w + h);
}
}
合約結構
Solidity的合約和面向對象語言中的類的定義很相似,每個合約可以包含 狀態變數,函數,函數修飾符,事件,結構類型 和 枚舉類型。另外,合約也支持繼承。
狀態變數(State Variables)
狀態變數和其他語言中類的成員變數很相似,狀態變數會永久存儲在合約的存儲空間里。
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // 這是一個狀態變數
// ...}
函數(Functions)
函數是合約中可執行代碼單元,下面是一個函數例子:
pragma solidity ^0.4.0;
contract SimpleAuction { function bid() public payable { // 這是一個函數
// ...
}
}
函數修飾器(Function Modifiers)
函數修飾器可以以聲明的方式中補充函數的語義。
pragma solidity ^0.4.11;
contract Purchase {
address public seller; modifier onlySeller() { // 聲明了一個修飾器
require(msg.sender == seller);
_;
} function abort() public onlySeller { // 修飾器的使用
// ...
}
}
事件 (Events)
事件是以太坊虛擬機(EVM)日誌基礎設施提供的一個便利介面。用於獲取當前發生的事件。
pragma solidity ^0.4.0;
contract SimpleAuction { event HighestBidIncreased(address bidder, uint amount); // 定義事件
function bid() public payable { // ...
emit HighestBidIncreased(msg.sender, msg.value); // 觸發事件
}
}
結構類型(Struct Types)
結構類型是一組用戶定義的變數組合在一起形成的類型。
pragma solidity ^0.4.0;
contract Ballot { struct Voter { // 結構類型
uint weight; bool voted;
address delegate; uint vote;
}
}
枚舉類型(Enum Types)
枚舉類型是用戶創建的包含幾個特定值的集合的自定義類型。
pragma solidity ^0.4.0;
contract Purchase { enum State { Created, Locked, Inactive } // Enum}
作者熊麗兵(Tiny熊),專註於區塊鏈底層研究和以太坊開發.是圓方圓區塊鏈的導師,更多熊老師的文章和視頻請關注圓方圓鏈圈公眾號。
TAG:圓方圓鏈圈 |