TokenVesting.sol 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. pragma solidity ^0.4.11;
  2. import './ERC20Basic.sol';
  3. import '../ownership/Ownable.sol';
  4. import '../math/Math.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. event Released(uint256 amount);
  15. event Revoked();
  16. // beneficiary of tokens after they are released
  17. address public beneficiary;
  18. uint256 public cliff;
  19. uint256 public start;
  20. uint256 public duration;
  21. bool public revocable;
  22. mapping (address => uint256) public released;
  23. mapping (address => bool) public revoked;
  24. /**
  25. * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
  26. * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
  27. * of the balance will have vested.
  28. * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
  29. * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
  30. * @param _duration duration in seconds of the period in which the tokens will vest
  31. * @param _revocable whether the vesting is revocable or not
  32. */
  33. function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) {
  34. require(_beneficiary != 0x0);
  35. require(_cliff <= _duration);
  36. beneficiary = _beneficiary;
  37. revocable = _revocable;
  38. duration = _duration;
  39. cliff = _start + _cliff;
  40. start = _start;
  41. }
  42. /**
  43. * @notice Transfers vested tokens to beneficiary.
  44. * @param token ERC20 token which is being vested
  45. */
  46. function release(ERC20Basic token) public {
  47. uint256 vested = vestedAmount(token);
  48. require(vested > 0);
  49. token.transfer(beneficiary, vested);
  50. released[token] = released[token].add(vested);
  51. Released(vested);
  52. }
  53. /**
  54. * @notice Allows the owner to revoke the vesting. Tokens already vested
  55. * remain in the contract, the rest are returned to the owner.
  56. * @param token ERC20 token which is being vested
  57. */
  58. function revoke(ERC20Basic token) public onlyOwner {
  59. require(revocable);
  60. require(!revoked[token]);
  61. uint256 balance = token.balanceOf(this);
  62. uint256 vested = vestedAmount(token);
  63. uint256 vesting = balance - vested;
  64. revoked[token] = true;
  65. token.transfer(owner, vesting);
  66. Revoked();
  67. }
  68. /**
  69. * @dev Calculates the amount that has already vested but hasn't been released yet.
  70. * @param token ERC20 token which is being vested
  71. */
  72. function vestedAmount(ERC20Basic token) public constant returns (uint256) {
  73. if (now < cliff) {
  74. return 0;
  75. } else if (now >= start + duration || revoked[token]) {
  76. return token.balanceOf(this);
  77. } else {
  78. uint256 currentBalance = token.balanceOf(this);
  79. uint256 totalBalance = currentBalance.add(released[token]);
  80. uint256 vested = totalBalance.mul(now - start).div(duration);
  81. uint256 unreleased = vested.sub(released[token]);
  82. // currentBalance can be 0 in case of vesting being revoked earlier.
  83. return Math.min256(currentBalance, unreleased);
  84. }
  85. }
  86. }