ReentrancyGuard gas optimization (#1996)
* Improve gas efficiency of reentrancyGuard * Add changelog entry * Fix ReentrancyGuard test
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
### Improvements
|
### 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))
|
* `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))
|
* `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), [#1996](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1996))
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
* `ERC165Checker` now requires a minimum Solidity compiler version of 0.5.10. ([#1829](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1829))
|
* `ERC165Checker` now requires a minimum Solidity compiler version of 0.5.10. ([#1829](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1829))
|
||||||
|
|||||||
@ -16,13 +16,16 @@ pragma solidity ^0.5.0;
|
|||||||
* metering changes introduced in the Istanbul hardfork.
|
* metering changes introduced in the Istanbul hardfork.
|
||||||
*/
|
*/
|
||||||
contract ReentrancyGuard {
|
contract ReentrancyGuard {
|
||||||
// counter to allow mutex lock with only one SSTORE operation
|
bool private _notEntered;
|
||||||
uint256 private _guardCounter;
|
|
||||||
|
|
||||||
constructor () internal {
|
constructor () internal {
|
||||||
// The counter starts at one to prevent changing it from zero to a non-zero
|
// Storing an initial non-zero value makes deployment a bit more
|
||||||
// value, which is a more expensive operation.
|
// expensive, but in exchange the refund on every call to nonReentrant
|
||||||
_guardCounter = 1;
|
// will be lower in amount. Since refunds are capped to a percetange of
|
||||||
|
// the total transaction's gas, it is best to keep them low in cases
|
||||||
|
// like this one, to increase the likelihood of the full refund coming
|
||||||
|
// into effect.
|
||||||
|
_notEntered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,10 +36,16 @@ contract ReentrancyGuard {
|
|||||||
* `private` function that does the actual work.
|
* `private` function that does the actual work.
|
||||||
*/
|
*/
|
||||||
modifier nonReentrant() {
|
modifier nonReentrant() {
|
||||||
_guardCounter += 1;
|
// On the first call to nonReentrant, _notEntered will be true
|
||||||
uint256 localCounter = _guardCounter;
|
require(_notEntered, "ReentrancyGuard: reentrant call");
|
||||||
|
|
||||||
|
// Any calls to nonReentrant after this point will fail
|
||||||
|
_notEntered = false;
|
||||||
|
|
||||||
_;
|
_;
|
||||||
require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
|
|
||||||
_guardCounter = 1;
|
// By storing the original value once again, a refund is triggered (see
|
||||||
|
// https://eips.ethereum.org/EIPS/eip-2200)
|
||||||
|
_notEntered = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ contract('ReentrancyGuard', function () {
|
|||||||
it('should not allow remote callback', async function () {
|
it('should not allow remote callback', async function () {
|
||||||
const attacker = await ReentrancyAttack.new();
|
const attacker = await ReentrancyAttack.new();
|
||||||
await expectRevert(
|
await expectRevert(
|
||||||
this.reentrancyMock.countAndCall(attacker.address), 'ReentrancyGuard: reentrant call');
|
this.reentrancyMock.countAndCall(attacker.address), 'ReentrancyAttack: failed call');
|
||||||
});
|
});
|
||||||
|
|
||||||
// The following are more side-effects than intended behavior:
|
// The following are more side-effects than intended behavior:
|
||||||
|
|||||||
Reference in New Issue
Block a user