Solidity – How Does the Re-entrancy Guard Modifier Work?

modifiersreentrant-attackssolidity

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.

Best Answer

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.

Related Topic