以太坊不只是一種加密數字貨幣,它更是功能完備的智能合約平臺,solidity就是用來開發以太坊上的智能合約的原生開發語言。solidity最先發佈於2015年,它是第一種圖靈完備的智能合約專用開發語言。目前除了以太坊以外,在其餘區塊鏈中也逐漸開始支持solidity,例如hyperledger fabric、tendermint等。在這個solidity快速教程中,咱們將使用最新0.5.7版的solidity,以一個具體的案例來介紹solidity智能合約的開發、部署與交互,但願對你快速掌握solidity智能合約的開發有所幫助。php
若是要高效系統地掌握以太坊智能合約與DApp的開發,推薦訪問匯智網的在線互動課程:以太坊開發入門 | java以太坊 | python以太坊 | php以太坊 | C#以太坊 | 電商DApp實戰 | ERC721通證明戰java
有一個老爺爺,在生命的最後歲月別無他求,只是但願本身的財產可以經過遺囑順利地傳給其餘家庭成員。python
在傳統的遺囑中,遺產分配方案是落實在法律文件上的,而後當真正開始分配時,法官須要重審文件並作出相應的決定。常見的問題發生在家庭成員之間對分配比例的爭執上,甚至所以而致使家庭成員關係的破裂。在法庭聽證階段,這些都會影響法官最終的裁決,並所以可能致使不公平的結果,甚至對家庭關係形成進一步的傷害。數組
那麼,若是咱們可讓遺產分配自動進行,是否能夠避免上述狀況的發生?安全
若是遺產是一個智能合約,那麼就不須要法官了。老爺爺能夠自主地利用合約管理資產,而後在他去世後由程序來分配遺產給家庭成員。合約裏的代碼就決定了最終的分配結果,所以無需法官的介入。例如薩拉分$10000,本獲得$5000,朱麗葉獲得$2000。代碼執行後,資產以代幣或加密貨幣的形式自動分配給這些家庭成員,而無需人工介入。雖然不能保證每一個成員都對遺產的分配結果滿意,可是沒有人會和代碼爭執。這聽起來還比較可行,對嗎?數據結構
記住這個案例,在這個快速教程中,咱們將使用solidity,爲老爺爺開發一個簡單的遺囑合約,來知足他最後的願望。框架
開發solidity智能合約最簡單的方法,就是使用官方提供的在線集成開發環境REMIX,你能夠點擊這裏打開remix,在網頁裏就完成solidity智能合約的編寫、編譯與部署:ide
在你打開remix頁面後,注意在右側的run
選項頁,environment
下拉框中,要選中JavaScript VM
。這個選項的意思是使用一個內存仿真以太坊節點做爲你的solidity智能合約的運行平臺,這樣就不用考慮與實際的以太坊主網交互所須要的帳號、資金、計算費用等問題,而能夠先把精力聚焦在學習如何使用solidity表達你的業務邏輯上。函數
點擊remix頁面左上方的+
圖標,就能夠建立一個新的代碼文件,咱們將其命名爲will.sol。在remix頁面中間的編輯區域能夠同時顯示多個文件,當前正在編輯的文件,則以活動選項頁的形式顯示文件名稱。學習
solidity仍是很早期階段的語言,從語法到編譯器都在不斷地演化,因此在solidity代碼的第一行,必定要用pragma關鍵字聲明這個文件中的solidity代碼須要哪一個版本的編譯器。例如:
注意在solidity中,末尾的分號不可省略。
接下來就能夠定義咱們的第一個合約:
使用contract關鍵字來定義一個合約,solidity的合約相似於咱們熟悉的OOP中的類,所以一般合約的名稱首字母也會大寫,例如Will
。一對大括號用來定義合約的實現邏輯,單行註釋也使用//
,這和不少開發語言都相似。
在咱們開始寫代碼以前,應當首先明確遺囑的條款。假設老爺爺的遺產是50個以太幣,其中20個留給他的兒子康萊德,剩下的30個留給他的妻子麗莎。在真實的環境中,當老爺爺去世後,應當有一個外部的程序將調用合約中定義的方法來分配遺產,可是咱們爲了便於學習將本身完成這個調用。
如今,讓咱們先完成以下代碼:
第5行代碼定義了合約的全部者。當咱們在solidity中定義變量時,必須先聲明其類型。address
是solidity中一種特殊的類型,它表示一個以太坊地址。address
類型的變量有一些特殊的方法,咱們在後面會進一步瞭解。
第6行代碼定義的fortune變量用來保存老爺爺的遺產數量,它的類型是uint
或unsigned int
,意思是這個變量是0或正整數。solidity中有不少數據類型,但咱們不會在這裏一一介紹,你能夠在官方文檔中深刻了解solidity的數據類型。
第7行代碼定義的isDeceased變量用來標識老爺爺是否已經去世,這是一個開關量,所以其類型爲boolean
,可能的值只有兩個:true或false,默認值爲false。
第9~13行代碼是合約的構造函數,這個特殊的函數將在合約部署的時候自動執行。
public
關鍵字被稱爲可見性修飾符,它的做用是聲明被修飾的方法是否容許外部調用。public
意味着在合約內部或外部(由其餘合約或其餘人)均可以調用該方法。
payable
關鍵字是solidity的特點之一,它使得被修飾的方法能夠發送或接收以太幣。爲構造函數聲明payable
關鍵字意味着當咱們部署合約的時候,能夠直接向合約存入以太幣,例如,做爲遺產的50個以太幣。當合約接收到以太幣後,這些幣就保存在合約地址上了。
在構造函數內部,咱們將owner
變量的值設置爲msg.sender
,這是一個以太坊平臺預置的全局變量,表示調用合約方法的帳號地址,在咱們的案例中,這的地址是老爺爺的。
同時咱們將fortune
變量的值設置爲msg.value
,這是另外一個全局變量,它表示被調用的方法接收到的以太幣的數量。
雖然變量isDeceased
被自動初始化爲默認值false,但爲了清晰起見,咱們將其顯式地設置爲false。
在solidity中,修飾符(Modifier)能夠爲函數附加額外的條件邏輯。例如,假設我有一個用來關燈的方法,同時有一個修飾符要求燈開關必須處於on狀態,那麼
咱們就能夠在方法上附加聲明這個修飾符,以便確保只有在燈開關處於on狀態時,才能夠調用這個方法,不然就拋出異常。
第15行代碼定義了onlyOwner
修飾符。若是一個方法附加聲明瞭這個修飾符,那麼就要求調用方法的帳號(msg.sender)必須與owner
變量的值一致(別忘了咱們在構造函數中設置了owner的值)。這個調用條件有助於遺產的分配,咱們將在後面看到這一點。
require
關鍵字的意思是,括號裏的表達式的值必須爲真(true),不然就會拋出異常,再也不繼續執行代碼。
_;
起到佔位符的做用,在執行過程當中,以太坊虛擬機會用被修飾的方法代碼來替換它。
第20行代碼定義了mustBeDeceased
修飾符。若是一個方法附加聲明瞭這個修飾符,那麼就只有在isDeceased
變量值爲true時,才能夠調用該方法,不然就拋出異常。
在上面的代碼中,咱們使用修飾符來限定方法的執行條件,固然也能夠不使用修飾符,而直接在方法實現代碼中使用require
,不過修飾符看起來更高級一些,也更容易實現代碼的複用。
如今咱們要繼續完成遺產在家庭成員之間的分配任務,這須要他們的錢包地址和分配數量。
正如咱們以前所述,康萊德將收到20個以太幣而麗莎將繼承30個。讓咱們建立一個數組來保存他們的錢包地址,而後寫一個方法來分配遺產。
第25行代碼定義了一個空數組familyWallets
,用來保存全部家庭成員的錢包地址。和其餘語言同樣,在solidity中數組是順序存放而且可使用序號來存取。注意方括號以前的關鍵字paybale
,只有address payable
類型的變量,才能夠接收以太幣,這是0.5版本的solidity與以前版本的區別之一。
第27行代碼建立了一個從address
類型到uint
類型的映射表變量inheritance
,用來保存每一個錢包地址的遺產數量。這是一個鍵/值對數據結構,相似於其餘語言中的字典或哈希表,能夠用鍵來存取值。
第29行代碼定義了一個方法,它的功能是將一個錢包地址添加到familyWallets
數組,而後設置該地址在inheritance
映射表中的遺產數量。注意附加的onlyOwner
修飾符,猜一下爲何咱們要在這裏聲明這個修飾符?
第30行代碼將傳入方法的錢包地址追加到familyWallets
數組的末尾。
第31行代碼將傳入方法的遺產繼承數量設置爲映射表inheritance
的指定地址(傳入方法的另外一個參數)的值。
讓咱們總結一下。到目前爲止,咱們已經學習了全局變量、數據類型、構造函數、特殊的關鍵字例如payable
和public
、內置的全局變量例如msg.sender
和msg.value
、修飾符和require
、數組、映射表和方法。咱們已經搭好了合約的框架,如今讓咱們把各部分整合起來最終完成合約。
做爲這個教程最後一部分的代碼,咱們將實現家庭成員遺產的自動分配。
第34行定義了payout()
方法,注意private
關鍵字,這個可視性修飾符是public
的反義詞,它只容許被修飾的方法在合約內部調用,就像在第42行的代碼那樣。之因此在這裏使用private
,主要是考慮到安全性,由於咱們不但願任何來自合約外部的調用。注意最後的mustBeDeceased
修飾符,目前咱們依然不能知足這個修飾符要求的條件來執行payout()
方法。
第35行代碼是一個for
循環,用來遍歷familyWallets
數組。語法以下:
第36行代碼是整個合約的核心,咱們調用address
類型的地址對象的transfer()
方法,向該地址轉帳預約的遺產繼承數量,inheritance[familyWallets[i]]
表示在inheritance
映射表中,鍵familyWallets[i]
的值,也就是第i個家庭成員的遺產繼承數量。
第40~42行代碼定義了一個方法,當老爺爺去世後將調用這個方法來觸發遺產的分配。在這裏咱們將變量isDeceased
的值設置爲true。
如今咱們完成了嗎?
實際上,還不徹底是...
這個智能合約的代碼是寫完了,可是咱們怎麼用它?如今是收穫果實的時候了。
你的remix頁面看起來應該像這樣:
在remix頁面右邊切換到compile
選項頁,確認按下圖選中編譯器的版本,而後點擊[start to compile]:
你可能會看到靜態分析生成的一個藍色文本框,咱們暫時忽略它的提醒,切換到run
選項頁:
確保Environment
下拉框中選中了Javascript VM
,點擊account
的下拉菜單將顯示5個測試帳戶,每一個帳戶都有100個以太幣,讓咱們選擇第一個。
向以太坊區塊鏈部署合約並非免費的,部署者須要支付手續費,一般被稱爲gas。引入這一機制的目的是避免區塊鏈計算資源被惡意濫用,要進一步瞭解gas,能夠查看這篇文章:1分鐘搞清Gas/ Gas Price/ Gas Limit。
gas limit
字段使用默認值就能夠了,咱們先不修改它。
value
字段表示咱們在部署合約時要發送給合約的以太幣數量。輸入50,還記得咱們在定義構造函數時附加的payable
關鍵字嗎?
如今繼續,點擊[deploy]。
你可能馬上會注意到3件事。首先,選中的帳戶餘額如今變成了49.9999… ,這是由於咱們轉給合約50個以太幣,還要扣除一點部署手續費。頁面底部的控制檯也會提供關於部署過程的詳細信息,你能夠查看一下。如今看起來是這樣:
咱們的合約已經成功部署了!它生成了本身的地址,而且顯示出咱們定義的兩個合約方法。做爲合約的持有者,咱們要作的第一件事,是設置家庭成員的繼承數量:康萊德(20)、麗莎(30)。假設咱們用account
下拉菜單中的第二個做爲康萊德的帳號,麗莎的用第三個。
選擇第二個帳號,點擊[拷貝到剪切板]圖標,而後輸入上圖中的setInheritance
後面的文本輸入框。
在咱們執行setInheritance
方法以前,有幾件事情要記住。
傳入合約的以太幣數量的單位是wei而不是以太幣,1 ETH = 1,000,000,000,000,000,000 WEI,這是很是小的單位,所以咱們須要將以太幣表示的遺產數量先轉換爲以WEI爲單位的值。
在將遺產數量換算後,在將其寫入上圖中的setInheritance
後面的文本輸入框中,以前輸入的地址後面,這兩個值之間注意要用逗號隔開。
還有,別忘了在account
下拉框選中第一個帳號,還記得onlyOwner
修飾符嗎?只有合約的持有人才能夠調用setInheritance
方法!
如今讓咱們依次爲康萊德和麗莎執行setInheritance方法。你應當能夠看到控制檯輸出的成功信息。看一下其中的decoded input
:
你看,它顯示的就是咱們輸入的數據。
遺產分配好了,可是壞消息來了。老爺爺在73歲時,在一次北極探險中不幸因心臟病突發去世。他老是這麼充滿激情與活力。
當咱們記念這位老爺爺的同時,咱們同時調用遺囑合約的deceased()
方法,完成老爺爺的最後的願望。。。
匯智網翻譯整理,轉載請標明出處