VestedToken.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. const assertJump = require('./helpers/assertJump');
  2. const timer = require('./helpers/timer');
  3. var VestedTokenMock = artifacts.require("./helpers/VestedTokenMock.sol");
  4. contract('VestedToken', function(accounts) {
  5. let token = null
  6. let now = 0
  7. const tokenAmount = 50
  8. const granter = accounts[0]
  9. const receiver = accounts[1]
  10. beforeEach(async () => {
  11. token = await VestedTokenMock.new(granter, 100);
  12. now = web3.eth.getBlock(web3.eth.blockNumber).timestamp;
  13. })
  14. it('granter can grant tokens without vesting', async () => {
  15. await token.transfer(receiver, tokenAmount, { from: granter })
  16. assert.equal(await token.balanceOf(receiver), tokenAmount);
  17. assert.equal(await token.transferableTokens(receiver, now), tokenAmount);
  18. })
  19. describe('getting a revokable/non-burnable token grant', async () => {
  20. const cliff = 10000
  21. const vesting = 20000 // seconds
  22. beforeEach(async () => {
  23. await token.grantVestedTokens(receiver, tokenAmount, now, now + cliff, now + vesting, true, false, { from: granter })
  24. })
  25. it('tokens are received', async () => {
  26. assert.equal(await token.balanceOf(receiver), tokenAmount);
  27. })
  28. it('has 0 transferable tokens before cliff', async () => {
  29. assert.equal(await token.transferableTokens(receiver, now), 0);
  30. })
  31. it('all tokens are transferable after vesting', async () => {
  32. assert.equal(await token.transferableTokens(receiver, now + vesting), tokenAmount);
  33. })
  34. it('throws when trying to transfer non vested tokens', async () => {
  35. try {
  36. await token.transfer(accounts[7], 1, { from: receiver })
  37. assert.fail('should have thrown before');
  38. } catch(error) {
  39. assertJump(error);
  40. }
  41. })
  42. it('throws when trying to transfer from non vested tokens', async () => {
  43. try {
  44. await token.approve(accounts[7], 1, { from: receiver })
  45. await token.transferFrom(receiver, accounts[7], tokenAmount, { from: accounts[7] })
  46. assert.fail('should have thrown before');
  47. } catch(error) {
  48. assertJump(error);
  49. }
  50. })
  51. it('can be revoked by granter', async () => {
  52. await token.revokeTokenGrant(receiver, 0, { from: granter });
  53. assert.equal(await token.balanceOf(receiver), 0);
  54. assert.equal(await token.balanceOf(granter), 100);
  55. })
  56. it('cannot be revoked by non granter', async () => {
  57. try {
  58. await token.revokeTokenGrant(receiver, 0, { from: accounts[3] });
  59. assert.fail('should have thrown before');
  60. } catch(error) {
  61. assertJump(error);
  62. }
  63. })
  64. it('can be revoked by granter and non vested tokens are returned', async () => {
  65. await timer(cliff);
  66. await token.revokeTokenGrant(receiver, 0, { from: granter });
  67. assert.equal(await token.balanceOf(receiver), tokenAmount * cliff / vesting);
  68. })
  69. it('can transfer all tokens after vesting ends', async () => {
  70. await timer(vesting);
  71. await token.transfer(accounts[7], tokenAmount, { from: receiver })
  72. assert.equal(await token.balanceOf(accounts[7]), tokenAmount);
  73. })
  74. it('can approve and transferFrom all tokens after vesting ends', async () => {
  75. await timer(vesting);
  76. await token.approve(accounts[7], tokenAmount, { from: receiver })
  77. await token.transferFrom(receiver, accounts[7], tokenAmount, { from: accounts[7] })
  78. assert.equal(await token.balanceOf(accounts[7]), tokenAmount);
  79. })
  80. it('can handle composed vesting schedules', async () => {
  81. await timer(cliff);
  82. await token.transfer(accounts[7], 12, { from: receiver })
  83. assert.equal(await token.balanceOf(accounts[7]), 12);
  84. let newNow = web3.eth.getBlock(web3.eth.blockNumber).timestamp
  85. await token.grantVestedTokens(receiver, tokenAmount, newNow, newNow + cliff, newNow + vesting, false, false, { from: granter })
  86. await token.transfer(accounts[7], 13, { from: receiver })
  87. assert.equal(await token.balanceOf(accounts[7]), tokenAmount / 2);
  88. assert.equal(await token.balanceOf(receiver), 3 * tokenAmount / 2)
  89. assert.equal(await token.transferableTokens(receiver, newNow), 0)
  90. await timer(vesting);
  91. await token.transfer(accounts[7], 3 * tokenAmount / 2, { from: receiver })
  92. assert.equal(await token.balanceOf(accounts[7]), tokenAmount * 2)
  93. })
  94. })
  95. describe('getting a non-revokable token grant', async () => {
  96. const cliff = 10000
  97. const vesting = 20000 // seconds
  98. beforeEach(async () => {
  99. await token.grantVestedTokens(receiver, tokenAmount, now, now + cliff, now + vesting, false, false, { from: granter })
  100. })
  101. it('tokens are received', async () => {
  102. assert.equal(await token.balanceOf(receiver), tokenAmount);
  103. })
  104. it('throws when granter attempts to revoke', async () => {
  105. try {
  106. await token.revokeTokenGrant(receiver, 0, { from: granter });
  107. assert.fail('should have thrown before');
  108. } catch(error) {
  109. assertJump(error);
  110. }
  111. })
  112. })
  113. describe('getting a revokable/burnable token grant', async () => {
  114. const cliff = 100000
  115. const vesting = 200000 // seconds
  116. const burnAddress = '0x000000000000000000000000000000000000dead'
  117. beforeEach(async () => {
  118. await token.grantVestedTokens(receiver, tokenAmount, now, now + cliff, now + vesting, true, true, { from: granter })
  119. })
  120. it('tokens are received', async () => {
  121. assert.equal(await token.balanceOf(receiver), tokenAmount);
  122. })
  123. it('can be revoked by granter and tokens are burned', async () => {
  124. await token.revokeTokenGrant(receiver, 0, { from: granter });
  125. assert.equal(await token.balanceOf(receiver), 0);
  126. assert.equal(await token.balanceOf(burnAddress), tokenAmount);
  127. })
  128. it('cannot be revoked by non granter', async () => {
  129. try {
  130. await token.revokeTokenGrant(receiver, 0, { from: accounts[3] });
  131. assert.fail('should have thrown before');
  132. } catch(error) {
  133. assertJump(error);
  134. }
  135. })
  136. it('can be revoked by granter and non vested tokens are returned', async () => {
  137. await timer(cliff);
  138. await token.revokeTokenGrant(receiver, 0, { from: granter });
  139. assert.equal(await token.balanceOf(burnAddress), tokenAmount * cliff / vesting);
  140. })
  141. })
  142. });