這是一篇對以太坊智能合約與 Solidity 的一些簡介,方便你們理解咱們這幾期對合約安全性分析的文章。部份內容翻譯自參考文獻[1]安全
本質上,以太坊是一個去中心化的虛擬機,在運行的過程當中,能夠按照必定順序執行合約。合約由一組供用戶調用的函數構成,好比說,一個標準的 ERC 20 合約應當實現如下六個函數。微信
當一個用戶想將本身的 ERC 20 token 轉給其餘地址的時候,能夠發起一筆交易來調用 transfer
函數,讓以太坊執行合約中 transfer
函數對應的代碼,從而完成轉帳。ide
在以太坊中,用戶能夠經過發起交易實現 3 個功能:函數
建立新的智能合約區塊鏈
執行合約中的函數ui
轉帳 ether翻譯
交易由礦工打包進區塊,全部區塊構成了一個鏈。這樣全部的交易就有了一個執行的順序,基於這個順序,也能夠定出每一個時刻的合約狀態和交易餘額。code
在以太坊中,合約以字節碼的形式發佈到區塊鏈上,並在 EVM (Ethereum Virutal Machine) 中執行。在用戶開發的時候,不須要直接編寫字節碼。以太坊社區提供了一套叫作 Solidity 的語言。一個由 Solidity 開發合約的代碼以下圖所示。orm
在合約的前兩行,定義了一個變量和一個字典映射。在每次合約被執行的時候,這兩個變量均可能被修改。當下一次合約被執行的時候,若是讀取了這兩個變量,獲得的將是修改後的內容。cdn
合約的第一個函數 AWallet
與合約名相同,是這個合約的構造函數。當這個合約在區塊鏈上被創造的時候,構造函數被執行,通常用於初始化合約中的一些變量。
在 Solidity 代碼中,能夠經過 msg.sender
和 msg.value
兩個變量獲取:1. 觸發本次合約執行的交易是誰發的,2. 觸發本次合約執行的交易向合約裏轉入了多少 ether。基於這兩個變量,能夠實現合約操做的權限管理,也能夠實現將一些數字資產由用戶私鑰控制轉爲合約執行控制。
Solidity 容許異常的存在,例如函數 pay
的第一行,若是調用這個函數的地址與建立合約的地址不一致,則意味着調用合約的人沒有動用合約裏資產的權限,那麼就經過 throw
觸發了一個異常。當異常被觸發時,沒有任何捕獲(catch)的方式,直接中止合約的執行,回滾狀態,並扣除所有的交易費用。
對於類型爲 address
的變量 r
, r.send(amount)
表示由合約向地址 v
發送數額爲 amount
的 wei. (10^18 wei = 1 ether )
最後一個沒有函數名的函數 function () 稱爲回退(fallback)函數,是智能合約中一個特殊的函數。由於 EVM 的字節碼中並無對函數的支持,因此,Solidity 在將代碼編譯成字節碼後,字節碼的第一部分即是函數匹配。用戶經過指定要調用函數的函數名和參數類型的哈希值的前四個字節來告訴 EVM 執行哪一個函數。例如 byte4(sha3("pay(uint,address)"))
,這四個字節被稱爲函數簽名。若是用戶調用時使用的函數簽名匹配到了一個函數,則執行這個函數。若是沒有匹配到任何函數,回退函數將做爲 default 選項被執行。
在以太坊中,每次合約函數的調用須要被全部的礦工執行。交易中的交易費能夠激勵礦工們作這件事情,同時保護以太坊合約執行上免受 DoS 攻擊(攻擊者提交大量計算機很大的合約)。
執行交易費由燃料用量(gas used)和燃料費(gas price)決定。燃料用量由合約執行過程當中執行了的操做計算,EVM 虛擬機的每個字節碼指令都標註了燃料用量。燃料費是用戶的出價,更高的燃料費意味着交易能夠更早被加入區塊。燃料用量乘燃料費就是合約執行的交易費。
同時,每筆交易要指定燃料用量上限(gas limit)。燃料用量上限乘以燃料費是預付款。交易發起時要保證帳戶餘額中有足夠的錢支付預付款。當燃料用到上限時,若是尚未執行結束,將判斷爲執行失敗,回滾全部操做,並沒收預付款。若是合約執行成功,預付款中未使用的部分會被退回。
參考文獻: [1] Atzei, Nicola, Massimo Bartoletti, and Tiziana Cimoli. "A survey of attacks on ethereum smart contracts (sok)." Principles of Security and Trust. Springer, Berlin, Heidelberg, 2017. 164-186.
歡迎關注咱們的微信公衆號:Conflux中文社區(Conflux-Chain)
添加微信羣管理員 Confluxgroup 回覆「加羣」加入 Conflux官方交流羣