AccessManager.behavior.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. const { mine } = require('@nomicfoundation/hardhat-network-helpers');
  2. const { expectRevertCustomError } = require('../../helpers/customError');
  3. const {
  4. LIKE_COMMON_IS_EXECUTING,
  5. LIKE_COMMON_GET_ACCESS,
  6. LIKE_COMMON_SCHEDULABLE,
  7. testAsSchedulableOperation,
  8. testAsRestrictedOperation,
  9. testAsDelayedOperation,
  10. testAsCanCall,
  11. testAsHasRole,
  12. } = require('./AccessManager.predicate');
  13. // ============ ADMIN OPERATION ============
  14. /**
  15. * @requires this.{manager,roles,calldata,role}
  16. */
  17. function shouldBehaveLikeDelayedAdminOperation() {
  18. const getAccessPath = LIKE_COMMON_GET_ACCESS;
  19. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay = function () {
  20. beforeEach('consume previously set grant delay', async function () {
  21. // Consume previously set delay
  22. await mine();
  23. });
  24. testAsDelayedOperation();
  25. };
  26. getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = function () {
  27. beforeEach('set execution delay', async function () {
  28. this.scheduleIn = this.executionDelay; // For testAsDelayedOperation
  29. });
  30. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  31. };
  32. beforeEach('set target as manager', function () {
  33. this.target = this.manager;
  34. });
  35. testAsRestrictedOperation({
  36. callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
  37. callerIsNotTheManager() {
  38. testAsHasRole({
  39. publicRoleIsRequired() {
  40. it('reverts as AccessManagerUnauthorizedAccount', async function () {
  41. await expectRevertCustomError(
  42. web3.eth.sendTransaction({ to: this.target.address, data: this.calldata, from: this.caller }),
  43. 'AccessManagerUnauthorizedAccount',
  44. [
  45. this.caller,
  46. this.roles.ADMIN.id, // Although PUBLIC is required, target function role doesn't apply to admin ops
  47. ],
  48. );
  49. });
  50. },
  51. specificRoleIsRequired: getAccessPath,
  52. });
  53. },
  54. });
  55. }
  56. /**
  57. * @requires this.{manager,roles,calldata,role}
  58. */
  59. function shouldBehaveLikeNotDelayedAdminOperation() {
  60. const getAccessPath = LIKE_COMMON_GET_ACCESS;
  61. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay = function () {
  62. beforeEach('set execution delay', async function () {
  63. await mine();
  64. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  65. });
  66. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  67. };
  68. getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = function () {
  69. beforeEach('set execution delay', async function () {
  70. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  71. });
  72. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  73. };
  74. beforeEach('set target as manager', function () {
  75. this.target = this.manager;
  76. });
  77. testAsRestrictedOperation({
  78. callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
  79. callerIsNotTheManager() {
  80. testAsHasRole({
  81. publicRoleIsRequired() {
  82. it('reverts as AccessManagerUnauthorizedAccount', async function () {
  83. await expectRevertCustomError(
  84. web3.eth.sendTransaction({ to: this.target.address, data: this.calldata, from: this.caller }),
  85. 'AccessManagerUnauthorizedAccount',
  86. [this.caller, this.roles.ADMIN.id], // Although PUBLIC_ROLE is required, admin ops are not subject to target function roles
  87. );
  88. });
  89. },
  90. specificRoleIsRequired: getAccessPath,
  91. });
  92. },
  93. });
  94. }
  95. /**
  96. * @requires this.{manager,roles,calldata,role}
  97. */
  98. function shouldBehaveLikeRoleAdminOperation(roleAdmin) {
  99. const getAccessPath = LIKE_COMMON_GET_ACCESS;
  100. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay = function () {
  101. beforeEach('set operation delay', async function () {
  102. await mine();
  103. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  104. });
  105. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  106. };
  107. getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = function () {
  108. beforeEach('set execution delay', async function () {
  109. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  110. });
  111. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  112. };
  113. beforeEach('set target as manager', function () {
  114. this.target = this.manager;
  115. });
  116. testAsRestrictedOperation({
  117. callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
  118. callerIsNotTheManager() {
  119. testAsHasRole({
  120. publicRoleIsRequired() {
  121. it('reverts as AccessManagerUnauthorizedAccount', async function () {
  122. await expectRevertCustomError(
  123. web3.eth.sendTransaction({ to: this.target.address, data: this.calldata, from: this.caller }),
  124. 'AccessManagerUnauthorizedAccount',
  125. [this.caller, roleAdmin], // Role admin ops require the role's admin
  126. );
  127. });
  128. },
  129. specificRoleIsRequired: getAccessPath,
  130. });
  131. },
  132. });
  133. }
  134. // ============ RESTRICTED OPERATION ============
  135. /**
  136. * @requires this.{manager,roles,calldata,role}
  137. */
  138. function shouldBehaveLikeAManagedRestrictedOperation() {
  139. function revertUnauthorized() {
  140. it('reverts as AccessManagedUnauthorized', async function () {
  141. await expectRevertCustomError(
  142. web3.eth.sendTransaction({ to: this.target.address, data: this.calldata, from: this.caller }),
  143. 'AccessManagedUnauthorized',
  144. [this.caller],
  145. );
  146. });
  147. }
  148. const getAccessPath = LIKE_COMMON_GET_ACCESS;
  149. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.beforeGrantDelay =
  150. revertUnauthorized;
  151. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasNoExecutionDelay.beforeGrantDelay =
  152. revertUnauthorized;
  153. getAccessPath.requiredRoleIsNotGranted = revertUnauthorized;
  154. getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay = function () {
  155. beforeEach('consume previously set grant delay', async function () {
  156. // Consume previously set delay
  157. await mine();
  158. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  159. });
  160. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  161. };
  162. getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = function () {
  163. beforeEach('consume previously set grant delay', async function () {
  164. this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
  165. });
  166. testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
  167. };
  168. const isExecutingPath = LIKE_COMMON_IS_EXECUTING;
  169. isExecutingPath.notExecuting = revertUnauthorized;
  170. testAsCanCall({
  171. closed: revertUnauthorized,
  172. open: {
  173. callerIsTheManager: isExecutingPath,
  174. callerIsNotTheManager: {
  175. publicRoleIsRequired() {
  176. it('succeeds called directly', async function () {
  177. await web3.eth.sendTransaction({ to: this.target.address, data: this.calldata, from: this.caller });
  178. });
  179. it('succeeds via execute', async function () {
  180. await this.manager.execute(this.target.address, this.calldata, { from: this.caller });
  181. });
  182. },
  183. specificRoleIsRequired: getAccessPath,
  184. },
  185. },
  186. });
  187. }
  188. module.exports = {
  189. shouldBehaveLikeDelayedAdminOperation,
  190. shouldBehaveLikeNotDelayedAdminOperation,
  191. shouldBehaveLikeRoleAdminOperation,
  192. shouldBehaveLikeAManagedRestrictedOperation,
  193. };