學習一門語言,最好的方法就是動手去實現乙個案例。
本文通過乙個官方的公開拍賣合約示例來介紹vyper程式設計。
當我們開始用vyper進行智慧型合約程式設計時,要記住乙個重要的原則:
所有vyper語法都是有效的python3語法,但並不是所有的python3語法都可以在vyper中使用。在這個合約中,我們將實現乙個簡單的公開拍賣功能,通過該合約參與者可以在有限的時間內提交出價,直至拍賣結束,最高的出價者競拍成功,合約自動將競拍款支付給受益人。
以下是**:
# 公開拍賣
# 拍賣引數
# beneficiary是受益人的以太坊位址,將獲得出價最高者的競拍款
# auction_start是競拍開始時間,auction_end是結束時間
beneficiary: public(address)
auction_start: public(timestamp)
auction_end: public(timestamp)
# 儲存當前最高出價的資訊
# highest_bidder是最高出價人以太坊位址
# highest_bid是當前最高出價
highest_bidder: public(address)
highest_bid: public(wei_value)
# 用於標識拍賣是否結束,為true時拍賣結束
ended: public(bool)
# 建構函式,進行初始化
# '_beneficiary'引數代表受益人位址
# '_bidding_time'引數代表拍賣持續的時長
@public
def __init__(_beneficiary: address, _bidding_time: timedelta):
self.beneficiary = _beneficiary
self.auction_start = block.timestamp
self.auction_end = self.auction_start + _bidding_time
# 競價函式,通過呼叫該函式傳送以太幣參與競拍
# 當競拍結束時,你沒有贏得拍賣,以太幣將被退還
@public
@payable
def bid():
# 檢查拍賣是否結束了
assert block.timestamp < self.auction_end
# 檢查出價是否比當前最**高
assert msg.value > self.highest_bid
if not self.highest_bid == 0:
# 退還之前最高出價者的資金
send(self.highest_bidder, self.highest_bid)
self.highest_bidder = msg.sender
self.highest_bid = msg.value
# 結束競拍,將最高出價傳送給受益人
@public
def end_auction():
# 1. 判斷合約是否結束
# 檢查是否超出拍賣的最後時間
assert block.timestamp >= self.auction_end
# 檢查該合約是否已經被呼叫過
assert not self.ended
# 2. 標記為競拍結束
self.ended = true
# 3. 傳送以太幣給受益人
send(self.beneficiary, self.highest_bid)
該拍賣合約非常簡單,僅包含乙個建構函式,兩個方法,以及一些狀態變數。下面我們來詳細討論這個合約。
一、合約名稱
我們會發現這個**沒有類似solidity的「contract openauction」的表述,這是因為vyper的語法跟python的模組命名類似,合約名就是檔名,即這個合約叫openauction的話,就把上面這段**儲存為乙個名叫openauction.vy的檔案。
二、變數宣告
vyper是靜態型別語言,要事先宣告所有變數的資料型別。
放在檔案開頭定義的變數為全域性變數。
beneficiary: public(address)
auction_start: public(timestamp)
auction_end: public(timestamp)
highest_bidder: public(address)
highest_bid: public(wei_value)
ended: public(bool)
關鍵字
說明public
幾乎在所有的語言中表示的意義都相同,就是可以被外部合約訪問。沒有宣告為public
的變數只能在合約內被訪問。public
還為變數建立了乙個「getter
」函式,可通過外部呼叫訪問contract.beneficiary()
。
address
是以太坊特有的一種資料型別,表示該變數被定義為儲存乙個以太坊位址,即乙個長度為20個位元組的十六進製制錢包位址,比如像這樣ca35b7d915458ef540ade6068dfe2f44e8fa733c
。
timestamp
是以太坊特有的一種資料型別,代表的是當前塊的unix時間戳(從1970/1/1 00:00:00 utc開始所經過的秒數)。
wei_value
以太幣金額,以wei
為單位
bool
跟其他語言的布林值變數一樣,有true
和false
兩個值。
三、建構函式
@public
def __init__(_beneficiary: address, _bidding_time: timedelta):
self.beneficiary = _beneficiary
self.auction_start = block.timestamp
self.auction_end = self.auction_start + _bidding_time
vyper的建構函式定義跟python的類建構函式一樣,用__init__
表示。
在函式的前面有乙個裝飾器@public
,這表示該函式可以被外部呼叫。vyper語言裡的其他裝飾器還包括:
裝飾器說明
@private
表示只能在合約內部呼叫
@constant
表示合約狀態不能被改變
@payable
表示可以接收以太幣轉賬
@nonrentant
表示只能被呼叫一次,防止重入攻擊
其中@public
和@private
是強制二選一的,其他的裝飾器視情況可選。
建構函式包含兩個引數:1、_beneficiary
是address
型別,代表受益人位址;2、_bidding_time
是timedelta
型別,代表拍賣持續的時長。
關鍵字單位
說明timestamp
1秒
表示乙個時刻
timedelta
1秒
表示一段時間長度,以秒為單位
注:兩個建構函式通過timedelta
型別的變數可以相加,乙個timestamp
型別的變數與乙個timedelta
型別的時間變數也可相加,但是兩個timestamp
型別的變數不能相加。
self
關鍵字來指代合約本身,將函式引數賦值給合約的變數。在建構函式裡,我們看到有乙個block
物件,通過它獲得了當前區塊的時間。block
是乙個以太坊預設物件,在任何的vyper合約中都能呼叫,不用宣告。與block
物件類似的還有msg
物件。
四、功能函式
這個智慧型合約裡包含兩個功能函式,競價函式與結束函式。
這兩個函式的功能都已經在上面的**注釋中進行了比較詳細的解釋,這裡主要解說一下**裡的一些知識點。
@payable
裝飾器說明bid()
函式可接收以太幣,想要進行投標的使用者可以呼叫該方法並傳送一定數量的以太幣。合約通過內建物件msg
的msg.sender
方法獲取訪問使用者的以太坊位址,通過msg.value
方法獲取訪問使用者傳送的以太幣數量。
注意!下方高能!在
msg.sender
將在內部函式呼叫之間發生變化。當從外部呼叫函式時,它對於第乙個函式呼叫是正確的,就是呼叫函式的人的位址。但是,在合約內部函式互相呼叫之後,msg.sender
將會引用合同本身而不是事務的傳送者。**這是乙個容易造成安全隱患的大坑!**在設計智慧型合約的時候,要牢記安全性,保持**簡單,可讀性強,安全第一!
bid()
和end_auction()
這兩個函式裡,最主要的是使用了vyper語言內建函式裡面的斷言函式assert
和傳送函式send
。
好了,這個例子到此就解釋完畢了,其實還是挺簡單的。
rust 案例 元組 通過例子學 Rust
元組 元組是乙個可以包含各種型別的組合。元組使用括號 來構成,每個元組的值都是 t1,t2,型別標記的形式,其中 t1,t2 是每個元素的型別。函式可以使用元組來返回多個值,因為元組可以 擁有任意數量的值。元組可以充當函式的引數和返回值 fn reverse pair i32,bool bool,i...
看例子學perl
變數 name kent print my name is name n print my name is name n 出力結果 my name is kent my name is name 注 單引號內變數不轉譯 c abc d 3 print c x d 出力結果 abcabcabc 注 x...
通過翻譯學英語
例項1 漢語 按人口計算,中國是世界上最大的國家 按領土面積計算,是第三大國家,僅次於俄羅斯和加拿大。不好譯文 according to population figure.china is the largest country in the whole world and according t...