|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | +pragma solidity 0.8.24; |
| 3 | +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; |
| 4 | + |
| 5 | +/** |
| 6 | + * @dev Variant of {ReentrancyGuard} that uses transient storage. |
| 7 | + * Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol |
| 8 | + * For detailed context on reentrancy guard check https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/ReentrancyGuardUpgradeable.sol |
| 9 | + * For detailed context on EIP1153(Transient Storage) check https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1153.md |
| 10 | + * |
| 11 | + */ |
| 12 | +abstract contract ReentrancyGuardTransientUpgradable is Initializable { |
| 13 | + /** |
| 14 | + * @dev Unauthorized reentrant call. |
| 15 | + */ |
| 16 | + error ReentrancyGuardReentrantCall(); |
| 17 | + |
| 18 | + uint256 private constant _NOT_ENTERED = 0; |
| 19 | + uint256 private constant _ENTERED = 1; |
| 20 | + |
| 21 | + // @notice acts as the storage slot in transient storage |
| 22 | + // avoiding the use of a namespace storage slot, to avoid storage collisions with upgrades |
| 23 | + uint256 _status; |
| 24 | + |
| 25 | + function __ReentrancyGuardTransient_init() internal onlyInitializing { |
| 26 | + __ReentrancyGuardTransient_init_unchained(); |
| 27 | + } |
| 28 | + |
| 29 | + function __ReentrancyGuardTransient_init_unchained() internal onlyInitializing {} |
| 30 | + |
| 31 | + /** |
| 32 | + * @dev Prevents a contract from calling itself, directly or indirectly. |
| 33 | + * Calling a `nonReentrant` function from another `nonReentrant` |
| 34 | + * function is not supported. It is possible to prevent this from happening |
| 35 | + * by making the `nonReentrant` function external, and making it call a |
| 36 | + * `private` function that does the actual work. |
| 37 | + */ |
| 38 | + modifier nonReentrant() { |
| 39 | + _nonReentrantBefore(); |
| 40 | + _; |
| 41 | + _nonReentrantAfter(); |
| 42 | + } |
| 43 | + |
| 44 | + function _nonReentrantBefore() private { |
| 45 | + // On the first call to nonReentrant, _status will be NOT_ENTERED |
| 46 | + if (_get() != _NOT_ENTERED) revert ReentrancyGuardReentrantCall(); |
| 47 | + |
| 48 | + // Any calls to nonReentrant after this point will fail |
| 49 | + _set(_ENTERED); |
| 50 | + } |
| 51 | + |
| 52 | + function _nonReentrantAfter() private { |
| 53 | + _set(_NOT_ENTERED); |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * @dev Store `value` at location `slot` in transient storage. |
| 58 | + */ |
| 59 | + function _set(uint256 value) internal { |
| 60 | + assembly ("memory-safe") { |
| 61 | + let slot := _status.slot |
| 62 | + tstore(slot, value) |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + /** |
| 67 | + * @dev Load the value held at location `slot` in transient storage. |
| 68 | + */ |
| 69 | + function _get() internal view returns (uint256 value) { |
| 70 | + assembly ("memory-safe") { |
| 71 | + let slot := _status.slot |
| 72 | + value := tload(slot) |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * @dev This empty reserved space is put in place to allow future versions to add new |
| 78 | + * variables without shifting down storage in the inheritance chain. |
| 79 | + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps |
| 80 | + */ |
| 81 | + uint256[49] private __gap; |
| 82 | +} |
0 commit comments