AccessManaged.test.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. const { expectEvent, time, expectRevert } = require('@openzeppelin/test-helpers');
  2. const { selector } = require('../../helpers/methods');
  3. const { expectRevertCustomError } = require('../../helpers/customError');
  4. const {
  5. time: { setNextBlockTimestamp },
  6. } = require('@nomicfoundation/hardhat-network-helpers');
  7. const { impersonate } = require('../../helpers/account');
  8. const AccessManaged = artifacts.require('$AccessManagedTarget');
  9. const AccessManager = artifacts.require('$AccessManager');
  10. const AuthoritiyObserveIsConsuming = artifacts.require('$AuthoritiyObserveIsConsuming');
  11. contract('AccessManaged', function (accounts) {
  12. const [admin, roleMember, other] = accounts;
  13. beforeEach(async function () {
  14. this.authority = await AccessManager.new(admin);
  15. this.managed = await AccessManaged.new(this.authority.address);
  16. });
  17. it('sets authority and emits AuthorityUpdated event during construction', async function () {
  18. await expectEvent.inConstruction(this.managed, 'AuthorityUpdated', {
  19. authority: this.authority.address,
  20. });
  21. expect(await this.managed.authority()).to.eq(this.authority.address);
  22. });
  23. describe('restricted modifier', function () {
  24. const method = 'fnRestricted()';
  25. beforeEach(async function () {
  26. this.selector = selector(method);
  27. this.role = web3.utils.toBN(42);
  28. await this.authority.$_setTargetFunctionRole(this.managed.address, this.selector, this.role);
  29. await this.authority.$_grantRole(this.role, roleMember, 0, 0);
  30. });
  31. it('succeeds when role is granted without execution delay', async function () {
  32. await this.managed.methods[method]({ from: roleMember });
  33. });
  34. it('reverts when role is not granted', async function () {
  35. await expectRevertCustomError(this.managed.methods[method]({ from: other }), 'AccessManagedUnauthorized', [
  36. other,
  37. ]);
  38. });
  39. it('panics in short calldata', async function () {
  40. // We avoid adding the `restricted` modifier to the fallback function because other tests may depend on it
  41. // being accessible without restrictions. We check for the internal `_checkCanCall` instead.
  42. await expectRevert.unspecified(this.managed.$_checkCanCall(other, '0x1234'));
  43. });
  44. describe('when role is granted with execution delay', function () {
  45. beforeEach(async function () {
  46. const executionDelay = web3.utils.toBN(911);
  47. await this.authority.$_grantRole(this.role, roleMember, 0, executionDelay);
  48. });
  49. it('reverts if the operation is not scheduled', async function () {
  50. const calldata = await this.managed.contract.methods[method]().encodeABI();
  51. const opId = await this.authority.hashOperation(roleMember, this.managed.address, calldata);
  52. await expectRevertCustomError(this.managed.methods[method]({ from: roleMember }), 'AccessManagerNotScheduled', [
  53. opId,
  54. ]);
  55. });
  56. it('succeeds if the operation is scheduled', async function () {
  57. // Arguments
  58. const delay = time.duration.hours(12);
  59. const calldata = await this.managed.contract.methods[method]().encodeABI();
  60. // Schedule
  61. const timestamp = await time.latest();
  62. const scheduledAt = timestamp.addn(1);
  63. const when = scheduledAt.add(delay);
  64. await setNextBlockTimestamp(scheduledAt);
  65. await this.authority.schedule(this.managed.address, calldata, when, {
  66. from: roleMember,
  67. });
  68. // Set execution date
  69. await setNextBlockTimestamp(when);
  70. // Shouldn't revert
  71. await this.managed.methods[method]({ from: roleMember });
  72. });
  73. });
  74. });
  75. describe('setAuthority', function () {
  76. beforeEach(async function () {
  77. this.newAuthority = await AccessManager.new(admin);
  78. });
  79. it('reverts if the caller is not the authority', async function () {
  80. await expectRevertCustomError(this.managed.setAuthority(other, { from: other }), 'AccessManagedUnauthorized', [
  81. other,
  82. ]);
  83. });
  84. it('reverts if the new authority is not a valid authority', async function () {
  85. await impersonate(this.authority.address);
  86. await expectRevertCustomError(
  87. this.managed.setAuthority(other, { from: this.authority.address }),
  88. 'AccessManagedInvalidAuthority',
  89. [other],
  90. );
  91. });
  92. it('sets authority and emits AuthorityUpdated event', async function () {
  93. await impersonate(this.authority.address);
  94. const { receipt } = await this.managed.setAuthority(this.newAuthority.address, { from: this.authority.address });
  95. await expectEvent(receipt, 'AuthorityUpdated', {
  96. authority: this.newAuthority.address,
  97. });
  98. expect(await this.managed.authority()).to.eq(this.newAuthority.address);
  99. });
  100. });
  101. describe('isConsumingScheduledOp', function () {
  102. beforeEach(async function () {
  103. this.authority = await AuthoritiyObserveIsConsuming.new();
  104. this.managed = await AccessManaged.new(this.authority.address);
  105. });
  106. it('returns bytes4(0) when not consuming operation', async function () {
  107. expect(await this.managed.isConsumingScheduledOp()).to.eq('0x00000000');
  108. });
  109. it('returns isConsumingScheduledOp selector when consuming operation', async function () {
  110. const receipt = await this.managed.fnRestricted({ from: other });
  111. await expectEvent.inTransaction(receipt.tx, this.authority, 'ConsumeScheduledOpCalled', {
  112. caller: other,
  113. data: this.managed.contract.methods.fnRestricted().encodeABI(),
  114. isConsuming: selector('isConsumingScheduledOp()'),
  115. });
  116. });
  117. });
  118. });