From 33047ffddcc81ba7b0349431c5065c448603d098 Mon Sep 17 00:00:00 2001 From: ericDeCourcy <19626305+ericDeCourcy@users.noreply.github.com> Date: Wed, 13 Nov 2019 10:54:15 -0700 Subject: [PATCH] Update ReentrancyGuard for Istanbul Hard Fork (#1992) * Update ReentrancyGuard for Istanbul Hard Fork Changes: Added L37, `_guardCounter = 1;` Rationale: The planned _Istanbul Hard Fork_ will implement [EIP 2200](https://github.com/ethereum/EIPs/blob/e4d4ea348e06c54d0075c400dc7b72430d427ff1/EIPS/eip-2200.md), which implements "net gas metering" for `sstore` operations. If the final value of `_guardCounter` is unchanged relative to the original value of it, a gas refund will be applied and charges for changing the value of `_guardCounter` will effectively not exist. This ends up being cheaper than the current implementation ONLY AFTER Istanbul. Before Istanbul, the added line actually ends up costing more gas. Note that if `_guardCounter` is `0` initially, the initial cost and subsequent refund will both be larger than if `_guardCounter` is `1` initially. Although in both cases, the net gas cost (`gasCost - gasRefund`) are equal, it's better in terms of cost to have both the gas cost and refund smaller, as there is some limit to the percentage of a gas refund that can actually be realized. * Update CHANGELOG.md Added note for change to ReentrancyGuard.sol * Update ReentrancyGuard.sol * Update CHANGELOG.md --- CHANGELOG.md | 1 + contracts/utils/ReentrancyGuard.sol | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4972caf14..33da09d44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Improvements * `ERC777`: `_burn` is now internal, providing more flexibility and making it easier to create tokens that deflate. ([#1908](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1908)) + * `ReentrancyGuard`: greatly improved gas efficiency by using the net gas metering mechanism introduced in the Istanbul hardfork. ([#1992](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1992)) ### Breaking changes * `ERC165Checker` now requires a minimum Solidity compiler version of 0.5.10. ([#1829](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1829)) diff --git a/contracts/utils/ReentrancyGuard.sol b/contracts/utils/ReentrancyGuard.sol index 4015cdec6..7804893af 100644 --- a/contracts/utils/ReentrancyGuard.sol +++ b/contracts/utils/ReentrancyGuard.sol @@ -11,6 +11,9 @@ pragma solidity ^0.5.0; * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. + * + * _Since v2.5.0:_ this module is now much more gas efficient, given net gas + * metering changes introduced in the Istanbul hardfork. */ contract ReentrancyGuard { // counter to allow mutex lock with only one SSTORE operation @@ -34,5 +37,6 @@ contract ReentrancyGuard { uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); + _guardCounter = 1; } }