Reusable Hash Time Locked Escrow

reusable-hash-time-locked-escrow · conditional-settlement · 2387 B runtime · funds-movement

scores

source

pragma solidity ^0.8.13;

contract ReusableHTLC {
    address public funder;
    address public recipient;
    bytes32 public hashLock;
    uint256 public timeout;
    uint256 public amount;
    bool public settled;

    constructor() {
        funder = msg.sender;
    }

    function fund() external payable {
        require(msg.sender == funder, "not funder");
        require(recipient == address(0), "active lock");
        amount += msg.value;
    }

    function lock(address _recipient, bytes32 _hashLock, uint256 _timeout) external payable {
        require(msg.sender == funder, "not funder");
        require(recipient == address(0), "active lock");
        require(_recipient != address(0), "bad recipient");
        require(_timeout > block.timestamp, "bad timeout");
        amount += msg.value;
        require(amount > 0, "zero amount");
        recipient = _recipient;
        hashLock = _hashLock;
        timeout = _timeout;
        settled = false;
    }

    function claim(bytes32 preimage) external {
        require(!settled, "settled");
        require(recipient != address(0), "no lock");
        require(block.timestamp < timeout, "expired");
        require(keccak256(abi.encodePacked(preimage)) == hashLock, "bad preimage");
        settled = true;
        address payable payee = payable(recipient);
        uint256 value = amount;
        amount = 0;
        recipient = address(0);
        (bool ok, ) = payee.call{value: value}("");
        require(ok, "transfer failed");
    }

    function refund() external {
        require(msg.sender == funder, "not funder");
        require(!settled, "settled");
        require(recipient != address(0), "no lock");
        require(block.timestamp >= timeout, "not expired");
        settled = true;
        uint256 value = amount;
        amount = 0;
        recipient = address(0);
        (bool ok, ) = payable(funder).call{value: value}("");
        require(ok, "transfer failed");
    }

    function relock(bytes32 newHashLock, uint256 newTimeout) external {
        require(msg.sender == funder, "not funder");
        require(!settled, "settled");
        require(recipient != address(0), "no lock");
        require(block.timestamp >= timeout, "not expired");
        require(newTimeout > block.timestamp, "bad timeout");
        hashLock = newHashLock;
        timeout = newTimeout;
    }
}

published

published on testnet · 0x4f28b60e7080a03474eaef701ec99b033d8a157A · tx 0x85f7efc3eaf094b8… · base (84532) · testnet · source as deployed