Solidity EVM OpenZeppelin Contracts – How Do Abstract Classes Prevent Reentrancy for Multiple Accounts in Solidity?

evmopenzeppelin-contractssolidity

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:

  1. How is status not overridden when multiple users call the function?
  2. How does the value of the _status persist between calls?
  3. Is there something else that the EVM is doing that I'm missing?

Best Answer

The EVM is a single-threaded Turing Machine, no other user can capture it before the current contract's code is done executing (or is aborted).