TokenVesting.sol 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. }