TokenVesting.sol 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* solium-disable security/no-block-members */
  2. pragma solidity ^0.4.24;
  3. import "../token/ERC20/SafeERC20.sol";
  4. import "../ownership/Ownable.sol";
  5. import "../math/SafeMath.sol";
  6. /**
  7. * @title TokenVesting
  8. * @dev A token holder contract that can release its token balance gradually like a
  9. * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
  10. * owner.
  11. */
  12. contract TokenVesting is Ownable {
  13. using SafeMath for uint256;
  14. using SafeERC20 for IERC20;
  15. event Released(uint256 amount);
  16. event Revoked();
  17. // beneficiary of tokens after they are released
  18. address private beneficiary_;
  19. uint256 private cliff_;
  20. uint256 private start_;
  21. uint256 private duration_;
  22. bool private revocable_;
  23. mapping (address => uint256) private released_;
  24. mapping (address => bool) private revoked_;
  25. /**
  26. * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
  27. * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
  28. * of the balance will have vested.
  29. * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
  30. * @param _cliffDuration duration in seconds of the cliff in which tokens will begin to vest
  31. * @param _start the time (as Unix time) at which point vesting starts
  32. * @param _duration duration in seconds of the period in which the tokens will vest
  33. * @param _revocable whether the vesting is revocable or not
  34. */
  35. constructor(
  36. address _beneficiary,
  37. uint256 _start,
  38. uint256 _cliffDuration,
  39. uint256 _duration,
  40. bool _revocable
  41. )
  42. public
  43. {
  44. require(_beneficiary != address(0));
  45. require(_cliffDuration <= _duration);
  46. beneficiary_ = _beneficiary;
  47. revocable_ = _revocable;
  48. duration_ = _duration;
  49. cliff_ = _start.add(_cliffDuration);
  50. start_ = _start;
  51. }
  52. /**
  53. * @return the beneficiary of the tokens.
  54. */
  55. function beneficiary() public view returns(address) {
  56. return beneficiary_;
  57. }
  58. /**
  59. * @return the cliff time of the token vesting.
  60. */
  61. function cliff() public view returns(uint256) {
  62. return cliff_;
  63. }
  64. /**
  65. * @return the start time of the token vesting.
  66. */
  67. function start() public view returns(uint256) {
  68. return start_;
  69. }
  70. /**
  71. * @return the duration of the token vesting.
  72. */
  73. function duration() public view returns(uint256) {
  74. return duration_;
  75. }
  76. /**
  77. * @return true if the vesting is revocable.
  78. */
  79. function revocable() public view returns(bool) {
  80. return revocable_;
  81. }
  82. /**
  83. * @return the amount of the token released.
  84. */
  85. function released(address _token) public view returns(uint256) {
  86. return released_[_token];
  87. }
  88. /**
  89. * @return true if the token is revoked.
  90. */
  91. function revoked(address _token) public view returns(bool) {
  92. return revoked_[_token];
  93. }
  94. /**
  95. * @notice Transfers vested tokens to beneficiary.
  96. * @param _token ERC20 token which is being vested
  97. */
  98. function release(IERC20 _token) public {
  99. uint256 unreleased = releasableAmount(_token);
  100. require(unreleased > 0);
  101. released_[_token] = released_[_token].add(unreleased);
  102. _token.safeTransfer(beneficiary_, unreleased);
  103. emit Released(unreleased);
  104. }
  105. /**
  106. * @notice Allows the owner to revoke the vesting. Tokens already vested
  107. * remain in the contract, the rest are returned to the owner.
  108. * @param _token ERC20 token which is being vested
  109. */
  110. function revoke(IERC20 _token) public onlyOwner {
  111. require(revocable_);
  112. require(!revoked_[_token]);
  113. uint256 balance = _token.balanceOf(address(this));
  114. uint256 unreleased = releasableAmount(_token);
  115. uint256 refund = balance.sub(unreleased);
  116. revoked_[_token] = true;
  117. _token.safeTransfer(owner(), refund);
  118. emit Revoked();
  119. }
  120. /**
  121. * @dev Calculates the amount that has already vested but hasn't been released yet.
  122. * @param _token ERC20 token which is being vested
  123. */
  124. function releasableAmount(IERC20 _token) public view returns (uint256) {
  125. return vestedAmount(_token).sub(released_[_token]);
  126. }
  127. /**
  128. * @dev Calculates the amount that has already vested.
  129. * @param _token ERC20 token which is being vested
  130. */
  131. function vestedAmount(IERC20 _token) public view returns (uint256) {
  132. uint256 currentBalance = _token.balanceOf(this);
  133. uint256 totalBalance = currentBalance.add(released_[_token]);
  134. if (block.timestamp < cliff_) {
  135. return 0;
  136. } else if (block.timestamp >= start_.add(duration_) || revoked_[_token]) {
  137. return totalBalance;
  138. } else {
  139. return totalBalance.mul(block.timestamp.sub(start_)).div(duration_);
  140. }
  141. }
  142. }