2

Following is code for a re-entrancy guard, but not sure if I understand it properly:

contract Test {
    using SafeMath for uint256;
    uint256 private counter = 1;
    modifier entrancyGuard() {
        counter = counter.add(1); // counter adds 1 to the existing 1 so becomes 2
        uint256 guard = counter; // assigns 2 to the "guard" variable
        _;
        require(guard == counter, "That is not allowed"); // 2 == 2? 
    }

    function safeWithdraw(uint256 amount) external entrancyGuard() {
        // Withdraw code
    }
}

I'm not sure how the modifier prevents re-entrancy.

  • Is this from Udacity course? I had a hard time trying to wrap my head around this when i first saw this code. I tried a few dry runs and it seemed to fail.Also it would be simple to use a boolean/mutex lock sort of solution like OpenZeppelin does. @abcoathup has already put the link in answer. I would recommend to follow the solution as given in OpenZeppelin contract instead. – Imdad May 15 at 4:27
2

The code:

modifier modi() {
    prolog();
    _;
    epilog();
}
function func() modi() {
    stuff();
}

Is equivalent to:

function func() {
    prolog();
    stuff();
    epilog();
}

If func is re-entered (i.e., called from within the execution of stuff), then prolog is executed a second time before epilog was executed for the first time.

So by identifying and reverting upon a scenario in which prolog is executed a second time before epilog was executed for the first time, we can guard func from being re-entered.

| improve this answer | |
3

My understanding is that:

  1. The counter is incremented
  2. A copy of the value of counter is kept
  3. Control is returned (https://solidity.readthedocs.io/en/v0.6.8/contracts.html#function-modifiers)
  4. There could be reentrancy where the counter would be incremented
  5. A check is made that the copy of the counter value still equals the counter otherwise it reverts

You may want to look at the OpenZeppelin Contracts implementation: Documentation: https://docs.openzeppelin.com/contracts/3.x/api/utils#ReentrancyGuard Code: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.1/contracts/utils/ReentrancyGuard.sol

I also suggest looking at the following post on Reentrancy: https://forum.openzeppelin.com/t/reentrancy-after-istanbul/1742

Disclosure: I am the Community Manager at OpenZeppelin

If you have questions on using OpenZeppelin you can also ask in the Community Forum: https://forum.openzeppelin.com/

| improve this answer | |
  • I'm still a bit confused. When there is reentrancy after the first run, does the counter outside of entrancyGuard() get reset to 1 through uint256 private counter = 1; and the variable uint256 guard, which is inside of entrancyGuard(), remain at 2? The Open Zeppelin document you referred to makes more sense to me because _notEntered = true; is set AFTER the function in question is run, whereas my example sets counter to be equal to the guard uint256 guard = counter;before the function is run. – Kevvv May 15 at 14:45
  • counter is updated to 3 when there is reentrancy whilst the original guard remains at 2 causing a revert. – abcoathup May 21 at 10:49

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.