ERC20Burnable.test.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. const { ethers } = require('hardhat');
  2. const { expect } = require('chai');
  3. const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
  4. const name = 'My Token';
  5. const symbol = 'MTKN';
  6. const initialBalance = 1000n;
  7. async function fixture() {
  8. const [owner, burner] = await ethers.getSigners();
  9. const token = await ethers.deployContract('$ERC20Burnable', [name, symbol], owner);
  10. await token.$_mint(owner, initialBalance);
  11. return { owner, burner, token, initialBalance };
  12. }
  13. describe('ERC20Burnable', function () {
  14. beforeEach(async function () {
  15. Object.assign(this, await loadFixture(fixture));
  16. });
  17. describe('burn', function () {
  18. it('reverts if not enough balance', async function () {
  19. const value = this.initialBalance + 1n;
  20. await expect(this.token.connect(this.owner).burn(value))
  21. .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
  22. .withArgs(this.owner, this.initialBalance, value);
  23. });
  24. describe('on success', function () {
  25. for (const { title, value } of [
  26. { title: 'for a zero value', value: 0n },
  27. { title: 'for a non-zero value', value: 100n },
  28. ]) {
  29. describe(title, function () {
  30. beforeEach(async function () {
  31. this.tx = await this.token.connect(this.owner).burn(value);
  32. });
  33. it('burns the requested value', async function () {
  34. await expect(this.tx).to.changeTokenBalance(this.token, this.owner, -value);
  35. });
  36. it('emits a transfer event', async function () {
  37. await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.owner, ethers.ZeroAddress, value);
  38. });
  39. });
  40. }
  41. });
  42. });
  43. describe('burnFrom', function () {
  44. describe('reverts', function () {
  45. it('if not enough balance', async function () {
  46. const value = this.initialBalance + 1n;
  47. await this.token.connect(this.owner).approve(this.burner, value);
  48. await expect(this.token.connect(this.burner).burnFrom(this.owner, value))
  49. .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
  50. .withArgs(this.owner, this.initialBalance, value);
  51. });
  52. it('if not enough allowance', async function () {
  53. const allowance = 100n;
  54. await this.token.connect(this.owner).approve(this.burner, allowance);
  55. await expect(this.token.connect(this.burner).burnFrom(this.owner, allowance + 1n))
  56. .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientAllowance')
  57. .withArgs(this.burner, allowance, allowance + 1n);
  58. });
  59. });
  60. describe('on success', function () {
  61. for (const { title, value } of [
  62. { title: 'for a zero value', value: 0n },
  63. { title: 'for a non-zero value', value: 100n },
  64. ]) {
  65. describe(title, function () {
  66. const originalAllowance = value * 3n;
  67. beforeEach(async function () {
  68. await this.token.connect(this.owner).approve(this.burner, originalAllowance);
  69. this.tx = await this.token.connect(this.burner).burnFrom(this.owner, value);
  70. });
  71. it('burns the requested value', async function () {
  72. await expect(this.tx).to.changeTokenBalance(this.token, this.owner, -value);
  73. });
  74. it('decrements allowance', async function () {
  75. expect(await this.token.allowance(this.owner, this.burner)).to.equal(originalAllowance - value);
  76. });
  77. it('emits a transfer event', async function () {
  78. await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.owner, ethers.ZeroAddress, value);
  79. });
  80. });
  81. }
  82. });
  83. });
  84. });