Time-Decayed Payout

time-decayed-payout · conditional-settlement · 2178 B runtime · funds-movement

scores

source

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

contract TimeDecayedPayout {
    address public immutable depositor;
    address public immutable beneficiary;
    uint256 public immutable start;
    uint256 public immutable deadline;
    uint256 public immutable principal;

    bool public claimed;
    bool public refunded;

    event Claimed(address indexed beneficiary, uint256 amount);
    event Refunded(address indexed depositor, uint256 amount);

    constructor(address _beneficiary, uint256 _duration) payable {
        require(_duration > 0, "duration-zero");
        require(_beneficiary != address(0), "beneficiary-zero");
        require(msg.value > 0, "principal-zero");

        depositor = msg.sender;
        beneficiary = _beneficiary;
        start = block.timestamp;
        deadline = block.timestamp + _duration;
        principal = msg.value;
    }

    function claim() external {
        require(msg.sender == beneficiary, "not-beneficiary");
        require(!claimed, "already-claimed");
        require(block.timestamp < deadline, "after-deadline");

        uint256 payout = _payoutAt(block.timestamp);
        require(payout > 0, "zero-payout");

        claimed = true;
        (bool ok, ) = beneficiary.call{value: payout}("");
        require(ok, "transfer-failed");

        emit Claimed(beneficiary, payout);
    }

    function refund() external {
        require(msg.sender == depositor, "not-depositor");
        require(!refunded, "already-refunded");
        require(block.timestamp >= deadline, "before-deadline");

        refunded = true;
        uint256 amount = address(this).balance;
        (bool ok, ) = depositor.call{value: amount}("");
        require(ok, "transfer-failed");

        emit Refunded(depositor, amount);
    }

    function _payoutAt(uint256 t) internal view returns (uint256) {
        uint256 numerator = principal * (deadline - t);
        uint256 denominator = deadline - start;
        return numerator / denominator;
    }

    receive() external payable {
        revert("no-direct-eth");
    }
}

published

published on testnet · 0xe5F0838155a006eF6bed668be0D59ac95384c8ec · tx 0xdcfb96f2a801376f… · base (84532) · testnet · source as deployed