PostDeliveryCrowdsale.sol 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. pragma solidity ^0.5.0;
  2. import "../validation/TimedCrowdsale.sol";
  3. import "../../math/SafeMath.sol";
  4. import "../../ownership/Secondary.sol";
  5. import "../../token/ERC20/IERC20.sol";
  6. /**
  7. * @title PostDeliveryCrowdsale
  8. * @dev Crowdsale that locks tokens from withdrawal until it ends.
  9. */
  10. contract PostDeliveryCrowdsale is TimedCrowdsale {
  11. using SafeMath for uint256;
  12. mapping(address => uint256) private _balances;
  13. __unstable__TokenVault private _vault;
  14. constructor() public {
  15. _vault = new __unstable__TokenVault();
  16. }
  17. /**
  18. * @dev Withdraw tokens only after crowdsale ends.
  19. * @param beneficiary Whose tokens will be withdrawn.
  20. */
  21. function withdrawTokens(address beneficiary) public {
  22. require(hasClosed(), "PostDeliveryCrowdsale: not closed");
  23. uint256 amount = _balances[beneficiary];
  24. require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");
  25. _balances[beneficiary] = 0;
  26. _vault.transfer(token(), beneficiary, amount);
  27. }
  28. /**
  29. * @return the balance of an account.
  30. */
  31. function balanceOf(address account) public view returns (uint256) {
  32. return _balances[account];
  33. }
  34. /**
  35. * @dev Overrides parent by storing due balances, and delivering tokens to the vault instead of the end user. This
  36. * ensures that the tokens will be available by the time they are withdrawn (which may not be the case if
  37. * `_deliverTokens` was called later).
  38. * @param beneficiary Token purchaser
  39. * @param tokenAmount Amount of tokens purchased
  40. */
  41. function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
  42. _balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
  43. _deliverTokens(address(_vault), tokenAmount);
  44. }
  45. }
  46. /**
  47. * @title __unstable__TokenVault
  48. * @dev Similar to an Escrow for tokens, this contract allows its primary account to spend its tokens as it sees fit.
  49. * This contract is an internal helper for PostDeliveryCrowdsale, and should not be used outside of this context.
  50. */
  51. // solhint-disable-next-line contract-name-camelcase
  52. contract __unstable__TokenVault is Secondary {
  53. function transfer(IERC20 token, address to, uint256 amount) public onlyPrimary {
  54. token.transfer(to, amount);
  55. }
  56. }