【鏈塊技術38期】智能合約基礎語言(二)——Solidity源文件佈局和合約結構

 

原文鏈接:【智能合約基礎語言02期】Solidity源文件佈局和合約結構

 

一、目錄

1.1 常見的內置函數

1、pragma版本雜注

2、註釋

3、導入源文件

1.2 合約結構

1、狀態變量

2、函數

3、函數修改器

4、事件

5、結構體

6、枚舉

7、常量

8、控制結構

9、映射

1.3 錯誤處理

1、assert

2、require

二、Solidity源文件的佈局——pragma(版本雜注)

說明:

1、版本要高於0.4.24纔可以編譯;

2、高於0.5的版本則不可編譯;

3、第三位的版本號可以變,留出來用做bug可以修復(如0.4.1的編譯器有bug,可在0.4.2修復,現有合約不用改代碼)。

▶源文件應該使用pragma進行註釋,防止由於編譯器升級導致的不兼容問題。

▶源文件可以使用大版本號相同,小版本號高於當前版本的編譯器進行編譯。

三、Solidity源文件的佈局——註釋

3.1 單行註釋(//)

3.2 多行註釋(/*...*/)

3.3 natspace註釋

natspec 註釋,它們是用三個反斜槓(///)或雙星號開頭的塊(/** ... */)書寫,它們應該直接在函數聲明或語句上使用。

注意:

natspec註釋在編譯過程中會被解析。可以不會使用,但是一定要認識,如果使用,一定要保證參數名與函數一致

四、Solidity源文件的佈局——import導入其他源文件

▶在全局層面上導入變量和函數,語句將從“filename”中導入所有的全局符號到當前全局作用域中。

▶創建一個新的全局符號 symbolName,其成員均來自 "filename" 中全局符號。

▶創建新的全局符號 alias 和 symbol2,分別從 "filename" 引用 symbol1 和 symbol2 。

▶這條語句等同於 import * as symbolName from "filename";

▶關於路徑

引入文件路徑時要注意,非.打頭的路徑會被認爲是絕對路徑,所以要引用同目錄下的文件使用。

五、編譯器解析引用文件機制

各編譯器提供了文件前綴映射機制。

1、可以將一個域名下的文件映射到本地,從而從本地的某個文件中讀取;

2、提供對同一實現的不同版本的支持(可能某版本的實現前後不兼容,需要區分);

3、如果前綴相同,取最長;

4、有一個”fallback-remapping”機制,空串會映射到“/usr/local/include/solidify”。

六、import導入其他源文件——實例

注意:

1、導入其他源文件相當於把多個源文件寫到一個源文件中;

2、文件名始終被視爲具有/作爲目錄分隔符的路徑

▶./作爲當前目錄

▶../作爲父目錄(如果沒有/ ,則不認爲是當前目錄或者父目錄)

3、如果不明確指定當前目錄或者父級目錄,引用將從文件系統根目錄開始尋找導入文件,這將導致實際導入的文件與目標文件不同(名字相同內容不同)。

七、合約結構

在 Solidity 中,合約類似於面向對象編程語言中的類。 每個合約中可以包含:

▶狀態變量(State Variables)

▶函數(Functions)

▶函數修改器(Function Modifiers)

▶事件(Events)

▶結構體(Structs)

▶枚舉(Enum )

(這幾個內容本章只是簡單介紹一下概念,後續章節會詳細講解。)

7.1 狀態變量

狀態變量——永久地存儲在合約存儲中的值。

7.2 函數

函數——合約中代碼的可執行單元。

7.3 函數修改器

函數修改器——用來以聲明的方式改良函數語義。

7.4 事件

事件——以太坊虛擬機日誌工具的方便接口。

7.5 結構體

結構體——可以將幾個變量分組的自定義類型(自定義複雜變量的模板)。

7.6 枚舉

枚舉——枚舉可用來創建有一定數量的值的自定義類型。

7.7 常量

狀態變量可以被定義爲constant,常量。這樣的話,它必須在編譯期間通過一個表達式賦值。賦值的表達式不允許:

▶訪問storage;

▶區塊鏈數據,如now,this.balance,block.number;

▶合約執行的中間數據,如msg.gas;

▶向外部合約發起調用。

注意:

不是所有的類型都支持常量,當前支持的僅有值類型和字符串。

八、控制結構

和其它程序語言一樣, 編程中不但需要變量常量存儲值, 而且需要編寫邏輯, 那麼邏輯部分就是由這些控制結構負責的:

1、支持:if,else,while,do,for,break,continue,return,二元表達式;

2、不支持:switch和goto;

3、條件判斷中的括號不可省略,但在單行語句中的大括號可以省略。 if(true) do('something');

4、需要注意的是,這裏沒有像C語言,和javascript裏的非Boolean類型的自動轉換,比如if(1){...}在Solidity中是無效的。

九、映射

solidity裏的映射可以理解爲python裏的字典,建立鍵-值的對應關係,可以通過鍵來查找值,鍵必須是唯一的,但值可以重複。

定義方式爲:mapping(鍵類型=>值類型),例如

這個映射的名字是balances,權限類型爲public,鍵的類型是地址address,值的類型是整型uint,在solidity中這個映射的作用一般是通過地址查詢餘額。鍵的類型允許除映射外的所有類型。 比如記錄一個地址裏有1000個eth。

十、錯誤處理

10.1 概述

錯誤處理是指程序發生錯誤時的處理方式,Solidity處理錯誤和我們常見的語言不一樣,它是通過回退狀態的方式處理錯誤,在發生異常時會撤銷當前調用(及其所有子調用)所改變的狀態,同時給調用者返回一個錯誤標識。(沒有try catch 不可能捕獲異常)。

10.2 assert()

assert(bool condition)用於判斷內部錯誤,條件不滿足時拋出異常。

特點:注意會消耗掉全部的gas

在下述場景中自動產生assert類型的異常:

▶數組下標越界或者小於0

▶被除數爲0, 如5/0 或 23 % 0

▶對一個二進制移動一個負的值。如:5<<i; i爲-1時

▶整數進行顯式轉換爲枚舉時,過大值、負值

▶調用未初始化內部函數

▶調用assert的參數爲false

10.3 require()

require(boolcondition):用於判斷輸入或外部組件錯誤,條件不滿足時拋出異常。

特點:不會消耗gas

在下述場景中自動產生require類型的異常:

▶調用throw;

▶調用require的參數爲false;

▶調用外部函數調用時,被調用的對象不包含代碼;

▶合約沒有payable修飾符的public的函數在接收- - 以太幣時(包括構造函數,和回退函數);

▶合約通過一個public的getter函數(public getter funciton)接收以太幣;

▶transfer()執行失敗。

範例:

10.4 其他異常處理方式

除了可以兩個函數assert和require來進行條件檢查,另外還有兩種方式來觸發異常:

revert()、revert(string reason)函數可以用來標記錯誤,終止執行並回退當前調用。

使用throw關鍵字拋出異常(從0.4.13版本,throw關鍵字已被棄用,將來會被淘汰。) 當子調用中發生異常時,異常會自動向上“冒泡”。 所謂冒泡就是從當前函數調用逐層向外觸發異常。

 

本文完,獲取更多資訊,敬請關注區塊鏈工程師。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章