1

I'm concerned about the security of the Reentrancy pattern that we can use in Solidity to prevent from calling multiple times a same function at the same time. This protection is nicely implemented here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol. But for my question, I did a smaller version merging the code of the modifier inside the function:

contract Contract1 {
    bool locked;

    function f() external {
        require(!locked, "Reentrant call");
        locked = true;
        // Do something
        locked = false;
    }
}

According to my understanding, in Solidity, on the Ethereum Virtual Machine, it is impossible to execute more than 1 instruction at a time, each instruction is executed sequentially, not in parallel. That's why before to execute locked = true, first require(!locked, "Reentrant call") have to be executed (and valid).

But would there be a possibility for 2 concurrent requests (let's say from user A and user B, or even from the same user) on f() to sequentially execute those instructions in this order:

  1. require(!locked, "Reentrant call")
  2. require(!locked, "Reentrant call") (which would also be valid at this stage)
  3. locked = true
  4. locked = true

If so, // Do something would be executed twice.

0

But would there be a possibility for 2 concurrent requests?

There can be many concurrent requests for miners to execute many different transactions, all calling the same function in the same contract.

So far your concern is in place.

But once a transaction is executed (i.e., added to the blockchain), it is executed atomically until completion.

So you can rest assure that your protection method works as intended.

Side note:

Instead of toggling bool locked between false and true, you can toggle uint locked between 1 and 2. This will reduce your method's gas consumption significantly, because changing a state variable from zero to non-zero costs a lot more than changing it from non-zero to non-zero.

4
  • Thank you for these explanations. But then I wonder, if transactions are executed atomically, isn't my reentrancy protection useless? I mean, if f() is executed atomically, it should not be possible to execute it more than once at a time, right? and so I should be able to remove the reentrancy protection. Sorry, I'm trying to fully understand the behavior. – Doug Nov 20 '20 at 16:40
  • 1
    @Doug: No. Reentrancy is still possible, for example, if in the Do something part you call some function in some other contract. And that includes transferring ETH to that other contract, which subsequently invokes the fallback function or the receive function in that contract. – goodvibration Nov 20 '20 at 16:46
  • 1
    Thanks to you I'm beginning to understand. I appreciate your help a lot. – Doug Nov 20 '20 at 16:52
  • @Doug: Of course, your mechanism will prevent that other contract function (the one executed from the Do something part) from re-entering your contract function. – goodvibration Nov 20 '20 at 17:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.