-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAuction.sol
More file actions
156 lines (122 loc) · 5.32 KB
/
Auction.sol
File metadata and controls
156 lines (122 loc) · 5.32 KB
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
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5 <0.9;
contract Auction{
//variables
address private owner;
address public highestBidder;
bool private ownerHasWithdrawn;
bool private cancelled;
uint public startDate;
uint public endDate;
uint public bidIncrement;
uint public highestBindingBid;
mapping(address => uint) private bids;
constructor(uint _startDate, uint _endDate, uint _bidIncrement){
require(_startDate < _endDate, "Start date should be greater than end date.");
owner = msg.sender;
startDate = _startDate;
endDate = _endDate;
bidIncrement = _bidIncrement;
}
modifier onlyOwner(){
require(msg.sender == owner, "Only owner can perform this action.");
_;
}
modifier isCancelled(){
require(cancelled == false, "The auction has been cancelled already.");
_;
}
modifier notCancelled(){
require(cancelled == false, "The auction has been cancelled.");
_;
}
modifier auctionExpired(){
require(block.timestamp < endDate, "The auction has expired.");
_;
}
modifier auctionStarted(){
require(block.timestamp > startDate, "The auction has not started yet.");
_;
}
modifier auctionEndedOrCancelled {
require(block.timestamp > endDate || cancelled, "Auction has not ended yet.");
_;
}
modifier notOwner {
require(msg.sender != owner, "Owner cannot bid.");
_;
}
function min(uint a, uint b) private view returns (uint) {
if (a < b) return a;
return b;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function cancelAuction() public onlyOwner isCancelled auctionExpired {
cancelled = true;
emit LogCancelled();
}
function placeBids() public payable auctionExpired auctionStarted notCancelled notOwner returns (bool) {
//reject payments of 0 eth
require(msg.value > 0, "Value needs to be greater than 0 eth.");
uint newBid = bids[msg.sender] + msg.value;
// if the user isn't even willing to overbid the highest binding bid, then revert the transaction
require(newBid > highestBindingBid, "New bid not greater than highest binding bid.");
//take the previous highest bid before updating fundsByBidder, in case msg.sender is the
// highestBidder and is just increasing their maximum bid).
uint highestBid = bids[highestBidder];
bids[msg.sender] = newBid;
if (newBid <= highestBid) {
// you can never bid less ETH than you've already bid.
highestBindingBid = min(newBid + bidIncrement, highestBid);
} else {
// 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 withdraw() public auctionEndedOrCancelled returns (bool) {
address payable withdrawalAccount;
uint withdrawalAmount;
if (cancelled) {
// if the auction was canceled, everyone should simply be allowed to withdraw their funds.
withdrawalAccount = payable(msg.sender);
withdrawalAmount = bids[withdrawalAccount];
} else {
// the auction finished without being cancelled
if (msg.sender == owner) {
// the auction's owner should be allowed to withdraw the highestBindingBid
withdrawalAccount = payable(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 = payable(highestBidder);
if (ownerHasWithdrawn) {
withdrawalAmount = bids[highestBidder];
} else {
withdrawalAmount = bids[highestBidder] - highestBindingBid;
}
} else {
//everyone who participated but didn't win the auction can withdraw their amount.
withdrawalAccount = payable(msg.sender);
withdrawalAmount = bids[withdrawalAccount];
}
}
require(withdrawalAmount >= 0, "Withdraw amount should be >= 0.");
bids[withdrawalAccount] -= withdrawalAmount;
require(payable(msg.sender).send(withdrawalAmount) == true, "Could not send.");
emit LogWithdrawal(msg.sender, withdrawalAccount, withdrawalAmount);
return true;
}
event LogCancelled();
event LogBid(address bidder, uint bid, address highestBidder, uint highestBid, uint highestBindingBid);
event LogWithdrawal(address withdrawer, address withdrawalAccount, uint amount);
}