ERC20VotesComp.test.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. /* eslint-disable */
  2. const { BN, constants, expectEvent, expectRevert, time } = require('@openzeppelin/test-helpers');
  3. const { expect } = require('chai');
  4. const { MAX_UINT256, ZERO_ADDRESS } = constants;
  5. const { fromRpcSig } = require('ethereumjs-util');
  6. const ethSigUtil = require('eth-sig-util');
  7. const Wallet = require('ethereumjs-wallet').default;
  8. const { batchInBlock } = require('../../../helpers/txpool');
  9. const { getDomain, domainType, domainSeparator } = require('../../../helpers/eip712');
  10. const { clock, clockFromReceipt } = require('../../../helpers/time');
  11. const { shouldBehaveLikeEIP6372 } = require('../../../governance/utils/EIP6372.behavior');
  12. const Delegation = [
  13. { name: 'delegatee', type: 'address' },
  14. { name: 'nonce', type: 'uint256' },
  15. { name: 'expiry', type: 'uint256' },
  16. ];
  17. const MODES = {
  18. blocknumber: artifacts.require('$ERC20VotesComp'),
  19. // no timestamp mode for ERC20VotesComp yet
  20. };
  21. contract('ERC20VotesComp', function (accounts) {
  22. const [holder, recipient, holderDelegatee, other1, other2] = accounts;
  23. const name = 'My Token';
  24. const symbol = 'MTKN';
  25. const supply = new BN('10000000000000000000000000');
  26. for (const [mode, artifact] of Object.entries(MODES)) {
  27. describe(`vote with ${mode}`, function () {
  28. beforeEach(async function () {
  29. this.token = await artifact.new(name, symbol, name);
  30. });
  31. shouldBehaveLikeEIP6372(mode);
  32. it('initial nonce is 0', async function () {
  33. expect(await this.token.nonces(holder)).to.be.bignumber.equal('0');
  34. });
  35. it('domain separator', async function () {
  36. expect(await this.token.DOMAIN_SEPARATOR()).to.equal(await getDomain(this.token).then(domainSeparator));
  37. });
  38. it('minting restriction', async function () {
  39. const amount = new BN('2').pow(new BN('96'));
  40. await expectRevert(this.token.$_mint(holder, amount), 'ERC20Votes: total supply risks overflowing votes');
  41. });
  42. describe('set delegation', function () {
  43. describe('call', function () {
  44. it('delegation with balance', async function () {
  45. await this.token.$_mint(holder, supply);
  46. expect(await this.token.delegates(holder)).to.be.equal(ZERO_ADDRESS);
  47. const { receipt } = await this.token.delegate(holder, { from: holder });
  48. const timepoint = await clockFromReceipt[mode](receipt);
  49. expectEvent(receipt, 'DelegateChanged', {
  50. delegator: holder,
  51. fromDelegate: ZERO_ADDRESS,
  52. toDelegate: holder,
  53. });
  54. expectEvent(receipt, 'DelegateVotesChanged', {
  55. delegate: holder,
  56. previousBalance: '0',
  57. newBalance: supply,
  58. });
  59. expect(await this.token.delegates(holder)).to.be.equal(holder);
  60. expect(await this.token.getCurrentVotes(holder)).to.be.bignumber.equal(supply);
  61. expect(await this.token.getPriorVotes(holder, timepoint - 1)).to.be.bignumber.equal('0');
  62. await time.advanceBlock();
  63. expect(await this.token.getPriorVotes(holder, timepoint)).to.be.bignumber.equal(supply);
  64. });
  65. it('delegation without balance', async function () {
  66. expect(await this.token.delegates(holder)).to.be.equal(ZERO_ADDRESS);
  67. const { receipt } = await this.token.delegate(holder, { from: holder });
  68. expectEvent(receipt, 'DelegateChanged', {
  69. delegator: holder,
  70. fromDelegate: ZERO_ADDRESS,
  71. toDelegate: holder,
  72. });
  73. expectEvent.notEmitted(receipt, 'DelegateVotesChanged');
  74. expect(await this.token.delegates(holder)).to.be.equal(holder);
  75. });
  76. });
  77. describe('with signature', function () {
  78. const delegator = Wallet.generate();
  79. const delegatorAddress = web3.utils.toChecksumAddress(delegator.getAddressString());
  80. const nonce = 0;
  81. const buildData = (contract, message) =>
  82. getDomain(contract).then(domain => ({
  83. primaryType: 'Delegation',
  84. types: { EIP712Domain: domainType(domain), Delegation },
  85. domain,
  86. message,
  87. }));
  88. beforeEach(async function () {
  89. await this.token.$_mint(delegatorAddress, supply);
  90. });
  91. it('accept signed delegation', async function () {
  92. const { v, r, s } = await buildData(this.token, {
  93. delegatee: delegatorAddress,
  94. nonce,
  95. expiry: MAX_UINT256,
  96. }).then(data => fromRpcSig(ethSigUtil.signTypedMessage(delegator.getPrivateKey(), { data })));
  97. expect(await this.token.delegates(delegatorAddress)).to.be.equal(ZERO_ADDRESS);
  98. const { receipt } = await this.token.delegateBySig(delegatorAddress, nonce, MAX_UINT256, v, r, s);
  99. const timepoint = await clockFromReceipt[mode](receipt);
  100. expectEvent(receipt, 'DelegateChanged', {
  101. delegator: delegatorAddress,
  102. fromDelegate: ZERO_ADDRESS,
  103. toDelegate: delegatorAddress,
  104. });
  105. expectEvent(receipt, 'DelegateVotesChanged', {
  106. delegate: delegatorAddress,
  107. previousBalance: '0',
  108. newBalance: supply,
  109. });
  110. expect(await this.token.delegates(delegatorAddress)).to.be.equal(delegatorAddress);
  111. expect(await this.token.getCurrentVotes(delegatorAddress)).to.be.bignumber.equal(supply);
  112. expect(await this.token.getPriorVotes(delegatorAddress, timepoint - 1)).to.be.bignumber.equal('0');
  113. await time.advanceBlock();
  114. expect(await this.token.getPriorVotes(delegatorAddress, timepoint)).to.be.bignumber.equal(supply);
  115. });
  116. it('rejects reused signature', async function () {
  117. const { v, r, s } = await buildData(this.token, {
  118. delegatee: delegatorAddress,
  119. nonce,
  120. expiry: MAX_UINT256,
  121. }).then(data => fromRpcSig(ethSigUtil.signTypedMessage(delegator.getPrivateKey(), { data })));
  122. await this.token.delegateBySig(delegatorAddress, nonce, MAX_UINT256, v, r, s);
  123. await expectRevert(
  124. this.token.delegateBySig(delegatorAddress, nonce, MAX_UINT256, v, r, s),
  125. 'ERC20Votes: invalid nonce',
  126. );
  127. });
  128. it('rejects bad delegatee', async function () {
  129. const { v, r, s } = await buildData(this.token, {
  130. delegatee: delegatorAddress,
  131. nonce,
  132. expiry: MAX_UINT256,
  133. }).then(data => fromRpcSig(ethSigUtil.signTypedMessage(delegator.getPrivateKey(), { data })));
  134. const receipt = await this.token.delegateBySig(holderDelegatee, nonce, MAX_UINT256, v, r, s);
  135. const { args } = receipt.logs.find(({ event }) => event == 'DelegateChanged');
  136. expect(args.delegator).to.not.be.equal(delegatorAddress);
  137. expect(args.fromDelegate).to.be.equal(ZERO_ADDRESS);
  138. expect(args.toDelegate).to.be.equal(holderDelegatee);
  139. });
  140. it('rejects bad nonce', async function () {
  141. const { v, r, s } = await buildData(this.token, {
  142. delegatee: delegatorAddress,
  143. nonce,
  144. expiry: MAX_UINT256,
  145. }).then(data => fromRpcSig(ethSigUtil.signTypedMessage(delegator.getPrivateKey(), { data })));
  146. await expectRevert(
  147. this.token.delegateBySig(delegatorAddress, nonce + 1, MAX_UINT256, v, r, s),
  148. 'ERC20Votes: invalid nonce',
  149. );
  150. });
  151. it('rejects expired permit', async function () {
  152. const expiry = (await time.latest()) - time.duration.weeks(1);
  153. const { v, r, s } = await buildData(this.token, {
  154. delegatee: delegatorAddress,
  155. nonce,
  156. expiry,
  157. }).then(data => fromRpcSig(ethSigUtil.signTypedMessage(delegator.getPrivateKey(), { data })));
  158. await expectRevert(
  159. this.token.delegateBySig(delegatorAddress, nonce, expiry, v, r, s),
  160. 'ERC20Votes: signature expired',
  161. );
  162. });
  163. });
  164. });
  165. describe('change delegation', function () {
  166. beforeEach(async function () {
  167. await this.token.$_mint(holder, supply);
  168. await this.token.delegate(holder, { from: holder });
  169. });
  170. it('call', async function () {
  171. expect(await this.token.delegates(holder)).to.be.equal(holder);
  172. const { receipt } = await this.token.delegate(holderDelegatee, { from: holder });
  173. const timepoint = await clockFromReceipt[mode](receipt);
  174. expectEvent(receipt, 'DelegateChanged', {
  175. delegator: holder,
  176. fromDelegate: holder,
  177. toDelegate: holderDelegatee,
  178. });
  179. expectEvent(receipt, 'DelegateVotesChanged', {
  180. delegate: holder,
  181. previousBalance: supply,
  182. newBalance: '0',
  183. });
  184. expectEvent(receipt, 'DelegateVotesChanged', {
  185. delegate: holderDelegatee,
  186. previousBalance: '0',
  187. newBalance: supply,
  188. });
  189. expect(await this.token.delegates(holder)).to.be.equal(holderDelegatee);
  190. expect(await this.token.getCurrentVotes(holder)).to.be.bignumber.equal('0');
  191. expect(await this.token.getCurrentVotes(holderDelegatee)).to.be.bignumber.equal(supply);
  192. expect(await this.token.getPriorVotes(holder, timepoint - 1)).to.be.bignumber.equal(supply);
  193. expect(await this.token.getPriorVotes(holderDelegatee, timepoint - 1)).to.be.bignumber.equal('0');
  194. await time.advanceBlock();
  195. expect(await this.token.getPriorVotes(holder, timepoint)).to.be.bignumber.equal('0');
  196. expect(await this.token.getPriorVotes(holderDelegatee, timepoint)).to.be.bignumber.equal(supply);
  197. });
  198. });
  199. describe('transfers', function () {
  200. beforeEach(async function () {
  201. await this.token.$_mint(holder, supply);
  202. });
  203. it('no delegation', async function () {
  204. const { receipt } = await this.token.transfer(recipient, 1, { from: holder });
  205. expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' });
  206. expectEvent.notEmitted(receipt, 'DelegateVotesChanged');
  207. this.holderVotes = '0';
  208. this.recipientVotes = '0';
  209. });
  210. it('sender delegation', async function () {
  211. await this.token.delegate(holder, { from: holder });
  212. const { receipt } = await this.token.transfer(recipient, 1, { from: holder });
  213. expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' });
  214. expectEvent(receipt, 'DelegateVotesChanged', {
  215. delegate: holder,
  216. previousBalance: supply,
  217. newBalance: supply.subn(1),
  218. });
  219. this.holderVotes = supply.subn(1);
  220. this.recipientVotes = '0';
  221. });
  222. it('receiver delegation', async function () {
  223. await this.token.delegate(recipient, { from: recipient });
  224. const { receipt } = await this.token.transfer(recipient, 1, { from: holder });
  225. expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' });
  226. expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousBalance: '0', newBalance: '1' });
  227. this.holderVotes = '0';
  228. this.recipientVotes = '1';
  229. });
  230. it('full delegation', async function () {
  231. await this.token.delegate(holder, { from: holder });
  232. await this.token.delegate(recipient, { from: recipient });
  233. const { receipt } = await this.token.transfer(recipient, 1, { from: holder });
  234. expectEvent(receipt, 'Transfer', { from: holder, to: recipient, value: '1' });
  235. expectEvent(receipt, 'DelegateVotesChanged', {
  236. delegate: holder,
  237. previousBalance: supply,
  238. newBalance: supply.subn(1),
  239. });
  240. expectEvent(receipt, 'DelegateVotesChanged', { delegate: recipient, previousBalance: '0', newBalance: '1' });
  241. this.holderVotes = supply.subn(1);
  242. this.recipientVotes = '1';
  243. });
  244. afterEach(async function () {
  245. expect(await this.token.getCurrentVotes(holder)).to.be.bignumber.equal(this.holderVotes);
  246. expect(await this.token.getCurrentVotes(recipient)).to.be.bignumber.equal(this.recipientVotes);
  247. // need to advance 2 blocks to see the effect of a transfer on "getPriorVotes"
  248. const timepoint = await clock[mode]();
  249. await time.advanceBlock();
  250. expect(await this.token.getPriorVotes(holder, timepoint)).to.be.bignumber.equal(this.holderVotes);
  251. expect(await this.token.getPriorVotes(recipient, timepoint)).to.be.bignumber.equal(this.recipientVotes);
  252. });
  253. });
  254. // The following tests are a adaptation of https://github.com/compound-finance/compound-protocol/blob/master/tests/Governance/CompTest.js.
  255. describe('Compound test suite', function () {
  256. beforeEach(async function () {
  257. await this.token.$_mint(holder, supply);
  258. });
  259. describe('balanceOf', function () {
  260. it('grants to initial account', async function () {
  261. expect(await this.token.balanceOf(holder)).to.be.bignumber.equal('10000000000000000000000000');
  262. });
  263. });
  264. describe('numCheckpoints', function () {
  265. it('returns the number of checkpoints for a delegate', async function () {
  266. await this.token.transfer(recipient, '100', { from: holder }); //give an account a few tokens for readability
  267. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('0');
  268. const t1 = await this.token.delegate(other1, { from: recipient });
  269. t1.timepoint = await clockFromReceipt[mode](t1.receipt);
  270. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('1');
  271. const t2 = await this.token.transfer(other2, 10, { from: recipient });
  272. t2.timepoint = await clockFromReceipt[mode](t2.receipt);
  273. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('2');
  274. const t3 = await this.token.transfer(other2, 10, { from: recipient });
  275. t3.timepoint = await clockFromReceipt[mode](t3.receipt);
  276. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('3');
  277. const t4 = await this.token.transfer(recipient, 20, { from: holder });
  278. t4.timepoint = await clockFromReceipt[mode](t4.receipt);
  279. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('4');
  280. expect(await this.token.checkpoints(other1, 0)).to.be.deep.equal([t1.timepoint.toString(), '100']);
  281. expect(await this.token.checkpoints(other1, 1)).to.be.deep.equal([t2.timepoint.toString(), '90']);
  282. expect(await this.token.checkpoints(other1, 2)).to.be.deep.equal([t3.timepoint.toString(), '80']);
  283. expect(await this.token.checkpoints(other1, 3)).to.be.deep.equal([t4.timepoint.toString(), '100']);
  284. await time.advanceBlock();
  285. expect(await this.token.getPriorVotes(other1, t1.timepoint)).to.be.bignumber.equal('100');
  286. expect(await this.token.getPriorVotes(other1, t2.timepoint)).to.be.bignumber.equal('90');
  287. expect(await this.token.getPriorVotes(other1, t3.timepoint)).to.be.bignumber.equal('80');
  288. expect(await this.token.getPriorVotes(other1, t4.timepoint)).to.be.bignumber.equal('100');
  289. });
  290. it('does not add more than one checkpoint in a block', async function () {
  291. await this.token.transfer(recipient, '100', { from: holder });
  292. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('0');
  293. const [t1, t2, t3] = await batchInBlock([
  294. () => this.token.delegate(other1, { from: recipient, gas: 100000 }),
  295. () => this.token.transfer(other2, 10, { from: recipient, gas: 100000 }),
  296. () => this.token.transfer(other2, 10, { from: recipient, gas: 100000 }),
  297. ]);
  298. t1.timepoint = await clockFromReceipt[mode](t1.receipt);
  299. t2.timepoint = await clockFromReceipt[mode](t2.receipt);
  300. t3.timepoint = await clockFromReceipt[mode](t3.receipt);
  301. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('1');
  302. expect(await this.token.checkpoints(other1, 0)).to.be.deep.equal([t1.timepoint.toString(), '80']);
  303. const t4 = await this.token.transfer(recipient, 20, { from: holder });
  304. t4.timepoint = await clockFromReceipt[mode](t4.receipt);
  305. expect(await this.token.numCheckpoints(other1)).to.be.bignumber.equal('2');
  306. expect(await this.token.checkpoints(other1, 1)).to.be.deep.equal([t4.timepoint.toString(), '100']);
  307. });
  308. });
  309. describe('getPriorVotes', function () {
  310. it('reverts if block number >= current block', async function () {
  311. await expectRevert(this.token.getPriorVotes(other1, 5e10), 'ERC20Votes: future lookup');
  312. });
  313. it('returns 0 if there are no checkpoints', async function () {
  314. expect(await this.token.getPriorVotes(other1, 0)).to.be.bignumber.equal('0');
  315. });
  316. it('returns the latest block if >= last checkpoint block', async function () {
  317. const { receipt } = await this.token.delegate(other1, { from: holder });
  318. const timepoint = await clockFromReceipt[mode](receipt);
  319. await time.advanceBlock();
  320. await time.advanceBlock();
  321. expect(await this.token.getPriorVotes(other1, timepoint)).to.be.bignumber.equal(
  322. '10000000000000000000000000',
  323. );
  324. expect(await this.token.getPriorVotes(other1, timepoint + 1)).to.be.bignumber.equal(
  325. '10000000000000000000000000',
  326. );
  327. });
  328. it('returns zero if < first checkpoint block', async function () {
  329. await time.advanceBlock();
  330. const { receipt } = await this.token.delegate(other1, { from: holder });
  331. const timepoint = await clockFromReceipt[mode](receipt);
  332. await time.advanceBlock();
  333. await time.advanceBlock();
  334. expect(await this.token.getPriorVotes(other1, timepoint - 1)).to.be.bignumber.equal('0');
  335. expect(await this.token.getPriorVotes(other1, timepoint + 1)).to.be.bignumber.equal(
  336. '10000000000000000000000000',
  337. );
  338. });
  339. it('generally returns the voting balance at the appropriate checkpoint', async function () {
  340. const t1 = await this.token.delegate(other1, { from: holder });
  341. await time.advanceBlock();
  342. await time.advanceBlock();
  343. const t2 = await this.token.transfer(other2, 10, { from: holder });
  344. await time.advanceBlock();
  345. await time.advanceBlock();
  346. const t3 = await this.token.transfer(other2, 10, { from: holder });
  347. await time.advanceBlock();
  348. await time.advanceBlock();
  349. const t4 = await this.token.transfer(holder, 20, { from: other2 });
  350. await time.advanceBlock();
  351. await time.advanceBlock();
  352. t1.timepoint = await clockFromReceipt[mode](t1.receipt);
  353. t2.timepoint = await clockFromReceipt[mode](t2.receipt);
  354. t3.timepoint = await clockFromReceipt[mode](t3.receipt);
  355. t4.timepoint = await clockFromReceipt[mode](t4.receipt);
  356. expect(await this.token.getPriorVotes(other1, t1.timepoint - 1)).to.be.bignumber.equal('0');
  357. expect(await this.token.getPriorVotes(other1, t1.timepoint)).to.be.bignumber.equal(
  358. '10000000000000000000000000',
  359. );
  360. expect(await this.token.getPriorVotes(other1, t1.timepoint + 1)).to.be.bignumber.equal(
  361. '10000000000000000000000000',
  362. );
  363. expect(await this.token.getPriorVotes(other1, t2.timepoint)).to.be.bignumber.equal(
  364. '9999999999999999999999990',
  365. );
  366. expect(await this.token.getPriorVotes(other1, t2.timepoint + 1)).to.be.bignumber.equal(
  367. '9999999999999999999999990',
  368. );
  369. expect(await this.token.getPriorVotes(other1, t3.timepoint)).to.be.bignumber.equal(
  370. '9999999999999999999999980',
  371. );
  372. expect(await this.token.getPriorVotes(other1, t3.timepoint + 1)).to.be.bignumber.equal(
  373. '9999999999999999999999980',
  374. );
  375. expect(await this.token.getPriorVotes(other1, t4.timepoint)).to.be.bignumber.equal(
  376. '10000000000000000000000000',
  377. );
  378. expect(await this.token.getPriorVotes(other1, t4.timepoint + 1)).to.be.bignumber.equal(
  379. '10000000000000000000000000',
  380. );
  381. });
  382. });
  383. });
  384. describe('getPastTotalSupply', function () {
  385. beforeEach(async function () {
  386. await this.token.delegate(holder, { from: holder });
  387. });
  388. it('reverts if block number >= current block', async function () {
  389. await expectRevert(this.token.getPastTotalSupply(5e10), 'ERC20Votes: future lookup');
  390. });
  391. it('returns 0 if there are no checkpoints', async function () {
  392. expect(await this.token.getPastTotalSupply(0)).to.be.bignumber.equal('0');
  393. });
  394. it('returns the latest block if >= last checkpoint block', async function () {
  395. const { receipt } = await this.token.$_mint(holder, supply);
  396. const timepoint = await clockFromReceipt[mode](receipt);
  397. await time.advanceBlock();
  398. await time.advanceBlock();
  399. expect(await this.token.getPastTotalSupply(timepoint)).to.be.bignumber.equal(supply);
  400. expect(await this.token.getPastTotalSupply(timepoint + 1)).to.be.bignumber.equal(supply);
  401. });
  402. it('returns zero if < first checkpoint block', async function () {
  403. await time.advanceBlock();
  404. const { receipt } = await this.token.$_mint(holder, supply);
  405. const timepoint = await clockFromReceipt[mode](receipt);
  406. await time.advanceBlock();
  407. await time.advanceBlock();
  408. expect(await this.token.getPastTotalSupply(timepoint - 1)).to.be.bignumber.equal('0');
  409. expect(await this.token.getPastTotalSupply(timepoint + 1)).to.be.bignumber.equal(
  410. '10000000000000000000000000',
  411. );
  412. });
  413. it('generally returns the voting balance at the appropriate checkpoint', async function () {
  414. const t1 = await this.token.$_mint(holder, supply);
  415. await time.advanceBlock();
  416. await time.advanceBlock();
  417. const t2 = await this.token.$_burn(holder, 10);
  418. await time.advanceBlock();
  419. await time.advanceBlock();
  420. const t3 = await this.token.$_burn(holder, 10);
  421. await time.advanceBlock();
  422. await time.advanceBlock();
  423. const t4 = await this.token.$_mint(holder, 20);
  424. await time.advanceBlock();
  425. await time.advanceBlock();
  426. t1.timepoint = await clockFromReceipt[mode](t1.receipt);
  427. t2.timepoint = await clockFromReceipt[mode](t2.receipt);
  428. t3.timepoint = await clockFromReceipt[mode](t3.receipt);
  429. t4.timepoint = await clockFromReceipt[mode](t4.receipt);
  430. expect(await this.token.getPastTotalSupply(t1.timepoint - 1)).to.be.bignumber.equal('0');
  431. expect(await this.token.getPastTotalSupply(t1.timepoint)).to.be.bignumber.equal('10000000000000000000000000');
  432. expect(await this.token.getPastTotalSupply(t1.timepoint + 1)).to.be.bignumber.equal(
  433. '10000000000000000000000000',
  434. );
  435. expect(await this.token.getPastTotalSupply(t2.timepoint)).to.be.bignumber.equal('9999999999999999999999990');
  436. expect(await this.token.getPastTotalSupply(t2.timepoint + 1)).to.be.bignumber.equal(
  437. '9999999999999999999999990',
  438. );
  439. expect(await this.token.getPastTotalSupply(t3.timepoint)).to.be.bignumber.equal('9999999999999999999999980');
  440. expect(await this.token.getPastTotalSupply(t3.timepoint + 1)).to.be.bignumber.equal(
  441. '9999999999999999999999980',
  442. );
  443. expect(await this.token.getPastTotalSupply(t4.timepoint)).to.be.bignumber.equal('10000000000000000000000000');
  444. expect(await this.token.getPastTotalSupply(t4.timepoint + 1)).to.be.bignumber.equal(
  445. '10000000000000000000000000',
  446. );
  447. });
  448. });
  449. });
  450. }
  451. });