| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 | // SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "./ConditionalEscrow.sol";/** * @title RefundEscrow * @dev Escrow that holds funds for a beneficiary, deposited from multiple * parties. * @dev Intended usage: See {Escrow}. Same usage guidelines apply here. * @dev The owner account (that is, the contract that instantiates this * contract) may deposit, close the deposit period, and allow for either * withdrawal by the beneficiary, or refunds to the depositors. All interactions * with `RefundEscrow` will be made through the owner contract. */contract RefundEscrow is ConditionalEscrow {    using Address for address payable;    enum State {        Active,        Refunding,        Closed    }    event RefundsClosed();    event RefundsEnabled();    State private _state;    address payable private immutable _beneficiary;    /**     * @dev Constructor.     * @param beneficiary_ The beneficiary of the deposits.     */    constructor(address payable beneficiary_) {        require(beneficiary_ != address(0), "RefundEscrow: beneficiary is the zero address");        _beneficiary = beneficiary_;        _state = State.Active;    }    /**     * @return The current state of the escrow.     */    function state() public view virtual returns (State) {        return _state;    }    /**     * @return The beneficiary of the escrow.     */    function beneficiary() public view virtual returns (address payable) {        return _beneficiary;    }    /**     * @dev Stores funds that may later be refunded.     * @param refundee The address funds will be sent to if a refund occurs.     */    function deposit(address refundee) public payable virtual override {        require(state() == State.Active, "RefundEscrow: can only deposit while active");        super.deposit(refundee);    }    /**     * @dev Allows for the beneficiary to withdraw their funds, rejecting     * further deposits.     */    function close() public virtual onlyOwner {        require(state() == State.Active, "RefundEscrow: can only close while active");        _state = State.Closed;        emit RefundsClosed();    }    /**     * @dev Allows for refunds to take place, rejecting further deposits.     */    function enableRefunds() public virtual onlyOwner {        require(state() == State.Active, "RefundEscrow: can only enable refunds while active");        _state = State.Refunding;        emit RefundsEnabled();    }    /**     * @dev Withdraws the beneficiary's funds.     */    function beneficiaryWithdraw() public virtual {        require(state() == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");        beneficiary().sendValue(address(this).balance);    }    /**     * @dev Returns whether refundees can withdraw their deposits (be refunded). The overridden function receives a     * 'payee' argument, but we ignore it here since the condition is global, not per-payee.     */    function withdrawalAllowed(address) public view override returns (bool) {        return state() == State.Refunding;    }}
 |