-
-
Save slavik0329/58f1944d61d00575476ee47937c3486c 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; | |
// DONE: This contract will accumulate the withdrawal trigger amounts. What | |
// to do with it? Will the following statement work? | |
// var amount = pendingReturns[msg.sender] + msg.value; | |
// TODO: Test the whole logic of recording ethers sent and all but the highest | |
// user being able to withdraw | |
// DONE: Check if withdraw requires a payable modifier (it works, but maybe that could change?) | |
// TODO: The pendingReturns[highestBidder] += highestBid; logic may not work | |
// TODO: Run through a whole series of test | |
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; | |
_; | |
} | |
// 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 | |
) { | |
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 addy) constant returns (uint256) { | |
if ( addy == highestBidder ) { | |
return highestBid; | |
} else { | |
return pendingReturns[addy]; | |
} | |
} | |
// Update highest bid or top up previous bid | |
function bidderUpdateBid() internal { | |
if (msg.sender == highestBidder) { | |
highestBid += msg.value; | |
} 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); | |
} | |
} | |
event HighestBidIncreased(address bidder, uint256 amount); | |
// 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() { | |
var amount = pendingReturns[msg.sender]; | |
if (amount > 0) { | |
pendingReturns[msg.sender] = 0; | |
if (!msg.sender.send(amount + msg.value)) 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; | |
} | |
event AuctionClosed(address winner, uint256 amount); | |
// 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