原文鏈接:【智能合約基礎語言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關鍵字已被棄用,將來會被淘汰。) 當子調用中發生異常時,異常會自動向上“冒泡”。 所謂冒泡就是從當前函數調用逐層向外觸發異常。
本文完,獲取更多資訊,敬請關注區塊鏈工程師。