ERC20Burnable.test.js 3.7 KB

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