Time-Slice Renting Auction
time-slice-renting-auction · auction-allocation · 2654 B runtime · funds-movement
scores
- usefulness: 70
- safety: 40
- liveness: 40
- authenticity: 70
- extensibility: 50
- bytecodeDiscipline: 80
- practical: 57
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract TimeSliceRentingAuction {
struct Slot {
uint256 startBlock;
uint256 endBlock;
address feeReceiver;
address winner;
uint256 highestBid;
bool resolved;
}
uint256 public nextSlotId;
mapping(uint256 => Slot) public slots;
mapping(uint256 => mapping(address => uint256)) public bids;
event SlotCreated(uint256 indexed slotId, uint256 startBlock, uint256 endBlock, address feeReceiver);
event Bid(uint256 indexed slotId, address indexed bidder, uint256 amount, uint256 totalBid);
event Resolved(uint256 indexed slotId, address winner, uint256 amount);
event Withdraw(uint256 indexed slotId, address indexed bidder, uint256 amount);
event Use(uint256 indexed slotId, address indexed user, uint256 blockNumber);
function createSlot(uint256 startBlock, uint256 endBlock, address feeReceiver) external returns (uint256 slotId) {
require(endBlock >= startBlock, "end<start");
require(startBlock > block.number + 5, "start too soon");
require(feeReceiver != address(0), "feeReceiver=0");
slotId = nextSlotId++;
slots[slotId] = Slot(startBlock, endBlock, feeReceiver, address(0), 0, false);
emit SlotCreated(slotId, startBlock, endBlock, feeReceiver);
}
function bid(uint256 slotId) external payable {
Slot storage slot = slots[slotId];
require(block.number <= auctionEnd(slot), "auction ended");
require(msg.value > 0, "zero bid");
uint256 newTotal = bids[slotId][msg.sender] + msg.value;
bids[slotId][msg.sender] = newTotal;
if (newTotal > slot.highestBid) {
slot.highestBid = newTotal;
slot.winner = msg.sender;
}
emit Bid(slotId, msg.sender, msg.value, newTotal);
}
function resolve(uint256 slotId) external {
Slot storage slot = slots[slotId];
require(!slot.resolved, "already resolved");
require(block.number > auctionEnd(slot), "auction still open");
slot.resolved = true;
uint256 amount = slot.highestBid;
emit Resolved(slotId, slot.winner, amount);
if (amount > 0) {
payable(slot.feeReceiver).transfer(amount);
}
}
function withdraw(uint256 slotId) external {
Slot storage slot = slots[slotId];
require(slot.resolved || block.number > auctionEnd(slot), "auction active");
require(msg.sender != slot.winner, "winner locked");
uint256 amount = bids[slotId][msg.sender];
require(amount > 0, "no bid");
bids[slotId][msg.sender] = 0;
emit Withdraw(slotId, msg.sender, amount);
payable(msg.sender).transfer(amount);
}
function use(uint256 slotId) external {
Slot storage slot = slots[slotId];
require(slot.resolved, "not resolved");
require(msg.sender == slot.winner, "not winner");
require(block.number >= slot.startBlock && block.number <= slot.endBlock, "time slot not active");
emit Use(slotId, msg.sender, block.number);
}
function auctionEnd(Slot storage slot) internal view returns (uint256) {
return slot.startBlock - 5;
}
}