智慧合約基礎語言(二)——Solidity原始檔佈局和合約結構
1
目錄
1.1 常見的內建函式
1、pragma版本雜注
2、註釋
3、匯入原始檔
1.2 合約結構
1、狀態變數
2、函式
3、函式修改器
4、事件
5、結構體
6、列舉
7、常量
8、控制結構
9、對映
1.3 錯誤處理
1、assert
2、require
2
Solidity原始檔的佈局
——pragma(版本雜注)
說明:
1、版本要高於0.4.24才可以編譯;
2、高於0.5的版本則不可編譯;
3、第三位的版本號可以變,留出來用做bug可以修復(如0.4.1的編譯器有bug,可在0.4.2修復,現有合約不用改程式碼)。
♦原始檔應該使用pragma進行註釋,防止由於編譯器升級導致的不相容問題。
♦原始檔可以使用大版本號相同,小版本號高於當前版本的編譯器進行編譯。
3
Solidity原始檔的佈局——註釋
3.1 單行註釋(//)
3.2 多行註釋(/*...*/)
3.3 natspace註釋
natspec 註釋,它們是用三個反斜槓(///)或雙星號開頭的塊(/** ... */)書寫,它們應該直接在函式宣告或語句上使用。
注意:
natspec註釋在編譯過程中會被解析。可以不會使用,但是一定要認識,如果使用,一定要保證引數名與函式一致
4
Solidity原始檔的佈局
——import匯入其他原始檔
♦在全域性層面上匯入變數和函式,語句將從“filename”中匯入所有的全域性符號到當前全域性作用域中。
♦建立一個新的全域性符號 symbolName,其成員均來自 "filename" 中全域性符號。
♦建立新的全域性符號 alias 和 symbol2,分別從 "filename" 引用 symbol1 和 symbol2 。
♦這條語句等同於 import * as symbolName from "filename";
♦關於路徑
引入檔案路徑時要注意,非.打頭的路徑會被認為是絕對路徑,所以要引用同目錄下的檔案使用。
5
編譯器解析引用檔案機制
各編譯器提供了檔案字首對映機制。
1、可以將一個域名下的檔案對映到本地,從而從本地的某個檔案中讀取;
2、提供對同一實現的不同版本的支援(可能某版本的實現前後不相容,需要區分);
3、如果字首相同,取最長;
4、有一個”fallback-remapping”機制,空串會對映到“/usr/local/include/solidify”。
6
import匯入其他原始檔——例項
注意:
1、匯入其他原始檔相當於把多個原始檔寫到一個原始檔中;
2、檔名始終被視為具有/作為目錄分隔符的路徑
♦./作為當前目錄
♦../作為父目錄(如果沒有/ ,則不認為是當前目錄或者父目錄)
3、如果不明確指定當前目錄或者父級目錄,引用將從檔案系統根目錄開始尋找匯入檔案,這將導致實際匯入的檔案與目標檔案不同(名字相同內容不同)。
7
合約結構
在 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;
♦向外部合約發起呼叫。
注意:
不是所有的型別都支援常量,當前支援的僅有值型別和字串。
8
控制結構
和其它程式語言一樣, 程式設計中不但需要變數常量儲存值, 而且需要編寫邏輯, 那麼邏輯部分就是由這些控制結構負責的:
1、支援:if,else,while,do,for,break,continue,return,二元表示式;
2、不支援:switch和goto;
3、條件判斷中的括號不可省略,但在單行語句中的大括號可以省略。 if(true) do('something');
4、需要注意的是,這裡沒有像C語言,和javascript裡的非Boolean型別的自動轉換,比如if(1){...}在Solidity中是無效的。
9
對映
solidity裡的對映可以理解為python裡的字典,建立鍵-值的對應關係,可以通過鍵來查詢值,鍵必須是唯一的,但值可以重複。
定義方式為:mapping(鍵型別=>值型別),例如
這個對映的名字是balances,許可權型別為public,鍵的型別是地址address,值的型別是整型uint,在solidity中這個對映的作用一般是通過地址查詢餘額。鍵的型別允許除對映外的所有型別。 比如記錄一個地址裡有1000個eth。
10
錯誤處理
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關鍵字已被棄用,將來會被淘汰。) 當子呼叫中發生異常時,異常會自動向上“冒泡”。 所謂冒泡就是從當前函式呼叫逐層向外觸發異常。
本文完,獲取更多資訊,敬請關注區塊鏈工程師。
來源:鏈塊學院
本文由布洛克專欄作者釋出,代表作者觀點,版權歸作者所有,不代表布洛克科技觀點
——TheEnd——
關注“布洛克科技”