HashLockEscrow

hashlockescrow · conditional-settlement · 2018 B runtime · funds-movement

scores

source

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

contract HashLockEscrow {
    struct Lock {
        address payee;
        uint256 amount;
        uint256 expiry;
        bytes32 hash;
    }

    mapping(address => Lock) public locks;

    bool private _locked;
    modifier nonReentrant() {
        require(!_locked, "reentrant");
        _locked = true;
        _;
        _locked = false;
    }

    event Deposit(address indexed depositor, address indexed payee, bytes32 indexed hash, uint256 amount, uint256 expiry);
    event Reveal(address indexed depositor, address indexed payee, uint256 amount);
    event Refund(address indexed depositor, uint256 amount);

    function deposit(bytes32 hash, address payee, uint256 duration) external payable {
        Lock storage lock = locks[msg.sender];
        require(lock.amount == 0, "active lock exists");
        require(payee != address(0), "payee zero");
        require(msg.value > 0, "zero amount");
        require(duration > 0, "zero duration");

        lock.payee = payee;
        lock.amount = msg.value;
        lock.expiry = block.timestamp + duration;
        lock.hash = hash;

        emit Deposit(msg.sender, payee, hash, msg.value, lock.expiry);
    }

    function reveal(bytes32 secret, address depositor) external nonReentrant {
        Lock storage lock = locks[depositor];
        require(lock.amount > 0, "no lock");
        require(msg.sender == lock.payee, "not payee");
        require(keccak256(abi.encodePacked(secret)) == lock.hash, "bad secret");

        uint256 amount = lock.amount;
        delete locks[depositor];

        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "transfer failed");

        emit Reveal(depositor, msg.sender, amount);
    }

    function refund() external nonReentrant {
        Lock storage lock = locks[msg.sender];
        require(lock.amount > 0, "no lock");
        require(block.timestamp > lock.expiry, "not expired");

        uint256 amount = lock.amount;
        delete locks[msg.sender];

        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "transfer failed");

        emit Refund(msg.sender, amount);
    }
}

published

published on testnet · 0x5cE18Ac544b0587648f1EB2aD194fA0426e1Ceac · tx 0xd4bc8aaa1530f4d1… · tempo (42431) · testnet