Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/good-cameras-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableMap`: Add `clear` function to EnumerableMaps which deletes all entries in the map.
5 changes: 5 additions & 0 deletions .changeset/sixty-tips-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`EnumerableSet`: Add `clear` function to EnumerableSets which deletes all values in the set.
95 changes: 95 additions & 0 deletions contracts/utils/structs/EnumerableMap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
* - Map can be cleared (all entries removed) in O(n).
*
* ```solidity
* contract Example {
Expand Down Expand Up @@ -90,6 +91,20 @@ library EnumerableMap {
return map._keys.remove(key);
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToBytes32Map storage map) internal {
uint256 len = length(map);
for (uint256 i = 0; i < len; ++i) {
delete map._values[map._keys.at(i)];
}
map._keys.clear();
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -185,6 +200,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(key));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToUintMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -278,6 +303,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(key));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToAddressMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -371,6 +406,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(key));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToBytes32Map storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -464,6 +509,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(uint256(uint160(key))));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToUintMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -557,6 +612,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(uint256(uint160(key))));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToAddressMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -650,6 +715,16 @@ library EnumerableMap {
return remove(map._inner, bytes32(uint256(uint160(key))));
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToBytes32Map storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -743,6 +818,16 @@ library EnumerableMap {
return remove(map._inner, key);
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToUintMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -836,6 +921,16 @@ library EnumerableMap {
return remove(map._inner, key);
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToAddressMap storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down
64 changes: 64 additions & 0 deletions contracts/utils/structs/EnumerableSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

pragma solidity ^0.8.20;

import {Arrays} from "../Arrays.sol";
import {Hashes} from "../cryptography/Hashes.sol";

/**
Expand All @@ -16,6 +17,7 @@ import {Hashes} from "../cryptography/Hashes.sol";
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
* - Set can be cleared (all elements removed) in O(n).
*
* ```solidity
* contract Example {
Expand Down Expand Up @@ -116,6 +118,20 @@ library EnumerableSet {
}
}

/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function _clear(Set storage set) private {
uint256 len = _length(set);
for (uint256 i = 0; i < len; ++i) {
delete set._positions[set._values[i]];
}
Arrays.unsafeSetLength(set._values, 0);
}

/**
* @dev Returns true if the value is in the set. O(1).
*/
Expand Down Expand Up @@ -182,6 +198,16 @@ library EnumerableSet {
return _remove(set._inner, value);
}

/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32Set storage set) internal {
_clear(set._inner);
}

/**
* @dev Returns true if the value is in the set. O(1).
*/
Expand Down Expand Up @@ -255,6 +281,16 @@ library EnumerableSet {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}

/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressSet storage set) internal {
_clear(set._inner);
}

/**
* @dev Returns true if the value is in the set. O(1).
*/
Expand Down Expand Up @@ -328,6 +364,16 @@ library EnumerableSet {
return _remove(set._inner, bytes32(value));
}

/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintSet storage set) internal {
_clear(set._inner);
}

/**
* @dev Returns true if the value is in the set. O(1).
*/
Expand Down Expand Up @@ -442,6 +488,24 @@ library EnumerableSet {
}
}

/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32x2Set storage self) internal {
bytes32[2][] storage v = self._values;

uint256 len = length(self);
for (uint256 i = 0; i < len; ++i) {
delete self._positions[_hash(v[i])];
}
assembly ("memory-safe") {
sstore(v.slot, 0)
}
}

/**
* @dev Returns true if the value is in the self. O(1).
*/
Expand Down
25 changes: 25 additions & 0 deletions scripts/generate/templates/EnumerableMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
* - Map can be cleared (all entries removed) in O(n).
*
* \`\`\`solidity
* contract Example {
Expand Down Expand Up @@ -91,6 +92,20 @@ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (
return map._keys.remove(key);
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToBytes32Map storage map) internal {
uint256 len = length(map);
for (uint256 i = 0; i < len; ++i) {
delete map._values[map._keys.at(i)];
}
map._keys.clear();
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down Expand Up @@ -188,6 +203,16 @@ function remove(${name} storage map, ${keyType} key) internal returns (bool) {
return remove(map._inner, ${toBytes32(keyType, 'key')});
}

/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(${name} storage map) internal {
clear(map._inner);
}

/**
* @dev Returns true if the key is in the map. O(1).
*/
Expand Down
Loading