I was reading through the openZeppelin contracts and saw the ReentrancyGuard contract, and realized I don't know how the EVM deals with these contracts.
Assuming you have a class:
contract someClass is ReentrancyGuard{
function giveMeMyEther() external nonReentrant{
//transfer ether from contract to sender;
}
}
What's happening with the nonReentrant
modifier? It looks like multiple users would be overwriting each other's reentrancy locks all the time.
What I would expect is that it would modify the _status on someClass
, which would (in effect) be a global lock on the contract. I would expect to need something more like mapping(address=>uint256)
to track reentrancy per user.
Based upon its widespread use, I assume that I don't understand what's going on in the EVM.
Here's the code for the current reentrancy guard modifier for openZeppelin:
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
Questions:
- How is status not overridden when multiple users call the function?
- How does the value of the _status persist between calls?
- Is there something else that the EVM is doing that I'm missing?