RefundEscrow.sol 3.1 KB

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