-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAuction(English comments).sol
139 lines (105 loc) · 4.27 KB
/
Auction(English comments).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
// SPDX-License-Identifier: Unlicansed
pragma solidity ^0.8.7;
contract Auction{
address payable public owner;
uint public startBlock;
uint public endBlock;
string public ipfsHash;
enum State {Started, Running, Ended, Canceled}
State public auctionState;
uint public highestBindingBid;
address payable public highestBidder;
mapping(address => uint) public bids;
uint bidIncrement;
//the owner can finalize the auction and get the highestBindingBid only once
bool public ownerFinalized = false;
constructor(){
owner = payable(msg.sender);
auctionState = State.Running;
startBlock = block.number;
endBlock = startBlock + 3;
ipfsHash = "";
bidIncrement = 1000000000000000000; // bidding in multiple of ETH
}
// declaring function modifiers
modifier notOwner(){
require(msg.sender != owner);
_;
}
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
modifier afterStart(){
require(block.number >= startBlock);
_;
}
modifier beforeEnd(){
require(block.number <= endBlock);
_;
}
//a helper pure function (it neither reads, nor it writes to the blockchain)
function min(uint a, uint b) pure internal returns(uint){
if (a <= b){
return a;
}else{
return b;
}
}
// only the owner can cancel the Auction before the Auction has ended
function cancelAuction() public beforeEnd onlyOwner{
auctionState = State.Canceled;
}
// the main function called to place a bid
function placeBid() public payable notOwner afterStart beforeEnd returns(bool){
// to place a bid auction should be running
require(auctionState == State.Running);
// minimum value allowed to be sent
// require(msg.value > 0.0001 ether);
uint currentBid = bids[msg.sender] + msg.value;
// the currentBid should be greater than the highestBindingBid.
// Otherwise there's nothing to do.
require(currentBid > highestBindingBid);
// updating the mapping variable
bids[msg.sender] = currentBid;
if (currentBid <= bids[highestBidder]){ // highestBidder remains unchanged
highestBindingBid = min(currentBid + bidIncrement, bids[highestBidder]);
}else{ // highestBidder is another bidder
highestBindingBid = min(currentBid, bids[highestBidder] + bidIncrement);
highestBidder = payable(msg.sender);
}
return true;
}
function finalizeAuction() public{
// the auction has been Canceled or Ended
require(auctionState == State.Canceled || block.number > endBlock);
// only the owner or a bidder can finalize the auction
require(msg.sender == owner || bids[msg.sender] > 0);
// the recipient will get the value
address payable recipient;
uint value;
if(auctionState == State.Canceled){ // auction canceled, not ended
recipient = payable(msg.sender);
value = bids[msg.sender];
}else{// auction ended, not canceled
if(msg.sender == owner && ownerFinalized == false){ //the owner finalizes the auction
recipient = owner;
value = highestBindingBid;
//the owner can finalize the auction and get the highestBindingBid only once
ownerFinalized = true;
}else{// another user (not the owner) finalizes the auction
if (msg.sender == highestBidder){
recipient = highestBidder;
value = bids[highestBidder] - highestBindingBid;
}else{ //this is neither the owner nor the highest bidder (it's a regular bidder)
recipient = payable(msg.sender);
value = bids[msg.sender];
}
}
}
// resetting the bids of the recipient to avoid multiple transfers to the same recipient
bids[recipient] = 0;
//sends value to the recipient
recipient.transfer(value);
}
}