forked from vechain/ThorNode-contracts
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathClockAuction.sol
208 lines (180 loc) · 6.96 KB
/
ClockAuction.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
198
199
200
201
202
203
204
205
206
207
208
// Copyright (c) 2018 The VeChainThor developers
// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying
// file LICENSE or <https://www.gnu.org/licenses/lgpl-3.0.html>
pragma solidity ^0.4.24;
import "./ClockAuctionBase.sol";
import "../utility/interfaces/IVIP181.sol";
contract ClockAuction is ClockAuctionBase {
/// @dev Constructor creates a reference to the token ownership contract
/// and verifies the owner cut is in the valid range.
/// @param _nftAddress - address of a deployed contract implementing
/// the Nonfungible Interface.
constructor(address _nftAddress, address _feePool) public {
require(_nftAddress != address(0), "invalid address");
require(_feePool != address(0), "invalid address");
VIP181 = IVIP181(_nftAddress);
feePool = _feePool;
}
/// @dev Creates and begins a new auction.
/// @param _auctionId - ID of auction.
/// @param _tokenId - ID of token to auction, sender must be owner.
/// @param _startingPrice - Price of item (in wei) at beginning of auction.
/// @param _endingPrice - Price of item (in wei) at end of auction.
/// @param _duration - Length of time to move between starting
/// price and ending price (in seconds).
/// @param _startedAt - StartedAt, if not the message sender
/// @param _seller - Seller, if not the message sender
function createAuction(
uint256 _auctionId,
uint256 _tokenId,
uint128 _startingPrice,
uint128 _endingPrice,
uint64 _duration,
uint64 _startedAt,
address _seller
)
external
whenNotPaused
{
require(msg.sender == address(VIP181), "permission denied");
require(!isOnAuction(_tokenId), "token is on auction");
// the duration of any auction should between 2 hours and 7 days.
require(_duration >= 2 hours, "at least 2 hours");
require(_duration <= 7 days, "at most 7 days");
// remove expired auction first if exist
_cancelAuction(_tokenId);
// add new auction
_addAuction(_auctionId, _tokenId, _startingPrice, _endingPrice, _duration, _startedAt, _seller);
}
/// @dev Bids on an open auction, completing the auction and transferring
/// ownership of the token if enough Ether is supplied.
/// @param _buyer - address of token buyer.
/// @param _tokenId - ID of token to bid on.
function bid(address _buyer, uint256 _tokenId)
external
payable
whenNotPaused
returns(uint256)
{
require(msg.sender == address(VIP181), "permission denied");
require(isOnAuction(_tokenId), "auction not found");
// if the candidates not empty check the _buyer in
if(hasWhiteList(_tokenId)) {
require(inWhiteList(_tokenId, _buyer), "blocked");
}
Auction storage auction = tokenIdToAuction[_tokenId];
address _seller = auction.seller;
// _bid will throw if the bid or funds transfer fails
uint256 _price = _bid(_buyer, _tokenId, msg.value);
VIP181.transferFrom(_seller, _buyer, _tokenId);
return _price;
}
/// @dev Cancels an auction that hasn't been won yet.
/// @param _tokenId - ID of token on auction
function cancelAuction(uint256 _tokenId)
external
whenNotPaused
{
require(msg.sender == address(VIP181), "permission denied");
require(exist(_tokenId), "auction not found");
_cancelAuction(_tokenId);
}
/// @dev Returns auction info for an token on auction.
/// @param _tokenId - ID of token on auction.
function getAuction(uint256 _tokenId)
public
view
returns (
uint256 autionId,
address seller,
uint256 startingPrice,
uint256 endingPrice,
uint64 duration,
uint64 startedAt
) {
Auction storage auction = tokenIdToAuction[_tokenId];
return (
auction.auctionId,
auction.seller,
auction.startingPrice,
auction.endingPrice,
auction.duration,
auction.startedAt
);
}
/// @dev Returns true if the auction exists
function exist(uint256 _tokenId)
public
view
returns(bool)
{
return tokenIdToAuction[_tokenId].auctionId > 0;
}
/// @dev Returns true if the token is on auction.
function isOnAuction(uint256 _tokenId)
public
view
returns (bool)
{
Auction storage _auction = tokenIdToAuction[_tokenId];
return _auction.startedAt > 0 && _auction.startedAt <= now && now < (_auction.startedAt + _auction.duration);
}
/// @dev Returns the current price of an auction.
/// @param _tokenId - ID of the token price we are checking.
function getCurrentPrice(uint256 _tokenId)
public
view
returns (uint256)
{
if (!isOnAuction(_tokenId)) {
return 0;
}
Auction storage auction = tokenIdToAuction[_tokenId];
return _currentPrice(auction);
}
function hasWhiteList(uint256 _tokenId)
public
view
returns (bool)
{
uint256 _auctionId = tokenIdToAuction[_tokenId].auctionId;
// always return false when tokenId is not on auction.
return auctionWhiteList[_auctionId].count > 0;
}
function inWhiteList(uint256 _tokenId, address _address)
public
view
returns (bool)
{
uint256 _auctionId = tokenIdToAuction[_tokenId].auctionId;
// always return false when tokenId is not on auction.
return auctionWhiteList[_auctionId].whiteList[_address];
}
/// @dev Add condidate for the auction of the passed token.
function addAuctionWhiteList(uint256 _tokenId, address _address)
external
whenNotPaused
{
require(msg.sender == address(VIP181), "permission denied");
require(isOnAuction(_tokenId), "auction not found");
require(!inWhiteList(_tokenId, _address), "in the list");
uint256 _auctionId = tokenIdToAuction[_tokenId].auctionId;
uint64 _count = auctionWhiteList[_auctionId].count;
auctionWhiteList[_auctionId].count++;
// Overflow check
assert(_count < auctionWhiteList[_auctionId].count);
auctionWhiteList[_auctionId].whiteList[_address] = true;
}
/// @dev Remove address from whitelist.
function removeAuctionWhiteList(uint256 _tokenId, address _address)
external
whenNotPaused
{
require(msg.sender == address(VIP181), "permission denied");
require(isOnAuction(_tokenId), "auction not found");
require(inWhiteList(_tokenId, _address), "not in the list");
uint256 _auctionId = tokenIdToAuction[_tokenId].auctionId;
auctionWhiteList[_auctionId].count--;
auctionWhiteList[_auctionId].whiteList[_address] = false;
}
}