RefundEscrow.sol 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "./ConditionalEscrow.sol";
  4. /**
  5. * @title RefundEscrow
  6. * @dev Escrow that holds funds for a beneficiary, deposited from multiple
  7. * parties.
  8. * @dev Intended usage: See {Escrow}. Same usage guidelines apply here.
  9. * @dev The owner account (that is, the contract that instantiates this
  10. * contract) may deposit, close the deposit period, and allow for either
  11. * withdrawal by the beneficiary, or refunds to the depositors. All interactions
  12. * with `RefundEscrow` will be made through the owner contract.
  13. */
  14. contract RefundEscrow is ConditionalEscrow {
  15. using Address for address payable;
  16. enum State {
  17. Active,
  18. Refunding,
  19. Closed
  20. }
  21. event RefundsClosed();
  22. event RefundsEnabled();
  23. State private _state;
  24. address payable private immutable _beneficiary;
  25. /**
  26. * @dev Constructor.
  27. * @param beneficiary_ The beneficiary of the deposits.
  28. */
  29. constructor(address payable beneficiary_) {
  30. require(beneficiary_ != address(0), "RefundEscrow: beneficiary is the zero address");
  31. _beneficiary = beneficiary_;
  32. _state = State.Active;
  33. }
  34. /**
  35. * @return The current state of the escrow.
  36. */
  37. function state() public view virtual returns (State) {
  38. return _state;
  39. }
  40. /**
  41. * @return The beneficiary of the escrow.
  42. */
  43. function beneficiary() public view virtual returns (address payable) {
  44. return _beneficiary;
  45. }
  46. /**
  47. * @dev Stores funds that may later be refunded.
  48. * @param refundee The address funds will be sent to if a refund occurs.
  49. */
  50. function deposit(address refundee) public payable virtual override {
  51. require(state() == State.Active, "RefundEscrow: can only deposit while active");
  52. super.deposit(refundee);
  53. }
  54. /**
  55. * @dev Allows for the beneficiary to withdraw their funds, rejecting
  56. * further deposits.
  57. */
  58. function close() public virtual onlyOwner {
  59. require(state() == State.Active, "RefundEscrow: can only close while active");
  60. _state = State.Closed;
  61. emit RefundsClosed();
  62. }
  63. /**
  64. * @dev Allows for refunds to take place, rejecting further deposits.
  65. */
  66. function enableRefunds() public virtual onlyOwner {
  67. require(state() == State.Active, "RefundEscrow: can only enable refunds while active");
  68. _state = State.Refunding;
  69. emit RefundsEnabled();
  70. }
  71. /**
  72. * @dev Withdraws the beneficiary's funds.
  73. */
  74. function beneficiaryWithdraw() public virtual {
  75. require(state() == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
  76. beneficiary().sendValue(address(this).balance);
  77. }
  78. /**
  79. * @dev Returns whether refundees can withdraw their deposits (be refunded). The overridden function receives a
  80. * 'payee' argument, but we ignore it here since the condition is global, not per-payee.
  81. */
  82. function withdrawalAllowed(address) public view override returns (bool) {
  83. return state() == State.Refunding;
  84. }
  85. }