Skip to content

Instantly share code, notes, and snippets.

@slavik0329
Created April 3, 2017 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slavik0329/66c34a07ea9ed075d99cb2f8648a4ddf to your computer and use it in GitHub Desktop.
Save slavik0329/66c34a07ea9ed075d99cb2f8648a4ddf to your computer and use it in GitHub Desktop.
pragma solidity ^0.4.8;
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