forked from ggonzalez94/base-auctions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSecondPriceSealedBidAuction.sol
79 lines (73 loc) · 3.23 KB
/
SecondPriceSealedBidAuction.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./BaseSealedBidAuction.sol";
/**
* @title SecondPriceSealedBidAuction
* @notice An abstract contract for a second-price sealed-bid auction(Vickrey Auction).
* In this format, the highest bidder pays the second-highest bid(or the reserve price if there are no two bids
* above the reserve price).
* @dev
* - Child contracts must still override `_transferAssetToWinner()` and `_returnAssetToSeller()` for handling the
* transfer of the specific asset.
* - Bids below the reserve price do not produce a winner.
*/
abstract contract SecondPriceSealedBidAuction is BaseSealedBidAuction {
/// @dev The highest bid in the auction
uint96 private highestBid;
/// @dev The second-highest bid in the auction
uint96 private secondHighestBid;
/**
* @param _seller The address of the seller
* @param _startTime The block timestamp at which the auction starts
* @param _commitDeadline No commits allowed after this time
* @param _revealDeadline No reveals allowed after this time
* @param _reservePrice The minimum acceptable price
*/
constructor(
address _seller,
uint256 _startTime,
uint256 _commitDeadline,
uint256 _revealDeadline,
uint96 _reservePrice
) BaseSealedBidAuction(_seller, _startTime, _commitDeadline, _revealDeadline) {
highestBid = _reservePrice;
secondHighestBid = _reservePrice;
}
/**
* @dev Checks if the amount is higher than the current highest bid and updates the state accordingly
* In the unlikely case of a tie, the first bidder to reveal wins.
* If this is not the highest bid, return the collateral to the bidder since they cannot win the auction.
* @inheritdoc BaseSealedBidAuction
*/
function _handleRevealedBid(address bidder, uint96 amount) internal virtual override {
uint96 currentHighestBid = highestBid;
// If the bid is the new highest bid, update highestBid and currentWinner, but also move the old highest bid to
// secondHighestBid
if (amount > currentHighestBid) {
highestBid = amount;
currentWinner = bidder;
secondHighestBid = currentHighestBid;
} else {
// If the bid is higher than the second-highest bid, we update the second-highest bid
if (amount > secondHighestBid) {
secondHighestBid = amount;
}
// And we return the collateral to the bidder, since they are not running to win the auction anyways
bids[bidder].collateral = 0;
(bool success,) = payable(bidder).call{value: amount}("");
require(success, "Withdraw failed");
}
}
/**
* @dev Computes the final price after the reveal phase ends.
* In a second-price auction, the winner pays the second-highest bid.
* @return finalPrice The amount the winner pays (0 if no winner)
*/
function _computeFinalPrice() internal virtual override returns (uint96) {
// If there are no revealed bids above the reserve price, return 0
if (currentWinner == address(0)) {
return 0;
}
return secondHighestBid;
}
}