以太坊智能合约简介(Solidity)
本文會通過兩個示例來簡單介紹智能合約
示例一:存儲(Storage)
下面這段代碼實現了一個uint值的存儲。
pragma solidity ^0.4.0;contract SimpleStorage {uint storedData;function set(uint x) public {storedData = x;}function get() public constant returns (uint) {return storedData;} }在某種意義上,Solidity合約就是在以太坊區塊鏈中特定地址內的一組代碼(合約的函數)和數據(合約的state)的集合。
uint?storedData;
這一行聲明了一個uint(256bit的無符號整數)類型的state變量:storedData。你可以認為storedData是數據庫中的一個存儲單元,它可以被通過執行數據庫管理代碼的方式查詢和修改。在以太坊中只有合約的所有者能這樣做。示例代碼中,set、get函數可以被用于修改或檢索變量的值
獲取state對象,不需要像其他語言那樣加this.前綴
由于此合約僅存儲了一個完全公開的數字,所以它的發布是無法被阻止的。但任何人都可以通過以另一參數調用set來覆蓋你剛剛保存的數字(但你寫過的那個數字仍會被保存在區塊鏈歷史中)。稍后,你將看到如何設置限制以確保只有你自己可以修改這個變量的值
注意,所有標識符(如合約名,變量名,函數名等)只能使用ascii字符集。UTF-8編碼的數據可以存儲在字符串變量中
使用與其他字符相似的Unicode字符時需要保持小心
?
示例二:子貨幣(Subcurrency)
下面的合約將會實現一種最簡單的加密貨幣。這里定義的貨幣可以憑空產生,但只有創建合約的人才有能力憑空生成貨幣(實現一個不同的發幣計劃是件微不足道的小事)。 此外,任何人都可以互相發送貨幣而不需要使用用戶名和密碼進行注冊——進行所有的一切,只需要一個以太坊密鑰對。
pragma solidity ^0.4.21;contract Coin {// The keyword "public" makes those variables// readable from outside.address public minter;mapping (address => uint) public balances;// Events allow light clients to react on// changes efficiently.event Sent(address from, address to, uint amount);// This is the constructor whose code is// run only when the contract is created.function Coin() public {minter = msg.sender;}function mint(address receiver, uint amount) public {if (msg.sender != minter) return;balances[receiver] += amount;}function send(address receiver, uint amount) public {if (balances[msg.sender] < amount) return;balances[msg.sender] -= amount;balances[receiver] += amount;emit Sent(msg.sender, receiver, amount);} }這段合約帶來了一些新的概念,以下將一一介紹
?
address?public?minter;聲明了一個address類型的state變量,這個變量是所有人都可以讀取的。address類型是一個不允許進行任何算術操作的160位值。它很適合被用來存儲合約地址或屬于外部個人的密鑰對。關鍵字public會自動生成一個允許你從合約外部獲取一個state變量當前值的函數。若沒有這個關鍵字,其他合約將無法獲取到這個變量。由編譯器生成的代碼和下面這行代碼大致相同
function minter() returns (address) { return minter; }(直接加上這句會導致編譯器報錯,因為此函數和state變量重名)
下一行:mapping?(address?=>?uint)?public?balances;
這句話創建了一個數據類型更加復雜的公共state變量——一個從地址到無符號整型的映射。此處的映射可以被看做一個虛擬初始化了的hash表,以便每個可能的密鑰存在,并映射到一個字節表示全是0的值上(這個比喻不太合理,因為包含一個有映射的所有鍵的列表是不可能的,包含所有值也是不可能的)。因此要么保存添加到映射中的內容,要么在不需要這種內容的部分使用它(就像這句)。由public關鍵字創建的getter函數【注1】在這種情況下更加復雜一些。看起來大概是這樣的:
function balances(address _account) public view returns (uint) {return balances[_account]; }用這個函數可以輕松查詢一個賬戶的余額
?
event?Sent(address?from,?address?to,?uint?amount);
這行聲明了一個所謂的“event(事件)”,它被最后的send函數發出。包括服務端應用在內的用戶接口可以以較低的成本監聽這些被發送到區塊鏈上的事件。一旦事件被發送,監聽者就會獲取到from、to、amount參數,以便監聽者跟蹤交易。為監聽這一事件,我們會使用
Coin.Sent().watch({}, '', function(error, result) {if (!error) {console.log("Coin transfer: " + result.args.amount +" coins were sent from " + result.args.from +" to " + result.args.to + ".");console.log("Balances now:\n" +"Sender: " + Coin.balances.call(result.args.from) +"Receiver: " + Coin.balances.call(result.args.to));} })注意,自動生成的函數balance是怎樣從用戶接口調用的
?
Coin這個特殊的函數時在創建合約時調用的構造器,他不能在合約構造完成后再被調用。它永久存儲了合約創建者的地址:msg(和tx、block一起)。msg是一個神奇的全局變量,包含一些允許連接到區塊鏈的屬性。msg.sender永遠是當前的(外部)函數調用所來自的地址。
?
這個合約中的函數可以被用戶和其他合約調用,如mint和send。mint只能被合約創建者進行有效的調用。而send可以被任何已經持有一些這種幣的人調用來向他人進行轉賬。注意如果你用這個合約發送幣到其他地址,你在區塊鏈瀏覽器上瀏覽目標地址時并不會看到任何效果產生,因為你發送了幣并改變余額的事實只存儲于這個特定的貨幣合約的數據存儲中。因為有了事件的使用,創建一個用于跟蹤你自己的貨幣的交易和余額的“區塊鏈瀏覽器”變得比較簡單。
?
?
【注1】:getter函數時編譯器為所有public的state變量自動創建的,它會返回一個uint類型的名為“data”的state變量值。狀態變量的初始化可以在聲明時完成。
?
總結
以上是生活随笔為你收集整理的以太坊智能合约简介(Solidity)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PostgreSQL触发器的使用
- 下一篇: 蓝牙协议 HFP,HSP,A2DP,A2