access-manager.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. const {
  2. bigint: { MAX_UINT64 },
  3. } = require('./constants');
  4. const { namespaceSlot } = require('./namespaced-storage');
  5. const { bigint: time } = require('./time');
  6. const { keccak256, AbiCoder } = require('ethers');
  7. function buildBaseRoles() {
  8. const roles = {
  9. ADMIN: {
  10. id: 0n,
  11. },
  12. SOME_ADMIN: {
  13. id: 17n,
  14. },
  15. SOME_GUARDIAN: {
  16. id: 35n,
  17. },
  18. SOME: {
  19. id: 42n,
  20. },
  21. PUBLIC: {
  22. id: MAX_UINT64,
  23. },
  24. };
  25. // Names
  26. Object.entries(roles).forEach(([name, role]) => (role.name = name));
  27. // Defaults
  28. for (const role of Object.keys(roles)) {
  29. roles[role].admin = roles.ADMIN;
  30. roles[role].guardian = roles.ADMIN;
  31. }
  32. // Admins
  33. roles.SOME.admin = roles.SOME_ADMIN;
  34. // Guardians
  35. roles.SOME.guardian = roles.SOME_GUARDIAN;
  36. return roles;
  37. }
  38. const formatAccess = access => [access[0], access[1].toString()];
  39. const MINSETBACK = time.duration.days(5);
  40. const EXPIRATION = time.duration.weeks(1);
  41. const EXECUTION_ID_STORAGE_SLOT = namespaceSlot('AccessManager', 3n);
  42. const CONSUMING_SCHEDULE_STORAGE_SLOT = namespaceSlot('AccessManaged', 0n);
  43. /**
  44. * @requires this.{manager, caller, target, calldata}
  45. */
  46. async function prepareOperation(manager, { caller, target, calldata, delay }) {
  47. const timestamp = await time.clock.timestamp();
  48. const scheduledAt = timestamp + 1n;
  49. await time.forward.timestamp(scheduledAt, false); // Fix next block timestamp for predictability
  50. return {
  51. schedule: () => manager.connect(caller).schedule(target, calldata, scheduledAt + delay),
  52. scheduledAt,
  53. operationId: hashOperation(caller, target, calldata),
  54. };
  55. }
  56. const lazyGetAddress = addressable => addressable.address ?? addressable.target ?? addressable;
  57. const hashOperation = (caller, target, data) =>
  58. keccak256(
  59. AbiCoder.defaultAbiCoder().encode(
  60. ['address', 'address', 'bytes'],
  61. [lazyGetAddress(caller), lazyGetAddress(target), data],
  62. ),
  63. );
  64. module.exports = {
  65. buildBaseRoles,
  66. formatAccess,
  67. MINSETBACK,
  68. EXPIRATION,
  69. EXECUTION_ID_STORAGE_SLOT,
  70. CONSUMING_SCHEDULE_STORAGE_SLOT,
  71. prepareOperation,
  72. hashOperation,
  73. };