vesting.test.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* global artifacts, web3, contract */
  2. require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
  3. const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper')
  4. const { toBN } = require('web3-utils')
  5. const RLP = require('rlp')
  6. const Torn = artifacts.require('./TORNMock.sol')
  7. const Vesting = artifacts.require('./VestingMock.sol')
  8. const duration = {
  9. seconds: function (val) {
  10. return val
  11. },
  12. minutes: function (val) {
  13. return val * this.seconds(60)
  14. },
  15. hours: function (val) {
  16. return val * this.minutes(60)
  17. },
  18. days: function (val) {
  19. return val * this.hours(24)
  20. },
  21. weeks: function (val) {
  22. return val * this.days(7)
  23. },
  24. years: function (val) {
  25. return val * this.days(365)
  26. },
  27. }
  28. const MONTH = toBN(duration.days(30))
  29. async function getNextAddr(sender, offset = 0) {
  30. const nonce = await web3.eth.getTransactionCount(sender)
  31. return (
  32. '0x' +
  33. web3.utils
  34. .sha3(RLP.encode([sender, Number(nonce) + Number(offset)]))
  35. .slice(12)
  36. .substring(14)
  37. )
  38. }
  39. contract('Vesting', (accounts) => {
  40. let torn
  41. let vesting
  42. let snapshotId
  43. // const owner = accounts[0]
  44. // const ownerPrivateKey = '0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d'
  45. const recipient = accounts[1]
  46. const governance = accounts[8]
  47. const testTimestamp = toBN(1584230400) // 03/15/2020 @ 12:00am (UTC)
  48. const startTimestamp = toBN(1586908800) // 04/15/2020 @ 12:00am (UTC)
  49. const cliffInMonths = toBN(12)
  50. const durationInMonths = toBN(36)
  51. const cap = toBN(10000000).mul(toBN(10 ** 18))
  52. before(async () => {
  53. const vestingExpectedAddr = await getNextAddr(accounts[0], 1)
  54. const thirtyDays = 30 * 24 * 3600
  55. torn = await Torn.new(governance, thirtyDays, [{ to: vestingExpectedAddr, amount: cap.toString() }])
  56. vesting = await Vesting.new(torn.address, recipient, startTimestamp, cliffInMonths, durationInMonths)
  57. await vesting.setFakeTimestamp(testTimestamp)
  58. const blockTimestamp = await vesting.blockTimestamp()
  59. blockTimestamp.should.be.eq.BN(testTimestamp)
  60. snapshotId = await takeSnapshot()
  61. })
  62. describe('#constructor', () => {
  63. it('should be initialized', async () => {
  64. const startFromContract = await vesting.startTimestamp()
  65. startFromContract.should.be.eq.BN(startTimestamp)
  66. const beneficiaryFromContract = await vesting.beneficiary()
  67. beneficiaryFromContract.should.be.eq.BN(recipient)
  68. const cliffInMonthsFromContract = await vesting.cliffInMonths()
  69. cliffInMonthsFromContract.should.be.eq.BN(cliffInMonths)
  70. const durationInMonthsFromContract = await vesting.durationInMonths()
  71. durationInMonthsFromContract.should.be.eq.BN(durationInMonths)
  72. const balance = await torn.balanceOf(vesting.address)
  73. balance.should.be.eq.BN(cap)
  74. })
  75. })
  76. describe('#release', () => {
  77. it('should reject if time has not come', async () => {
  78. await vesting.release().should.be.rejectedWith('No tokens to release')
  79. await vesting.release({ from: recipient }).should.be.rejectedWith('No tokens to release')
  80. await vesting.setFakeTimestamp(startTimestamp)
  81. await vesting.release().should.be.rejectedWith('No tokens to release')
  82. await vesting.release({ from: recipient }).should.be.rejectedWith('No tokens to release')
  83. const rightBeforeCliff = startTimestamp.add(MONTH.mul(toBN(12))).sub(toBN(duration.days(1)))
  84. await vesting.setFakeTimestamp(rightBeforeCliff)
  85. await vesting.release().should.be.rejectedWith('No tokens to release')
  86. await vesting.release({ from: recipient }).should.be.rejectedWith('No tokens to release')
  87. })
  88. it('should work if time has come', async () => {
  89. const cliff = startTimestamp.add(MONTH.mul(toBN(12)))
  90. await vesting.setFakeTimestamp(cliff)
  91. let balanceBefore = await torn.balanceOf(recipient)
  92. await vesting.release()
  93. let balanceAfter = await torn.balanceOf(recipient)
  94. const monthAfterCliff = cliff.add(MONTH)
  95. await vesting.setFakeTimestamp(monthAfterCliff)
  96. balanceBefore = await torn.balanceOf(recipient)
  97. await vesting.release()
  98. balanceAfter = await torn.balanceOf(recipient)
  99. balanceAfter.should.be.eq.BN(balanceBefore.add(cap.divRound(toBN(36))))
  100. await vesting.release().should.be.rejectedWith('No tokens to release')
  101. const monthAfterCliffPlusWeek = monthAfterCliff.add(toBN(duration.weeks(1)))
  102. await vesting.setFakeTimestamp(monthAfterCliffPlusWeek)
  103. await vesting.release().should.be.rejectedWith('No tokens to release')
  104. const yearAfterCliff = cliff.add(MONTH.mul(toBN(12)))
  105. await vesting.setFakeTimestamp(yearAfterCliff)
  106. balanceBefore = await torn.balanceOf(recipient)
  107. await vesting.release()
  108. balanceAfter = await torn.balanceOf(recipient)
  109. balanceAfter.should.be.eq.BN(balanceBefore.add(cap.divRound(toBN(36)).mul(toBN(11))).sub(toBN(3))) // -3 wei because of round error
  110. const atTheEnd = cliff.add(MONTH.mul(toBN(24)))
  111. await vesting.setFakeTimestamp(atTheEnd)
  112. balanceBefore = await torn.balanceOf(recipient)
  113. await vesting.release()
  114. balanceAfter = await torn.balanceOf(recipient)
  115. balanceAfter.should.be.eq.BN(cap)
  116. })
  117. })
  118. afterEach(async () => {
  119. await revertSnapshot(snapshotId.result)
  120. // eslint-disable-next-line require-atomic-updates
  121. snapshotId = await takeSnapshot()
  122. })
  123. })