question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

EnumerableSet.clear()

See original GitHub issue

🧐 Motivation Use case: I need to store a bunch of approvals in a set and once the number of approvals reach a specific length, I need to execute an operation and clear all the approvals.

📝 Details

Right now, it is possible to clear the set with this code:

address[] memory values = approvals.values();
for (uint256 i = 0; i < values.length; i++) {
  approvals.remove(values[i]);
}

but it is rather inefficient because each call to .remove() does .pop() and multiple storage reads/writes.

The implementation of .clear() might look like this:

function clear(Set storage set) private {
  for (uint256 i = 0; i < set._values.length; i++) {
    set._indexes[set._values[i]] = 0;
  }
  // this line is dangerous as it might consume unbounded amount of gas
  set._values = new bytes32[](0); 
}

If set._values = new bytes32[](0); is too dangerous, another way to implement .clear() is to make another struct with .clear() method:

struct ClearableAddressSet {
  uint256 _setId;
  // setId => AddressSet
  mapping(uint256 => AddressSet) _sets;
}

// delegate all functions
function add(ClearableAddressSet storage set, address value) internal returns (bool) {
  return set._sets[set._setId].add(value);
}

function clear() internal {
  // by incrementing `_setId`, a new set is "created".
  set._setId++;
}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
frangiocommented, Mar 22, 2022

Yeah I think the best option is to use an array of EnumerableSet and just move on to the next one when you clear.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract Example {
    using EnumerableSet for EnumerableSet.AddressSet;

    EnumerableSet.AddressSet[] private sets;
    uint setIndex;

    function _getCurrentSet() internal view returns (EnumerableSet.AddressSet storage) {
        return sets[setIndex];
    }

    function _clearSet() internal {
        setIndex += 1;
    }
}

I don’t think it makes sense for us to provide this pattern out of the box.

0reactions
emizzlecommented, Nov 15, 2022

Agree with @envatic, using an array panics, though wasn’t necessarily in the case of an upgradable contract. Panic exception is:

Error: VM Exception while processing transaction: reverted with panic code 0x32 (Array accessed at an out-of-bounds or negative index)

Using a mapping instead worked 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Utilities - OpenZeppelin Docs
EnumerableSet : like EnumerableMap , but for sets. Can be used to store privileged accounts, issued IDs, etc. Because Solidity does not support...
Read more >
EnumerableSet vs Access Control in Openzeppelin
Using enumerable sets works similar (you are storing the indexes that correspond to the addresses). There shouldn't be a reason for you to ......
Read more >
Address 0x4F290e83B414097C107F5AD483a9ae15434B43d3
function totalSupply() external view returns (uint256); ... library EnumerableSet { // To implement this library for multiple types with as ...
Read more >
Enumerable.Empty<TResult> Method (System.Linq)
Generic.IEnumerable<TResult> Empty<TResult> (); static member Empty : unit -> seq<'Result> Public Function Empty(Of TResult) () As IEnumerable(Of TResult) ...
Read more >
Ethereum Contract Diff Checker - Etherscan
Increaser; using SignatureChecker for EnumerableSet. ... If true, future calls to mint() with the same parameters will fail. @dev In production we will ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found