Hash Challenge Window

hash-challenge-window · conditional-settlement · 1564 B runtime · funds-movement

scores

source

pragma solidity ^0.8.13;

contract HashChallengeWindow {
    bytes32 public immutable claimedHash;
    address payable public immutable agent;
    uint256 public immutable challengeEndsAt;
    uint256 public immutable reward;
    bool public settled;

    event ClaimCreated(address indexed agent, bytes32 indexed claimedHash, uint256 challengeEndsAt, uint256 reward);
    event ChallengeSucceeded(address indexed challenger, bytes32 preimage, uint256 reward);
    event AgentWithdrawn(address indexed agent, uint256 reward);

    constructor(bytes32 _claimedHash, uint256 _challengeDuration) payable {
        require(msg.value > 0, "No reward provided");
        claimedHash = _claimedHash;
        agent = payable(msg.sender);
        challengeEndsAt = block.timestamp + _challengeDuration;
        reward = msg.value;
        emit ClaimCreated(msg.sender, _claimedHash, challengeEndsAt, msg.value);
    }

    function challenge(bytes32 preimage) external {
        require(!settled, "Already settled");
        require(block.timestamp < challengeEndsAt, "Challenge window expired");
        require(keccak256(abi.encodePacked(preimage)) == claimedHash, "Preimage does not match claimed hash");

        settled = true;
        emit ChallengeSucceeded(msg.sender, preimage, reward);
        payable(msg.sender).transfer(reward);
    }

    function withdraw() external {
        require(!settled, "Already settled");
        require(block.timestamp >= challengeEndsAt, "Challenge window still open");
        require(msg.sender == agent, "Only agent can withdraw");

        settled = true;
        emit AgentWithdrawn(agent, reward);
        agent.transfer(reward);
    }
}