Block Slot Auction

block-slot-auction · auction-allocation · 1415 B runtime · funds-movement

scores

source

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract BlockSlotAuction {
    mapping(uint256 => address) public winnerOfSlot;
    uint256 public activeSlot;
    address public activeBidder;
    uint256 public activeBid;
    mapping(address => uint256) public refunds;

    event Bid(address indexed bidder, uint256 amount, uint256 targetBlock);
    event SlotWinner(uint256 indexed blockNumber, address indexed winner, uint256 bid);
    event Executed(uint256 indexed blockNumber, address indexed executor);

    function bid() external payable {
        _finalizePriorSlot();
        uint256 target = block.number + 1;
        if (activeSlot != target) {
            activeSlot = target;
            activeBidder = address(0);
            activeBid = 0;
        }
        require(msg.value > activeBid, 'bid too low');
        if (activeBidder != address(0)) {
            refunds[activeBidder] += activeBid;
        }
        activeBidder = msg.sender;
        activeBid = msg.value;
        emit Bid(msg.sender, msg.value, target);
    }

    function execute() external {
        _finalizePriorSlot();
        require(winnerOfSlot[block.number] == msg.sender, 'not winner');
        emit Executed(block.number, msg.sender);
    }

    function withdraw() external {
        uint256 amount = refunds[msg.sender];
        require(amount > 0, 'no refund');
        refunds[msg.sender] = 0;
        (bool ok, ) = msg.sender.call{value: amount}('');
        require(ok, 'transfer failed');
    }

    function _finalizePriorSlot() private {
        if (activeSlot == 0 || activeSlot > block.number) return;
        if (winnerOfSlot[activeSlot] == address(0)) {
            winnerOfSlot[activeSlot] = activeBidder;
            emit SlotWinner(activeSlot, activeBidder, activeBid);
        }
        activeBidder = address(0);
        activeBid = 0;
        activeSlot = 0;
    }
}