You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.7 KiB
82 lines
2.7 KiB
4 years ago
|
# Open Auction
|
||
|
|
||
|
# Auction params
|
||
|
# Beneficiary receives money from the highest bidder
|
||
|
beneficiary: public(address)
|
||
|
auctionStart: public(uint256)
|
||
|
auctionEnd: public(uint256)
|
||
|
|
||
|
# Current state of auction
|
||
|
highestBidder: public(address)
|
||
|
highestBid: public(uint256)
|
||
|
|
||
|
# 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(HashMap[address, uint256])
|
||
|
|
||
|
# Create a simple auction with `_bidding_time`
|
||
|
# seconds bidding time on behalf of the
|
||
|
# beneficiary address `_beneficiary`.
|
||
|
@external
|
||
|
def __init__(_beneficiary: address, _bidding_time: uint256):
|
||
|
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.
|
||
|
@external
|
||
|
@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.
|
||
|
@external
|
||
|
def withdraw():
|
||
|
pending_amount: uint256 = 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.
|
||
|
@external
|
||
|
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)
|