ERC20Burnable.test.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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.address, 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)
  38. .to.emit(this.token, 'Transfer')
  39. .withArgs(this.owner.address, ethers.ZeroAddress, value);
  40. });
  41. });
  42. }
  43. });
  44. });
  45. describe('burnFrom', function () {
  46. describe('reverts', function () {
  47. it('if not enough balance', async function () {
  48. const value = this.initialBalance + 1n;
  49. await this.token.connect(this.owner).approve(this.burner, value);
  50. await expect(this.token.connect(this.burner).burnFrom(this.owner, value))
  51. .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
  52. .withArgs(this.owner.address, this.initialBalance, value);
  53. });
  54. it('if not enough allowance', async function () {
  55. const allowance = 100n;
  56. await this.token.connect(this.owner).approve(this.burner, allowance);
  57. await expect(this.token.connect(this.burner).burnFrom(this.owner, allowance + 1n))
  58. .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientAllowance')
  59. .withArgs(this.burner.address, allowance, allowance + 1n);
  60. });
  61. });
  62. describe('on success', function () {
  63. for (const { title, value } of [
  64. { title: 'for a zero value', value: 0n },
  65. { title: 'for a non-zero value', value: 100n },
  66. ]) {
  67. describe(title, function () {
  68. const originalAllowance = value * 3n;
  69. beforeEach(async function () {
  70. await this.token.connect(this.owner).approve(this.burner, originalAllowance);
  71. this.tx = await this.token.connect(this.burner).burnFrom(this.owner, value);
  72. });
  73. it('burns the requested value', async function () {
  74. await expect(this.tx).to.changeTokenBalance(this.token, this.owner, -value);
  75. });
  76. it('decrements allowance', async function () {
  77. expect(await this.token.allowance(this.owner, this.burner)).to.equal(originalAllowance - value);
  78. });
  79. it('emits a transfer event', async function () {
  80. await expect(this.tx)
  81. .to.emit(this.token, 'Transfer')
  82. .withArgs(this.owner.address, ethers.ZeroAddress, value);
  83. });
  84. });
  85. }
  86. });
  87. });
  88. });