Bitmap Slot Auction
bitmap-slot-auction · auction-allocation · 1769 B runtime · funds-movement
scores
- usefulness: 100
- safety: 70
- liveness: 20
- authenticity: 15
- extensibility: 30
- bytecodeDiscipline: 85
- practical: 72
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract BitmapSlotAuction {
address public immutable beneficiary;
uint256[32] private bids;
address[32] private bidders;
uint8 public bidCount;
bool public settled;
address public winner;
uint256 public winningBid;
uint256 public price;
uint8 public awardedSlot;
event Bid(address indexed bidder, uint256 bidMask, uint8 indexed index);
event Claimed(address indexed winner, uint8 indexed slot, uint256 price);
constructor(address _beneficiary) {
require(_beneficiary != address(0), "beneficiary zero");
beneficiary = _beneficiary;
}
/// @notice Place a bid. `packed` is both the bid amount and the 256-bit mask.
function bid(uint256 packed) external {
require(!settled, "settled");
require(bidCount < 32, "full");
require(packed != 0, "zero");
bids[bidCount] = packed;
bidders[bidCount] = msg.sender;
emit Bid(msg.sender, packed, bidCount);
bidCount++;
}
/// @notice Settle: the highest bidder (first if tied) wins, pays the second-highest bid,
/// and receives the lowest set bit of their mask as the awarded slot.
function claim() external payable {
require(!settled, "settled");
require(bidCount > 0, "empty");
address topBidder;
uint256 top;
uint256 second;
for (uint8 i = 0; i < bidCount; i++) {
uint256 b = bids[i];
if (b > top) {
second = top;
top = b;
topBidder = bidders[i];
} else if (b > second) {
second = b;
}
}
require(msg.sender == topBidder, "not winner");
require(msg.value == second, "payment");
settled = true;
winner = topBidder;
winningBid = top;
price = second;
awardedSlot = _lowestSetBit(top);
if (second > 0) {
(bool ok,) = beneficiary.call{value: second}("");
require(ok, "transfer failed");
}
emit Claimed(msg.sender, awardedSlot, second);
}
function _lowestSetBit(uint256 x) internal pure returns (uint8 index) {
while ((x & 1) == 0) {
x >>= 1;
index++;
}
}
}