VestedToken.sol 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. pragma solidity ^0.4.8;
  2. import "./StandardToken.sol";
  3. import "./LimitedTransferToken.sol";
  4. contract VestedToken is StandardToken, LimitedTransferToken {
  5. struct TokenGrant {
  6. address granter;
  7. uint256 value;
  8. uint64 cliff;
  9. uint64 vesting;
  10. uint64 start;
  11. }
  12. mapping (address => TokenGrant[]) public grants;
  13. function grantVestedTokens(
  14. address _to,
  15. uint256 _value,
  16. uint64 _start,
  17. uint64 _cliff,
  18. uint64 _vesting) {
  19. if (_cliff < _start) {
  20. throw;
  21. }
  22. if (_vesting < _start) {
  23. throw;
  24. }
  25. if (_vesting < _cliff) {
  26. throw;
  27. }
  28. TokenGrant memory grant = TokenGrant(msg.sender, _value, _cliff, _vesting, _start);
  29. grants[_to].push(grant);
  30. transfer(_to, _value);
  31. }
  32. function revokeTokenGrant(address _holder, uint _grantId) {
  33. TokenGrant grant = grants[_holder][_grantId];
  34. if (grant.granter != msg.sender) {
  35. throw;
  36. }
  37. uint256 nonVested = nonVestedTokens(grant, uint64(now));
  38. // remove grant from array
  39. delete grants[_holder][_grantId];
  40. grants[_holder][_grantId] = grants[_holder][grants[_holder].length - 1];
  41. grants[_holder].length -= 1;
  42. balances[msg.sender] = safeAdd(balances[msg.sender], nonVested);
  43. balances[_holder] = safeSub(balances[_holder], nonVested);
  44. Transfer(_holder, msg.sender, nonVested);
  45. }
  46. function tokenGrantsCount(address _holder) constant returns (uint index) {
  47. return grants[_holder].length;
  48. }
  49. function tokenGrant(address _holder, uint _grantId) constant returns (address granter, uint256 value, uint256 vested, uint64 start, uint64 cliff, uint64 vesting) {
  50. TokenGrant grant = grants[_holder][_grantId];
  51. granter = grant.granter;
  52. value = grant.value;
  53. start = grant.start;
  54. cliff = grant.cliff;
  55. vesting = grant.vesting;
  56. vested = vestedTokens(grant, uint64(now));
  57. }
  58. function vestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
  59. return calculateVestedTokens(
  60. grant.value,
  61. uint256(time),
  62. uint256(grant.start),
  63. uint256(grant.cliff),
  64. uint256(grant.vesting)
  65. );
  66. }
  67. function calculateVestedTokens(
  68. uint256 tokens,
  69. uint256 time,
  70. uint256 start,
  71. uint256 cliff,
  72. uint256 vesting) constant returns (uint256 vestedTokens)
  73. {
  74. if (time < cliff) {
  75. return 0;
  76. }
  77. if (time >= vesting) {
  78. return tokens;
  79. }
  80. uint256 cliffTokens = safeDiv(safeMul(tokens, safeSub(cliff, start)), safeSub(vesting, start));
  81. vestedTokens = cliffTokens;
  82. uint256 vestingTokens = safeSub(tokens, cliffTokens);
  83. vestedTokens = safeAdd(vestedTokens, safeDiv(safeMul(vestingTokens, safeSub(time, cliff)), safeSub(vesting, cliff)));
  84. }
  85. function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
  86. return safeSub(grant.value, vestedTokens(grant, time));
  87. }
  88. function lastTokenIsTransferableDate(address holder) constant public returns (uint64 date) {
  89. date = uint64(now);
  90. uint256 grantIndex = grants[holder].length;
  91. for (uint256 i = 0; i < grantIndex; i++) {
  92. date = max64(grants[holder][i].vesting, date);
  93. }
  94. }
  95. function transferableTokens(address holder, uint64 time) constant public returns (uint256 nonVested) {
  96. uint256 grantIndex = grants[holder].length;
  97. for (uint256 i = 0; i < grantIndex; i++) {
  98. nonVested = safeAdd(nonVested, nonVestedTokens(grants[holder][i], time));
  99. }
  100. return min256(safeSub(balances[holder], nonVested), super.transferableTokens(holder, time));
  101. }
  102. }