diff --git a/CHANGELOG.md b/CHANGELOG.md index c98ce623b1e..3b5b96c6d9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * `ReentrancyGuard`: Add a `_reentrancyGuardEntered` function to expose the guard status. ([#3714](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3714)) + * `ERC20Votes`: optimize by using unchecked arithmetic. ([#3748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3748)) ## Unreleased diff --git a/contracts/token/ERC20/extensions/ERC20Votes.sol b/contracts/token/ERC20/extensions/ERC20Votes.sol index da16cbada52..581d4f0f3b8 100644 --- a/contracts/token/ERC20/extensions/ERC20Votes.sol +++ b/contracts/token/ERC20/extensions/ERC20Votes.sol @@ -63,7 +63,9 @@ abstract contract ERC20Votes is IVotes, ERC20Permit { */ function getVotes(address account) public view virtual override returns (uint256) { uint256 pos = _checkpoints[account].length; - return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + unchecked { + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } } /** @@ -80,7 +82,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit { /** * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. - * It is but NOT the sum of all the delegated votes! + * It is NOT the sum of all the delegated votes! * * Requirements: * @@ -130,7 +132,9 @@ abstract contract ERC20Votes is IVotes, ERC20Permit { } } - return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes; + unchecked { + return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes; + } } /** @@ -243,15 +247,19 @@ abstract contract ERC20Votes is IVotes, ERC20Permit { ) private returns (uint256 oldWeight, uint256 newWeight) { uint256 pos = ckpts.length; - Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1); + unchecked { + Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1); - oldWeight = oldCkpt.votes; - newWeight = op(oldWeight, delta); + oldWeight = oldCkpt.votes; + newWeight = op(oldWeight, delta); - if (pos > 0 && oldCkpt.fromBlock == block.number) { - _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight); - } else { - ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)})); + if (pos > 0 && oldCkpt.fromBlock == block.number) { + _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight); + } else { + ckpts.push( + Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}) + ); + } } }