I'm a bit concerned about the get()
function in EnumerableSet
.
It's purpose, along with length()
is to allow retrieving all elements in the set when the set grows too big and enumerate()
runs out of gas.
As pointed out in the code comments, the order of the elements inside a set is not guaranteed. More specifically each time an element is removed its position is occupied by the one with the highest index.
Looping through all the elements in the set using length()
and get()
is not guaranteed to return all the elements, but knowing whether this happened or not will be very difficult for the developer.
I'm very concerned about developers thinking that iterating over an EnumerableSet
is fine, and that leading to bugs, vulnerabilities, and a lot of frustration.
I can see two alternatives to enumerate()
when the set grows too big for a block.
- Implement a state machine, and lock down the set while being iterated.
- Encourage developers to emit events when changing the set, and keeping track of the set contents off-chain.
The first approach is the one I would take when I need to iterate over large data sets to do a state change for each set element. For example when distributing dividends for all token holders.
The second approach is the one I would take when I need to reveal the contents of the set to the front end.
I would leave length()
in EnumerableSet.sol
, but I would remove get()
after pointing out the limitations carefully.