Initializable.sol 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
  3. pragma solidity ^0.8.19;
  4. import "../../utils/Address.sol";
  5. /**
  6. * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
  7. * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
  8. * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
  9. * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
  10. *
  11. * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
  12. * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
  13. * case an upgrade adds a module that needs to be initialized.
  14. *
  15. * For example:
  16. *
  17. * [.hljs-theme-light.nopadding]
  18. * ```solidity
  19. * contract MyToken is ERC20Upgradeable {
  20. * function initialize() initializer public {
  21. * __ERC20_init("MyToken", "MTK");
  22. * }
  23. * }
  24. *
  25. * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
  26. * function initializeV2() reinitializer(2) public {
  27. * __ERC20Permit_init("MyToken");
  28. * }
  29. * }
  30. * ```
  31. *
  32. * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
  33. * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
  34. *
  35. * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
  36. * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
  37. *
  38. * [CAUTION]
  39. * ====
  40. * Avoid leaving a contract uninitialized.
  41. *
  42. * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
  43. * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
  44. * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
  45. *
  46. * [.hljs-theme-light.nopadding]
  47. * ```
  48. * /// @custom:oz-upgrades-unsafe-allow constructor
  49. * constructor() {
  50. * _disableInitializers();
  51. * }
  52. * ```
  53. * ====
  54. */
  55. abstract contract Initializable {
  56. /**
  57. * @dev Indicates that the contract has been initialized.
  58. * @custom:oz-retyped-from bool
  59. */
  60. uint8 private _initialized;
  61. /**
  62. * @dev Indicates that the contract is in the process of being initialized.
  63. */
  64. bool private _initializing;
  65. /**
  66. * @dev The contract is already initialized.
  67. */
  68. error AlreadyInitialized();
  69. /**
  70. * @dev The contract is not initializing.
  71. */
  72. error NotInitializing();
  73. /**
  74. * @dev Triggered when the contract has been initialized or reinitialized.
  75. */
  76. event Initialized(uint8 version);
  77. /**
  78. * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
  79. * `onlyInitializing` functions can be used to initialize parent contracts.
  80. *
  81. * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
  82. * constructor.
  83. *
  84. * Emits an {Initialized} event.
  85. */
  86. modifier initializer() {
  87. bool isTopLevelCall = !_initializing;
  88. if (!(isTopLevelCall && _initialized < 1) && !(address(this).code.length == 0 && _initialized == 1)) {
  89. revert AlreadyInitialized();
  90. }
  91. _initialized = 1;
  92. if (isTopLevelCall) {
  93. _initializing = true;
  94. }
  95. _;
  96. if (isTopLevelCall) {
  97. _initializing = false;
  98. emit Initialized(1);
  99. }
  100. }
  101. /**
  102. * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
  103. * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
  104. * used to initialize parent contracts.
  105. *
  106. * A reinitializer may be used after the original initialization step. This is essential to configure modules that
  107. * are added through upgrades and that require initialization.
  108. *
  109. * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
  110. * cannot be nested. If one is invoked in the context of another, execution will revert.
  111. *
  112. * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
  113. * a contract, executing them in the right order is up to the developer or operator.
  114. *
  115. * WARNING: setting the version to 255 will prevent any future reinitialization.
  116. *
  117. * Emits an {Initialized} event.
  118. */
  119. modifier reinitializer(uint8 version) {
  120. if (_initializing || _initialized >= version) {
  121. revert AlreadyInitialized();
  122. }
  123. _initialized = version;
  124. _initializing = true;
  125. _;
  126. _initializing = false;
  127. emit Initialized(version);
  128. }
  129. /**
  130. * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
  131. * {initializer} and {reinitializer} modifiers, directly or indirectly.
  132. */
  133. modifier onlyInitializing() {
  134. if (!_initializing) {
  135. revert NotInitializing();
  136. }
  137. _;
  138. }
  139. /**
  140. * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
  141. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
  142. * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
  143. * through proxies.
  144. *
  145. * Emits an {Initialized} event the first time it is successfully executed.
  146. */
  147. function _disableInitializers() internal virtual {
  148. if (_initializing) {
  149. revert AlreadyInitialized();
  150. }
  151. if (_initialized != type(uint8).max) {
  152. _initialized = type(uint8).max;
  153. emit Initialized(type(uint8).max);
  154. }
  155. }
  156. /**
  157. * @dev Returns the highest version that has been initialized. See {reinitializer}.
  158. */
  159. function _getInitializedVersion() internal view returns (uint8) {
  160. return _initialized;
  161. }
  162. /**
  163. * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
  164. */
  165. function _isInitializing() internal view returns (bool) {
  166. return _initializing;
  167. }
  168. }