Ownable2Step.test.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. const { ethers } = require('hardhat');
  2. const { expect } = require('chai');
  3. const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
  4. async function fixture() {
  5. const [owner, accountA, accountB] = await ethers.getSigners();
  6. const ownable2Step = await ethers.deployContract('$Ownable2Step', [owner]);
  7. return {
  8. ownable2Step,
  9. owner,
  10. accountA,
  11. accountB,
  12. };
  13. }
  14. describe('Ownable2Step', function () {
  15. beforeEach(async function () {
  16. Object.assign(this, await loadFixture(fixture));
  17. });
  18. describe('transfer ownership', function () {
  19. it('starting a transfer does not change owner', async function () {
  20. await expect(this.ownable2Step.connect(this.owner).transferOwnership(this.accountA))
  21. .to.emit(this.ownable2Step, 'OwnershipTransferStarted')
  22. .withArgs(this.owner, this.accountA);
  23. expect(await this.ownable2Step.owner()).to.equal(this.owner);
  24. expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
  25. });
  26. it('changes owner after transfer', async function () {
  27. await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
  28. await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
  29. .to.emit(this.ownable2Step, 'OwnershipTransferred')
  30. .withArgs(this.owner, this.accountA);
  31. expect(await this.ownable2Step.owner()).to.equal(this.accountA);
  32. expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
  33. });
  34. it('guards transfer against invalid user', async function () {
  35. await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
  36. await expect(this.ownable2Step.connect(this.accountB).acceptOwnership())
  37. .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
  38. .withArgs(this.accountB);
  39. });
  40. });
  41. describe('renouncing ownership', function () {
  42. it('changes owner after renouncing ownership', async function () {
  43. await expect(this.ownable2Step.connect(this.owner).renounceOwnership())
  44. .to.emit(this.ownable2Step, 'OwnershipTransferred')
  45. .withArgs(this.owner, ethers.ZeroAddress);
  46. // If renounceOwnership is removed from parent an alternative is needed ...
  47. // without it is difficult to cleanly renounce with the two step process
  48. // see: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3620#discussion_r957930388
  49. expect(await this.ownable2Step.owner()).to.equal(ethers.ZeroAddress);
  50. });
  51. it('pending owner resets after renouncing ownership', async function () {
  52. await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
  53. expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
  54. await this.ownable2Step.connect(this.owner).renounceOwnership();
  55. expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
  56. await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
  57. .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
  58. .withArgs(this.accountA);
  59. });
  60. it('allows to recover access using the internal _transferOwnership', async function () {
  61. await this.ownable2Step.connect(this.owner).renounceOwnership();
  62. await expect(this.ownable2Step.$_transferOwnership(this.accountA))
  63. .to.emit(this.ownable2Step, 'OwnershipTransferred')
  64. .withArgs(ethers.ZeroAddress, this.accountA);
  65. expect(await this.ownable2Step.owner()).to.equal(this.accountA);
  66. });
  67. it('allows the owner to cancel an initiated ownership transfer by setting newOwner to zero address', async function () {
  68. // initiate ownership transfer to accountA
  69. await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
  70. expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
  71. // cancel the ownership transfer by setting newOwner to zero address
  72. await expect(this.ownable2Step.connect(this.owner).transferOwnership(ethers.ZeroAddress))
  73. .to.emit(this.ownable2Step, 'OwnershipTransferStarted')
  74. .withArgs(this.owner, ethers.ZeroAddress);
  75. expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
  76. // verify that accountA cannot accept ownership anymore
  77. await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
  78. .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
  79. .withArgs(this.accountA);
  80. });
  81. });
  82. });