Random-Deadline Sealed-Bid Auction
random-deadline-sealed-bid-auction · auction-allocation · 2619 B runtime · funds-movement
scores
- usefulness: 45
- safety: 30
- liveness: 35
- authenticity: 30
- extensibility: 60
- bytecodeDiscipline: 75
- practical: 44
source
pragma solidity ^0.8.13;
contract RandomDeadlineAuction {
uint256 public constant MAX_LIFETIME = 256;
uint256 public constant REVEAL_WINDOW = 64;
uint256 public constant MAX_BIDS = 256;
struct Bid {
address payable bidder;
uint96 amount;
bytes32 commitment;
bool revealed;
bool refunded;
}
address payable public beneficiary;
uint256 public closingBlock;
uint256 public revealEnd;
Bid[] public bids;
bool public settled;
address public winner;
uint256 public winningAmount;
event Committed(address indexed bidder, uint256 indexed id);
event Revealed(address indexed bidder, uint256 indexed id, uint256 amount);
event Refunded(address indexed bidder, uint256 indexed id, uint256 amount);
event Settled(address indexed winner, uint256 amount);
constructor(address payable _beneficiary) {
beneficiary = _beneficiary;
uint256 random = uint256(blockhash(block.number));
if (random == 0) {
random = uint256(blockhash(block.number - 1));
}
closingBlock = block.number + (random % MAX_LIFETIME) + 1;
revealEnd = closingBlock + REVEAL_WINDOW;
}
function commit(bytes32 commitment) external payable {
require(block.number < closingBlock);
require(bids.length < MAX_BIDS);
require(msg.value > 0);
bids.push(Bid(payable(msg.sender), uint96(msg.value), commitment, false, false));
emit Committed(msg.sender, bids.length - 1);
}
function reveal(uint256 id, uint256 amount, string calldata secret) external {
require(block.number >= closingBlock && block.number <= revealEnd);
require(id < bids.length);
Bid storage b = bids[id];
require(msg.sender == b.bidder);
require(!b.revealed);
require(amount == b.amount);
require(keccak256(abi.encodePacked(msg.sender, amount, secret)) == b.commitment);
b.revealed = true;
emit Revealed(msg.sender, id, amount);
}
function settle() external {
require(block.number > revealEnd);
require(!settled);
uint256 best;
for (uint256 i = 0; i < bids.length; i++) {
if (bids[i].revealed && bids[i].amount > best) {
best = bids[i].amount;
winner = bids[i].bidder;
winningAmount = best;
}
}
settled = true;
if (winningAmount > 0) {
(bool ok, ) = beneficiary.call{value: winningAmount}("");
require(ok);
}
emit Settled(winner, winningAmount);
}
function refund(uint256 id) external {
require(settled);
require(id < bids.length);
Bid storage b = bids[id];
require(b.bidder != winner);
require(!b.refunded);
b.refunded = true;
(bool ok, ) = b.bidder.call{value: b.amount}("");
require(ok);
emit Refunded(b.bidder, id, b.amount);
}
}