ERC721Votes.test.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /* eslint-disable */
  2. const { BN, expectEvent, time } = require('@openzeppelin/test-helpers');
  3. const { expect } = require('chai');
  4. const { getChainId } = require('../../../helpers/chainid');
  5. const { shouldBehaveLikeVotes } = require('../../../governance/utils/Votes.behavior');
  6. const ERC721Votes = artifacts.require('$ERC721Votes');
  7. contract('ERC721Votes', function (accounts) {
  8. const [ account1, account2, account1Delegatee, other1, other2 ] = accounts;
  9. const name = 'My Vote';
  10. const symbol = 'MTKN';
  11. beforeEach(async function () {
  12. this.chainId = await getChainId();
  13. this.votes = await ERC721Votes.new(name, symbol, name, "1");
  14. this.NFT0 = new BN('10000000000000000000000000');
  15. this.NFT1 = new BN('10');
  16. this.NFT2 = new BN('20');
  17. this.NFT3 = new BN('30');
  18. });
  19. describe('balanceOf', function () {
  20. beforeEach(async function () {
  21. await this.votes.$_mint(account1, this.NFT0);
  22. await this.votes.$_mint(account1, this.NFT1);
  23. await this.votes.$_mint(account1, this.NFT2);
  24. await this.votes.$_mint(account1, this.NFT3);
  25. });
  26. it('grants to initial account', async function () {
  27. expect(await this.votes.balanceOf(account1)).to.be.bignumber.equal('4');
  28. });
  29. });
  30. describe('transfers', function () {
  31. beforeEach(async function () {
  32. await this.votes.$_mint(account1, this.NFT0);
  33. });
  34. it('no delegation', async function () {
  35. const { receipt } = await this.votes.transferFrom(account1, account2, this.NFT0, { from: account1 });
  36. expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: this.NFT0 });
  37. expectEvent.notEmitted(receipt, 'DelegateVotesChanged');
  38. this.account1Votes = '0';
  39. this.account2Votes = '0';
  40. });
  41. it('sender delegation', async function () {
  42. await this.votes.delegate(account1, { from: account1 });
  43. const { receipt } = await this.votes.transferFrom(account1, account2, this.NFT0, { from: account1 });
  44. expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: this.NFT0 });
  45. expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousBalance: '1', newBalance: '0' });
  46. const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer');
  47. expect(receipt.logs.filter(({ event }) => event == 'DelegateVotesChanged').every(({ logIndex }) => transferLogIndex < logIndex)).to.be.equal(true);
  48. this.account1Votes = '0';
  49. this.account2Votes = '0';
  50. });
  51. it('receiver delegation', async function () {
  52. await this.votes.delegate(account2, { from: account2 });
  53. const { receipt } = await this.votes.transferFrom(account1, account2, this.NFT0, { from: account1 });
  54. expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: this.NFT0 });
  55. expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousBalance: '0', newBalance: '1' });
  56. const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer');
  57. expect(receipt.logs.filter(({ event }) => event == 'DelegateVotesChanged').every(({ logIndex }) => transferLogIndex < logIndex)).to.be.equal(true);
  58. this.account1Votes = '0';
  59. this.account2Votes = '1';
  60. });
  61. it('full delegation', async function () {
  62. await this.votes.delegate(account1, { from: account1 });
  63. await this.votes.delegate(account2, { from: account2 });
  64. const { receipt } = await this.votes.transferFrom(account1, account2, this.NFT0, { from: account1 });
  65. expectEvent(receipt, 'Transfer', { from: account1, to: account2, tokenId: this.NFT0 });
  66. expectEvent(receipt, 'DelegateVotesChanged', { delegate: account1, previousBalance: '1', newBalance: '0'});
  67. expectEvent(receipt, 'DelegateVotesChanged', { delegate: account2, previousBalance: '0', newBalance: '1' });
  68. const { logIndex: transferLogIndex } = receipt.logs.find(({ event }) => event == 'Transfer');
  69. expect(receipt.logs.filter(({ event }) => event == 'DelegateVotesChanged').every(({ logIndex }) => transferLogIndex < logIndex)).to.be.equal(true);
  70. this.account1Votes = '0';
  71. this.account2Votes = '1';
  72. });
  73. it('returns the same total supply on transfers', async function () {
  74. await this.votes.delegate(account1, { from: account1 });
  75. const { receipt } = await this.votes.transferFrom(account1, account2, this.NFT0, { from: account1 });
  76. await time.advanceBlock();
  77. await time.advanceBlock();
  78. expect(await this.votes.getPastTotalSupply(receipt.blockNumber - 1)).to.be.bignumber.equal('1');
  79. expect(await this.votes.getPastTotalSupply(receipt.blockNumber + 1)).to.be.bignumber.equal('1');
  80. this.account1Votes = '0';
  81. this.account2Votes = '0';
  82. });
  83. it('generally returns the voting balance at the appropriate checkpoint', async function () {
  84. await this.votes.$_mint(account1, this.NFT1);
  85. await this.votes.$_mint(account1, this.NFT2);
  86. await this.votes.$_mint(account1, this.NFT3);
  87. const total = await this.votes.balanceOf(account1);
  88. const t1 = await this.votes.delegate(other1, { from: account1 });
  89. await time.advanceBlock();
  90. await time.advanceBlock();
  91. const t2 = await this.votes.transferFrom(account1, other2, this.NFT0, { from: account1 });
  92. await time.advanceBlock();
  93. await time.advanceBlock();
  94. const t3 = await this.votes.transferFrom(account1, other2, this.NFT2, { from: account1 });
  95. await time.advanceBlock();
  96. await time.advanceBlock();
  97. const t4 = await this.votes.transferFrom(other2, account1, this.NFT2, { from: other2 });
  98. await time.advanceBlock();
  99. await time.advanceBlock();
  100. expect(await this.votes.getPastVotes(other1, t1.receipt.blockNumber - 1)).to.be.bignumber.equal('0');
  101. expect(await this.votes.getPastVotes(other1, t1.receipt.blockNumber)).to.be.bignumber.equal(total);
  102. expect(await this.votes.getPastVotes(other1, t1.receipt.blockNumber + 1)).to.be.bignumber.equal(total);
  103. expect(await this.votes.getPastVotes(other1, t2.receipt.blockNumber)).to.be.bignumber.equal('3');
  104. expect(await this.votes.getPastVotes(other1, t2.receipt.blockNumber + 1)).to.be.bignumber.equal('3');
  105. expect(await this.votes.getPastVotes(other1, t3.receipt.blockNumber)).to.be.bignumber.equal('2');
  106. expect(await this.votes.getPastVotes(other1, t3.receipt.blockNumber + 1)).to.be.bignumber.equal('2');
  107. expect(await this.votes.getPastVotes(other1, t4.receipt.blockNumber)).to.be.bignumber.equal('3');
  108. expect(await this.votes.getPastVotes(other1, t4.receipt.blockNumber + 1)).to.be.bignumber.equal('3');
  109. this.account1Votes = '0';
  110. this.account2Votes = '0';
  111. });
  112. afterEach(async function () {
  113. expect(await this.votes.getVotes(account1)).to.be.bignumber.equal(this.account1Votes);
  114. expect(await this.votes.getVotes(account2)).to.be.bignumber.equal(this.account2Votes);
  115. // need to advance 2 blocks to see the effect of a transfer on "getPastVotes"
  116. const blockNumber = await time.latestBlock();
  117. await time.advanceBlock();
  118. expect(await this.votes.getPastVotes(account1, blockNumber)).to.be.bignumber.equal(this.account1Votes);
  119. expect(await this.votes.getPastVotes(account2, blockNumber)).to.be.bignumber.equal(this.account2Votes);
  120. });
  121. });
  122. describe('Voting workflow', function () {
  123. beforeEach(async function () {
  124. this.account1 = account1;
  125. this.account1Delegatee = account1Delegatee;
  126. this.account2 = account2;
  127. this.name = 'My Vote';
  128. });
  129. shouldBehaveLikeVotes();
  130. });
  131. });