通過例子學Vyper(一)

2021-09-13 00:00:34 字數 4987 閱讀 8594

學習一門語言,最好的方法就是動手去實現乙個案例。

本文通過乙個官方的公開拍賣合約示例來介紹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跟其他語言的布林值變數一樣,有truefalse兩個值。

三、建構函式

@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、_beneficiaryaddress型別,代表受益人位址;2、_bidding_timetimedelta型別,代表拍賣持續的時長。

關鍵字單位

說明timestamp1秒

表示乙個時刻

timedelta1秒

表示一段時間長度,以秒為單位

注:兩個timedelta型別的變數可以相加,乙個timestamp型別的變數與乙個timedelta型別的時間變數也可相加,但是兩個timestamp型別的變數不能相加。

建構函式通過self關鍵字來指代合約本身,將函式引數賦值給合約的變數。在建構函式裡,我們看到有乙個block物件,通過它獲得了當前區塊的時間。block是乙個以太坊預設物件,在任何的vyper合約中都能呼叫,不用宣告。與block物件類似的還有msg物件。

四、功能函式

這個智慧型合約裡包含兩個功能函式,競價函式與結束函式。

這兩個函式的功能都已經在上面的**注釋中進行了比較詳細的解釋,這裡主要解說一下**裡的一些知識點。

@payable裝飾器說明bid()函式可接收以太幣,想要進行投標的使用者可以呼叫該方法並傳送一定數量的以太幣。合約通過內建物件msgmsg.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...