Như một ví dụ giới thiệu về hợp đồng thông minh được viết bằng Vyper, chúng ta sẽ bắt đầu với một hợp đồng đấu giá mở đơn giản. Khi chúng ta đi sâu vào mã, điều quan trọng cần nhớ là tất cả cú pháp Vyper là cú pháp Python3 hợp lệ, tuy nhiên không phải tất cả chức năng Python3 đều có sẵn trong Vyper.
Trong hợp đồng này, chúng ta sẽ xem xét một hợp đồng đấu giá mở đơn giản, nơi những người tham gia có thể gửi giá thầu trong một khoảng thời gian giới hạn. Khi thời gian đấu giá kết thúc, người thụ hưởng được xác định trước sẽ nhận được số tiền trả giá cao nhất.
# Open Auction
# Auction params
# Người thụ hưởng nhận tiền từ người trả giá cao nhất
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)
# Hiện trạng đấu giá
highestBidder: public(address)
highestBid: public(uint256)
# Đặt thành true ở cuối, không cho phép mọi thay đổi
ended: public(bool)
# Theo dõi các giá thầu được hoàn lại để chúng tôi có thể theo dõi mô hình rút tiền
pendingReturns: public(HashMap[address, uint256])
# Tạo một phiên đấu giá đơn giản với `_auction_start`
# Thời gian đặt giá thầu `_bidding_time` giây thay mặt cho
# địa chỉ người thụ hưởng `_ người thụ hưởng`.
@external
def __init__(_beneficiary: address, _auction_start: uint256, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = _auction_start # thời gian bắt đầu đấu giá có thể trong quá khứ, hiện tại hoặc tương lai
self.auctionEnd = self.auctionStart + _bidding_time
assert block.timestamp < self.auctionEnd # thời gian kết thúc đấu giá phải trong tương lai
# Đặt giá thầu trên phiên đấu giá với giá trị được gửi
# cùng với giao dịch này.
# Giá trị sẽ chỉ được hoàn lại nếu
# đấu giá không thắng.
@external
@payable
def bid():
# Kiểm tra xem thời gian đấu thầu đã bắt đầu chưa.
assert block.timestamp >= self.auctionStart
# Kiểm tra xem thời gian đấu thầu đã hết chưa.
assert block.timestamp < self.auctionEnd
# Kiểm tra xem giá thầu có đủ cao không
assert msg.value > self.highestBid
# Theo dõi khoản hoàn trả cho người trả giá cao trước đó
self.pendingReturns[self.highestBidder] += self.highestBid
# Theo dõi giá thầu cao mới
self.highestBidder = msg.sender
self.highestBid = msg.value
# Rút lại giá thầu đã hoàn lại trước đó. Mô hình rút tiền là
# được sử dụng ở đây để tránh sự cố bảo mật. Nếu tiền hoàn lại là trực tiếp
# được gửi như một phần của bid (), hợp đồng đặt giá thầu độc hại có thể chặn
# các khoản tiền hoàn lại đó và do đó chặn các giá thầu mới cao hơn đến.
@external
def withdraw():
pending_amount: uint256 = self.pendingReturns[msg.sender]
self.pendingReturns[msg.sender] = 0
send(msg.sender, pending_amount)
# Kết thúc cuộc đấu giá và gửi giá thầu cao nhất
# cho người thụ hưởng.
@external
def endAuction():
# Đó là một hướng dẫn tốt để cấu trúc các chức năng tương tác
# với các hợp đồng khác (tức là họ gọi các hàm hoặc gửi Ether)
# thành ba giai đoạn:
# 1. kiểm tra điều kiện
# 2. thực hiện các hành động (điều kiện có thể thay đổi)
# 3. tương tác với các hợp đồng khác
# Nếu các giai đoạn này bị trộn lẫn, hợp đồng khác có thể gọi là
# trở lại hợp đồng hiện tại và sửa đổi trạng thái hoặc nguyên nhân
# hiệu ứng (thanh toán Ether) được thực hiện nhiều lần.
# Nếu các chức năng được gọi nội bộ bao gồm tương tác với bên ngoài
# hợp đồng, chúng cũng phải được coi là tương tác với
# hợp đồng bên ngoài.
# 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)
Như bạn có thể thấy, ví dụ này chỉ có một hàm tạo, hai phương thức để gọi và một vài biến để quản lý trạng thái hợp đồng. Đây là tất cả những gì chúng ta cần để triển khai cơ bản hợp đồng thông minh đấu giá.
Bắt đầu đi sâu hơn
# Auction params
# Người thụ hưởng nhận tiền từ người trả giá cao nhất
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)
# Hiện trạng đấu giá
highestBidder: public(address)
highestBid: public(uint256)
# Đặt thành true ở cuối, không cho phép mọi thay đổi
ended: public(bool)
# Theo dõi các giá thầu được hoàn lại để chúng tôi có thể theo dõi mô hình rút tiền
pendingReturns: public(HashMap[address, uint256])
Chúng ta bắt đầu bằng cách khai báo một vài biến để theo dõi trạng thái hợp đồng của chúng ta. Chúng ta khởi tạo beneficiary
(người thụ hưởng) biến toàn cục bằng cách public
trên địa chỉ kiểu dữ liệu. Người thụ hưởng sẽ là người nhận tiền từ người trả giá cao nhất. Chúng ta cũng khởi tạo các biến auctionStart
và auctionEnd
với loại dữ liệu uint256
để quản lý giai đoạn đấu giá mở và highestBid
với loại dữ liệu uint256, mệnh giá nhỏ nhất của ether, để quản lý trạng thái đấu giá. Biến kết thúc là một boolean để xác định liệu phiên đấu giá có chính thức kết thúc hay không. Biến pendingReturns
là một map
cho phép sử dụng các cặp key-value để theo dõi chính xác mô hình rút tiền đấu giá.
Bạn có thể nhận thấy tất cả các biến được chuyển vào public
function . Bằng cách khai báo biến public
, biến có thể được gọi bởi các hợp đồng bên ngoài. Việc khởi tạo các biến không có hàm public sẽ được mặc định là một khai báo private và do đó, chỉ các phương thức trong cùng một hợp đồng mới có thể truy cập được.
Hàm public cũng tạo ra một hàm ‘getter’ cho biến, có thể truy cập thông qua một lệnh gọi bên ngoài chẳng hạn như
contract.beneficiary()
Bây giờ hàm tạo.
@external
def __init__(_beneficiary: address, _auction_start: uint256, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = _auction_start # auction start time can be in the past, present or future
self.auctionEnd = self.auctionStart + _bidding_time
assert block.timestamp < self.auctionEnd # auction end time should be in the future