From 7e32fe5906c0010b871551ced56d0483cd31c3dc Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 29 May 2023 21:23:36 +0200 Subject: [PATCH 1/4] remove Counters.sol --- CHANGELOG.md | 3 +- contracts/mocks/proxy/UUPSUpgradeableMock.sol | 7 +- contracts/utils/Counters.sol | 43 ---------- contracts/utils/Nonces.sol | 17 ++-- contracts/utils/README.adoc | 3 - docs/modules/ROOT/pages/erc721.adoc | 13 ++- docs/modules/ROOT/pages/utilities.adoc | 2 - test/utils/Counters.test.js | 84 ------------------- 8 files changed, 17 insertions(+), 155 deletions(-) delete mode 100644 contracts/utils/Counters.sol delete mode 100644 test/utils/Counters.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d2853cf887..2fc4cc5e348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ ### Removals -The following contracts were removed: +The following contracts and libraries were removed: +- `Counters` - `ERC20Snapshot` - `ERC20VotesComp` - `GovernorVotesComp` diff --git a/contracts/mocks/proxy/UUPSUpgradeableMock.sol b/contracts/mocks/proxy/UUPSUpgradeableMock.sol index f02271c498a..8b869bf226e 100644 --- a/contracts/mocks/proxy/UUPSUpgradeableMock.sol +++ b/contracts/mocks/proxy/UUPSUpgradeableMock.sol @@ -3,17 +3,16 @@ pragma solidity ^0.8.0; import "../../proxy/utils/UUPSUpgradeable.sol"; -import "../../utils/Counters.sol"; contract NonUpgradeableMock { - Counters.Counter internal _counter; + uint256 internal _counter; function current() external view returns (uint256) { - return Counters.current(_counter); + return _counter; } function increment() external { - return Counters.increment(_counter); + ++_counter; } } diff --git a/contracts/utils/Counters.sol b/contracts/utils/Counters.sol deleted file mode 100644 index 8a4f2a2e72f..00000000000 --- a/contracts/utils/Counters.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) - -pragma solidity ^0.8.0; - -/** - * @title Counters - * @author Matt Condon (@shrugs) - * @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;` - */ -library Counters { - struct Counter { - // This variable should never be directly accessed by users of the library: interactions must be restricted to - // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add - // this feature: see https://github.com/ethereum/solidity/issues/4637 - uint256 _value; // default: 0 - } - - function current(Counter storage counter) internal view returns (uint256) { - return counter._value; - } - - function increment(Counter storage counter) internal { - unchecked { - counter._value += 1; - } - } - - function decrement(Counter storage counter) internal { - uint256 value = counter._value; - require(value > 0, "Counter: decrement overflow"); - unchecked { - counter._value = value - 1; - } - } - - function reset(Counter storage counter) internal { - counter._value = 0; - } -} diff --git a/contracts/utils/Nonces.sol b/contracts/utils/Nonces.sol index ce65909ffc4..493bbe1a28d 100644 --- a/contracts/utils/Nonces.sol +++ b/contracts/utils/Nonces.sol @@ -1,21 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./Counters.sol"; - /** * @dev Provides tracking nonces for addresses. Nonces will only increment. */ abstract contract Nonces { - using Counters for Counters.Counter; - - mapping(address => Counters.Counter) private _nonces; + mapping(address => uint256) private _nonces; /** * @dev Returns an address nonce. */ function nonces(address owner) public view virtual returns (uint256) { - return _nonces[owner].current(); + return _nonces[owner]; } /** @@ -23,9 +19,10 @@ abstract contract Nonces { * * Returns the current value and increments nonce. */ - function _useNonce(address owner) internal virtual returns (uint256 current) { - Counters.Counter storage nonce = _nonces[owner]; - current = nonce.current(); - nonce.increment(); + function _useNonce(address owner) internal virtual returns (uint256) { + unchecked { + // It is important to do x++ and not ++x here. + return _nonces[owner]++; + } } } diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 07cee64270c..aa5182bd1af 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -10,7 +10,6 @@ The {Address}, {Arrays}, {Base64} and {Strings} libraries provide more operation For new data types: - * {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. @@ -75,8 +74,6 @@ Ethereum contracts have no native concept of an interface, so applications must {{Base64}} -{{Counters}} - {{Strings}} {{ShortStrings}} diff --git a/docs/modules/ROOT/pages/erc721.adoc b/docs/modules/ROOT/pages/erc721.adoc index 812630ab39f..76ca39c3aa5 100644 --- a/docs/modules/ROOT/pages/erc721.adoc +++ b/docs/modules/ROOT/pages/erc721.adoc @@ -17,11 +17,9 @@ Here's what a contract for tokenized items might look like: pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; -import "@openzeppelin/contracts/utils/Counters.sol"; contract GameItem is ERC721URIStorage { - using Counters for Counters.Counter; - Counters.Counter private _tokenIds; + uint256 private _nextTokenId; constructor() ERC721("GameItem", "ITM") {} @@ -29,12 +27,11 @@ contract GameItem is ERC721URIStorage { public returns (uint256) { - uint256 newItemId = _tokenIds.current(); - _mint(player, newItemId); - _setTokenURI(newItemId, tokenURI); + uint256 tokenId = _nextTokenId++; + _mint(player, tokenId); + _setTokenURI(tokenId, tokenURI); - _tokenIds.increment(); - return newItemId; + return tokenId; } } ---- diff --git a/docs/modules/ROOT/pages/utilities.adoc b/docs/modules/ROOT/pages/utilities.adoc index eecb8293ea2..1dadeb9992c 100644 --- a/docs/modules/ROOT/pages/utilities.adoc +++ b/docs/modules/ROOT/pages/utilities.adoc @@ -97,8 +97,6 @@ If you need support for more powerful collections than Solidity's native arrays [[misc]] == Misc -Want to keep track of some numbers that increment by 1 every time you want another one? Check out xref:api:utils.adoc#Counters[`Counters`]. This is useful for lots of things, like creating incremental identifiers, as shown on the xref:erc721.adoc[ERC721 guide]. - === Base64 xref:api:utils.adoc#Base64[`Base64`] util allows you to transform `bytes32` data into its Base64 `string` representation. diff --git a/test/utils/Counters.test.js b/test/utils/Counters.test.js deleted file mode 100644 index 6fb89922d36..00000000000 --- a/test/utils/Counters.test.js +++ /dev/null @@ -1,84 +0,0 @@ -const { expectRevert } = require('@openzeppelin/test-helpers'); - -const { expect } = require('chai'); - -const Counters = artifacts.require('$Counters'); - -contract('Counters', function () { - beforeEach(async function () { - this.counter = await Counters.new(); - }); - - it('starts at zero', async function () { - expect(await this.counter.$current(0)).to.be.bignumber.equal('0'); - }); - - describe('increment', function () { - context('starting from 0', function () { - it('increments the current value by one', async function () { - await this.counter.$increment(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('1'); - }); - - it('can be called multiple times', async function () { - await this.counter.$increment(0); - await this.counter.$increment(0); - await this.counter.$increment(0); - - expect(await this.counter.$current(0)).to.be.bignumber.equal('3'); - }); - }); - }); - - describe('decrement', function () { - beforeEach(async function () { - await this.counter.$increment(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('1'); - }); - context('starting from 1', function () { - it('decrements the current value by one', async function () { - await this.counter.$decrement(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('0'); - }); - - it('reverts if the current value is 0', async function () { - await this.counter.$decrement(0); - await expectRevert(this.counter.$decrement(0), 'Counter: decrement overflow'); - }); - }); - context('after incremented to 3', function () { - it('can be called multiple times', async function () { - await this.counter.$increment(0); - await this.counter.$increment(0); - - expect(await this.counter.$current(0)).to.be.bignumber.equal('3'); - - await this.counter.$decrement(0); - await this.counter.$decrement(0); - await this.counter.$decrement(0); - - expect(await this.counter.$current(0)).to.be.bignumber.equal('0'); - }); - }); - }); - - describe('reset', function () { - context('null counter', function () { - it('does not throw', async function () { - await this.counter.$reset(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('0'); - }); - }); - - context('non null counter', function () { - beforeEach(async function () { - await this.counter.$increment(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('1'); - }); - it('reset to 0', async function () { - await this.counter.$reset(0); - expect(await this.counter.$current(0)).to.be.bignumber.equal('0'); - }); - }); - }); -}); From bb843fcaef43c37f944f20d68375189fe2fb7cb0 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 30 May 2023 15:57:13 +0200 Subject: [PATCH 2/4] Update Nonces.sol --- contracts/utils/Nonces.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/utils/Nonces.sol b/contracts/utils/Nonces.sol index 07a63f5787d..8d9b08746cf 100644 --- a/contracts/utils/Nonces.sol +++ b/contracts/utils/Nonces.sol @@ -20,6 +20,8 @@ abstract contract Nonces { * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { + // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be + // decremented or reset. This guarantees that the nonce never overflows. unchecked { // It is important to do x++ and not ++x here. return _nonces[owner]++; From e8c5dfb8c6002ac2fc2ee22a7899d190dc7d3e94 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 30 May 2023 17:52:52 -0300 Subject: [PATCH 3/4] lint --- contracts/utils/Nonces.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/Nonces.sol b/contracts/utils/Nonces.sol index 8d9b08746cf..04b884797e1 100644 --- a/contracts/utils/Nonces.sol +++ b/contracts/utils/Nonces.sol @@ -20,7 +20,7 @@ abstract contract Nonces { * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { - // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be + // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be // decremented or reset. This guarantees that the nonce never overflows. unchecked { // It is important to do x++ and not ++x here. From 943603405b123519b51c748698ebb68408b12ecc Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Wed, 31 May 2023 00:08:16 -0300 Subject: [PATCH 4/4] fix test --- test/utils/Nonces.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/Nonces.test.js b/test/utils/Nonces.test.js index a09cddb1f2a..4a01bb1bc8d 100644 --- a/test/utils/Nonces.test.js +++ b/test/utils/Nonces.test.js @@ -19,7 +19,7 @@ contract('Nonces', function (accounts) { expect(await this.nonces.nonces(sender)).to.be.bignumber.equal('0'); const { receipt } = await this.nonces.$_useNonce(sender); - expectEvent(receipt, 'return$_useNonce', { current: '0' }); + expectEvent(receipt, 'return$_useNonce', ['0']); expect(await this.nonces.nonces(sender)).to.be.bignumber.equal('1'); });