BitMaps.sol 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol)
  3. pragma solidity ^0.8.20;
  4. /**
  5. * @dev Library for managing uint256 to bool mapping in a compact and efficient way, provided the keys are sequential.
  6. * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
  7. *
  8. * BitMaps pack 256 booleans across each bit of a single 256-bit slot of `uint256` type.
  9. * Hence booleans corresponding to 256 _sequential_ indices would only consume a single slot,
  10. * unlike the regular `bool` which would consume an entire slot for a single value.
  11. *
  12. * This results in gas savings in two ways:
  13. *
  14. * - Setting a zero value to non-zero only once every 256 times
  15. * - Accessing the same warm slot for every 256 _sequential_ indices
  16. */
  17. library BitMaps {
  18. struct BitMap {
  19. mapping(uint256 bucket => uint256) _data;
  20. }
  21. /**
  22. * @dev Returns whether the bit at `index` is set.
  23. */
  24. function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
  25. uint256 bucket = index >> 8;
  26. uint256 mask = 1 << (index & 0xff);
  27. return bitmap._data[bucket] & mask != 0;
  28. }
  29. /**
  30. * @dev Sets the bit at `index` to the boolean `value`.
  31. */
  32. function setTo(BitMap storage bitmap, uint256 index, bool value) internal {
  33. if (value) {
  34. set(bitmap, index);
  35. } else {
  36. unset(bitmap, index);
  37. }
  38. }
  39. /**
  40. * @dev Sets the bit at `index`.
  41. */
  42. function set(BitMap storage bitmap, uint256 index) internal {
  43. uint256 bucket = index >> 8;
  44. uint256 mask = 1 << (index & 0xff);
  45. bitmap._data[bucket] |= mask;
  46. }
  47. /**
  48. * @dev Unsets the bit at `index`.
  49. */
  50. function unset(BitMap storage bitmap, uint256 index) internal {
  51. uint256 bucket = index >> 8;
  52. uint256 mask = 1 << (index & 0xff);
  53. bitmap._data[bucket] &= ~mask;
  54. }
  55. }