Browse Source

Add ReentrancyGuard status getter (#3714)

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
zhiqiangxu 3 years ago
parent
commit
eb03304b70

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 # Changelog
 
+## Unreleased
+
+ * `ReentrancyGuard`: Add a `_reentrancyGuardEntered` function to expose the guard status. ([#3714](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3714))
+
 ## Unreleased
 
  * `TimelockController`: Added a new `admin` constructor parameter that is assigned the admin role instead of the deployer account. ([#3722](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3722))

+ 8 - 0
contracts/mocks/ReentrancyMock.sol

@@ -40,4 +40,12 @@ contract ReentrancyMock is ReentrancyGuard {
     function _count() private {
         counter += 1;
     }
+
+    function guardedCheckEntered() public nonReentrant {
+        require(_reentrancyGuardEntered());
+    }
+
+    function unguardedCheckNotEntered() public view {
+        require(!_reentrancyGuardEntered());
+    }
 }

+ 8 - 0
contracts/security/ReentrancyGuard.sol

@@ -66,4 +66,12 @@ abstract contract ReentrancyGuard {
         // https://eips.ethereum.org/EIPS/eip-2200)
         _status = _NOT_ENTERED;
     }
+
+    /**
+     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
+     * `nonReentrant` function in the call stack.
+     */
+    function _reentrancyGuardEntered() internal view returns (bool) {
+        return _status == _ENTERED;
+    }
 }

+ 8 - 0
test/security/ReentrancyGuard.test.js

@@ -23,6 +23,14 @@ contract('ReentrancyGuard', function (accounts) {
       this.reentrancyMock.countAndCall(attacker.address), 'ReentrancyAttack: failed call');
   });
 
+  it('_reentrancyGuardEntered should be true when guarded', async function () {
+    await this.reentrancyMock.guardedCheckEntered();
+  });
+
+  it('_reentrancyGuardEntered should be false when unguarded', async function () {
+    await this.reentrancyMock.unguardedCheckNotEntered();
+  });
+
   // The following are more side-effects than intended behavior:
   // I put them here as documentation, and to monitor any changes
   // in the side-effects.