EnumerableSet.sol 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. pragma solidity ^0.6.0;
  2. /**
  3. * @dev Library for managing
  4. * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  5. * types.
  6. *
  7. * Sets have the following properties:
  8. *
  9. * - Elements are added, removed, and checked for existence in constant time
  10. * (O(1)).
  11. * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  12. *
  13. * ```
  14. * contract Example {
  15. * // Add the library methods
  16. * using EnumerableSet for EnumerableSet.AddressSet;
  17. *
  18. * // Declare a set state variable
  19. * EnumerableSet.AddressSet private mySet;
  20. * }
  21. * ```
  22. *
  23. * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
  24. * (`UintSet`) are supported.
  25. */
  26. library EnumerableSet {
  27. // To implement this library for multiple types with as little code
  28. // repetition as possible, we write it in terms of a generic Set type with
  29. // bytes32 values.
  30. // The Set implementation uses private functions, and user-facing
  31. // implementations (such as AddressSet) are just wrappers around the
  32. // underlying Set.
  33. // This means that we can only create new EnumerableSets for types that fit
  34. // in bytes32.
  35. struct Set {
  36. // Storage of set values
  37. bytes32[] _values;
  38. // Position of the value in the `values` array, plus 1 because index 0
  39. // means a value is not in the set.
  40. mapping (bytes32 => uint256) _indexes;
  41. }
  42. /**
  43. * @dev Add a value to a set. O(1).
  44. *
  45. * Returns true if the value was added to the set, that is if it was not
  46. * already present.
  47. */
  48. function _add(Set storage set, bytes32 value) private returns (bool) {
  49. if (!_contains(set, value)) {
  50. set._values.push(value);
  51. // The value is stored at length-1, but we add 1 to all indexes
  52. // and use 0 as a sentinel value
  53. set._indexes[value] = set._values.length;
  54. return true;
  55. } else {
  56. return false;
  57. }
  58. }
  59. /**
  60. * @dev Removes a value from a set. O(1).
  61. *
  62. * Returns true if the value was removed from the set, that is if it was
  63. * present.
  64. */
  65. function _remove(Set storage set, bytes32 value) private returns (bool) {
  66. // We read and store the value's index to prevent multiple reads from the same storage slot
  67. uint256 valueIndex = set._indexes[value];
  68. if (valueIndex != 0) { // Equivalent to contains(set, value)
  69. // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
  70. // the array, and then remove the last element (sometimes called as 'swap and pop').
  71. // This modifies the order of the array, as noted in {at}.
  72. uint256 toDeleteIndex = valueIndex - 1;
  73. uint256 lastIndex = set._values.length - 1;
  74. // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
  75. // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
  76. bytes32 lastvalue = set._values[lastIndex];
  77. // Move the last value to the index where the value to delete is
  78. set._values[toDeleteIndex] = lastvalue;
  79. // Update the index for the moved value
  80. set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
  81. // Delete the slot where the moved value was stored
  82. set._values.pop();
  83. // Delete the index for the deleted slot
  84. delete set._indexes[value];
  85. return true;
  86. } else {
  87. return false;
  88. }
  89. }
  90. /**
  91. * @dev Returns true if the value is in the set. O(1).
  92. */
  93. function _contains(Set storage set, bytes32 value) private view returns (bool) {
  94. return set._indexes[value] != 0;
  95. }
  96. /**
  97. * @dev Returns the number of values on the set. O(1).
  98. */
  99. function _length(Set storage set) private view returns (uint256) {
  100. return set._values.length;
  101. }
  102. /**
  103. * @dev Returns the value stored at position `index` in the set. O(1).
  104. *
  105. * Note that there are no guarantees on the ordering of values inside the
  106. * array, and it may change when more values are added or removed.
  107. *
  108. * Requirements:
  109. *
  110. * - `index` must be strictly less than {length}.
  111. */
  112. function _at(Set storage set, uint256 index) private view returns (bytes32) {
  113. require(set._values.length > index, "EnumerableSet: index out of bounds");
  114. return set._values[index];
  115. }
  116. // AddressSet
  117. struct AddressSet {
  118. Set _inner;
  119. }
  120. /**
  121. * @dev Add a value to a set. O(1).
  122. *
  123. * Returns true if the value was added to the set, that is if it was not
  124. * already present.
  125. */
  126. function add(AddressSet storage set, address value) internal returns (bool) {
  127. return _add(set._inner, bytes32(uint256(value)));
  128. }
  129. /**
  130. * @dev Removes a value from a set. O(1).
  131. *
  132. * Returns true if the value was removed from the set, that is if it was
  133. * present.
  134. */
  135. function remove(AddressSet storage set, address value) internal returns (bool) {
  136. return _remove(set._inner, bytes32(uint256(value)));
  137. }
  138. /**
  139. * @dev Returns true if the value is in the set. O(1).
  140. */
  141. function contains(AddressSet storage set, address value) internal view returns (bool) {
  142. return _contains(set._inner, bytes32(uint256(value)));
  143. }
  144. /**
  145. * @dev Returns the number of values in the set. O(1).
  146. */
  147. function length(AddressSet storage set) internal view returns (uint256) {
  148. return _length(set._inner);
  149. }
  150. /**
  151. * @dev Returns the value stored at position `index` in the set. O(1).
  152. *
  153. * Note that there are no guarantees on the ordering of values inside the
  154. * array, and it may change when more values are added or removed.
  155. *
  156. * Requirements:
  157. *
  158. * - `index` must be strictly less than {length}.
  159. */
  160. function at(AddressSet storage set, uint256 index) internal view returns (address) {
  161. return address(uint256(_at(set._inner, index)));
  162. }
  163. // UintSet
  164. struct UintSet {
  165. Set _inner;
  166. }
  167. /**
  168. * @dev Add a value to a set. O(1).
  169. *
  170. * Returns true if the value was added to the set, that is if it was not
  171. * already present.
  172. */
  173. function add(UintSet storage set, uint256 value) internal returns (bool) {
  174. return _add(set._inner, bytes32(value));
  175. }
  176. /**
  177. * @dev Removes a value from a set. O(1).
  178. *
  179. * Returns true if the value was removed from the set, that is if it was
  180. * present.
  181. */
  182. function remove(UintSet storage set, uint256 value) internal returns (bool) {
  183. return _remove(set._inner, bytes32(value));
  184. }
  185. /**
  186. * @dev Returns true if the value is in the set. O(1).
  187. */
  188. function contains(UintSet storage set, uint256 value) internal view returns (bool) {
  189. return _contains(set._inner, bytes32(value));
  190. }
  191. /**
  192. * @dev Returns the number of values on the set. O(1).
  193. */
  194. function length(UintSet storage set) internal view returns (uint256) {
  195. return _length(set._inner);
  196. }
  197. /**
  198. * @dev Returns the value stored at position `index` in the set. O(1).
  199. *
  200. * Note that there are no guarantees on the ordering of values inside the
  201. * array, and it may change when more values are added or removed.
  202. *
  203. * Requirements:
  204. *
  205. * - `index` must be strictly less than {length}.
  206. */
  207. function at(UintSet storage set, uint256 index) internal view returns (uint256) {
  208. return uint256(_at(set._inner, index));
  209. }
  210. }