-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAuction.sol
197 lines (161 loc) · 5.78 KB
/
Auction.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
pragma solidity ^0.4.8;
contract Auction {
// static
address public owner;
uint private bidIncrement;
uint public startTime;
uint public endTime;
// state
bool public canceled;
uint public highestBindingBid;
address public highestBidder;
mapping(address => uint256) public fundsByBidder;
bool ownerHasWithdrawn;
event LogBid(address bidder, uint bid, address highestBidder, uint highestBid, uint highestBindingBid);
event LogWithdrawal(address withdrawer, address withdrawalAccount, uint amount);
event LogCanceled();
constructor(address _owner, uint duration) public {
require(_owner != 0x0);
owner = _owner;
bidIncrement = 1;
startTime = block.timestamp;
endTime = block.timestamp + duration;
}
function getHighestBid()
public
constant
returns (uint)
{
return fundsByBidder[highestBidder];
}
function placeBid()
public
payable
onlyBeforeEnd
onlyNotCanceled
onlyNotOwner
returns (bool success)
{
// reject payments of 0 ETH
require(msg.value != 0);
// calculate the user's total bid based on the current amount they've sent to the contract
// plus whatever has been sent with this transaction
uint newBid = fundsByBidder[msg.sender] + msg.value;
// if the user isn't even willing to overbid the highest binding bid, there's nothing for us
// to do except revert the transaction.
require(newBid > highestBindingBid);
// grab the previous highest bid (before updating fundsByBidder, in case msg.sender is the
// highestBidder and is just increasing their maximum bid).
uint highestBid = fundsByBidder[highestBidder];
fundsByBidder[msg.sender] = newBid;
if (newBid <= highestBid) {
// if the user has overbid the highestBindingBid but not the highestBid, we simply
// increase the highestBindingBid and leave highestBidder alone.
// note that this case is impossible if msg.sender == highestBidder because you can never
// bid less ETH than you've already bid.
highestBindingBid = min(newBid + bidIncrement, highestBid);
} else {
// if msg.sender is already the highest bidder, they must simply be wanting to raise
// their maximum bid, in which case we shouldn't increase the highestBindingBid.
// if the user is NOT highestBidder, and has overbid highestBid completely, we set them
// as the new highestBidder and recalculate highestBindingBid.
if (msg.sender != highestBidder) {
highestBidder = msg.sender;
highestBindingBid = min(newBid, highestBid + bidIncrement);
}
highestBid = newBid;
}
emit LogBid(msg.sender, newBid, highestBidder, highestBid, highestBindingBid);
return true;
}
function min(uint a, uint b)
private
constant
returns (uint)
{
if (a < b) return a;
return b;
}
function cancelAuction()
public
onlyOwner
onlyBeforeEnd
onlyNotCanceled
returns (bool success)
{
canceled = true;
emit LogCanceled();
return true;
}
function endAuction()
public
onlyOwner
onlyBeforeEnd
onlyNotCanceled
returns (bool success)
{
endTime = block.timestamp;
return true;
}
function withdraw()
public
onlyEndedOrCanceled
returns (bool success)
{
address withdrawalAccount;
uint withdrawalAmount;
if (canceled) {
// if the auction was canceled, everyone should simply be allowed to withdraw their funds
withdrawalAccount = msg.sender;
withdrawalAmount = fundsByBidder[withdrawalAccount];
} else {
// the auction finished without being canceled
if (msg.sender == owner) {
// the auction's owner should be allowed to withdraw the highestBindingBid
withdrawalAccount = highestBidder;
withdrawalAmount = highestBindingBid;
ownerHasWithdrawn = true;
} else if (msg.sender == highestBidder) {
// the highest bidder should only be allowed to withdraw the difference between their
// highest bid and the highestBindingBid
withdrawalAccount = highestBidder;
if (ownerHasWithdrawn) {
withdrawalAmount = fundsByBidder[highestBidder];
} else {
withdrawalAmount = fundsByBidder[highestBidder] - highestBindingBid;
}
} else {
// anyone who participated but did not win the auction should be allowed to withdraw
// the full amount of their funds
withdrawalAccount = msg.sender;
withdrawalAmount = fundsByBidder[withdrawalAccount];
}
}
require(withdrawalAmount != 0);
fundsByBidder[withdrawalAccount] -= withdrawalAmount;
// send the funds
require(msg.sender.send(withdrawalAmount));
emit LogWithdrawal(msg.sender, withdrawalAccount, withdrawalAmount);
return true;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
modifier onlyNotOwner {
require(msg.sender != owner);
_;
}
modifier onlyBeforeEnd {
require(block.timestamp < endTime);
_;
}
modifier onlyNotCanceled {
require(!canceled);
_;
}
modifier onlyEndedOrCanceled {
require((block.timestamp > endTime) || canceled);
_;
}
}