Skip to content

Commit f740084

Browse files
authored
Revert "Add Bytes32x2Set (#5442)" (#5569)
1 parent ca7a4e3 commit f740084

File tree

5 files changed

+10
-288
lines changed

5 files changed

+10
-288
lines changed

.changeset/lucky-teachers-sip.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

contracts/utils/structs/EnumerableSet.sol

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
pragma solidity ^0.8.20;
66

77
import {Arrays} from "../Arrays.sol";
8-
import {Hashes} from "../cryptography/Hashes.sol";
98

109
/**
1110
* @dev Library for managing
@@ -420,133 +419,4 @@ library EnumerableSet {
420419

421420
return result;
422421
}
423-
424-
struct Bytes32x2Set {
425-
// Storage of set values
426-
bytes32[2][] _values;
427-
// Position is the index of the value in the `values` array plus 1.
428-
// Position 0 is used to mean a value is not in the self.
429-
mapping(bytes32 valueHash => uint256) _positions;
430-
}
431-
432-
/**
433-
* @dev Add a value to a self. O(1).
434-
*
435-
* Returns true if the value was added to the set, that is if it was not
436-
* already present.
437-
*/
438-
function add(Bytes32x2Set storage self, bytes32[2] memory value) internal returns (bool) {
439-
if (!contains(self, value)) {
440-
self._values.push(value);
441-
// The value is stored at length-1, but we add 1 to all indexes
442-
// and use 0 as a sentinel value
443-
self._positions[_hash(value)] = self._values.length;
444-
return true;
445-
} else {
446-
return false;
447-
}
448-
}
449-
450-
/**
451-
* @dev Removes a value from a self. O(1).
452-
*
453-
* Returns true if the value was removed from the set, that is if it was
454-
* present.
455-
*/
456-
function remove(Bytes32x2Set storage self, bytes32[2] memory value) internal returns (bool) {
457-
// We cache the value's position to prevent multiple reads from the same storage slot
458-
bytes32 valueHash = _hash(value);
459-
uint256 position = self._positions[valueHash];
460-
461-
if (position != 0) {
462-
// Equivalent to contains(self, value)
463-
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
464-
// the array, and then remove the last element (sometimes called as 'swap and pop').
465-
// This modifies the order of the array, as noted in {at}.
466-
467-
uint256 valueIndex = position - 1;
468-
uint256 lastIndex = self._values.length - 1;
469-
470-
if (valueIndex != lastIndex) {
471-
bytes32[2] memory lastValue = self._values[lastIndex];
472-
473-
// Move the lastValue to the index where the value to delete is
474-
self._values[valueIndex] = lastValue;
475-
// Update the tracked position of the lastValue (that was just moved)
476-
self._positions[_hash(lastValue)] = position;
477-
}
478-
479-
// Delete the slot where the moved value was stored
480-
self._values.pop();
481-
482-
// Delete the tracked position for the deleted slot
483-
delete self._positions[valueHash];
484-
485-
return true;
486-
} else {
487-
return false;
488-
}
489-
}
490-
491-
/**
492-
* @dev Removes all the values from a set. O(n).
493-
*
494-
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
495-
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
496-
*/
497-
function clear(Bytes32x2Set storage self) internal {
498-
bytes32[2][] storage v = self._values;
499-
500-
uint256 len = length(self);
501-
for (uint256 i = 0; i < len; ++i) {
502-
delete self._positions[_hash(v[i])];
503-
}
504-
assembly ("memory-safe") {
505-
sstore(v.slot, 0)
506-
}
507-
}
508-
509-
/**
510-
* @dev Returns true if the value is in the self. O(1).
511-
*/
512-
function contains(Bytes32x2Set storage self, bytes32[2] memory value) internal view returns (bool) {
513-
return self._positions[_hash(value)] != 0;
514-
}
515-
516-
/**
517-
* @dev Returns the number of values on the self. O(1).
518-
*/
519-
function length(Bytes32x2Set storage self) internal view returns (uint256) {
520-
return self._values.length;
521-
}
522-
523-
/**
524-
* @dev Returns the value stored at position `index` in the self. O(1).
525-
*
526-
* Note that there are no guarantees on the ordering of values inside the
527-
* array, and it may change when more values are added or removed.
528-
*
529-
* Requirements:
530-
*
531-
* - `index` must be strictly less than {length}.
532-
*/
533-
function at(Bytes32x2Set storage self, uint256 index) internal view returns (bytes32[2] memory) {
534-
return self._values[index];
535-
}
536-
537-
/**
538-
* @dev Return the entire set in an array
539-
*
540-
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
541-
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
542-
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
543-
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
544-
*/
545-
function values(Bytes32x2Set storage self) internal view returns (bytes32[2][] memory) {
546-
return self._values;
547-
}
548-
549-
function _hash(bytes32[2] memory value) private pure returns (bytes32) {
550-
return Hashes.efficientKeccak256(value[0], value[1]);
551-
}
552422
}

scripts/generate/templates/EnumerableSet.js

Lines changed: 1 addition & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const header = `\
66
pragma solidity ^0.8.20;
77
88
import {Arrays} from "../Arrays.sol";
9-
import {Hashes} from "../cryptography/Hashes.sol";
109
1110
/**
1211
* @dev Library for managing
@@ -261,149 +260,14 @@ function values(${name} storage set) internal view returns (${type}[] memory) {
261260
}
262261
`;
263262

264-
const memorySet = ({ name, type }) => `\
265-
struct ${name} {
266-
// Storage of set values
267-
${type}[] _values;
268-
// Position is the index of the value in the \`values\` array plus 1.
269-
// Position 0 is used to mean a value is not in the self.
270-
mapping(bytes32 valueHash => uint256) _positions;
271-
}
272-
273-
/**
274-
* @dev Add a value to a self. O(1).
275-
*
276-
* Returns true if the value was added to the set, that is if it was not
277-
* already present.
278-
*/
279-
function add(${name} storage self, ${type} memory value) internal returns (bool) {
280-
if (!contains(self, value)) {
281-
self._values.push(value);
282-
// The value is stored at length-1, but we add 1 to all indexes
283-
// and use 0 as a sentinel value
284-
self._positions[_hash(value)] = self._values.length;
285-
return true;
286-
} else {
287-
return false;
288-
}
289-
}
290-
291-
/**
292-
* @dev Removes a value from a self. O(1).
293-
*
294-
* Returns true if the value was removed from the set, that is if it was
295-
* present.
296-
*/
297-
function remove(${name} storage self, ${type} memory value) internal returns (bool) {
298-
// We cache the value's position to prevent multiple reads from the same storage slot
299-
bytes32 valueHash = _hash(value);
300-
uint256 position = self._positions[valueHash];
301-
302-
if (position != 0) {
303-
// Equivalent to contains(self, value)
304-
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
305-
// the array, and then remove the last element (sometimes called as 'swap and pop').
306-
// This modifies the order of the array, as noted in {at}.
307-
308-
uint256 valueIndex = position - 1;
309-
uint256 lastIndex = self._values.length - 1;
310-
311-
if (valueIndex != lastIndex) {
312-
${type} memory lastValue = self._values[lastIndex];
313-
314-
// Move the lastValue to the index where the value to delete is
315-
self._values[valueIndex] = lastValue;
316-
// Update the tracked position of the lastValue (that was just moved)
317-
self._positions[_hash(lastValue)] = position;
318-
}
319-
320-
// Delete the slot where the moved value was stored
321-
self._values.pop();
322-
323-
// Delete the tracked position for the deleted slot
324-
delete self._positions[valueHash];
325-
326-
return true;
327-
} else {
328-
return false;
329-
}
330-
}
331-
332-
/**
333-
* @dev Removes all the values from a set. O(n).
334-
*
335-
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
336-
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
337-
*/
338-
function clear(${name} storage self) internal {
339-
${type}[] storage v = self._values;
340-
341-
uint256 len = length(self);
342-
for (uint256 i = 0; i < len; ++i) {
343-
delete self._positions[_hash(v[i])];
344-
}
345-
assembly ("memory-safe") {
346-
sstore(v.slot, 0)
347-
}
348-
}
349-
350-
/**
351-
* @dev Returns true if the value is in the self. O(1).
352-
*/
353-
function contains(${name} storage self, ${type} memory value) internal view returns (bool) {
354-
return self._positions[_hash(value)] != 0;
355-
}
356-
357-
/**
358-
* @dev Returns the number of values on the self. O(1).
359-
*/
360-
function length(${name} storage self) internal view returns (uint256) {
361-
return self._values.length;
362-
}
363-
364-
/**
365-
* @dev Returns the value stored at position \`index\` in the self. O(1).
366-
*
367-
* Note that there are no guarantees on the ordering of values inside the
368-
* array, and it may change when more values are added or removed.
369-
*
370-
* Requirements:
371-
*
372-
* - \`index\` must be strictly less than {length}.
373-
*/
374-
function at(${name} storage self, uint256 index) internal view returns (${type} memory) {
375-
return self._values[index];
376-
}
377-
378-
/**
379-
* @dev Return the entire set in an array
380-
*
381-
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
382-
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
383-
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
384-
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
385-
*/
386-
function values(${name} storage self) internal view returns (${type}[] memory) {
387-
return self._values;
388-
}
389-
`;
390-
391-
const hashes = `\
392-
function _hash(bytes32[2] memory value) private pure returns (bytes32) {
393-
return Hashes.efficientKeccak256(value[0], value[1]);
394-
}
395-
`;
396-
397263
// GENERATE
398264
module.exports = format(
399265
header.trimEnd(),
400266
'library EnumerableSet {',
401267
format(
402268
[].concat(
403269
defaultSet,
404-
TYPES.filter(({ size }) => size == undefined).map(details => customSet(details)),
405-
TYPES.filter(({ size }) => size != undefined).map(details => memorySet(details)),
406-
hashes,
270+
TYPES.map(details => customSet(details)),
407271
),
408272
).trimEnd(),
409273
'}',
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
const { capitalize } = require('../../helpers');
22

3-
const mapType = ({ type, size }) => [type == 'uint256' ? 'Uint' : capitalize(type), size].filter(Boolean).join('x');
3+
const mapType = str => (str == 'uint256' ? 'Uint' : capitalize(str));
44

5-
const formatType = ({ type, size = undefined }) => ({
6-
name: `${mapType({ type, size })}Set`,
7-
type: size != undefined ? `${type}[${size}]` : type,
8-
base: size != undefined ? type : undefined,
9-
size,
5+
const formatType = type => ({
6+
name: `${mapType(type)}Set`,
7+
type,
108
});
119

12-
const TYPES = [{ type: 'bytes32' }, { type: 'bytes32', size: 2 }, { type: 'address' }, { type: 'uint256' }].map(
13-
formatType,
14-
);
10+
const TYPES = ['bytes32', 'address', 'uint256'].map(formatType);
1511

1612
module.exports = { TYPES, formatType };

test/utils/structs/EnumerableSet.test.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ async function fixture() {
2020
const mock = await ethers.deployContract('$EnumerableSet');
2121

2222
const env = Object.fromEntries(
23-
TYPES.map(({ name, type, base, size }) => [
23+
TYPES.map(({ name, type }) => [
2424
type,
2525
{
26-
values: Array.from(
27-
{ length: 3 },
28-
size ? () => Array.from({ length: size }, generators[base]) : generators[type],
29-
),
26+
values: Array.from({ length: 3 }, generators[type]),
3027
methods: getMethods(mock, {
3128
add: `$add(uint256,${type})`,
3229
remove: `$remove(uint256,${type})`,
@@ -37,8 +34,8 @@ async function fixture() {
3734
values: `$values_EnumerableSet_${name}(uint256)`,
3835
}),
3936
events: {
40-
addReturn: `return$add_EnumerableSet_${name}_${type.replace(/[[\]]/g, '_')}`,
41-
removeReturn: `return$remove_EnumerableSet_${name}_${type.replace(/[[\]]/g, '_')}`,
37+
addReturn: `return$add_EnumerableSet_${name}_${type}`,
38+
removeReturn: `return$remove_EnumerableSet_${name}_${type}`,
4239
},
4340
},
4441
]),

0 commit comments

Comments
 (0)