StorageSlot.sol 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. /**
  4. * @dev Library for reading and writing primitive types to specific storage slots.
  5. *
  6. * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
  7. * This library helps with reading and writing to such slots without the need for inline assembly.
  8. *
  9. * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
  10. *
  11. * Example usage to set ERC1967 implementation slot:
  12. * ```
  13. * contract ERC1967 {
  14. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  15. *
  16. * function _getImplementation() internal view returns (address) {
  17. * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
  18. * }
  19. *
  20. * function _setImplementation(address newImplementation) internal {
  21. * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
  22. * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
  23. * }
  24. * }
  25. * ```
  26. *
  27. * Available since v4.1.0 for `address`, `bool`, `bytes32`, and `uint256`.
  28. */
  29. library StorageSlot {
  30. struct AddressSlot {
  31. address value;
  32. }
  33. struct BooleanSlot {
  34. bool value;
  35. }
  36. struct Bytes32Slot {
  37. bytes32 value;
  38. }
  39. struct Uint256Slot {
  40. uint256 value;
  41. }
  42. /**
  43. * @dev Returns an `AddressSlot` with member `value` located at `slot`.
  44. */
  45. function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
  46. assembly {
  47. r.slot := slot
  48. }
  49. }
  50. /**
  51. * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
  52. */
  53. function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
  54. assembly {
  55. r.slot := slot
  56. }
  57. }
  58. /**
  59. * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
  60. */
  61. function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
  62. assembly {
  63. r.slot := slot
  64. }
  65. }
  66. /**
  67. * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
  68. */
  69. function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
  70. assembly {
  71. r.slot := slot
  72. }
  73. }
  74. }