Silence-Approve Settlement

silence-approve-settlement · conditional-settlement · 2017 B runtime · funds-movement

scores

source

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

contract SilenceApproveSettlement {
    struct Payment {
        address payer;
        address payable agent;
        uint256 amount;
        uint256 deadline;
        bool disputed;
        bool claimed;
    }

    mapping(uint256 => Payment) public payments;
    uint256 private nextPaymentId;

    event PaymentCreated(uint256 indexed paymentId, address indexed payer, address indexed agent, uint256 amount, uint256 deadline);
    event Claimed(uint256 indexed paymentId, address indexed agent, uint256 amount);
    event Disputed(uint256 indexed paymentId, address indexed disputer);
    event Released(uint256 indexed paymentId, address indexed payer, address indexed agent, uint256 amount);

    function depositFor(address payable agent, uint256 deadline)
        external
        payable
        returns (uint256 paymentId)
    {
        require(msg.value > 0, "Amount zero");
        require(deadline > block.timestamp, "Deadline past");

        paymentId = nextPaymentId++;
        payments[paymentId] = Payment({
            payer: msg.sender,
            agent: agent,
            amount: msg.value,
            deadline: deadline,
            disputed: false,
            claimed: false
        });

        emit PaymentCreated(paymentId, msg.sender, agent, msg.value, deadline);
    }

    function claim(uint256 paymentId) external {
        Payment storage p = payments[paymentId];
        require(msg.sender == p.agent, "Not agent");
        require(!p.claimed, "Already claimed");
        require(!p.disputed, "Disputed");
        require(block.timestamp > p.deadline, "Before deadline");

        p.claimed = true;
        p.agent.transfer(p.amount);
        emit Claimed(paymentId, p.agent, p.amount);
    }

    function dispute(uint256 paymentId) external {
        Payment storage p = payments[paymentId];
        require(!p.claimed, "Already claimed");
        require(!p.disputed, "Already disputed");
        require(block.timestamp < p.deadline, "After deadline");

        p.disputed = true;
        emit Disputed(paymentId, msg.sender);
    }

    function release(uint256 paymentId) external {
        Payment storage p = payments[paymentId];
        require(msg.sender == p.payer, "Not payer");
        require(p.disputed, "Not disputed");
        require(!p.claimed, "Already claimed");

        p.claimed = true;
        p.agent.transfer(p.amount);
        emit Released(paymentId, msg.sender, p.agent, p.amount);
    }
}