Created
April 2, 2017 20:58
-
-
Save slavik0329/e91516a12d9229fc0828dbda6a76a08e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.0; | |
contract BetterAuction { | |
// Auction beneficiary | |
address public beneficiary; | |
// Auction start time, seconds from 1970-01-01 | |
uint256 public auctionStart; | |
// Auction bidding period in seconds, relative to auctionStart | |
uint256 public biddingPeriod; | |
// Period after auction ends when the beneficiary can withdraw all funds, relative to auctionStart | |
uint256 public recoveryAfterPeriod; | |
// User sends this amount to the contract to withdraw funds, 0.0001 ETH | |
uint256 public constant WITHDRAWAL_TRIGGER_AMOUNT = 100000000000000; | |
// Address of the highest bidder | |
address public highestBidder; | |
// Highest bid amount | |
uint256 public highestBid; | |
// Allowed withdrawals of previous bids | |
mapping(address => uint256) pendingReturns; | |
// Set to true at the end, disallows any change | |
bool auctionClosed; | |
modifier isBeneficiary { | |
if (msg.sender != beneficiary) throw; | |
_; | |
} | |
modifier isAuctionActive { | |
if (now < auctionStart || now > (auctionStart + biddingPeriod)) throw; | |
_; | |
} | |
modifier isAuctionEnded { | |
if (now < (auctionStart + biddingPeriod)) throw; | |
_; | |
} | |
modifier isRecoveryActive { | |
if (now < (auctionStart + recoveryAfterPeriod)) throw; | |
_; | |
} | |
event HighestBidIncreased(address bidder, uint256 amount); | |
event AuctionClosed(address winner, uint256 amount); | |
// Auction starts at deployment, runs for _biddingPeriod (seconds from | |
// auction start), and funds can be recovered after _recoverPeriod | |
// (seconds from auction start) | |
function BetterAuction( | |
address _beneficiary, | |
uint256 _biddingPeriod, | |
uint256 _recoveryAfterPeriod | |
) { | |
if (_beneficiary == 0) throw; | |
beneficiary = _beneficiary; | |
auctionStart = now; | |
if (_biddingPeriod > _recoveryAfterPeriod) throw; | |
biddingPeriod = _biddingPeriod; | |
recoveryAfterPeriod = _recoveryAfterPeriod; | |
} | |
// Users want to know when the auction ends, seconds from 1970-01-01 | |
function auctionEndTime() constant returns (uint256) { | |
return auctionStart + biddingPeriod; | |
} | |
// Users want to know theirs or someones current bid | |
function getBid(address _address) constant returns (uint256) { | |
if (_address == highestBidder) { | |
return highestBid; | |
} else { | |
return pendingReturns[_address]; | |
} | |
} | |
// Update highest bid or top up previous bid | |
function bidderUpdateBid() internal { | |
if (msg.sender == highestBidder) { | |
highestBid += msg.value; | |
HighestBidIncreased(msg.sender, highestBid); | |
} else if (pendingReturns[msg.sender] + msg.value > highestBid) { | |
var amount = pendingReturns[msg.sender] + msg.value; | |
pendingReturns[msg.sender] = 0; | |
// Save previous highest bidders funds | |
pendingReturns[highestBidder] = highestBid; | |
// Record the highest bid | |
highestBid = amount; | |
highestBidder = msg.sender; | |
HighestBidIncreased(msg.sender, amount); | |
} else { | |
throw; | |
} | |
} | |
// Bidders can only place bid while the auction is active | |
function bidderPlaceBid() isAuctionActive payable { | |
if ((pendingReturns[msg.sender] > 0 || msg.sender == highestBidder) && msg.value > 0) { | |
bidderUpdateBid(); | |
} else { | |
// Reject bids below the highest bid | |
if (msg.value <= highestBid) throw; | |
// Save previous highest bidders funds | |
if (highestBidder != 0) { | |
pendingReturns[highestBidder] += highestBid; | |
} | |
// Record the highest bid | |
highestBidder = msg.sender; | |
highestBid = msg.value; | |
HighestBidIncreased(msg.sender, msg.value); | |
} | |
} | |
// Recover any ethers accidentally sent to contract | |
function beneficiaryRecoverFunds() isBeneficiary isRecoveryActive { | |
if (!beneficiary.send(this.balance)) throw; | |
} | |
// Withdraw a bid that was overbid. | |
function nonHighestBidderRefund() payable { | |
var amount = pendingReturns[msg.sender]; | |
if (amount > 0) { | |
pendingReturns[msg.sender] = 0; | |
if (!msg.sender.send(amount + msg.value)) throw; | |
} else { | |
throw; | |
} | |
} | |
// Close the auction and receive the highest bid amount | |
function beneficiaryCloseAuction() isBeneficiary isAuctionEnded { | |
if (auctionClosed) throw; | |
auctionClosed = true; | |
AuctionClosed(highestBidder, highestBid); | |
if (!beneficiary.send(highestBid)) throw; | |
} | |
// Bidders send their bids to the contract. If this is the trigger amount | |
// allow non-highest bidders to withdraw their funds | |
function () payable { | |
if (msg.value == WITHDRAWAL_TRIGGER_AMOUNT) { | |
nonHighestBidderRefund(); | |
} else { | |
bidderPlaceBid(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment