RefundableCrowdsale.sol 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. pragma solidity ^0.4.24;
  2. import "../../math/SafeMath.sol";
  3. import "./FinalizableCrowdsale.sol";
  4. import "../../payment/escrow/RefundEscrow.sol";
  5. /**
  6. * @title RefundableCrowdsale
  7. * @dev Extension of Crowdsale contract that adds a funding goal, and
  8. * the possibility of users getting a refund if goal is not met.
  9. * WARNING: note that if you allow tokens to be traded before the goal
  10. * is met, then an attack is possible in which the attacker purchases
  11. * tokens from the crowdsale and when they sees that the goal is
  12. * unlikely to be met, they sell their tokens (possibly at a discount).
  13. * The attacker will be refunded when the crowdsale is finalized, and
  14. * the users that purchased from them will be left with worthless
  15. * tokens. There are many possible ways to avoid this, like making the
  16. * the crowdsale inherit from PostDeliveryCrowdsale, or imposing
  17. * restrictions on token trading until the crowdsale is finalized.
  18. * This is being discussed in
  19. * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877
  20. * This contract will be updated when we agree on a general solution
  21. * for this problem.
  22. */
  23. contract RefundableCrowdsale is FinalizableCrowdsale {
  24. using SafeMath for uint256;
  25. // minimum amount of funds to be raised in weis
  26. uint256 private _goal;
  27. // refund escrow used to hold funds while crowdsale is running
  28. RefundEscrow private _escrow;
  29. /**
  30. * @dev Constructor, creates RefundEscrow.
  31. * @param goal Funding goal
  32. */
  33. constructor(uint256 goal) internal {
  34. require(goal > 0);
  35. _escrow = new RefundEscrow(wallet());
  36. _goal = goal;
  37. }
  38. /**
  39. * @return minimum amount of funds to be raised in wei.
  40. */
  41. function goal() public view returns(uint256) {
  42. return _goal;
  43. }
  44. /**
  45. * @dev Investors can claim refunds here if crowdsale is unsuccessful
  46. * @param beneficiary Whose refund will be claimed.
  47. */
  48. function claimRefund(address beneficiary) public {
  49. require(finalized());
  50. require(!goalReached());
  51. _escrow.withdraw(beneficiary);
  52. }
  53. /**
  54. * @dev Checks whether funding goal was reached.
  55. * @return Whether funding goal was reached
  56. */
  57. function goalReached() public view returns (bool) {
  58. return weiRaised() >= _goal;
  59. }
  60. /**
  61. * @dev escrow finalization task, called when finalize() is called
  62. */
  63. function _finalization() internal {
  64. if (goalReached()) {
  65. _escrow.close();
  66. _escrow.beneficiaryWithdraw();
  67. } else {
  68. _escrow.enableRefunds();
  69. }
  70. super._finalization();
  71. }
  72. /**
  73. * @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
  74. */
  75. function _forwardFunds() internal {
  76. _escrow.deposit.value(msg.value)(msg.sender);
  77. }
  78. }