forked from trizin/NFT-Marketplace-on-Avalanche
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Auction.sol
130 lines (111 loc) · 6.38 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
pragma solidity ^0.7.0;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
contract Auction {
using SafeMath for uint256;
uint256 public endTime; // Timestamp of the end of the auction (in seconds)
uint256 public startTime; // The block timestamp which marks the start of the auction
uint public maxBid; // The maximum bid
address public maxBidder; // The address of the maximum bidder
address public creator; // The address of the auction creator
Bid[] public bids; // The bids made by the bidders
uint public tokenId; // The id of the token
bool public isCancelled; // If the the auction is cancelled
bool public isDirectBuy; // True if the auction ended due to direct buy
uint public minIncrement; // The minimum increment for the bid
uint public directBuyPrice; // The price for a direct buy
uint public startPrice; // The starting price for the auction
address public nftAddress; // The address of the NFT contract
IERC721 _nft; // The NFT token
enum AuctionState {
OPEN,
CANCELLED,
ENDED,
DIRECT_BUY
}
struct Bid { // A bid on an auction
address sender;
uint256 bid;
}
// Auction constructor
constructor(address _creator,uint _endTime,uint _minIncrement,uint _directBuyPrice, uint _startPrice,address _nftAddress,uint _tokenId){
creator = _creator; // The address of the auction creator
endTime = block.timestamp + _endTime; // The timestamp which marks the end of the auction (now + 30 days = 30 days from now)
startTime = block.timestamp; // The timestamp which marks the start of the auction
minIncrement = _minIncrement; // The minimum increment for the bid
directBuyPrice = _directBuyPrice; // The price for a direct buy
startPrice = _startPrice; // The starting price for the auction
_nft = IERC721(_nftAddress); // The address of the nft token
nftAddress = _nftAddress;
tokenId = _tokenId; // The id of the token
maxBidder = _creator; // Setting the maxBidder to auction creator.
}
// Returns a list of all bids and addresses
function allBids()
external
view
returns (address[] memory, uint256[] memory)
{
address[] memory addrs = new address[](bids.length);
uint256[] memory bidPrice = new uint256[](bids.length);
for (uint256 i = 0; i < bids.length; i++) {
addrs[i] = bids[i].sender;
bidPrice[i] = bids[i].bid;
}
return (addrs, bidPrice);
}
// Place a bid on the auction
function placeBid() payable external returns(bool){
require(msg.sender != creator); // The auction creator can not place a bid
require(getAuctionState() == AuctionState.OPEN); // The auction must be open
require(msg.value > startPrice); // The bid must be higher than the starting price
require(msg.value > maxBid + minIncrement); // The bid must be higher than the current bid + the minimum increment
address lastHightestBidder = maxBidder; // The address of the last highest bidder
uint256 lastHighestBid = maxBid; // The last highest bid
maxBid = msg.value; // The new highest bid
maxBidder = msg.sender; // The address of the new highest bidder
if(msg.value >= directBuyPrice){ // If the bid is higher than the direct buy price
isDirectBuy = true; // The auction has ended
}
bids.push(Bid(msg.sender,msg.value)); // Add the new bid to the list of bids
if(lastHighestBid != 0){ // if there is a bid
address(uint160(lastHightestBidder)).transfer(lastHighestBid); // refund the previous bid to the previous highest bidder
}
emit NewBid(msg.sender,msg.value); // emit a new bid event
return true; // The bid was placed successfully
}
// Withdraw the token after the auction is over
function withdrawToken() external returns(bool){
require(getAuctionState() == AuctionState.ENDED || getAuctionState() == AuctionState.DIRECT_BUY); // The auction must be ended by either a direct buy or timeout
require(msg.sender == maxBidder); // The highest bidder can only withdraw the token
_nft.transferFrom(address(this), maxBidder, tokenId); // Transfer the token to the highest bidder
emit WithdrawToken(maxBidder); // Emit a withdraw token event
}
// Withdraw the funds after the auction is over
function withdrawFunds() external returns(bool){
require(getAuctionState() == AuctionState.ENDED || getAuctionState() == AuctionState.DIRECT_BUY); // The auction must be ended by either a direct buy or timeout
require(msg.sender == creator); // The auction creator can only withdraw the funds
address(uint160(creator)).transfer(maxBid); // Transfers funds to the creator
emit WithdrawFunds(msg.sender,maxBid); // Emit a withdraw funds event
}
function cancelAuction() external returns(bool){ // Cancel the auction
require(msg.sender == creator); // Only the auction creator can cancel the auction
require(getAuctionState() == AuctionState.OPEN); // The auction must be open
require(maxBid == 0); // The auction must not be cancelled if there is a bid
isCancelled = true; // The auction has been cancelled
_nft.transferFrom(address(this), creator, tokenId); // Transfer the NFT token to the auction creator
emit AuctionCanceled(); // Emit Auction Canceled event
return true;
}
// Get the auction state
function getAuctionState() public view returns(AuctionState) {
if(isCancelled) return AuctionState.CANCELLED; // If the auction is cancelled return CANCELLED
if(isDirectBuy) return AuctionState.DIRECT_BUY; // If the auction is ended by a direct buy return DIRECT_BUY
if(block.timestamp >= endTime) return AuctionState.ENDED; // The auction is over if the block timestamp is greater than the end timestamp, return ENDED
return AuctionState.OPEN; // Otherwise return OPEN
}
event NewBid(address bidder, uint bid); // A new bid was placed
event WithdrawToken(address withdrawer); // The auction winner withdrawed the token
event WithdrawFunds(address withdrawer, uint256 amount); // The auction owner withdrawed the funds
event AuctionCanceled(); // The auction was cancelled
}