Threshold-Triggered Payment Vault

threshold-triggered-payment-vault · conditional-settlement · 1961 B runtime · funds-movement

scores

source

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

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

contract ThresholdVault {
    IERC20 public immutable token;
    address public immutable target;
    address public immutable beneficiary;
    address public immutable depositor;
    uint256 public immutable amount;
    uint256 public immutable threshold;
    uint256 public immutable deadline;

    uint8 private status; // 0 = pending, 1 = released, 2 = refunded

    event Released(uint256 amount);
    event Refunded(uint256 amount);

    constructor(
        IERC20 _token,
        address _target,
        address _beneficiary,
        uint256 _amount,
        uint256 _threshold,
        uint256 _deadline
    ) {
        require(address(_token) != address(0), 'zero token');
        require(_target != address(0), 'zero target');
        require(_beneficiary != address(0), 'zero beneficiary');
        require(_amount > 0, 'zero amount');
        require(_deadline > block.timestamp, 'deadline past');

        token = _token;
        target = _target;
        beneficiary = _beneficiary;
        depositor = msg.sender;
        amount = _amount;
        threshold = _threshold;
        deadline = _deadline;

        require(_token.transferFrom(msg.sender, address(this), _amount), 'deposit failed');
    }

    function release() external {
        require(status == 0, 'finalized');
        require(block.timestamp < deadline, 'deadline passed');
        require(token.balanceOf(target) >= threshold, 'threshold not met');

        status = 1;
        require(token.transfer(beneficiary, amount), 'release transfer failed');
        emit Released(amount);
    }

    function refund() external {
        require(status == 0, 'finalized');
        require(block.timestamp >= deadline, 'deadline active');

        status = 2;
        require(token.transfer(depositor, amount), 'refund transfer failed');
        emit Refunded(amount);
    }
}