RefundEscrow.sol 2.9 KB

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