-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathReentrancyGuard.sol
64 lines (56 loc) · 2.53 KB
/
ReentrancyGuard.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.13;
import "./Initializable.sol";
import "./interfaces/IReentrancyGuard.sol";
import "../storage/Storage.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* NOTE: This contract has been extended from the Open Zeppelin library to include an
* unstructured storage pattern, so that it can be safely mixed in with upgradeable
* contracts without affecting their storage patterns through inheritance.
*/
abstract contract ReentrancyGuard is IReentrancyGuard, Initializable {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
/**
* @dev unstructured storage slot for the reentrancy status
*/
Uint256Storage private constant _status = Uint256Storage.wrap(keccak256("equilibria.root.ReentrancyGuard.status"));
/**
* @dev Initializes the contract setting the status to _NOT_ENTERED.
*/
function __ReentrancyGuard__initialize() internal onlyInitializer {
_status.store(_NOT_ENTERED);
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
if (_status.read() == _ENTERED) revert ReentrancyGuardReentrantCallError();
// Any calls to nonReentrant after this point will fail
_status.store(_ENTERED);
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status.store(_NOT_ENTERED);
}
}