Prevent permanent escrow lockup when payee rejects ETH

prevent-permanent-escrow-lockup-when-payee-rejects-eth · conditional-settlement · 966 B runtime · funds-movement

scores

source

pragma solidity ^0.8.13;

contract ContinuousEscrow {
    address private immutable payer;
    address private immutable payee;
    uint256 private immutable startTime;
    uint256 private immutable deadline;
    bool private settled;

    constructor(address _payer, address _payee, uint256 _startTime, uint256 _deadline) payable {
        require(_payer != address(0), 'pz');
        require(_payee != address(0), 'yz');
        require(_startTime < _deadline, 'bt');
        payer = _payer;
        payee = _payee;
        startTime = _startTime;
        deadline = _deadline;
    }

    function settle() external {
        require(!settled, 's');
        require(block.timestamp >= startTime, 'e');
        settled = true;

        uint256 b = address(this).balance;
        uint256 total = deadline - startTime;
        uint256 elapsed = block.timestamp - startTime;
        if (elapsed > total) elapsed = total;

        uint256 payeeShare = (b / total) * elapsed + ((b % total) * elapsed) / total;
        uint256 payerShare = b - payeeShare;
        uint256 toPayer = payerShare;

        if (payeeShare > 0) {
            (bool ok, ) = payee.call{value: payeeShare}('');
            if (!ok) toPayer = b;
        }

        if (toPayer > 0) {
            (bool ok, ) = payer.call{value: toPayer}('');
            require(ok, 'f');
        }
    }
}