TokenVesting.sol 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* solium-disable security/no-block-members */
  2. pragma solidity ^0.5.0;
  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 TokensReleased(address token, uint256 amount);
  16. event TokenVestingRevoked(address token);
  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 (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public {
  36. require(beneficiary != address(0));
  37. require(cliffDuration <= duration);
  38. require(duration > 0);
  39. require(start.add(duration) > block.timestamp);
  40. _beneficiary = beneficiary;
  41. _revocable = revocable;
  42. _duration = duration;
  43. _cliff = start.add(cliffDuration);
  44. _start = start;
  45. }
  46. /**
  47. * @return the beneficiary of the tokens.
  48. */
  49. function beneficiary() public view returns (address) {
  50. return _beneficiary;
  51. }
  52. /**
  53. * @return the cliff time of the token vesting.
  54. */
  55. function cliff() public view returns (uint256) {
  56. return _cliff;
  57. }
  58. /**
  59. * @return the start time of the token vesting.
  60. */
  61. function start() public view returns (uint256) {
  62. return _start;
  63. }
  64. /**
  65. * @return the duration of the token vesting.
  66. */
  67. function duration() public view returns (uint256) {
  68. return _duration;
  69. }
  70. /**
  71. * @return true if the vesting is revocable.
  72. */
  73. function revocable() public view returns (bool) {
  74. return _revocable;
  75. }
  76. /**
  77. * @return the amount of the token released.
  78. */
  79. function released(address token) public view returns (uint256) {
  80. return _released[token];
  81. }
  82. /**
  83. * @return true if the token is revoked.
  84. */
  85. function revoked(address token) public view returns (bool) {
  86. return _revoked[token];
  87. }
  88. /**
  89. * @notice Transfers vested tokens to beneficiary.
  90. * @param token ERC20 token which is being vested
  91. */
  92. function release(IERC20 token) public {
  93. uint256 unreleased = _releasableAmount(token);
  94. require(unreleased > 0);
  95. _released[address(token)] = _released[address(token)].add(unreleased);
  96. token.safeTransfer(_beneficiary, unreleased);
  97. emit TokensReleased(address(token), unreleased);
  98. }
  99. /**
  100. * @notice Allows the owner to revoke the vesting. Tokens already vested
  101. * remain in the contract, the rest are returned to the owner.
  102. * @param token ERC20 token which is being vested
  103. */
  104. function revoke(IERC20 token) public onlyOwner {
  105. require(_revocable);
  106. require(!_revoked[address(token)]);
  107. uint256 balance = token.balanceOf(address(this));
  108. uint256 unreleased = _releasableAmount(token);
  109. uint256 refund = balance.sub(unreleased);
  110. _revoked[address(token)] = true;
  111. token.safeTransfer(owner(), refund);
  112. emit TokenVestingRevoked(address(token));
  113. }
  114. /**
  115. * @dev Calculates the amount that has already vested but hasn't been released yet.
  116. * @param token ERC20 token which is being vested
  117. */
  118. function _releasableAmount(IERC20 token) private view returns (uint256) {
  119. return _vestedAmount(token).sub(_released[address(token)]);
  120. }
  121. /**
  122. * @dev Calculates the amount that has already vested.
  123. * @param token ERC20 token which is being vested
  124. */
  125. function _vestedAmount(IERC20 token) private view returns (uint256) {
  126. uint256 currentBalance = token.balanceOf(address(this));
  127. uint256 totalBalance = currentBalance.add(_released[address(token)]);
  128. if (block.timestamp < _cliff) {
  129. return 0;
  130. } else if (block.timestamp >= _start.add(_duration) || _revoked[address(token)]) {
  131. return totalBalance;
  132. } else {
  133. return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
  134. }
  135. }
  136. }