Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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 items 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
47 changes: 47 additions & 0 deletions contracts/utils/structs/EnumerableSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

pragma solidity ^0.8.20;

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

/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
Expand All @@ -14,6 +16,7 @@ pragma solidity ^0.8.20;
* - 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 @@ -114,6 +117,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 @@ -180,6 +197,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 @@ -253,6 +280,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 @@ -326,6 +363,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
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
27 changes: 27 additions & 0 deletions scripts/generate/templates/EnumerableSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const { TYPES } = require('./EnumerableSet.opts');
const header = `\
pragma solidity ^0.8.20;

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

/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
Expand All @@ -15,6 +17,7 @@ pragma solidity ^0.8.20;
* - 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 @@ -117,6 +120,20 @@ function _remove(Set storage set, bytes32 value) private returns (bool) {
}
}

/**
* @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 @@ -185,6 +202,16 @@ function remove(${name} storage set, ${type} value) internal returns (bool) {
return _remove(set._inner, ${toBytes32(type, '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(${name} storage set) internal {
_clear(set._inner);
}

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