diff --git a/CHANGELOG.md b/CHANGELOG.md index 704593f69..b647cabe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## Unreleased + * Enumerables: Improve gas cost of removal in `EnumerableSet` and `EnumerableMap`. + ## Unreleased * `IERC20Metadata`: add a new extended interface that includes the optional `name()`, `symbol()` and `decimals()` functions. ([#2561](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2561)) diff --git a/contracts/utils/structs/EnumerableSet.sol b/contracts/utils/structs/EnumerableSet.sol index 6b0107219..0b9903bee 100644 --- a/contracts/utils/structs/EnumerableSet.sol +++ b/contracts/utils/structs/EnumerableSet.sol @@ -81,15 +81,14 @@ library EnumerableSet { uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; - // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs - // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. + if (lastIndex != toDeleteIndex) { + bytes32 lastvalue = set._values[lastIndex]; - bytes32 lastvalue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastvalue; - // Update the index for the moved value - set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex + // Move the last value to the index where the value to delete is + set._values[toDeleteIndex] = lastvalue; + // Update the index for the moved value + set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex + } // Delete the slot where the moved value was stored set._values.pop();