From ee9fb3b48f08aae855e58bfd24442d780c749793 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 17 May 2021 19:00:39 +0200 Subject: [PATCH 1/3] add a reset function on counter --- contracts/mocks/CountersImpl.sol | 4 ++++ contracts/utils/Counters.sol | 6 ++++++ test/utils/Counters.test.js | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/contracts/mocks/CountersImpl.sol b/contracts/mocks/CountersImpl.sol index 108142e39a7..651b50baf72 100644 --- a/contracts/mocks/CountersImpl.sol +++ b/contracts/mocks/CountersImpl.sol @@ -20,4 +20,8 @@ contract CountersImpl { function decrement() public { _counter.decrement(); } + + function reset() public { + _counter.reset(); + } } diff --git a/contracts/utils/Counters.sol b/contracts/utils/Counters.sol index 746a2631eca..fcffbba6db9 100644 --- a/contracts/utils/Counters.sol +++ b/contracts/utils/Counters.sol @@ -35,4 +35,10 @@ library Counters { counter._value = value - 1; } } + + function reset(Counter storage counter) internal { + unchecked { + counter._value = 0; + } + } } diff --git a/test/utils/Counters.test.js b/test/utils/Counters.test.js index 90a1ae8453e..04be4c0c8bd 100644 --- a/test/utils/Counters.test.js +++ b/test/utils/Counters.test.js @@ -61,4 +61,24 @@ contract('Counters', function (accounts) { }); }); }); + + describe('reset', function () { + context('null counter', function () { + it('does not throw', async function () { + await this.counter.reset(); + expect(await this.counter.current()).to.be.bignumber.equal('0'); + }); + }); + + context('non null counter', function () { + beforeEach(async function () { + await this.counter.increment(); + expect(await this.counter.current()).to.be.bignumber.equal('1'); + }); + it('reset to 0', async function () { + await this.counter.reset(); + expect(await this.counter.current()).to.be.bignumber.equal('0'); + }); + }); + }); }); From bbe472f06ca75621d2eb11655a5ff035741f4085 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 17 May 2021 19:04:19 +0200 Subject: [PATCH 2/3] Add changelog entry and fix documentation --- CHANGELOG.md | 1 + contracts/utils/Counters.sol | 2 +- contracts/utils/README.adoc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f24736d3db7..27d09e50267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * `ERC20Votes`: add a new extension of the `ERC20` token with support for voting snapshots and delegation. This extension is compatible with Compound's `Comp` token interface. ([#2632](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2632)) * Enumerables: Improve gas cost of removal in `EnumerableSet` and `EnumerableMap`. * Enumerables: Improve gas cost of lookup in `EnumerableSet` and `EnumerableMap`. + * `Counter`: add a reset method. ([#2678](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2678)) ## 4.1.0 (2021-04-29) diff --git a/contracts/utils/Counters.sol b/contracts/utils/Counters.sol index fcffbba6db9..75f49f9757c 100644 --- a/contracts/utils/Counters.sol +++ b/contracts/utils/Counters.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) - * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number + * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 7e28047b645..ae5c38a50a9 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -10,7 +10,7 @@ The {Address}, {Arrays} and {Strings} libraries provide more operations related For new data types: - * {Counters}: a simple way to get a counter that can only be incremented or decremented. Very useful for ID generation, counting contract activity, among others. + * {Counters}: a simple way to get a counter that can only be incremented, decremented or reset. Very useful for ID generation, counting contract activity, among others. * {EnumerableMap}: like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] type, but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`). * {EnumerableSet}: like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc. From 0b9696325f4ad3fbc0894e3254917a5d4248f857 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 18 May 2021 18:30:09 +0200 Subject: [PATCH 3/3] remove unecessary unchecked block --- contracts/utils/Counters.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/utils/Counters.sol b/contracts/utils/Counters.sol index 75f49f9757c..624055ce408 100644 --- a/contracts/utils/Counters.sol +++ b/contracts/utils/Counters.sol @@ -37,8 +37,6 @@ library Counters { } function reset(Counter storage counter) internal { - unchecked { - counter._value = 0; - } + counter._value = 0; } }