forked from slavik0329/BetterAuction
-
Notifications
You must be signed in to change notification settings - Fork 0
/
betterauction.sol
171 lines (154 loc) · 6.08 KB
/
betterauction.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// ------------------------------------------------------------------------
// BetterAuction
//
// Decentralised open auction on the Ethereum blockchain
//
// Note: When a bidder is outbid they can top up their bid by sending more
// ether to the contract or they can get their outbid funds back by calling
// nonHighestBidderRefund directly or by simply sending exactly 0.0001 ETH
// to the contract.
//
// (c) Steve Dakh & BokkyPooBah 2017.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
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();
}
}
}