Vyper的智能合约简介

Vyper是一种智能的面向合约的pythonic编程语言,面向以太坊虚拟机(EVM)。

它旨在遵循Python的类似简单性,安全性和可读性原则,并提供以下功能:

  • 边界和溢出检查:在数组访问和算术级别上。
  • 支持有符号整数和小数定点数
  • 可判定性:应该可以计算任何函数调用的气体消耗的精确上限。
  • 强类型:包括对单位的支持(例如,时间戳,timedelta,秒,wei,wei /秒,米每秒平方)。
  • 小而易懂的编译器代码
  • 对纯函数的有限支持:任何标记为常量的内容都不允许更改状态。

并遵循类似的原则,Vyper不支持:

  • 修饰符
  • 类继承
  • 内联汇编
  • 函数重载
  • 运算符重载
  • 递归调用
  • 无限长的循环
  • 二进制定点

介绍公开拍卖示例

作为在Vyper中编写的智能合约的介绍性示例,我们从公开的拍卖合约开始。所有Vyper语法都是有效的Python3语法,但并不是所有的Python3功能都可以在Vyper中使用。

在此合约中,参与者可以在有限的时间段内提交出价。当拍卖期结束时,预定的受益人接收最高出价金额。

# Open Auction

# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(address)
auctionStart: public(timestamp)
auctionEnd: public(timestamp)

# Current state of auction
highestBidder: public(address)
highestBid: public(wei_value)

# Set to true at the end, disallows any change
ended: public(bool)

# Keep track of refunded bids so we can follow the withdraw pattern
pendingReturns: public(map(address, wei_value))

# Create a simple auction with `_bidding_time`
# seconds bidding time on behalf of the
# beneficiary address `_beneficiary`.
@public
def __init__(_beneficiary: address, _bidding_time: timedelta):
    self.beneficiary = _beneficiary
    self.auctionStart = block.timestamp
    self.auctionEnd = self.auctionStart + _bidding_time

# Bid on the auction with the value sent
# together with this transaction.
# The value will only be refunded if the
# auction is not won.
@public
@payable
def bid():
    # Check if bidding period is over.
    assert block.timestamp < self.auctionEnd
    # Check if bid is high enough
    assert msg.value > self.highestBid
    # Track the refund for the previous high bidder
    self.pendingReturns[self.highestBidder] += self.highestBid
    # Track new high bid
    self.highestBidder = msg.sender
    self.highestBid = msg.value

# Withdraw a previously refunded bid. The withdraw pattern is
# used here to avoid a security issue. If refunds were directly
# sent as part of bid(), a malicious bidding contract could block
# those refunds and thus block new higher bids from coming in.
@public
def withdraw():
    pending_amount: wei_value = self.pendingReturns[msg.sender]
    self.pendingReturns[msg.sender] = 0
    send(msg.sender, pending_amount)

# End the auction and send the highest bid
# to the beneficiary.
@public
def endAuction():
    # It is a good guideline to structure functions that interact
    # with other contracts (i.e. they call functions or send Ether)
    # into three phases:
    # 1. checking conditions
    # 2. performing actions (potentially changing conditions)
    # 3. interacting with other contracts
    # If these phases are mixed up, the other contract could call
    # back into the current contract and modify the state or cause
    # effects (Ether payout) to be performed multiple times.
    # If functions called internally include interaction with external
    # contracts, they also have to be considered interaction with
    # external contracts.

    # 1. Conditions
    # Check if auction endtime has been reached
    assert block.timestamp >= self.auctionEnd
    # Check if this function has already been called
    assert not self.ended

    # 2. Effects
    self.ended = True

    # 3. Interaction
    send(self.beneficiary, self.highestBid)

此示例只有一个构造函数,两个要调用的方法,以及用于管理合约状态的变量。这就是我们拍卖智能合约基本实施所需的全部内容。

让我们开始吧

# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(address)
auctionStart: public(timestamp)
auctionEnd: public(timestamp)

# Current state of auction
highestBidder: public(address)
highestBid: public(wei_value)

# Set to true at the end, disallows any change
ended: public(bool)

我们首先声明变量以跟踪我们的合约状态。我们通过调用public数据类型来初始化全局变量受益者address受益人将是最高出价者的资金接收者。我们还初始化变量auctionStartauctionEnd使用数据类型timestamp来管理公开拍卖期,并highestBid使用数据类型wei_value(以太小的以太面额)来管理拍卖状态。该变量ended是一个布尔值,用于确定拍卖是否正式结束。

所有变量都传递给public函数。通过声明变量public,变量可以通过外部契约调用。在没有公共函数的情况下初始化变量默认为私有声明,因此只能访问同一合约中的方法。公共函数还为变量创建了一个“getter”函数,可通过外部调用访问contract.beneficiary()

现在,构造函数。

合约初始化有两个参数:_beneficiary类型address_bidding_time类型timedelta,拍卖开始和结束之间的时差。我们这两条信息存储到合约的变量self.beneficiaryself.auctionEnd我们可以通过电话访问当前时间block.timestampblock是任何Vyper合约中可用的对象,并在调用时提供有关块的信息。与块类似,合约中我们可以使用的另一个重要对象是msg,它提供有关方法调用者的信息。

通过初始设置,让我们看看我们的用户如何进行出价。

所述@payable装饰允许用户一些ether发送到合约以调用装饰方法。在这种情况下,想要进行投标的用户bid()在发送等于其期望出价(不包括汽油费)的金额时调用该方法。在调用合约中的任何方法时,我们都会提供一个内置变量msg,我们可以访问任何方法调用者的公共地址msg.sender同样,可以通过调用访问用户发送的以太坊数量msg.value

我们首先使用assert带有任何布尔语句函数检查当前时间是否在拍卖结束时间之前我们还会检查新出价是否高于最高出价。如果两个断言语句通过,我们可以安全地继续下一行; 否则,该bid()方法抛出错误并恢复事务。如果两个断言陈述和前一个出价不等于零通过的检查,我们可以有把握地得出结论,我们有一个有效的新的最高出价。我们将之前的内容发回给前highestBid一个highestBidder并设置我们的新highestBidhighestBidder

使用该endAuction()方法,我们检查当前时间是否超过了auctionEnd我们在合约初始化时设置时间。我们还检查self.ended以前没有设置过True如果拍卖已经结束,我们这样做是为了防止对该方法的任何调用,如果没有进行检查,这可能是恶意的。然后,我们通过设置self.ended并向True受益人发送最高出价金额来正式结束拍卖

下一步

这个介绍和示例取自官方Vyper文档,这是您最好的资源。推荐的后续步骤是:

提示:投资有风险,入市需谨慎,本资讯不作为投资理财建议。请理性投资,切实提高风险防范意识;如有发现的违法犯罪线索,可积极向有关部门举报反映。
你可能还喜欢